? fix.sh
? includes/table.inc
Index: example.drushrc.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/example.drushrc.php,v
retrieving revision 1.28
diff -u -p -r1.28 example.drushrc.php
--- example.drushrc.php	27 Jan 2010 19:19:14 -0000	1.28
+++ example.drushrc.php	28 Jan 2010 09:22:24 -0000
@@ -162,15 +162,15 @@ $options['skip-tables'] = array(
  * - 'remote-user': The username to log in as when using ssh or rsync.
  * - 'path-aliases': An array of aliases for common rsync targets.
  *   Relative aliases are always taken from the Drupal root.
- *     '!drush': The path to the folder where drush is stored.  Optional;
+ *     '%drush': The path to the folder where drush is stored.  Optional;
  *       defaults to the folder containing the running script.  Always be sure
  *       to set '!drush' if the path to drush is different on the remote server.
- *     '!drush-script': The path to the 'drush' script (used by backend invoke);
+ *     '%drush-script': The path to the 'drush' script (used by backend invoke);
  *       default is 'drush' on remote machines, or the full path to drush.php on
  *       the local machine.  Note that you only need to define one of '!drush'
  *       or '!drush-script', as drush can infer one from the other.
- *     '!dump': Path to the file that "drush sql-sync" should use to store sql-dump file.
- *     '!files': Path to 'files' directory.
+ *     '%dump': Path to the file that "drush sql-sync" should use to store sql-dump file.
+ *     '%files': Path to 'files' directory.  This will be looked up if not specified.
  *
  * Remove the leading hash signs to enable.
  */
@@ -181,11 +181,11 @@ $options['skip-tables'] = array(
 #    'remote-host' => 'mystagingserver.myisp.com',
 #    'remote-user' => 'publisher',
 #    'path-aliases' => array(
-#      '!drush' => '/drush/path/to/drush',
-#      '!drush-script' => '/drush/path/to/drush/drush',
-#      '!dump' => '/path/to/live/sql_dump.sql',
-#      '!files' => 'sites/mydrupalsite.com/files',
-#      '!custom' => '/my/custom/path',
+#      '%drush' => '/path/to/drush',
+#      '%drush-script' => '/path/to/drush/drush',
+#      '%dump' => '/path/to/live/sql_dump.sql',
+#      '%files' => 'sites/mydrupalsite.com/files',
+#      '%custom' => '/my/custom/path',
 #     ),
 #  );
 #$options['site-aliases']['dev'] = array(
Index: commands/core/core.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/core/core.drush.inc,v
retrieving revision 1.77
diff -u -p -r1.77 core.drush.inc
--- commands/core/core.drush.inc	25 Jan 2010 16:13:01 -0000	1.77
+++ commands/core/core.drush.inc	28 Jan 2010 09:22:24 -0000
@@ -368,6 +368,7 @@ function _core_site_status_table() {
     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');
+      $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'];
@@ -387,6 +388,8 @@ function _core_site_status_table() {
         }
       }
     }
+    $status_table['Default theme'] = drush_theme_get_default();
+    $status_table['Administration theme'] = drush_theme_get_admin();
   }
   if (function_exists('php_ini_loaded_file')) {
     // Function available on PHP >= 5.2.4, but we use it if available to help
@@ -394,8 +397,6 @@ function _core_site_status_table() {
     $status_table['PHP configuration'] = php_ini_loaded_file();
   }
   $status_table['Drush Version'] = DRUSH_VERSION;
-  $status_table['Default theme'] = drush_theme_get_default();
-  $status_table['Administration theme'] = drush_theme_get_admin();
   return $status_table;
 }
 
@@ -436,6 +437,7 @@ function drush_core_status() {
       }
     }
   }
+  drush_backend_set_result($status_table);
   // Print either an ini-format list or a formatted ASCII table
   if (drush_get_option('pipe')) {
     if (count($status_table) == 1) {
Index: commands/core/rsync.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/core/rsync.inc,v
retrieving revision 1.8
diff -u -p -r1.8 rsync.inc
--- commands/core/rsync.inc	27 Jan 2010 16:29:19 -0000	1.8
+++ commands/core/rsync.inc	28 Jan 2010 09:22:25 -0000
@@ -33,19 +33,21 @@ function drush_core_rsync($source, $dest
     if ((!empty($source_settings)) && (!empty($destination_settings)) && array_key_exists('path-aliases',$source_settings) && array_key_exists('path-aliases', $destination_settings)) {
       $source_path_aliases = $source_settings['path-aliases'];
       $destination_path_aliases = $destination_settings['path-aliases'];
-      $source_root = $source_path_aliases['!root'];
-      $destination_root = $destination_path_aliases['!root'];
+      $source_root = $source_settings['root'];
+      $destination_root = $destination_settings['root'];
       // First call drush sync to rsync the source and destination paths as provided
       $result = _drush_core_sync($source, $destination, array('exclude-sites' => TRUE));
       // After sync-ing with 'exclude-sites', go back and sync the
       // site directory for this installation.
       if ($result !== FALSE) {
-        $result = _drush_core_sync($source . ':!root/sites/' . $source_settings['uri'] . '/', $destination . ':!root/sites/' . $destination_settings['uri'] . '/');
+        $result = _drush_core_sync($source . ':sites/' . $source_settings['uri'] . '/', $destination . ':sites/' . $destination_settings['uri'] . '/');
       }
       // Iterate over all of the other path aliases
       foreach ($source_path_aliases as $key => $value) {
-        // Skip this entry if its value is a path that is somewhere inside of the root,
-        // which we already rsync'ed at the top of this function.  (This also skips '!root').
+        // Sync this entry if it exists in both the source and the
+        // destination path aliases, unless its value is a path that 
+        // is somewhere inside of the root, which we already rsync'ed 
+        // at the top of this function.
         if (($result !== FALSE) && (strncmp($source_root, $value, strlen($value)) != 0) && array_key_exists($key, $destination_path_aliases)) {
           $result = _drush_core_sync($source . ':' . $key, $destination . ':' . $key);
         }
@@ -224,7 +226,7 @@ function drush_core_call_rsync($source, 
  * A path is "machine:/path" or "machine:path" or "/path" or "path".
  * 'machine' might instead be an alias record, or the name
  * of a site in the 'sites' folder.  'path' might be (or contain)
- * '!root' or some other path alias.  This function will examine
+ * '%root' or some other path alias.  This function will examine
  * all components of the path and evaluate them as necessary to
  * come to the final path.
  *
@@ -238,6 +240,7 @@ function drush_core_call_rsync($source, 
  *   in the 'rsync-path' item.
  */
 function _drush_core_evaluate_path($path, $remote_user = '') {
+  $site_alias_settings = array();
   $path_aliases = array();
   // Parse site aliases if there is a colon in the path
   $colon_pos = strpos($path, ':');
@@ -289,20 +292,22 @@ function _drush_core_evaluate_path($path
 
   // Always add transient defaults
   _drush_sitealias_add_transient_defaults($site_alias_settings);
+
+  // Resolve path aliases such as %files, if any exist in the path
+  drush_sitealias_resolve_path_references($site_alias_settings, $path);
+
   if (array_key_exists('path-aliases', $site_alias_settings)) {
     $path_aliases = $site_alias_settings['path-aliases'];
   }
 
-  // If path aliases does not contain an alias for '!root',
+  // If site alias does not contain a 'root',
   // then assume that the remote Drupal root is the same
   // as the local Drupal root.
-  if (!array_key_exists('!root', $path_aliases)) {
-    $path_aliases['!root'] = drush_get_context('DRUSH_DRUPAL_ROOT');
-  }
+  $drupal_root = array_key_exists('root', $site_alias_settings) ? $site_alias_settings['root'] : drush_get_context('DRUSH_DRUPAL_ROOT');
   foreach ($path_aliases as $key => $value) {
     // Expand all relative path aliases to be based off of the Drupal root
-    if (($value[0] != '/') && ($key != '!root')) {
-      $path_aliases[$key] = $path_aliases['!root'] . '/' . $value;
+    if (($value[0] != '/') && ($key != '%root')) {
+      $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
@@ -314,7 +319,7 @@ function _drush_core_evaluate_path($path
       $path_aliases[$key] = $path_aliases[$key] . '/';
     }
   }
-
+  
   // Fill in path aliases in the path.
   $path = str_replace(array_keys($path_aliases), array_values($path_aliases), $path);
 
@@ -326,7 +331,7 @@ function _drush_core_evaluate_path($path
   // and path components together.
   // First make empty paths or relative paths start from the drupal root.
   if (empty($path) || ($path[0] != '/')) {
-      $path = $path_aliases['!root'] . $path;
+      $path = $drupal_root . $path;
   }
 
   // If there is a $machine component, to the path, then
Index: commands/core/sitealias.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/core/sitealias.drush.inc,v
retrieving revision 1.11
diff -u -p -r1.11 sitealias.drush.inc
--- commands/core/sitealias.drush.inc	27 Jan 2010 16:29:19 -0000	1.11
+++ commands/core/sitealias.drush.inc	28 Jan 2010 09:22:25 -0000
@@ -139,12 +139,17 @@ function _drush_sitealias_print_record($
 
   // Make sure that the default items have been added for all aliases
   _drush_sitealias_add_static_defaults($alias_record);
-
+  
+  drush_sitealias_resolve_path_references($alias_record);
+  
   // Include the optional items, if requested
   if ($output_optional_items) {
     _drush_sitealias_add_transient_defaults($alias_record);
   }
 
+  if (isset($output_db_url) || isset($output_db)) {
+    drush_sitealias_add_db_settings($alias_record);
+  }
   // If the user specified --with-db-url, then leave the
   // 'db-url' entry in the alias record (unless it is not
   // set, in which case we will leave the 'databases' record instead).
@@ -178,9 +183,9 @@ function _drush_sitealias_print_record($
   // We don't want the name to go into the output
   unset($alias_record['name']);
 
-  // We only want to output the 'root' item; don't output the '!root' path alias
-  if (array_key_exists('path-aliases', $alias_record) && array_key_exists('!root', $alias_record['path-aliases'])) {
-    unset($alias_record['path-aliases']['!root']);
+  // We only want to output the 'root' item; don't output the '%root' path alias
+  if (array_key_exists('path-aliases', $alias_record) && array_key_exists('%root', $alias_record['path-aliases'])) {
+    unset($alias_record['path-aliases']['%root']);
     // If there is nothing left in path-aliases, then clear it out
     if (count($alias_record['path-aliases']) == 0) {
       unset($alias_record['path-aliases']);
Index: commands/sql/sql.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/sql/sql.drush.inc,v
retrieving revision 1.36
diff -u -p -r1.36 sql.drush.inc
--- commands/sql/sql.drush.inc	20 Jan 2010 18:10:11 -0000	1.36
+++ commands/sql/sql.drush.inc	28 Jan 2010 09:22:25 -0000
@@ -85,7 +85,7 @@ function sql_drush_command() {
   );
   $items['sql-sync'] = array(
     'description' => 'Copy source database to target database using rsync.',
-    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION,
+    'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
     'examples' => array(
       'drush sql-sync prod dev' => 'Copy the DB defined in sites/prod to the DB in sites/dev.',
     ),
Index: commands/sql/sync.sql.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/sql/sync.sql.inc,v
retrieving revision 1.13
diff -u -p -r1.13 sync.sql.inc
--- commands/sql/sync.sql.inc	16 Jan 2010 01:11:45 -0000	1.13
+++ commands/sql/sync.sql.inc	28 Jan 2010 09:22:25 -0000
@@ -148,7 +148,7 @@ function _drush_sql_sync($source, $desti
         // Check to see if we are using a temporary file in a situation
         // where the user did not specify "--temp".
         if (($source_is_tmp || $target_is_tmp) && (!isset($use_temp_files)) && (isset($source_remote_host)  || isset($target_remote_host))) {
-          drush_print(dt('WARNING:  Using temporary files to store and transfer sql-dump.  It is recommended that you specify --source-dump and --target-dump options on the command line, or set \'!dump\' in the path-aliases section of your site alias records. This facilitates fast file transfer via rsync.'));
+          drush_print(dt('WARNING:  Using temporary files to store and transfer sql-dump.  It is recommended that you specify --source-dump and --target-dump options on the command line, or set \'%dump\' in the path-aliases section of your site alias records. This facilitates fast file transfer via rsync.'));
         }
 
         $txt_source = (isset($source_remote_host) ? $source_remote_host . '/' : '') . $source_db_url['database'];
Index: includes/backend.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/backend.inc,v
retrieving revision 1.26
diff -u -p -r1.26 backend.inc
--- includes/backend.inc	27 Jan 2010 16:29:19 -0000	1.26
+++ includes/backend.inc	28 Jan 2010 09:22:26 -0000
@@ -342,7 +342,7 @@ function _drush_backend_generate_command
   }
 
   $drush_path = !is_null($drush_path) ? $drush_path : (is_null($hostname) ? DRUSH_COMMAND : 'drush'); // Call own drush.php file on local machines, or 'drush' on remote machines.
-  $data['root'] = ($data['root']) ? $data['root'] : drush_get_context('DRUSH_DRUPAL_ROOT');
+  $data['root'] = array_key_exists('root', $data) ? $data['root'] : drush_get_context('DRUSH_DRUPAL_ROOT');
   $data['uri'] = array_key_exists('uri', $data) ? $data['uri'] : drush_get_context('DRUSH_URI');
 
   $option_str = _drush_backend_argument_string($data, $method);
Index: includes/drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/drush.inc,v
retrieving revision 1.81
diff -u -p -r1.81 drush.inc
--- includes/drush.inc	27 Jan 2010 16:29:19 -0000	1.81
+++ includes/drush.inc	28 Jan 2010 09:22:27 -0000
@@ -826,17 +826,7 @@ function drush_remote_command() {
     $command = array_shift($args);
 
     foreach ($site_list as $site_spec) {
-      $site_record = _drush_sitealias_get_record($site_spec);
-      if (!empty($site_record)) {
-        // Pass only the root and uri parameters from the site alias;
-        // put them in the 'options' context where they are sure to
-        // be picked up by the command redispatch helper.
-        drush_set_option('root', $site_record['root'], 'options');
-        drush_set_option('uri', $site_record['uri'], 'options');
-        drush_unset_option('r');
-        drush_unset_option('l');
-        drush_do_command_redispatch($command, $args, $site_record['remote-host'], $site_record['remote-user']);
-      }
+      drush_do_site_command(_drush_sitealias_get_record($site_spec), $command, $args);
     }
     return TRUE;
   }
@@ -925,26 +915,51 @@ function drush_do_multiple_command($comm
   return $is_multiple_command;
 }
 
+function drush_do_site_command($site_record, $command, $args = array(), $data = array()) {
+  $values = NULL;
+  if (!empty($site_record)) {
+    // Pass the root and uri parameters from the site alias
+    $data['root'] = $site_record['root'];
+    $data['uri'] = $site_record['uri'];
+    
+    $drush_path = NULL;
+    if (array_key_exists('path-aliases', $site_record) && !array_key_exists('remote-host', $site_record)) {
+      if (array_key_exists('%drush-script', $site_record['path-aliases'])) {
+        $drush_path = $site_record['path-aliases']['%drush-script'];
+      }
+      if (array_key_exists('%drush', $site_record['path-aliases'])) {
+        $drush_path = $site_record['path-aliases']['%drush'] . '/drush';
+      }
+    }
+    
+    $values = drush_backend_invoke_args($command, $args, $data, 'GET', FALSE, $drush_path, array_key_exists('remote-host', $site_record) ? $site_record['remote-host'] : NULL, array_key_exists('remote-user', $site_record) ? $site_record['remote-user'] : NULL);
+  }
+  return $values;
+}
+
 /**
  * Redispatch the specified command using the same
  * options that were passed to this invocation of drush.
  */
-function drush_do_command_redispatch($command, $args, $remote_host = NULL, $remote_user = NULL) {
+function drush_do_command_redispatch($command, $args = array(), $remote_host = NULL, $remote_user = NULL, $drush_path = NULL) {
   $data = drush_redispatch_get_options();
 
   // If the path to drush was supplied, then pass it to backend invoke.
-  // (Perhaps this should be added to the default handling of backend invoke.)
-  $drush_path = drush_get_option('drush-script');
-  if (!isset($drush_path)) {
-    $drush_folder = drush_get_option('drush');
-    if (isset($drush)) {
-      $drush_path = $drush_folder . '/drush';
+  if ($drush_path == NULL) {
+    $drush_path = drush_get_option('drush-script');
+    if (!isset($drush_path)) {
+      $drush_folder = drush_get_option('drush');
+      if (isset($drush)) {
+        $drush_path = $drush_folder . '/drush';
+      }
     }
   }
   // Call through to backend invoke.
   drush_log(dt('Begin redispatch via backend invoke'));
   $values = drush_backend_invoke_args($command, $args, $data, 'GET', TRUE, $drush_path, $remote_host, $remote_user);
   drush_log(dt('Backend invoke is complete'));
+  
+  return $values;
 }
 
 /**
Index: includes/sitealias.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/sitealias.inc,v
retrieving revision 1.14
diff -u -p -r1.14 sitealias.inc
--- includes/sitealias.inc	27 Jan 2010 16:29:20 -0000	1.14
+++ includes/sitealias.inc	28 Jan 2010 09:22:27 -0000
@@ -115,7 +115,7 @@ function _drush_sitealias_get_record($al
         }
         else {
           // Copy various parts of the parsed URL into the appropriate records of the alias record
-          foreach (array('user' => 'remote-user', 'pass' => 'remote-pass', 'host' => 'remote-host', 'fragment' => 'uri', 'path' => '!root') as $url_key => $option_key) {
+          foreach (array('user' => 'remote-user', 'pass' => 'remote-pass', 'host' => 'remote-host', 'fragment' => 'uri', 'path' => 'root') as $url_key => $option_key) {
             if (array_key_exists($url_key, $parsed)) {
               _drush_sitealias_set_record_element($alias_record, $option_key, $parsed[$url_key]);
             }
@@ -152,20 +152,8 @@ function _drush_sitealias_get_record($al
 
     // If the alias record does not have a defined 'databases' entry,
     // then we'll need to look one up
-    if ($db_settings_needed && !isset($alias_record['db-url']) && !isset($alias_record['databases']) && !isset($alias_record['site-list'])) {
-      // If the alias record is remote, then we'll use backend_invoke to fetch the
-      // database settings from the remote machine
-      if (array_key_exists('remote-host', $alias_record)) {
-        $data = array('root' => $alias_record['root'], 'uri' => $alias_record['uri'], 'all' => TRUE);
-        $args = array();
-        $values = drush_backend_invoke_args("sql-conf", $args, $data, 'GET', FALSE, $alias_record['path-aliases']['!drush-script'], $alias_record['remote-host'], $alias_record['remote-user']);
-        $alias_record['databases'] = $values['object'];
-      }
-      // If the alias record is for a local machine, then look up and
-      // use the database settings from the appropriate settings.php file.
-      else {
-        $alias_record = array_merge(_drush_sitealias_build_record_from_settings($alias_record['uri'], $alias_record['root']), $alias_record);
-      }
+    if ($db_settings_needed) {
+      drush_sitealias_add_db_settings(&$alias_record);
     }
 
     // Add the static defaults
@@ -184,6 +172,53 @@ function _drush_sitealias_get_record($al
   return $alias_record;
 }
 
+function drush_sitealias_add_db_settings(&$alias_record)
+{
+  // If the alias record does not have a defined 'databases' entry,
+  // then we'll need to look one up
+  if (!isset($alias_record['db-url']) && !isset($alias_record['databases']) && !isset($alias_record['site-list'])) {
+    // If the alias record is remote, then we'll use backend_invoke to fetch the
+    // database settings from the remote machine
+    if (array_key_exists('remote-host', $alias_record)) {
+      $values = drush_do_site_command($alias_record, "sql-conf", array(), array('all' => TRUE));
+      $alias_record['databases'] = $values['object'];
+    }
+    // If the alias record is for a local machine, then look up and
+    // use the database settings from the appropriate settings.php file.
+    else {
+      $alias_record = array_merge(_drush_sitealias_build_record_from_settings($alias_record['uri'], $alias_record['root']), $alias_record);
+    }
+  }
+}
+
+function drush_sitealias_resolve_path_references(&$alias_record, $test_string = '') {
+  $resolution_needed = FALSE;
+  // 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)) {
+    foreach ($alias_record['path-aliases'] as $key => $value) {
+      if (substr($value,0,1) == '@') {
+        if (empty($test_string) || (strstr($test_string, $key) !== FALSE)) {
+          $resolution_needed = TRUE;
+        }
+      }
+    }
+  }
+  
+  if ($resolution_needed) {
+    $values = drush_do_site_command($alias_record, "status");
+    $status_values = $values['object'];
+    foreach ($alias_record['path-aliases'] as $key => $value) {
+      if (substr($value,0,1) == '@') {
+        $status_key = strtr(substr($value,1), '-_', '  ');
+        if (array_key_exists($status_key, $status_values)) {
+          $alias_record['path-aliases'][$key] = $status_values[$status_key];
+        }
+      }
+    }
+  }
+}
+
 function drush_sitealias_resolve_sitelist($alias_record) {
   $result_list = array();
   if (isset($alias_record)) {
@@ -334,15 +369,28 @@ function _drush_sitealias_add_static_def
   if (isset($alias_record['db-url']) && !isset($alias_record['databases'])) {
     $alias_record['databases'] = drush_sitealias_convert_db_from_db_url($alias_record['db-url']);
   }
-  // If there is a 'root' entry, then copy it to the '!root'
-  // path alias
-  if (array_key_exists('root', $alias_record) && (!array_key_exists('path-aliases', $alias_record) || !array_key_exists('!root', $alias_record['path-aliases']))) {
-    $alias_record['path-aliases']['!root'] = $alias_record['root'];
-  }
-  // If there is a '!root' entry in the path aliases but no
-  // 'root' entry, then copy the path alias to 'root'
-  if (!array_key_exists('root', $alias_record) && array_key_exists('path-aliases', $alias_record) && array_key_exists('!root', $alias_record['path-aliases'])) {
-    $alias_record['root'] = $alias_record['path-aliases']['!root'];
+  // Adjustments for aliases to drupal instances (as opposed to aliases that are site lists)
+  if (array_key_exists('uri', $alias_record)) {
+    // Make sure that there is always a 'path-aliases' array
+    if (!array_key_exists('path-aliases', $alias_record)) {
+      $alias_record['path-aliases'] = array();
+    }
+    // If there is a '%root' or '!root' entry in the path aliases but no
+    // 'root' entry, then copy the path alias to 'root'
+    if (!array_key_exists('root', $alias_record) && array_key_exists('path-aliases', $alias_record) && array_key_exists('%root', $alias_record['path-aliases'])) {
+      $alias_record['root'] = $alias_record['path-aliases']['%root'];
+    }
+    if (!array_key_exists('root', $alias_record) && array_key_exists('path-aliases', $alias_record) && array_key_exists('!root', $alias_record['path-aliases'])) {
+      $alias_record['root'] = $alias_record['path-aliases']['!root'];
+    }
+    // If there is a 'root' entry, then copy it to the '%root' path alias
+    $alias_record['path-aliases']['%root'] = $alias_record['root'];
+    // Add %files if it does not exist
+    if (!array_key_exists('%files', $alias_record['path-aliases'])) {
+      // Path values that start with '@' will call 'drush status'
+      // to get the actual value to be substituted.
+      $alias_record['path-aliases']['%files'] = '@File_Directory_Path';
+    }
   }
 }
 
@@ -516,17 +564,17 @@ function _drush_find_local_sites_at_root
 function _drush_sitealias_add_transient_defaults(&$alias_record) {
   if (isset($alias_record['path-aliases'])) {
     // Add the path to the drush folder to the path aliases as !drush
-    if (!array_key_exists('!drush', $alias_record['path-aliases'])) {
-      if (array_key_exists('!drush-script', $alias_record['path-aliases'])) {
-        $alias_record['path-aliases']['!drush'] = dirname($alias_record['path-aliases']['!drush-script']);
+    if (!array_key_exists('%drush', $alias_record['path-aliases'])) {
+      if (array_key_exists('%drush-script', $alias_record['path-aliases'])) {
+        $alias_record['path-aliases']['%drush'] = dirname($alias_record['path-aliases']['%drush-script']);
       }
       else {
-        $alias_record['path-aliases']['!drush'] = dirname($GLOBALS['argv'][0]);
+        $alias_record['path-aliases']['%drush'] = dirname($GLOBALS['argv'][0]);
       }
     }
     // Add the path to the site folder to the path aliases as !site
-    if (!array_key_exists('!site', $alias_record['path-aliases']) && array_key_exists('uri', $alias_record)) {
-      $alias_record['path-aliases']['!site'] = 'sites/' . $alias_record['uri'] . '/';
+    if (!array_key_exists('%site', $alias_record['path-aliases']) && array_key_exists('uri', $alias_record)) {
+      $alias_record['path-aliases']['%site'] = 'sites/' . $alias_record['uri'] . '/';
     }
   }
 }
@@ -573,7 +621,7 @@ function _drush_sitealias_find_record_fo
 
   $all_site_aliases = drush_get_option('site-aliases', array());
   foreach ($all_site_aliases as $one_alias_name => $one_alias_record) {
-    if (!isset($one_alias_record['remote-host']) && isset($one_alias_record['path-aliases']) && isset($one_alias_record['path-aliases']['!root']) && ($one_alias_record['uri'] == $alias) && ($one_alias_record['path-aliases']['!root'] == $drupal_root)) {
+    if (!isset($one_alias_record['remote-host']) && isset($one_alias_record['root']) && isset($one_alias_record['uri']) && ($one_alias_record['uri'] == $alias) && ($one_alias_record['root'] == $drupal_root)) {
       $alias_record = $one_alias_record;
     }
   }
@@ -639,11 +687,8 @@ function drush_sitealias_build_record_fr
     else {
       $alias_record['databases'] = $databases;
     }
-    $alias_record['path-aliases'] = array(
-      '!root' => $drupal_root,
-      /*'!files' => '/path/to/file/storage', */
-      /*'!dump' => '/path/to/sql/dumpfile', */ );
 
+    $alias_record['root'] = $drupal_root;
     if (isset($alias)) {
       $alias_record['uri'] = $alias;
     }
@@ -738,10 +783,10 @@ function drush_sitealias_convert_db_from
 
 /**
  * Utility function used by drush_get_alias; keys that start with
- * '!' are path aliases, the rest are entries in the alias record.
+ * '%' or '!' are path aliases, the rest are entries in the alias record.
  */
 function _drush_sitealias_set_record_element(&$alias_record, $key, $value) {
-  if (substr($key,0,1) == '!') {
+  if ((substr($key,0,1) == '%') || (substr($key,0,1) == '!')) {
     $alias_record['path-aliases'][$key] = $value;
   }
   elseif (!empty($key)) {
@@ -800,7 +845,7 @@ function drush_sitealias_set_alias_conte
   }
   // Transfer selected path aliases to the drush options.
   if (array_key_exists('path-aliases', $site_alias_settings)) {
-    foreach (array('!root', '!drush', '!drush-script', '!dump', '!include') as $key) {
+    foreach (array('%drush', '%drush-script', '%dump', '%include') as $key) {
       if (array_key_exists($key, $site_alias_settings['path-aliases'])) {
         drush_set_option($prefix . substr($key, 1), $site_alias_settings['path-aliases'][$key], 'alias');
       }
