Index: includes/update.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/update.inc,v
retrieving revision 1.41
diff -u -p -r1.41 update.inc
--- includes/update.inc	31 Mar 2010 19:10:39 -0000	1.41
+++ includes/update.inc	10 Apr 2010 12:52:22 -0000
@@ -1126,16 +1126,10 @@ function update_build_dependency_graph($
   }
 
   // Now add any explicit update dependencies declared by modules.
-  $update_dependencies = update_invoke_all('update_dependencies');
+  $update_dependencies = update_retrieve_dependencies();
   foreach ($graph as $function => $data) {
     if (!empty($update_dependencies[$data['module']][$data['number']])) {
       foreach ($update_dependencies[$data['module']][$data['number']] as $module => $number) {
-        // If we have an explicit dependency on more than one update from a
-        // particular module, choose the highest one, since that contains the
-        // actual direct dependency.
-        if (is_array($number)) {
-          $number = max($number);
-        }
         $dependency = $module . '_update_' . $number;
         $graph[$dependency]['edges'][$function] = TRUE;
         $graph[$dependency]['module'] = $module;
@@ -1184,39 +1178,45 @@ function update_already_performed($modul
 }
 
 /**
- * Invoke an update system hook in all installed modules.
+ * Invoke hook_update_dependencies() in all installed modules.
  *
- * This function is similar to module_invoke_all(), except it does not require
- * that a module be enabled to invoke its hook, only that it be installed. This
- * allows the update system to properly perform updates even on modules that
- * are currently disabled.
- *
- * @param $hook
- *   The name of the hook to invoke.
- * @param ...
- *   Arguments to pass to the hook.
+ * This function is similar to module_invoke_all(), with the main difference
+ * that it does not require a module to be enabled to invoke its hook, only that
+ * it be installed. This allows the update system to properly perform updates
+ * even on modules that are currently disabled.
  *
  * @return
- *   An array of return values of the hook implementations. If modules return
- *   arrays from their implementations, those are merged into one array.
+ *   An array of return values obtained by merging the results of the
+ *   hook_update_dependencies() implementations in all installed modules.
  *
  * @see module_invoke_all()
  */
-function update_invoke_all() {
-  $args = func_get_args();
-  $hook = $args[0];
-  unset($args[0]);
+function update_retrieve_dependencies() {
   $return = array();
-  $modules = db_query("SELECT name FROM {system} WHERE type = 'module' AND schema_version != :schema", array(':schema' => SCHEMA_UNINSTALLED))->fetchCol();
+  // Get a list of installed modules, arranged so that we invoke their hooks in
+  // the same order that module_invoke_all() does.
+  $modules = db_query("SELECT name FROM {system} WHERE type = 'module' AND schema_version != :schema ORDER BY weight ASC, name ASC", array(':schema' => SCHEMA_UNINSTALLED))->fetchCol();
   foreach ($modules as $module) {
-    $function = $module . '_' . $hook;
+    $function = $module . '_update_dependencies';
     if (function_exists($function)) {
-      $result = call_user_func_array($function, $args);
+      $result = $function();
+      // Rather than using array_merge_recursive(), which treats string keys
+      // (the module names) differently from integer keys (the update function
+      // numbers), we explicitly loop through the expected array structure here
+      // so that we can properly merge the array in both cases.
       if (isset($result) && is_array($result)) {
-        $return = array_merge_recursive($return, $result);
-      }
-      elseif (isset($result)) {
-        $return[] = $result;
+        foreach ($result as $module => $module_data) {
+          foreach ($module_data as $update => $update_data) {
+            foreach ($update_data as $module_dependency => $update_dependency) {
+              // If we have an explicit dependency on more than one update from
+              // a particular module, choose the highest one, since that
+              // comprises all previous updates from that module.
+              if (!isset($return[$module][$update][$module_dependency]) || $update_dependency > $return[$module][$update][$module_dependency]) {
+                $return[$module][$update][$module_dependency] = $update_dependency;
+              }
+            }
+          }
+        }
       }
     }
   }
Index: modules/simpletest/tests/update.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/update.test,v
retrieving revision 1.1
diff -u -p -r1.1 update.test
--- modules/simpletest/tests/update.test	3 Feb 2010 18:16:23 -0000	1.1
+++ modules/simpletest/tests/update.test	10 Apr 2010 12:52:22 -0000
@@ -86,3 +86,31 @@ class UpdateDependencyMissingTestCase ex
   }
 }
 
+/**
+ * Tests for the invocation of hook_update_dependencies().
+ */
+class UpdateDependencyHookInvocationTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Update dependency hook invocation',
+      'description' => 'Test that the hook invocation for determining update dependencies works correctly.',
+      'group' => 'Update API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('update_test_1', 'update_test_2');
+    require_once DRUPAL_ROOT . '/includes/update.inc';
+  }
+
+  /**
+   * Test the structure of the array returned by hook_update_dependencies().
+   */
+  function testHookUpdateDependencies() {
+    $update_dependencies = update_retrieve_dependencies();
+    $this->assertTrue($update_dependencies['system'][7000]['update_test_1'] == 7000, t('An update function that has a dependency on two separate modules has the first dependency recorded correctly.'));
+    $this->assertTrue($update_dependencies['system'][7000]['update_test_2'] == 7001, t('An update function that has a dependency on two separate modules has the second dependency recorded correctly.'));
+    $this->assertTrue($update_dependencies['system'][7001]['update_test_1'] == 7002, t('An update function that depends on more than one update from the same module only has the dependency on the higher-numbered update function recorded.'));
+  }
+}
+
Index: modules/simpletest/tests/update_test_1.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/update_test_1.install,v
retrieving revision 1.1
diff -u -p -r1.1 update_test_1.install
--- modules/simpletest/tests/update_test_1.install	3 Feb 2010 18:16:23 -0000	1.1
+++ modules/simpletest/tests/update_test_1.install	10 Apr 2010 12:52:22 -0000
@@ -7,6 +7,33 @@
  */
 
 /**
+ * Implements hook_update_dependencies().
+ */
+function update_test_1_update_dependencies() {
+  // These dependencies are used in combination with those declared in
+  // update_test_2_update_dependencies() for the sole purpose of testing that
+  // the results of hook_update_dependencies() are collected correctly and have
+  // the correct array structure. Therefore, we use updates from system module
+  // (which have already run), so that they will not get in the way of other
+  // tests.
+  $dependencies['system'][7000] = array(
+    // Compare to update_test_2_update_dependencies(), where the same system
+    // module update function is forced to depend on an update function from a
+    // different module. This allows us to test that both dependencies are
+    // correctly recorded.
+    'update_test_1' => 7000,
+  );
+  $dependencies['system'][7001] = array(
+    // Compare to update_test_2_update_dependencies(), where the same system
+    // module update function is forced to depend on a different update
+    // function within the same module. This allows us to test that only the
+    // dependency on the higher-numbered update function is recorded.
+    'update_test_1' => 7002,
+  );
+  return $dependencies;
+}
+
+/**
  * Dummy update_test_1 update 7000.
  */
 function update_test_1_update_7000() {
Index: modules/simpletest/tests/update_test_2.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/update_test_2.install,v
retrieving revision 1.1
diff -u -p -r1.1 update_test_2.install
--- modules/simpletest/tests/update_test_2.install	3 Feb 2010 18:16:23 -0000	1.1
+++ modules/simpletest/tests/update_test_2.install	10 Apr 2010 12:52:22 -0000
@@ -8,11 +8,27 @@
 
 /**
  * Implements hook_update_dependencies().
+ *
+ * @see update_test_1_update_dependencies()
  */
 function update_test_2_update_dependencies() {
+  // Combined with update_test_3_update_dependencies(), we are declaring here
+  // that these two modules run updates in the following order:
+  // 1. update_test_2_update_7000()
+  // 2. update_test_3_update_7000()
+  // 3. update_test_2_update_7001()
+  // 4. update_test_2_update_7002()
   $dependencies['update_test_2'][7001] = array(
     'update_test_3' => 7000,
   );
+
+  $dependencies['system'][7000] = array(
+    'update_test_2' => 7001,
+  );
+  $dependencies['system'][7001] = array(
+    'update_test_1' => 7001,
+  );
+
   return $dependencies;
 }
 
Index: modules/simpletest/tests/update_test_3.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/update_test_3.install,v
retrieving revision 1.1
diff -u -p -r1.1 update_test_3.install
--- modules/simpletest/tests/update_test_3.install	3 Feb 2010 18:16:23 -0000	1.1
+++ modules/simpletest/tests/update_test_3.install	10 Apr 2010 12:52:23 -0000
@@ -8,6 +8,8 @@
 
 /**
  * Implements hook_update_dependencies().
+ *
+ * @see update_test_2_update_dependencies()
  */
 function update_test_3_update_dependencies() {
   $dependencies['update_test_3'][7000] = array(
