diff --git a/.ddev/config.yaml b/.ddev/config.yaml index 5da6ffc2dc..4510d79f7b 100644 --- a/.ddev/config.yaml +++ b/.ddev/config.yaml @@ -27,3 +27,4 @@ web_environment: # - UNISH_DB_URL=pgsql://db:db@db:5432?module=pgsql - DRUSH_OPTIONS_URI=$DDEV_PRIMARY_URL - EDITOR=nano + - DRUSH_ALLOW_XDEBUG=1 diff --git a/composer.json b/composer.json index 5b7f35516c..a040b807c4 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,8 @@ "security": "https://github.com/drush-ops/drush/security/advisories" }, "bin": [ - "drush" + "drush", + "drush.php" ], "repositories": { "drupal_org": { diff --git a/docs/commands.md b/docs/commands.md index a93c651889..1df190f218 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -151,3 +151,11 @@ With this configuration in place, global commands may be placed as described in 1. The directory above `Commands` must be one of: 1. A Folder listed in the 'include' option. Include may be provided via [config](#global-drush-commands) or via CLI. 1. ../drush, /drush or /sites/all/drush. These paths are relative to Drupal root. + +Xdebug +------------ + +Drush disables Xdebug by default. This improves performance substantially, because developers are often debugging something other than Drush and they still need to clear caches, import config, etc. There are two equivalent ways to override Drush's disabling of Xdebug: + +- Pass the `--xdebug` global option. +- Set an environment variable: `DRUSH_ALLOW_XDEBUG=1 drush [command]` diff --git a/drush b/drush index 5318cb3973..01d29459d4 100755 --- a/drush +++ b/drush @@ -1,4 +1,34 @@ -#!/usr/bin/env php -/dev/null 2>&1 ; pwd -P )" + DRUSH_PHP="$SCRIPTPATH/drush.php" +else + DRUSH_PHP="$COMPOSER_RUNTIME_BIN_DIR/drush.php" +fi + +parse_commandline() +{ + while test $# -gt 0 + do + _key="$1" + case "$_key" in + --xdebug) + DRUSH_ALLOW_XDEBUG=1 + return + ;; + esac + shift + done +} + +parse_commandline "$@" + +if [ "$DRUSH_ALLOW_XDEBUG" != 1 ] +then + export XDEBUG_MODE=off +fi + +"$DRUSH_PHP" "$@" diff --git a/drush.bat b/drush.bat deleted file mode 100644 index 6087c717b8..0000000000 --- a/drush.bat +++ /dev/null @@ -1,5 +0,0 @@ -@ECHO OFF -REM Running this file is equivalent to running `php drush` -setlocal DISABLEDELAYEDEXPANSION -SET BIN_TARGET=%~dp0drush -php "%BIN_TARGET%" %* diff --git a/drush.php b/drush.php index b6cb544bea..5b1e5eb108 100755 --- a/drush.php +++ b/drush.php @@ -1,3 +1,4 @@ +#!/usr/bin/env php addOption( new InputOption('--define', '-D', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Define a configuration item value.', []) ); + + $this->getDefinition() + ->addOption( + new InputOption('--xdebug', null, InputOption::VALUE_NONE, 'Drush turns off Xdebug to achieve better performance. Pass this option to keep Xdebug enabled.') + ); } public function bootstrapManager() diff --git a/src/Config/ConfigLocator.php b/src/Config/ConfigLocator.php index 82faf575fc..faec051b7e 100644 --- a/src/Config/ConfigLocator.php +++ b/src/Config/ConfigLocator.php @@ -263,7 +263,13 @@ public function addSitewideConfig(string $siteRoot): ?self // Remember that we've seen this location. $this->siteRoots[] = $siteRoot; - $this->addConfigPaths(self::DRUPAL_CONTEXT, [ dirname($siteRoot) . '/drush', "$siteRoot/drush", "$siteRoot/sites/all/drush" ]); + $paths = [ + dirname($siteRoot) . '/drush', + "$siteRoot/drush", + "$siteRoot/sites/all/drush", + ]; + $paths = array_filter($paths, is_dir(...)); + $this->addConfigPaths(self::DRUPAL_CONTEXT, $paths); return $this; } diff --git a/src/Preflight/Preflight.php b/src/Preflight/Preflight.php index 8ed61f1593..6ba2729b95 100644 --- a/src/Preflight/Preflight.php +++ b/src/Preflight/Preflight.php @@ -255,6 +255,11 @@ public function preflight($argv): array // Now that we know the value, set debug flag. $this->logger()->setDebug($this->preflightArgs->get(PreflightArgs::DEBUG, false)); + // Give hint if a developer might be trying to debug Drush. + if (extension_loaded('xdebug')) { + $this->logger()->log(strtr('Drush disables Xdebug by default. To override this, see !url', ['!url' => 'https://www.drush.org/latest/commands/#xdebug'])); + } + // Do legacy initialization (load static includes, define old constants, etc.) $this->init(); diff --git a/tests/functional/SqlSyncTest.php b/tests/functional/SqlSyncTest.php index 80ba9622e1..8bb1377e3f 100644 --- a/tests/functional/SqlSyncTest.php +++ b/tests/functional/SqlSyncTest.php @@ -53,14 +53,14 @@ public function testSimulatedSqlSync() $this->drush(SqlSyncCommands::SYNC, ['@synctest.remote', '@synctest.local'], $options, '@synctest.local'); $output = $this->getSimplifiedErrorOutput(); $this->assertStringContainsString("[notice] Simulating: ssh -o PasswordAuthentication=whatever www-admin@server.isp.simulated '/path/to/drush sql:dump --no-interaction --strict=0 --gzip --result-file=auto --format=json --uri=remote", $output); - $this->assertStringContainsString("[notice] Simulating: __DIR__/drush core:rsync @synctest.remote:/simulated/path/to/dump.tgz @synctest.local:__SANDBOX__/tmp/dump.tgz --yes --uri=local -- --remove-source-files", $output); - $this->assertStringContainsString("[notice] Simulating: __DIR__/drush sql:query --no-interaction --strict=0 --file=__SANDBOX__/tmp/dump.tgz --file-delete --uri=local", $output); + $this->assertStringContainsString("[notice] Simulating: __DIR__/drush.php core:rsync @synctest.remote:/simulated/path/to/dump.tgz @synctest.local:__SANDBOX__/tmp/dump.tgz --yes --uri=local -- --remove-source-files", $output); + $this->assertStringContainsString("[notice] Simulating: __DIR__/drush.php sql:query --no-interaction --strict=0 --file=__SANDBOX__/tmp/dump.tgz --file-delete --uri=local", $output); // Test simulated simple sql:sync local-to-remote $this->drush(SqlSyncCommands::SYNC, ['@synctest.local', '@synctest.remote'], $options, '@synctest.local'); $output = $this->getSimplifiedErrorOutput(); - $this->assertStringContainsString("[notice] Simulating: __DIR__/drush sql:dump --no-interaction --strict=0 --gzip --result-file=auto --format=json --uri=local", $output); - $this->assertStringContainsString("[notice] Simulating: __DIR__/drush core:rsync @synctest.local:/simulated/path/to/dump.tgz @synctest.remote:/tmp/dump.tgz --yes --uri=local -- --remove-source-files", $output); + $this->assertStringContainsString("[notice] Simulating: __DIR__/drush.php sql:dump --no-interaction --strict=0 --gzip --result-file=auto --format=json --uri=local", $output); + $this->assertStringContainsString("[notice] Simulating: __DIR__/drush.php core:rsync @synctest.local:/simulated/path/to/dump.tgz @synctest.remote:/tmp/dump.tgz --yes --uri=local -- --remove-source-files", $output); $this->assertStringContainsString("[notice] Simulating: ssh -o PasswordAuthentication=whatever www-admin@server.isp.simulated '/path/to/drush sql:query --no-interaction --strict=0 --file=/tmp/dump.tgz --file-delete --uri=remote'", $output); // Test simulated remote invoke with a remote runner.