/[drupal]/contributions/modules/drush/drush.php
ViewVC logotype

Diff of /contributions/modules/drush/drush.php

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.32 by weitzman, Sat Dec 6 14:55:50 2008 UTC revision 1.33 by weitzman, Sat Dec 6 21:34:56 2008 UTC
# Line 1  Line 1 
1  #!/usr/bin/env php  #!/usr/bin/env php
2  <?php  <?php
3    // $Id$
 // $Id: drush.php,v 1.31 2008/11/28 17:18:46 adrian Exp $  
4    
5  /**  /**
6   * @file   * @file
# Line 10  Line 9 
9   * @requires PHP CLI 4.3.0, PHP CLI 5.x, or newer.   * @requires PHP CLI 4.3.0, PHP CLI 5.x, or newer.
10   */   */
11    
 define('DRUSH_DRUPAL_BOOTSTRAP', 'includes/bootstrap.inc');  
   
12  // Terminate immediately unless invoked as a command line script  // Terminate immediately unless invoked as a command line script
13  if (!drush_verify_cli()) {  if (!drush_verify_cli()) {
14    die('drush.php is designed to run via the command line.');    die('drush.php is designed to run via the command line.');
15  }  }
16    
17    require_once dirname(__FILE__) . '/includes/environment.inc';
18    require_once dirname(__FILE__) . '/includes/command.inc';
19    require_once dirname(__FILE__) . '/includes/drush.inc';
20    
21  exit(drush_bootstrap($GLOBALS['argc'], $GLOBALS['argv']));  exit(drush_bootstrap($GLOBALS['argc'], $GLOBALS['argv']));
22    
23  /**  /**
# Line 27  exit(drush_bootstrap($GLOBALS['argc'], $ Line 28  exit(drush_bootstrap($GLOBALS['argc'], $
28   * access to.   * access to.
29   *   *
30   * @return   * @return
31   *   A boolean value that is true when PHP is being run through the command line,   *   A boolean value that is true when PHP is being run through the command line,
32   *   and false if being run through cgi or mod_php.   *   and false if being run through cgi or mod_php.
33   */   */
34  function drush_verify_cli() {  function drush_verify_cli() {
35    if (php_sapi_name() == 'cgi') {    if (php_sapi_name() == 'cgi') {
36      return (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0);      return (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0);
37    }    }
38    
39    return (php_sapi_name() == 'cli');    return (php_sapi_name() == 'cli');
40  }  }
41    
42  /**  /**
43   * Load drushrc files (if available) from several possible locations.   * The main Drush function.
44   *   *
45   * @param $root   * - Parses the command line arguments, configuration files and environment.
46   *   The Drupal root to check.   * - Prepares and executes a Drupal bootstrap, if possible,
47     * - Dispatches the given command.
48     *
49     * @return
50     *   Whatever the given command returns.
51   */   */
 function drush_load_rc($root) {  
   global $override, $args;  
   
   # Specified rc file  
   $configs[] = drush_get_option(array('c', 'config'), FALSE);  
   # Rc file in same directory as the drush.php file  
   $configs[] = dirname($_SERVER['SCRIPT_FILENAME']) . "/drushrc.php";  
   # Rc file in current directory  
   $configs[] = "drushrc.php";  
   # Rc file in located drupal root  
   $configs[] = drush_get_option(array('r', 'root'), $root). '/drushrc.php';  
   # Rc file in user's home directory  
   $configs[] = $_SERVER['HOME'] . '/.drushrc.php';  
   
   foreach ($configs as $config) {  
     if (file_exists($config)) {  
       define('DRUSH_CONFIG', $config);  
       require_once($config);  
       if (is_array($options)) {  
         $args['options'] = array_merge($options, $args['options']); # Sets all the default options for drush  
       }  
       break;  
     }  
   }  
 }  
   
52  function drush_bootstrap($argc, $argv) {  function drush_bootstrap($argc, $argv) {
   global $args, $override, $conf;  
   
53    // Parse command line options and arguments.    // Parse command line options and arguments.
54    $args = drush_parse_args($argv, array('h', 'u', 'r', 'l', 'c'));    $GLOBALS['args'] = drush_parse_args($argv, array('c', 'h', 'u', 'r', 'l', 'i'));
55    
56    // We use PWD if available because getcwd() resolves symlinks, which    $path = drush_cwd();
57    // could take us outside of the Drupal root, making it impossible to find.  
58    $path = $_SERVER['PWD'];    // Load available .drushrc file(s). Allows you to provide defaults for options and variables.
59    if (empty($path)) {    drush_load_config($path);
     $path = getcwd();  
   }  
   
   // Convert windows paths.  
   $path = drush_convert_path($path);  
   
   // Try and locate the Drupal root directory  
   $root = _drush_locate_root($path);  
   
   // Load .drushrc file if available. Allows you to provide defaults for options and variables.  
   drush_load_rc($root);  
   
   $uri = FALSE;  
   // If the current directory contains a settings.php we assume that is the desired site URI.  
   if (file_exists('./settings.php')) {  
     // Export the following settings.php variables to the global namespace.  
     global $db_url, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access;  
     // If the settings.php has a defined path we use the URI from that.  
     include_once('./settings.php');  
     if (isset($base_url)) {  
       $uri = $base_url;  
     }  
     else {  
       // Alternatively we default to the name of the current directory, if it is not 'default'.  
       $elements = explode('/', $path);  
       $current = array_pop($elements);  
       if ($current != 'default') {  
         $uri = 'http://'. $current;  
       }  
     }  
   }  
60    
61    // Define basic options as constants.    // Define basic options as constants.
   define('DRUSH_URI',         drush_get_option(array('l', 'uri'), $uri));  
62    define('DRUSH_VERBOSE',     drush_get_option(array('v', 'verbose'), FALSE));    define('DRUSH_VERBOSE',     drush_get_option(array('v', 'verbose'), FALSE));
63    define('DRUSH_AFFIRMATIVE', drush_get_option(array('y', 'yes'), FALSE));    define('DRUSH_AFFIRMATIVE', drush_get_option(array('y', 'yes'), FALSE));
64    define('DRUSH_SIMULATE',    drush_get_option(array('s', 'simulate'), FALSE));    define('DRUSH_SIMULATE',    drush_get_option(array('s', 'simulate'), FALSE));
65    
66    // TODO: Make use of this as soon as the external    define('DRUSH_URI',         drush_get_option(array('l', 'uri'), drush_site_uri($path)));
67    define('DRUSH_USER',        drush_get_option(array('u', 'user'), 0));    define('DRUSH_USER',        drush_get_option(array('u', 'user'), 0));
68    
69    // If no root is defined, we try to guess from the current directory.    // Preliminary check on command descriptor
70    define('DRUSH_DRUPAL_ROOT',  drush_get_option(array('r', 'root'), $root));    list($command, $arguments) = drush_parse_command($GLOBALS['args']['commands']);
   
   // Possible temporary. See http://drupal.org/node/312421.  
   define('DRUPAL_ROOT', DRUSH_DRUPAL_ROOT);  
71    
72    // If the Drupal directory can't be found, and no -r option was specified,    if ($drupal_root = drush_get_option(array('r', 'root'), drush_locate_root($path))) {
   // or the path specified in -r does not point to a Drupal directory,  
   // we have no alternative but to give up the ghost at this point.  
   // (NOTE: t() is not available yet.)  
   if (!DRUSH_DRUPAL_ROOT || !is_dir(DRUSH_DRUPAL_ROOT) || !file_exists(DRUSH_DRUPAL_ROOT . '/' . DRUSH_DRUPAL_BOOTSTRAP))  {  
     $dir = '';  
     if (DRUSH_DRUPAL_ROOT) {  
       $dir = ' in ' . DRUSH_DRUPAL_ROOT;  
     }  
     // Provide a helpful exit message, letting the user know where we looked  
     // (if we looked at all) and a hint on how to specify the directory manually.  
     $message = "E: Could not locate a Drupal installation directory$dir. Aborting.\n";  
     $message .= "Hint: You can specify your Drupal installation directory with the --root\n";  
     $message .= "parameter on the command line or \$options['root'] in your drushrc.php file.\n";  
     die($message);  
   }  
73    
74    // Fake the necessary HTTP headers that Drupal needs:      drush_drupal_set_environment($drupal_root);
   if (DRUSH_URI) {  
     $drupal_base_url = parse_url(DRUSH_URI);  
     $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];  
     $_SERVER['PHP_SELF'] = $drupal_base_url['path'].'/index.php';  
   }  
   else {  
     $_SERVER['HTTP_HOST'] = NULL;  
     $_SERVER['PHP_SELF'] = NULL;  
   }  
   $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];  
   $_SERVER['REMOTE_ADDR'] = '';  
   $_SERVER['REQUEST_METHOD'] = NULL;  
   $_SERVER['SERVER_SOFTWARE'] = NULL;  
   $_SERVER['HTTP_USER_AGENT'] = NULL;  
75    
76    // Change to Drupal root dir.      // Bootstrap Drupal.
77    chdir(DRUSH_DRUPAL_ROOT);      if (drush_drupal_bootstrap($drupal_root, $command['bootstrap'])) {
78    // Bootstrap Drupal.        /**
79    _drush_bootstrap_drupal();         * Allow the drushrc.php file to override $conf settings.
80    /**         * This is a separate variable because the $conf array gets initialized to an empty array,
81     * Allow the drushrc.php file to override $conf settings.         * in the drupal bootstrap process, and changes in settings.php would wipe out the drushrc.php
82     * This is a separate variable because the $conf array gets initialized to an empty array,         * settings
83     * in the drupal bootstrap process, and changes in settings.php would wipe out the drushrc.php         */
84     * settings        if (is_array($GLOBALS['override'])) {
85     */          $GLOBALS['conf'] = array_merge($GLOBALS['conf'], $GLOBALS['override']);
86    if (is_array($override)) {        }
     $conf = array_merge($conf, $override);  
   }  
   
   // Login the specified user (if given).  
   if (DRUSH_USER) {  
     _drush_login(DRUSH_USER);  
   }  
87    
88    // Now we can use all of Drupal.        // Login the specified user (if given).
89          if (DRUSH_USER) {
90            drush_drupal_login(DRUSH_USER);
91          }
92    
93          // Now we can use all of Drupal.
94        }
95      }
96    
97    if (DRUSH_SIMULATE) {    if (DRUSH_SIMULATE) {
98      drush_print(t('SIMULATION MODE IS ENABLED. NO ACTUAL ACTION WILL BE TAKEN. SYSTEM WILL REMAIN UNCHANGED.'));      drush_print('SIMULATION MODE IS ENABLED. NO ACTUAL ACTION WILL BE TAKEN. SYSTEM WILL REMAIN UNCHANGED.');
99    }    }
100    
101    // Dispatch the command.    // Dispatch the command(s).
102    $output = drush_dispatch($args['commands']);    $output = drush_dispatch($GLOBALS['args']['commands']);
103    
104    // prevent a '1' at the end of the outputs    // prevent a '1' at the end of the outputs
105    if ($output === true) {    if ($output === TRUE) {
106      $output = '';      $output = '';
107    }    }
108    
# Line 197  function drush_bootstrap($argc, $argv) { Line 110  function drush_bootstrap($argc, $argv) {
110    return $output;    return $output;
111  }  }
112    
   
113  /**  /**
114   * Exhaustive depth-first search to try and locate the Drupal root directory.   * Sets up various constants and $_SERVER entries used by
115   * This makes it possible to run drush from a subdirectory of the drupal root.   * Drupal, essentially mimicking a webserver environment.
116   *   *
117   * @param $path   * @param string
118   *   The path the start the search from.   *   Path to Drupal installation root.
119   */   */
120  function _drush_locate_root($path) {  function drush_drupal_set_environment($drupal_root) {
121    // Check the current path.    define('DRUSH_DRUPAL_ROOT', $drupal_root);
122    if (file_exists($path . '/' . DRUSH_DRUPAL_BOOTSTRAP)) {    // Possibly temporary. See http://drupal.org/node/312421.
123      return $path;    define('DRUPAL_ROOT', DRUSH_DRUPAL_ROOT);
   }  
   // Move up dir by dir and check each.  
   while ($path = _drush_locate_root_moveup($path)) {  
     if (file_exists($path . '/' . DRUSH_DRUPAL_BOOTSTRAP)) {  
       return $path;  
     }  
   }  
124    
125    return FALSE;    // Fake the necessary HTTP headers that Drupal needs:
126      if (DRUSH_URI) {
127        $drupal_base_url = parse_url(DRUSH_URI);
128        $_SERVER['HTTP_HOST'] = $drupal_base_url['host'];
129        $_SERVER['PHP_SELF'] = $drupal_base_url['path'] . '/index.php';
130      }
131      else {
132        $_SERVER['HTTP_HOST'] = 'default';
133        $_SERVER['PHP_SELF'] = '/index.php';
134      }
135      $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'];
136      $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
137      $_SERVER['REQUEST_METHOD']  = NULL;
138      $_SERVER['SERVER_SOFTWARE'] = NULL;
139      $_SERVER['HTTP_USER_AGENT'] = NULL;
140  }  }
141    
142  function _drush_locate_root_moveup($path) {  /**
143    if (empty($path)) {   * Shutdown function for use while Drupal is bootstrapping.
144      return FALSE;   */
145    function drush_shutdown() {
146      if (!defined('DRUSH_DRUPAL_BOOTSTRAPPED')) {
147        $site_path = drush_site_path();
148        $message = "E: Drush was not able to start (bootstrap) Drupal.\n";
149        $message .= "Hint: This error often occurs when Drush is trying to bootstrap a site\n";
150        $message .= "that has not been installed or does not have a configured database.\n";
151        $message .= "Drush was looking for the site in '$site_path'. You can select another site\n";
152        $message .= "with a working database setup by specifying the URI to use with the --uri\n";
153        $message .= "parameter on the command line or \$options['uri'] in your drushrc.php file.\n";
154        die($message);
155    }    }
   $path = explode('/', $path);  
   // Move one directory up.  
   array_pop($path);  
   return implode($path, '/');  
156  }  }
157    
158  /**  /**
159   * Bootstrap Drupal.   * Bootstrap Drupal.
160     *
161     * @param string
162     *   path to Drupal installation root.
163     *
164     * @param mixed
165     *   NULL for a full bootstrap or any of the Drupal bootstrap sequence constants.
166     *   These depend on the Drupal major version.
167     *
168     * @return
169     *   TRUE if Drupal successfully bootstrapped to the given state.
170   */   */
171  function _drush_bootstrap_drupal() {  function drush_drupal_bootstrap($drupal_root, $bootstrap = NULL) {
172      // Change to Drupal root dir.
173      chdir($drupal_root);
174    
175    require_once DRUSH_DRUPAL_BOOTSTRAP;    require_once DRUSH_DRUPAL_BOOTSTRAP;
176    
177    if (($conf_path = conf_path()) && !file_exists("./$conf_path/settings.php")) {    if (($conf_path = conf_path()) && !file_exists("./$conf_path/settings.php")) {
178      // Provide a helpful exit message, letting the user know where we looked      return FALSE;
     // (if we looked at all) and a hint on how to specify the URI manually.  
     $message = "E: Unable to load Drupal configuration from $conf_path. Aborting.\n";  
     $message .= "Hint: You can specify your Drupal URI to use with the --uri\n";  
     $message .= "parameter on the command line or \$options['uri'] in your drushrc.php file.\n";  
     die($message);  
179    }    }
180    
181    // The bootstrap can fail silently, so we catch that in a shutdown function.    // The bootstrap can fail silently, so we catch that in a shutdown function.
182    register_shutdown_function('drush_shutdown');    register_shutdown_function('drush_shutdown');
183    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);    if (is_null($bootstrap)) {
184    if (module_exists('drush')) {      drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
     require_once drupal_get_path('module', 'drush') . '/drush.inc';  
185    }    }
186    else {    else {
187      $message = "E: You must enable the Drush module for the site you want to use.\n";      drupal_bootstrap($bootstrap);
     $message .= "Hint: Drush was looking in the site '$conf_path'. You can select another site\n";  
     $message .= "with Drush enabled by specifying the Drupal URI to use with the --uri\n";  
     $message .= "parameter on the command line or \$options['uri'] in your drushrc.php file.\n";  
     die($message);  
188    }    }
 }  
189    
190  function drush_shutdown() {    // The bootstrap succeeded.
191    if (!function_exists('drupal_set_content')) {    define('DRUSH_DRUPAL_BOOTSTRAPPED', TRUE);
192      $message = "E: Drush was not able to start (bootstrap) Drupal.\n";    return TRUE;
     $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 \$db_url.\n";  
     $message .= "Drush was looking in the site '$conf_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";  
     die($message);  
   }  
193  }  }
194    
195  /**  /**
196   * Log a certain user in.   * Log the given user in to a bootstrapped Drupal site.
197     *
198     * @param mixed
199     *   Numeric user id or user name.
200     *
201     * @return boolean
202     *   TRUE if user was logged in, otherwise FALSE.
203   */   */
204  function _drush_login($drush_user) {  function drush_drupal_login($drush_user) {
205    global $user;    global $user;
206    $user = module_invoke('user', 'load', is_numeric($drush_user) ? array('uid' => $drush_user) : array('name' => $drush_user));    $user = module_invoke('user', 'load', is_numeric($drush_user) ? array('uid' => $drush_user) : array('name' => $drush_user));
207    
208    if (empty($user)) {    if (empty($user)) {
209      if (is_numeric($drush_user)) {      if (is_numeric($drush_user)) {
210        drush_die(t('Could not login with user ID #%user.', array('%user' => $drush_user)));        drush_die(dt('Could not login with user ID #%user.', array('%user' => $drush_user)));
211      }      }
212      else {      else {
213        drush_die(t('Could not login with user account `%user\'.', array('%user' => $drush_user)));        drush_die(dt('Could not login with user account `%user\'.', array('%user' => $drush_user)));
214      }      }
215      return FALSE;      return FALSE;
216    }    }
217    
218    return TRUE;    return TRUE;
219  }  }
   
 /**  
  * Parse console arguments.  
  *  
  * @param $args  
  *   The console argument array (usually $argv)  
  * @param $arg_opts  
  *   An array of options that are followed by an argument.  
  *   e.g. shell.php -u admin -v --> $arg_opts = array('u')  
  * @param $default_options  
  * @return  
  *   A associative array:  
  *   $return['commands'] ia a numeric array of all commands,  
  *   $return['options'] contains the options. The option keys  
  *   are always noted without - or -- and are set to TRUE if they were  
  *   invoked, to the argument if followed by an argument, and if not present  
  *   to their default value or FALSE if no default value was specified.  
  */  
 function drush_parse_args($args = array(), $arg_opts = array(), $default_options = array()) {  
   $options = $default_options;  
   $commands = array();  
   
   for ($i = 1; $i < count($args); $i++) {  
     $opt = $args[$i];  
     // Is the arg an option (starting with '-')?  
     if ($opt{0} == "-" && strlen($opt) != 1) {  
       // Do we have multiple options behind one '-'?  
       if (strlen($opt) > 2 && $opt{1} != "-") {  
         // Each char becomes a key of its own.  
         for ($j = 1; $j < strlen($opt); $j++) {  
           $options[substr($opt, $j, 1)] = true;  
         }  
       }  
       // Do we have a longopt (starting with '--')?  
       elseif ($opt{1} == "-") {  
         if ($pos = strpos($opt, '=')) {  
           $options[substr($opt, 2, $pos - 2)] = substr($opt, $pos + 1);  
         }  
         else {  
           $options[substr($opt, 2)] = true;  
         }  
       }  
       else {  
         $opt = substr($opt, 1);  
         // Check if the current opt is in $arg_opts (= has to be followed by an argument).  
         if ((in_array($opt, $arg_opts))) {  
           if (($args[$i+1] == NULL) || ($args[$i+1] == "") || ($args[$i + 1]{0} == "-")) {  
             exit("Invalid input: -$opt needs to be followed by an argument.");  
           }  
           $options[$opt] = $args[$i + 1];  
           $i++;  
         }  
         else {  
           $options[$opt] = true;  
         }  
       }  
     }  
     // If it's not an option, it's a command.  
     else {  
       $commands[] = $opt;  
     }  
   }  
   return array('options' => $options, 'commands' => $commands);  
 }  
   
 /**  
  * Get the value for an option.  
  *  
  * If the first argument is an array, then it checks wether one of the options  
  * exists and return the value of the first one found. Useful for allowing both  
  * -h and --host-name  
  *  
  */  
 function drush_get_option($option, $default = NULL) {  
   $options = $GLOBALS['args']['options'];  
   if (is_array($option)) {  
     foreach ($option as $current) {  
       if (array_key_exists($current, $options)) {  
         return $options[$current];  
       }  
     }  
     return $default;  
   }  
   
   if (!array_key_exists($option, $options)) {  
     return $default;  
   }  
   else {  
     return $options[$option];  
   }  
 }  
   
 /**  
  * Converts a Windows path (dir1\dir2\dir3) into a Unix path (dir1/dir2/dir3).  
  */  
 function drush_convert_path($path) {  
   return str_replace('\\','/', $path);  
 }  
   

Legend:
Removed from v.1.32  
changed lines
  Added in v.1.33

  ViewVC Help
Powered by ViewVC 1.1.3