Index: drush.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/drush.php,v
retrieving revision 1.44
diff -u -u -p -r1.44 drush.php
--- drush.php	28 Feb 2009 18:46:46 -0000	1.44
+++ drush.php	1 Mar 2009 04:16:27 -0000
@@ -51,10 +51,7 @@ function drush_verify_cli() {
  *   Whatever the given command returns.
  */
 function drush_bootstrap($argc, $argv) {
-  global $args, $conf, $override;
-
-  // The bootstrap can fail silently, so we catch that in a shutdown function.
-  register_shutdown_function('drush_shutdown');
+  global $args, $conf, $override, $bootstrap_level;
 
   // Parse command line options and arguments.
   $args = drush_parse_args($argv, array('c', 'h', 'u', 'r', 'l', 'i'));
@@ -80,34 +77,58 @@ function drush_bootstrap($argc, $argv) {
 
   define('DRUSH_URI',         drush_get_option(array('l', 'uri'), drush_site_uri($drupal_root)));
   define('DRUSH_USER',        drush_get_option(array('u', 'user'), 0));
-  // Quickly attempt to find the command. A second attempt is performed in drush_dispatch().
-  list($command, $arguments) = drush_parse_command($args['commands']);
-  if ($drupal_root) {
 
+  $bootstrap_level = -1;
+  if ($drupal_root) {
+    // Attempt to bootstrap progressively, until we fail (passing execution on to
+    // drush_continue) or complete a full bootstrap.
     drush_drupal_set_environment($drupal_root);
-
-    // Bootstrap Drupal.
-    if (drush_drupal_bootstrap($drupal_root, $command['bootstrap'])) {
-      /**
-       * Allow the drushrc.php file to override $conf settings.
-       * This is a separate variable because the $conf array gets initialized to an empty array,
-       * in the drupal bootstrap process, and changes in settings.php would wipe out the drushrc.php
-       * settings
-       */
-      if (is_array($override)) {
-        $conf = array_merge($conf, $override);
-      }
-
-      // We have changed bootstrap level, so re-detect command files.
-      drush_commandfile_cache_flush();
-
-      // Login the specified user (if given).
-      if (DRUSH_USER) {
-        drush_drupal_login(DRUSH_USER);
-      }
+    register_shutdown_function('drush_bootstrap_continue');
+    drush_drupal_bootstrap($drupal_root);
+  }
+  // We are completely unbootstrapped, or we made it to full bootstrap.
+  // Either way, continue on to process the commands.
+  drush_bootstrap_continue();
+}
+
+function drush_bootstrap_continue() {
+  global $bootstrap_level, $args;
+  // Clean up any maintanance pages from a failed bootstrap.
+  ob_clean();
+
+  if (defined('DRUSH_DRUPAL_BOOTSTRAPPED')) {
+    /**
+     * Allow the drushrc.php file to override $conf settings.
+     * This is a separate variable because the $conf array gets initialized to an empty array,
+     * in the drupal bootstrap process, and changes in settings.php would wipe out the drushrc.php
+     * settings
+     */
+    if (is_array($override)) {
+      $conf = array_merge($conf, $override);
+    }
+
+    // We have changed bootstrap level, so re-detect command files.
+    drush_commandfile_cache_flush();
+
+    // Login the specified user (if given).
+    if (DRUSH_USER) {
+      drush_drupal_login(DRUSH_USER);
     }
   }
 
+  if (DRUSH_URI) {
+    // Only display the database errors/hints if have a specific URL,
+    // which suggests the user wanted to bootstrap in the first place.
+    if ($bootstrap_level < 2) {
+      drush_set_error(DRUSH_DRUPAL_DB_ERROR);
+    }
+    elseif (!defined('DRUSH_DRUPAL_BOOTSTRAPPED')) {
+      drush_set_error(DRUSH_DRUPAL_BOOTSTRAP_ERROR);
+    }
+    // Collect any other log messages.
+    _drush_log_drupal_messages();
+  }
+ 
   if (DRUSH_SIMULATE) {
     drush_print('SIMULATION MODE IS ENABLED. NO ACTUAL ACTION WILL BE TAKEN. SYSTEM WILL REMAIN UNCHANGED.');
   }
@@ -120,8 +141,11 @@ function drush_bootstrap($argc, $argv) {
     $output = '';
   }
 
-  // TODO: Terminate with the correct exit status.
-  return $output;
+  if (DRUSH_BACKEND) {
+    drush_backend_output();
+  }
+
+  exit(($error = drush_get_error()) ? $error : DRUSH_SUCCESS);
 }
 
 /**
@@ -157,28 +181,6 @@ function drush_drupal_set_environment($d
 }
 
 /**
- * Shutdown function for use while Drupal is bootstrapping.
- */
-function drush_shutdown() {
-  if (DRUSH_URI) {
-    if (!defined('DRUSH_DRUPAL_BOOTSTRAP_DATABASE')) {
-      ob_end_clean();
-      drush_set_error(DRUSH_DRUPAL_DB_ERROR);
-    }
-    elseif (!defined('DRUSH_DRUPAL_BOOTSTRAP_FULL')) {
-      ob_end_clean();
-      drush_set_error(DRUSH_DRUPAL_BOOTSTRAP_ERROR);
-    }
-    _drush_log_drupal_messages();
-  }
-  if (DRUSH_BACKEND) {
-    drush_backend_output();
-  }
-
-  exit(($error = drush_get_error()) ? $error : DRUSH_SUCCESS);
-}
-
-/**
  * Bootstrap Drupal.
  *
  * @param string
@@ -192,52 +194,43 @@ function drush_shutdown() {
  *   TRUE if Drupal successfully bootstrapped to the given state.
  */
 function drush_drupal_bootstrap($drupal_root, $bootstrap = NULL) {
+  global $bootstrap_level;
+
   // Change to Drupal root dir.
   chdir($drupal_root);
 
   if ($bootstrap != -1) {
     require_once DRUSH_DRUPAL_BOOTSTRAP;
 
+    if (is_null($bootstrap)) {
+      $bootstrap = DRUPAL_BOOTSTRAP_FULL;
+    }
+
     if (($conf_path = conf_path()) && !file_exists("./$conf_path/settings.php")) {
+      $bootstrap_level = -1;
       return FALSE;
     }
 
-    if (is_null($bootstrap)) {
-      drush_drupal_bootstrap_db(); 
-      drush_drupal_bootstrap_full(); 
+    // Enable output buffering so we don't get a maintanance page
+    ob_start();
+    
+    while ($bootstrap_level < $bootstrap) {
+      // We attempt the next bootstrap in the sequence, so that if it fails we
+      // are left with the maximum reachable bootstrap. 
+      drupal_bootstrap($bootstrap_level + 1);
+      $bootstrap_level++;
+    }
 
+    if ($bootstrap_level == DRUPAL_BOOTSTRAP_FULL) {
       // Set this constant when we are fully bootstrapped.
       define('DRUSH_DRUPAL_BOOTSTRAPPED', TRUE);
     }
-    else {
-      drupal_bootstrap($bootstrap);
-    }
   }
 
   return TRUE;
 }
 
 /**
- * Bootstrap the Drupal database.
- */
-function drush_drupal_bootstrap_db() {
-  ob_start();
-  drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
-  ob_end_clean();
-  define('DRUSH_DRUPAL_BOOTSTRAP_DATABASE', TRUE);
-}
-
-/**
- * Fully bootstrap Drupal.
- */
-function drush_drupal_bootstrap_full() {
-  ob_start();
-  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-  ob_end_clean();
-  define('DRUSH_DRUPAL_BOOTSTRAP_FULL', TRUE);
-}
-
-/**
  * Log the given user in to a bootstrapped Drupal site.
  *
  * @param mixed
Index: includes/command.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/command.inc,v
retrieving revision 1.14
diff -u -u -p -r1.14 command.inc
--- includes/command.inc	15 Feb 2009 19:33:38 -0000	1.14
+++ includes/command.inc	1 Mar 2009 04:16:27 -0000
@@ -31,6 +31,9 @@ function drush_get_commands() {
   // Filter out commands which are invalid for the current version of core Drupal.
   $commands = drush_enforce_requirement_core($commands);
   
+  // Filter out commands which are invalid for the current bootstrap level.
+  $commands = drush_enforce_requirement_bootstrap($commands);
+  
   // Filter out commands which are missing their dependant Drupal modules.
   $commands = drush_enforce_requirement_drupal_dependencies($commands);
   
@@ -394,3 +397,18 @@ function drush_enforce_requirement_core(
   return $valid;
 }
 
+
+// Return commands that are valid for the current bootstrap level.
+function drush_enforce_requirement_bootstrap($commands) {
+  global $bootstrap_level;
+
+  $valid = array();
+  if (!empty($commands)) {
+    foreach ($commands as $key => $command) {
+      if ((empty($command['bootstrap']) && defined('DRUSH_DRUPAL_BOOTSTRAPPED')) || (is_numeric($command['bootstrap']) && $command['bootstrap'] <= $bootstrap_level)) {
+        $valid[$key] = $command;
+      }
+    }
+  }
+  return $valid;
+}
Index: includes/core_commands.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/core_commands.drush.inc,v
retrieving revision 1.25
diff -u -u -p -r1.25 core_commands.drush.inc
--- includes/core_commands.drush.inc	28 Feb 2009 18:46:46 -0000	1.25
+++ includes/core_commands.drush.inc	1 Mar 2009 04:16:27 -0000
@@ -29,6 +29,7 @@ function core_commands_drush_command() {
   $items['status'] = array(
     'callback' => 'core_commands_status',
     'description' => 'Provides a birds-eye view of the current Drupal installation, if any.',
+    'bootstrap' => 0, // Just configuration (no point otherwise).
   );
   $items['script'] = array(
     'callback' => 'core_commands_script',
@@ -39,6 +40,7 @@ function core_commands_drush_command() {
     'arguments' => array(
       'path/to/script' => 'One or more file paths. Paths may be absolute or relative to the current working dir.',
     ),
+    'bootstrap' => -1, // No bootstrap at all.
   );
   $items['cache clear'] = array(
     'callback' => 'core_commands_cache_clear',
@@ -87,27 +89,17 @@ function core_commands_drush_help($secti
     case 'drush:dl':
       return dt("Quickly download projects from drupal.org. Automatically figures out which module version you want based on its latest release, or you may specify a particular version. Downloads drupal core as well.  If no destination is provided, defaults to a site specific modules directory if available, then to sites/all/modules if available, then to the current working directory.");
     case 'error:DRUSH_DRUPAL_DB_ERROR' : 
-      $message = dt("Drush was not able to start (bootstrap) the Drupal database.\n");
+      $message = dt("Drush was not able to start (bootstrap) the Drupal database and so you only have access to a limited number of commands.\n");
       $message .= dt("Hint: This error often occurs when Drush is trying to bootstrap a site that has not been installed or does not have a configured database.\n");
       $message .= dt("\nDrush was attempting to connect to : \n!credentials\n", array('!credentials' => _core_commands_site_credentials()));
       $message .= dt("You can select another site with a working database setup by specifying the URI to use with the --uri parameter on the command line or \$options['uri'] in your drushrc.php file.\n");
       return $message;
     case 'error:DRUSH_DRUPAL_BOOTSTRAP_ERROR' :
-      $message = dt("Drush was not able to start (bootstrap) Drupal.\n");
+      $message = dt("Drush was not able to start (bootstrap) Drupal and so you only have access to a limited number of commands.\n");
       $message .= dt("Hint: This error can only occur once the database connection has already been succesfully initiated, therefor this error generally points to a site configuration issue, and not a problem connecting to the database.\n");
       $message .= dt("\nDrush was attempting to connect to : \n!credentials\n", array('!credentials' => _core_commands_site_credentials()));
       $message .= dt("You can select another site with a working database setup by specifying the URI to use with the --uri parameter on the command line or \$options['uri'] in your drushrc.php file.\n");
       return $message;
-
-      $site_path = drush_site_path();
-      $message = "Drush was not able to start (bootstrap) Drupal.\n";
-      $message .= "Hint: This error often occurs when Drush is trying to bootstrap a site\n";
-      $message .= "that has not been installed or does not have a configured database.\n";
-      $message .= "Drush was looking for the site in '$site_path'. You can select another site\n";
-      $message .= "with a working database setup by specifying the URI to use with the --uri\n";
-      $message .= "parameter on the command line or \$options['uri'] in your drushrc.php file.\n";
-      return $message;
-      break;
   }
 }
 
