? boo.php
? drush-shebang.txt
? drushscript
? includes/table.inc
Index: examples/example.drushrc.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/examples/example.drushrc.php,v
retrieving revision 1.14
diff -u -p -r1.14 example.drushrc.php
--- examples/example.drushrc.php	9 Dec 2010 21:43:33 -0000	1.14
+++ examples/example.drushrc.php	21 Dec 2010 07:53:14 -0000
@@ -128,6 +128,19 @@
 # $options['output_charset'] = 'ISO-8859-1//TRANSLIT';
 
 /*
+ * Multiple command execution options
+ */
+// By default, drush will ask for confirmation before
+// it executes a single command on more than one target.
+// To always skip this prompt, set autoconfirm-multi to TRUE.
+# $options['autoconfirm-multi'] = TRUE;
+
+// If you would like drush to prepend the name of the
+// site to the output of any multiple command execution,
+// then set the --label-multi option
+# $options['label-multi'] = TRUE;
+
+/*
  * Customize this associative array with your own tables. This is the list of
  * tables whose *data* is skipped by the 'sql-dump' and 'sql-sync' commands when
  * a structure-tables-key is provided. You may add new tables to the existing
Index: includes/drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/drush.inc,v
retrieving revision 1.169
diff -u -p -r1.169 drush.inc
--- includes/drush.inc	20 Dec 2010 21:50:22 -0000	1.169
+++ includes/drush.inc	21 Dec 2010 07:53:15 -0000
@@ -235,6 +235,7 @@ function drush_get_global_options() {
   $options['-c, --config']             = dt("Specify a config file to use. See example.drushrc.php");
   $options['-u, --user']               = dt("Specify a user to login with. May be a name or a number.");
   $options['-b, --backend']            = dt("Hide all output and return structured data (internal use only).");
+  $options['--label-multi']            = dt("Show site name when executing a command on multiple sites (e.g. `drush @site1,@site2 status`).");
   $options['-p, --pipe']               = dt("Emit a compact representation of the command for scripting.");
   $options['--nocolor']                = dt("Suppress color highlighting on log messages.");
   $options['--show-passwords']         = dt("Show database passwords in commands that display connection information.");
@@ -1609,11 +1610,13 @@ function drush_remote_command() {
     if (!is_array($site_list)) {
       $site_list = explode(',', $site_list);
     }
+    $site_list = drush_sitealias_resolve_sitespecs($site_list);
+    $site_list = drush_sitealias_simplify_names($site_list);
     $args = drush_get_arguments();
 
-    if (!drush_get_context('DRUSH_SIMULATE')) {
+    if (!drush_get_context('DRUSH_SIMULATE') && !drush_get_option('autoconfirm-multi',FALSE)) {
       drush_print(dt("You are about to execute '!command' on all of the following targets:", array('!command' => implode(" ", $args))));
-      foreach ($site_list as $one_destination) {
+      foreach ($site_list as $one_destination => $one_record) {
         drush_print(dt('  !target', array('!target' => $one_destination)));
       }
 
@@ -1622,10 +1625,34 @@ function drush_remote_command() {
       }
     }
     $command = array_shift($args);
-
-    foreach ($site_list as $site_spec) {
-      $values = drush_do_site_command(_drush_sitealias_get_record($site_spec), $command, $args);
-      drush_print($values['output']);
+    $multi_options = drush_get_context('options');
+    
+    if (drush_get_option('label-multi', FALSE)) {
+      $label_separator = ' >> ';
+      $max_name_length = 0;
+      foreach ($site_list as $alias_name => $alias_record) {
+	if (strlen($alias_name) > $max_name_length) {
+	  $max_name_length = strlen($alias_name);
+	}
+      }
+      $multi_options['reserve-margin'] = $max_name_length + strlen($label_separator);
+      foreach ($site_list as $alias_name => $alias_record) {
+        $values = drush_do_site_command($alias_record, $command, $args, $multi_options);
+        foreach (explode("\n", $values['output']) as $line) {
+	  if (empty($line)) {
+	    drush_print();
+	  }
+	  else {
+            drush_print(str_pad($alias_name, $max_name_length, " ") . $label_separator . $line);
+	  }
+	}
+      }
+    }
+    else {
+      foreach ($site_list as $alias_name => $alias_record) {
+        $values = drush_do_site_command($alias_record, $command, $args, $multi_options);
+        drush_print($values['output']);
+      }
     }
     return TRUE;
   }
Index: includes/environment.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/environment.inc,v
retrieving revision 1.107
diff -u -p -r1.107 environment.inc
--- includes/environment.inc	6 Dec 2010 21:57:08 -0000	1.107
+++ includes/environment.inc	21 Dec 2010 07:53:16 -0000
@@ -551,6 +551,12 @@ function _drush_bootstrap_drush() {
     // If stty failed, or we couldn't parse it's output, we assume 80 columns.
     if ($stty_status || !$stty_count) $columns = 80;
   }
+  // If a caller wants to reserve some room to add additional
+  // information to the drush output via post-processing, the
+  // --reserve-margin flag can be used to declare how much
+  // space to leave out.  This only affects drush functions
+  // such as drush_print_table that wrap the output.
+  $columns -= drush_get_option('reserve-margin', 0);
   drush_set_context('DRUSH_COLUMNS', $columns);
 
   // statically define a way to call drush again
Index: includes/sitealias.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/sitealias.inc,v
retrieving revision 1.64
diff -u -p -r1.64 sitealias.inc
--- includes/sitealias.inc	9 Dec 2010 01:06:24 -0000	1.64
+++ includes/sitealias.inc	21 Dec 2010 07:53:17 -0000
@@ -35,6 +35,27 @@ function drush_sitealias_check_arg() {
 }
 
 /**
+ * Given a list of alias records, shorten the name used if possible
+ */
+function drush_sitealias_simplify_names($site_list) {
+//  foreach ($site_list as $original_name => $alias_record) {
+//  }
+  $result = array();
+  foreach ($site_list as $original_name => $alias_record) {
+    $adjusted_name = $alias_record['name'];
+    $hashpos = strpos($original_name, '#');
+    if ($hashpos !== FALSE) {
+      $adjusted_name = substr($original_name, $hashpos);
+      if (array_key_exists('remote-host', $alias_record)) {
+        $adjusted_name = $alias_record['remote-host'] . $adjusted_name;
+      }
+    }
+    $result[$adjusted_name] = $alias_record;
+  }
+  return $result;
+}
+
+/**
  * Given an array of site specifications, resolve each one in turn and
  * return an array of alias records.  If you only want a single record,
  * it is preferable to simply call drush_sitealias_get_record directly.
@@ -289,7 +310,7 @@ function drush_sitealias_alias_path($ali
 function drush_sitealias_local_site_path($alias_record) {
   $result = NULL;
 
-  if (isset($alias_record['uri']) && isset($alias_record['root']) && !isset($alias_record['remote_host'])) {
+  if (isset($alias_record['uri']) && isset($alias_record['root']) && !isset($alias_record['remote-host'])) {
     $result = realpath($alias_record['root'] . '/sites/' . drush_sitealias_uri_to_site_dir($alias_record['uri']));
   }
 
@@ -994,22 +1015,23 @@ function _drush_sitealias_find_local_sit
 function _drush_find_local_sites_at_root($a_drupal_root = '', $search_depth = 1) {
   $site_list = array();
   $base_path = (empty($a_drupal_root) ? drush_get_context('DRUSH_DRUPAL_ROOT') : $a_drupal_root );
-  if (drush_valid_drupal_root($base_path)) {
-    // If $a_drupal_root is in fact a valid drupal root, then return
-    // all of the sites found inside the 'sites' folder of this drupal instance.
-    $site_list = _drush_find_local_sites_in_sites_folder($base_path);
-  }
-  else {
-    $bootstrap_files = drush_scan_directory($base_path, '/' . basename(DRUSH_DRUPAL_BOOTSTRAP) . '/' , array('.', '..', 'CVS'), 0, drush_get_option('search-depth', $search_depth) + 1, 'filename', 1);
-    foreach ($bootstrap_files as $one_bootstrap => $info) {
-      $includes_dir = dirname($one_bootstrap);
-      if (basename($includes_dir) == basename(dirname(DRUSH_DRUPAL_BOOTSTRAP))) {
-        $drupal_root = dirname($includes_dir);
-        $site_list = array_merge(_drush_find_local_sites_in_sites_folder($drupal_root), $site_list);
+  if (!empty($base_path)) {
+    if (drush_valid_drupal_root($base_path)) {
+      // If $a_drupal_root is in fact a valid drupal root, then return
+      // all of the sites found inside the 'sites' folder of this drupal instance.
+      $site_list = _drush_find_local_sites_in_sites_folder($base_path);
+    }
+    else {
+      $bootstrap_files = drush_scan_directory($base_path, '/' . basename(DRUSH_DRUPAL_BOOTSTRAP) . '/' , array('.', '..', 'CVS'), 0, drush_get_option('search-depth', $search_depth) + 1, 'filename', 1);
+      foreach ($bootstrap_files as $one_bootstrap => $info) {
+	$includes_dir = dirname($one_bootstrap);
+	if (basename($includes_dir) == basename(dirname(DRUSH_DRUPAL_BOOTSTRAP))) {
+          $drupal_root = dirname($includes_dir);
+          $site_list = array_merge(_drush_find_local_sites_in_sites_folder($drupal_root), $site_list);
+	}
       }
     }
   }
-
   return $site_list;
 }
 
