Index: modules/update/update.compare.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/update/update.compare.inc,v
retrieving revision 1.17
diff -u -p -r1.17 update.compare.inc
--- modules/update/update.compare.inc	29 Apr 2009 18:39:50 -0000	1.17
+++ modules/update/update.compare.inc	9 May 2009 19:21:07 -0000
@@ -49,54 +49,80 @@ function update_get_projects() {
  * Populate an array of project data.
  */
 function _update_process_info_list(&$projects, $list, $project_type) {
-  foreach ($list as $file) {
-    if (empty($file->status)) {
-      // Skip disabled modules or themes.
-      continue;
+  // For theme projects, we also need to find base theme projects.
+  $project_subtypes[] = $project_type;
+  if ($project_type = 'theme') {
+    $project_subtypes[] = 'base_theme';
+    $base_themes = array();
+  }
+  foreach ($project_subtypes AS $project_subtype) {
+    // Determine the full list of base themes for the enabled themes.
+    if ($project_subtype == 'base_theme') {
+      foreach ($base_themes AS $theme) {
+        // Flag this project as having an enabled sub-theme.
+        $list[$theme]->has_enabled_subtheme = TRUE;
+        // Check if this base theme has a parent theme.
+        if (!empty($list[$theme]->info['base theme']) && !in_array($list[$theme]->info['base theme'], $base_themes)) {
+          // Add parent theme to the end of the array we are currently looping over.
+          $base_themes[] = $list[$theme]->info['base theme'];
+        }
+      }
     }
+    foreach ($list as $file) {
+      if (empty($file->status) && !isset($file->has_enabled_subtheme)) {
+        // Unless this is a base theme with an enabled sub-theme, skip disabled modules or themes.
+        continue;
+      }
 
-    // Skip if the .info file is broken.
-    if (empty($file->info)) {
-      continue;
-    }
+      // Save the list of parent themes for enabled themes; this is a partial
+      // list of base themes.
+      if ($project_subtype == 'theme' && !empty($file->info['base theme'])) {
+        $base_themes[] = $file->info['base theme'];
+      }
 
-    // If the .info doesn't define the 'project', try to figure it out.
-    if (!isset($file->info['project'])) {
-      $file->info['project'] = update_get_project_name($file);
-    }
+      // Skip if the .info file is broken.
+      if (empty($file->info)) {
+        continue;
+      }
 
-    // If we still don't know the 'project', give up.
-    if (empty($file->info['project'])) {
-      continue;
-    }
+      // If the .info doesn't define the 'project', try to figure it out.
+      if (!isset($file->info['project'])) {
+        $file->info['project'] = update_get_project_name($file);
+      }
 
-    // If we don't already know it, grab the change time on the .info file
-    // itself. Note: we need to use the ctime, not the mtime (modification
-    // time) since many (all?) tar implementations will go out of their way to
-    // set the mtime on the files it creates to the timestamps recorded in the
-    // tarball. We want to see the last time the file was changed on disk,
-    // which is left alone by tar and correctly set to the time the .info file
-    // was unpacked.
-    if (!isset($file->info['_info_file_ctime'])) {
-      $info_filename = dirname($file->filepath) . '/' . $file->name . '.info';
-      $file->info['_info_file_ctime'] = filectime($info_filename);
-    }
+      // If we still don't know the 'project', give up.
+      if (empty($file->info['project'])) {
+        continue;
+      }
 
-    $project_name = $file->info['project'];
-    if (!isset($projects[$project_name])) {
-      // Only process this if we haven't done this project, since a single
-      // project can have multiple modules or themes.
-      $projects[$project_name] = array(
-        'name' => $project_name,
-        'info' => $file->info,
-        'datestamp' => isset($file->info['datestamp']) ? $file->info['datestamp'] : 0,
-        'includes' => array($file->name => $file->info['name']),
-        'project_type' => $project_name == 'drupal' ? 'core' : $project_type,
-      );
-    }
-    else {
-      $projects[$project_name]['includes'][$file->name] = $file->info['name'];
-      $projects[$project_name]['info']['_info_file_ctime'] = max($projects[$project_name]['info']['_info_file_ctime'], $file->info['_info_file_ctime']);
+      // If we don't already know it, grab the change time on the .info file
+      // itself. Note: we need to use the ctime, not the mtime (modification
+      // time) since many (all?) tar implementations will go out of their way to
+      // set the mtime on the files it creates to the timestamps recorded in the
+      // tarball. We want to see the last time the file was changed on disk,
+      // which is left alone by tar and correctly set to the time the .info file
+      // was unpacked.
+      if (!isset($file->info['_info_file_ctime'])) {
+        $info_filename = dirname($file->filepath) . '/' . $file->name . '.info';
+        $file->info['_info_file_ctime'] = filectime($info_filename);
+      }
+
+      $project_name = $file->info['project'];
+      if (!isset($projects[$project_name])) {
+        // Only process this if we haven't done this project, since a single
+        // project can have multiple modules or themes.
+        $projects[$project_name] = array(
+          'name' => $project_name,
+          'info' => $file->info,
+          'datestamp' => isset($file->info['datestamp']) ? $file->info['datestamp'] : 0,
+          'includes' => array($file->name => $file->info['name']),
+          'project_type' => $project_name == 'drupal' ? 'core' : $project_type,
+        );
+      }
+      else {
+        $projects[$project_name]['includes'][$file->name] = $file->info['name'];
+        $projects[$project_name]['info']['_info_file_ctime'] = max($projects[$project_name]['info']['_info_file_ctime'], $file->info['_info_file_ctime']);
+      }
     }
   }
 }
