? drush-977048.patch
? drush-977048_5.patch
? includes/table.inc
Index: commands/pm/pm.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/pm/pm.drush.inc,v
retrieving revision 1.153
diff -u -r1.153 pm.drush.inc
--- commands/pm/pm.drush.inc	6 Dec 2010 21:57:08 -0000	1.153
+++ commands/pm/pm.drush.inc	6 Dec 2010 22:40:24 -0000
@@ -24,14 +24,9 @@
 define('DRUSH_PM_REQUESTED_CURRENT', 102);
 
 /**
- * User requested version already installed.
- */
-define('DRUSH_PM_NO_VERSION', 103);
-
-/**
  * User requested version not found.
  */
-define('DRUSH_PM_REQUESTED_NOT_FOUND', 104);
+define('DRUSH_PM_REQUESTED_NOT_FOUND', 103);
 
 /**
  * Implementation of hook_drush_help().
@@ -323,6 +318,59 @@
 }
 
 /**
+ * Obtain an array of installed projects off the extensions available.
+ *
+ * A project is considered to be 'enabled' when any of its extensions is
+ * enabled.
+ *
+ * @return
+ *   Array of installed projects with info of version, status and provided
+* extensions.
+ */
+function drush_get_projects() {
+  $projects = array('drupal' => array('version' => VERSION));
+  $extensions = drush_get_extensions();
+  foreach ($extensions as $extension) {
+    // The project name is not available in this cases:
+    // 1. the extension is part of drupal core.
+    // 2. the project was checked out from CVS/git and cvs_deploy/git_deploy
+    // is not installed.
+    // 3. it is not a project hosted in drupal.org.
+    if (!isset($extension->info['project'])) {
+      if ($extension->info['version'] == VERSION) {
+        $project = 'drupal';
+      }
+      else {
+        if (is_dir(dirname($extension->filename) . '/CVS') && (!module_exists('cvs_deploy'))) {
+          drush_log(dt('Extension !extension is fetched from cvs. Ignoring.', array('!extension' => $extension->name)), 'warning');
+       }
+        elseif (is_dir(dirname($extension->filename) . '/.git') && (!module_exists('git_deploy'))) {
+          drush_log(dt('Extension !extension is fetched from git. Ignoring.', array('!extension' => $extension->name)), 'warning');
+        }
+        continue;
+      }
+    }
+    else {
+        $project = $extension->info['project'];
+    }
+    // Create/update the project in $projects with the project data.
+    if (!isset($projects[$project])) {
+      $projects[$project] = array(
+        'version' => $extension->info['version'],
+        'status' => $extension->status,
+        'extensions' => array(),
+      );
+    }
+    elseif ($extension->status != 0) {
+      $projects[$project]['status'] = $extension->status;
+    }
+    $projects[$project]['extensions'][] = $extension->name;
+  }
+
+  return $projects;
+}
+
+/**
  * @} End of "defgroup extensions".
  */
 
@@ -981,7 +1029,18 @@
 /**
  * Obtain releases for a project's xml as returned by the update service.
  */
-function _drush_pm_get_releases_from_xml($xml) {
+function _drush_pm_get_releases_from_xml($xml, $project) {
+  // If bootstraped, we can obtain which is the installed release of a project.
+  static $installed_projects = FALSE;
+  if (!$installed_projects) {
+    if (drush_get_context('DRUSH_BOOTSTRAP_PHASE') >= DRUSH_BOOTSTRAP_DRUPAL_FULL) {
+      $installed_projects = drush_get_projects();
+    }
+    else {
+      $installed_projects = array();
+    }
+  }
+
   foreach (array('title', 'short_name', 'dc:creator', 'api_version', 'recommended_major', 'supported_majors', 'default_major', 'project_status', 'link') as $item) {
     if (array_key_exists($item, $xml)) {
       $value = $xml->xpath($item);
@@ -1032,6 +1091,12 @@
         $statuses[] = "Security";
       }
     }
+    if (isset($installed_projects[$project])) {
+      if ($installed_projects[$project]['version'] == $release_info['version']) {
+         $statuses[] = dt('Installed');
+         $project_info['installed'] = $release_info['version'];
+       }
+    }
     $release_info['release_status'] = $statuses;
     $releases[$release_info['version']] = $release_info;
   }
@@ -1066,7 +1131,7 @@
   // If we are not bootstrapped, then we will extract the release info from
   // the release-history xml.
   else {
-    $project_info = _drush_pm_get_releases_from_xml($xml);
+    $project_info = _drush_pm_get_releases_from_xml($xml, $project);
     $releases = $project_info['releases'];
   }
   return $releases;
@@ -1177,11 +1242,8 @@
     }
   }
 
-  // Info on extensions present in the bootstrapped site will be used to
-  // identify if any project release is installed.
-  $extension_info = drush_get_extensions();
-
   // Iterate the projects to collect relevant information.
+  $installed_projects = drush_get_projects();
   foreach ($info as $key => $project) {
     // Find latest and recommended versions based on the recommended
     // major version.
@@ -1224,13 +1286,8 @@
       if ($release['version_extra'] == 'dev') {
         $status[] = dt('Development');
       }
-      // #TODO# Note here we suffer the project<->package-name problem:
-      // Following only works for modules/themes with name with
-      // drupal.org's project name (zen->zen but not for cck->content).
-      // See _drush_pm_releasenotes() for an option to get that info
-      // from update's project data.
-      if (isset($extension_info[$key])) {
-        if ($extension_info[$key]->info['version'] == $version) {
+      if (isset($installed_projects[$key])) {
+        if ($installed_projects[$key]['version'] == $version) {
           $status[] = dt('Installed');
           $info[$key]['installed'] = $version;
         }
@@ -1282,16 +1339,6 @@
 
   foreach ($info as $key => $project) {
     $selected_versions = array();
-    // #TODO# project<->package-name problem. See _drush_pm_get_releases().
-    if (!isset($project['installed']) && (drush_get_context('DRUSH_BOOTSTRAP_PHASE') >= DRUSH_BOOTSTRAP_DRUPAL_FULL)) {
-      // Installed package's version (e.g. cck) is detected by
-      // _drush_pm_get_releases(). Attempted to obtain information
-      // about it from update_cache.
-      $cache_project_info = _update_cache_get('update_project_projects');
-      if (isset($cache_project_info->data[$key])) {
-        $project['installed'] = $cache_project_info->data[$key]['info']['version'];
-      }
-    }
     // If the request included version, only show its release notes.
     if (isset($requests[$key]['version'])) {
       $selected_versions[] = $requests[$key]['version'];
@@ -1446,6 +1493,13 @@
   if (is_dir($drupal_root . '/' . 'backup')) {
     return drush_set_error('DRUSH_PM_BACKUP_DIR_FORBIDDEN', dt('It\'s a security risk to have a backup folder in your Drupal root. You must move it elsewhere before proceeding.'));
   }
+
+  // Validate package-handler.
+  $package_handler = drush_get_option('package-handler', 'wget');
+  drush_include_engine('package_handler', $package_handler);
+  if (!package_handler_validate()) {
+    return FALSE;
+  }
 }
 
 /**
@@ -1863,6 +1917,13 @@
       drush_log(dt('Switching to --variant=!variant.', array('!variant' => $new_variant)), 'ok');
     }
   }
+  
+  // Validate package-handler.
+  $package_handler = drush_get_option('package-handler', 'wget');
+  drush_include_engine('package_handler', $package_handler);
+  if (!package_handler_validate()) {
+    return FALSE;
+  }
 }
 
 /**
@@ -1892,7 +1953,7 @@
       continue;
     }
 
-    $project_info = _drush_pm_get_releases_from_xml($xml);
+    $project_info = _drush_pm_get_releases_from_xml($xml, $name);
     $info[$name] = $project_info;
   }
   return $info;
Index: commands/pm/updatecode.pm.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/pm/updatecode.pm.inc,v
retrieving revision 1.26
diff -u -r1.26 updatecode.pm.inc
--- commands/pm/updatecode.pm.inc	6 Dec 2010 19:26:24 -0000	1.26
+++ commands/pm/updatecode.pm.inc	6 Dec 2010 22:40:24 -0000
@@ -31,17 +31,18 @@
 
   // Preprocess requested projects.
   if (!empty($requests)) {
-    // Check requests are installed and enabled projects and force
-    // update projects where a specific version is requested.
+    // 1. Check requests are installed projects with any extension enabled.
+    // 2. Explicitly set the version to update a project to if a specific
+    // version is requested.
+    $projects = drush_get_projects();
     foreach ($requests as $name => $request) {
-      if (!isset($update_info[$name])) {
-        // Catch projects with no version data (common for CVS checkouts
-        // if you don't have CVS deploy installed).
-        $update_info[$name] = array(
-          'title' => $name,
-          'existing_version' => 'Unknown',
-          'status'=> DRUSH_PM_NO_VERSION,
-        );
+       if (!isset($projects[$name])) {
+        drush_set_error('DRUSH_PM_PROJECT_IS_NOT_INSTALLED', dt('Project !project is not installed so it can\'t be updated.', array('!project' => $name)));
+        unset($requests[$name]);
+      }
+      else if ($projects[$name]['status'] == 0) {
+        drush_set_error('DRUSH_PM_PROJECT_NOT_UPDATEABLE', dt('Project !project has no enabled extensions so it can\'t be updated.', array('!project' => $name)));
+        unset($requests[$name]);
       }
       else if (!empty($request['version'])) {
         // Match the requested release
@@ -59,6 +60,10 @@
         $update_info[$name]['candidate_version'] = $release['version'];
       }
     }
+    // None of the requested projects is valid?
+    if (empty($requests)) {
+      return FALSE;
+    }
   }
 
   // Table headers.
@@ -67,6 +72,15 @@
   // Process releases, notifying user of status and building a list of proposed updates
   $updateable = pm_project_filter($update_info, $rows, $security_only);
 
+  // If specific project updates were requested then remove releases for all others
+  if (!empty($requests)) {
+    foreach ($updateable as $name => $project) {
+      if (!isset($requests[$name])) {
+        unset($updateable[$name]);
+      }
+    }
+  }
+
   // Pipe preparation.
   if (drush_get_context('DRUSH_PIPE')) {
     $pipe = "";
@@ -88,15 +102,6 @@
   drush_print_table($rows, TRUE);
   drush_print();
 
-  // If specific project updates were requested then remove releases for all others
-  if (!empty($requests)) {
-    foreach ($updateable as $name => $project) {
-      if (!isset($requests[$name])) {
-        unset($updateable[$name]);
-      }
-    }
-  }
-
   // If there are any locked projects that were not requested, then remove them
   if (!empty($locked_list)) {
     foreach ($updateable as $name => $project) {
@@ -429,9 +434,6 @@
       case DRUSH_PM_REQUESTED_CURRENT:
         $status = dt('Specified version already installed');
         break;
-      case DRUSH_PM_NO_VERSION:
-        $status = dt('No version information found (if you have a CVS checkout you should install CVS Deploy module)');
-        break;
       case DRUSH_PM_REQUESTED_NOT_FOUND:
         $status = dt('Specified version not found');
         break;
Index: commands/pm/package_handler/cvs.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/pm/package_handler/cvs.inc,v
retrieving revision 1.21
diff -u -r1.21 cvs.inc
--- commands/pm/package_handler/cvs.inc	13 Oct 2010 19:48:58 -0000	1.21
+++ commands/pm/package_handler/cvs.inc	6 Dec 2010 22:40:24 -0000
@@ -6,6 +6,26 @@
  */
 
 /**
+ * Validate this package handler can run.
+ */
+function package_handler_validate() {
+  // Check cvs command exists. Disable possible output.
+  $debug = drush_get_context('DRUSH_DEBUG');
+  drush_set_context('DRUSH_DEBUG', FALSE);
+  $success = drush_shell_exec('cvs --version');
+  drush_set_context('DRUSH_DEBUG', $debug);
+  if (!$success) {
+    return drush_set_error('DRUSH_SHELL_COMMAND_NOT_FOUND', dt('cvs executable not found.'));
+  }
+  // Check cvs_deploy is enabled. Only for bootstrapped sites.
+  if (drush_get_context('DRUSH_BOOTSTRAP_PHASE') >= DRUSH_BOOTSTRAP_DRUPAL_FULL) {
+    if (!module_exists('cvs_deploy')) {
+      drush_log(dt('cvs package handler needs cvs_deploy module enabled to work properly.'), 'warning');
+    }
+  }
+}
+
+/**
  * Install a project.
  *
  * @param $project The project array with name, base and full (final) paths.
Index: commands/pm/package_handler/git_drupalorg.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/pm/package_handler/git_drupalorg.inc,v
retrieving revision 1.3
diff -u -r1.3 git_drupalorg.inc
--- commands/pm/package_handler/git_drupalorg.inc	4 Dec 2010 14:20:02 -0000	1.3
+++ commands/pm/package_handler/git_drupalorg.inc	6 Dec 2010 22:40:25 -0000
@@ -6,6 +6,26 @@
  */
 
 /**
+ * Validate this package handler can run.
+ */
+function package_handler_validate() {
+  // Check git command exists. Disable possible output.
+  $debug = drush_get_context('DRUSH_DEBUG');
+  drush_set_context('DRUSH_DEBUG', FALSE);
+  $success = drush_shell_exec('git --version');
+  drush_set_context('DRUSH_DEBUG', $debug);
+  if (!$success) {
+    return drush_set_error('DRUSH_SHELL_COMMAND_NOT_FOUND', dt('git executable not found.'));
+  }
+  // Check git_deploy is enabled. Only for bootstrapped sites.
+  if (drush_get_context('DRUSH_BOOTSTRAP_PHASE') >= DRUSH_BOOTSTRAP_DRUPAL_FULL) {
+    if (!module_exists('git_deploy')) {
+      drush_log(dt('git package handler needs git_deploy module enabled to work properly.'), 'warning');
+    }
+  }
+}
+
+/**
  * Install a project.
  *
  * @param $project The project array with name, base and full (final) paths.
Index: commands/pm/package_handler/wget.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/pm/package_handler/wget.inc,v
retrieving revision 1.17
diff -u -r1.17 wget.inc
--- commands/pm/package_handler/wget.inc	24 Nov 2010 12:39:59 -0000	1.17
+++ commands/pm/package_handler/wget.inc	6 Dec 2010 22:40:25 -0000
@@ -6,6 +6,23 @@
  */
 
 /**
+ * Validate this package handler can run.
+ */
+function package_handler_validate() {
+  // Check wget or curl command exists. Disable possible output.
+  $debug = drush_get_context('DRUSH_DEBUG');
+  drush_set_context('DRUSH_DEBUG', FALSE);
+  $success = drush_shell_exec('wget --version');
+  if (!$success) {
+    $success = drush_shell_exec('curl --version');
+  }
+  drush_set_context('DRUSH_DEBUG', $debug);
+  if (!$success) {
+    return drush_set_error('DRUSH_SHELL_COMMAND_NOT_FOUND', dt('wget nor curl executables found.'));
+  }
+}
+
+/**
  * Download a project.
  *
  * @param $request Array with information on the request to download.
Index: includes/drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/drush.inc,v
retrieving revision 1.156
diff -u -r1.156 drush.inc
--- includes/drush.inc	6 Dec 2010 21:57:08 -0000	1.156
+++ includes/drush.inc	6 Dec 2010 22:40:25 -0000
@@ -1034,9 +1034,9 @@
       _drush_shell_exec_output_set($output);
 
       if (drush_get_context('DRUSH_DEBUG')) {
-	foreach ($output as $line) {
+        foreach ($output as $line) {
           drush_print($line, 2);
-	}
+        }
       }
 
       // Exit code 0 means success.
