function drush_preflight_command_dispatch

8.0.x drush_preflight_command_dispatch()
6.x drush_preflight_command_dispatch()
7.x drush_preflight_command_dispatch()
5.x drush_preflight_command_dispatch()
master drush_preflight_command_dispatch()

Handle any command preprocessing that may need to be done, including potentially redispatching the command immediately (e.g. for remote commands).

Return value

TRUE if the command was handled remotely.

1 call to drush_preflight_command_dispatch()
drush_main in includes/
The main Drush function.


includes/, line 774
Preflight, postflight and shutdown code.


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();

  // 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_set_context('cli', $cli_options);
  $args = drush_get_arguments();
  $command_name = array_shift($args);
  $root = \Drush::bootstrapManager()->getRoot();
  $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.
      $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) {
        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);
    return TRUE;
  return FALSE;