? includes/table.inc
Index: includes/command.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/command.inc,v
retrieving revision 1.60
diff -u -p -r1.60 command.inc
--- includes/command.inc	21 Jan 2010 15:01:53 -0000	1.60
+++ includes/command.inc	21 Jan 2010 22:31:45 -0000
@@ -287,14 +287,17 @@ function drush_invoke($command) {
   // for better readability after the allow-spaces-in-commands
   // backwards-compatibility feature is removed.
   $hook = strtr($command, "- ", "__"); // n.b. str tr, not str str.
-  $list = drush_commandfile_list();
-
+  $list = array_keys(drush_commandfile_list());
+  $context_hooks = drush_get_context_hooks();
+  if (isset($context_hooks)) {
+    $list = array_merge($list, $context_hooks);
+  }
   $functions = array();
   // First we build a list of functions that are about to be executed
   $variations = array($hook . "_validate", "pre_$hook", $hook, "post_$hook");
   $all_available_hooks = array();
   foreach ($variations as $var_hook) {
-    foreach ($list as $commandfile => $filename) {
+    foreach ($list as $commandfile) {
       $oldfunc = sprintf("drush_%s_%s", $commandfile, $var_hook);
       $func = str_replace('drush_' . $commandfile . '_' . $commandfile, 'drush_' . $commandfile, $oldfunc);
       $all_available_hooks[] = $func;
@@ -322,12 +325,12 @@ function drush_invoke($command) {
     if ($rollback === FALSE) {
       $completed[] = $func;
       if (function_exists($func)) {
-	call_user_func_array($func, $args);
-	_drush_log_drupal_messages();
-	if (drush_get_error()) {
+        call_user_func_array($func, $args);
+        _drush_log_drupal_messages();
+        if (drush_get_error()) {
           drush_log(dt('An error occurred at function : @func', array('@func' => $func)), 'error');
           $rollback = TRUE;
-	}
+        }
       }
     }
   }
@@ -563,10 +566,21 @@ function drush_command_include($command)
   }
 }
 
+function drush_adjust_environment_for_command($command) {
+  $options_were_set  = _drush_command_add_command_specific_options($command);
+  $options_were_set |= drush_context_process_selected_contexts();
+  
+  // If we set or cleared any options, go back and re-bootstrap any global
+  // options such as -y and -v.
+  if ($options_were_set) {
+    _drush_bootstrap_global_options();
+  }
+}
+
 /**
  * Conditionally include default options based on the command used.
  */
-function drush_command_default_options($command) {
+function _drush_command_add_command_specific_options($command) {
   // Look for command-specific options for this command
   // keyed both on the command's primary name, and on each
   // of its aliases.
@@ -587,11 +601,8 @@ function drush_command_default_options($
       $options_were_set = TRUE;
     }
   }
-  // If we set or cleared any options, go back and re-bootstrap any global
-  // options such as -y and -v.
-  if ($options_were_set) {
-    _drush_bootstrap_global_options();
-  }
+  
+  return $options_were_set;
 }
 
 function _drush_command_set_default_options($command) {
Index: includes/context.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/context.inc,v
retrieving revision 1.18
diff -u -p -r1.18 context.inc
--- includes/context.inc	1 Jan 2010 07:53:11 -0000	1.18
+++ includes/context.inc	21 Jan 2010 22:31:46 -0000
@@ -81,6 +81,96 @@ function drush_context_names() {
 }
 
 /**
+ * Check to see if there are any custom contexts
+ * that need to be applied
+ */
+function drush_context_process_selected_contexts() {
+  $context_selectors = drush_get_option('context-selectors', array());
+  $selected_contexts = array();
+
+  $applied_context_name = drush_get_option('context');
+  if (isset($applied_context_name)) {
+    $selected_contexts[] = $applied_context_name;
+  }
+  
+  foreach($context_selectors as $selector) {
+    $selected = NULL;
+    $callback = NULL;
+    if (is_array($selector)) {
+      $is_selected = TRUE;
+      if (array_key_exists('selectors', $selector)) {
+        foreach ($selector['selectors'] as $option_key => $required_value) {
+          $option_value = drush_get_option($option_key);
+          if (isset($required_value)) {
+            if ($option_value != $required_value) {
+              $is_selected = FALSE;
+            }
+          }
+          else {
+            if (isset($option_value)) {
+              $is_selected = FALSE;
+            }
+          }
+        }
+      }
+      if ($is_selected) {
+        $selected = $selector['context'];
+        $selector['is-selected'] = TRUE;
+      }
+      if (array_key_exists('callback', $selector)) {
+        $callback = $selector['callback'];
+      }
+    }
+    else {
+      $callback = $selector;
+    }
+
+    if (isset($callback) && (function_exists($callback))) {
+      $selected = call_user_func_array($callback, $selector);
+    }
+    
+    if (isset($selected)) {
+      $selected_contexts = array_merge($selected_contexts, (array)$selected);
+    }
+  } 
+   return drush_context_process_context(array_unique($selected_contexts));
+}
+
+function drush_context_process_context($contexts) {
+  $set_options = FALSE;
+  if (isset($contexts)) {
+    if (!is_array($contexts)) {
+      $contexts = array($contexts);
+    }
+    foreach ($contexts as $context_name) {
+      $context_cache = drush_get_context('user-' . $context_name);
+
+      $context_hook = $context_name;
+
+      if (array_key_exists('options', $context_cache)) {
+        drush_set_options($context_cache['options']);
+	$set_options = TRUE;
+      }
+      if (array_key_exists('hooks', $context_cache)) {
+        $context_hook = $context_cache['hooks'];
+      }
+      if (array_key_exists('includes', $context_cache)) {
+        $includes - $context_cache['includes'];
+        if (!is_array($includes)) {
+          $includes = array($includes);
+        }
+        foreach ($includes as $include_file) {
+          require_once($include_file);
+        }
+      }
+
+      drush_add_context_hook($context_hook);
+    }
+  }
+  return $set_options;
+}
+
+/**
  * Return a list of possible drushrc file locations.
  *
  * @return
@@ -131,7 +221,7 @@ function _drush_config_file($context) {
 /**
  * Load drushrc files (if available) from several possible locations.
  */
-function drush_load_config($context) {
+function drush_load_config($config_context) {
   global $drush_conf_override;
 
   // Only reset $drush_conf_override if the array is not set, otherwise keep old values and append new values to it.
@@ -139,10 +229,11 @@ function drush_load_config($context) {
     $drush_conf_override = array();
   }
 
-  $config = _drush_config_file($context);
+  $config = _drush_config_file($config_context);
   if (file_exists($config)) {
-    drush_log(dt('Loading drushrc "!config" into "!context" scope.', array('!config' => realpath($config), '!context' => $context)), 'bootstrap');
-    $options['context-path'][$context] = $config;
+    drush_log(dt('Loading drushrc "!config" into "!context" scope.', array('!config' => realpath($config), '!context' => $config_context)), 'bootstrap');
+    $options = $context = array();
+    $options['context-path'][$config_context] = $config;
     require_once($config);
     
     // There are certain options such as 'site-aliases' and 'command-specific'
@@ -152,8 +243,8 @@ function drush_load_config($context) {
     // that came before in previously-loaded configuration files.  We place
     // all of them into the 'default' context so that this does not happen.
     if (isset($options)) {
-      foreach (array('site-aliases', 'command-specific') as $option_name) {
-        if ((isset($options)) && (array_key_exists($option_name, $options))) {
+      foreach (array('site-aliases', 'command-specific', 'context-selectors') as $option_name) {
+        if (array_key_exists($option_name, $options)) {
           $cache =& drush_get_context('default');
           if (array_key_exists($option_name, $cache)) {
             $cache[$option_name] = array_merge($cache[$option_name], $options[$option_name]);
@@ -166,7 +257,14 @@ function drush_load_config($context) {
       }
     }
     
-    drush_set_context($context, $options);
+    drush_set_context($config_context, $options);
+    
+    // Copy user contexts from configuration file into the drush context cache
+    if (isset($context)) {
+      foreach ($context as $context_name => $context_value) {
+        drush_set_context('user-' . $context_name, $context_value);
+      }
+    }
 
     // Instruct core not to queries since we are not outputting them.
     // This can be overridden by a command or a drushrc file if needed.
@@ -203,6 +301,37 @@ function drush_set_context($context, $va
   return $value;
 }
 
+/**
+ * Add a context hook.  The context hooks
+ * are evaluated after the commandfile hooks
+ * in drush_invoke.
+ *
+ * @param hook
+ *   The name of the hook to add
+ */
+function drush_add_context_hook($hook) {
+  if (isset($hook)) {
+    $hook_list = drush_get_context_hooks();
+    if (!is_array($hook)) {
+      $hook = array($hook);
+    }
+    foreach ($hook as $hook_name) {
+      if (!in_array($hook_name, $hook_list)) {
+        $hook_list[] = $hook_name;
+        drush_set_context('hook_list', $hook_list);
+      }
+    }
+  }
+}
+
+/**
+ * Get the list of context hooks.  Called by
+ * drush_invoke; these are added to the hook
+ * list immediately after the commandfile hooks.
+ */
+function drush_get_context_hooks() {
+  return drush_get_context('hook_list');
+}
 
 /**
  * Return a specific context, or the whole context cache
@@ -294,6 +423,7 @@ function drush_set_command($command) {
 function drush_get_command() {
   return drush_get_context('command');
 }
+
 /**
  * Get the value for an option.
  *
@@ -389,6 +519,12 @@ function drush_set_option($option, $valu
   return $value;
 }
 
+function drush_set_options($options, $context = 'process') {
+  foreach ($options as $option => $value) {
+    drush_set_option($option, $value, $context);
+  }
+}
+
 /**
  * A small helper function to set the value in the default context
  */
Index: includes/drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/drush.inc,v
retrieving revision 1.80
diff -u -p -r1.80 drush.inc
--- includes/drush.inc	21 Jan 2010 15:01:53 -0000	1.80
+++ includes/drush.inc	21 Jan 2010 22:31:46 -0000
@@ -24,9 +24,9 @@ function drush_dispatch($command = NULL)
   $return = FALSE;
 
   if ($command) {
-    // Add command-specific options, if applicable
-    drush_command_default_options($command);
-
+    // Add command-specific options and user-selected contexts, if applicable
+    drush_adjust_environment_for_command($command);
+    
     if (isset($command['must-replace-spaces'])) {
       $required_name = str_replace(' ', '-', $command['command']);
       drush_set_error(dt('Notice: "!name" must be renamed to "!requiredname" in order to work with this version of drush.  If you are the maintainer for the module that defines this command, please rename it immediately.  If you are a user of this command, you may enable spaces in commands for a while by setting "allow-spaces-in-commands" in your drush configuration file.  See example.drushrc.php.', array('!name' => $command['command'], '!requiredname' => $required_name)));
@@ -295,7 +295,7 @@ function drush_op($function) {
   array_shift($args); // Skip function name
 
   if (drush_get_context('DRUSH_VERBOSE') || drush_get_context('DRUSH_SIMULATE')) {
-     drush_print("Calling $function(". implode(", ", $args) .')');
+    drush_print("Calling $function(". implode(", ", $args) .')');
   }
 
   if (drush_get_context('DRUSH_SIMULATE')) {
