Index: drush.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush.php,v
retrieving revision 1.60
diff -u -p -u -p -r1.60 drush.php
--- drush.php	16 Apr 2009 02:48:43 -0000	1.60
+++ drush.php	29 Apr 2009 23:36:58 -0000
@@ -15,6 +15,8 @@ if (!drush_verify_cli()) {
 }
 
 define('DRUSH_BASE_PATH', dirname(__FILE__));
+define('DRUSH_COMMAND', $GLOBALS['argv'][0]);
+
 require_once DRUSH_BASE_PATH . '/includes/environment.inc';
 require_once DRUSH_BASE_PATH . '/includes/command.inc';
 require_once DRUSH_BASE_PATH . '/includes/drush.inc';
@@ -23,6 +25,7 @@ require_once DRUSH_BASE_PATH . '/include
 
 drush_set_context('argc', $GLOBALS['argc']);
 drush_set_context('argv', $GLOBALS['argv']);
+
 exit(drush_main());
 
 /**
@@ -57,7 +60,7 @@ function drush_main() {
     if (drush_bootstrap($phase)) {
       $command = drush_parse_command();
       if (is_array($command)) {
-        if ($command['bootstrap'] == $phase) {
+        if ($command['bootstrap'] == $phase && empty($command['bootstrap_errors'])) {
           drush_log(dt("Found command: !command", array('!command' => $command['command'])), 'bootstrap');
           // Dispatch the command(s).
           // After this point the drush_shutdown function will run,
@@ -70,9 +73,18 @@ function drush_main() {
       break;
     }
   }
-  $args = implode(" ", drush_get_arguments());
-  // If we reach this point, we have not found a valid command.
-  drush_set_error('DRUSH_COMMAND_NOT_FOUND', dt("The command 'drush.php !args' could not be executed.", array('!args' => $args)));
+  // If we reach this point, we have not found either a valid or matching command.
+  $args = implode(' ', drush_get_arguments());
+  $drush_command = array_pop(explode('/', DRUSH_COMMAND));
+  if ($command) {
+    foreach ($command['bootstrap_errors'] as $key => $error) {
+      drush_set_error($key, $error); 
+    }
+    drush_set_error('DRUSH_COMMAND_NOT_EXECUTABLE', dt("The command '!drush_command !args' could not be executed.", array('!drush_command' => $drush_command, '!args' => $args)));
+  }
+  else {
+    drush_set_error('DRUSH_COMMAND_NOT_FOUND', dt("The command '!drush_command !args' could not be found.", array('!drush_command' => $drush_command, '!args' => $args)));
+  }
 }
 
 /**
Index: commands/core/core.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/core/core.drush.inc,v
retrieving revision 1.22
diff -u -p -u -p -r1.22 core.drush.inc
--- commands/core/core.drush.inc	24 Apr 2009 05:20:37 -0000	1.22
+++ commands/core/core.drush.inc	29 Apr 2009 23:36:58 -0000
@@ -127,7 +127,7 @@ function core_help() {
   if (empty($commands)) {
     drush_show_help(array('help'));
     $phases = _drush_bootstrap_phases(); 
-    drush_print('Commands: ');
+    drush_print(dt('Commands: '));
 
     $printed_rows = array();
     $phase_index = DRUSH_BOOTSTRAP_DRUSH;
@@ -150,7 +150,7 @@ function core_help() {
         
         $rows = array();
         foreach($commands as $key => $command) {
-          if (!array_key_exists($key, $printed_rows)) {
+          if (!array_key_exists($key, $printed_rows) && empty($commands[$key]['bootstrap_errors'])) {
             $rows[$key] = array(sprintf("%-20s", $key), $commands[$key]['description']);
           }
         }
Index: includes/backend.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/backend.inc,v
retrieving revision 1.11
diff -u -p -u -p -r1.11 backend.inc
--- includes/backend.inc	21 Apr 2009 16:55:55 -0000	1.11
+++ includes/backend.inc	29 Apr 2009 23:36:58 -0000
@@ -283,8 +283,7 @@ function _drush_backend_invoke($cmd, $da
  *   A text string representing a fully escaped command.
  */
 function _drush_backend_generate_command($command, &$data, $method = 'GET', $drush_path = null, $hostname = null, $username = null) {
-
-  $drush_path = !is_null($drush_path) ? $drush_path : $_SERVER['argv'][0]; // Call own drush.php file.
+  $drush_path = !is_null($drush_path) ? $drush_path : DRUSH_COMMAND; // Call own drush.php file.
   $data['root'] = ($data['root']) ? $data['root'] : drush_get_context('DRUSH_DRUPAL_ROOT');
   $data['uri'] = array_key_exists('uri', $data) ? $data['uri'] : drush_get_context('DRUSH_URI');
 
Index: includes/command.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/command.inc,v
retrieving revision 1.27
diff -u -p -u -p -r1.27 command.inc
--- includes/command.inc	17 Apr 2009 18:18:17 -0000	1.27
+++ includes/command.inc	29 Apr 2009 23:36:58 -0000
@@ -76,9 +76,6 @@ function drush_parse_args() {
  * Get a list of all implemented commands.
  * This invokes hook_drush_command().
  *
- * @param boolean
- *   If TRUE, the internal commands table will be rebuild.
- *
  * @return
  *   Associative array of currently active command descriptors.
  *
@@ -91,19 +88,30 @@ function drush_get_commands() {
       $function = $commandfile . '_drush_command';
       $result = $function();
       foreach ((array)$result as $key => $command) {
-        // Add some defaults
+        // Add some defaults and normalize the command descriptor
         $command += array(
+          'command' => $key,
           'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_LOGIN,
           'commandfile' => $commandfile,
           'path' => dirname($path),
           'engines' => array(), // Helpful for drush_show_help(). 
+          'callback' => 'drush_command',
+          'description' => NULL,
+          'arguments' => array(),
+          'options' => array(),
+          'extras' => array(),
+          'core' => array(),
+          'scope' => 'site',
+          'drupal dependencies' => array(),
+          'drush dependencies' => array(),
+          'bootstrap_errors' => array(),
         );
-        // Filter out commands which are invalid for this bootstrap phase, core or have missing dependencies.
-        if (drush_enforce_requirement_bootstrap_phase($command)
-            && drush_enforce_requirement_core($command)
-            && drush_enforce_requirement_drupal_dependencies($command)) {
-          $commands[$key] = $command;
-        }
+        // Collect all the commands (without filtering) so we can match non-executable
+        // commands, and later explain why they are not executable.
+        drush_enforce_requirement_bootstrap_phase($command);
+        drush_enforce_requirement_core($command);
+        drush_enforce_requirement_drupal_dependencies($command);
+        $commands[$key] = $command;
       }
     }
   }
@@ -150,27 +158,13 @@ function drush_parse_command() {
     $part = implode(" ", $args);
     if (isset($implemented[$part])) {
       $command = $implemented[$part];
-      // Normalize command descriptor
-      $command += array(
-        'command' => $part,
-        'callback' => 'drush_command',
-        'description' => NULL,
-        'arguments' => array(),
-        'options' => array(),
-        'extras' => array(),
-        'core' => array(),
-        'scope' => 'site',
-        'bootstrap' => NULL,
-        'drupal dependencies' => array(),
-        'drush dependencies' => array(),
-      );
     }
     else {
       $arguments[] = array_pop($args);
     }
   }
 
-  // We have found a command that can be executed. Set the appropriate values.
+  // We have found a command that matches. Set the appropriate values.
   if ($command) {
     $arguments = array_reverse($arguments);
 
@@ -528,17 +522,20 @@ function drush_scan_directory($dir, $mas
  * Check that a command is valid for the current bootstrap phase.
  * 
  * @param $command
- *   Command to check
+ *   Command to check. Any errors  will be added to the 'bootstrap_errors' element.  
  * 
  * @return
  *   TRUE if command is valid.
  */
-function drush_enforce_requirement_bootstrap_phase($command) {
+function drush_enforce_requirement_bootstrap_phase(&$command) {
   $valid = array();
   $current_phase = drush_get_context('DRUSH_BOOTSTRAP_PHASE');
   if ($command['bootstrap'] == $current_phase) {
     return TRUE;
   }
+  // TODO: pprovide description text for each bootstrap level so we can give
+  // the user something more helpful and specific here.
+  $command['bootstrap_errors']['DRUSH_COMMAND_INSUFFICIENT_BOOTSTRAP'] = dt('Command !command needs a higher bootstrap level to run - you will need invoke drush from a more functional Drupal environment to run this command.', array('!command' => $command['command']));
 }
 
 /**
@@ -546,12 +543,12 @@ function drush_enforce_requirement_boots
  * dependencies.
  * 
  * @param $command
- *   Command to check
+ *   Command to check. Any errors  will be added to the 'bootstrap_errors' element.
  * 
  * @return
  *   TRUE if command is valid.
  */
-function drush_enforce_requirement_drupal_dependencies($command) {
+function drush_enforce_requirement_drupal_dependencies(&$command) {
   if (empty($command['drupal dependencies'])) {
     return TRUE;
   }
@@ -562,19 +559,26 @@ function drush_enforce_requirement_drupa
       }
     }
   }
+  $command['bootstrap_errors']['DRUSH_COMMAND_DEPENDENCY_ERROR'] = dt('Command !command needs the following modules installed/enabled to run: !dependencies.', array('!command' => $command['command'], '!dependencies' => implode(', ', $command['drupal dependencies'])));
 }
 
 /**
  * Check that a command is valid for the current major version of core.
  * 
  * @param $command
- *   Command to check
+ *   Command to check. Any errors  will be added to the 'bootstrap_errors' element.
  * 
  * @return
  *   TRUE if command is valid.
  */
-function drush_enforce_requirement_core($command) {
-  if (empty($command['core']) || in_array(drush_drupal_major_version(), $command['core'])) {
+function drush_enforce_requirement_core(&$command) {
+  $core = $command['core'];
+  if (empty($core) || in_array(drush_drupal_major_version(), $core)) {
     return TRUE;
   }
+  $versions = array_pop($core);
+  if (!empty($core)) {
+    $versions = implode(', ', $core) . dt(' or ') . $versions;
+  }
+  $command['bootstrap_errors']['DRUSH_COMMAND_CORE_VERSION_ERROR'] = dt('Command !command requires Drupal core version !versions to run.', array('!command' => $command['command'], '!versions' => $versions));
 }
Index: includes/drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/drush.inc,v
retrieving revision 1.29
diff -u -p -u -p -r1.29 drush.inc
--- includes/drush.inc	19 Apr 2009 03:56:32 -0000	1.29
+++ includes/drush.inc	29 Apr 2009 23:36:58 -0000
@@ -153,12 +153,12 @@ function drush_include_engine($type, $en
     $path = $engines[$engine]['path'];
   }
   if (!$path) {
-    return drush_set_error('DRUSH_ENGINE INCLUDE_NO_PATH', "No $path was set for including the $type engine $engine.");
+    return drush_set_error('DRUSH_ENGINE INCLUDE_NO_PATH', dt('No !path was set for including the !type engine !engine.', array('!path' => $path, '!type' => $type, '!engine' => $engine)));
   }
   if (drush_include($path, $engine, $version)) {
     return TRUE;
   }
-  return drush_set_error('DRUSH_ENGINE INCLUDE_FAILED', "Unable to include the $type engine $engine from $path.");
+  return drush_set_error('DRUSH_ENGINE INCLUDE_FAILED', dt('Unable to include the !type engine !engine from !path.' , array('!path' => $path, '!type' => $type, '!engine' => $engine)));
 }
 
 /**
