Index: install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.233
diff -u -p -r1.233 install.php
--- install.php	10 Jan 2010 00:56:32 -0000	1.233
+++ install.php	10 Jan 2010 20:32:22 -0000
@@ -1505,7 +1505,7 @@ function _install_module_batch($module, 
   // loaded by drupal_bootstrap in subsequent batch requests, and other
   // modules possibly depending on it can safely perform their installation
   // steps.
-  module_enable(array($module));
+  module_enable(array($module), FALSE);
   $context['results'][] = $module;
   $context['message'] = st('Installed %module module.', array('%module' => $module_name));
 }
@@ -1711,7 +1711,7 @@ function install_configure_form_submit($
 
   // Enable update.module if this option was selected.
   if ($form_state['values']['update_status_module'][1]) {
-    drupal_install_modules(array('update'));
+    module_enable(array('update'), FALSE);
 
     // Add the site maintenance account's email address to the list of
     // addresses to be notified when updates are available, if selected.
Index: includes/install.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/install.inc,v
retrieving revision 1.123
diff -u -p -r1.123 install.inc
--- includes/install.inc	9 Jan 2010 23:03:21 -0000	1.123
+++ includes/install.inc	10 Jan 2010 20:32:22 -0000
@@ -536,52 +536,6 @@ function drupal_verify_profile($install_
 }
 
 /**
- * Calls the install function for a given list of modules.
- *
- * @param $module_list
- *   The modules to install.
- * @param $disable_modules_installed_hook
- *   Normally just testing wants to set this to TRUE.
- * 
- * @return
- *   TRUE if installation was attempted, FALSE if one or more dependencies are
- *   missing.
- */
-function drupal_install_modules($module_list = array(), $disable_modules_installed_hook = FALSE) {
-  $files = system_rebuild_module_data();
-  $module_list = array_flip(array_values($module_list));
-  do {
-    $moved = FALSE;
-    foreach ($module_list as $module => $weight) {
-      $file = $files[$module];
-      if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) {
-        foreach ($file->info['dependencies'] as $dependency) {
-          if (!isset($module_list[$dependency])) {
-            if (!isset($files[$dependency])) {
-              // A dependency was not found, abort installation.
-              return FALSE;
-            }
-            elseif (!$files[$dependency]->status) {
-              // Add dependencies to $module_list and install them first.
-              $module_list[$dependency] = $weight - 1;
-              $moved = TRUE;
-            }
-          }
-          elseif ($module_list[$module] < $module_list[$dependency] +1) {
-            $module_list[$module] = $module_list[$dependency] +1;
-            $moved = TRUE;
-          }
-        }
-      }
-    }
-  } while ($moved);
-  asort($module_list);
-  $module_list = array_keys($module_list);
-  module_enable($module_list, $disable_modules_installed_hook);
-  return TRUE;
-}
-
-/**
  * Callback to install an individual install profile module.
  *
  * Used during installation to install modules one at a time and then
Index: includes/module.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/module.inc,v
retrieving revision 1.178
diff -u -p -r1.178 module.inc
--- includes/module.inc	7 Jan 2010 04:54:18 -0000	1.178
+++ includes/module.inc	10 Jan 2010 20:32:22 -0000
@@ -287,10 +287,52 @@ function module_load_all_includes($type,
  *
  * @param $module_list
  *   An array of module names.
+ * @param $check_dependencies
+ *   If TRUE, dependencies will be added and enabled in the correct order.
+ *   Set to FALSE to use $module_list as-is.
  * @param $disable_modules_installed_hook
  *   Normally just testing wants to set this to TRUE.
+ * @return
+ *   FALSE if one or more dependencies are missing, TRUE otherwise.
  */
-function module_enable($module_list, $disable_modules_installed_hook = FALSE) {
+function module_enable($module_list, $check_dependencies = TRUE, $disable_modules_installed_hook = FALSE) {
+  if ($check_dependencies) {
+    // Get all module data so we can find dependencies and sort.
+    $module_data = system_rebuild_module_data();
+    // Create an associative array with weights as values.
+    $module_list = array_flip(array_values($module_list));
+
+    while (list($module) = each($module_list)) {
+      if (!isset($module_data[$module])) {
+        // This module is not found in the filesystem, abort.
+        return FALSE;
+      }
+      if ($module_data[$module]->status) {
+        // Skip already enabled modules.
+        unset($module_list[$module]);
+        continue;
+      }
+      $module_list[$module] = $module_data[$module]->sort;
+
+      // Add dependencies to the list, with a placeholder weight.
+      // The new modules will be processed as the while loop continues.
+      foreach ($module_data[$module]->info['dependencies'] as $dependency) {
+        if (!isset($module_list[$dependency])) {
+          $module_list[$dependency] = 0;
+        }
+      }
+    }
+
+    if (!$module_list) {
+      // Nothing to do. All modules already enabled.
+      return TRUE;
+    }
+
+    // Sort the module list by pre-calculated weights.
+    arsort($module_list);
+    $module_list = array_keys($module_list);
+  }
+
   $invoke_modules = array();
 
   // Try to install the enabled modules and collect which were installed.
@@ -328,6 +370,7 @@ function module_enable($module_list, $di
     if (!$disable_modules_installed_hook && !empty($modules_installed)) {
       module_invoke_all('modules_installed', $modules_installed);
     }
+    system_update_bootstrap_status();
   }
 
   foreach ($invoke_modules as $module) {
@@ -346,6 +389,8 @@ function module_enable($module_list, $di
     // enabled.
     module_invoke_all('modules_enabled', $invoke_modules);
   }
+
+  return TRUE;
 }
 
 /**
@@ -353,9 +398,41 @@ function module_enable($module_list, $di
  *
  * @param $module_list
  *   An array of module names.
- */
-function module_disable($module_list) {
+ * @param $check_dependents
+ *   If TRUE, dependents will be added and disabled in the correct order.
+ *   Set to FALSE to use $module_list as-is.
+ */
+function module_disable($module_list, $check_dependents = TRUE) {
+  if ($check_dependencies) {
+    // Get all module data so we can find dependents and sort.
+    $module_data = system_rebuild_module_data();
+    // Create an associative array with weights as values.
+    $module_list = array_flip(array_values($module_list));
+
+    while (list($module) = each($module_list)) {
+      if (!isset($module_data[$module]) || !$module_data[$module]->status) {
+        // This module doesn't exist or is already disabled, skip it.
+        unset($module_list[$module]);
+        continue;
+      }
+      $module_list[$module] = $module_data[$module]->sort;
+
+      // Add dependent modules to the list, with a placeholder weight.
+      // The new modules will be processed as the while loop continues.
+      foreach ($module_data[$module]->required_by as $dependent => $dependent_data) {
+        if (!isset($module_list[$dependent]) && !strstr($module_data[$dependent]->filename, '.profile')) {
+          $module_list[$dependent] = 0;
+        }
+      }
+    }
+
+    // Sort the module list by pre-calculated weights.
+    asort($module_list);
+    $module_list = array_keys($module_list);
+  }
+
   $invoke_modules = array();
+
   foreach ($module_list as $module) {
     if (module_exists($module)) {
       // Check if node_access table needs rebuilding.
@@ -385,6 +462,7 @@ function module_disable($module_list) {
     module_invoke_all('modules_disabled', $invoke_modules);
     // Update the registry to remove the newly-disabled module.
     registry_update();
+    system_update_bootstrap_status();
   }
 
   // If there remains no more node_access module, rebuilding will be
Index: modules/field/tests/field.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field.test,v
retrieving revision 1.10
diff -u -p -r1.10 field.test
--- modules/field/tests/field.test	26 Dec 2009 16:50:08 -0000	1.10
+++ modules/field/tests/field.test	10 Jan 2010 20:32:23 -0000
@@ -2253,7 +2253,7 @@ class FieldCrudTestCase extends FieldTes
     $field = field_read_field($field_name);
     $this->assertTrue($field_definition <= $field, t('The field was properly read.'));
 
-    module_disable($modules);
+    module_disable($modules, FALSE);
 
     $fields = field_read_fields(array('field_name' => $field_name), array('include_inactive' => TRUE));
     $this->assertTrue(isset($fields[$field_name]) && $field_definition < $field, t('The field is properly read when explicitly fetching inactive fields.'));
@@ -2265,7 +2265,7 @@ class FieldCrudTestCase extends FieldTes
       $this->assertTrue(empty($field), t('%modules disabled. The field is marked inactive.', array('%modules' => implode(', ', $modules))));
 
       $module = array_shift($modules);
-      module_enable(array($module));
+      module_enable(array($module), FALSE);
     }
 
     // Check that the field is active again after all modules have been
Index: modules/simpletest/drupal_web_test_case.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/drupal_web_test_case.php,v
retrieving revision 1.189
diff -u -p -r1.189 drupal_web_test_case.php
--- modules/simpletest/drupal_web_test_case.php	9 Jan 2010 21:54:01 -0000	1.189
+++ modules/simpletest/drupal_web_test_case.php	10 Jan 2010 20:32:23 -0000
@@ -1136,18 +1136,18 @@ class DrupalWebTestCase extends DrupalTe
 
     $this->preloadRegistry();
 
-    // Include the default profile
+    // Include the default profile.
     variable_set('install_profile', 'standard');
     $profile_details = install_profile_info('standard', 'en');
 
     // Install the modules specified by the default profile.
-    drupal_install_modules($profile_details['dependencies'], TRUE);
+    module_enable($profile_details['dependencies'], FALSE, TRUE);
 
     drupal_static_reset('_node_types_build');
 
     if ($modules = func_get_args()) {
       // Install modules needed for this test.
-      drupal_install_modules($modules, TRUE);
+      module_enable($modules, TRUE, TRUE);
     }
 
     // Because the schema is static cached, we need to flush
@@ -1158,7 +1158,7 @@ class DrupalWebTestCase extends DrupalTe
 
     // Run default profile tasks.
     $install_state = array();
-    drupal_install_modules(array('standard'), TRUE);
+    module_enable(array('standard'), FALSE, TRUE);
 
     // Rebuild caches.
     node_types_rebuild();
Index: modules/simpletest/tests/module.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/module.test,v
retrieving revision 1.18
diff -u -p -r1.18 module.test
--- modules/simpletest/tests/module.test	5 Jan 2010 18:00:14 -0000	1.18
+++ modules/simpletest/tests/module.test	10 Jan 2010 20:32:23 -0000
@@ -37,7 +37,7 @@ class ModuleUnitTest extends DrupalWebTe
     $this->assertModuleList($module_list, t('Standard profile'));
 
     // Try to install a new module.
-    drupal_install_modules(array('contact'));
+    module_enable(array('contact'));
     $module_list[] = 'contact';
     sort($module_list);
     $this->assertModuleList($module_list, t('After adding a module'));
@@ -101,25 +101,25 @@ class ModuleUnitTest extends DrupalWebTe
   }
 
   /**
-   * Test drupal_install_modules() and dependency resolution.
+   * Test dependency resolution.
    */
-  function testDrupalInstallModules() {
-    drupal_install_modules(array('module_test'));
+  function testDependencyResolution() {
+    module_enable(array('module_test'), FALSE);
     $this->assertTrue(module_exists('module_test'), t('Test module is enabled.'));
 
     // First, create a fake missing dependency. Forum depends on poll, which
     // depends on a made-up module, foo. Nothing should be installed.
     variable_set('dependency_test', 'missing dependency');
-    $result = drupal_install_modules(array('forum'));
-    $this->assertFalse($result, t('drupal_install_modules() returns FALSE if dependencies are missing.'));
-    $this->assertFalse(module_exists('forum'), t('drupal_install_modules() aborts if dependencies are missing.'));
+    $result = module_enable(array('forum'));
+    $this->assertFalse($result, t('module_enable() returns FALSE if dependencies are missing.'));
+    $this->assertFalse(module_exists('forum'), t('module_enable() aborts if dependencies are missing.'));
 
-    // Now, fix the missing dependency. drupal_install_modules() should work.
+    // Now, fix the missing dependency. module_enable() should work.
     variable_set('dependency_test', 'dependency');
-    $result = drupal_install_modules(array('forum'));
-    $this->assertTrue($result, t('drupal_install_modules() returns the correct value.'));
+    $result = module_enable(array('forum'));
+    $this->assertTrue($result, t('module_enable() returns the correct value.'));
     // Verify that the fake dependency chain was installed.
-    $this->assertTrue(module_exists('poll') && module_exists('php'), t('Dependency chain was installed by drupal_install_modules().'));
+    $this->assertTrue(module_exists('poll') && module_exists('php'), t('Dependency chain was installed by module_enable().'));
     // Finally, verify that the original module was installed.
     $this->assertTrue(module_exists('forum'), t('Module installation with unlisted dependencies succeeded.'));
   }
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.248
diff -u -p -r1.248 system.admin.inc
--- modules/system/system.admin.inc	9 Jan 2010 23:03:21 -0000	1.248
+++ modules/system/system.admin.inc	10 Jan 2010 20:32:24 -0000
@@ -1207,7 +1207,7 @@ function system_modules_submit($form, &$
       $sort[$module] = $files[$module]->sort;
     }
     array_multisort($sort, $modules_to_be_enabled);
-    module_enable($modules_to_be_enabled);
+    module_enable($modules_to_be_enabled, FALSE);
   }
   // Disable the modules that need disabling.
   if (!empty($disable_modules)) {
@@ -1229,7 +1229,7 @@ function system_modules_submit($form, &$
       $sort[$module] = $files[$module]->sort;
     }
     array_multisort($sort, $new_modules);
-    drupal_install_modules($new_modules);
+    module_enable($new_modules, FALSE);
   }
 
   $current_module_list = module_list(TRUE);
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.440
diff -u -p -r1.440 system.install
--- modules/system/system.install	9 Jan 2010 23:15:26 -0000	1.440
+++ modules/system/system.install	10 Jan 2010 20:32:25 -0000
@@ -2082,8 +2082,7 @@ function system_update_7018() {
  */
 function system_update_7020() {
   $module_list = array('field_sql_storage', 'field');
-  drupal_install_modules($module_list);
-  module_enable($module_list);
+  module_enable($module_list, FALSE);
 }
 
 /**
@@ -2305,8 +2304,7 @@ function system_update_7027() {
     ->condition('type', 'module')
     ->condition('name', $module_list)
     ->execute();
-  drupal_install_modules($module_list);
-  module_enable($module_list);
+  module_enable($module_list, FALSE);
 }
 
 /**
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.873
diff -u -p -r1.873 system.module
--- modules/system/system.module	10 Jan 2010 00:09:37 -0000	1.873
+++ modules/system/system.module	10 Jan 2010 20:32:25 -0000
@@ -2202,7 +2202,17 @@ function system_rebuild_module_data() {
   ksort($modules);
   system_get_files_database($modules, 'module');
   system_update_files_database($modules, 'module');
-  // Refresh bootstrap status.
+  $modules = _module_build_dependencies($modules);
+  return $modules;
+}
+
+/**
+ * Refresh bootstrap column in the system table.
+ *
+ * This column indicates which modules to load when invoking the boot and exit
+ * hooks.
+ */
+function system_update_bootstrap_status() {
   $bootstrap_modules = array();
   foreach (bootstrap_hooks() as $hook) {
     foreach (module_implements($hook) as $module) {
@@ -2218,8 +2228,6 @@ function system_rebuild_module_data() {
     $query->condition('name', $bootstrap_modules, 'NOT IN');
   }
   $query->execute();
-  $modules = _module_build_dependencies($modules);
-  return $modules;
 }
 
 /**
Index: modules/system/system.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.test,v
retrieving revision 1.102
diff -u -p -r1.102 system.test
--- modules/system/system.test	9 Jan 2010 23:03:21 -0000	1.102
+++ modules/system/system.test	10 Jan 2010 20:32:25 -0000
@@ -208,7 +208,7 @@ class ModuleDependencyTestCase extends M
     $this->assert(count($checkbox) == 1, t('Checkbox for the module is disabled.'));
 
     // Force enable the system_dependencies_test module.
-    module_enable(array('system_dependencies_test'));
+    module_enable(array('system_dependencies_test'), FALSE);
 
     // Verify that the module is forced to be disabled when submitting
     // the module page.
