Index: install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.176
diff -u -p -r1.176 install.php
--- install.php	2 Jun 2009 06:58:15 -0000	1.176
+++ install.php	6 Jun 2009 08:01:42 -0000
@@ -642,7 +642,7 @@ function install_tasks($profile, $task) 
   // Install profile modules.
   if ($task == 'profile-install') {
     $modules = variable_get('install_profile_modules', array());
-    $files = module_rebuild_cache();
+    $files = system_get_module_data();
     variable_del('install_profile_modules');
     $operations = array();
     foreach ($modules as $module) {
Index: update.php
===================================================================
RCS file: /cvs/drupal/drupal/update.php,v
retrieving revision 1.286
diff -u -p -r1.286 update.php
--- update.php	2 Jun 2009 06:58:15 -0000	1.286
+++ update.php	6 Jun 2009 08:01:42 -0000
@@ -499,8 +499,8 @@ function update_check_incompatibility($n
 
   // Store values of expensive functions for future use.
   if (empty($themes) || empty($modules)) {
-    $themes = _system_theme_data();
-    $modules = module_rebuild_cache();
+    $themes = _system_get_theme_data();
+    $modules = system_get_module_data();
   }
 
   if ($type == 'module' && isset($modules[$name])) {
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.917
diff -u -p -r1.917 common.inc
--- includes/common.inc	3 Jun 2009 02:50:21 -0000	1.917
+++ includes/common.inc	6 Jun 2009 08:01:45 -0000
@@ -4529,10 +4529,10 @@ function drupal_flush_all_caches() {
   // If invoked from update.php, we must not update the theme information in the
   // database, or this will result in all themes being disabled.
   if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') {
-    _system_theme_data();
+    _system_get_theme_data();
   }
   else {
-    system_theme_data();
+    system_get_theme_data();
   }
 
   drupal_theme_rebuild();
Index: includes/install.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/install.inc,v
retrieving revision 1.91
diff -u -p -r1.91 install.inc
--- includes/install.inc	24 May 2009 17:39:30 -0000	1.91
+++ includes/install.inc	6 Jun 2009 08:01:47 -0000
@@ -495,7 +495,7 @@ function drupal_verify_profile($profile,
  *   Normally just testing wants to set this to TRUE.
  */
 function drupal_install_modules($module_list = array(), $disable_modules_installed_hook = FALSE) {
-  $files = module_rebuild_cache();
+  $files = system_get_module_data();
   $module_list = array_flip(array_values($module_list));
   do {
     $moved = FALSE;
@@ -592,7 +592,7 @@ function drupal_install_system() {
     ->execute();
   // Now that we've installed things properly, bootstrap the full Drupal environment
   drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-  module_rebuild_cache();
+  system_get_module_data();
 }
 
 /**
Index: includes/module.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/module.inc,v
retrieving revision 1.142
diff -u -p -r1.142 module.inc
--- includes/module.inc	24 May 2009 17:39:30 -0000	1.142
+++ includes/module.inc	6 Jun 2009 08:01:47 -0000
@@ -76,75 +76,6 @@ function module_list($refresh = FALSE, $
 }
 
 /**
- * Rebuild the database cache of module files.
- *
- * @return
- *   The array of filesystem objects used to rebuild the cache.
- */
-function module_rebuild_cache() {
-  // Get current list of modules, including uninstalled modules.
-  $files = drupal_system_listing('/\.module$/', 'modules', 'name', 0);
-
-  // Extract current files from database.
-  system_get_files_database($files, 'module');
-
-  ksort($files);
-
-  // Set defaults for module info
-  $defaults = array(
-    'dependencies' => array(),
-    'dependents' => array(),
-    'description' => '',
-    'package' => 'Other',
-    'version' => NULL,
-    'php' => DRUPAL_MINIMUM_PHP,
-    'files' => array(),
-  );
-
-  foreach ($files as $filepath => $file) {
-    // Look for the info file.
-    $file->info = drupal_parse_info_file(dirname($file->filepath) . '/' . $file->name . '.info');
-
-    // Skip modules that don't provide info.
-    if (empty($file->info)) {
-      unset($files[$filepath]);
-      continue;
-    }
-    // Merge in defaults and save.
-    $files[$filepath]->info = $file->info + $defaults;
-
-    // Invoke hook_system_info_alter() to give installed modules a chance to
-    // modify the data in the .info files if necessary.
-    drupal_alter('system_info', $files[$filepath]->info, $files[$filepath]);
-
-    // Update the contents of the system table:
-    if (isset($file->status) || (isset($file->old_filepath) && $file->old_filepath != $file->filepath)) {
-      db_update('system')
-        ->fields(array(
-            'info' => serialize($files[$filepath]->info),
-            'name' => $file->name,
-            'filename' => $file->filepath))
-        ->condition('filename', $file->old_filepath)
-        ->execute();
-    }
-    else {
-      // This is a new module.
-      $files[$filepath]->status = 0;
-      db_insert('system')
-        ->fields(array(
-            'name' => $file->name,
-            'info' => serialize($files[$filepath]->info),
-            'type' => 'module',
-            'filename' => $file->filepath,
-            'status' => 0))
-        ->execute();
-    }
-  }
-  $files = _module_build_dependencies($files);
-  return $files;
-}
-
-/**
  * Find dependencies any level deep and fill in required by information too.
  *
  * @param $files
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.493
diff -u -p -r1.493 theme.inc
--- includes/theme.inc	2 Jun 2009 03:57:22 -0000	1.493
+++ includes/theme.inc	6 Jun 2009 08:01:47 -0000
@@ -528,7 +528,7 @@ function list_themes($refresh = FALSE) {
     }
     else {
       // Scan the installation when the database should not be read.
-      $themes = _system_theme_data();
+      $themes = _system_get_theme_data();
     }
 
     foreach ($themes as $theme) {
Index: includes/theme.maintenance.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.maintenance.inc,v
retrieving revision 1.29
diff -u -p -r1.29 theme.maintenance.inc
--- includes/theme.maintenance.inc	28 May 2009 16:44:05 -0000	1.29
+++ includes/theme.maintenance.inc	6 Jun 2009 08:01:47 -0000
@@ -223,7 +223,7 @@ function template_preprocess_maintenance
 
   global $theme;
   // Retrieve the theme data to list all available regions.
-  $theme_data = _system_theme_data();
+  $theme_data = _system_get_theme_data();
   $regions = $theme_data[$theme]->info['regions'];
 
   // Get all region content set with drupal_add_region_content().
Index: modules/help/help.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/help/help.admin.inc,v
retrieving revision 1.8
diff -u -p -r1.8 help.admin.inc
--- modules/help/help.admin.inc	18 Feb 2009 14:28:22 -0000	1.8
+++ modules/help/help.admin.inc	6 Jun 2009 08:01:47 -0000
@@ -47,7 +47,7 @@ function help_page($name) {
 
 function help_links_as_list() {
   $empty_arg = drupal_help_arg();
-  $module_info = module_rebuild_cache();
+  $module_info = system_get_module_data();
 
   $modules = array();
   foreach (module_implements('help', TRUE) as $module) {
Index: modules/simpletest/simpletest.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/simpletest.module,v
retrieving revision 1.52
diff -u -p -r1.52 simpletest.module
--- modules/simpletest/simpletest.module	30 May 2009 11:17:32 -0000	1.52
+++ modules/simpletest/simpletest.module	6 Jun 2009 08:01:47 -0000
@@ -211,7 +211,7 @@ function simpletest_get_all_tests() {
   if (!isset($classes)) {
     require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'simpletest') . '/drupal_web_test_case.php';
     $files = array();
-    foreach (array_keys(module_rebuild_cache()) as $module) {
+    foreach (array_keys(system_get_module_data()) as $module) {
       $module_path = drupal_get_path('module', $module);
       $test = $module_path . "/$module.test";
       if (file_exists($test)) {
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.153
diff -u -p -r1.153 system.admin.inc
--- modules/system/system.admin.inc	5 Jun 2009 05:28:28 -0000	1.153
+++ modules/system/system.admin.inc	6 Jun 2009 08:01:49 -0000
@@ -86,7 +86,7 @@ function system_admin_menu_block_page() 
  */
 function system_admin_by_module() {
 
-  $modules = module_rebuild_cache();
+  $modules = system_get_module_data();
   $menu_items = array();
   $help_arg = module_exists('help') ? drupal_help_arg() : FALSE;
 
@@ -141,7 +141,7 @@ function system_settings_overview() {
 function system_themes_form() {
   drupal_clear_css_cache();
 
-  $themes = system_theme_data();
+  $themes = system_get_theme_data();
   uasort($themes, 'system_sort_modules_by_info_name');
 
   $status = array();
@@ -325,7 +325,7 @@ function system_theme_settings(&$form_st
   if ($key) {
     $settings = theme_get_settings($key);
     $var = str_replace('/', '_', 'theme_' . $key . '_settings');
-    $themes = system_theme_data();
+    $themes = system_get_theme_data();
     $features = $themes[$key]->info['features'];
   }
   else {
@@ -580,7 +580,7 @@ function system_modules($form_state = ar
   node_types_rebuild();
   cache_clear_all('schema', 'cache');
   // Get current list of modules.
-  $files = module_rebuild_cache();
+  $files = system_get_module_data();
 
   // Remove hidden modules from display list.
   foreach ($files as $filename => $file) {
@@ -761,7 +761,7 @@ function _system_modules_build_row($info
  * Display confirmation form for required modules.
  *
  * @param $modules
- *   Array of module file objects as returned from module_rebuild_cache().
+ *   Array of module file objects as returned from system_get_module_data().
  * @param $storage
  *   The contents of $form_state['storage']; an array with two
  *   elements: the list of required modules and the list of status
@@ -819,7 +819,7 @@ function system_modules_submit($form, &$
 
   // Get a list of all modules, it will be used to find which module requires
   // which.
-  $files = module_rebuild_cache();
+  $files = system_get_module_data();
 
   // The modules to be enabled.
   $modules_to_be_enabled = array();
Index: modules/system/system.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v
retrieving revision 1.39
diff -u -p -r1.39 system.api.php
--- modules/system/system.api.php	4 Jun 2009 03:33:28 -0000	1.39
+++ modules/system/system.api.php	6 Jun 2009 08:01:50 -0000
@@ -530,7 +530,7 @@ function hook_mail_alter(&$message) {
 /**
  * Alter the information parsed from module and theme .info files
  *
- * This hook is invoked in  module_rebuild_cache() and in system_theme_data().
+ * This hook is invoked in _system_get_module_data() and in _system_get_theme_data().
  * A module may implement this hook in order to add to or alter the data
  * generated by reading the .info file with drupal_parse_info_file().
  *
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.338
diff -u -p -r1.338 system.install
--- modules/system/system.install	4 Jun 2009 03:33:28 -0000	1.338
+++ modules/system/system.install	6 Jun 2009 08:01:53 -0000
@@ -353,7 +353,7 @@ function system_install() {
   }
 
   // Load system theme data appropriately.
-  system_theme_data();
+  system_get_theme_data();
 
   // Inserting uid 0 here confuses MySQL -- the next user might be created as
   // uid 2 which is not what we want. So we insert the first user here, the
@@ -1542,8 +1542,8 @@ function system_update_6008() {
   db_drop_field($ret, 'system', 'description');
 
   // Rebuild system table contents.
-  module_rebuild_cache();
-  system_theme_data();
+  system_get_module_data();
+  system_get_theme_data();
 
   return $ret;
 }
@@ -1614,8 +1614,8 @@ function system_update_6012() {
  */
 function system_update_6013() {
   // Rebuild system table contents.
-  module_rebuild_cache();
-  system_theme_data();
+  system_get_module_data();
+  system_get_theme_data();
 
   return array(array('success' => TRUE, 'query' => 'Cache rebuilt.'));
 }
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.708
diff -u -p -r1.708 system.module
--- modules/system/system.module	5 Jun 2009 05:28:28 -0000	1.708
+++ modules/system/system.module	6 Jun 2009 08:01:53 -0000
@@ -1159,9 +1159,8 @@ function system_get_files_database(&$fil
   foreach ($result as $file) {
     if (isset($files[$file->name]) && is_object($files[$file->name])) {
       $file->filepath = $file->filename;
-      $file->old_filepath = $file->filepath;
       foreach ($file as $key => $value) {
-        if (!isset($files[$file->name]) || !isset($files[$file->name]->$key)) {
+        if (!isset($files[$file->name]->key)) {
           $files[$file->name]->$key = $value;
         }
       }
@@ -1170,75 +1169,139 @@ function system_get_files_database(&$fil
 }
 
 /**
- * Prepare defaults for themes.
+ * Updates the records in the system table based on the files array.
+ * 
+ * @param $files
+ *   An array of files.
+ * @param $type
+ *   The type of the files.
+ */
+function system_update_files_database(&$files, $type) {
+  $result = db_query("SELECT * FROM {system} WHERE type = :type", array(':type' => $type));
+
+  // Add all files that need to be deleted to a DatabaseCondition.
+  $delete = db_or();
+  foreach ($result as $file) {
+    if (isset($files[$file->name]) && is_object($files[$file->name])) {
+      // Keep the old filename from the database in case the file has moved.
+      $old_filename = $file->filename;
+
+      $updated_fields = array();
+
+      // Handle info specially, compare the serialized value.
+      $serialized_info = serialize($files[$file->name]->info);
+      if ($serialized_info != $file->info) {
+        $updated_fields['info'] = $serialized_info;
+      }
+      unset($file->info);
+
+      // Scan remaining fields to find only the updated values.
+      foreach ($file as $key => $value) {
+        if (isset($files[$file->name]->$key) && $files[$file->name]->$key != $value) {
+          $updated_fields[$key] = $files[$file->name]->$key;
+        }
+      }
+
+      // Update the record.
+      if (count($updated_fields)) {
+        db_update('system')
+          ->fields($updated_fields)
+          ->condition('filename', $old_filename)
+          ->execute();
+      }
+
+      // Indiciate that the file exists already.
+      $files[$file->name]->exists = TRUE;
+    }
+    else {
+      // File is not found in file system, so delete record from the system table.
+      $delete->condition('filename', $file->filename);
+    }
+  }
+
+  if (count($delete) > 0) {
+    // Delete all missing files from the system table
+    db_delete('system')
+      ->condition($delete)
+      ->execute();
+  }
+
+  // All remaining files are not in the system table, so we need to add them.
+  $query = db_insert('system')->fields(array('filename', 'name', 'type', 'owner', 'info'));
+  foreach($files as &$file) {
+    if (isset($file->exists)) {
+      unset($file->exists);
+    }
+    else {
+      $query->values(array(
+        'filename' => $file->filepath,
+        'name' => $file->name,
+        'type' => $type,
+        'owner' => isset($file->owner) ? $file->owner : '',
+        'info' => serialize($file->info),
+      ));
+      $file->type = $type;
+      $file->status = 0;
+      $file->schema_version = -1;
+    }
+  }
+  $query->execute();
+}
+
+/**
+ * Helper function to scan and collect module .info data.
  *
  * @return
- *   An array of default themes settings.
+ *   An associative array of module information.
  */
-function system_theme_default() {
-  return array(
-    'regions' => array(
-      'left' => 'Left sidebar',
-      'right' => 'Right sidebar',
-      'content' => 'Content',
-      'header' => 'Header',
-      'footer' => 'Footer',
-      'highlight' => 'Highlighted content',
-      'help' => 'Help',
-    ),
+function _system_get_module_data() {
+  // Find modules
+  $modules = drupal_system_listing('/\.module$/', 'modules', 'name', 0);
+
+  // Set defaults for module info.
+  $defaults = array(
+    'dependencies' => array(),
+    'dependents' => array(),
     'description' => '',
-    'features' => array(
-      'comment_user_picture',
-      'comment_user_verification',
-      'favicon',
-      'logo',
-      'name',
-      'node_user_picture',
-      'search',
-      'slogan',
-      'main_menu',
-      'secondary_menu',
-    ),
-    'screenshot' => 'screenshot.png',
+    'version' => NULL,
     'php' => DRUPAL_MINIMUM_PHP,
   );
+
+  // Read info files for each module.
+  foreach ($modules as $key => $module) {
+    // Look for the info file.
+    $module->info = drupal_parse_info_file(dirname($module->filepath) . '/' . $module->name . '.info');
+
+    // Skip modules that don't provide info.
+    if (empty($module->info)) {
+      unset($modules[$key]);
+      continue;
+    }
+
+    // Merge in defaults and save.
+    $modules[$key]->info = $module->info + $defaults;
+
+    // Invoke hook_system_info_alter() to give installed modules a chance to
+    // modify the data in the .info files if necessary.
+    drupal_alter('system_info', $modules[$key]->info, $modules[$key]);
+  }
+
+  return $modules;
 }
 
 /**
- * Collect data about all currently available themes.
+ * Collect data about all currently available modules.
  *
  * @return
- *   Array of all available themes and their data.
+ *   Array of all available modules and their data.
  */
-function system_theme_data() {
-  // Scan the installation theme .info files and their engines.
-  $themes = _system_theme_data();
-
-  // Extract current files from database.
-  system_get_files_database($themes, 'theme');
-
-  db_delete('system')
-    ->condition('type', 'theme')
-    ->execute();
-
-  $query = db_insert('system')->fields(array('name', 'owner', 'info', 'type', 'filename', 'status'));
-  foreach ($themes as $theme) {
-    if (!isset($theme->owner)) {
-      $theme->owner = '';
-    }
-
-    $query->values(array(
-      'name' => $theme->name,
-      'owner' => $theme->owner,
-      'info' => serialize($theme->info),
-      'type' => 'theme',
-      'filename' => $theme->filename,
-      'status' => isset($theme->status) ? $theme->status : 0,
-    ));
-  }
-  $query->execute();
-
-  return $themes;
+function system_get_module_data() {
+  $modules = _system_get_module_data();
+  ksort($modules);
+  system_get_files_database($modules, 'module');
+  system_update_files_database($modules, 'module');
+  $modules = _module_build_dependencies($modules);
+  return $modules;
 }
 
 /**
@@ -1247,7 +1310,7 @@ function system_theme_data() {
  * @return
  *   An associative array of themes information.
  */
-function _system_theme_data() {
+function _system_get_theme_data() {
   static $themes_info = array();
 
   if (empty($themes_info)) {
@@ -1256,7 +1319,37 @@ function _system_theme_data() {
     // Find theme engines
     $engines = drupal_system_listing('/\.engine$/', 'themes/engines');
 
-    $defaults = system_theme_default();
+    // Set defaults for theme info.
+    $defaults = array(
+      'regions' => array(
+        'left' => 'Left sidebar',
+        'right' => 'Right sidebar',
+        'content' => 'Content',
+        'header' => 'Header',
+        'footer' => 'Footer',
+        'highlight' => 'Highlighted content',
+        'help' => 'Help',
+      ),
+      'description' => '',
+      'features' => array(
+        'comment_user_picture',
+        'favicon',
+        'mission',
+        'logo',
+        'name',
+        'node_user_picture',
+        'search',
+        'slogan',
+        'main_menu',
+        'secondary_menu',
+      ),
+      'stylesheets' => array(
+        'all' => array('style.css')
+      ),
+      'scripts' => array('script.js'),
+      'screenshot' => 'screenshot.png',
+      'php' => DRUPAL_MINIMUM_PHP,
+    );
 
     $sub_themes = array();
     // Read info files for each theme
@@ -1340,6 +1433,20 @@ function _system_theme_data() {
 }
 
 /**
+ * Collect data about all currently available themes.
+ *
+ * @return
+ *   Array of all available themes and their data.
+ */
+function system_get_theme_data() {
+  $themes = _system_get_theme_data();
+  ksort($themes);
+  system_get_files_database($themes, 'theme');
+  system_update_files_database($themes, 'theme');
+  return $themes;
+}
+
+/**
  * Recursive function to find the top level base theme. Themes can inherit
  * templates and function implementations from earlier themes.
  *
Index: modules/update/update.compare.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/update/update.compare.inc,v
retrieving revision 1.21
diff -u -p -r1.21 update.compare.inc
--- modules/update/update.compare.inc	6 Jun 2009 06:26:13 -0000	1.21
+++ modules/update/update.compare.inc	6 Jun 2009 08:01:54 -0000
@@ -36,8 +36,8 @@ function update_get_projects() {
     $projects = update_project_cache('update_project_projects');
     if (empty($projects)) {
       // Still empty, so we have to rebuild the cache.
-      _update_process_info_list($projects, module_rebuild_cache(), 'module');
-      _update_process_info_list($projects, system_theme_data(), 'theme');
+      _update_process_info_list($projects, system_get_module_data(), 'module');
+      _update_process_info_list($projects, system_get_theme_data(), 'theme');
       // Allow other modules to alter projects before fetching and comparing.
       drupal_alter('update_projects', $projects);
       // Cache the site's project data for at most 1 hour.
