? drush.decoupled.v3.DRUPAL-6--1.patch
Index: README.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/README.txt,v
retrieving revision 1.15
diff -u -5 -p -u -p -r1.15 README.txt
--- README.txt	26 Mar 2008 03:03:56 -0000	1.15
+++ README.txt	20 Nov 2008 02:55:10 -0000
@@ -14,30 +14,28 @@ for those. There are several modules tha
 this download. See Package Manager, SQL Tools, and Toolbox.
 
 INSTALLATION
 ------------
 For Linux/Unix/Mac:
-  1. Untar the tarball into your module directory (sites/all/modules)
-  2. Enable drush.module and any submodules you want to use. You must enable the CVS or wget modules
-     if you want to install modules (you do).
-  3. (optional, but recommended:) To ease the use of drush,
+  1. Untar the tarball into a convenient folder (/path/to/drush)
+  2. (optional, but recommended:) To ease the use of drush,
      - create a link to drush.php in a directory that is in your $PATH, e.g.:
-       $ ln /path/to/drush.php /usr/bin/drush
+       $ ln /path/to/drush/drush.php /usr/bin/drush
      OR
      - create an alias to drush.php:
-       $ alias drush='php modules/drush/drush.php'
+       $ alias drush='php /path/to/drush/drush.php'
        (this goes into .profile or .bash_aliases in your home folder)
 
-  4. Start using drush by running "drush" from your Drupal root directory.
+  3. Start using drush by running "drush" from your Drupal root directory.
 
-     (or, if you did not follow step 3, by running "./sites/all/modules/drush.php"
-      or navigating to sites/all/modules/drush and running "./drush.php" )
+     (or, if you did not follow step 3, by running "/path/to/drush/drush.php"
+      or navigating to /path/to/drush and running "./drush.php" )
       
     If you have troubles, try using the -l and -r flags when invoking drush.php. See below.
 
 For Windows (experimental!):
-  - Follow steps 1 and 2. Use drush by navigating to sites/all/modules/drush
+  - Follow step 1. Use drush by navigating to /path/to/drush
     and running 'drush.bat'.
   - Whenever the documentation or the help text refers to
    'drush [option] <command>' or something similar, 'drush' has to be replaced
     by 'drush.bat'.
   - If drush.bat is not working for you, either add the directory in which your
@@ -52,22 +50,23 @@ any Drupal directory:
 
 Use the 'help' command to get a list of available options and commands:
 
   $ drush help
 
-Please note that drush requires a working drupal setup in order to function
-correctly. So for multisite installations, you might need to use the -l or other command line 
-options just to get the help command to work:
+For multisite installations, you might need to use the -l or other command line 
+options just to get drush to work:
 
   $ drush -l http://association.drupal.org/drupal help
 
 Related Options:
   -r <path>, --root=<path>      Drupal root directory to use (default: current directory)            
   -l <uri> , --uri=<uri>        URI of the drupal site to use (only needed in multisite environments)
   -v, --verbose                 Display all available output
   
-If you get tired of typing options all the time, you can add them to your drush.php alias or create a drushrc.php file. These provide additional options for your drush call. They provide great flexibility for a multi-site installation, for example. See example.drushrc.php.                                         
+If you get tired of typing options all the time, you can add them to your drush.php alias or
+create a drushrc.php file. These provide additional options for your drush call. They provide 
+great flexibility for a multi-site installation, for example. See example.drushrc.php.
 
 REQUIREMENTS
 ------------
 This version of drush is designed for Drupal 6.x running on a Unix/Linux
 platform.
Index: drush.drush.inc
===================================================================
RCS file: drush.drush.inc
diff -N drush.drush.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ drush.drush.inc	20 Nov 2008 02:55:10 -0000
@@ -0,0 +1,95 @@
+<?php
+// $Id$
+/**
+ * @file Drush commands
+ *
+ * Defines the drush help command.
+
+
+/**
+ * Implementation of hook_drush_command().
+ */
+function drush_drush_command() {
+  $items['help'] = array(
+    'callback' => 'drush_callback_help',
+    'description' => 'View help. Run "drush help [command]" to view command-specific help.'
+  );
+  return $items;
+}
+
+/**
+ * Get the available options for Drush.
+ *
+ * @return
+ *    An associative array containing the option definition as the key, and the description as the value,
+ *    for each of the available options.
+ */
+function drush_get_options() {
+  // TODO: Add a hook for this, to allow other modules to add their options
+  $options['-r <path>, --root=<path>'] = t("Drupal root directory to use (default: current directory)");
+  $options['-l <uri> , --uri=<uri>']   = t('URI of the drupal site to use (only needed in multisite environments)');
+  $options['-v, --verbose']            = t('Display all available output');
+  $options['-y, --yes']                = t("Assume 'yes' as answer to all prompts");
+  $options['-s, --simulate']           = t("Simulate all relevant actions (don't actually change the system)");
+  $options['-i, --include']           = t("A list of paths to search for drush commands");
+  $options['-c, --config']             = t("Specify a config file to use. See example.drushrc.php");
+  return $options;
+}
+
+/**
+ * Command callback. Display help.
+ */
+function drush_callback_help() {
+  $commands = func_get_args();
+
+  // Display general help text if no command is specified.
+  if (empty($commands)) {
+    drush_print(t('Usage: drush.php [options] <command> <command> ...'));
+    drush_print();
+    drush_print(t('Options: '));
+    foreach (drush_get_options() as $option => $description) {
+      $rows[] = array($option, $description);
+    }
+
+    drush_print_table($rows, 2);
+    drush_print();
+    drush_print('Commands: ');
+
+    $commands = drush_get_commands();
+    $rows = array();
+    foreach($commands as $key => $command) {
+      $rows[] = array($key, $commands[$key]['description']);
+    }
+    drush_print_table($rows, 2);
+  }
+  // Print command specific help.
+  else {
+    $commandstring = implode(" ", $commands);
+
+    if (!drush_is_command($commandstring)) {
+      return drush_error(t('Invalid command !command.', array('!command' => implode(" ", $commands))));
+    }
+
+    $help = module_invoke_all('help', 'drush:'. $commandstring);
+    if (!empty($help)) {
+      drush_print(implode("\n", $help));
+    }
+    else {
+      drush_print(t("No help available for command 'drush $commandstring'."));
+    }
+  }
+}
+
+/**
+ * This is called if no command or an unknown command is entered.
+ */
+function drush_usage() {
+  $commands = func_get_args();
+
+  if (drush_get_option('help') || empty($commands)) {
+    return drush_callback_help();
+  }
+
+  return drush_error(t('Invalid command !command.', array('!command' => implode(" ", $commands))));
+
+}
Index: drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush.inc,v
retrieving revision 1.16
diff -u -5 -p -u -p -r1.16 drush.inc
--- drush.inc	19 May 2008 01:31:57 -0000	1.16
+++ drush.inc	20 Nov 2008 02:55:10 -0000
@@ -4,10 +4,13 @@
 /**
  * @file
  * The drush API implementation and helpers.
  */
 
+// Load the drush module engine.
+require_once(dirname(__FILE__) . '/module.inc');
+
 /**
  * Dispatch a given set of commands.
  * Modules can add commands by implementing hook_drush_command().
  */
 function drush_dispatch($commands) {
@@ -48,11 +51,11 @@ function drush_get_commands($refresh = F
 
   if (!$refresh && !empty($commands)) {
     return $commands;
   }
 
-  $commands = module_invoke_all('drush_command', TRUE);
+  $commands = drush_module_invoke_all('drush_command', TRUE);
 
   return $commands;
 }
 
 function drush_is_command($command) {
Index: drush.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush.module,v
retrieving revision 1.7
diff -u -5 -p -u -p -r1.7 drush.module
--- drush.module	1 Feb 2008 21:56:08 -0000	1.7
+++ drush.module	20 Nov 2008 02:55:10 -0000
@@ -4,10 +4,11 @@
 /**
  * @file
  * drush (the drupal shell) provides a command line interface for Drupal.
  */
 
+include_once('drush.drush.inc');
 
 /**
  * Implementation of hook_help()
  */
 function drush_help($section) {
@@ -47,91 +48,5 @@ function drush_help($section) {
     
   }
 }
 
 
-/**
- * Implementation of hook_drush_command().
- */
-function drush_drush_command() {
-  $items['help'] = array(
-    'callback' => 'drush_callback_help',
-    'description' => 'View help. Run "drush help [command]" to view command-specific help.'
-  );
-  return $items;
-}
-
-/**
- * Get the available options for Drush.
- *
- * @return
- *    An associative array containing the option definition as the key, and the description as the value,
- *    for each of the available options.
- */
-function drush_get_options() {
-  // TODO: Add a hook for this, to allow other modules to add their options
-  $options['-r <path>, --root=<path>'] = t("Drupal root directory to use (default: current directory)");
-  $options['-l <uri> , --uri=<uri>']   = t('URI of the drupal site to use (only needed in multisite environments)');
-  $options['-v, --verbose']            = t('Display all available output');
-  $options['-y, --yes']                = t("Assume 'yes' as answer to all prompts");
-  $options['-s, --simulate']           = t("Simulate all relevant actions (don't actually change the system)");
-  $options['-c, --config']             = t("Specify a config file to use. See example.drushrc.php");
-  return $options;
-}
-
-/**
- * Command callback. Display help.
- */
-function drush_callback_help() {
-  $commands = func_get_args();
-
-  // Display general help text if no command is specified.
-  if (empty($commands)) {
-    drush_print(t('Usage: drush.php [options] <command> <command> ...'));
-    drush_print();
-    drush_print(t('Options: '));
-    foreach (drush_get_options() as $option => $description) {
-      $rows[] = array($option, $description);
-    }
-
-    drush_print_table($rows, 2);
-    drush_print();
-    drush_print('Commands: ');
-
-    $commands = drush_get_commands();
-    $rows = array();
-    foreach($commands as $key => $command) {
-      $rows[] = array($key, $commands[$key]['description']);
-    }
-    drush_print_table($rows, 2);
-  }
-  // Print command specific help.
-  else {
-    $commandstring = implode(" ", $commands);
-
-    if (!drush_is_command($commandstring)) {
-      return drush_error(t('Invalid command !command.', array('!command' => implode(" ", $commands))));
-    }
-
-    $help = module_invoke_all('help', 'drush:'. $commandstring);
-    if (!empty($help)) {
-      drush_print(implode("\n", $help));
-    }
-    else {
-      drush_print(t("No help available for command 'drush $commandstring'."));
-    }
-  }
-}
-
-/**
- * This is called if no command or an unknown command is entered.
- */
-function drush_usage() {
-  $commands = func_get_args();
-
-  if (drush_get_option('help') || empty($commands)) {
-    return drush_callback_help();
-  }
-
-  return drush_error(t('Invalid command !command.', array('!command' => implode(" ", $commands))));
-
-}
\ No newline at end of file
Index: drush.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush.php,v
retrieving revision 1.24.2.3
diff -u -5 -p -u -p -r1.24.2.3 drush.php
--- drush.php	18 Nov 2008 01:07:49 -0000	1.24.2.3
+++ drush.php	20 Nov 2008 02:55:10 -0000
@@ -241,20 +241,11 @@ function _drush_bootstrap_drupal() {
   }
 
   // The bootstrap can fail silently, so we catch that in a shutdown function.
   register_shutdown_function('drush_shutdown');
   drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-  if (module_exists('drush')) {
-    require_once drupal_get_path('module', 'drush') . '/drush.inc';
-  }
-  else {
-    $message = "E: You must enable the Drush module for the site you want to use.\n";
-    $message .= "Hint: Drush was looking in the site '$conf_path'. You can select another site\n";
-    $message .= "with Drush enabled by specifying the Drupal URI to use with the --uri\n";
-    $message .= "parameter on the command line or \$options['uri'] in your drushrc.php file.\n";
-    die($message);
-  }
+  require_once dirname(__FILE__) . '/drush.inc';
 }
 
 function drush_shutdown() {
   if (!function_exists('drupal_set_content')) {
     $message = "E: Drush was not able to start (bootstrap) Drupal.\n";
Index: example.drushrc.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/example.drushrc.php,v
retrieving revision 1.5.2.1
diff -u -5 -p -u -p -r1.5.2.1 example.drushrc.php
--- example.drushrc.php	14 Nov 2008 22:08:56 -0000	1.5.2.1
+++ example.drushrc.php	20 Nov 2008 02:55:10 -0000
@@ -16,10 +16,13 @@
 // $options['l'] = 'http://example.com/subir';
 
 // specify your Drupal core base directory (useful if you use symlinks)
 // $options['r'] = '/home/USER/workspace/drupal-6';
 
+// specify additional directories to search for *.drush.inc files
+// $options['i'] = 'sites/default:profiles/myprofile'; 
+
 // enable verbose mode
 // $options['v'] = 1; 
 
 /*
  * Customize this associative array with your own tables. This is the 
Index: module.inc
===================================================================
RCS file: module.inc
diff -N module.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ module.inc	20 Nov 2008 02:55:10 -0000
@@ -0,0 +1,180 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * The drush module engine.
+ *
+ * Closely follows the equivalent Drupal core functions.
+ *
+ */
+
+/**
+ * Invoke a hook in all available modules that implement it.
+ *
+ * @param $hook
+ *   The name of the hook to invoke.
+ * @param ...
+ *   Arguments to pass to the hook.
+ * @return
+ *   An array of return values of the hook implementations. If modules return
+ *   arrays from their implementations, those are merged into one array.
+ */
+function drush_module_invoke_all() {
+  $args = func_get_args();
+  $hook = $args[0];
+  unset($args[0]);
+  $return = array();
+  foreach (drush_module_implements($hook) as $module) {
+    $function = $module .'_'. $hook;
+    $result = call_user_func_array($function, $args);
+    if (isset($result) && is_array($result)) {
+      $return = array_merge_recursive($return, $result);
+    }
+    else if (isset($result)) {
+      $return[] = $result;
+    }
+  }
+  return $return;
+}
+
+/**
+ * Determine which modules are implementing a hook.
+ *
+ * @param $hook
+ *   The name of the hook (e.g. "help" or "menu").
+ *
+ * @return
+ *   An array with the names of the modules which are implementing this hook.
+ */
+function drush_module_implements($hook) {
+  static $implementations;
+
+  if (!isset($implementations[$hook])) {
+    $implementations[$hook] = array();
+    $list = drush_module_list();
+    foreach ($list as $module) {
+      if (drush_module_hook($module, $hook)) {
+        $implementations[$hook][] = $module;
+      }
+    }
+
+    // If Drupal has been bootstrapped, we scan enabled modules
+    // for drush commands as well.
+    if (function_exists('module_list') && function_exists('module_hook')) {
+      $list = module_list();
+      foreach ($list as $module) {
+        if (module_hook($module, $hook)) {
+          $implementations[$hook][] = $module;
+        }
+      }
+    }
+    
+  }
+  return (array)$implementations[$hook];
+}
+
+/**
+ * Collect a list of all available modules.
+ *
+ * @return
+ *   An associative array whose keys and values are the names of all available
+ *   modules.
+ */
+function drush_module_list() {
+  static $list = array();
+  if (empty($list)) {
+    $dirs[] = dirname(__FILE__);
+    if ($include = drush_get_option(array('i', 'include'), FALSE)) {
+      $dirs = array_merge($dirs, explode(":", $include));
+    }
+    foreach ($dirs as $dir) {
+      $files = drush_scan_directory($dir, '\.drush\.inc$');
+      foreach ($files as $filename => $info) {
+        require_once($filename);
+        $list[] = basename($filename, '.drush.inc');
+      }
+    }
+  }
+  return $list;
+}
+
+/**
+ * Determine whether a module implements a hook.
+ *
+ * @param $module
+ *   The name of the module (without the .module extension).
+ * @param $hook
+ *   The name of the hook (e.g. "help" or "menu").
+ * @return
+ *   TRUE if the the hook is implemented.
+ */
+function drush_module_hook($module, $hook) {
+  return function_exists($module .'_'. $hook);
+}
+
+
+/**
+ * Finds all files that match a given mask in a given directory.
+ * Directories and files beginning with a period are excluded; this
+ * prevents hidden files and directories (such as SVN working directories)
+ * from being scanned.
+ *
+ * @param $dir
+ *   The base directory for the scan, without trailing slash.
+ * @param $mask
+ *   The regular expression of the files to find.
+ * @param $nomask
+ *   An array of files/directories to ignore.
+ * @param $callback
+ *   The callback function to call for each match.
+ * @param $recurse
+ *   When TRUE, the directory scan will recurse the entire tree
+ *   starting at the provided directory.
+ * @param $key
+ *   The key to be used for the returned array of files. Possible
+ *   values are "filename", for the path starting with $dir,
+ *   "basename", for the basename of the file, and "name" for the name
+ *   of the file without an extension.
+ * @param $min_depth
+ *   Minimum depth of directories to return files from.
+ * @param $depth
+ *   Current depth of recursion. This parameter is only used internally and should not be passed.
+ *
+ * @return
+ *   An associative array (keyed on the provided key) of objects with
+ *   "path", "basename", and "name" members corresponding to the
+ *   matching files.
+ */
+function drush_scan_directory($dir, $mask, $nomask = array('.', '..', 'CVS'), $callback = 0, $recurse = TRUE, $key = 'filename', $min_depth = 0, $depth = 0) {
+  $key = (in_array($key, array('filename', 'basename', 'name')) ? $key : 'filename');
+  $files = array();
+
+  if (is_dir($dir) && $handle = opendir($dir)) {
+    while (FALSE !== ($file = readdir($handle))) {
+      if (!in_array($file, $nomask) && $file[0] != '.') {
+        if (is_dir("$dir/$file") && $recurse) {
+          // Give priority to files in this folder by merging them in after any subdirectory files.
+          $files = array_merge(drush_scan_directory("$dir/$file", $mask, $nomask, $callback, $recurse, $key, $min_depth, $depth + 1), $files);
+        }
+        elseif ($depth >= $min_depth && ereg($mask, $file)) {
+          // Always use this match over anything already set in $files with the same $$key.
+          $filename = "$dir/$file";
+          $basename = basename($file);
+          $name = substr($basename, 0, strrpos($basename, '.'));
+          $files[$$key] = new stdClass();
+          $files[$$key]->filename = $filename;
+          $files[$$key]->basename = $basename;
+          $files[$$key]->name = $name;
+          if ($callback) {
+            $callback($filename);
+          }
+        }
+      }
+    }
+
+    closedir($handle);
+  }
+
+  return $files;
+}
Index: drush_pm/drush_pm.drush.inc
===================================================================
RCS file: drush_pm/drush_pm.drush.inc
diff -N drush_pm/drush_pm.drush.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ drush_pm/drush_pm.drush.inc	20 Nov 2008 02:55:10 -0000
@@ -0,0 +1,547 @@
+<?php
+// $Id$
+/**
+ * @file Drush pm commands
+ */
+
+/**
+ * Project is a user requested version update.
+ */
+define('DRUSH_PM_REQUESTED_UPDATE', 101);
+
+/**
+ * User requested version already installed.
+ */
+define('DRUSH_PM_REQUESTED_CURRENT', 102);
+
+/**
+ * Implementation of hook_drush_command().
+ */
+function drush_pm_drush_command() {
+  $items['pm install'] = array(
+    'callback' => 'drush_pm_install',
+    'description' => 'Install one or more modules'
+  );
+  $items['pm refresh'] = array(
+    'callback' => 'drush_pm_refresh',
+    'description' => 'Refresh update status information'
+  );
+  $items['pm update'] = array(
+    'callback' => 'drush_pm_update',
+    'description' => 'Update your modules'
+  );
+  $items['pm info'] = array(
+    'callback' => 'drush_pm_info',
+    'description' => 'Release information for a module'
+  );
+  return $items;
+}
+
+
+/**
+ * Parse out the project name and version and return as a structured array
+ *
+ * @param $requests an array of project names
+ */
+function drush_pm_parse_project_version($requests) {
+  $requestdata = array();
+  foreach($requests as $request) {
+    // project-HEAD or project-5.x-1.0-beta
+    // '5.x-' is optional, as is '-beta'
+    preg_match('/-(HEAD|(\d+)\.([\dx]+)(-.+)?)$/', $request, $matches);
+    if ($matches[0]) {
+      // Specific version requested
+      $version = $matches[0];
+      $project = substr($request, 0, strlen($request) - strlen($version));
+    }
+    else {
+      // Recommended stable version requested
+      $project = $request;
+    }
+    if (empty($project)) {
+      drush_die(t("Project name not found.\n\nRun drush help pm install for more information."));
+    }
+    $requestdata[$project] = array(
+      'name' => $project,
+      'version' => trim($version, ' -'),
+    );
+  }
+  return $requestdata;
+}
+
+/**
+ * Command callback. Installs one or more packages (so far only modules).
+ */
+function drush_pm_install() {
+  $requests = func_get_args();
+  if (empty($requests)) {
+    drush_die(t("No project specified.\n\nRun drush help pm install for more information."));
+  }
+  
+  // Parse out project name and version
+  $requests = drush_pm_parse_project_version($requests);
+  
+  // If a URI is provided then we install to that specific site, otherwise we install to sites/all/modules
+  if (DRUSH_URI) {
+    $path = conf_path();
+    $modulepath = DRUSH_DRUPAL_ROOT .'/'. $path .'/modules/';
+  }
+  
+  if (!isset($modulepath) || !file_exists($modulepath)) {
+    $modulepath = DRUSH_DRUPAL_ROOT .'/sites/all/modules/';
+  }
+
+  // Get the module info from drupal.org via xml-rpc
+  $releases = drush_pm_get_project_info($requests);
+  if (!$releases) {
+    drush_die(t("None of the given projects exists or has releases that are compatible with your Drupal version."));
+  }
+  
+  $startdir = getcwd();
+
+  $package_handler = drush_pm_get_package_handler() .'_install_project';
+  if (!function_exists($package_handler)) {
+  	drush_die(t("The $package_handler package handler does not handle installs."));
+  }
+
+  // Download and install each module
+  foreach($requests as $project => $request) {
+    if (isset($releases[$project]) && $release = drush_pm_get_release($request, $releases[$project])) {
+      if (is_dir($modulepath . $project)) {
+        drush_error(t('Project !project is already installed. Skipping.', array('!project' => $project)));
+      }
+      elseif ($package_handler($project, $release, $modulepath)) {
+        drush_print(t("Project !project successfully installed (version !version).",
+          array('!project' => $project, '!version' => $release['version'])));
+        module_invoke_all('drush_pm_post_install', $project, $release, $modulepath);
+      }
+    }
+    else {
+      drush_error(t('Project !project doesn\' exist or has no releases that are compatible with your Drupal version. Skipping.', array('!project' => $project)));
+    }
+  }
+
+  drush_op('chdir', $startdir);
+}
+
+/**
+ * Command callback. Displays update status info and allows to update installed modules.
+ * Pass specific projects as arguments, otherwise we update all that have candidate releases.
+ *
+ * This command prompts for confirmation before updating, so it is safe to run just to check on 
+ * In this case, say at the confirmation prompt.
+ */
+function drush_pm_update() {  
+  // Get update status information.
+  $releases = _drush_pm_get_update_info();
+
+  // Get specific requests
+  $requests = func_get_args();
+  
+  // Parse out project name and version
+  $requests = drush_pm_parse_project_version($requests);
+
+  // Preprocess releases
+  if (!empty($requests)) {
+    // Force update projects where a specific version is reqested
+    foreach ($requests as $project => $request) {
+      if (!empty($request['version'])) {
+        // Match the requested release
+        $release = drush_pm_get_release($request, $releases[$project]);
+        if ($release['version'] == $releases[$project]['existing_version']) {
+          $releases[$project]['status'] = DRUSH_PM_REQUESTED_CURRENT;          
+        }
+        else {
+          $releases[$project]['status'] = DRUSH_PM_REQUESTED_UPDATE;
+        }
+        // Set the candidate version to the requested release
+        $releases[$project]['candidate_version'] = $release['version'];
+      }
+    }
+  }
+
+  // Table headers.
+  $rows[] = array(t('Name'), t('Installed version'), t('Recommended version'), t('Status'));
+
+  // Process releases, notifying user of status and building a list of proposed updates
+  $updateable = array();
+  foreach ($releases as $release) {
+    if (!$release['title']) {
+      continue;
+    }
+
+    switch($release['status']) {
+      case UPDATE_CURRENT:
+        $status = t('Up to date');
+        $release['candidate_version'] = $release['recommended'];
+        break;
+      case UPDATE_NOT_CURRENT:
+        $status = t('Update available');
+        $release['candidate_version'] = $release['recommended'];
+        $updateable[$release['name']] = $release;
+        break;
+      case UPDATE_NOT_SECURE:
+        $status = t('SECURITY UPDATE available');
+        $release['candidate_version'] = $release['recommended'];
+        $updateable[$release['name']] = $release;
+        break;
+      case UPDATE_REVOKED:
+        $status = t('Intalled version REVOKED');
+        $release['candidate_version'] = $release['recommended'];
+        $updateable[$project['name']] = $release;
+        break;
+      case DRUSH_PM_REQUESTED_UPDATE:
+        $status = t('Specified version available');
+        $updateable[$release['name']] = $release;
+        break;
+      case DRUSH_PM_REQUESTED_CURRENT:
+        $status = t('Specified version already installed');
+        break;
+      case UPDATE_NOT_SUPPORTED:
+        $status = t('Installed version not supported');
+        $release['candidate_version'] = $release['recommended'];
+        $updateable[$project['name']] = $release;
+        break;
+      case UPDATE_NOT_CHECKED:
+        $status = t('Unable to check status');
+        break;
+      case UPDATE_UNKNOWN:
+      default:
+        $status = t('Unknown');
+        break;
+    }
+
+    $rows[] = array($release['title'], $release['existing_version'], $release['candidate_version'], $status);
+  }
+
+  $last = variable_get('update_last_check', 0);
+  drush_print(t('Update information last refreshed: ') . ($last  ? format_date($last) : t('Never')));
+  drush_print();
+  drush_print(t("Update status information on all installed and enabled Drupal modules:"));
+  drush_print_table($rows, 2, TRUE);
+  drush_print();
+
+  // If specific project updates were requested then remove releases for all others
+  if (!empty($requests)) {
+    foreach ($updateable as $project => $release) {
+      if (!isset($requests[$project])) {
+        unset($updateable[$project]);
+      }
+    }
+  }
+
+  if (empty($updateable)) {
+    drush_die(t('No updates available.'));
+  }
+
+  // Offer to update to the identified releases
+  drush_pm_update_packages($updateable);
+}
+
+/**
+ * Update packages according to an array of releases, following interactive
+ * confirmation from the user.
+ * 
+ * @param $releases
+ *   An array of releases from the drupal.org update service, with an additional
+ *   array key candidate_version that specifies the version to be installed.
+ */
+function drush_pm_update_packages($releases) {
+  if (isset($releases['drupal'])) {
+    drush_print("NOTE: An update for the Drupal core is available. \nDrupal itself can't yet be updated by this tool. Please update Drupal manually.\n");
+    unset($releases['drupal']);
+  }
+
+  drush_print(t('Updates will be made to the following projects:'));
+  foreach($releases as $release) {
+    $print .= $release['title'] . " [" . $release['name'] . '-' . $release['candidate_version'] . "], ";
+  }
+  drush_print(substr($print, 0, strlen($print)-2));
+  drush_print();
+  drush_print(t("Note: Updated modules can potentially break your site. It's not recommended to update production sites without prior testing."));
+  if (module_exists('drush_pm_svn')) {
+    drush_print(t("Note: A backup of your package will be stored to backups directory if no .svn directory is found."));
+  }
+  drush_print(t('Note: If you have made any modifications to any file that belongs to one of these projects, you will have to migrate those modifications after updating.'));
+  if(!drush_confirm(t('Do you really want to continue?'))) {
+    drush_die('Aborting.');
+  }
+
+  $package_handler = drush_pm_get_package_handler() .'_update_project';
+  if (!function_exists($package_handler)) {
+    drush_die(t("The $package_handler package handler does not handle updates."));
+  }
+  
+  // Save the date to be used in the backup directory's path name.
+  $date = date('YmdHis');
+  
+  // Now we start the actual updating.
+  foreach($releases as $release) {
+    drush_verbose(t('Starting to update !project ...', array('!project' => $release['title'])));
+    
+    $source = DRUSH_DRUPAL_ROOT .'/' . $release['path'];
+    
+    $skip_backup = module_invoke_all('drush_pm_skip_backup', $source);
+    if (!count($skip_backup)) {
+      $backup_dir = DRUSH_DRUPAL_ROOT. '/backup';
+      drush_op('mkdir', $backup_dir, 0777);
+      $backup_dir .= '/modules';
+      drush_op('mkdir', $backup_dir, 0777);
+      $backup_dir .= "/$date";
+      drush_op('mkdir', $backup_dir, 0777);
+      $backup_target = $backup_dir . '/'. $release['name'];
+      if (!drush_op('rename', $source, $backup_target)) {
+        drush_die(t('Failed to backup project directory !source to !backup_target', array('!source' => $source, '!backup_target' => $backup_target)));
+      }
+    }
+  
+    // Install the new version.
+    // $basepath is the dir where the current module is installed. It's one dir up from the
+    // place of the project's info files.
+    $basepath = explode('/', $release['path']);
+    // move a directory up, so we can copy updated dir to parent
+    array_pop($basepath);
+    $project_parent_path = DRUSH_DRUPAL_ROOT. '/'. implode('/', $basepath). '/';
+    if (!$package_handler($release['name'], $release['releases'][$release['candidate_version']], $project_parent_path)) {
+      if (!count($skip_backup)) {
+        drush_error(t('Updating project !project failed. Restoring previously installed version.', array('!project' => $release['name'])));
+        drush_op('rename', $backup_target, $source);
+      }
+      else {
+        drush_error(t('Updating project !project failed. Please revert to the previously installed version.', array('!project' => $release['name'])));
+      }
+    }
+    else {
+      drush_print(t('Project !project was updated successfully. Installed version is now !version.', array('!project' => $release['name'], '!version' => $release['candidate_version'])));
+      module_invoke_all('drush_pm_post_update', $release['name'], $release['releases'][$release['candidate_version']], $project_parent_path);
+    }
+  }
+  if ($backup_dir) {
+    drush_print(t("Backups were saved into the directory !backup_dir.", array('!backup_dir' => $backup_dir))); 
+  }
+  drush_print(t("You should now run update.php through your browser."));
+}
+
+/**
+ * Find a module handler
+ */
+function drush_pm_get_package_handler() {
+  $package_handlers = module_invoke_all('drush_pm_package_handler');
+  
+  if (empty($package_handlers)) {
+    drush_die(t("No package handlers found."));
+  }
+
+  $handler = drush_get_option('handler');
+  // See if we have the full handler provided
+  if (array_search($handler, $package_handlers)) {
+    return $handler;
+  }
+  // Allow a shortcut for any functions named drush_pm_*
+  if (array_search('drush_pm_'. $handler, $package_handlers)) {
+    return 'drush_pm_'. $handler;
+  }
+
+  // Fallback on the first provided handler (from the lightest module)
+  return $package_handlers[0];
+}
+
+/**
+ * Get update information for all installed projects.
+ *
+ * @return An array containing remote and local versions for all installed projects
+ */
+function _drush_pm_get_update_info($projects = NULL) {
+  $info = update_get_available();
+  $data = update_calculate_project_data($info);
+  $data = drush_pm_get_project_path($data);
+  return $data;
+}
+
+/**
+ * Command callback. Refresh update status information.
+ */
+function drush_pm_refresh() {
+  drush_print(t("Refreshing update status information ..."));
+  update_refresh();
+  drush_print(t("Done."));
+}
+
+/**
+ * Get project information from drupal.org.
+ *
+ * @param $projects An array of project names
+ */
+function drush_pm_get_project_info($projects) {
+  $info = array();
+  $data = array();
+  foreach ($projects as $project_name => $project) {
+    $url = UPDATE_DEFAULT_URL. "/$project_name/". DRUPAL_CORE_COMPATIBILITY;
+    $xml = drupal_http_request($url);
+    $data[] = $xml->data;
+  }
+  if ($data) {
+    include_once drupal_get_path('module', 'update') .'/update.fetch.inc';
+    $parser = new update_xml_parser;
+    $info = $parser->parse($data);
+  }
+  return $info;
+}
+
+/**
+ * Get the recommended release for a certain so far uninstalled project.
+ *
+ * @param $project A project information array for the requested project 
+ * @param $info A project information array for this project, as returned by an update service from drush_pm_get_project_info()
+ */
+function drush_pm_get_release($project, $info) {
+  $minor = '';
+  $version_patch_changed = '';
+
+  if ($project['version']) {
+    // The user specified a specific version - try to find that exact version
+    foreach($info['releases'] as $version => $release) {
+       // Ignore unpublished releases.
+      if ($release['status'] != 'published') {
+        continue;
+      }
+      
+      // Straight match
+      if (!isset($recommended_version) && $release['version'] == $project['version']) {
+        $recommended_version = $version;
+      }
+      // Shortcut match with ommitted Drupal version
+      if (!isset($recommended_version) && $release['version'] == DRUPAL_CORE_COMPATIBILITY .'-'. $project['version']) {
+        $recommended_version = $version;
+      }
+    }
+  }
+  else {
+    // No version specified - try to find the best version we can
+    foreach($info['releases'] as $version => $release) {
+       // Ignore unpublished releases.
+      if ($release['status'] != 'published') {
+        continue;
+      }
+  
+      // If we haven't found a recommended version yet, put the dev
+      // version as recommended and hope it gets overwritten later.
+      // Look for the 'latest version' if we haven't found it yet.
+      // Latest version is defined as the most recent version for the
+      // default major version.
+      if (!isset($latest_version) && $release['version_major'] == $info['default_major']) {
+        $latest_version = $version;
+      }
+  
+      if (!isset($recommended_version) && $release['version_major'] == $info['default_major']) {
+        if ($minor != $release['version_patch']) {
+          $minor = $release['version_patch'];
+          $version_patch_changed = $version;
+        }
+        if (empty($release['version_extra']) && $minor == $release['version_patch']) {
+          $recommended_version = $version_patch_changed;
+        }
+        continue;
+      }
+    }
+  }
+
+  if (isset($recommended_version)) {
+    return $info['releases'][$recommended_version];
+  }
+  else if (isset($latest_version)) {
+    return $info['releases'][$latest_version];
+  }
+  else {
+    return false;
+  }
+}
+
+/**
+ * We need to set the project path by looking at the module location. Ideally, update.module would do this for us.
+ */
+function drush_pm_get_project_path($projects) {
+  foreach ($projects as $project => $info) {
+    if (!isset($info['path'])  && $project != 'drupal') {
+      // looks for an enabled module.
+      foreach ($info['includes'] as $module => $name) {
+        if ($path = drupal_get_path('module', $module)) {
+          continue;
+        }
+      }
+      // As some modules are not located in their project's root directory
+      // but in a subdirectory (e.g. all the ecommerce modules), we take the module's
+      // info file's path, and then move up until we are at a directory with the
+      // project's name.
+      $parts = explode('/', $path);
+      $i = count($parts) - 1;
+      $stop = array_search($project, $parts);
+      while ($i > $stop) {
+        unset($parts[$i]);
+        $i--;
+      }
+      $projects[$project]['path'] = implode('/', $parts);
+    }
+  }
+  return $projects;
+}
+
+/**
+ * A drush command callback. Show release info for given project(s).
+ *
+ **/
+function drush_pm_info() {
+  $projects = func_get_args();
+  $projects = drupal_map_assoc($projects);
+  $info = drush_pm_get_project_info($projects);
+
+  $rows[] = array(t('Project'), t('Release'), t('Date'));
+  foreach ($info as $key => $project) {
+    foreach ($project['releases'] as $release) {
+
+      $rows[] = array(
+        $key,
+        $release['version'],
+        format_date($release['date'], 'custom', 'Y-M-d'),
+      );
+    }
+  }
+  return drush_print_table($rows, FALSE, TRUE);
+}
+
+/**
+ * Deletes a directory, all files in it and all subdirectories in it (recursively).
+ * Use with care!
+ * Written by Andreas Kalsch
+ */
+function delete_dir($dir) {
+  if (substr($dir, strlen($dir)-1, 1) != '/')
+    $dir .= '/';
+
+  if ($handle = opendir($dir)) {
+    while ($obj = readdir($handle)) {
+      if ($obj != '.' && $obj != '..') {
+        if (is_dir($dir.$obj)) {
+          if (!delete_dir($dir.$obj)) {
+            return false;
+          }
+        }
+        elseif (is_file($dir.$obj)) {
+          if (!unlink($dir.$obj)) {
+            return false;
+          }
+        }
+      }
+    }
+
+    closedir($handle);
+
+    if (!@rmdir($dir)) {
+      return false;
+    }
+    return true;
+  }
+  return false;
+}
+
+
Index: drush_pm/drush_pm.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush_pm/drush_pm.module,v
retrieving revision 1.25.2.4
diff -u -5 -p -u -p -r1.25.2.4 drush_pm.module
--- drush_pm/drush_pm.module	15 Nov 2008 03:37:32 -0000	1.25.2.4
+++ drush_pm/drush_pm.module	20 Nov 2008 02:55:10 -0000
@@ -11,19 +11,11 @@
  * - Version: a requested version, such as 1.0 or 1.x-dev.
  * - Release: a specific release of a project, with associated metadata (from the drupal.org update service).
  * - Package: the collection of files that make up a release.
  */
 
-/**
- * Project is a user requested version update.
- */
-define('DRUSH_PM_REQUESTED_UPDATE', 101);
-
-/**
- * User requested version already installed.
- */
-define('DRUSH_PM_REQUESTED_CURRENT', 102);
+include_once('drush_pm.drush.inc');
 
 /**
  * Implementation of hook_help().
  */
 function drush_pm_help($section) {
@@ -64,33 +56,10 @@ Use the -y option to answer all question
 View all releases for a given project. Useful for deciding which version to install/update. 
     ");
   }
 }
 
-/**
- * Implementation of hook_drush_command().
- */
-function drush_pm_drush_command() {
-  $items['pm install'] = array(
-    'callback' => 'drush_pm_install',
-    'description' => 'Install one or more modules'
-  );
-  $items['pm refresh'] = array(
-    'callback' => 'drush_pm_refresh',
-    'description' => 'Refresh update status information'
-  );
-  $items['pm update'] = array(
-    'callback' => 'drush_pm_update',
-    'description' => 'Update your modules'
-  );
-  $items['pm info'] = array(
-    'callback' => 'drush_pm_info',
-    'description' => 'Release information for a module'
-  );
-  return $items;
-}
-
 function drush_pm_requirements($phase) {
   switch ($phase) {
     case 'runtime':
     $package_handlers = module_invoke_all('drush_pm_package_handler');
       $requirements['handlers'] = array(
@@ -100,513 +69,6 @@ function drush_pm_requirements($phase) {
       );
       break;
   }
   return is_array($requirements) ? $requirements : array();
 }
-
-/**
- * Parse out the project name and version and return as a structured array
- *
- * @param $requests an array of project names
- */
-function drush_pm_parse_project_version($requests) {
-  $requestdata = array();
-  foreach($requests as $request) {
-    // project-HEAD or project-5.x-1.0-beta
-    // '5.x-' is optional, as is '-beta'
-    preg_match('/-(HEAD|(\d+)\.([\dx]+)(-.+)?)$/', $request, $matches);
-    if ($matches[0]) {
-      // Specific version requested
-      $version = $matches[0];
-      $project = substr($request, 0, strlen($request) - strlen($version));
-    }
-    else {
-      // Recommended stable version requested
-      $project = $request;
-    }
-    if (empty($project)) {
-      drush_die(t("Project name not found.\n\nRun drush help pm install for more information."));
-    }
-    $requestdata[$project] = array(
-      'name' => $project,
-      'version' => trim($version, ' -'),
-    );
-  }
-  return $requestdata;
-}
-
-/**
- * Command callback. Installs one or more packages (so far only modules).
- */
-function drush_pm_install() {
-  $requests = func_get_args();
-  if (empty($requests)) {
-    drush_die(t("No project specified.\n\nRun drush help pm install for more information."));
-  }
-  
-  // Parse out project name and version
-  $requests = drush_pm_parse_project_version($requests);
-  
-  // If a URI is provided then we install to that specific site, otherwise we install to sites/all/modules
-  if (DRUSH_URI) {
-    $path = conf_path();
-    $modulepath = DRUSH_DRUPAL_ROOT .'/'. $path .'/modules/';
-  }
-  
-  if (!isset($modulepath) || !file_exists($modulepath)) {
-    $modulepath = DRUSH_DRUPAL_ROOT .'/sites/all/modules/';
-  }
-
-  // Get the module info from drupal.org via xml-rpc
-  $releases = drush_pm_get_project_info($requests);
-  if (!$releases) {
-    drush_die(t("None of the given projects exists or has releases that are compatible with your Drupal version."));
-  }
-  
-  $startdir = getcwd();
-
-  $package_handler = drush_pm_get_package_handler() .'_install_project';
-  if (!function_exists($package_handler)) {
-  	drush_die(t("The $package_handler package handler does not handle installs."));
-  }
-
-  // Download and install each module
-  foreach($requests as $project => $request) {
-    if (isset($releases[$project]) && $release = drush_pm_get_release($request, $releases[$project])) {
-      if (is_dir($modulepath . $project)) {
-        drush_error(t('Project !project is already installed. Skipping.', array('!project' => $project)));
-      }
-      elseif ($package_handler($project, $release, $modulepath)) {
-        drush_print(t("Project !project successfully installed (version !version).",
-          array('!project' => $project, '!version' => $release['version'])));
-        module_invoke_all('drush_pm_post_install', $project, $release, $modulepath);
-      }
-    }
-    else {
-      drush_error(t('Project !project doesn\' exist or has no releases that are compatible with your Drupal version. Skipping.', array('!project' => $project)));
-    }
-  }
-
-  drush_op('chdir', $startdir);
-}
-
-/**
- * Command callback. Displays update status info and allows to update installed modules.
- * Pass specific projects as arguments, otherwise we update all that have candidate releases.
- *
- * This command prompts for confirmation before updating, so it is safe to run just to check on 
- * In this case, say at the confirmation prompt.
- */
-function drush_pm_update() {  
-  // Get update status information.
-  $releases = _drush_pm_get_update_info();
-
-  // Get specific requests
-  $requests = func_get_args();
-  
-  // Parse out project name and version
-  $requests = drush_pm_parse_project_version($requests);
-
-  // Preprocess releases
-  if (!empty($requests)) {
-    // Force update projects where a specific version is reqested
-    foreach ($requests as $project => $request) {
-      if (!empty($request['version'])) {
-        // Match the requested release
-        $release = drush_pm_get_release($request, $releases[$project]);
-        if ($release['version'] == $releases[$project]['existing_version']) {
-          $releases[$project]['status'] = DRUSH_PM_REQUESTED_CURRENT;          
-        }
-        else {
-          $releases[$project]['status'] = DRUSH_PM_REQUESTED_UPDATE;
-        }
-        // Set the candidate version to the requested release
-        $releases[$project]['candidate_version'] = $release['version'];
-      }
-    }
-  }
-
-  // Table headers.
-  $rows[] = array(t('Name'), t('Installed version'), t('Recommended version'), t('Status'));
-
-  // Process releases, notifying user of status and building a list of proposed updates
-  $updateable = array();
-  foreach ($releases as $release) {
-    if (!$release['title']) {
-      continue;
-    }
-
-    switch($release['status']) {
-      case UPDATE_CURRENT:
-        $status = t('Up to date');
-        $release['candidate_version'] = $release['recommended'];
-        break;
-      case UPDATE_NOT_CURRENT:
-        $status = t('Update available');
-        $release['candidate_version'] = $release['recommended'];
-        $updateable[$release['name']] = $release;
-        break;
-      case UPDATE_NOT_SECURE:
-        $status = t('SECURITY UPDATE available');
-        $release['candidate_version'] = $release['recommended'];
-        $updateable[$release['name']] = $release;
-        break;
-      case UPDATE_REVOKED:
-        $status = t('Intalled version REVOKED');
-        $release['candidate_version'] = $release['recommended'];
-        $updateable[$project['name']] = $release;
-        break;
-      case DRUSH_PM_REQUESTED_UPDATE:
-        $status = t('Specified version available');
-        $updateable[$release['name']] = $release;
-        break;
-      case DRUSH_PM_REQUESTED_CURRENT:
-        $status = t('Specified version already installed');
-        break;
-      case UPDATE_NOT_SUPPORTED:
-        $status = t('Installed version not supported');
-        $release['candidate_version'] = $release['recommended'];
-        $updateable[$project['name']] = $release;
-        break;
-      case UPDATE_NOT_CHECKED:
-        $status = t('Unable to check status');
-        break;
-      case UPDATE_UNKNOWN:
-      default:
-        $status = t('Unknown');
-        break;
-    }
-
-    $rows[] = array($release['title'], $release['existing_version'], $release['candidate_version'], $status);
-  }
-
-  $last = variable_get('update_last_check', 0);
-  drush_print(t('Update information last refreshed: ') . ($last  ? format_date($last) : t('Never')));
-  drush_print();
-  drush_print(t("Update status information on all installed and enabled Drupal modules:"));
-  drush_print_table($rows, 2, TRUE);
-  drush_print();
-
-  // If specific project updates were requested then remove releases for all others
-  if (!empty($requests)) {
-    foreach ($updateable as $project => $release) {
-      if (!isset($requests[$project])) {
-        unset($updateable[$project]);
-      }
-    }
-  }
-
-  if (empty($updateable)) {
-    drush_die(t('No updates available.'));
-  }
-
-  // Offer to update to the identified releases
-  drush_pm_update_packages($updateable);
-}
-
-/**
- * Update packages according to an array of releases, following interactive
- * confirmation from the user.
- * 
- * @param $releases
- *   An array of releases from the drupal.org update service, with an additional
- *   array key candidate_version that specifies the version to be installed.
- */
-function drush_pm_update_packages($releases) {
-  if (isset($releases['drupal'])) {
-    drush_print("NOTE: An update for the Drupal core is available. \nDrupal itself can't yet be updated by this tool. Please update Drupal manually.\n");
-    unset($releases['drupal']);
-  }
-
-  drush_print(t('Updates will be made to the following projects:'));
-  foreach($releases as $release) {
-    $print .= $release['title'] . " [" . $release['name'] . '-' . $release['candidate_version'] . "], ";
-  }
-  drush_print(substr($print, 0, strlen($print)-2));
-  drush_print();
-  drush_print(t("Note: Updated modules can potentially break your site. It's not recommended to update production sites without prior testing."));
-  if (module_exists('drush_pm_svn')) {
-    drush_print(t("Note: A backup of your package will be stored to backups directory if no .svn directory is found."));
-  }
-  drush_print(t('Note: If you have made any modifications to any file that belongs to one of these projects, you will have to migrate those modifications after updating.'));
-  if(!drush_confirm(t('Do you really want to continue?'))) {
-    drush_die('Aborting.');
-  }
-
-  $package_handler = drush_pm_get_package_handler() .'_update_project';
-  if (!function_exists($package_handler)) {
-    drush_die(t("The $package_handler package handler does not handle updates."));
-  }
-  
-  // Save the date to be used in the backup directory's path name.
-  $date = date('YmdHis');
-  
-  // Now we start the actual updating.
-  foreach($releases as $release) {
-    drush_verbose(t('Starting to update !project ...', array('!project' => $release['title'])));
-    
-    $source = DRUSH_DRUPAL_ROOT .'/' . $release['path'];
-    
-    $skip_backup = module_invoke_all('drush_pm_skip_backup', $source);
-    if (!count($skip_backup)) {
-      $backup_dir = DRUSH_DRUPAL_ROOT. '/backup';
-      drush_op('mkdir', $backup_dir, 0777);
-      $backup_dir .= '/modules';
-      drush_op('mkdir', $backup_dir, 0777);
-      $backup_dir .= "/$date";
-      drush_op('mkdir', $backup_dir, 0777);
-      $backup_target = $backup_dir . '/'. $release['name'];
-      if (!drush_op('rename', $source, $backup_target)) {
-        drush_die(t('Failed to backup project directory !source to !backup_target', array('!source' => $source, '!backup_target' => $backup_target)));
-      }
-    }
-  
-    // Install the new version.
-    // $basepath is the dir where the current module is installed. It's one dir up from the
-    // place of the project's info files.
-    $basepath = explode('/', $release['path']);
-    // move a directory up, so we can copy updated dir to parent
-    array_pop($basepath);
-    $project_parent_path = DRUSH_DRUPAL_ROOT. '/'. implode('/', $basepath). '/';
-    if (!$package_handler($release['name'], $release['releases'][$release['candidate_version']], $project_parent_path)) {
-      if (!count($skip_backup)) {
-        drush_error(t('Updating project !project failed. Restoring previously installed version.', array('!project' => $release['name'])));
-        drush_op('rename', $backup_target, $source);
-      }
-      else {
-        drush_error(t('Updating project !project failed. Please revert to the previously installed version.', array('!project' => $release['name'])));
-      }
-    }
-    else {
-      drush_print(t('Project !project was updated successfully. Installed version is now !version.', array('!project' => $release['name'], '!version' => $release['candidate_version'])));
-      module_invoke_all('drush_pm_post_update', $release['name'], $release['releases'][$release['candidate_version']], $project_parent_path);
-    }
-  }
-  if ($backup_dir) {
-    drush_print(t("Backups were saved into the directory !backup_dir.", array('!backup_dir' => $backup_dir))); 
-  }
-  drush_print(t("You should now run update.php through your browser."));
-}
-
-/**
- * Find a module handler
- */
-function drush_pm_get_package_handler() {
-  $package_handlers = module_invoke_all('drush_pm_package_handler');
-  
-  if (empty($package_handlers)) {
-    drush_die(t("No package handlers found."));
-  }
-
-  $handler = drush_get_option('handler');
-  // See if we have the full handler provided
-  if (array_search($handler, $package_handlers)) {
-    return $handler;
-  }
-  // Allow a shortcut for any functions named drush_pm_*
-  if (array_search('drush_pm_'. $handler, $package_handlers)) {
-    return 'drush_pm_'. $handler;
-  }
-
-  // Fallback on the first provided handler (from the lightest module)
-  return $package_handlers[0];
-}
-
-/**
- * Get update information for all installed projects.
- *
- * @return An array containing remote and local versions for all installed projects
- */
-function _drush_pm_get_update_info($projects = NULL) {
-  $info = update_get_available();
-  $data = update_calculate_project_data($info);
-  $data = drush_pm_get_project_path($data);
-  return $data;
-}
-
-/**
- * Command callback. Refresh update status information.
- */
-function drush_pm_refresh() {
-  drush_print(t("Refreshing update status information ..."));
-  update_refresh();
-  drush_print(t("Done."));
-}
-
-/**
- * Get project information from drupal.org.
- *
- * @param $projects An array of project names
- */
-function drush_pm_get_project_info($projects) {
-  $info = array();
-  $data = array();
-  foreach ($projects as $project_name => $project) {
-    $url = UPDATE_DEFAULT_URL. "/$project_name/". DRUPAL_CORE_COMPATIBILITY;
-    $xml = drupal_http_request($url);
-    $data[] = $xml->data;
-  }
-  if ($data) {
-    include_once drupal_get_path('module', 'update') .'/update.fetch.inc';
-    $parser = new update_xml_parser;
-    $info = $parser->parse($data);
-  }
-  return $info;
-}
-
-/**
- * Get the recommended release for a certain so far uninstalled project.
- *
- * @param $project A project information array for the requested project 
- * @param $info A project information array for this project, as returned by an update service from drush_pm_get_project_info()
- */
-function drush_pm_get_release($project, $info) {
-  $minor = '';
-  $version_patch_changed = '';
-
-  if ($project['version']) {
-    // The user specified a specific version - try to find that exact version
-    foreach($info['releases'] as $version => $release) {
-       // Ignore unpublished releases.
-      if ($release['status'] != 'published') {
-        continue;
-      }
-      
-      // Straight match
-      if (!isset($recommended_version) && $release['version'] == $project['version']) {
-        $recommended_version = $version;
-      }
-      // Shortcut match with ommitted Drupal version
-      if (!isset($recommended_version) && $release['version'] == DRUPAL_CORE_COMPATIBILITY .'-'. $project['version']) {
-        $recommended_version = $version;
-      }
-    }
-  }
-  else {
-    // No version specified - try to find the best version we can
-    foreach($info['releases'] as $version => $release) {
-       // Ignore unpublished releases.
-      if ($release['status'] != 'published') {
-        continue;
-      }
-  
-      // If we haven't found a recommended version yet, put the dev
-      // version as recommended and hope it gets overwritten later.
-      // Look for the 'latest version' if we haven't found it yet.
-      // Latest version is defined as the most recent version for the
-      // default major version.
-      if (!isset($latest_version) && $release['version_major'] == $info['default_major']) {
-        $latest_version = $version;
-      }
-  
-      if (!isset($recommended_version) && $release['version_major'] == $info['default_major']) {
-        if ($minor != $release['version_patch']) {
-          $minor = $release['version_patch'];
-          $version_patch_changed = $version;
-        }
-        if (empty($release['version_extra']) && $minor == $release['version_patch']) {
-          $recommended_version = $version_patch_changed;
-        }
-        continue;
-      }
-    }
-  }
-
-  if (isset($recommended_version)) {
-    return $info['releases'][$recommended_version];
-  }
-  else if (isset($latest_version)) {
-    return $info['releases'][$latest_version];
-  }
-  else {
-    return false;
-  }
-}
-
-/**
- * We need to set the project path by looking at the module location. Ideally, update.module would do this for us.
- */
-function drush_pm_get_project_path($projects) {
-  foreach ($projects as $project => $info) {
-    if (!isset($info['path'])  && $project != 'drupal') {
-      // looks for an enabled module.
-      foreach ($info['includes'] as $module => $name) {
-        if ($path = drupal_get_path('module', $module)) {
-          continue;
-        }
-      }
-      // As some modules are not located in their project's root directory
-      // but in a subdirectory (e.g. all the ecommerce modules), we take the module's
-      // info file's path, and then move up until we are at a directory with the
-      // project's name.
-      $parts = explode('/', $path);
-      $i = count($parts) - 1;
-      $stop = array_search($project, $parts);
-      while ($i > $stop) {
-        unset($parts[$i]);
-        $i--;
-      }
-      $projects[$project]['path'] = implode('/', $parts);
-    }
-  }
-  return $projects;
-}
-
-/**
- * A drush command callback. Show release info for given project(s).
- *
- **/
-function drush_pm_info() {
-  $projects = func_get_args();
-  $projects = drupal_map_assoc($projects);
-  $info = drush_pm_get_project_info($projects);
-
-  $rows[] = array(t('Project'), t('Release'), t('Date'));
-  foreach ($info as $key => $project) {
-    foreach ($project['releases'] as $release) {
-
-      $rows[] = array(
-        $key,
-        $release['version'],
-        format_date($release['date'], 'custom', 'Y-M-d'),
-      );
-    }
-  }
-  return drush_print_table($rows, FALSE, TRUE);
-}
-
-/**
- * Deletes a directory, all files in it and all subdirectories in it (recursively).
- * Use with care!
- * Written by Andreas Kalsch
- */
-function delete_dir($dir) {
-  if (substr($dir, strlen($dir)-1, 1) != '/')
-    $dir .= '/';
-
-  if ($handle = opendir($dir)) {
-    while ($obj = readdir($handle)) {
-      if ($obj != '.' && $obj != '..') {
-        if (is_dir($dir.$obj)) {
-          if (!delete_dir($dir.$obj)) {
-            return false;
-          }
-        }
-        elseif (is_file($dir.$obj)) {
-          if (!unlink($dir.$obj)) {
-            return false;
-          }
-        }
-      }
-    }
-
-    closedir($handle);
-
-    if (!@rmdir($dir)) {
-      return false;
-    }
-    return true;
-  }
-  return false;
-}
-
 ?>
Index: drush_pm_cvs/drush_pm_cvs.drush.inc
===================================================================
RCS file: drush_pm_cvs/drush_pm_cvs.drush.inc
diff -N drush_pm_cvs/drush_pm_cvs.drush.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ drush_pm_cvs/drush_pm_cvs.drush.inc	20 Nov 2008 02:55:10 -0000
@@ -0,0 +1,90 @@
+<?php
+// $Id$
+/**
+ * @file Drush PM CVS extension
+ */
+
+/**
+ * Hook drush_pm_module_handler
+ */
+function drush_pm_cvs_drush_pm_package_handler() {
+  return array('drush_pm_cvs');
+}
+
+/**
+ * Install a project (so far, only modules are supported).
+ *
+ * @param $project The short name of the drupal.org project
+ * @param $info The details (fetched from drupal.org via xml-rpc)
+ * @param $path The path to install the module to.
+ */
+function drush_pm_cvs_install_project($project, $info, $path = '.') {
+  drush_op('chdir', $path);
+
+  drush_verbose("Downloading project $project ...");
+
+  $cvsparams = drush_get_option('cvsparams');
+  
+  // Check it out.
+  drush_pm_cvs_checkout($project, $info['tag'], $cvsparams);
+
+  if (is_dir($path . $project) && !DRUSH_SIMULATE) {
+    drush_verbose("Checking out " . $project . " was successful.");
+    return TRUE;
+  }
+  else {
+    return drush_error("Unable to check out $filename to $path from cvs.drupal.org");
+  }
+}
+
+/**
+ * Update a project (so far, only modules are supported).
+ *
+ * @param $project The short name of the drupal.org project
+ * @param $info The details (fetched from drupal.org via xml-rpc)
+ * @param $path The path to install the module to.
+ */
+function drush_pm_cvs_update_project($project, $info, $path = '.') {
+  drush_op('chdir', $path);
+
+  drush_verbose("Updating project $project ...");
+
+  $cvsmethod = drush_get_option('cvsmethod');
+  if (empty($cvsmethod) && file_exists($project. '/.svn')) {
+    // If we have .svn files the default is to update in place
+    // this will try and merge any changes, which could break things
+    // but we assume anyone using SVN is competent enough to deal with this!
+    $cvsmethod = 'update';
+  }
+
+  $cvsparams = drush_get_option('cvsparams');
+  
+  drush_verbose($cvsmethod);
+  drush_verbose(strpos(strtolower($cvsmethod), 'up'));
+  if (substr($cvsmethod, 0, 2) == 'up') {
+  	// Update the working copy.
+  	drush_op('chdir', $project);
+  	if (!drush_shell_exec('cvs update -dP '. $cvsparams . ' -r '. $info['tag'])) {
+  	  drush_die("Unable to update $project from cvs.drupal.org.");
+  	}
+  	drush_op('chdir', '..');
+  }
+  else {
+    // Check it out.
+    drush_pm_cvs_checkout($project, $info['tag'], $cvsparams);
+  }
+
+  if (is_dir($path . $project) && !DRUSH_SIMULATE) {
+    drush_verbose("Updating out " . $project . " was successful.");
+    return TRUE;
+  }
+  else {
+    return drush_error("Unable to update $project from cvs.drupal.org");
+  }
+}
+
+function drush_pm_cvs_checkout($project, $tag, $cvsparams) {
+  if (!drush_shell_exec('cvs -z6 '. $cvsparams .' -d:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal-contrib checkout -d '. $project .' -r '. $tag .' contributions/modules/'. $project)) {
+    drush_die("Unable to checkout $project from cvs.drupal.org.");
+  }
+}
Index: drush_pm_cvs/drush_pm_cvs.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush_pm_cvs/drush_pm_cvs.module,v
retrieving revision 1.3
diff -u -5 -p -u -p -r1.3 drush_pm_cvs.module
--- drush_pm_cvs/drush_pm_cvs.module	30 May 2008 03:53:05 -0000	1.3
+++ drush_pm_cvs/drush_pm_cvs.module	20 Nov 2008 02:55:10 -0000
@@ -1,8 +1,10 @@
 <?php
 // $Id: drush_pm_cvs.module,v 1.3 2008/05/30 03:53:05 weitzman Exp $
 
+include_once('drush_pm_cvs.drush.inc');
+
 /**
  * Implementation of hook_help().
  */
 function drush_pm_cvs_help($section) {
   $help = '';
@@ -19,89 +21,5 @@ e.g. --cvsparams=\"-C\" (note that quote
 changes when updating an SVN managed project.\n");
     return $help;
   }
 }
 
-/**
- * Hook drush_pm_module_handler
- */
-function drush_pm_cvs_drush_pm_package_handler() {
-  return array('drush_pm_cvs');
-}
-
-/**
- * Install a project (so far, only modules are supported).
- *
- * @param $project The short name of the drupal.org project
- * @param $info The details (fetched from drupal.org via xml-rpc)
- * @param $path The path to install the module to.
- */
-function drush_pm_cvs_install_project($project, $info, $path = '.') {
-  drush_op('chdir', $path);
-
-  drush_verbose("Downloading project $project ...");
-
-  $cvsparams = drush_get_option('cvsparams');
-  
-  // Check it out.
-  drush_pm_cvs_checkout($project, $info['tag'], $cvsparams);
-
-  if (is_dir($path . $project) && !DRUSH_SIMULATE) {
-    drush_verbose("Checking out " . $project . " was successful.");
-    return TRUE;
-  }
-  else {
-    return drush_error("Unable to check out $filename to $path from cvs.drupal.org");
-  }
-}
-
-/**
- * Update a project (so far, only modules are supported).
- *
- * @param $project The short name of the drupal.org project
- * @param $info The details (fetched from drupal.org via xml-rpc)
- * @param $path The path to install the module to.
- */
-function drush_pm_cvs_update_project($project, $info, $path = '.') {
-  drush_op('chdir', $path);
-
-  drush_verbose("Updating project $project ...");
-
-  $cvsmethod = drush_get_option('cvsmethod');
-  if (empty($cvsmethod) && file_exists($project. '/.svn')) {
-    // If we have .svn files the default is to update in place
-    // this will try and merge any changes, which could break things
-    // but we assume anyone using SVN is competent enough to deal with this!
-    $cvsmethod = 'update';
-  }
-
-  $cvsparams = drush_get_option('cvsparams');
-  
-  drush_verbose($cvsmethod);
-  drush_verbose(strpos(strtolower($cvsmethod), 'up'));
-  if (substr($cvsmethod, 0, 2) == 'up') {
-  	// Update the working copy.
-  	drush_op('chdir', $project);
-  	if (!drush_shell_exec('cvs update -dP '. $cvsparams . ' -r '. $info['tag'])) {
-  	  drush_die("Unable to update $project from cvs.drupal.org.");
-  	}
-  	drush_op('chdir', '..');
-  }
-  else {
-    // Check it out.
-    drush_pm_cvs_checkout($project, $info['tag'], $cvsparams);
-  }
-
-  if (is_dir($path . $project) && !DRUSH_SIMULATE) {
-    drush_verbose("Updating out " . $project . " was successful.");
-    return TRUE;
-  }
-  else {
-    return drush_error("Unable to update $project from cvs.drupal.org");
-  }
-}
-
-function drush_pm_cvs_checkout($project, $tag, $cvsparams) {
-  if (!drush_shell_exec('cvs -z6 '. $cvsparams .' -d:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal-contrib checkout -d '. $project .' -r '. $tag .' contributions/modules/'. $project)) {
-    drush_die("Unable to checkout $project from cvs.drupal.org.");
-  }
-}
Index: drush_pm_svn/drush_pm_svn.drush.inc
===================================================================
RCS file: drush_pm_svn/drush_pm_svn.drush.inc
diff -N drush_pm_svn/drush_pm_svn.drush.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ drush_pm_svn/drush_pm_svn.drush.inc	20 Nov 2008 02:55:10 -0000
@@ -0,0 +1,94 @@
+<?php
+// $Id$
+/**
+ * @file Drush pm SVN extension
+ */
+
+/**
+ * Implementation of hook_drush_pm_skip_backup().
+ */
+function drush_pm_svn_drush_pm_skip_backup($source) {
+  if (file_exists($source. '/.svn')) {
+    // Skip backup since we need all .svn  directories. Assuming admin can use svn revert if new project is bad.
+    drush_verbose(t('Backup skipped because .svn directory was detected. Use Subversion to revert if needed.'));
+    return TRUE;
+  }
+}
+
+/**
+ * Implementation of hook_drush_pm_post_update().
+ */
+function drush_pm_svn_drush_pm_post_update($project, $info, $path = '.') {
+  if (drush_pm_svn_sync($project, $info, $path)) {
+    // Only attempt commit on a sucessful sync
+    drush_pm_svn_commit($project, $info, $path);
+  }
+}
+
+/**
+ * Implementation of hook_drush_pm_post_install().
+ */
+function drush_pm_svn_drush_pm_post_install($project, $info, $path = '.') {
+  if (drush_pm_svn_sync($project, $info, $path)) {
+    // Only attempt commit on a sucessful sync
+    drush_pm_svn_commit($project, $info, $path);
+  }
+}
+
+/**
+ * Automatically add any unversioned files to Subversion and remove any files
+ * that have been deleted on the file system
+ */
+function drush_pm_svn_sync($project, $info, $path = '.') {
+  if (drush_get_option('svnsync')) {
+    $errors = '';
+    if (drush_shell_exec('svn status '. drush_get_option('svnstatusparams') .' '. $project)) {
+      $output = drush_shell_exec_output();
+      foreach ($output as $line) {
+        if (preg_match('/^\? *(.*)/', $line, $matches)) {
+          if (!drush_shell_exec('svn add '. drush_get_option('svnaddparams') .' '. $matches[1])) {
+            $errors .= implode("\n", drush_shell_exec_output());
+          }
+        }
+        if (preg_match('/^\! *(.*)/', $line, $matches)) {
+          if (!drush_shell_exec('svn remove '. drush_get_option('svnremoveparams') .' '. $matches[1])) {
+            $errors .= implode("\n", drush_shell_exec_output());
+          }
+        }
+      }
+      if (!empty($errors)) {
+        drush_print(t("Problems were encountered adding or removing files to/from subversion.\nThe specific errors are below:"));
+        drush_print($errors);
+        return FALSE;
+      }
+    }
+    else {
+      drush_print(t("Drush was unable to get the svn status. Check that you have Subversion \ninstalled and that the site is a subversion working copy.\nThe specific errors are below:"));
+      drush_print(implode("\n", drush_shell_exec_output()));
+      return FALSE;
+    }
+    return TRUE;
+  }
+}
+
+/**
+ * Automatically commit changes to the repository
+ */
+function drush_pm_svn_commit($project, $info, $path = '.') {
+  if (drush_get_option('svncommit')) {
+    $message = drush_get_option('svnmessage');
+    if (empty($message)) {
+      $message = t("Drush automatic commit: \n") . implode(' ', $_SERVER['argv']);
+    }
+    if (drush_shell_exec('svn commit '. drush_get_option('svncommitparams') .' -m "'. $message .'" '. $project)) {
+      drush_print(t('Project committed to Subversion successfully'));
+    }
+    else {
+      drush_print(t("'Problems were encountered committing your changes to Subversion.\nThe specific errors are below:"));
+      drush_print(implode("\n", drush_shell_exec_output()));
+    }
+  }
+  else {
+    drush_print(t("You should consider committing the new code to your Subversion repository.\nIf this version becomes undesireable, use Subversion to roll back."));
+  }
+}
Index: drush_pm_svn/drush_pm_svn.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush_pm_svn/drush_pm_svn.module,v
retrieving revision 1.1
diff -u -5 -p -u -p -r1.1 drush_pm_svn.module
--- drush_pm_svn/drush_pm_svn.module	19 May 2008 01:31:57 -0000	1.1
+++ drush_pm_svn/drush_pm_svn.module	20 Nov 2008 02:55:10 -0000
@@ -1,8 +1,10 @@
 <?php
 // $Id: drush_pm_svn.module,v 1.1 2008/05/19 01:31:57 weitzman Exp $
 
+include_once('drush_pm_svn.drush.inc');
+
 /**
  * Implementation of hook_help().
  */
 function drush_pm_svn_help($section) {
   $help = '';
@@ -28,93 +30,5 @@ e.g. --svncommitparams=\"--username joe\
 commit changes as the user 'joe'.\n");
     return $help;
   }
 }
 
-/**
- * Implementation of hook_drush_pm_skip_backup().
- */
-function drush_pm_svn_drush_pm_skip_backup($source) {
-  if (file_exists($source. '/.svn')) {
-    // Skip backup since we need all .svn  directories. Assuming admin can use svn revert if new project is bad.
-    drush_verbose(t('Backup skipped because .svn directory was detected. Use Subversion to revert if needed.'));
-    return TRUE;
-  }
-}
-
-/**
- * Implementation of hook_drush_pm_post_update().
- */
-function drush_pm_svn_drush_pm_post_update($project, $info, $path = '.') {
-  if (drush_pm_svn_sync($project, $info, $path)) {
-    // Only attempt commit on a sucessful sync
-    drush_pm_svn_commit($project, $info, $path);
-  }
-}
-
-/**
- * Implementation of hook_drush_pm_post_install().
- */
-function drush_pm_svn_drush_pm_post_install($project, $info, $path = '.') {
-  if (drush_pm_svn_sync($project, $info, $path)) {
-    // Only attempt commit on a sucessful sync
-    drush_pm_svn_commit($project, $info, $path);
-  }
-}
-
-/**
- * Automatically add any unversioned files to Subversion and remove any files
- * that have been deleted on the file system
- */
-function drush_pm_svn_sync($project, $info, $path = '.') {
-  if (drush_get_option('svnsync')) {
-    $errors = '';
-    if (drush_shell_exec('svn status '. drush_get_option('svnstatusparams') .' '. $project)) {
-      $output = drush_shell_exec_output();
-      foreach ($output as $line) {
-        if (preg_match('/^\? *(.*)/', $line, $matches)) {
-          if (!drush_shell_exec('svn add '. drush_get_option('svnaddparams') .' '. $matches[1])) {
-            $errors .= implode("\n", drush_shell_exec_output());
-          }
-        }
-        if (preg_match('/^\! *(.*)/', $line, $matches)) {
-          if (!drush_shell_exec('svn remove '. drush_get_option('svnremoveparams') .' '. $matches[1])) {
-            $errors .= implode("\n", drush_shell_exec_output());
-          }
-        }
-      }
-      if (!empty($errors)) {
-        drush_print(t("Problems were encountered adding or removing files to/from subversion.\nThe specific errors are below:"));
-        drush_print($errors);
-        return FALSE;
-      }
-    }
-    else {
-      drush_print(t("Drush was unable to get the svn status. Check that you have Subversion \ninstalled and that the site is a subversion working copy.\nThe specific errors are below:"));
-      drush_print(implode("\n", drush_shell_exec_output()));
-      return FALSE;
-    }
-    return TRUE;
-  }
-}
-
-/**
- * Automatically commit changes to the repository
- */
-function drush_pm_svn_commit($project, $info, $path = '.') {
-  if (drush_get_option('svncommit')) {
-    $message = drush_get_option('svnmessage');
-    if (empty($message)) {
-      $message = t("Drush automatic commit: \n") . implode(' ', $_SERVER['argv']);
-    }
-    if (drush_shell_exec('svn commit '. drush_get_option('svncommitparams') .' -m "'. $message .'" '. $project)) {
-      drush_print(t('Project committed to Subversion successfully'));
-    }
-    else {
-      drush_print(t("'Problems were encountered committing your changes to Subversion.\nThe specific errors are below:"));
-      drush_print(implode("\n", drush_shell_exec_output()));
-    }
-  }
-  else {
-    drush_print(t("You should consider committing the new code to your Subversion repository.\nIf this version becomes undesireable, use Subversion to roll back."));
-  }
-}
Index: drush_pm_wget/drush_pm_wget.drush.inc
===================================================================
RCS file: drush_pm_wget/drush_pm_wget.drush.inc
diff -N drush_pm_wget/drush_pm_wget.drush.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ drush_pm_wget/drush_pm_wget.drush.inc	20 Nov 2008 02:55:11 -0000
@@ -0,0 +1,75 @@
+<?php
+// $Id$
+/**
+ * @file Drush PM Wget extension 
+ */
+
+/**
+ * Hook drush_pm_module_handler
+ */
+function drush_pm_wget_drush_pm_package_handler() {
+  return array('drush_pm_wget');
+}
+
+/**
+ * Install a project (so far, only modules are supported).
+ *
+ * @param $project The short name of the drupal.org project
+ * @param $info The details (fetched from drupal.org via xml-rpc)
+ * @param $path The path to install the module to.
+ */
+function drush_pm_wget_install_project($project, $info, $path = '.') {
+
+  drush_op('chdir', $path);
+
+  drush_verbose("Downloading project $project ...");
+
+  // Get the filename...
+  $filename = explode('/', $info['download_link']);
+  $filename = array_pop($filename);
+
+  // Download it.
+  if (!drush_shell_exec("wget " .$info['download_link'])) {
+    drush_shell_exec("curl -O " .$info['download_link']);
+  }
+
+  if (file_exists($path. $filename) || DRUSH_SIMULATE) {
+    drush_verbose("Downloading " . $filename . " was successful.");
+  }
+  else {
+    return drush_error("Unable to download $filename to $path from ". $info['download_link']);
+  }
+
+  // Check Md5 hash
+  if (md5_file($filename) != $info['mdhash'] && !DRUSH_SIMULATE) {
+    drush_op('unlink', $filename);
+    return drush_error("Error: File $filename is corrupt (wrong md5 checksum).");
+  }
+  else {
+    drush_verbose("Md5 checksum of $filename verified.");
+  }
+
+  // Decompress
+  drush_shell_exec("gzip -d " . $filename);
+  $filename = substr($filename, 0, strlen($filename)-3);
+  // Untar
+  drush_shell_exec("tar -xf " . $filename);
+  // We're not using tar -xzf because that's not working on windows...
+
+  // Remove the tarball
+  drush_op('unlink', $filename);
+
+  if (!is_dir($path . $project) && !DRUSH_SIMULATE) {
+    return drush_error("Error. Downloaded file $filename couldn't be untarred correctly");
+  }
+  else {
+    return TRUE;
+  }
+}
+
+/**
+ * This is an alias of the install function, since they are identical
+ */
+function drush_pm_wget_update_project($project, $info, $path = '.') {
+  return drush_pm_wget_install_project($project, $info, $path);
+}
Index: drush_pm_wget/drush_pm_wget.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush_pm_wget/drush_pm_wget.module,v
retrieving revision 1.1
diff -u -5 -p -u -p -r1.1 drush_pm_wget.module
--- drush_pm_wget/drush_pm_wget.module	8 Jan 2008 04:30:19 -0000	1.1
+++ drush_pm_wget/drush_pm_wget.module	20 Nov 2008 02:55:11 -0000
@@ -1,8 +1,10 @@
 <?php
 // $Id: drush_pm_wget.module,v 1.1 2008/01/08 04:30:19 weitzman Exp $
 
+include_once('drush_pm_wget.drush.inc');
+
 /**
  * Implementation of hook_help().
  */
 function drush_pm_wget_help($section) {
   switch ($section) {
@@ -10,74 +12,5 @@ function drush_pm_wget_help($section) {
     case 'drush:pm update':
       return t("Note: the wget handler will use the curl command if wget is not found\n");
   }
 }
 
-/**
- * Hook drush_pm_module_handler
- */
-function drush_pm_wget_drush_pm_package_handler() {
-  return array('drush_pm_wget');
-}
-
-/**
- * Install a project (so far, only modules are supported).
- *
- * @param $project The short name of the drupal.org project
- * @param $info The details (fetched from drupal.org via xml-rpc)
- * @param $path The path to install the module to.
- */
-function drush_pm_wget_install_project($project, $info, $path = '.') {
-
-  drush_op('chdir', $path);
-
-  drush_verbose("Downloading project $project ...");
-
-  // Get the filename...
-  $filename = explode('/', $info['download_link']);
-  $filename = array_pop($filename);
-
-  // Download it.
-  if (!drush_shell_exec("wget " .$info['download_link'])) {
-    drush_shell_exec("curl -O " .$info['download_link']);
-  }
-
-  if (file_exists($path. $filename) || DRUSH_SIMULATE) {
-    drush_verbose("Downloading " . $filename . " was successful.");
-  }
-  else {
-    return drush_error("Unable to download $filename to $path from ". $info['download_link']);
-  }
-
-  // Check Md5 hash
-  if (md5_file($filename) != $info['mdhash'] && !DRUSH_SIMULATE) {
-    drush_op('unlink', $filename);
-    return drush_error("Error: File $filename is corrupt (wrong md5 checksum).");
-  }
-  else {
-    drush_verbose("Md5 checksum of $filename verified.");
-  }
-
-  // Decompress
-  drush_shell_exec("gzip -d " . $filename);
-  $filename = substr($filename, 0, strlen($filename)-3);
-  // Untar
-  drush_shell_exec("tar -xf " . $filename);
-  // We're not using tar -xzf because that's not working on windows...
-
-  // Remove the tarball
-  drush_op('unlink', $filename);
-
-  if (!is_dir($path . $project) && !DRUSH_SIMULATE) {
-    return drush_error("Error. Downloaded file $filename couldn't be untarred correctly");
-  }
-  else {
-    return TRUE;
-  }
-}
-
-/**
- * This is an alias of the install function, since they are identical
- */
-function drush_pm_wget_update_project($project, $info, $path = '.') {
-  return drush_pm_wget_install_project($project, $info, $path);
-}
Index: drush_simpletest/drush_simpletest.drush.inc
===================================================================
RCS file: drush_simpletest/drush_simpletest.drush.inc
diff -N drush_simpletest/drush_simpletest.drush.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ drush_simpletest/drush_simpletest.drush.inc	20 Nov 2008 02:55:11 -0000
@@ -0,0 +1,64 @@
+<?php
+// $Id$
+/**
+ * @file Drush simpletest commands
+ */
+
+/**
+ * Implementation of hook_drush_command().
+ */
+function drush_simpletest_drush_command() {
+  $items['test run'] = array(
+    'callback' => 'drush_test_run',
+    'description' => 'Run one or more Simpletest tests.',
+  );
+  $items['test list'] = array(
+    'callback' => 'drush_test_list',
+    'description' => 'List the available Simpletest test classes.',
+  );
+  return $items;
+}
+
+function drush_test_list() {
+  simpletest_load();
+  // TODO: Refactor simpletest.module so we don't copy code from DrupalUnitTests
+  $files = array();
+  foreach (module_list() as $module) {
+    $module_path = drupal_get_path('module', $module);
+    if (file_exists($module_path .'/tests/')) {
+      $dir = $module_path .'/tests';
+      $tests = file_scan_directory($dir, '\.test$');
+      $files = array_merge($files, $tests);
+    }   
+  }   
+  $files = array_keys($files);
+
+  $existing_classes = get_declared_classes();
+  foreach ($files as $file) {
+    include_once($file);
+  }
+  $classes = array_diff(get_declared_classes(), $existing_classes);
+  $rows[] = array(t('Class'), t('Name'), t('Description'));
+  foreach ($classes as $class) {
+    $tmp = new $class;
+    if (method_exists($tmp, 'get_info')) {
+      $info =  $tmp->get_info();
+      $rows[] = array($class, $info['name'], truncate_utf8($info['desc'], 30, TRUE, TRUE));
+    }
+  }
+  return drush_print_table($rows, 0, TRUE);
+}
+
+
+function drush_test_run($tests = NULL) {
+  simpletest_load();
+  if (is_null($tests)) {
+    drush_print(t('Running all tests'));
+    $result = simpletest_run_tests();
+    }
+  else {
+    $tests = explode(',', $tests);
+    $result = simpletest_run_tests($tests, 'text');
+  }
+  return $result;
+}
Index: drush_simpletest/drush_simpletest.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush_simpletest/drush_simpletest.module,v
retrieving revision 1.3.2.1
diff -u -5 -p -u -p -r1.3.2.1 drush_simpletest.module
--- drush_simpletest/drush_simpletest.module	24 Jul 2008 14:21:13 -0000	1.3.2.1
+++ drush_simpletest/drush_simpletest.module	20 Nov 2008 02:55:11 -0000
@@ -4,10 +4,12 @@
 /**
  * @file
  *
  */
 
+include_once('drush_simpletest.drush.inc');
+
 /**
  * Implementation of hook_help().
  */
 function drush_simpletest_help($section) {
   switch ($section) {
@@ -16,63 +18,5 @@ function drush_simpletest_help($section)
       case 'drush:test list':
         return t("Usage drush [options] test list.\n\nList the available tests. Use drush test run command to run them. ");
   }
 }
 
-/**
- * Implementation of hook_drush_command().
- */
-function drush_simpletest_drush_command() {
-  $items['test run'] = array(
-    'callback' => 'drush_test_run',
-    'description' => 'Run one or more Simpletest tests.',
-  );
-  $items['test list'] = array(
-    'callback' => 'drush_test_list',
-    'description' => 'List the available Simpletest test classes.',
-  );
-  return $items;
-}
-
-function drush_test_list() {
-  simpletest_load();
-  // TODO: Refactor simpletest.module so we don't copy code from DrupalUnitTests
-  $files = array();
-  foreach (module_list() as $module) {
-    $module_path = drupal_get_path('module', $module);
-    if (file_exists($module_path .'/tests/')) {
-      $dir = $module_path .'/tests';
-      $tests = file_scan_directory($dir, '\.test$');
-      $files = array_merge($files, $tests);
-    }   
-  }   
-  $files = array_keys($files);
-
-  $existing_classes = get_declared_classes();
-  foreach ($files as $file) {
-    include_once($file);
-  }
-  $classes = array_diff(get_declared_classes(), $existing_classes);
-  $rows[] = array(t('Class'), t('Name'), t('Description'));
-  foreach ($classes as $class) {
-    $tmp = new $class;
-    if (method_exists($tmp, 'get_info')) {
-      $info =  $tmp->get_info();
-      $rows[] = array($class, $info['name'], truncate_utf8($info['desc'], 30, TRUE, TRUE));
-    }
-  }
-  return drush_print_table($rows, 0, TRUE);
-}
-
-
-function drush_test_run($tests = NULL) {
-  simpletest_load();
-  if (is_null($tests)) {
-    drush_print(t('Running all tests'));
-    $result = simpletest_run_tests();
-    }
-  else {
-    $tests = explode(',', $tests);
-    $result = simpletest_run_tests($tests, 'text');
-  }
-  return $result;
-}
Index: drush_sql/drush_sql.drush.inc
===================================================================
RCS file: drush_sql/drush_sql.drush.inc
diff -N drush_sql/drush_sql.drush.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ drush_sql/drush_sql.drush.inc	20 Nov 2008 02:55:11 -0000
@@ -0,0 +1,314 @@
+<?php
+// $Id$
+/**
+ * @file Drush sql commands
+ */
+
+
+/**
+ * Implementation of hook_drush_command().
+ */
+function drush_sql_drush_command() {
+  $items['sql url'] = array(
+    'callback' => 'drush_sql_url',
+    'description' => 'Print database connection details.'
+  );
+  $items['sql version server'] = array(
+    'callback' => 'drush_sql_version_server',
+    'description' => 'Print database server version number.'
+  );
+  $items['sql version client'] = array(
+    'callback' => 'drush_sql_version_client',
+    'description' => 'Print database client library version number.'
+  );
+  $items['sql dump'] = array(
+    'callback' => 'drush_sql_dump',
+    'description' => 'Exports the Drupal DB as SQL using mysqldump or pg_dump.'
+  );
+  $items['sql query'] = array(
+    'callback' => 'drush_sql_query',
+    'description' => 'Execute a query against the site database.'
+  );
+  $items['sql load'] = array(
+    'callback' => 'drush_sql_load',
+    'description' => 'Copy source database to target database.'
+  );
+  return $items;
+}
+
+
+/**
+ * Command callback. Displays the Drupal site's database connection string.
+ */
+function drush_sql_url() {
+  drush_print($GLOBALS['db_url']);
+}
+
+/**
+ * Command callback. Displays the MySQL or PostgreSQL server version number.
+ */
+function drush_sql_version_server() {
+  switch (_drush_sql_get_scheme()) {
+    case 'mysql':
+    case 'mysqli':
+      drush_print(mysql_get_server_info());
+      break;
+    case 'pgsql':
+      // NOTE: apparently the server version is only available if PHP was
+      // compiled with PostgreSQL 7.4 or later, so we'll fall back to
+      // displaying the client version if that's the case.
+      $info = pg_version();
+      drush_print(isset($info['server_version']) ? $info['server_version'] : $info['client']);
+      break;
+    default:
+      drush_die(_drush_sql_get_invalid_url_msg());
+  }
+}
+
+/**
+ * Command callback. Displays the MySQL or PostgreSQL client version number.
+ */
+function drush_sql_version_client() {
+  switch (_drush_sql_get_scheme()) {
+    case 'mysql':
+    case 'mysqli':
+      drush_print(mysql_get_client_info());
+      break;
+    case 'pgsql':
+      $info = pg_version();
+      drush_print($info['client']);
+      break;
+    default:
+      drush_die(_drush_sql_get_invalid_url_msg());
+  }
+}
+
+/**
+ * Command callback. Outputs the entire Drupal database in SQL format using mysqldump or
+ * pg_dump.
+ *
+ * @param db_url
+ * @param execute
+ * @param skip
+ *    A key in the sql_skip array which specifies a list of tables to ignore when migrating.
+ */
+function drush_sql_dump($db_url = NULL, $execute = TRUE, $skip = NULL) {
+  if (is_null($db_url)) {
+    $db_url = $GLOBALS['db_url'];
+  }
+
+  switch (_drush_sql_get_scheme($db_url)) {
+    case 'mysql':
+    case 'mysqli':
+      $exec = 'mysqldump' . (DRUSH_VERBOSE ? ' -v' : '');
+      if ($file = drush_get_option('result-file')) {
+        $exec .= ' --result-file '. $file;
+      }
+      $exec .= ' --opt -Q' . _drush_sql_get_credentials($db_url);
+      break;
+    case 'pgsql':
+      drush_die(t('Sorry, pg_dump support not implemented yet.')); // TODO: pg_dump command.
+      break;
+    default:
+      drush_die(_drush_sql_get_invalid_url_msg($db_url));
+  }
+
+  // Get any arguments to be passed through to the SQL client program.
+  if (func_num_args() > 3 && ($args = func_get_args())) {
+    $args = ' ' . implode(' ', array_slice($args, 3)); // skip standard arguments
+  }
+  
+  // Skip large core tables if instructed.  Used by 'sql load' command.
+    if ($skip && strpos($exec, '--ignore-table') === FALSE) {
+      $all_skip_tables = (array)drush_get_option('skip-tables');
+      $skip_tables = $all_skip_tables[$skip];
+      $database = _drush_sql_get_database($db_url);
+      foreach ($skip_tables as $table) {
+        $ignores[] = "--ignore-table=$database.$table";
+      }
+      $exec .= ' '. implode(' ', $ignores);
+    }
+  
+  if (!$execute) {
+    return $exec;
+  }
+  
+  if (DRUSH_VERBOSE) {
+    drush_print(t('Executing: !cmd', array('!cmd' => $exec)));
+  }
+
+  return drush_op('system', $exec) !== FALSE;
+}
+
+/**
+ * Command callback. Executes the given SQL query on the Drupal database.
+ * Reads from STDIN if no query is provided.
+ */
+function drush_sql_query($query = NULL) {
+  // Get any arguments to be passed through to the SQL client program.
+  if (func_num_args() > 1 && ($args = func_get_args())) {
+    $args = ' ' . implode(' ', array_slice($args, 1)); // skip query argument
+  }
+  
+  return drush_sql_query_execute($query, NULL, $args);
+}
+
+function drush_sql_query_execute($query, $db_url = NULL, $args = NULL) {
+  // FIXME: currently we require the query due to an apparent inability to
+  // run the mysql child process interactively. Need to look more into
+  // proc_open() to see if it could be used for interactive execution.
+  if (empty($query)) {
+    if ($fstat = fstat(STDIN)) {
+      $query = fread(STDIN,$fstat[size]);
+    }
+    else {
+      drush_die(t('No SQL query given as argument.'));
+    }
+  }
+  
+  // Save query to a file. we will redirect it in.
+  $filename = time(). '.sql';
+  if ($file = file_save_data($query, $filename)) {
+    switch (_drush_sql_get_scheme()) {
+      case 'mysql':
+      case 'mysqli':
+        $exec = 'mysql' . (DRUSH_VERBOSE ? ' -v' : '');
+        $exec .= _drush_sql_get_credentials($db_url);
+        $exec .= " < ./$file";
+        break;
+      case 'pgsql':
+        drush_die(t('Sorry, psql support not implemented yet.')); // TODO: psql command.
+        break;
+      default:
+        drush_die(_drush_sql_get_invalid_url_msg($db_url));
+    }
+    $exec .= $args;
+
+    if (DRUSH_VERBOSE) {
+      drush_print(t('Executing: !cmd', array('!cmd' => $exec)));
+    }
+    $return = drush_op('system', $exec) !== FALSE;
+    unlink($file);  
+    return $return;
+  }
+}
+
+/**
+ * Copy an entire database to another database. For example, migrate from Production to dev
+ * or dev to staging.
+ * 
+ * conf_path() uses a static var so we can't use it to figure out paths based on URIs.
+ *
+ * @param source
+ *   The name of a subdirectory under sites. Its settings.php specifies the database which should be migrated.
+ * @param target
+ *    The name of a subdirectory under sites. Its settings.php specifies the database which whose tables will 
+ *    be replaced with the contents of `source`.
+ * @param skip
+ *    A key in the sql_skip array which specifies a list of tables to ignore when migrating.
+ * 
+ **/
+function drush_sql_load($source, $target, $skip = NULL) {
+  // Don't use require_once - we need to ovewrite db_url under some circumstances.
+  require "./sites/$source/settings.php";
+  $db_url_source = is_array($db_url) ? $db_url['default'] : $db_url;
+  require "./sites/$target/settings.php";
+  $db_url_target = is_array($db_url) ? $db_url['default'] : $db_url;
+  
+  // Prompt for confirmation. This is destructive.
+  if (!DRUSH_SIMULATE) {
+    drush_print(t("You will destroy data from !target and replace with data from !source.", array('!source' => $db_url_source, '!target' => $db_url_target)));
+    // TODO: actually make the backup if desired.
+    drush_print(t("You might want to make a backup first, using sql_dump command.\n"));
+    if (!drush_confirm(t('Do you really want to continue?'))) {
+      drush_die('Aborting.');
+    }
+  }
+  
+  // Get command to export from source.
+  if ($retrieve = drush_sql_dump($db_url_source, FALSE, $skip)) {
+    // Get any arguments to be passed through to the mysqldump.
+    $args = array();
+    if (func_num_args() > 3 && ($args = func_get_args())) {
+      $retrieve .= ' ' . implode(' ', array_slice($args, 3)); // skip standard arguments
+    }
+    
+    // Build import command for target.
+    $send = 'mysql' . (DRUSH_VERBOSE ? ' -v' : '');
+    $send .= _drush_sql_get_credentials($db_url_target);
+    
+    // Build pipe command and redirect output to the bit bucket.
+    // Redirection prevented loads of SQL from writing to screen.
+    $exec = "$retrieve | $send > /dev/null 2>&1";
+
+    if (DRUSH_VERBOSE) {
+      drush_print(t('Executing: !cmd', array('!cmd' => $exec)));
+    }
+    
+    $return = drush_op('system', $exec) !== FALSE;
+  }
+  return $return;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// SQL SERVICE HELPERS
+
+// this sets some globals so please beware.
+function drush_sql_get_path($uri) {
+  $drupal_base_url = parse_url($uri);
+  $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
+  $_SERVER['PHP_SELF'] = $drupal_base_url['path'].'/index.php';
+  return conf_path();
+}
+
+function _drush_sql_get_scheme($db_url = NULL) {
+  if (is_null($db_url)) {
+    $db_url = $GLOBALS['db_url'];
+  }
+  $url = (object)parse_url($db_url);
+  return ($url->scheme);
+}
+
+function _drush_sql_get_database($db_url = NULL) {
+  if (is_null($db_url)) {
+    $db_url = $GLOBALS['db_url'];
+  }
+  $url = (object)parse_url($db_url);
+  return substr($url->path, 1);
+}
+
+function _drush_sql_get_credentials($db_url = NULL) {
+  if (is_null($db_url)) {
+    $db_url = $GLOBALS['db_url'];
+  }
+
+  // NOTE: this regex could also parse the connection string URL:
+  //   ^([\w]+)://([\w\d_]+):([^@]*)@([\w\d\.\-]*)/([\w\d_]+)$
+
+  $url = (object)parse_url($db_url);
+  $url->user = urldecode($url->user);
+  $url->pass = urldecode($url->pass);
+  $url->host = urldecode($url->host);
+  $url->path = substr(urldecode($url->path), 1); // skip leading '/' character
+
+  switch ($url->scheme) {
+    case 'mysql':
+    case 'mysqli':
+      return ' -h' . $url->host .
+        (!isset($url->port) ? '' : ' -P' . $url->port) .
+        ' -u' . $url->user .
+        (empty($url->pass) ? '' : ' -p' . $url->pass) . ' ' . $url->path;
+    case 'pgsql':
+      drush_die(t('Sorry, psql support not implemented yet.')); // TODO: psql credentials.
+      return;
+    default:
+      drush_die(_drush_sql_get_invalid_url_msg());
+  }
+}
+
+function _drush_sql_get_invalid_url_msg($db_url = NULL) {
+  if (is_null($db_url)) {
+    $db_url = $GLOBALS['db_url'];
+  }
+  return t('Unable to parse DB connection string: `%url\'.', array('%url' => $db_url));
+}
Index: drush_sql/drush_sql.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush_sql/drush_sql.module,v
retrieving revision 1.12.2.1
diff -u -5 -p -u -p -r1.12.2.1 drush_sql.module
--- drush_sql/drush_sql.module	1 Nov 2008 04:27:46 -0000	1.12.2.1
+++ drush_sql/drush_sql.module	20 Nov 2008 02:55:11 -0000
@@ -4,10 +4,12 @@
 /**
  * @file
  *  The drush SQL commands
  */
 
+include_once('drush_sql.drush.inc');
+
 /**
  * Implementation of hook_help().
  */
 function drush_sql_help($section) {
   switch ($section) {
@@ -18,312 +20,5 @@ function drush_sql_help($section) {
     case 'drush:sql load':
       return t('Usage: drush [options] sql load <source_dir> <target_dir> <skip>. <source_dir> and <target_dir> are names of directories under \'sites\'. These determine from where and to where you want your database copied. Optional: specify \'common\' for <skip> if you wish to omit disposable tables like cache*, search*, etc. Your skip lists are specified in your drushrc.php file. Any additional arguments are passed to the mysqldump command directly.');
   }
 }
 
-/**
- * Implementation of hook_drush_command().
- */
-function drush_sql_drush_command() {
-  $items['sql url'] = array(
-    'callback' => 'drush_sql_url',
-    'description' => 'Print database connection details.'
-  );
-  $items['sql version server'] = array(
-    'callback' => 'drush_sql_version_server',
-    'description' => 'Print database server version number.'
-  );
-  $items['sql version client'] = array(
-    'callback' => 'drush_sql_version_client',
-    'description' => 'Print database client library version number.'
-  );
-  $items['sql dump'] = array(
-    'callback' => 'drush_sql_dump',
-    'description' => 'Exports the Drupal DB as SQL using mysqldump or pg_dump.'
-  );
-  $items['sql query'] = array(
-    'callback' => 'drush_sql_query',
-    'description' => 'Execute a query against the site database.'
-  );
-  $items['sql load'] = array(
-    'callback' => 'drush_sql_load',
-    'description' => 'Copy source database to target database.'
-  );
-  return $items;
-}
-
-
-/**
- * Command callback. Displays the Drupal site's database connection string.
- */
-function drush_sql_url() {
-  drush_print($GLOBALS['db_url']);
-}
-
-/**
- * Command callback. Displays the MySQL or PostgreSQL server version number.
- */
-function drush_sql_version_server() {
-  switch (_drush_sql_get_scheme()) {
-    case 'mysql':
-    case 'mysqli':
-      drush_print(mysql_get_server_info());
-      break;
-    case 'pgsql':
-      // NOTE: apparently the server version is only available if PHP was
-      // compiled with PostgreSQL 7.4 or later, so we'll fall back to
-      // displaying the client version if that's the case.
-      $info = pg_version();
-      drush_print(isset($info['server_version']) ? $info['server_version'] : $info['client']);
-      break;
-    default:
-      drush_die(_drush_sql_get_invalid_url_msg());
-  }
-}
-
-/**
- * Command callback. Displays the MySQL or PostgreSQL client version number.
- */
-function drush_sql_version_client() {
-  switch (_drush_sql_get_scheme()) {
-    case 'mysql':
-    case 'mysqli':
-      drush_print(mysql_get_client_info());
-      break;
-    case 'pgsql':
-      $info = pg_version();
-      drush_print($info['client']);
-      break;
-    default:
-      drush_die(_drush_sql_get_invalid_url_msg());
-  }
-}
-
-/**
- * Command callback. Outputs the entire Drupal database in SQL format using mysqldump or
- * pg_dump.
- *
- * @param db_url
- * @param execute
- * @param skip
- *    A key in the sql_skip array which specifies a list of tables to ignore when migrating.
- */
-function drush_sql_dump($db_url = NULL, $execute = TRUE, $skip = NULL) {
-  if (is_null($db_url)) {
-    $db_url = $GLOBALS['db_url'];
-  }
-
-  switch (_drush_sql_get_scheme($db_url)) {
-    case 'mysql':
-    case 'mysqli':
-      $exec = 'mysqldump' . (DRUSH_VERBOSE ? ' -v' : '');
-      if ($file = drush_get_option('result-file')) {
-        $exec .= ' --result-file '. $file;
-      }
-      $exec .= ' --opt -Q' . _drush_sql_get_credentials($db_url);
-      break;
-    case 'pgsql':
-      drush_die(t('Sorry, pg_dump support not implemented yet.')); // TODO: pg_dump command.
-      break;
-    default:
-      drush_die(_drush_sql_get_invalid_url_msg($db_url));
-  }
-
-  // Get any arguments to be passed through to the SQL client program.
-  if (func_num_args() > 3 && ($args = func_get_args())) {
-    $args = ' ' . implode(' ', array_slice($args, 3)); // skip standard arguments
-  }
-  
-  // Skip large core tables if instructed.  Used by 'sql load' command.
-    if ($skip && strpos($exec, '--ignore-table') === FALSE) {
-      $all_skip_tables = (array)drush_get_option('skip-tables');
-      $skip_tables = $all_skip_tables[$skip];
-      $database = _drush_sql_get_database($db_url);
-      foreach ($skip_tables as $table) {
-        $ignores[] = "--ignore-table=$database.$table";
-      }
-      $exec .= ' '. implode(' ', $ignores);
-    }
-  
-  if (!$execute) {
-    return $exec;
-  }
-  
-  if (DRUSH_VERBOSE) {
-    drush_print(t('Executing: !cmd', array('!cmd' => $exec)));
-  }
-
-  return drush_op('system', $exec) !== FALSE;
-}
-
-/**
- * Command callback. Executes the given SQL query on the Drupal database.
- * Reads from STDIN if no query is provided.
- */
-function drush_sql_query($query = NULL) {
-  // Get any arguments to be passed through to the SQL client program.
-  if (func_num_args() > 1 && ($args = func_get_args())) {
-    $args = ' ' . implode(' ', array_slice($args, 1)); // skip query argument
-  }
-  
-  return drush_sql_query_execute($query, NULL, $args);
-}
-
-function drush_sql_query_execute($query, $db_url = NULL, $args = NULL) {
-  // FIXME: currently we require the query due to an apparent inability to
-  // run the mysql child process interactively. Need to look more into
-  // proc_open() to see if it could be used for interactive execution.
-  if (empty($query)) {
-    if ($fstat = fstat(STDIN)) {
-      $query = fread(STDIN,$fstat[size]);
-    }
-    else {
-      drush_die(t('No SQL query given as argument.'));
-    }
-  }
-  
-  // Save query to a file. we will redirect it in.
-  $filename = time(). '.sql';
-  if ($file = file_save_data($query, $filename)) {
-    switch (_drush_sql_get_scheme()) {
-      case 'mysql':
-      case 'mysqli':
-        $exec = 'mysql' . (DRUSH_VERBOSE ? ' -v' : '');
-        $exec .= _drush_sql_get_credentials($db_url);
-        $exec .= " < ./$file";
-        break;
-      case 'pgsql':
-        drush_die(t('Sorry, psql support not implemented yet.')); // TODO: psql command.
-        break;
-      default:
-        drush_die(_drush_sql_get_invalid_url_msg($db_url));
-    }
-    $exec .= $args;
-
-    if (DRUSH_VERBOSE) {
-      drush_print(t('Executing: !cmd', array('!cmd' => $exec)));
-    }
-    $return = drush_op('system', $exec) !== FALSE;
-    unlink($file);  
-    return $return;
-  }
-}
-
-/**
- * Copy an entire database to another database. For example, migrate from Production to dev
- * or dev to staging.
- * 
- * conf_path() uses a static var so we can't use it to figure out paths based on URIs.
- *
- * @param source
- *   The name of a subdirectory under sites. Its settings.php specifies the database which should be migrated.
- * @param target
- *    The name of a subdirectory under sites. Its settings.php specifies the database which whose tables will 
- *    be replaced with the contents of `source`.
- * @param skip
- *    A key in the sql_skip array which specifies a list of tables to ignore when migrating.
- * 
- **/
-function drush_sql_load($source, $target, $skip = NULL) {
-  // Don't use require_once - we need to ovewrite db_url under some circumstances.
-  require "./sites/$source/settings.php";
-  $db_url_source = is_array($db_url) ? $db_url['default'] : $db_url;
-  require "./sites/$target/settings.php";
-  $db_url_target = is_array($db_url) ? $db_url['default'] : $db_url;
-  
-  // Prompt for confirmation. This is destructive.
-  if (!DRUSH_SIMULATE) {
-    drush_print(t("You will destroy data from !target and replace with data from !source.", array('!source' => $db_url_source, '!target' => $db_url_target)));
-    // TODO: actually make the backup if desired.
-    drush_print(t("You might want to make a backup first, using sql_dump command.\n"));
-    if (!drush_confirm(t('Do you really want to continue?'))) {
-      drush_die('Aborting.');
-    }
-  }
-  
-  // Get command to export from source.
-  if ($retrieve = drush_sql_dump($db_url_source, FALSE, $skip)) {
-    // Get any arguments to be passed through to the mysqldump.
-    $args = array();
-    if (func_num_args() > 3 && ($args = func_get_args())) {
-      $retrieve .= ' ' . implode(' ', array_slice($args, 3)); // skip standard arguments
-    }
-    
-    // Build import command for target.
-    $send = 'mysql' . (DRUSH_VERBOSE ? ' -v' : '');
-    $send .= _drush_sql_get_credentials($db_url_target);
-    
-    // Build pipe command and redirect output to the bit bucket.
-    // Redirection prevented loads of SQL from writing to screen.
-    $exec = "$retrieve | $send > /dev/null 2>&1";
-
-    if (DRUSH_VERBOSE) {
-      drush_print(t('Executing: !cmd', array('!cmd' => $exec)));
-    }
-    
-    $return = drush_op('system', $exec) !== FALSE;
-  }
-  return $return;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// SQL SERVICE HELPERS
-
-// this sets some globals so please beware.
-function drush_sql_get_path($uri) {
-  $drupal_base_url = parse_url($uri);
-  $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
-  $_SERVER['PHP_SELF'] = $drupal_base_url['path'].'/index.php';
-  return conf_path();
-}
-
-function _drush_sql_get_scheme($db_url = NULL) {
-  if (is_null($db_url)) {
-    $db_url = $GLOBALS['db_url'];
-  }
-  $url = (object)parse_url($db_url);
-  return ($url->scheme);
-}
-
-function _drush_sql_get_database($db_url = NULL) {
-  if (is_null($db_url)) {
-    $db_url = $GLOBALS['db_url'];
-  }
-  $url = (object)parse_url($db_url);
-  return substr($url->path, 1);
-}
-
-function _drush_sql_get_credentials($db_url = NULL) {
-  if (is_null($db_url)) {
-    $db_url = $GLOBALS['db_url'];
-  }
-
-  // NOTE: this regex could also parse the connection string URL:
-  //   ^([\w]+)://([\w\d_]+):([^@]*)@([\w\d\.\-]*)/([\w\d_]+)$
-
-  $url = (object)parse_url($db_url);
-  $url->user = urldecode($url->user);
-  $url->pass = urldecode($url->pass);
-  $url->host = urldecode($url->host);
-  $url->path = substr(urldecode($url->path), 1); // skip leading '/' character
-
-  switch ($url->scheme) {
-    case 'mysql':
-    case 'mysqli':
-      return ' -h' . $url->host .
-        (!isset($url->port) ? '' : ' -P' . $url->port) .
-        ' -u' . $url->user .
-        (empty($url->pass) ? '' : ' -p' . $url->pass) . ' ' . $url->path;
-    case 'pgsql':
-      drush_die(t('Sorry, psql support not implemented yet.')); // TODO: psql credentials.
-      return;
-    default:
-      drush_die(_drush_sql_get_invalid_url_msg());
-  }
-}
-
-function _drush_sql_get_invalid_url_msg($db_url = NULL) {
-  if (is_null($db_url)) {
-    $db_url = $GLOBALS['db_url'];
-  }
-  return t('Unable to parse DB connection string: `%url\'.', array('%url' => $db_url));
-}
\ No newline at end of file
Index: drush_tools/drush_tools.drush.inc
===================================================================
RCS file: drush_tools/drush_tools.drush.inc
diff -N drush_tools/drush_tools.drush.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ drush_tools/drush_tools.drush.inc	20 Nov 2008 02:55:11 -0000
@@ -0,0 +1,132 @@
+<?php
+// $Id$
+/**
+ * @file Drush tools
+ */
+
+/**
+ * Implementation of hook_drush_command().
+ */
+function drush_tools_drush_command() {
+  $items['cache clear'] = array(
+    'callback' => 'drush_tools_cache_clear',
+    'description' => 'Clear all caches'
+  );
+  $items['cron'] = array(
+    'callback' => 'drush_tools_cron_run',
+    'description' => 'Run cron'
+  );
+  $items['watchdog show'] = array(
+    'callback' => 'drush_tools_watchdog_show',
+    'description' => 'Show the most recent watchdog log messages'
+  );
+  $items['watchdog delete'] = array(
+    'callback' => 'drush_tools_watchdog_delete',
+    'description' => 'Delete all messages of a certain type'
+  );
+  $items['sync'] = array(
+    'callback' => 'drush_tools_sync',
+    'description' => 'Rsync the Drupal tree to/from another server using ssh'
+  );
+  $items['eval'] = array(
+    'callback' => 'drush_tools_eval',
+    'description' => 'Evaluate a command',
+  );
+  return $items;
+}
+
+function drush_tools_cron_run() {
+  drupal_cron_run();
+  drush_print(t('Cron run successfully.'));
+}
+
+function drush_tools_cache_clear() {
+  drupal_flush_all_caches();
+  drush_print(t('Cache cleared.'));
+}
+
+/**
+ * Push files from or to the local Drupal install using SSH and RSync
+ *
+ * @return void
+ **/
+function drush_tools_sync($source, $destination) {
+  // Local paths are relative to Drupal root
+  if (!strstr($source, ':')) {
+    $source = DRUSH_DRUPAL_ROOT. "/$source";
+  }
+  if (!strstr($destination, ':')) {
+    $destination = DRUSH_DRUPAL_ROOT. "/$destination";
+  }
+  
+  // Prompt for confirmation. This is destructive.
+  if (!DRUSH_SIMULATE) {
+    drush_print(t("You will destroy data from !target and replace with data from !source", array('!source' => $source, '!target' => $destination)));
+    if (!drush_confirm(t('Do you really want to continue?'))) {
+      drush_die('Aborting.');
+    }
+  }
+  
+  $options = '-az';
+  $exec = "rsync -e ssh $options --exclude \"*.svn*\" $source $destination";
+  if (DRUSH_VERBOSE) {
+    // the drush_op() will be verbose about the command that gets executed.
+    $options .= 'v';
+  }
+
+  return drush_op('system', $exec) !== FALSE;
+}
+/**
+ * Displays the most recent watchdog log messages (default: 10 messages).
+ */
+function drush_tools_watchdog_show($limit = 10, $type = NULL) {
+  $severities = array(WATCHDOG_NOTICE => t('notice'), WATCHDOG_WARNING => t('warning'), WATCHDOG_ERROR => t('error'));
+
+  $sql = 'SELECT w.*, u.name, u.uid FROM {watchdog} w INNER JOIN {users} u ON w.uid = u.uid ORDER BY w.wid DESC';
+  $result = (!empty($type) ?
+    db_query_range($sql . " WHERE w.type = '%s'", $type, 0, (int)$limit) :
+    db_query_range($sql, 0, (int)$limit));
+  
+
+  $rows = array();
+  module_load_include('inc', 'dblog', 'dblog.admin');
+  while ($watchdog = db_fetch_object($result)) {
+    $rows[] = array(
+      format_date($watchdog->timestamp, 'small'),
+      $severities[$watchdog->severity],
+      t($watchdog->type),
+      truncate_utf8(decode_entities(strtr($watchdog->message, unserialize($watchdog->variables))), 68, FALSE, FALSE),
+      theme('username', $watchdog),
+    );
+  }
+
+  if (count($rows) == 0) {
+    drush_die(t('No log messages available.'));
+  }
+  drush_verbose(t('Last !count watchdog log messages:', array('!count' => $limit)));
+
+  array_unshift($rows, array(t('Date'), t('Severity'), t('Type'), t('Message'), t('User')));
+  drush_print_table($rows, 2, TRUE);
+}
+
+/**
+ * Deletes all log messages of a certain type from the watchdog log
+ * (default: all).
+ */
+function drush_tools_watchdog_delete($type = NULL) {
+  if ($type == "all") {
+    drush_op('db_query', 'DELETE FROM {watchdog}'); // indiscriminately delete all
+    drush_print(t('Deleted !n rows.', array('!n' => db_affected_rows())));
+  }
+  elseif (!empty($type)) {
+    drush_op('db_query', 'DELETE FROM {watchdog} WHERE type = \'%s\'', $type);
+    drush_print(t('Deleted !n rows.', array('!n' => db_affected_rows())));
+  }
+  else {
+    drush_print(t('Please specify a message type, or "all" to delete all messages.'));
+  }
+}
+
+function drush_tools_eval($command) {
+  eval($command);
+}
Index: drush_tools/drush_tools.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush_tools/drush_tools.module,v
retrieving revision 1.9.2.6
diff -u -5 -p -u -p -r1.9.2.6 drush_tools.module
--- drush_tools/drush_tools.module	15 Nov 2008 04:39:17 -0000	1.9.2.6
+++ drush_tools/drush_tools.module	20 Nov 2008 02:55:11 -0000
@@ -6,10 +6,12 @@
  *
  * A soup of site utilities.
  *
  */
 
+include_once('drush_tools.drush.inc');
+
 /**
  * Implementation of hook_help().
  */
 function drush_tools_help($section) {
   switch ($section) {
@@ -22,131 +24,5 @@ function drush_tools_help($section) {
         case 'drush:eval':
           return t("Usage: drush eval <code>\n\nRun arbitrary PHP code in the context of Drupal. For example: drush eval \"variable_set('hello', 'world');\".");
   }
 }
 
-/**
- * Implementation of hook_drush_command().
- */
-function drush_tools_drush_command() {
-  $items['cache clear'] = array(
-    'callback' => 'drush_tools_cache_clear',
-    'description' => 'Clear all caches'
-  );
-  $items['cron'] = array(
-    'callback' => 'drush_tools_cron_run',
-    'description' => 'Run cron'
-  );
-  $items['watchdog show'] = array(
-    'callback' => 'drush_tools_watchdog_show',
-    'description' => 'Show the most recent watchdog log messages'
-  );
-  $items['watchdog delete'] = array(
-    'callback' => 'drush_tools_watchdog_delete',
-    'description' => 'Delete all messages of a certain type'
-  );
-  $items['sync'] = array(
-    'callback' => 'drush_tools_sync',
-    'description' => 'Rsync the Drupal tree to/from another server using ssh'
-  );
-  $items['eval'] = array(
-    'callback' => 'drush_tools_eval',
-    'description' => 'Evaluate a command',
-  );
-  return $items;
-}
-
-function drush_tools_cron_run() {
-  drupal_cron_run();
-  drush_print(t('Cron run successfully.'));
-}
-
-function drush_tools_cache_clear() {
-  drupal_flush_all_caches();
-  drush_print(t('Cache cleared.'));
-}
-
-/**
- * Push files from or to the local Drupal install using SSH and RSync
- *
- * @return void
- **/
-function drush_tools_sync($source, $destination) {
-  // Local paths are relative to Drupal root
-  if (!strstr($source, ':')) {
-    $source = DRUSH_DRUPAL_ROOT. "/$source";
-  }
-  if (!strstr($destination, ':')) {
-    $destination = DRUSH_DRUPAL_ROOT. "/$destination";
-  }
-  
-  // Prompt for confirmation. This is destructive.
-  if (!DRUSH_SIMULATE) {
-    drush_print(t("You will destroy data from !target and replace with data from !source", array('!source' => $source, '!target' => $destination)));
-    if (!drush_confirm(t('Do you really want to continue?'))) {
-      drush_die('Aborting.');
-    }
-  }
-  
-  $options = '-az';
-  $exec = "rsync -e ssh $options --exclude \"*.svn*\" $source $destination";
-  if (DRUSH_VERBOSE) {
-    // the drush_op() will be verbose about the command that gets executed.
-    $options .= 'v';
-  }
-
-  return drush_op('system', $exec) !== FALSE;
-}
-/**
- * Displays the most recent watchdog log messages (default: 10 messages).
- */
-function drush_tools_watchdog_show($limit = 10, $type = NULL) {
-  $severities = array(WATCHDOG_NOTICE => t('notice'), WATCHDOG_WARNING => t('warning'), WATCHDOG_ERROR => t('error'));
-
-  $sql = 'SELECT w.*, u.name, u.uid FROM {watchdog} w INNER JOIN {users} u ON w.uid = u.uid ORDER BY w.wid DESC';
-  $result = (!empty($type) ?
-    db_query_range($sql . " WHERE w.type = '%s'", $type, 0, (int)$limit) :
-    db_query_range($sql, 0, (int)$limit));
-  
-
-  $rows = array();
-  module_load_include('inc', 'dblog', 'dblog.admin');
-  while ($watchdog = db_fetch_object($result)) {
-    $rows[] = array(
-      format_date($watchdog->timestamp, 'small'),
-      $severities[$watchdog->severity],
-      t($watchdog->type),
-      truncate_utf8(decode_entities(strtr($watchdog->message, unserialize($watchdog->variables))), 68, FALSE, FALSE),
-      theme('username', $watchdog),
-    );
-  }
-
-  if (count($rows) == 0) {
-    drush_die(t('No log messages available.'));
-  }
-  drush_verbose(t('Last !count watchdog log messages:', array('!count' => $limit)));
-
-  array_unshift($rows, array(t('Date'), t('Severity'), t('Type'), t('Message'), t('User')));
-  drush_print_table($rows, 2, TRUE);
-}
-
-/**
- * Deletes all log messages of a certain type from the watchdog log
- * (default: all).
- */
-function drush_tools_watchdog_delete($type = NULL) {
-  if ($type == "all") {
-    drush_op('db_query', 'DELETE FROM {watchdog}'); // indiscriminately delete all
-    drush_print(t('Deleted !n rows.', array('!n' => db_affected_rows())));
-  }
-  elseif (!empty($type)) {
-    drush_op('db_query', 'DELETE FROM {watchdog} WHERE type = \'%s\'', $type);
-    drush_print(t('Deleted !n rows.', array('!n' => db_affected_rows())));
-  }
-  else {
-    drush_print(t('Please specify a message type, or "all" to delete all messages.'));
-  }
-}
-
-function drush_tools_eval($command) {
-  eval($command);
-}
\ No newline at end of file
