? includes/table.inc
Index: drush.api.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush.api.php,v
retrieving revision 1.5
diff -u -p -r1.5 drush.api.php
--- drush.api.php	7 Jan 2010 15:28:25 -0000	1.5
+++ drush.api.php	20 Jan 2010 06:46:29 -0000
@@ -18,21 +18,21 @@
  * 4. drush_hook_post_COMMAND()
  *
  * For example, here are the hook opportunities for a mysite.drush.inc file
- * that wants to hook into the `dl` command.
+ * that wants to hook into the `download` command.
  *
- * 1. drush_mysite_dl_validate()
- * 2. drush_mysite_pre_dl()
- * 3. drush_mysite_dl()
- * 4. drush_mysite_post_dl()
+ * 1. drush_mysite_download_validate()
+ * 2. drush_mysite_pre_download()
+ * 3. drush_mysite_download()
+ * 4. drush_mysite_post_download()
  *
  * If any of those fails, the rollback mechanism is called. It will
  * call, in reverse, all _rollback hooks. The mysite command file can implement
  * the following rollback hooks:
  *
- * 1. drush_mysite_post_dl_rollback()
- * 2. drush_mysite_dl_rollback()
- * 3. drush_mysite_pre_dl_rollback()
- * 4. drush_mysite_dl_validate_rollback()
+ * 1. drush_mysite_post_download_rollback()
+ * 2. drush_mysite_download_rollback()
+ * 3. drush_mysite_pre_download_rollback()
+ * 4. drush_mysite_download_validate_rollback()
  *
  * Before any command is called, hook_drush_init() is also called.
  * hook_drush_exit() is called at the very end of command invocation.
Index: example.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/example.drush.inc,v
retrieving revision 1.7
diff -u -p -r1.7 example.drush.inc
--- example.drush.inc	18 Jan 2010 21:02:25 -0000	1.7
+++ example.drush.inc	20 Jan 2010 06:46:29 -0000
@@ -56,7 +56,7 @@ function example_drush_command() {
  */
 function example_drush_help($section) {
   switch ($section) {
-    case 'drush:example':
+    case 'drush:example-foo':
       return dt("Prints the amount of time since January 1st, 1970, in years and weeks.");
   }
 }
@@ -65,9 +65,24 @@ function example_drush_help($section) {
  * Example drush command callback. This is where the action takes place.
  *
  * The function name should be same as command name but with dashes turned to
- * slashes and 'drush_' prepended.
+ * underscores and 'drush_commandfile_' prepended, where 'commandfile' is
+ * taken from the file 'commandfile.drush.inc', which in this case is 'example'.
+ * Note also that a simplification step is also done in instances where
+ * the commandfile name is the same as the beginning of the command name,
+ * "drush_example_example_foo" is simplified to just "drush_example_foo".
+ * To also implement a hook that is called before your command, implement
+ * "drush_hook_pre_example_foo".  For a list of all available hooks for a
+ * given command, run drush in --debug mode.
  *
- * In this function, all of Drupals API is (usually) available, including
+ * If for some reason you do not want your hook function to be named
+ * after your command, you may define a 'callback' item in your command
+ * object that specifies the exact name of the function that should be
+ * called.  However, the specified callback function must still begin
+ * with "drush_commandfile_" (e.g. 'callback' => "drush_example_foo_execute").
+ * All hook functions are still called (e.g. drush_example_pre_foo_execute,
+ * and so on.)
+ *
+ * In this function, all of Drupal's API is (usually) available, including
  * any functions you have added in your own modules/themes.
  *
  */
Index: commands/pm/pm.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/pm/pm.drush.inc,v
retrieving revision 1.77
diff -u -p -r1.77 pm.drush.inc
--- commands/pm/pm.drush.inc	19 Jan 2010 00:17:55 -0000	1.77
+++ commands/pm/pm.drush.inc	20 Jan 2010 06:46:30 -0000
@@ -104,7 +104,7 @@ function pm_drush_command() {
   );
   $items['pm-list'] = array(
     'description' => 'Show module enabled/disabled status',
-    'callback' => 'pm_module_manage',
+    'callback' => 'drush_pm_module_manage',
     'callback arguments' => array(array(), FALSE),
     'options' => array(
       '--pipe' => 'Returns a space delimited list of enabled modules.',
@@ -184,7 +184,7 @@ function pm_drush_command() {
  */
 function drush_pm_enable() {
   $args = func_get_args();
-  return pm_module_manage($args, TRUE);
+  return drush_pm_module_manage($args, TRUE);
 }
 
 /**
@@ -192,7 +192,7 @@ function drush_pm_enable() {
  */
 function drush_pm_disable() {
   $args = func_get_args();
-  return pm_module_manage($args, FALSE);
+  return drush_pm_module_manage($args, FALSE);
 }
 
 /**
@@ -240,7 +240,7 @@ function drush_pm_uninstall() {
   }
 }
 
-function pm_module_manage($modules = array(), $enable = TRUE) {
+function drush_pm_module_manage($modules = array(), $enable = TRUE) {
   if (function_exists('module_load_include')) {
     module_load_include('inc', 'system', 'system.admin');
   }
Index: commands/simpletest/simpletest.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/simpletest/simpletest.drush.inc,v
retrieving revision 1.5
diff -u -p -r1.5 simpletest.drush.inc
--- commands/simpletest/simpletest.drush.inc	7 Jan 2010 14:15:16 -0000	1.5
+++ commands/simpletest/simpletest.drush.inc	20 Jan 2010 06:46:30 -0000
@@ -22,7 +22,6 @@ function simpletest_drush_help($section)
  */
 function simpletest_drush_command() {
   $items['test-mail'] = array(
-    'callback' => 'drush_test_mail',
     'description' => 'Run all tests and mail the results to your team.',
     'examples' => array(
        "drush test-mail me@example.com --extra=\"--class BlockTestCase\"" => "Run block tests & email to me.",
@@ -39,13 +38,11 @@ function simpletest_drush_command() {
     'core' => array('6','7'),
   );
   $items['test-clean'] = array(
-    'callback' => 'drush_test_clean',
     'description' => 'Delete leftover tables and files from prior test runs.',
     'drupal dependencies' => array('simpletest'),
     'core' => array('6','7'),
   );
   $items['test-drush'] = array(
-    'callback' => 'drush_test_drush',
     'description' => 'Run drush-specific tests',
     'bootstrap' => DRUSH_BOOTSTRAP_DRUSH,
   );
@@ -53,14 +50,14 @@ function simpletest_drush_command() {
 }
 
 // A drush command callback.
-function drush_test_clean() {
+function drush_simpletest_test_clean() {
   simpletest_clean_environment();
   drush_print("Simpletest environment successfully cleaned.");
 }
 
 
 // A Drush command callback.
-function drush_test_mail($recipients) {
+function drush_simpletest_test_mail($recipients) {
   $run_tests = './scripts/run-tests.sh';
   if (!file_exists($run_tests)) {
     return drush_set_error('DRUSH_SIMPLETEST_RUNTESTS_SH', dt('You must copy or symlink run-tests.sh into your /scripts directory beneath Drupal root.'));
@@ -101,7 +98,7 @@ function drush_simpletest_format_results
  *
  * http://drupal.org/node/483940
  */
-function drush_test_drush() {
+function drush_simpletest_test_drush() {
   drush_log(dt("Invoking %drush help in a subprocess", array('%drush' => DRUSH_COMMAND)));
   drush_backend_invoke('help', array(), 'GET', FALSE);
-}
\ No newline at end of file
+}
Index: includes/command.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/command.inc,v
retrieving revision 1.57
diff -u -p -r1.57 command.inc
--- includes/command.inc	19 Jan 2010 03:36:08 -0000	1.57
+++ includes/command.inc	20 Jan 2010 06:46:30 -0000
@@ -91,6 +91,7 @@ function drush_get_commands() {
         // Add some defaults and normalize the command descriptor
         $command += array(
           'command' => $key,
+          'command-hook' => $key,
           'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_LOGIN,
           'commandfile' => $commandfile,
           'path' => dirname($path),
@@ -109,6 +110,19 @@ function drush_get_commands() {
           'drush dependencies' => array(),
           'bootstrap_errors' => array(),
         );
+        // If command callback is correctly named, then fix
+        // up the command entry so that drush_invoke will be
+        // called.
+        if ($command['callback'] != 'drush_command') {
+          $required_command_prefix = 'drush_' . $commandfile . '_';
+          if ((substr($command['callback'], 0, strlen($required_command_prefix)) == $required_command_prefix)) {
+            $command['command-hook'] = substr($command['callback'], strlen($required_command_prefix));
+            $command['callback'] = 'drush_command';
+          }
+          else {
+            $command['callback-required-prefix'] = $required_command_prefix;
+          }
+        }
         // Enforce the no-spaces in command names rule
         if ((!drush_get_option('allow-spaces-in-commands', FALSE)) && (strpos($key, ' ') !== FALSE)) {
           $command['must-replace-spaces'] = TRUE;
@@ -163,7 +177,12 @@ function drush_get_commands() {
  *
  * drush_parse_command returns a normalized command descriptor, which
  * is an associative array with the following entries:
- * - callback: name of function to invoke for this command.
+ * - callback: name of function to invoke for this command.  The callback
+ *     function name _must_ begin with "drush_commandfile_", where commandfile
+ *     is from the file "commandfile.drush.inc", which contains the
+ *     commandfile_drush_command() function that returned this command.
+ *     Note that the callback entry is optional; it is preferable to
+ *     omit it, in which case drush_invoke() will generate the hook function name.
  * - callback arguments: an array of arguments to pass to the calback.
  * - description: description of the command.
  * - arguments: an array of arguments that are understood by the command. for help texts.
@@ -288,7 +307,12 @@ function drush_invoke($command) {
       }
     }
   }
-  drush_log(dt("Available drush_invoke() hooks for !command: !available", array('!command' => $command, '!available' => "\n" . implode("\n", $all_available_hooks))), 'debug');
+  // If no hook functions were found, print a warning.
+  if (empty($functions)) {
+    drush_log(dt("No hook functions were found for !command.", array('!command' => $command)), 'warning');
+  }
+  // In debug mode, we will also print all available function names.
+  drush_log(dt("Available drush_invoke() hooks for !command: !available", array('!command' => $command, '!available' => "\n" . implode("\n", $all_available_hooks))), empty($functions) ? 'warning' : 'debug');
   $rollback = FALSE;
   $completed = array();
   $available_rollbacks = array();
@@ -346,7 +370,7 @@ function drush_command() {
   }
 
   if (!drush_get_error()) {
-    call_user_func_array('drush_invoke', array_merge(array($command['command']), $args));
+    call_user_func_array('drush_invoke', array_merge(array($command['command-hook']), $args));
   }
 
   if (!drush_get_error()) {
Index: includes/drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/drush.inc,v
retrieving revision 1.77
diff -u -p -r1.77 drush.inc
--- includes/drush.inc	15 Jan 2010 00:44:59 -0000	1.77
+++ includes/drush.inc	20 Jan 2010 06:46:31 -0000
@@ -40,7 +40,14 @@ function drush_dispatch($command = NULL)
         return FALSE;
       }
     }
+    // Print a warning if a command callback function is misnamed
+    if (isset($command['callback-required-prefix'])) {
+      drush_log(dt('Warning: The command callback function !callback has a deprecated name.  It must begin with !requiredprefix.  Skipping hook functions.', array('!callback' => $command['callback'], '!requiredprefix' => $command['callback-required-prefix'])));
+    }
     // Call the callback function of the active command.
+    // TODO:  If we make the required prefix actually required rather than just emitting a
+    // warning, then this could become a direct call to drush_command (all commands with
+    // the required prefix will now go through drush_command + drush_invoke).
     $return = call_user_func_array($command['callback'], $command['arguments']);
   }
 
