Index: modules/update/update.compare.inc
===================================================================
RCS file: /Users/wright/drupal/local_repo/drupal/modules/update/update.compare.inc,v
retrieving revision 1.31
diff -u -p -r1.31 update.compare.inc
--- modules/update/update.compare.inc	29 Sep 2009 16:30:29 -0000	1.31
+++ modules/update/update.compare.inc	5 Oct 2009 22:41:53 -0000
@@ -42,8 +42,11 @@ function update_get_projects() {
       _update_process_info_list($projects, $theme_data, 'theme', TRUE);
       if (variable_get('update_check_disabled', FALSE)) {
         _update_process_info_list($projects, $module_data, 'module', FALSE);
-        _update_process_info_list($projects, $theme_data, 'theme', FALSE);
       }
+      // We always need to process disabled themes, since disabled base themes
+      // are still considered active if they have an enabled subtheme.
+      _update_process_info_list($projects, $theme_data, 'theme', FALSE);
+
       // 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.
@@ -80,8 +83,25 @@ function update_get_projects() {
  * @see update_get_projects()
  */
 function _update_process_info_list(&$projects, $list, $project_type, $status) {
+  $check_disabled = variable_get('update_check_disabled', FALSE);
   foreach ($list as $file) {
-    if ($file->status != $status) {
+    // A disabled base theme of an enabled sub-theme still has all of its code
+    // run by the sub-theme, so we include it in our "enabled" projects list.
+    if (!$file->status && !empty($file->sub_themes)) {
+      foreach ($file->sub_themes as $key => $name) {
+        // Build a list of enabled sub-themes.
+        if ($list[$key]->status) {
+          $file->enabled_sub_themes[$key] = $name;
+        }
+      }
+      // If there are no enabled subthemes and we're only processing enabled
+      // projects, we should ingore this theme and go on to the next one.
+      if (empty($file->enabled_sub_themes) && !$check_disabled) {
+        continue;
+      }
+    }
+    // Otherwise, just add projects of the proper status to our list.
+    elseif ($file->status != $status) {
       continue;
     }
 
@@ -133,10 +153,25 @@ function _update_process_info_list(&$pro
     else {
       $project_display_type = $project_type;
     }
-    if (empty($status)) {
+    if (empty($status) && empty($file->enabled_sub_themes)) {
       // If we're processing disabled modules or themes, append a suffix.
+      // However, we don't do this to a a base theme with enabled
+      // subthemes, since we treat that case as if it is enabled.
       $project_display_type .= '-disabled';
     }
+    // Add a list of sub-themes that "depend on" the project and a list of base
+    // themes that are "required by" the project.
+    if ($project_name == 'drupal') {
+      // Drupal core is always required, so this extra info would be noise.
+      $sub_themes = array();
+      $base_themes = array();
+    }
+    else {
+      // Add list of enabled sub-themes.
+      $sub_themes = !empty($file->enabled_sub_themes) ? $file->enabled_sub_themes : array();
+      // Add list of base themes.
+      $base_themes = !empty($file->base_themes) ? $file->base_themes : array();
+    }
     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.
@@ -147,6 +182,8 @@ function _update_process_info_list(&$pro
         'includes' => array($file->name => $file->info['name']),
         'project_type' => $project_display_type,
         'project_status' => $status,
+        'sub_themes' => $sub_themes,
+        'base_themes' => $base_themes,
       );
     }
     elseif ($projects[$project_name]['project_type'] == $project_display_type) {
@@ -158,6 +195,8 @@ function _update_process_info_list(&$pro
       $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']);
       $projects[$project_name]['datestamp'] = max($projects[$project_name]['datestamp'], $file->info['datestamp']);
+      $projects[$project_name]['sub_themes'] = array_merge($projects[$project_name]['sub_themes'], $sub_themes);
+      $projects[$project_name]['base_themes'] = array_merge($projects[$project_name]['base_themes'], $base_themes);
     }
     elseif (empty($status)) {
       // If we have a project_name that matches, but the project_display_type
Index: modules/update/update.report.inc
===================================================================
RCS file: /Users/wright/drupal/local_repo/drupal/modules/update/update.report.inc,v
retrieving revision 1.22
diff -u -p -r1.22 update.report.inc
--- modules/update/update.report.inc	5 Oct 2009 02:26:36 -0000	1.22
+++ modules/update/update.report.inc	5 Oct 2009 21:10:54 -0000
@@ -194,6 +194,20 @@ function theme_update_report($data) {
     }
     $row .= "</div>\n";
 
+    if (!empty($project['base_themes'])) {
+      $row .= '<div class="basethemes">';
+      sort($project['base_themes']);
+      $row .= t('Depends on: %basethemes', array('%basethemes' => implode(', ', $project['base_themes'])));
+      $row .= "</div>\n";
+    }
+
+    if (!empty($project['sub_themes'])) {
+      $row .= '<div class="subthemes">';
+      sort($project['sub_themes']);
+      $row .= t('Required by: %subthemes', array('%subthemes' => implode(', ', $project['sub_themes'])));
+      $row .= "</div>\n";
+    }
+
     $row .= "</div>\n"; // info div.
 
     if (!isset($rows[$project['project_type']])) {
