- // Load Drush core include files, and parse command line arguments.
- if (drush_preflight_prepare() === FALSE) {
- return(1);
- }
- // Start code coverage collection.
- if ($coverage_file = drush_get_option('drush-coverage', FALSE)) {
- drush_set_context('DRUSH_CODE_COVERAGE', $coverage_file);
- xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
- register_shutdown_function('drush_coverage_shutdown');
- }
-
- // Load the global Drush configuration files, and global Drush commands.
- // Find the selected site based on --root, --uri or cwd
- // Preflight the selected site, and load any configuration and commandfiles associated with it.
- // Select and return the bootstrap class.
- $bootstrap = drush_preflight();
-
- // Reset our bootstrap phase to the beginning
- drush_set_context('DRUSH_BOOTSTRAP_PHASE', DRUSH_BOOTSTRAP_NONE);
-
- $return = '';
- if (!drush_get_error()) {
- if ($file = drush_get_option('early', FALSE)) {
- require_once drush_is_absolute_path($file) ? $file : DRUSH_BASE_PATH . DIRECTORY_SEPARATOR . $file;
- $function = 'drush_early_' . basename($file, '.inc');
- if (function_exists($function)) {
- if ($return = $function()) {
- // If the function returns FALSE, we continue and attempt to bootstrap
- // as normal. Otherwise, we exit early with the returned output.
- if ($return === TRUE) {
- $return = '';
- }
- }
- }
- }
- else {
- // Do any necessary preprocessing operations on the command,
- // perhaps handling immediately.
- $command_handled = drush_preflight_command_dispatch();
- if (!$command_handled) {
- $return = $bootstrap->bootstrap_and_dispatch();
- }
- }
- }
- // TODO: Get rid of global variable access here, and just trust
- // the bootstrap object returned from drush_preflight(). This will
- // require some adjustments to Drush bootstrapping.
- // See: https://github.com/drush-ops/drush/pull/1303
- if ($bootstrap = drush_get_bootstrap_object()) {
- $bootstrap->terminate();
- }
- drush_postflight();
- if (is_object($return)) {
- $return = 0;
- }
-
- // How strict are we? If we are very strict, turn 'ok' into 'error'
- // if there are any warnings in the log.
- if (($return == 0) && (drush_get_option('strict') > 1) && drush_log_has_errors()) {
- $return = 1;
- }
-
- // After this point the drush_shutdown function will run,
- // exiting with the correct exit code.
- return $return;
-}
-
-/**
- * Prepare Drush for preflight.
- *
- * Runs before drush_main().
- *
- * @see drush_main()
- * @see drush.php
- */
-function drush_preflight_prepare() {
- define('DRUSH_BASE_PATH', dirname(dirname(__FILE__)));
- // Local means that autoload.php is inside of Drush. That is, Drush is its own Composer project.
- // Global means autoload.php is outside of Drush. That is, Drush is a dependency of a bigger project.
- $local_vendor_path = DRUSH_BASE_PATH . '/vendor/autoload.php';
- $global_vendor_path = DRUSH_BASE_PATH . '/../../../vendor/autoload.php';
-
- // Check for a local composer install or a global composer install. Vendor dirs are in different spots).
- if (file_exists($local_vendor_path)) {
- $vendor_path = $local_vendor_path;
- }
- elseif (file_exists($global_vendor_path)) {
- $vendor_path = $global_vendor_path;
- }
- else {
- $msg = "Unable to load autoload.php. Run composer install to fetch dependencies and write this file (http://docs.drush.org/en/master/install-alternative/). Or if you prefer, use the drush.phar which already has dependencies included (http://docs.drush.org/en/master/install).\n";
- fwrite(STDERR, $msg);
- return FALSE;
- }
-
- $classloader = require $vendor_path;
-
- require_once DRUSH_BASE_PATH . '/includes/startup.inc';
- require_once DRUSH_BASE_PATH . '/includes/bootstrap.inc';
- require_once DRUSH_BASE_PATH . '/includes/environment.inc';
- require_once DRUSH_BASE_PATH . '/includes/annotationcommand_adapter.inc';
- require_once DRUSH_BASE_PATH . '/includes/command.inc';
- require_once DRUSH_BASE_PATH . '/includes/drush.inc';
- require_once DRUSH_BASE_PATH . '/includes/engines.inc';
- require_once DRUSH_BASE_PATH . '/includes/backend.inc';
- require_once DRUSH_BASE_PATH . '/includes/batch.inc';
- require_once DRUSH_BASE_PATH . '/includes/context.inc';
- require_once DRUSH_BASE_PATH . '/includes/sitealias.inc';
- require_once DRUSH_BASE_PATH . '/includes/exec.inc';
- require_once DRUSH_BASE_PATH . '/includes/drupal.inc';
- require_once DRUSH_BASE_PATH . '/includes/output.inc';
- require_once DRUSH_BASE_PATH . '/includes/cache.inc';
- require_once DRUSH_BASE_PATH . '/includes/filesystem.inc';
- require_once DRUSH_BASE_PATH . '/includes/dbtng.inc';
- require_once DRUSH_BASE_PATH . '/includes/array_column.inc';
-
- // Stash our vendor path and classloader.
- drush_set_context('DRUSH_VENDOR_PATH', dirname($vendor_path));
- drush_set_context('DRUSH_CLASSLOADER', $classloader);
-
- // Can't log until we have a logger, so we'll create this ASAP.
- _drush_create_default_logger();
-
- // Terminate immediately unless invoked as a command line script
- if (!drush_verify_cli()) {
- return drush_set_error('DRUSH_REQUIREMENTS_ERROR', dt('Drush is designed to run via the command line.'));
- }
-
- // Check supported version of PHP.
- // Note: If this is adjusted, check other code that compares
- // PHP_VERSION, such as drush_json_encode(), runserver/runserver.drush.inc, and also
- // adjust _drush_environment_check_php_ini() and the php_prohibited_options
- // list in the drush script. See http://drupal.org/node/1748228
- define('DRUSH_MINIMUM_PHP', '5.4.5');
- if (version_compare(phpversion(), DRUSH_MINIMUM_PHP) < 0 && !getenv('DRUSH_NO_MIN_PHP')) {
- return drush_set_error('DRUSH_REQUIREMENTS_ERROR', dt('Your command line PHP installation is too old. Drush requires at least PHP !version. To suppress this check, set the environment variable DRUSH_NO_MIN_PHP=1', array('!version' => DRUSH_MINIMUM_PHP)));
- }
-
- if (!$return = _drush_environment_check_php_ini()) {
- return; // An error was logged.
- }
-
- $drush_info = drush_read_drush_info();
- define('DRUSH_VERSION', $drush_info['drush_version']);
- $version_parts = explode('.', DRUSH_VERSION);
- define('DRUSH_MAJOR_VERSION', $version_parts[0]);
- define('DRUSH_MINOR_VERSION', $version_parts[1]);
-
- define('DRUSH_REQUEST_TIME', microtime(TRUE));
-
- drush_set_context('argc', $GLOBALS['argc']);
- drush_set_context('argv', $GLOBALS['argv']);
-
- // Set an error handler and a shutdown function
- set_error_handler('drush_error_handler');
- register_shutdown_function('drush_shutdown');
- // We need some global options/arguments processed at this early stage.
- drush_parse_args();
-
- // Process initial global options such as --debug.
- _drush_preflight_global_options();
-
- drush_log(dt("Drush preflight prepare loaded autoloader at !autoloader", array('!autoloader' => realpath($vendor_path))), LogLevel::PREFLIGHT);
-}
-
-/**
- * During the initialization of Drush, this is the first
- * step where we load our configuration and commandfiles,
- * and select the site we are going to operate on; however,
- * we take no irreversible actions (e.g. site bootstrapping).
- * This allows commands that are declared with no bootstrap
- * to select a new site root and bootstrap it.
- *
- * In this step we will register the shutdown function,
- * parse the command line arguments and store them in their
- * related contexts.
- *
- * Configuration files (drushrc.php) that are
- * a) Specified on the command line
- * b) Stored in the root directory of drush.php
- * c) Stored in the home directory of the system user.
- *
- * Additionally the DRUSH_QUIET and DRUSH_BACKEND contexts,
- * will be evaluated now, as they need to be set very early in
- * the execution flow to be able to take affect.
- *
- * @return \Drush\Boot\Boot;
- */
-function drush_preflight() {
- // Create an alias '@none' to represent no Drupal site
- _drush_sitealias_cache_alias('@none', array('root' => '', 'uri' => ''));
-
- // Discover terminal width for pretty output.
- _drush_preflight_columns();
-
- // Display is tidy now that column width has been handled.
- drush_log(dt('Starting Drush preflight.'), LogLevel::PREFLIGHT);
-
- // Statically define a way to call drush again.
- define('DRUSH_COMMAND', drush_find_drush());
-
- // prime the CWD cache
- drush_cwd();
-
- // Set up base environment for system-wide file locations.
- _drush_preflight_base_environment();
-
- // Setup global alias_paths[] in context system.
- if (!drush_get_option('local')) {
- _drush_preflight_alias_path();
- }
- if (!drush_get_option('local')) {
- // Load a drushrc.php file in the drush.php's directory.
- drush_load_config('drush');
-
- // Load a drushrc.php file in the $ETC_PREFIX/etc/drush directory.
- drush_load_config('system');
-
- // Load a drushrc.php file at ~/.drushrc.php.
- drush_load_config('user');
-
- // Load a drushrc.php file in the ~/.drush directory.
- drush_load_config('home.drush');
- }
-
- // Load a custom config specified with the --config option.
- drush_load_config('custom');
-
- _drush_preflight_global_options();
- // Load all the commandfiles findable from any of the
- // scopes listed above.
- _drush_find_commandfiles_drush();
-
- // Look up the alias identifier that the user wants to use,
- // either via an argument or via 'site-set'.
- $target_alias = drush_sitealias_check_arg_and_site_set();
-
- // Process the site alias that specifies which instance
- // of Drush (local or remote) this command will operate on.
- // We must do this after we load our config files (so that
- // site aliases are available), but before the rest of
- // Drush preflight and Drupal root bootstrap phase are
- // done, since site aliases may set option values that
- // affect these phases.
- $alias_record = _drush_sitealias_set_context_by_name($target_alias);
-
- // Find the selected site based on --root, --uri or cwd
- drush_preflight_root();
-
- // Preflight the selected site, and load any configuration and commandfiles associated with it.
- drush_preflight_site();
-
- // Check to see if anything changed during the 'site' preflight
- // that might allow us to find our alias record now
- if (empty($alias_record)) {
- $alias_record = _drush_sitealias_set_context_by_name($target_alias);
-
- // If the site alias settings changed late in the preflight,
- // then run the preflight for the root and site contexts again.
- if (!empty($alias_record)) {
- $remote_host = drush_get_option('remote-host');
- if (!isset($remote_host)) {
- drush_preflight_root();
- drush_preflight_site();
- }
- }
- }
-
- // Fail if we could not find the selected site alias.
- if ($target_alias && empty($alias_record)) {
- // We will automatically un-set the site-set alias if it could not be found.
- // Otherwise, we'd be stuck -- the user would only be able to execute Drush
- // commands again after `drush @none site-set @none`, and most folks would
- // have a hard time figuring that out.
- $site_env = drush_sitealias_site_get();
- if ($site_env == $target_alias) {
- drush_sitealias_site_clear();
- }
- return drush_set_error('DRUSH_BOOTSTRAP_NO_ALIAS', dt("Could not find the alias !alias", array('!alias' => $target_alias)));
- }
-
- // If applicable swaps in shell alias values.
- drush_shell_alias_replace($target_alias);
-
- // Copy global options to their respective contexts
- _drush_preflight_global_options();
-
- // Set environment variables based on #env-vars.
- drush_set_environment_vars($alias_record);
-
- // Select the bootstrap object and return it.
- return drush_select_bootstrap_class();
-}
-
-/**
- * If --root is provided, set context.
- */
-function drush_preflight_root() {
- $root = drush_get_option('root');
- if (!isset($root)) {
- $root = drush_locate_root();
- }
- if ($root) {
- $root = realpath($root);
- }
- // @todo This context name should not mention Drupal.
- // @todo Drupal code should use DRUSH_DRUPAL_ROOT instead of this constant.
- drush_set_context('DRUSH_SELECTED_DRUPAL_ROOT', $root);
-
- // Load the config options from Drupal's /drush, ../drush, and sites/all/drush directories,
- // even prior to bootstrapping the root.
- drush_load_config('drupal');
-
- // Search for commandfiles in the root locations
- $discovery = annotationcommand_adapter_get_discovery();
- $searchpath = [dirname($root) . '/drush', "$root/drush", "$root/sites/all/drush"];
-
- $drush_root_extensions = $discovery->discover($searchpath, '\Drush');
- drush_set_context(
- 'DRUSH_ANNOTATED_COMMANDFILES',
- array_merge(
- drush_get_context('DRUSH_ANNOTATED_COMMANDFILES'),
- $drush_root_extensions
- )
- );
-}
-
-function drush_preflight_site() {
- // Load the Drupal site configuration options upfront.
- drush_load_config('site');
-
- // Determine URI and set constants/contexts accordingly. Keep this after loading of drupal,site configs.
- _drush_preflight_uri();
-
- // If someone set 'uri' in the 'site' context, then copy it
- // to the 'process' context (to give it a higher priority
- // than the 'cli' and 'alias' contexts) and reset our selected
- // site and @self alias.
- $uri = drush_get_option('uri');
- if ($uri != drush_get_option('uri', $uri, 'site')) {
- drush_set_option('uri', drush_get_option('uri', $uri, 'site'));
- _drush_preflight_uri();
- }
-
- // Create a @self site alias record.
- drush_sitealias_create_self_alias();
-}
-
-function _drush_preflight_global_options() {
- // Debug implies verbose
- $verbose = drush_get_option('verbose', FALSE);
- $debug = drush_get_option('debug', FALSE);
- drush_set_context('DRUSH_VERBOSE', $verbose || $debug);
- drush_set_context('DRUSH_DEBUG', $debug);
- drush_set_context('DRUSH_DEBUG_NOTIFY', $verbose && $debug);
- drush_set_context('DRUSH_SIMULATE', drush_get_option('simulate', FALSE));
-
- // Backend implies affirmative unless negative is explicitly specified
- drush_set_context('DRUSH_NEGATIVE', drush_get_option('no', FALSE));
- drush_set_context('DRUSH_AFFIRMATIVE', drush_get_option(array('yes', 'pipe'), FALSE) || (drush_get_context('DRUSH_BACKEND') && !drush_get_context('DRUSH_NEGATIVE')));
-
- // Pipe implies quiet.
- drush_set_context('DRUSH_QUIET', drush_get_option(array('quiet', 'pipe')));
- drush_set_context('DRUSH_PIPE', drush_get_option('pipe'));
-
- // Suppress colored logging if --nocolor option is explicitly given or if
- // terminal does not support it.
- $nocolor = (drush_get_option('nocolor', FALSE));
- if (!$nocolor) {
- // Check for colorless terminal. If there is no terminal, then
- // 'tput colors 2>&1' will return "tput: No value for $TERM and no -T specified",
- // which is not numeric and therefore will put us in no-color mode.
- $colors = exec('tput colors 2>&1');
- $nocolor = !($colors === FALSE || (is_numeric($colors) && $colors >= 3));
- }
- drush_set_context('DRUSH_NOCOLOR', $nocolor);
-}
-
-/**
- * Sets up basic environment that controls where Drush looks for files on a
- * system-wide basis. Important to call for "early" functions that need to
- * work with unit tests.
- */
-function _drush_preflight_base_environment() {
- // Copy ETC_PREFIX and SHARE_PREFIX from environment variables if available.
- // This alters where we check for server-wide config and alias files.
- // Used by unit test suite to provide a clean environment.
- if (getenv('ETC_PREFIX')) drush_set_context('ETC_PREFIX', getenv('ETC_PREFIX'));
- if (getenv('SHARE_PREFIX')) drush_set_context('SHARE_PREFIX', getenv('SHARE_PREFIX'));
-
- drush_set_context('DOC_PREFIX', DRUSH_BASE_PATH);
- if (!file_exists(DRUSH_BASE_PATH . '/README.md') && file_exists(drush_get_context('SHARE_PREFIX', '/usr') . '/share/doc/drush' . '/README.md')) {
- drush_set_context('DOC_PREFIX', drush_get_context('SHARE_PREFIX', '/usr') . '/share/doc/drush');
- }
-
- $default_prefix_configuration = drush_is_windows() ? getenv('ALLUSERSPROFILE') . '/Drush' : '';
- $default_prefix_commandfile = drush_is_windows() ? getenv('ALLUSERSPROFILE') . '/Drush' : '/usr';
- $site_wide_configuration_dir = drush_get_context('ETC_PREFIX', $default_prefix_configuration) . '/etc/drush';
- $site_wide_commandfile_dir = drush_get_context('SHARE_PREFIX', $default_prefix_commandfile) . '/share/drush/commands';
- drush_set_context('DRUSH_SITE_WIDE_CONFIGURATION', $site_wide_configuration_dir);
- drush_set_context('DRUSH_SITE_WIDE_COMMANDFILES', $site_wide_commandfile_dir);
-
- $server_home = drush_server_home();
- if (isset($server_home)) {
- drush_set_context('DRUSH_PER_USER_CONFIGURATION', $server_home . '/.drush');
- }
-}
-
-/*
- * Set the terminal width, used for wrapping table output.
- * Normally this is exported using tput in the drush script.
- * If this is not present we do an additional check using stty here.
- * On Windows in CMD and PowerShell is this exported using mode con.
- */
-function _drush_preflight_columns() {
- if (!($columns = getenv('COLUMNS'))) {
- // Trying to export the columns using stty.
- exec('stty size 2>&1', $columns_output, $columns_status);
- if (!$columns_status) $columns = preg_replace('/\d+\s(\d+)/', '$1', $columns_output[0], -1, $columns_count);
-
- // If stty fails and Drush us running on Windows are we trying with mode con.
- if (($columns_status || !$columns_count) && drush_is_windows()) {
- $columns_output = array();
- exec('mode con', $columns_output, $columns_status);
- if (!$columns_status && is_array($columns_output)) {
- $columns = (int)preg_replace('/\D/', '', $columns_output[4], -1, $columns_count);
- }
- else {
- drush_log(dt('Drush could not detect the console window width. Set a Windows Environment Variable of COLUMNS to the desired width.'), LogLevel::WARNING);
- }
- }
-
- // Failling back to default columns value
- if (empty($columns)) {
- $columns = 80;
- }
- }
- // If a caller wants to reserve some room to add additional
- // information to the drush output via post-processing, the
- // --reserve-margin flag can be used to declare how much
- // space to leave out. This only affects drush functions
- // such as drush_print_table() that wrap the output.
- $columns -= drush_get_option('reserve-margin', 0);
- drush_set_context('DRUSH_COLUMNS', $columns);
-}
-
-function _drush_preflight_alias_path() {
- $alias_path =& drush_get_context('ALIAS_PATH');
- $default_prefix_configuration = drush_is_windows() ? getenv('ALLUSERSPROFILE') . '/Drush' : '';
- $site_wide_configuration_dir = drush_get_context('ETC_PREFIX', $default_prefix_configuration) . '/etc/drush';
- $alias_path[] = drush_sitealias_alias_base_directory($site_wide_configuration_dir);
-
- $alias_path[] = drush_sitealias_alias_base_directory(dirname(__FILE__) . '/..');
-
- $server_home = drush_server_home();
- if (isset($server_home)) {
- $alias_path[] = drush_sitealias_alias_base_directory($server_home . '/.drush');
- }
-}
-
-/*
- * Set root and uri.
- */
-function _drush_preflight_root_uri() {
- drush_preflight_root();
- _drush_preflight_uri();
-}
-
-/**
- * If --uri is provided, set context.
- */
-function _drush_preflight_uri() {
- $uri = drush_get_option('uri', '');
- drush_set_context('DRUSH_SELECTED_URI', $uri);
-}
-
-function _drush_find_commandfiles_drush() {
- // Core commands shipping with Drush
- $searchpath[] = dirname(__FILE__) . '/../commands/';
-
- // User commands, specified by 'include' option
- $include = drush_get_context('DRUSH_INCLUDE', array());
- foreach ($include as $path) {
- if (is_dir($path)) {
- drush_log('Include ' . $path, LogLevel::NOTICE);
- $searchpath[] = $path;
- }
- }
-
- if (!drush_get_option('local')) {
- // System commands, residing in $SHARE_PREFIX/share/drush/commands
- $share_path = drush_get_context('DRUSH_SITE_WIDE_COMMANDFILES');
- if (is_dir($share_path)) {
- $searchpath[] = $share_path;
- }
-
- // User commands, residing in ~/.drush
- $per_user_config_dir = drush_get_context('DRUSH_PER_USER_CONFIGURATION');
- if (!empty($per_user_config_dir)) {
- $searchpath[] = $per_user_config_dir;
- }
- }
-
- // @todo the zero parameter is a bit weird here. It's $phase.
- _drush_add_commandfiles($searchpath, 0);
-
- // Also discover Drush's own annotation commands.
- $discovery = annotationcommand_adapter_get_discovery();
- $annotation_commandfiles = $discovery->discover(DRUSH_BASE_PATH . '/lib/Drush', '\Drush');
-
- // And, finally, search for commandfiles in the $searchpath
- $searchpath = array_map(
- function ($item) {
- if (strtolower(basename($item)) == 'commands') {
- return dirname($item);
- }
- return $item;
- },
- $searchpath
- );
- $global_drush_extensions = $discovery->discover($searchpath, '\Drush');
- $annotation_commandfiles += $global_drush_extensions;
-
- drush_set_context('DRUSH_ANNOTATED_COMMANDFILES', $annotation_commandfiles);
-}
-
-/**
- * Handle any command preprocessing that may need to be done, including
- * potentially redispatching the command immediately (e.g. for remote
- * commands).
- *
- * @return
- * TRUE if the command was handled remotely.
- */
-function drush_preflight_command_dispatch() {
- $interactive = drush_get_option('interactive', FALSE);
-
- // The command will be executed remotely if the --remote-host flag
- // is set; note that if a site alias is provided on the command line,
- // and the site alias references a remote server, then the --remote-host
- // option will be set when the site alias is processed.
- // @see drush_sitealias_check_arg_and_site_set and _drush_sitealias_set_context_by_name
- $remote_host = drush_get_option('remote-host');
- $site_list = drush_get_option('site-list');
- // Get the command early so that we can allow commands to directly handle remote aliases if they wish
- $command = drush_parse_command();
- drush_command_default_options($command);
-
- // If the command sets the 'strict-option-handling' flag, then we will remove
- // any cli options that appear after the command name from the 'cli' context.
- // The cli options that appear before the command name are stored in the
- // 'DRUSH_GLOBAL_CLI_OPTIONS' context, so we will just overwrite the cli context
- // with this, after doing the neccessary fixup from short-form to long-form options.
- // After we do that, we put back any local drush options identified by $command['options'].
- if (is_array($command) && !empty($command['strict-option-handling'])) {
- $cli_options = drush_get_context('DRUSH_GLOBAL_CLI_OPTIONS', array());
- // Now we are going to sort out any options that exist in $command['options'];
- // we will remove these from DRUSH_COMMAND_ARGS and put them back into the
- // cli options.
- $cli_context = drush_get_context('cli');
- $remove_from_command_args = array();
- foreach ($command['options'] as $option => $info) {
- if (array_key_exists($option, $cli_context)) {
- $cli_options[$option] = $cli_context[$option];
- $remove_from_command_args[$option] = $option;
- }
- }
- if (!empty($remove_from_command_args)) {
- $drush_command_args = array();
- foreach (drush_get_context('DRUSH_COMMAND_ARGS') as $arg) {
- if (!_drush_should_remove_command_arg($arg, $remove_from_command_args)) {
- $drush_command_args[] = $arg;
- }
- }
- drush_set_context('DRUSH_COMMAND_ARGS', $drush_command_args);
- }
- drush_expand_short_form_options($cli_options);
- drush_set_context('cli', $cli_options);
- _drush_preflight_global_options();
- }
- $args = drush_get_arguments();
- $command_name = array_shift($args);
- $root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT');
- $local_drush = drush_get_option('drush-script');
- if (empty($local_drush) && !empty($root)) {
- $local_drush = find_wrapper_or_launcher($root);
- }
- $is_local = drush_get_option('local');
- $values = NULL;
- if (!empty($root) && !empty($local_drush) && empty($is_local)) {
- if (!drush_is_absolute_path($local_drush)) {
- $local_drush = $root . DIRECTORY_SEPARATOR . $local_drush;
- }
- $local_drush = realpath($local_drush);
- $this_drush = drush_find_drush();
- // If there is a local Drush selected, and it is not the
- // same Drush that is currently running, redispatch to it.
- // We assume that if the current Drush is nested inside
- // the current Drupal root (or, more specifically, the
- // current Drupal root's parent), then it is a site-local Drush.
- // We avoid redispatching in that instance to prevent an
- // infinite loop.
- if (file_exists($local_drush) && !drush_is_nested_directory(dirname($root), $this_drush)) {
- $uri = drush_get_context('DRUSH_SELECTED_URI');
- $aditional_options = array(
- 'root' => $root,
- );
- if (!empty($uri)) {
- $aditional_options['uri'] = $uri;
- }
- // We need to chdir to the Drupal root here, for the
- // benefit of the Drush wrapper.
- chdir($root);
- $values = drush_do_command_redispatch(is_array($command) ? $command : $command_name, $args, NULL, NULL, $local_drush, TRUE, $aditional_options);
- }
- }
- // If the command sets the 'handle-remote-commands' flag, then we will short-circuit
- // remote command dispatching and site-list command dispatching, and always let
- // the command handler run on the local machine.
- if (is_array($command) && !empty($command['handle-remote-commands'])) {
- return FALSE;
- }
- if (isset($remote_host)) {
- $remote_user = drush_get_option('remote-user');
-
- // Force interactive mode if there is a single remote target. #interactive is added by drush_do_command_redispatch
- $user_interactive = drush_get_option('interactive');
- drush_set_option('interactive', TRUE);
- $values = drush_do_command_redispatch(is_array($command) ? $command : $command_name, $args, $remote_host, $remote_user, $user_interactive);
- }
- // If the --site-list flag is set, then we will execute the specified
- // command once for every site listed in the site list.
- if (isset($site_list)) {
- if (!is_array($site_list)) {
- $site_list = explode(',', $site_list);
- }
- $site_record = array('site-list' => $site_list);
- $args = drush_get_arguments();
-
- if (!drush_get_context('DRUSH_SIMULATE') && !$interactive && !drush_get_context('DRUSH_AFFIRMATIVE') && !drush_get_context('DRUSH_QUIET')) {
- drush_print(dt("You are about to execute '!command' non-interactively (--yes forced) on all of the following targets:", array('!command' => implode(" ", $args))));
- foreach ($site_list as $one_destination) {
- drush_print(dt(' !target', array('!target' => $one_destination)));
- }
-
- if (drush_confirm('Continue? ') === FALSE) {
- drush_user_abort();
- return TRUE;
- }
- }
- $command_name = array_shift($args);
- $multi_options = drush_redispatch_get_options();
- $backend_options = array();
- if (drush_get_option('pipe') || drush_get_option('interactive')) {
- $backend_options['interactive'] = TRUE;
- }
- if (drush_get_option('no-label', FALSE)) {
- $backend_options['no-label'] = TRUE;
- }
- // If the user specified a format, try to look up the
- // default list separator for the specified format.
- // If the user did not specify a different label separator,
- // then pass in the default as an option, so that the
- // separator between the items in the list and the site
- // name will be consistent.
- $format = drush_get_option('format', FALSE);
- if ($format && !array_key_exists('label-separator', $multi_options)) {
- $formatter = drush_load_engine('outputformat', $format);
- if ($formatter) {
- $list_separator = $formatter->get_info('list-separator');
- if ($list_separator) {
- $multi_options['label-separator'] = $list_separator;
- }
- }
- }
- $values = drush_invoke_process($site_record, $command_name, $args, $multi_options, $backend_options);
- }
- if (isset($values)) {
- if (is_array($values) && ($values['error_status'] > 0)) {
- // Force an error result code. Note that drush_shutdown() will still run.
- drush_set_context('DRUSH_EXECUTION_COMPLETED', TRUE);
- exit($values['error_status']);
- }
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Look for instances of arguments or parameters that
- * start with "~/". Replace these with "$HOME/".
- *
- * Note that this function is called _after_ Drush does
- * its redispatch checks; tildes are passed through
- * unmodified on a redispatch, and are only expanded when
- * a command is handled locally.
- */
-function drush_preflight_tilde_expansion(&$command) {
- // Skip tilde expansion for commands that use
- // stict option handling, or those that explicitly
- // turn it off via $command['tilde-expansion'] = FALSE.
- if ($command['tilde-expansion'] && !$command['strict-option-handling']) {
- $cli =& drush_get_context('cli');
- $match = '#^~/#';
- $replacement = drush_server_home() . '/';
- foreach ($cli as $key => $value) {
- if (is_string($value) && preg_match($match, $value)) {
- $cli[$key] = preg_replace($match, $replacement, $value);
- }
- }
- $command['arguments'] = array_map(function($value) use($match, $replacement) { return is_string($value) ? preg_replace($match, $replacement, $value) : $value; } , $command['arguments']);
- }