Index: update.php
===================================================================
RCS file: /cvs/drupal/drupal/update.php,v
retrieving revision 1.247
diff -u -r1.247 update.php
--- update.php	7 Jan 2008 19:43:28 -0000	1.247
+++ update.php	15 Jan 2008 13:24:35 -0000
@@ -134,6 +134,13 @@
  * Perform one update and store the results which will later be displayed on
  * the finished page.
  *
+ * An update function can force the current and all later updates for this
+ * module to abort by returning a $ret array with an element like:
+ * $ret['#abort'] = array('success' => FALSE, 'query' => 'What went wrong');
+ * The schema version will not be updated in this case, and all the
+ * aborted updates will continue to appear on update.php as updates that
+ * have not yet been run.
+ *
  * @param $module
  *   The module whose update will be run.
  * @param $number
@@ -142,6 +149,12 @@
  *   The batch context array
  */
 function update_do_one($module, $number, &$context) {
+  // If updates for this module have been aborted
+  // in a previous step, go no further.
+  if (!empty($context['results'][$module]['#abort'])) {
+    return;
+  }
+
   $function = $module .'_update_'. $number;
   if (function_exists($function)) {
     $ret = $function($context['sandbox']);
@@ -158,9 +171,13 @@
   if (!isset($context['results'][$module][$number])) {
     $context['results'][$module][$number] = array();
   }
-  $context['results'][$module][$number] = array_merge($context['results'][$module][$number], $ret);;
+  $context['results'][$module][$number] = array_merge($context['results'][$module][$number], $ret);
 
-  if ($context['finished'] == 1) {
+  if (isset($ret['#abort'])) {
+    $context['results'][$module]['#abort'] = TRUE;
+  }
+  // The schema update is not updated once a module's updates have been aborted.
+  if ($context['finished'] == 1 && !$context['results'][$module]['#abort']) {
     // Update the installed version
     drupal_set_installed_schema_version($module, $number);
   }
@@ -317,19 +334,21 @@
     foreach ($_SESSION['update_results'] as $module => $updates) {
       $output .= '<h3>'. $module .' module</h3>';
       foreach ($updates as $number => $queries) {
-        $output .= '<h4>Update #'. $number .'</h4>';
-        $output .= '<ul>';
-        foreach ($queries as $query) {
-          if ($query['success']) {
-            $output .= '<li class="success">'. $query['query'] .'</li>';
+        if ($number != '#abort') {
+          $output .= '<h4>Update #'. $number .'</h4>';
+          $output .= '<ul>';
+          foreach ($queries as $query) {
+            if ($query['success']) {
+              $output .= '<li class="success">'. $query['query'] .'</li>';
+            }
+            else {
+              $output .= '<li class="failure"><strong>Failed:</strong> '. $query['query'] .'</li>';
+            }
           }
-          else {
-            $output .= '<li class="failure"><strong>Failed:</strong> '. $query['query'] .'</li>';
+          if (!count($queries)) {
+            $output .= '<li class="none">No queries</li>';
           }
         }
-        if (!count($queries)) {
-          $output .= '<li class="none">No queries</li>';
-        }
         $output .= '</ul>';
       }
     }
