Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1193
diff -u -p -r1.1193 common.inc
--- includes/common.inc	24 Jul 2010 17:28:25 -0000	1.1193
+++ includes/common.inc	28 Jul 2010 22:44:52 -0000
@@ -87,6 +87,34 @@ define('JS_DEFAULT', 0);
 define('JS_THEME', 100);
 
 /**
+ * Constants defining aggregation of JavaScript and CSS files.
+ */
+
+/**
+ * No aggregation.
+ */
+define('DRUPAL_AGGREGATION_DISABLED', 0);
+
+/**
+ * Default aggregation. The filename of the aggregate file is an md5 hash of
+ * the array of source file information. The last modified timestamp of each
+ * source file is part of this information, so when a source file is updated, it
+ * results in a new aggregate file being made.
+ */
+define('DRUPAL_AGGREGATION_ENABLED', 1);
+
+/**
+ * Optimized aggregation. The filename of the aggregate file is an md5 hash of
+ * the array of source file information. The last modified timestamp of each
+ * source file is not part of this information, so modification of source files
+ * does not automatically result in a new aggregate file. This saves on file
+ * stats, which can be significant for high traffic websites, but requires the
+ * site administrator to empty the aggregation cache whenever a source file is
+ * modified.
+ */
+define('DRUPAL_AGGREGATION_ENABLED_WITHOUT_STAT', 2);
+
+/**
  * Error code indicating that the request made by drupal_http_request() exceeded
  * the specified timeout.
  */
@@ -2937,8 +2965,11 @@ function drupal_group_css($css) {
  * @see drupal_pre_render_styles()
  */
 function drupal_aggregate_css(&$css_groups) {
-  $preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
-
+  $preprocess_css = variable_get('preprocess_css', DRUPAL_AGGREGATION_ENABLED);
+  // Force aggregation to disabled if we are in maintanance mode.
+  if (defined('MAINTENANCE_MODE')) {
+    $preprocess_css = DRUPAL_AGGREGATION_DISABLED;
+  }
   // For each group that needs aggregation, aggregate its items.
   foreach ($css_groups as $key => $group) {
     switch ($group['type']) {
@@ -2946,6 +2977,19 @@ function drupal_aggregate_css(&$css_grou
       // the group's data property to the file path of the aggregate file.
       case 'file':
         if ($group['preprocess'] && $preprocess_css) {
+          // Unless aggregation is enabled without file stats, add each file's
+          // last modified timestamp to the information from which the aggregate
+          // filename will be generated.
+          if ($preprocess_css != DRUPAL_AGGREGATION_ENABLED_WITHOUT_STAT) {
+            foreach ($group['items'] as &$item) {
+              // Don't override information that may have been set earlier, such
+              // as in hook_css_alter().
+              if (!isset($item['mtime']) && file_exists($item['data'])) {
+                $item['mtime'] = filemtime($item['data']);
+              }
+            }
+            unset($item);
+          }
           $css_groups[$key]['data'] = drupal_build_css_cache($group['items']);
         }
         break;
@@ -3770,7 +3814,11 @@ function drupal_get_js($scope = 'header'
   $index = 1;
   $processed = array();
   $files = array();
-  $preprocess_js = (variable_get('preprocess_js', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
+  $preprocess_js = variable_get('preprocess_js', DRUPAL_AGGREGATION_ENABLED);
+  // Force aggregation to disabled if we are in maintanance mode.
+  if (defined('MAINTENANCE_MODE')) {
+    $preprocess_js = DRUPAL_AGGREGATION_DISABLED;
+  }
 
   // A dummy query-string is added to filenames, to gain control over
   // browser-caching. The string changes on every update or full cache
@@ -3858,6 +3906,19 @@ function drupal_get_js($scope = 'header'
   // Aggregate any remaining JS files that haven't already been output.
   if ($preprocess_js && count($files) > 0) {
     foreach ($files as $key => $file_set) {
+      // Unless aggregation is enabled without file stats, add each file's
+      // last modified timestamp to the information from which the aggregate
+      // filename will be generated.
+      if ($preprocess_js != DRUPAL_AGGREGATION_ENABLED_WITHOUT_STAT) {
+        foreach ($file_set as &$item) {
+          // Don't override information that may have been set earlier, such
+          // as in hook_js_alter().
+          if (!isset($item['mtime']) && file_exists($item['data'])) {
+            $item['mtime'] = filemtime($item['data']);
+          }
+        }
+        unset($item);
+      }
       $uri = drupal_build_js_cache($file_set);
       // Only include the file if was written successfully. Errors are logged
       // using watchdog.
Index: modules/color/color.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/color/color.test,v
retrieving revision 1.5
diff -u -p -r1.5 color.test
--- modules/color/color.test	8 Jul 2010 03:41:27 -0000	1.5
+++ modules/color/color.test	28 Jul 2010 22:44:52 -0000
@@ -29,6 +29,7 @@ class ColorTestCase extends DrupalWebTes
     // This test relies on Garland, the mother of all the colorable themes.
     theme_enable(array('garland'));
     variable_set('theme_default', 'garland');
+    variable_set('preprocess_css', DRUPAL_AGGREGATION_DISABLED);
   }
 
   /**
Index: modules/profile/profile.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.test,v
retrieving revision 1.26
diff -u -p -r1.26 profile.test
--- modules/profile/profile.test	29 May 2010 11:37:33 -0000	1.26
+++ modules/profile/profile.test	28 Jul 2010 22:44:52 -0000
@@ -339,7 +339,12 @@ class ProfileTestAutocomplete extends Pr
     $field_html = '<input type="text" maxlength="255" name="' . $field['form_name'] . '" id="' . drupal_html_id('edit-' . $field['form_name']) . '" size="60" value="' . $field['value'] . '" class="form-text form-autocomplete required" />';
 
     // Check that autocompletion html is found on the user's profile edit page.
+    // Since we're checking for autocomplete.js in the HTML source, we need to
+    // disable JavaScript aggregation for this request.
+    $preprocess_js = variable_get('preprocess_js', DRUPAL_AGGREGATION_ENABLED);
+    variable_set('preprocess_js', DRUPAL_AGGREGATION_DISABLED);
     $this->drupalGet('user/' . $this->admin_user->uid . '/edit/' . $category);
+    variable_set('preprocess_js', $preprocess_js);
     $this->assertRaw($autocomplete_html, t('Autocomplete found.'));
     $this->assertRaw('misc/autocomplete.js', t('Autocomplete JavaScript found.'));
     $this->assertRaw('class="form-text form-autocomplete"', t('Autocomplete form element class found.'));
Index: modules/simpletest/tests/common.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v
retrieving revision 1.116
diff -u -p -r1.116 common.test
--- modules/simpletest/tests/common.test	7 Jul 2010 17:00:43 -0000	1.116
+++ modules/simpletest/tests/common.test	28 Jul 2010 22:44:52 -0000
@@ -546,6 +546,11 @@ class DrupalTagsHandlingTestCase extends
  * Test the Drupal CSS system.
  */
 class CascadingStylesheetsTestCase extends DrupalWebTestCase {
+  /**
+   * Store configured value for CSS preprocessing.
+   */
+  protected $preprocess_css = NULL;
+
   public static function getInfo() {
     return array(
       'name' => 'Cascading stylesheets',
@@ -556,10 +561,21 @@ class CascadingStylesheetsTestCase exten
 
   function setUp() {
     parent::setUp('php', 'locale', 'common_test');
+
+    // Disable preprocessing.
+    $this->preprocess_css = variable_get('preprocess_css', DRUPAL_AGGREGATION_ENABLED);
+    variable_set('preprocess_css', DRUPAL_AGGREGATION_DISABLED);
+
     // Reset drupal_add_css() before each test.
     drupal_static_reset('drupal_add_css');
   }
 
+  function tearDown() {
+    // Restore configured value for CSS preprocessing.
+    variable_set('preprocess_css', $this->preprocess_css);
+    parent::tearDown();
+  }
+
   /**
    * Check default stylesheets as empty.
    */
@@ -1092,8 +1108,8 @@ class JavaScriptTestCase extends DrupalW
     parent::setUp('locale', 'simpletest', 'common_test');
 
     // Disable preprocessing
-    $this->preprocess_js = variable_get('preprocess_js', 0);
-    variable_set('preprocess_js', 0);
+    $this->preprocess_js = variable_get('preprocess_js', DRUPAL_AGGREGATION_ENABLED);
+    variable_set('preprocess_js', DRUPAL_AGGREGATION_DISABLED);
 
     // Reset drupal_add_js() and drupal_add_library() statics before each test.
     drupal_static_reset('drupal_add_js');
Index: modules/simpletest/tests/common_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common_test.module,v
retrieving revision 1.11
diff -u -p -r1.11 common_test.module
--- modules/simpletest/tests/common_test.module	18 May 2010 06:59:46 -0000	1.11
+++ modules/simpletest/tests/common_test.module	28 Jul 2010 22:44:52 -0000
@@ -220,7 +220,8 @@ function common_test_library() {
  * Adds a JavaScript file and a CSS file with a query string appended.
  */
 function common_test_js_and_css_querystring() {
-   drupal_add_js(drupal_get_path('module', 'node') . '/node.js?arg1=value1&arg2=value2');
-   drupal_add_css(drupal_get_path('module', 'node') . '/node.css?arg1=value1&arg2=value2');
-   return '';
+  // It makes no sense to preprocess files with query strings.
+  drupal_add_js(drupal_get_path('module', 'node') . '/node.js?arg1=value1&arg2=value2', array('preprocess' => FALSE));
+  drupal_add_css(drupal_get_path('module', 'node') . '/node.css?arg1=value1&arg2=value2', array('preprocess' => FALSE));
+  return '';
 }
Index: modules/simpletest/tests/menu.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/menu.test,v
retrieving revision 1.31
diff -u -p -r1.31 menu.test
--- modules/simpletest/tests/menu.test	8 Jul 2010 03:41:27 -0000	1.31
+++ modules/simpletest/tests/menu.test	28 Jul 2010 22:44:52 -0000
@@ -7,6 +7,11 @@
  */
 
 class MenuRouterTestCase extends DrupalWebTestCase {
+  /**
+   * Store configured value for CSS preprocessing.
+   */
+  protected $preprocess_css = NULL;
+
   public static function getInfo() {
     return array(
       'name' => 'Menu router',
@@ -18,11 +23,24 @@ class MenuRouterTestCase extends DrupalW
   function setUp() {
     // Enable dummy module that implements hook_menu.
     parent::setUp('menu_test');
+
     // Make the tests below more robust by explicitly setting the default theme
     // and administrative theme that they expect.
     theme_enable(array('garland'));
     variable_set('theme_default', 'garland');
     variable_set('admin_theme', 'seven');
+
+    // Several tests determine which theme got used by asserting the existence
+    // of a particular CSS file in the HTML source, so we disable CSS
+    // aggregation for these tests.
+    $this->preprocess_css = variable_get('preprocess_css', DRUPAL_AGGREGATION_ENABLED);
+    variable_set('preprocess_css', DRUPAL_AGGREGATION_DISABLED);
+  }
+
+  function tearDown() {
+    // Restore configured value for CSS preprocessing.
+    variable_set('preprocess_css', $this->preprocess_css);
+    parent::tearDown();
   }
 
   /**
Index: modules/simpletest/tests/theme.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/theme.test,v
retrieving revision 1.16
diff -u -p -r1.16 theme.test
--- modules/simpletest/tests/theme.test	29 Apr 2010 05:22:06 -0000	1.16
+++ modules/simpletest/tests/theme.test	28 Jul 2010 22:44:52 -0000
@@ -171,6 +171,7 @@ class ThemeHookInitUnitTest extends Drup
   function setUp() {
     parent::setUp('theme_test');
     variable_set('theme_default', 'garland');
+    variable_set('preprocess_css', DRUPAL_AGGREGATION_DISABLED);
   }
 
   /**
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.293
diff -u -p -r1.293 system.admin.inc
--- modules/system/system.admin.inc	28 Jul 2010 02:57:36 -0000	1.293
+++ modules/system/system.admin.inc	28 Jul 2010 22:44:52 -0000
@@ -1680,15 +1680,25 @@ function system_performance_settings() {
     '#suffix' => '</div>',
   );
   $form['bandwidth_optimization']['preprocess_css'] = array(
-    '#type' => 'checkbox',
+    '#type' => 'radios',
     '#title' => t('Aggregate and compress CSS files into one file.'),
-    '#default_value' => intval(variable_get('preprocess_css', 0) && $is_writable),
+    '#options' => array(
+      DRUPAL_AGGREGATION_DISABLED => t('Disabled. This can be useful during development, but slows down page download and display.'),
+      DRUPAL_AGGREGATION_ENABLED => t('Normal (recommended)'),
+      DRUPAL_AGGREGATION_ENABLED_WITHOUT_STAT => t('Aggressive. This setting skips the normal verification of changes to source CSS files, potentially reducing disk load on high traffic website.'),
+    ),
+    '#default_value' => $is_writable ? variable_get('preprocess_css', DRUPAL_AGGREGATION_ENABLED) : 0,
     '#disabled' => $disabled,
   );
   $form['bandwidth_optimization']['preprocess_js'] = array(
-    '#type' => 'checkbox',
+    '#type' => 'radios',
     '#title' => t('Aggregate JavaScript files into one file.'),
-    '#default_value' => intval(variable_get('preprocess_js', 0) && $is_writable),
+    '#options' => array(
+      DRUPAL_AGGREGATION_DISABLED => t('Disabled. This can be useful during development, but slows down page download and display.'),
+      DRUPAL_AGGREGATION_ENABLED => t('Normal (recommended)'),
+      DRUPAL_AGGREGATION_ENABLED_WITHOUT_STAT => t('Aggressive. This setting skips the normal verification of changes to source JavaScript files, potentially reducing disk load on high traffic website.'),
+    ),
+    '#default_value' => $is_writable ? variable_get('preprocess_js', DRUPAL_AGGREGATION_ENABLED) : 0,
     '#disabled' => $disabled,
   );
 
