? includes/table.inc
Index: commands/core/core.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/core/core.drush.inc,v
retrieving revision 1.92
diff -u -p -r1.92 core.drush.inc
--- commands/core/core.drush.inc	13 Apr 2010 20:02:04 -0000	1.92
+++ commands/core/core.drush.inc	15 Apr 2010 19:48:30 -0000
@@ -156,22 +156,34 @@ function core_drush_command() {
     'deprecated-aliases' => array('installsite', 'is'),
   );
 
-  $items['core-directory'] = array(
+  $items['drupal-directory'] = array(
     'description' => dt('Return path to a given module/theme directory. See --help for more details.'),
     'arguments' => array(
-      'target' => 'A module/theme name, or special names like root, files, private. Defaults to root.',
+      'target' => 'A module/theme name, or special names like root, files, private, or an alias : path alias string such as @alias:%files. Defaults to root.',
     ),
     'examples' => array(
-      'cd `drush cd devel`' => 'Navigate into the devel module directory',
-      'cd `drush cd` ' => 'Navigate to the root of your Drupal site',
-      'cd `drush cd files`' => 'Navigate to the files directory.',
-      'edit `drush cd devel`' => "Open devel directory in your editor (customize 'edit' for your editor)",
-      'cdd devel' => 'Navigate to devel directory. See required function above,',
+      'cd `drush dd devel`' => 'Navigate into the devel module directory',
+      'cd `drush dd` ' => 'Navigate to the root of your Drupal site',
+      'cd `drush dd files`' => 'Navigate to the files directory.',
+      'drush dd @alias:%files' => 'Print the path to the files directory on the site @alias.',
+      'edit `drush dd devel`/devel.module' => "Open devel module in your editor (customize 'edit' for your editor)",
     ),
-    'aliases' => array('cd'),
+    'aliases' => array('dd'),
     'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
   );
-
+  
+  $items['command-line-interpreter'] = array(
+    'description' => dt('Enter a new shell optimized for drush use.  See the examples below for command usage from within the drush cli.'),
+    'examples' => array(
+      'help' => 'Print available drush commands',
+      'cdd' => 'Navigate to the root of your Drupal site',
+      'cdd files' => 'Navigate to the files directory.',
+      'on @alias sql-conf' => 'Run the command "sql-conf" on the site indicated by @alias',
+    ),
+    'aliases' => array('cli'),
+    'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
+  );
+  
   $items['batch-process'] = array(
     'description' => dt('Process operations in the specified batch set'),
     'hidden' => TRUE,
@@ -317,22 +329,10 @@ function core_drush_help($section) {
       return dt("Run arbitrary PHP code in the context of Drupal");
     case 'drush:site-install':
       return dt("Install Drupal using specified install profile.");
-    case 'drush:core-directory':
-      $prefix = dt("Return the filesystem path for projects/themes and other key folders. Unlike most drush commands, you usually want to prefix the command with cd and enclose the command invocation in backticks. See Examples below. For even more convenient usage (Unix/OSX only), add the following code to your .profile, .bash_profile, or .bashrc file.");
-      $suffix = <<<EOD
-
-
-function cdd() {
-  DEST=`drush $2 core-directory $1`
-  if [ -z "\$DEST" ]
-  then
-    echo $1 "was not found."
-  else
-    cd \$DEST;
-  fi
-}
-EOD;
-      return $prefix . $suffix;
+    case 'drush:drupal-directory':
+      return dt("Return the filesystem path for projects/themes and other key folders. Unlike most drush commands, you usually want to prefix the command with cd and enclose the command invocation in backticks. See Examples below.");
+    case 'drush:command-line-interpreter':
+      return dt("Enter a new shell optimized for drush use.  See help for more details.");
     case 'error:DRUSH_DRUPAL_DB_ERROR' :
       $message = dt("Drush was not able to start (bootstrap) the Drupal database.\n");
       $message .= dt("Hint: This error often occurs when Drush is trying to bootstrap a site that has not been installed or does not have a configured database.\n");
@@ -358,7 +358,7 @@ function _core_site_credentials() {
 function _core_site_credential_table($status_table) {
   $credentials = '';
   foreach ($status_table as $key => $value) {
-      $credentials .= sprintf("  %-18s: %s\n", $key, $value);
+    $credentials .= sprintf("  %-18s: %s\n", $key, $value);
   }
   return $credentials;
 }
@@ -366,22 +366,54 @@ function _core_site_credential_table($st
 function _core_site_credential_list($status_table) {
   $credentials = '';
   foreach ($status_table as $key => $value) {
-    $credentials .= sprintf("%s=%s\n", strtolower(str_replace(' ', '_', $key)), $value);
+    if (isset($value)) {
+      $credentials .= sprintf("%s=%s\n", strtolower(str_replace(' ', '_', $key)), $value);
+    }
   }
   return $credentials;
 }
 
-function _core_site_status_table() {
+function _core_path_aliases($project = '') {
+  $paths = array();
+  $phase = drush_get_context('DRUSH_BOOTSTRAP_PHASE');
+  if ($drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT')) {
+    $paths['%root'] = $drupal_root;
+    if ($site_root = drush_get_context('DRUSH_DRUPAL_SITE_ROOT')) {
+      $paths['%site'] = $site_root;
+      $paths['%modules'] = 'sites'.DIRECTORY_SEPARATOR.'all'.DIRECTORY_SEPARATOR.'modules';
+      $paths['%themes'] = 'sites'.DIRECTORY_SEPARATOR.'all'.DIRECTORY_SEPARATOR.'themes';
+      if (drush_drupal_major_version() >= 7) {
+        $paths['%files'] = DrupalPublicStreamWrapper::getDirectoryPath();
+        $paths['%private'] = DrupalPrivateStreamWrapper::getDirectoryPath();
+      }
+      elseif (function_exists('file_directory_path')) {
+        $paths['%files'] = file_directory_path();
+      }
+      // If the 'project' parameter was specified, then search
+      // for a project (or a few) and add its path to the path list
+      if (!empty($project)) {
+        foreach(explode(',', $project) as $target) {
+          $path = drush_core_find_project_path($target);
+          if(isset($path)) {
+            $paths['%' . $target] = $path;
+          }
+        }
+      }
+    }
+  }
+
+  // Add in all of the global paths from $options['path-aliases']
+  $paths = array_merge($paths, drush_get_option('path-aliases', array()));
+  
+  return $paths;
+}
+
+function _core_site_status_table($project = '') {
   $phase = drush_get_context('DRUSH_BOOTSTRAP_PHASE');
   if ($drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT')) {
-    $status_table['Drupal Root'] = $drupal_root;
     $status_table['Drupal Version'] = drush_drupal_version();
     if ($site_root = drush_get_context('DRUSH_DRUPAL_SITE_ROOT')) {
-      $status_table['Site Path'] = $site_root;
       $status_table['Site URI'] = drush_get_context('DRUSH_URI');
-      if (function_exists('file_directory_path')) {
-        $status_table['File Directory Path'] = file_directory_path();
-      }
       if ($creds = drush_get_context('DRUSH_DB_CREDENTIALS')) {
         $status_table['Database Driver'] = $creds['driver'];
         $status_table['Database Hostname'] = $creds['host'];
@@ -413,6 +445,35 @@ function _core_site_status_table() {
   }
   $status_table['Drush Version'] = DRUSH_VERSION;
   $status_table['Drush configuration'] = implode(' ', drush_get_context_options('context-path', TRUE));
+  
+  // None of the Status keys are in dt(); this helps with machine-parsing of status?
+  $path_names['root'] = 'Drupal Root';
+  $path_names['site'] = 'Site Path';
+  $path_names['modules'] = 'Modules Path';
+  $path_names['themes'] = 'Themes Path';
+  $path_names['files'] = 'File Directory Path';
+  $path_names['private'] = 'Private File Directory Path';
+  
+  $paths = _core_path_aliases($project);
+  if (!empty($paths)) {
+    $status_table['Paths'] = NULL;
+    foreach ($paths as $target => $one_path) {
+      $name = $target;
+      if (substr($name,0,1) == '%') {
+        $name = substr($name,1);
+      }
+      if (array_key_exists($name, $path_names)) {
+        $name = $path_names[$name];
+      }
+      $status_table[$name] = $one_path;
+    }
+  }
+    
+  // Store the paths into the '%paths' index; this will be
+  // used by other code, but will not be included in the output
+  // of the drush status command.
+  $status_table['%paths'] = $paths;
+  
   return $status_table;
 }
 
@@ -442,7 +503,7 @@ function drush_core_cron() {
  */
 function drush_core_status() {
   drush_bootstrap_max();
-  $status_table = _core_site_status_table();
+  $status_table = _core_site_status_table(drush_get_option('project',''));
   // If args are specified, filter out any entry that is not named
   // (in other words, only show lines named by one of the arg values)
   $args = func_get_args();
@@ -454,6 +515,7 @@ function drush_core_status() {
     }
   }
   drush_backend_set_result($status_table);
+  unset($status_table['%paths']);
   // Print either an ini-format list or a formatted ASCII table
   if (drush_get_option('pipe')) {
     if (count($status_table) == 1) {
@@ -465,6 +527,8 @@ function drush_core_status() {
     }
   }
   else {
+    unset($status_table['Modules Path']);
+    unset($status_table['Themes Path']);
     drush_print_table(drush_key_value_to_array_table($status_table));
   }
   return;
@@ -562,37 +626,57 @@ function drush_core_updatedb_batch_proce
   _update_batch_command($id);
 }
 
-function drush_core_directory($target = 'root') {
+function _drush_core_directory($target = 'root') {
   // Normalize to a sitealias in the target.
-  if (substr($target, 0, 1) != '/' && substr($target, 0, 1) != '@') {
-    // @self makes no sense before 'site' level.
-    if (drush_bootstrap(DRUSH_BOOTSTRAP_DRUPAL_SITE)) {
-      $additional_options = array();
-      $path = drush_sitealias_evaluate_path('@self:%' . $target, $additional_options);
+  $normalized_target = $target;
+  if (strpos($target, ':') === FALSE) {
+    if (substr($target,0,1) == '@') {
+      $normalized_target = $target; // . ':%site';
     }
     else {
-      return drush_set_error(dt('!target not found.', array('!target' => $target)));
+      // @self makes no sense before 'site' level.
+      if(!drush_bootstrap(DRUSH_BOOTSTRAP_DRUPAL_SITE)) {
+        return FALSE;
+      }
+      $normalized_target = '@self:';
+      if (substr($target,0,1) != '%') {
+        $normalized_target .= '%';
+      }
+      $normalized_target .= $target;
     }
   }
 
-  if (isset($path['path-aliases']['%' . $target])) {
-    // Hurray, we found the destination quickly.
-    drush_print($path['rsync-path']);
-    return;
+  $additional_options = array();
+  $values = drush_sitealias_evaluate_path($normalized_target, $additional_options);
+
+  if (isset($values['path'])) {
+    // Hurray, we found the destination
+    return $values['path'];
   }
+  return NULL;
+}
+
+function drush_core_drupal_directory($target = 'root') {
+  $path = _drush_core_directory($target);
 
-  // We need to know which site is active in order to add its masks.
-  if (!drush_bootstrap(DRUSH_BOOTSTRAP_DRUPAL_SITE)) {
-    return drush_set_error(dt('!target not found.', array('!target' => $target)));
+  if (isset($path)) {
+    drush_print($path);
+  }
+  else {
+    return drush_set_error(dt('Core directory path !target not found.', array('!target' => $target)));
   }
+   
+  return TRUE;
+}
 
+function drush_core_find_project_path($target) {
   $theme_suffix = drush_drupal_major_version() >= 6 ? '.info' : '/style.css';
   $masks = array(
-    conf_path() . '/modules' => "/$target.module/",
-    'profiles/default/modules' => "/$target.module/", // Too early for variable_get('install_profile', 'default'); Just use default.
-    'sites/all/modules' => "/$target.module/", // Add all module paths, even disabled modules.
-    conf_path() . '/themes' => "/$target" . "$theme_suffix/",
-    'sites/all/themes' => "/$target" . "$theme_suffix/",
+    conf_path() . '/modules' => "/^$target.module/",
+    'profiles/default/modules' => "/^$target.module/", // Too early for variable_get('install_profile', 'default'); Just use default.
+    'sites/all/modules' => "/^$target.module/", // Add all module paths, even disabled modules.
+    conf_path() . '/themes' => "/^$target" . "$theme_suffix/",
+    'sites/all/themes' => "/^$target" . "$theme_suffix/",
   );
 
   $files = array();
@@ -600,8 +684,84 @@ function drush_core_directory($target = 
     if ($files = drush_scan_directory("$key", $mask, array('..', '.', 'CVS', '.svn', '.bzr'), 0, TRUE, 'name')) {
       // Just use the first match.
       $file = reset($files);
-      drush_print(drush_get_context('DRUSH_DRUPAL_ROOT') . '/' . dirname($file->filename));
-      return;
+      return drush_get_context('DRUSH_DRUPAL_ROOT') . '/' . dirname($file->filename);
     }
   }
+  
+  return NULL;
 }
+
+function drush_core_command_line_interpreter() {
+  drush_bootstrap_max();
+  
+  // Set up our default bashrc file for the drush cli
+  $bashrc_data = <<<EOD
+
+PS1="drush> "
+
+alias on="drush"
+DRUSH_CLI=true
+
+
+function cdd() {
+  TARGET=
+  PARAM=\$1
+  if [ \$# -gt 1 ] ; then
+    TARGET=\$1
+    PARAM=\$2
+  fi
+  DEST=`drush \$TARGET drupal-directory \$PARAM`
+  if [ \$? != 0 ] || [ -z "\$DEST" ]
+  then
+    echo "Target \$1 was not found."
+  else
+    echo "cd \$DEST"
+    cd \$DEST;
+  fi
+}
+
+function lsd() {
+  TARGET=
+  PARAM=\$1
+  if [ \$# -gt 1 ] ; then
+    TARGET=\$1
+    PARAM=\$2
+  fi
+  DEST=`drush \$TARGET drupal-directory \$PARAM`
+  if [ \$? != 0 ] || [ -z "\$DEST" ]
+  then
+    echo "Target \$1 was not found."
+  else
+    echo "ls \$DEST"
+    ls \$DEST;
+  fi
+}
+
+EOD;
+  
+  // Add aliases for all of our commands
+  $commands = drush_get_commands();
+  foreach ($commands as $key => $command) {
+    // Filter out old commands that still have spaces
+    if (strpos($key, ' ') === FALSE) {
+      $bashrc_data .= "function $key() {\n  drush $key \$@\n}\n";
+    }
+  }
+  
+  // Before entering the new bash script, cd to the current site root,
+  // if any.  This will make our default site for drush match the
+  // currently bootstrapped site (at least until the user cd's away).
+  if ($site_root = drush_get_context('DRUSH_DRUPAL_SITE_ROOT')) {
+    chdir($site_root);
+  }
+    
+  drush_print("Entering the drush cli.  Use CONTROL-D to exit.");
+  drush_print("Type 'help' for help.");
+  
+  // Save out bashrc in a temporary file and launch bash.
+  // control-d to exit.  The temp file will be deleted after
+  // we exit.
+  $bashrc = drush_save_data_to_temp_file($bashrc_data);
+  drush_op('system', 'bash --rcfile ' . $bashrc . ' > `tty`');
+}
+
Index: commands/core/rsync.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/core/rsync.inc,v
retrieving revision 1.16
diff -u -p -r1.16 rsync.inc
--- commands/core/rsync.inc	15 Apr 2010 15:47:04 -0000	1.16
+++ commands/core/rsync.inc	15 Apr 2010 19:48:30 -0000
@@ -21,8 +21,8 @@ function drush_core_rsync($source, $dest
   // After preflight, evaluate file paths
   $source_settings = drush_sitealias_evaluate_path($source, $additional_options);
   $destination_settings = drush_sitealias_evaluate_path($destination, $additional_options);
-  $source_path = $source_settings['rsync-path'];
-  $destination_path = $destination_settings['rsync-path'];
+  $source_path = $source_settings['evaluated-path'];
+  $destination_path = $destination_settings['evaluated-path'];
 
   if (!isset($source_settings)) {
     return drush_set_error('DRUSH_BAD_PATH', dt('Could not evaluate source path !path.', array('!path' => $source)));
@@ -33,8 +33,15 @@ function drush_core_rsync($source, $dest
     
   // Check to see if this is an rsync multiple command (multiple sources and multiple destinations)
   $is_multiple = drush_do_multiple_command('rsync', $source_settings, $destination_settings, TRUE);
-
+  
   if ($is_multiple === FALSE) {
+    // If the user path is the same for the source and the destination, then
+    // always add a slash to the end of the source.  If the user path is not
+    // the same in the source and the destinaiton, then you need to know how
+    // rsync paths work, and put on the trailing '/' if you want it.
+    if ($source_settings['user-path'] == $destination_settings['user-path']) {
+      $source_path .= '/';
+    }
     // Prompt for confirmation. This is destructive.
     if (!drush_get_context('DRUSH_SIMULATE')) {
       drush_print(dt("You will destroy data from !target and replace with data from !source", array('!source' => $source_path, '!target' => $destination_path)));
@@ -98,7 +105,7 @@ function drush_core_call_rsync($source, 
     $options .= ' --include="sites/all" --exclude="sites/*"';
   }
   if (_drush_rsync_option_exists('mode', $additional_options)) {
-    $mode = "-" . _drush_rsync_get_option($additional_options, 'mode');
+    $mode = "-" . drush_get_option_override($additional_options, 'mode');
   }
   if (drush_get_context('DRUSH_VERBOSE')) {
     // the drush_op() will be verbose about the command that gets executed.
@@ -197,7 +204,7 @@ function drush_core_call_rsync($source, 
     'protocol',
     );
   foreach ($rsync_available_options as $test_option) {
-    $value = _drush_rsync_get_option($additional_options, $test_option);
+    $value = drush_get_option_override($additional_options, $test_option);
     if (isset($value)) {
       if ($value === TRUE) {
         $options .= " --$test_option";
@@ -208,7 +215,7 @@ function drush_core_call_rsync($source, 
     }
   }
 
-  $ssh_options = _drush_rsync_get_option($additional_options, 'ssh-options', '');
+  $ssh_options = drush_get_option_override($additional_options, 'ssh-options', '');
   $exec = "rsync -e 'ssh $ssh_options' $mode$options $source $destination";
 
   $exec_result = drush_op('system', $exec) !== FALSE;
Index: includes/context.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/context.inc,v
retrieving revision 1.27
diff -u -p -r1.27 context.inc
--- includes/context.inc	8 Apr 2010 19:17:30 -0000	1.27
+++ includes/context.inc	15 Apr 2010 19:48:31 -0000
@@ -383,6 +383,31 @@ function drush_get_option($option, $defa
 }
 
 /**
+ * Get the value for an option, but first checks the provided option overrides.
+ *
+ * The feature of drush_get_option that allows a list of option names
+ * to be passed in an array is NOT supported.
+ *
+ * @param option_overrides
+ *   An array to check for values before calling drush_get_option.
+ * @param option
+ *   The name of the option to get.
+ * @param default
+ *   Optional. The value to return if the option has not been set.
+ * @param context
+ *   Optional. The context to check for the option. If this is set, only this context will be searched.
+ * 
+ */
+function drush_get_option_override($option_overrides, $option, $value = NULL, $context = NULL) {
+  if (array_key_exists($option, $option_overrides)) {
+    return $option_overrides[$option];
+  }
+  else {
+    return drush_get_option($option, $value, $context);
+  }
+}
+
+/**
  * Get all of the values for an option in every context.
  *
  * @param option
Index: includes/drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/drush.inc,v
retrieving revision 1.107
diff -u -p -r1.107 drush.inc
--- includes/drush.inc	12 Apr 2010 14:29:54 -0000	1.107
+++ includes/drush.inc	15 Apr 2010 19:48:32 -0000
@@ -989,7 +989,13 @@ function drush_print_table($rows, $heade
 function drush_key_value_to_array_table($keyvalue_table) {
   $table = array();
   foreach ($keyvalue_table as $key => $value) {
-    $table[] = array($key, ' :', $value);
+    if (isset($value)) {
+      $table[] = array($key, ' :', $value);
+    }
+    else {
+      $table[] = array('', '', '');
+      $table[] = array($key . ':', '', '');
+    }
   }
   return $table;
 }
Index: includes/sitealias.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/sitealias.inc,v
retrieving revision 1.40
diff -u -p -r1.40 sitealias.inc
--- includes/sitealias.inc	15 Apr 2010 15:47:04 -0000	1.40
+++ includes/sitealias.inc	15 Apr 2010 19:48:34 -0000
@@ -570,6 +570,24 @@ function drush_sitealias_add_db_settings
 }
 
 /**
+ * Check to see if we have already bootstrapped to a site.
+ */
+function drush_sitealias_is_bootstrapped_site($alias_record) {
+  if (!isset($alias_record['remote-host'])) {
+    $self_record = drush_sitealias_get_record("@self");
+    if (empty($self_record)) {
+      // TODO:  If we have not bootstrapped to a site yet, we could
+      // perhaps bootstrap to $alias_record here.
+      return FALSE;
+    }
+    elseif(($alias_record['root'] == $self_record['root']) && ($alias_record['uri'] == $self_record['uri'])) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
  * Walk through the path aliases and find any paths that begin with a '@'.
  * If found, query the 'status' function for the local or remote
  * site and use the result returned to populate the value of the
@@ -589,6 +607,18 @@ function drush_sitealias_add_db_settings
  */
 function drush_sitealias_resolve_path_references(&$alias_record, $test_string = '') {
   $resolution_needed = FALSE;
+  
+  // Convert the test string into an array of items, and
+  // from this make a comma-separated list of projects
+  // that we can pass to 'drush status'.
+  $test_array = explode('/', $test_string);
+  $project_array = array();
+  foreach($test_array as $one_item) {
+    if (substr($one_item,0,1) == '%') {
+      $project_array[] = substr($one_item,1);
+    }    
+  }
+  
   // Check to see if we have any path values that begin with '@'
   // that also exist in the test string
   if (array_key_exists('path-aliases', $alias_record)) {
@@ -598,19 +628,48 @@ function drush_sitealias_resolve_path_re
           $resolution_needed = TRUE;
         }
       }
+      // If we already have a path in the path aliases, then
+      // there is no need to search for it remotely; we can remove
+      // it from the project array.
+      if (substr($key,0,1) == '%') {
+        unset($project_array['%' . substr($key,1)]);
+      }
     }
   }
-
-  if ($resolution_needed) {
-    $values = drush_do_site_command($alias_record, "status");
-    $status_values = $values['object'];
-    if (isset($status_values)) {
-      foreach ($alias_record['path-aliases'] as $key => $value) {
-        if (substr($value,0,1) == '@') {
-          $status_key = strtr(substr($value,1), '-_', '  ');
+  $project_list = implode(',', $project_array);
+  
+  if ($resolution_needed || !empty($project_array)) {
+    // Optimization:  if we're already bootstrapped to the
+    // site specified by $alias_record, then we can just
+    // call _core_site_status_table() rather than use backend invoke.
+    if (drush_sitealias_is_bootstrapped_site($alias_record)) {
+      // Make sure that we are bootstrapped at least to the 'site'
+      // level, and include file.inc to insure that we have access
+      // to the %file path.
+      if (drush_bootstrap(DRUSH_BOOTSTRAP_DRUPAL_SITE)) {
+        include_once DRUPAL_ROOT . '/includes/file.inc';
+      }
+      $status_values = _core_site_status_table($project_list);
+    }
+    else {
+      $values = drush_do_site_command($alias_record, "status", array(), empty($project_list) ? array() : array('project' => $project_list));
+      $status_values = $values['object'];
+    }
+    if (isset($status_values['%paths'])) {
+      foreach ($status_values['%paths'] as $key => $path) {
+        $alias_record['path-aliases'][$key] = $path;
+      }
+    }
+    // TODO:  Remove this old code, which is only useful when talking to old (remote) versions of drush-3.0-rc3 and earlier
+    if (isset($status_values['paths'])) {
+      foreach ($alias_record['path-aliases'] as $key => $path_alias_key) {
+        if (substr($path_alias_key,0,1) == '@') {
+          $status_key = strtr(substr($path_alias_key,1), '-_', '  ');
           if (array_key_exists($status_key, $status_values)) {
             $alias_record['path-aliases'][$key] = $status_values[$status_key];
-            drush_log(dt('Resolved path !key to !value', array('!key' => $status_key, '!value' => $status_values[$status_key])));
+          }
+          elseif (array_key_exists('%paths',$status_values) && array_key_exists($path_alias_key, $status_values['%paths'])) {
+            $alias_record['path-aliases'][$key] = $status_values['%paths'][$path_alias_key];
           }
           else {
             unset($alias_record['path-aliases'][$key]);
@@ -1289,7 +1348,7 @@ function _drush_sitealias_preflight_path
  * @return
  *   The site record for the machine specified in the path, if any,
  *   with the path to pass to rsync (including the machine specifier)
- *   in the 'rsync-path' item.
+ *   in the 'evaluated-path' item.
  */
 function drush_sitealias_evaluate_path($path, &$additional_options) {
   $site_alias_settings = array();
@@ -1305,7 +1364,6 @@ function drush_sitealias_evaluate_path($
   $path = $preflight['path'];
   $machine = $preflight['machine'];
   
-  
   if (isset($alias)) {
     $site_alias_settings = drush_sitealias_get_record($alias);
   }
@@ -1338,15 +1396,15 @@ function drush_sitealias_evaluate_path($
 
   // If the --exclude-other-sites option is specified, then
   // convert that into --include-path='%site' and --exclude-sites.
-  if (_drush_rsync_get_option($additional_options, 'exclude-other-sites', FALSE) && !_drush_rsync_get_option($additional_options, 'exclude-other-sites-processed', FALSE, 'process')) {
-    $additional_options['include-path'] = '%site,' . _drush_rsync_get_option($additional_options, 'include-path', '');
+  if (drush_get_option_override($additional_options, 'exclude-other-sites', FALSE) && !drush_get_option_override($additional_options, 'exclude-other-sites-processed', FALSE, 'process')) {
+    $additional_options['include-path'] = '%site,' . drush_get_option_override($additional_options, 'include-path', '');
     $additional_options['exclude-sites'] = TRUE;
     $additional_options['exclude-other-sites-processed'] = TRUE;
   }
   // If the --exclude-files option is specified, then
   // convert that into --exclude-path='%files'.
-  if (_drush_rsync_get_option($additional_options, 'exclude-files', FALSE) && !_drush_rsync_get_option($additional_options, 'exclude-files-processed', FALSE, 'process')) {
-    $additional_options['exclude-path'] = '%files,' . _drush_rsync_get_option($additional_options, 'exclude-path', '');
+  if (drush_get_option_override($additional_options, 'exclude-files', FALSE) && !drush_get_option_override($additional_options, 'exclude-files-processed', FALSE, 'process')) {
+    $additional_options['exclude-path'] = '%files,' . drush_get_option_override($additional_options, 'exclude-path', '');
     $additional_options['exclude-files-processed'] = TRUE;
   }
 
@@ -1366,8 +1424,8 @@ function drush_sitealias_evaluate_path($
   // in it, so that resolution is only done if the path alias is referenced.
   // Therefore, we can concatenate without worrying too much about the structure of
   // this variable's contents.
-  $include_path = _drush_rsync_get_option($additional_options, 'include-path', '');
-  $exclude_path = _drush_rsync_get_option($additional_options, 'exclude-path', '');
+  $include_path = drush_get_option_override($additional_options, 'include-path', '');
+  $exclude_path = drush_get_option_override($additional_options, 'exclude-path', '');
   $resolve_path = $path . $include_path . $exclude_path;
   // Resolve path aliases such as %files, if any exist in the path
   if (!empty($resolve_path)) {
@@ -1400,14 +1458,9 @@ function drush_sitealias_evaluate_path($
     if (($value[0] != '/') && ($key != '%root')) {
       $full_path_aliases[$key] = $drupal_root . $value;
     }
-    // Rsync is very particular about the meaning of paths that
-    // end with a '/' compared to those that do not.  In order to
-    // copy from !path to !path without creating an extra spurrious
-    // directory, the path alias must end with a '/'.  Therefore
-    // we will add a slash to the end of any alias that does not
-    // already have one.
-    if ($value[strlen($value)-1] != '/') {
-      $full_path_aliases[$key] = $full_path_aliases[$key] . '/';
+    // We do not want slashes on the end of our path aliases.
+    if ($value[strlen($value)-1] == '/') {
+      $full_path_aliases[$key] = substr($full_path_aliases[$key], -1);
     }
   }
 
@@ -1433,22 +1486,28 @@ function drush_sitealias_evaluate_path($
 
   // If there is a $machine component, to the path, then
   // add it to the beginning
+  $evaluated_path = $path;
   if (!empty($machine)) {
-    $path = $machine . ':' . $path;
+    $evaluated_path = $machine . ':' . $path;
   }
 
-  // TODO: Rename this key.
-  $site_alias_settings['rsync-path'] = $path;
+  //
+  // Add our result paths:
+  //
+  //    evaluated-path:         machine:/path
+  //    server-component:       machine
+  //    path-component:         :/path
+  //    path:                   /path
+  //    user-path:              path (as specified in input parameter)
+  //
+  $site_alias_settings['evaluated-path'] = $evaluated_path;
+  if (!empty($machine)) {
+    $site_alias_settings['server-component'] = $machine;
+  }
   $site_alias_settings['path-component'] = $path_component;
-
+  $site_alias_settings['path'] = $path;
+  $site_alias_settings['user-path'] = $preflight['path'];
+  
   return $site_alias_settings;
 }
 
-function _drush_rsync_get_option($additional_options, $option, $value = NULL, $context = NULL) {
-  if (array_key_exists($option, $additional_options)) {
-    return $additional_options[$option];
-  }
-  else {
-    return drush_get_option($option, $value, $context);
-  }
-}
