? .drush-cache.info
? includes/table.inc
Index: commands/core/core.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/core/core.drush.inc,v
retrieving revision 1.141
diff -u -p -r1.141 core.drush.inc
--- commands/core/core.drush.inc	9 Dec 2010 03:30:29 -0000	1.141
+++ commands/core/core.drush.inc	11 Dec 2010 05:32:34 -0000
@@ -39,6 +39,17 @@ function core_drush_command() {
     ),
     'topics' => array('docs-readme'),
   );
+  $items['version'] = array(
+    'description' => 'Show drush version.',
+    'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap.
+  );
+  $items['self-update'] = array(
+    'description' => 'Update drush to the latest version, if available.',
+    'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, // No bootstrap.
+    'options' => array(
+      '--dev' => 'Allow updates to latest dev release.',
+    ),
+  );
   $items['core-cron'] = array(
     'description' => 'Run all cron hooks.',
     'aliases' => array('cron'),
@@ -251,12 +262,32 @@ function drush_core_updatedb() {
 }
 
 /**
+ * Called for `druch version` or `drush --version`
+ */
+function drush_core_version() {
+  drush_log(dt("drush !version", array('!version' => DRUSH_VERSION)), 'ok');
+  // Next check to see if there is a newer drush.
+  if (drush_get_option('self-update', TRUE)) {
+    drush_self_update();
+  }
+}
+
+function drush_core_self_update() {
+  if (drush_get_option(array('dev', 'head'), TRUE)) {
+    drush_set_option('self-update', 'head');
+  }
+  
+  if (drush_self_update() === FALSE) {
+    drush_log(dt("drush is already up-to-date."), 'ok');
+  }
+}
+
+/**
  * This is called for help command, or no command.
  */
 function drush_core_help() {
   $commands = func_get_args();
 
-
   if (empty($commands)) {
     // Build a fake command for the purposes of showing examples and options.
     $fake = array(
Index: commands/pm/pm.drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/pm/pm.drush.inc,v
retrieving revision 1.169
diff -u -p -r1.169 pm.drush.inc
--- commands/pm/pm.drush.inc	10 Dec 2010 05:06:02 -0000	1.169
+++ commands/pm/pm.drush.inc	11 Dec 2010 05:32:36 -0000
@@ -223,7 +223,8 @@ function pm_drush_command() {
       'drush dl cck zen es' => 'Download latest versions of CCK, Zen and Spanish translations for your Drupal version.',
       'drush dl og-1.3' => 'Download a specfic version of Organic groups module for my version of Drupal.',
       'drush dl diff-6.x-2.x' => 'Download a specific development branch of diff module for a specific Drupal version.',
-      'drush dl views --dev' => 'Download the most recent development branch of the views module.',
+      'drush dl views --select' => 'Show a list of recent releases of the views project, prompt for which one to download.',
+      'drush dl drush --dev' => 'Upgrade to drush-HEAD.',
     ),
     'arguments' => array(
       'projects' => 'A list of drpal.org project names, with optional version. Defaults to \'drupal\'',
@@ -2257,10 +2258,17 @@ function drush_pm_download() {
     if (!$version_control = drush_pm_include_version_control($request['project_install_location'])) {
       continue;
     }
-
-    // Final project install location.
-    $request['project_install_location'] .= '/' . $request['project_dir'];
-
+    
+    // Check for drush self update
+    if ($request['project_install_location'] == DRUSH_BASE_PATH) {
+      // Move the running drush out of the way
+      drush_move_dir(DRUSH_BASE_PATH, DRUSH_BASE_PATH . "-" . DRUSH_VERSION, TRUE);
+    }
+    else {
+      // For all other projects, the final project install location will go in the project_dir.
+      $request['project_install_location'] .= '/' . $request['project_dir'];
+    }
+    
     // Check if install location already exists.
     if (is_dir($request['project_install_location'])) {
       if (!drush_confirm(dt('Install location !location already exists. Do you want to overwrite it?', array('!location' => $request['project_install_location'])))) {
@@ -2308,20 +2316,29 @@ function pm_drush_pm_download_destinatio
   if ($project['project_type'] == 'module') {
     $module_files = drush_scan_directory($project['full_project_path'], '/.*\.module/');
     if (empty($module_files)) {
-      $drush_command_files = drush_scan_directory($project['full_project_path'], '/.*\.drush.inc/');
-      if (!empty($drush_command_files)) {
-        $install_dir = drush_get_context('SHARE_PREFIX', '/usr') . '/share/drush/commands';
-        if (!is_dir($install_dir)) {
-          $install_dir = drush_server_home() . '/.drush';
-        }
-        // Make the .drush dir if it does not already exist.
-        if (!is_dir($install_dir)) {
-          mkdir($install_dir);
-        }
-        // Change the location if the mkdir worked.
-        if (is_dir($install_dir)) {
-          $project['project_install_location'] = $install_dir;
-        }
+      if ($project['name'] == 'drush') {
+        // $project['version'] is empty here, so compose the version from the $release structure.
+	$drush_release_version = $release['version_major'] . "." . $release['version_patch'] . (empty($release['version_extra']) ? '' : ('-' . $release['version_extra']));
+        if(($project['project_install_location'] != DRUSH_BASE_PATH) && ($release['version_major'] >= '4') && (drush_confirm(dt('You are downloading drush version !version to !path.  Would you instead like to install it over the version of drush you are running right now (!currentversion)?', array('!version' => $drush_release_version, '!path' => $project['project_install_location'], '!currentversion' => DRUSH_VERSION))))) {
+          $project['project_install_location'] = DRUSH_BASE_PATH;
+	}
+      }
+      else {
+	$drush_command_files = drush_scan_directory($project['full_project_path'], '/.*\.drush.inc/');
+	if (!empty($drush_command_files)) {
+          $install_dir = drush_get_context('SHARE_PREFIX', '/usr') . '/share/drush/commands';
+          if (!is_dir($install_dir)) {
+            $install_dir = drush_server_home() . '/.drush';
+          }
+          // Make the .drush dir if it does not already exist.
+          if (!is_dir($install_dir)) {
+            mkdir($install_dir);
+          }
+          // Change the location if the mkdir worked.
+          if (is_dir($install_dir)) {
+            $project['project_install_location'] = $install_dir;
+          }
+	}
       }
     }
   }
Index: commands/pm/updatecode.pm.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/pm/updatecode.pm.inc,v
retrieving revision 1.33
diff -u -p -r1.33 updatecode.pm.inc
--- commands/pm/updatecode.pm.inc	11 Dec 2010 04:52:19 -0000	1.33
+++ commands/pm/updatecode.pm.inc	11 Dec 2010 05:32:36 -0000
@@ -11,6 +11,14 @@
  * just to check on. In this case, say at the confirmation prompt.
  */
 function drush_pm_updatecode() {
+  // First check to see if there is a newer drush.
+  if (drush_get_option('self-update', TRUE)) {
+    if (drush_self_update() === TRUE) {
+      drush_log(dt('Installed new version of drush; exiting.'), 'ok');
+      return TRUE;
+    }
+  }
+  
   // We don't provide for other options here, so we supply an explicit path.
   drush_include_engine('update_info', 'drupal', NULL, DRUSH_BASE_PATH . '/commands/pm/update_info');
 
Index: examples/example.drushrc.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/examples/example.drushrc.php,v
retrieving revision 1.14
diff -u -p -r1.14 example.drushrc.php
--- examples/example.drushrc.php	9 Dec 2010 21:43:33 -0000	1.14
+++ examples/example.drushrc.php	11 Dec 2010 05:32:36 -0000
@@ -58,6 +58,11 @@
 // Load a drushrc.php configuration file from the current working directory.
 # $options['c'] = '.';
 
+// Control automatically check for updates in pm-updatecode and drush version.
+// FALSE = never check for updates.  'head' = allow updates to drush-HEAD.
+// TRUE (default) = allow updates to latest stable release.
+# $options['self-update'] = FALSE;
+
 // Specify CVS for checkouts
 # $options['package-handler'] = 'cvs';
 
Index: includes/command.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/command.inc,v
retrieving revision 1.92
diff -u -p -r1.92 command.inc
--- includes/command.inc	9 Dec 2010 05:53:59 -0000	1.92
+++ includes/command.inc	11 Dec 2010 05:32:37 -0000
@@ -653,6 +653,10 @@ function drush_parse_command() {
       $command = $implemented['help'];
       $command['arguments'] = $arguments;
     }
+    // Also convert --version into `drush version`
+    if (drush_get_option('version')) {
+      $command = $implemented['version'];
+    }
     else {
       _drush_prepare_command($command, $arguments);
     }
Index: includes/drush.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/drush.inc,v
retrieving revision 1.165
diff -u -p -r1.165 drush.inc
--- includes/drush.inc	9 Dec 2010 21:43:33 -0000	1.165
+++ includes/drush.inc	11 Dec 2010 05:32:38 -0000
@@ -171,6 +171,49 @@ function drush_drupal_version($drupal_ro
   return $version;
 }
 
+/**
+ * Install a newer version of drush, if available
+ */
+function drush_self_update() {  
+  // Do nothing unless we can write to the drush install location
+  if (!is_writable(DRUSH_BASE_PATH)) {
+    return FALSE;
+  }
+  // Don't check unless we have a datestamp in drush.info
+  $drush_info = drush_read_drush_info();
+  if (($drush_info === FALSE) || (!array_key_exists('datestamp', $drush_info) && !array_key_exists('drush_install_date', $drush_info))) {
+    return FALSE;
+  }
+  
+  // Get release info for drush
+  $info = _drush_pm_get_releases(array('drush'));
+  // Check for newer releases based on the datestamp if it is available, or based
+  // on the install date if it is not.  The install date is maintained in drush_read_drush_info().
+  $version_date = array_key_exists('datestamp', $drush_info) ? $drush_info['datestamp'] : $drush_info['drush_install_date'];
+  $newer_version = FALSE;
+  foreach ($info['drush']['releases'] as $version => $release_info) {
+    // We deliberately skip any dev releases.  To do a self-update
+    // from drush-HEAD to drush-HEAD, use `drush dl drush --dev`.
+    // We do not want to encourage people on HEAD to update every release.
+    // We -do- want to encourage people to upgrade across version-major
+    // releases, though (e.g. from drush-4 to drush-5).
+    if ((drush_get_option('self-update') == 'head') || (!array_key_exists('version_extra', $release_info) || ($release_info['version_extra'] != 'dev'))) {
+      if ($release_info['date'] > $version_date) {
+	$newer_version = $release_info['version'];
+	$version_date = $release_info['date'];
+      }
+    }
+  }
+  
+  if ($newer_version) {
+    if(drush_confirm(dt('A newer version of drush, !version, was released on !date.  Would you like to download and install it?', array('!version' => $newer_version, '!date' => date('Y-M-d', $version_date))))) {
+      // pm-download will select the most recent stable release, which is what we want.
+      drush_invoke_process_args("pm-download", array("drush"), array("destination" => DRUSH_BASE_PATH, 'y' => TRUE));
+    }    
+  }
+  
+  return $newer_version !== FALSE;
+}
 
 function drush_drupal_cache_clear_all() {
   $prior = drush_get_context('DRUSH_AFFIRMATIVE');
@@ -239,6 +282,7 @@ function drush_get_global_options() {
   $options['--nocolor']                = dt("Suppress color highlighting on log messages.");
   $options['--show-passwords']         = dt("Show database passwords in commands that display connection information.");
   $options['-h, --help']               = dt("This help system.");
+  $options['--version']                = dt("Show drush version.");
   $options['--php']                    = dt("The absolute path to your PHP intepreter, if not 'php' in the path.");
   return $options;
 }
Index: includes/environment.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/drush/includes/environment.inc,v
retrieving revision 1.107
diff -u -p -r1.107 environment.inc
--- includes/environment.inc	6 Dec 2010 21:57:08 -0000	1.107
+++ includes/environment.inc	11 Dec 2010 05:32:39 -0000
@@ -1225,8 +1225,64 @@ function drush_find_drush() {
  */
 function drush_read_drush_info() {
   $drush_info_file = dirname(__FILE__) . '/../drush.info';
+  $drush_info_cache_file = dirname(__FILE__) . '/../.drush-cache.info';
+  
+  $drush_info = parse_ini_file($drush_info_file);
+  if (($drush_info !== FALSE) && (!array_key_exists('datestamp', $drush_info))) {
+    $drush_info_cache = array();
+    if (file_exists($drush_info_cache_file)) {
+      $drush_info_cache = parse_ini_file($drush_info_cache_file);
+    }
+    if (!array_key_exists('drush_install_date', $drush_info_cache) && (is_writable(dirname($drush_info_cache_file)))) {
+      $drush_info_cache['drush_install_date'] = time();
+      write_ini_file($drush_info_cache, $drush_info_cache_file);
+    }
+    $drush_info = array_merge($drush_info, $drush_info_cache);
+  }
+  
+  return $drush_info;
+}
+
+// Write an ini file back to disk
+function write_ini_file($assoc_arr, $path, $has_sections = FALSE) {
+  $content = ""; 
+
+  if ($has_sections) { 
+    foreach ($assoc_arr as $key=>$elem) { 
+      $content .= "[".$key."]\n"; 
+      foreach ($elem as $key=>$elem2) { 
+        if(is_array($elem2)) { 
+          for($i=0;$i<count($elem2);$i++) { 
+            $content .= $key."[] = \"".$elem2[$i]."\"\n"; 
+          } 
+        } 
+        else if($elem2=="") {
+	  $content .= $key." = \n"; 
+	}
+        else {
+	  $content .= $key." = \"".$elem2."\"\n"; 
+	}
+      } 
+    } 
+  } 
+  else { 
+    foreach ($assoc_arr as $key=>$elem) { 
+      if(is_array($elem)) { 
+        for($i=0;$i<count($elem);$i++) { 
+          $content .= $key."[] = \"".$elem[$i]."\"\n"; 
+        } 
+      } 
+      else if($elem=="") {
+        $content .= $key." = \n"; 
+      }
+      else {
+        $content .= $key." = \"".$elem."\"\n"; 
+      }
+    } 
+  } 
 
-  return parse_ini_file($drush_info_file);
+  file_put_contents($path, $content);
+  return TRUE;
 }
 
 /**
