cvs diff: Diffing modules/update
Index: modules/update/update.manager.inc
===================================================================
RCS file: /Users/wright/drupal/local_repo/drupal/modules/update/update.manager.inc,v
retrieving revision 1.27
diff -u -p -r1.27 update.manager.inc
--- modules/update/update.manager.inc	1 Dec 2010 00:23:36 -0000	1.27
+++ modules/update/update.manager.inc	1 Dec 2010 05:16:35 -0000
@@ -557,11 +557,16 @@ function update_manager_install_form_sub
   // Unfortunately, we can only use the directory name for this. :(
   $project = drupal_substr($files[0], 0, -1);
 
-  try {
-    update_manager_archive_verify($project, $local_cache, $directory);
-  }
-  catch (Exception $e) {
-    form_set_error($field, $e->getMessage());
+  $archive_errors = update_manager_archive_verify($project, $local_cache, $directory);
+  if (!empty($archive_errors)) {
+    form_set_error($field, array_shift($archive_errors));
+    // @todo: Fix me in D8: We need a way to set multiple errors on the same
+    // form element and have all of them appear!
+    if (!empty($archive_errors)) {
+      foreach ($archive_errors as $key => $message) {
+        drupal_set_message($message, 'error');
+      }
+    }
     return;
   }
 
@@ -682,15 +687,13 @@ function update_manager_archive_extract(
  * @param string $directory
  *   The directory that the archive was extracted into.
  *
- * @return void
- * @throws Exception on failure.
+ * @return array
+ *   An array of error messages to display if the archive was invalid. If
+ *   there are no errors, it will be an empty array.
  *
  */
 function update_manager_archive_verify($project, $archive_file, $directory) {
-  $failures = module_invoke_all('verify_update_archive', $project, $archive_file, $directory);
-  if (!empty($failures)) {
-    throw new Exception(t('Unable to extract %file', array('%file' => $archive_file)));
-  }
+  return module_invoke_all('verify_update_archive', $project, $archive_file, $directory);
 }
 
 /**
@@ -770,11 +773,11 @@ function update_manager_batch_project_ge
   }
 
   // Verify it.
-  try {
-    update_manager_archive_verify($project, $local_cache, $extract_directory);
-  }
-  catch (Exception $e) {
-    $context['results']['errors'][$project] = $e->getMessage();
+  $archive_errors = update_manager_archive_verify($project, $local_cache, $extract_directory);
+  if (!empty($archive_errors)) {
+    foreach ($archive_errors as $key => $message) {
+      $context['results']['errors']["$project-$key"] = $message;
+    }
     return;
   }
 
Index: modules/update/update.module
===================================================================
RCS file: /Users/wright/drupal/local_repo/drupal/modules/update/update.module,v
retrieving revision 1.70
diff -u -p -r1.70 update.module
--- modules/update/update.module	6 Oct 2010 13:36:30 -0000	1.70
+++ modules/update/update.module	1 Dec 2010 06:34:05 -0000
@@ -641,6 +641,76 @@ function theme_update_last_check($variab
 }
 
 /**
+ * Implements hook_verify_update_archive().
+ *
+ * First, we ensure that the archive isn't a copy of Drupal core, which the
+ * Update manager does not yet support. @see http://drupal.org/node/606592
+ *
+ * Then, we make sure that every module or theme included in the archive has a
+ * .info file, and that the .info file claims the code is compatible with
+ * Drupal 7.
+ *
+ * @see drupal_system_listing()
+ * @see _system_rebuild_modules()
+ */
+function update_verify_update_archive($project, $archive_file, $directory) {
+  // Make sure this isn't a tarball of Drupal core.
+  if (
+    file_exists("$directory/$project/index.php")
+    && file_exists("$directory/$project/update.php")
+    && file_exists("$directory/$project/includes/bootstrap.inc")
+    && file_exists("$directory/$project/modules/node/node.module")
+    && file_exists("$directory/$project/modules/system/system.module")
+  ) {
+    return array(
+      'no-core' => t('Automatic updating of Drupal core is not supported. See the <a href="@upgrade-guide">upgrade guide</a> for information on how to update Drupal core manually.', array('@upgrade-guide' => 'http://drupal.org/upgrade')),
+    );
+  }
+
+  $failures = array();
+
+  $missing_info = array();
+  $files = file_scan_directory("$directory/$project", '/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', array('key' => 'name', 'min_depth' => 0));
+  foreach ($files as $key => $file) {
+    // If it has no info file, set an error.
+    $info_file = dirname($file->uri) . '/' . $file->name . '.info';
+    if (!file_exists($info_file)) {
+      $missing_info[] = $file->filename;
+    }
+  }
+  if (!empty($missing_info)) {
+    $failures['no info file'] = format_plural(
+      count($missing_info),
+      '%archive_file contains %names which is missing an info file.',
+      '%archive_file contains the following modules which are missing info files: %names',
+      array('%archive_file' => basename($archive_file), '%names' => implode(', ', $missing_info))
+    );
+  }
+
+  $incompatible = array();
+  $files = file_scan_directory("$directory/$project", '/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info/', array('key' => 'name', 'min_depth' => 0));
+  foreach ($files as $key => $file) {
+    // Get the .info file for the module or theme this file belongs to.
+    $info = drupal_parse_info_file($file->uri);
+
+    // If the module or theme is incompatible with Drupal core, set an error.
+    if (empty($info['core']) || $info['core'] != DRUPAL_CORE_COMPATIBILITY) {
+      $incompatible[] = $info['name'];
+    }
+  }
+
+  if (!empty($incompatible)) {
+    $failures['incompatible'] = format_plural(
+      count($incompatible),
+      '%archive_file contains a version of %names which is not compatible with Drupal !version.',
+      '%archive_file contains versions of the following modules or themes which are not compatible with Drupal !version: %names',
+      array('!version' => DRUPAL_CORE_COMPATIBILITY, '%archive_file' => basename($archive_file), '%names' => implode(', ', $incompatible))
+    );
+  }
+  return $failures;
+}
+
+/**
  * @defgroup update_status_cache Private update status cache system
  * @{
  *
cvs diff: Diffing modules/update/tests
