assertEquals($expected, $actual);
70 |
71 | // Generate a makefile with version numbers.
72 | $this->drush('generate-makefile', array($makefile), $options);
73 | $actual = file_get_contents($makefile);
74 | $this->assertContains('projects[devel][version] = "', $actual);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/commands/xh.drush.inc:
--------------------------------------------------------------------------------
1 | 'Enable profiling via XHProf',
16 | );
17 | $command['sub-options']['xh']['xh-link'] = 'URL to your XHProf report site.';
18 | $command['sub-options']['xh']['xh-path'] = 'Absolute path to the xhprof project.';
19 | }
20 | }
21 | }
22 |
23 | function xh_enabled() {
24 | if (drush_get_option('xh')) {
25 | if (!extension_loaded('xhprof')) {
26 | return drush_set_error('You must enable the xhprof PHP extension in your CLI PHP in order to profile.');
27 | }
28 | if (!drush_get_option('xh-path', '')) {
29 | return drush_set_error('You must provide the xh-path option in your drushrc or on the CLI in order to profile.');
30 | }
31 | return TRUE;
32 | }
33 | }
34 |
35 | /**
36 | * Implements hook_drush_init().
37 | */
38 | function xh_drush_init() {
39 | if (xh_enabled()) {
40 | if ($path = drush_get_option('xh-path', '')) {
41 | include_once $path . '/xhprof_lib/utils/xhprof_lib.php';
42 | include_once $path . '/xhprof_lib/utils/xhprof_runs.php';
43 | xhprof_enable(); // @todo support custom flags
44 | }
45 | }
46 | }
47 |
48 | /**
49 | * Implements hook_drush_exit().
50 | */
51 | function xh_drush_exit() {
52 | if (xh_enabled()) {
53 | $args = func_get_args();
54 | $namespace = 'Drush'; // variable_get('site_name', '');
55 | $xhprof_data = xhprof_disable();
56 | $xhprof_runs = new XHProfRuns_Default();
57 | $run_id = $xhprof_runs->save_run($xhprof_data, $namespace);
58 | if ($url = xh_link($run_id)) {
59 | drush_log(dt('XHProf run saved. View report at !url', array('!url' => $url)), 'ok');
60 | }
61 | }
62 | }
63 |
64 | /**
65 | * Returns the XHProf link.
66 | */
67 | function xh_link($run_id) {
68 | if ($xhprof_url = trim(drush_get_option('xh-link'))) {
69 | $namespace = 'Drush'; //variable_get('site_name', '');
70 | return $xhprof_url . '/index.php?run=' . urlencode($run_id) . '&source=' . urlencode($namespace);
71 | }
72 | else {
73 | drush_log('Configure xh_link in order to see a link to the XHProf report for this request instead of this message.');
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/lib/Drush/Sql/Sqlsqlsrv.php:
--------------------------------------------------------------------------------
1 | db_spec['database']) ? 'master' : $this->db_spec['database'];
18 | // Host and port are optional but have defaults.
19 | $host = empty($this->db_spec['host']) ? '.\SQLEXPRESS' : $this->db_spec['host'];
20 | if ($this->db_spec['username'] == '') {
21 | return ' -S ' . $host . ' -d ' . $database;
22 | }
23 | else {
24 | return ' -S ' . $host . ' -d ' . $database . ' -U ' . $this->db_spec['username'] . ' -P ' . $this->db_spec['password'];
25 | }
26 | }
27 |
28 | public function db_exists() {
29 | // TODO: untested, but the gist is here.
30 | $database = $this->db_spec['database'];
31 | // Get a new class instance that has no 'database'.
32 | $db_spec_no_db = $this->db_spec;
33 | unset($db_spec_no_db['database']);
34 | $sql_no_db = drush_sql_get_class($db_spec_no_db);
35 | $query = "if db_id('$database') IS NOT NULL print 1";
36 | drush_shell_exec($sql_no_db->connect() . ' -Q %s', $query);
37 | $output = drush_shell_exec_output();
38 | return $output[0] == 1;
39 | }
40 |
41 | public function listTables() {
42 | $return = $this->query('SELECT TABLE_NAME FROM information_schema.tables');
43 | $tables = drush_shell_exec_output();
44 | if (!empty($tables)) {
45 | // Shift off the header of the column of data returned.
46 | array_shift($tables);
47 | return $tables;
48 | }
49 | }
50 |
51 | // @todo $file is no longer provided. We are supposed to return bash that can be piped to gzip.
52 | // Probably sqlsrv needs to override dump() entirely.
53 | public function dumpCmd($table_selection) {
54 | if (!$file) {
55 | $file = $this->db_spec['database'] . '_' . date('Ymd_His') . '.bak';
56 | }
57 | $exec = "sqlcmd -U \"" . $this->db_spec['username'] . "\" -P \"" . $this->db_spec['password'] . "\" -S \"" . $this->db_spec['host'] . "\" -Q \"BACKUP DATABASE [" . $this->db_spec['database'] . "] TO DISK='" . $file . "'\"";
58 | return array($exec, $file);
59 | }
60 |
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/tests/siteIntallD6Test.php:
--------------------------------------------------------------------------------
1 | markTestSkipped('This test class is designed for Drupal 6.');
15 | return;
16 | }
17 | }
18 |
19 | /**
20 | * Test a D6 install with extra options.
21 | */
22 | public function testExtraConfigurationOptions() {
23 | // Set up codebase without installing Drupal.
24 | $sites = $this->setUpDrupal(1, FALSE, '6');
25 | $root = $this->webroot();
26 | $site = key($sites);
27 |
28 | // Copy the "example" test profile into the newly created site's profiles directory
29 | $profile_dir = "$root/profiles/example";
30 | mkdir($profile_dir);
31 | copy(dirname(__FILE__) . '/resources/example.profile', $profile_dir . '/example.profile');
32 |
33 | $test_string = $this->randomString();
34 | // example.profile Has values 0-2 defined as allowed.
35 | $test_int = rand(0, 2);
36 | $site_name = $this->randomString();
37 |
38 | $this->drush('site-install', array(
39 | // First argument is the profile name
40 | 'example',
41 | // Then the extra profile options
42 | "myopt1=$test_string",
43 | "myopt2=$test_int",
44 | ),
45 | array(
46 | 'db-url' => $this->db_url($site),
47 | 'yes' => NULL,
48 | 'sites-subdir' => $site,
49 | 'root' => $root,
50 | 'site-name' => $site_name,
51 | 'uri' => $site,
52 | ));
53 |
54 | $this->checkVariable('site_name', $site_name, $site);
55 | $this->checkVariable('myopt1', $test_string, $site);
56 | $this->checkVariable('myopt2', $test_int, $site);
57 | }
58 |
59 | /**
60 | * Check the value of a Drupal variable against an expectation using drush.
61 | *
62 | * @param $name
63 | * The variable name.
64 | * @param $value
65 | * The expected value of this variable.
66 | * @param $site
67 | * The name of an individual multisite installation site.
68 | */
69 | private function checkVariable($name, $value, $site) {
70 | $options = array(
71 | 'root' => $this->webroot(),
72 | 'uri' => $site,
73 | );
74 |
75 | $this->drush('variable-get', array($name), $options);
76 | $this->assertEquals("$name: $value", $this->getOutput());
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/lib/Drush/Boot/DrupalBoot7.php:
--------------------------------------------------------------------------------
1 | bootstrap_drupal_database_has_table('blocked_ips');
54 | }
55 |
56 | function bootstrap_drupal_database() {
57 | drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
58 | parent::bootstrap_drupal_database();
59 | }
60 |
61 | function bootstrap_drupal_configuration() {
62 | drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
63 |
64 | // Unset drupal error handler and restore drush's one.
65 | restore_error_handler();
66 |
67 | parent::bootstrap_drupal_configuration();
68 | }
69 |
70 | function bootstrap_drupal_full() {
71 | if (!drush_get_context('DRUSH_QUIET', FALSE)) {
72 | ob_start();
73 | }
74 | drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
75 | if (!drush_get_context('DRUSH_QUIET', FALSE)) {
76 | ob_end_clean();
77 | }
78 |
79 | parent::bootstrap_drupal_full();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/commands/core/outputformat/topics/table.html:
--------------------------------------------------------------------------------
1 | The 'table' formatter will convert an associative array into a formatted,
2 | word-wrapped table. Each item in the associative array represents one row
3 | in the table. Each row is similarly composed of associative arrays, with
4 | the key of each item indicating the column, and the value indicating the
5 | contents of the cell. See below for an example source array.
6 |
7 | The command core-requirements is an example of a command that produces output
8 | in a tabular format.
9 |
10 | $ drush core-requirements
11 |
12 | Title Severity Description
13 | Cron maintenance Error Last run 2 weeks ago
14 | tasks Cron has not run recently. For more
15 | information, see the online handbook entry for
16 | configuring cron jobs. You can run cron
17 | manually.
18 | Drupal Info 7.19
19 |
20 | (Note: the output above has been shortened for clarity; the actual output
21 | of core-requirements contains additional rows not shown here.)
22 |
23 | It is possible to determine the available fields by consulting drush
24 | help core requirements:
25 |
26 | --fields=<title, severity, description> Fields to output. All
27 | available fields are:
28 | title, severity, sid,
29 | description, value,
30 | reason, weight.
31 |
32 | It is possible to control the fields that appear in the table, and their
33 | order, by naming the desired fields in the --fields option. The space
34 | between items is optional, so `--fields=title,sid` is valid.
35 |
36 | Code:
37 |
38 | return array (
39 | 'cron' =>
40 | array (
41 | 'title' => 'Cron maintenance tasks',
42 | 'severity' => 2,
43 | 'value' => 'Last run 2 weeks ago',
44 | 'description' => 'Cron has not run recently. For more information, see the online handbook entry for configuring cron jobs. You can run cron manually.',
45 | 'severity-label' => 'Error',
46 | ),
47 | 'drupal' =>
48 | array (
49 | 'title' => 'Drupal',
50 | 'value' => '7.19',
51 | 'severity' => -1,
52 | 'weight' => -10,
53 | 'severity-label' => 'Info',
54 | ),
55 | )
56 |
57 |
--------------------------------------------------------------------------------
/tests/quickDrupalTest.php:
--------------------------------------------------------------------------------
1 | makefile_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'makefiles';
22 | }
23 |
24 | /**
25 | * Run a given quick-drupal test.
26 | *
27 | * @param $test
28 | * The test makefile to run, as defined by $this->getQuickDrupalTestParameters();
29 | */
30 | private function runQuickDrupalTest($test) {
31 | $config = $this->getQuickDrupalTestParameters($test);
32 | $default_options = array(
33 | 'yes' => NULL,
34 | 'no-server' => NULL,
35 | );
36 | $options = array_merge($config['options'], $default_options);
37 | if (array_key_exists('makefile', $config)) {
38 | $makefile = $this->makefile_path . DIRECTORY_SEPARATOR . $config['makefile'];
39 | $options['makefile'] = $makefile;
40 | }
41 | $return = !empty($config['fail']) ? self::EXIT_ERROR : self::EXIT_SUCCESS;
42 | $target = UNISH_SANDBOX . '/qd-' . $test;
43 | $options['root'] = $target;
44 | $this->drush('core-quick-drupal', $config['args'], $options, NULL, NULL, $return);
45 |
46 | // Use pm-list to determine if all of the correct modules were enabled
47 | if (empty($config['fail'])) {
48 | $this->drush('pm-list', array(), array('root' => $target, 'status' => 'enabled', 'no-core' => NULL, 'pipe' => NULL));
49 | $output = $this->getOutput();
50 | $this->assertEquals($config['expected-modules'], $output, 'quick-drupal included the correct set of modules');
51 | }
52 | }
53 |
54 | function testQuickDrupal() {
55 | $this->runQuickDrupalTest('devel');
56 | }
57 |
58 | function getQuickDrupalTestParameters($key) {
59 | $tests = array(
60 | 'devel' => array(
61 | 'name' => 'Test quick-drupal with a makefile that downloads devel',
62 | 'makefile' => 'qd-devel.make',
63 | 'expected-modules' => 'devel',
64 | 'args' => array(),
65 | 'options' => array(
66 | 'skip' => NULL, // for speed up enable of devel module.
67 | 'browser' => 0,
68 | 'profile' => UNISH_DRUPAL_MAJOR_VERSION == 6 ? 'standard' : 'testing',
69 | ),
70 | ),
71 | );
72 | return $tests[$key];
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/variableTest.php:
--------------------------------------------------------------------------------
1 | = 8) {
12 | $this->markTestSkipped("Variable system was removed in Drupal 8.");
13 | }
14 |
15 | $sites = $this->setUpDrupal(1, TRUE);
16 | $options_without_pipe = array(
17 | 'yes' => NULL,
18 | 'root' => $this->webroot(),
19 | 'uri' => key($sites),
20 | );
21 | $options = $options_without_pipe + array(
22 | 'pipe' => NULL,
23 | );
24 |
25 | $this->drush('variable-set', array('test_integer', '3.14159'), $options);
26 | $this->drush('variable-get', array('test_integer'), $options);
27 | $var_export = $this->getOutput();
28 | eval($var_export);
29 | $this->assertEquals("3.14159", $variables['test_integer'], 'Integer variable was successfully set and get.');
30 |
31 | $this->drush('variable-set', array('date_default_timezone', 'US/Mountain'), $options);
32 | $this->drush('variable-get', array('date_default_timezone'), $options); // Wildcard get.
33 | $var_export = $this->getOutput();
34 | eval($var_export);
35 | $this->assertEquals('US/Mountain', $variables['date_default_timezone'], 'Variable was successfully set and get.');
36 |
37 | $this->drush('variable-set', array('site_name', 'control'), $options + array('exact' => NULL));
38 | $this->drush('variable-set', array('site_na', 'unish'), $options + array('always-set' => NULL));
39 | $this->drush('variable-get', array('site_na'), $options + array('exact' => NULL));
40 | $var_export = $this->getOutput();
41 | eval($var_export);
42 | $this->assertEquals('unish', $variables['site_na'], '--always-set option works as expected.');
43 |
44 | $this->drush('variable-set', array('site_n', 'exactish'), $options + array('exact' => NULL));
45 | $this->drush('variable-get', array('site_n'), $options + array('exact' => NULL));
46 | $var_export = $this->getOutput();
47 | eval($var_export);
48 | $this->assertEquals('exactish', $variables['site_n'], '--exact option works as expected.');
49 |
50 | $this->drush('variable-get', array('site_n'), $options_without_pipe + array('exact' => NULL));
51 | $site_n_value = $this->getOutput();
52 | $this->assertEquals('exactish', $site_n_value, '--exact option works as expected with --pipe.');
53 |
54 | $this->drush('variable-delete', array('site_name'), $options);
55 | $output = $this->getOutput();
56 | $this->assertEmpty($output, 'Variable was successfully deleted.');
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/commands/make/update.make.inc:
--------------------------------------------------------------------------------
1 | $project) {
26 | if (($project['download']['type'] == 'git') && !empty($project['download']['url'])) {
27 | // TODO check that tag or branch are valid version strings (with pm_parse_version()).
28 | if (!empty($project['download']['tag'])) {
29 | $version = $project['download']['tag'];
30 | }
31 | elseif (!empty($project['download']['branch'])) {
32 | $version = $project['download']['branch'] . '-dev';
33 | }
34 | /*
35 | elseif (!empty($project['download']['refspec'])) {
36 | #TODO# Parse refspec.
37 | }
38 | */
39 | else {
40 | // If no tag or branch, we can't match a d.o version.
41 | continue;
42 | }
43 | $projects[$project_name] = $project + array(
44 | 'path' => '',
45 | 'label' => $project_name,
46 | 'version' => $version,
47 | );
48 | }
49 | elseif ($project['download']['type'] == 'pm') {
50 | $projects[$project_name] = $project + array(
51 | 'path' => '',
52 | 'label' => $project_name,
53 | );
54 | }
55 | }
56 |
57 | // Check for updates.
58 | $update_status = drush_get_engine('update_status');
59 | $update_info = $update_status->getStatus($projects, TRUE);
60 |
61 | $security_only = drush_get_option('security-only', FALSE);
62 | foreach ($update_info as $project_name => $project_update_info) {
63 | if (!$security_only || ($security_only && $project_update_info['status'] == DRUSH_UPDATESTATUS_NOT_SECURE)) {
64 | $make_projects[$project_name]['download']['full_version'] = $project_update_info['recommended'];
65 | }
66 | }
67 |
68 | // Inject back make projects and generate the updated makefile.
69 | drush_set_option('DRUSH_MAKE_PROJECTS', $make_projects);
70 | make_generate_from_makefile(drush_get_option('result-file'), $makefile);
71 | }
72 |
73 |
--------------------------------------------------------------------------------
/docs/examples.md:
--------------------------------------------------------------------------------
1 | This folder contains example files which you are copy and edit as needed. Read the documentation right in the file. If you see an opportunity to improve the file, please submit a pull request.
2 |
3 | * [drush](https://raw.githubusercontent.com/drush-ops/drush/master/examples/drush). A handy launcher script which calls the Drush located in vendor/bin/drush and can add options like --local, --root, etc.
4 | * [example.make](https://raw.githubusercontent.com/drush-ops/drush/master/examples/example.make). An ini style make file.
5 | * [example.make.yml](https://raw.githubusercontent.com/drush-ops/drush/master/examples/example.make.yml). A YML make file.
6 | * [example.bashrc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/example.bashrc). Enhance your shell with lots of Drush niceties including bash completion.
7 | * [example.prompt.sh](https://raw.githubusercontent.com/drush-ops/drush/master/examples/example.prompt.sh). Displays Git repository and Drush alias status in your prompt.
8 | * [example.drush.ini](https://raw.githubusercontent.com/drush-ops/drush/master/examples/example.drush.ini). Configure your PHP just for Drush requests.
9 | * [example.drushrc.php](https://raw.githubusercontent.com/drush-ops/drush/master/examples/example.drushrc.php). A Drush configuration file.
10 | * [example.aliases.drushrc.php](https://raw.githubusercontent.com/drush-ops/drush/master/examples/example.aliases.drushrc.php). Example site alias definitions.
11 | * [helloworld.script](https://raw.githubusercontent.com/drush-ops/drush/master/examples/helloworld.script). An example Drush script.
12 | * [git-bisect.example.sh](https://raw.githubusercontent.com/drush-ops/drush/master/examples/git-bisect.example.sh). Spelunking through Drush's git history with bisect.
13 | * [policy.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/policy.drush.inc). A policy file can disallow prohibited commands/options etc.
14 | * [sync_via_http.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/sync_via_http.drush.inc). sql-sync modification that transfers via http instead of rsync.
15 | * [sync_enable.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/sync_enable.drush.inc). Automatically enable modules after a sql-sync.
16 | * [pm_update.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/pm_update.drush.inc). Restore sqlsrv driver after core update.
17 | * [xkcd.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/xkcd.drush.inc). A fun example command that browses XKCD comics.
18 | * [sandwich.drush.inc](https://raw.githubusercontent.com/drush-ops/drush/master/examples/sandwich.drush.inc). A fun example command inspired by a famous XKCD comic.
19 |
--------------------------------------------------------------------------------
/tests/sqlConnectCreateTest.php:
--------------------------------------------------------------------------------
1 | setUpDrupal(1, TRUE);
17 | $options = array(
18 | 'yes' => NULL,
19 | 'root' => $this->webroot(),
20 | 'uri' => key($sites),
21 | );
22 |
23 | // Get the connection details with sql-connect and check its structure.
24 | $this->drush('sql-connect', array(), $options);
25 | $connectionString = $this->getOutput();
26 |
27 | // Not all drivers need -e option like sqlite
28 | $shell_options = "-e";
29 | $db_driver = $this->db_driver();
30 | if ($db_driver == 'mysql') {
31 | $this->assertRegExp('/^mysql --user=[^\s]+ --password=.* --database=[^\s]+ --host=[^\s]+/', $connectionString);
32 | }
33 | elseif ($db_driver == 'sqlite') {
34 | $this->assertContains('sqlite3', $connectionString);
35 | $shell_options = '';
36 | }
37 | elseif ($db_driver == 'pgsql') {
38 | $this->assertRegExp('/^psql -q --dbname=[^\s]+ --host=[^\s]+ --port=[^\s]+ --username=[^\s]+/', $connectionString);
39 | }
40 | else {
41 | $this->markTestSkipped('sql-connect test does not recognize database type in ' . UNISH_DB_URL);
42 | }
43 |
44 | // Issue a query and check the result to verify the connection.
45 | $this->execute($connectionString . ' ' . $shell_options . ' "SELECT uid FROM users where uid = 1;"');
46 | $output = $this->getOutput();
47 | $this->assertContains('1', $output);
48 |
49 | // Run 'core-status' and insure that we can bootstrap Drupal.
50 | $this->drush('core-status', array("Drupal bootstrap"), $options);
51 | $output = $this->getOutput();
52 | $this->assertContains('Successful', $output);
53 |
54 | // Test to see if 'sql-create' can erase the database.
55 | // The only output is a confirmation string, so we'll run
56 | // other commands to confirm that this worked.
57 | $this->drush('sql-create', array(), $options);
58 |
59 | // Try to execute a query. This should give a "table not found" error.
60 | $this->execute($connectionString . ' ' . $shell_options . ' "SELECT uid FROM users where uid = 1;"', self::EXIT_ERROR);
61 |
62 | // We should still be able to run 'core-status' without getting an
63 | // error, although Drupal should not bootstrap any longer.
64 | $this->drush('core-status', array("Drupal bootstrap"), $options);
65 | $output = $this->getOutput();
66 | $this->assertNotContains('Successful', $output);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/tests/commandUnitTest.php:
--------------------------------------------------------------------------------
1 | drush_major_version();
12 | $major_plus1 = $major + 1;
13 |
14 | // Write matched and unmatched files to the system search path.
15 | $files = array(
16 | $path . "/$major.drush$major.inc",
17 | $path . "/drush$major/drush$major.drush.inc",
18 | $path . "/$major_plus1.drush$major_plus1.inc",
19 | $path . "/drush$major_plus1/drush$major_plus1.drush.inc",
20 | );
21 | mkdir($path);
22 | mkdir($path . '/drush' . $major);
23 | mkdir($path . '/drush' . $major_plus1);
24 | foreach ($files as $file) {
25 | $contents = <<assertTrue(in_array(realpath($files[0]), $loaded), 'Loaded a version-specific command file.');
36 | $this->assertTrue(in_array(realpath($files[1]), $loaded), 'Loaded a version-specific command directory.');
37 | $this->assertFalse(in_array(realpath($files[2]), $loaded), 'Did not load a mismatched version-specific command file.');
38 | $this->assertFalse(in_array(realpath($files[3]), $loaded), 'Did not load a a mismatched version-specific command directory.');
39 | }
40 |
41 | /**
42 | * Assert that $command has interesting properties. Reference command by
43 | * it's alias (dl) to assure that those aliases are built as expected.
44 | */
45 | public function testGetCommands() {
46 | drush_preflight();
47 | $commands = drush_get_commands();
48 | $command = $commands['dl'];
49 |
50 | $this->assertEquals('dl', current($command['aliases']));
51 | $this->assertArrayHasKey('version_control', $command['engines']);
52 | $this->assertArrayHasKey('package_handler', $command['engines']);
53 | $this->assertArrayHasKey('release_info', $command['engines']);
54 | $this->assertEquals('pm-download', $command['command']);
55 | $this->assertEquals('pm', $command['commandfile']);
56 | $this->assertEquals('drush_command', $command['callback']);
57 | $this->assertArrayHasKey('examples', $command['sections']);
58 | $this->assertTrue($command['is_alias']);
59 |
60 | $command = $commands['pm-download'];
61 | $this->assertArrayNotHasKey('is_alias', $command);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/examples/example.drush.ini:
--------------------------------------------------------------------------------
1 | ;
2 | ; Example of a drush php settings override file
3 | ;
4 | ; IMPORTANT: Before following the instructions in
5 | ; this file, first check to see that the cli version
6 | ; of php is installed on your system. (e.g. On
7 | ; debian systems, `sudo apt-get install php5-cli`.)
8 | ;
9 | ; Use this file in instances when your system is
10 | ; -not- configured to use separate php.ini files for
11 | ; webserver and cli use. You can determine which
12 | ; php.ini file drush is using by running "drush status".
13 | ; If the php.ini file shown is your webserver ini
14 | ; file, then rename this file, example.drush.ini,
15 | ; to drush.ini and copy it to one of the following
16 | ; locations:
17 | ;
18 | ; 1. Drush installation folder
19 | ; 2. User's .drush folder (i.e. ~/.drush/drush.ini)
20 | ; 3. System wide configuration folder (i.e. /etc/drush/drush.ini)
21 | ;
22 | ; If the environment variable DRUSH_INI is defined,
23 | ; then the file it specified will be used as drush.ini.
24 | ;
25 | ; export DRUSH_INI='/path/to/drush.ini'
26 | ;
27 | ; When in use, the variables defined in this file
28 | ; will override the setting values that appear in
29 | ; your php.ini file. See the examples below for
30 | ; some values that may need to be set in order for
31 | ; drush to work.
32 | ;
33 | ; NOTE: There is a certain amount of overhead
34 | ; required for each override, so drush.ini should
35 | ; only be used for a relatively small number
36 | ; of variables. Comment out any variable that
37 | ; has the same value as the webserver php.ini
38 | ; to keep the size of the override list small.
39 | ;
40 | ; To fully specify the value of all php.ini variables,
41 | ; copy your webserver php.ini file to one of the
42 | ; locations mentioned above (e.g. /etc/drush/php.ini)
43 | ; and edit it to suit. Alternately, you may use
44 | ; the environment variable PHP_INI to point at
45 | ; the file that Drush should use.
46 | ;
47 | ; export PHP_INI='/path/to/php.ini'
48 | ;
49 | ; The options listed below are particularly relevant
50 | ; to drush.
51 | ;
52 |
53 | ;
54 | ; drush needs as much memory as Drupal in order
55 | ; to run; make the memory limit setting match
56 | ; what you have in your webserver's php.ini.
57 | ;
58 | memory_limit = 128M
59 |
60 | ;
61 | ; Show all errors and direct them to stderr
62 | ; when running drush.
63 | ;
64 | error_reporting = E_ALL | E_NOTICE | E_STRICT
65 | display_errors = stderr
66 |
67 | ;
68 | ; If your php.ini for your webserver is too
69 | ; restrictive, you can re-enable functionality
70 | ; for drush by adjusting values in this file.
71 | ;
72 | ; Here are some examples of settings that are
73 | ; sometimes set to restrictive values in a
74 | ; webserver's php.ini:
75 | ;
76 | ;safe_mode =
77 | ;open_basedir =
78 | ;disable_functions =
79 | ;disable_classes =
80 |
--------------------------------------------------------------------------------
/lib/Drush/Boot/DrupalBoot6.php:
--------------------------------------------------------------------------------
1 | bootstrap_drupal_database_has_table('cache');
57 | }
58 |
59 | function bootstrap_drupal_database() {
60 | drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
61 | parent::bootstrap_drupal_database();
62 | }
63 |
64 | function bootstrap_drupal_configuration() {
65 | drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
66 |
67 | parent::bootstrap_drupal_configuration();
68 | }
69 |
70 | function bootstrap_drupal_full() {
71 | if (!drush_get_context('DRUSH_QUIET', FALSE)) {
72 | ob_start();
73 | }
74 | drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
75 | if (!drush_get_context('DRUSH_QUIET', FALSE)) {
76 | ob_end_clean();
77 | }
78 |
79 | // Unset drupal error handler and restore drush's one.
80 | restore_error_handler();
81 |
82 | parent::bootstrap_drupal_full();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/tests/COVERAGE.txt:
--------------------------------------------------------------------------------
1 | COMMANDS
2 | ------------
3 | pm-download: GOOD.
4 | need test for `pm-download --select` (hard to test; depends on state of project releases on d.o.)
5 | pm-updatecode: GOOD.
6 | pm-update: FAIR. Implicitly tested by pm-updatecode but updatedb not yet tested.
7 | pm-releasenotes
8 | pm-releases
9 | pm-enable: GOOD. testEnDisUnList().
10 | pm-disable: GOOD. testEnDisUnList().
11 | pm-uninstall: GOOD. testEnDisUnList().
12 | pm-list: GOOD. testEnDisUnList().
13 | pm-info: GOOD. testEnDisUnList().
14 | pm-refresh:
15 | version-control: FAIR. See updatecode. To be deprecated all git workflow after git.drupal.org?
16 | package-hander:
17 |
18 | sql-cli:
19 | sql-connect:
20 | sql-query: FAIR. Implicit by site-install, sql-sync
21 | sql-dump: GOOD. tested by sqlDumpTest.
22 | sql-sync: GOOD. testLocalSqlSync().
23 | need test: %dump, %dump-dir, --dump, --dump-dir, --source-dump, --target-dump, --source-dump-dir and --target-dump-dir and permutations of same used together.
24 | sql-drop: FAIR. Implicit by site-install
25 | sql-sanitize: FAIR. Implicit by testLocalSqlSync()
26 |
27 |
28 | updatedb: NONE. Used to be implicitly tested by siteUpgradeTest.
29 | archive-dump: GOOD
30 | archive-restore: GOOD. Has own test and implicitly tested by environment cache in Unish framework.
31 | help
32 | version: GOOD. Implicit by testStandaloneScript()
33 | php-eval: GOOD. Implicitly tested by many tests (e.g. completeTest).
34 | php-script: GOOD.
35 | drupal-directory: GOOD
36 | cache-get: GOOD
37 | cache-set: GOOD
38 | cache-clear: GOOD
39 | core-config: NONE
40 | core-cron
41 | core-status: FAIR: Implicit test by contextTest.
42 | docs
43 | core-rsync
44 | core-quick-drupal: GOOD
45 | image: GOOD
46 | queue-*: GOOD
47 | runserver
48 | search-*
49 | shellalias: GOOD
50 | need test: shell alias with site alias
51 | site-install: FAIR. Implicit test by setUpDrupal().
52 | ssh: GOOD
53 | topic
54 | usage-*
55 | variable-*: GOOD
56 | watchdog-*: GOOD
57 |
58 | user-*: GOOD.
59 |
60 | field-*: GOOD.
61 |
62 | make: GOOD
63 |
64 | INCLUDES
65 | ------------
66 | backend: GOOD
67 | need test: --pipe with remote alias and --pipe with list of aliases
68 | batch: GOOD
69 | bootstrap:
70 | command: FAIR
71 | complete: GOOD
72 | context: FAIR. Many functions implicitly tested. Option merging (config, include, alias-path) not tested.
73 | drush: NONE.
74 | environment
75 | sitealias. FAIR. Explicit test for alias lists. Single aliases implicitly tested by contextTest. Option propagation tested by backendTest. Option recovery for @self alias tested by sqlDumpTest.
76 | dbtng: Good. Implicit by variable-*.
77 | drupal
78 | exec: GOOD: Implicitly tested all over.
79 | filesystem
80 | output
81 |
82 |
83 | ROOT
84 | -------------
85 | drush:
86 | need test: drush.ini
87 | drush.php
88 | drush.bat: N/A
89 | drush.complete.sh: N/A
90 |
--------------------------------------------------------------------------------
/examples/sandwich-nocolor.txt:
--------------------------------------------------------------------------------
1 | ::::::::::::::::::::::::::::::::::MMMMMMMMMMMM:::::::::::::::::::::::::::::::::
2 | :::::::::::::::::::::::::MMMMMMMM:::::::::::MM:::::::::::::::::::::::::::::::::
3 | :::::::::::::::::::MMMMM::::::::::::::::::::MMMM:::::::::::::::::::::::::::::::
4 | ::::::::::::::MMMMM:::::::::M::::::::M::::::::::MMMM:::::::::::::::::::::::::::
5 | ::::::::::MMMM::M:::::::::::::::::::::::::::::::::::MMMM:::::::::::::::::::::::
6 | :::::::MMM::::::::::::::::::::::::::::::::::::::::::::::MMMM:::::::::::::::::::
7 | :::::MM:::::::::::::::::::::::::::::::::::::::::::::::::::::MMMM:::::::::::::::
8 | :::::M::::::::::::::::::::::::::::::::::::::::::::::::::::::::::MMM::::::::::::
9 | :::::MMM$MM::::::::::::::::::::::::::::::::::::::::::::::::::::::::MMM:::::::::
10 | :::::M$$$$$MM:::::::::::::::::::::::::::::::::::::::::::::M::::::::::MMM:::::::
11 | ::MMMMM$M$$$$MM:::::::::M:::::::::::::::::::::::::::::::::::::::::::MMMMM::::::
12 | ::MIIIMMMM$M$$$MM:::::::::::::::::::::::::::::::::::::::::::MMMMMMM$$$$M:::::::
13 | :::MIIIIIIMM$$$$$MM::::::::::::::M:::::::::::::::::::MMMMMMM$$$$$$$$$$$$:::::::
14 | :MMIIIIIIIIMM$$$$$$MMM::::::::::::::::::::::::MMMMMM$$$$$$$$$$$$$$$$$$$$M::::::
15 | MIIMMMMMIIIIIMMM$$$$$$MM:::::::::::::::MMMMMM$$$$$$$$$$$$$$$$$$$$$$$$$$$M::::::
16 | MMM:MM:MMMMIIIIMMM$$$$$$MM:::::::MMMMMMM$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$MMMMM::
17 | ::M::::MM::IIIIIIMM$$$$$$$$MMMMM$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$MMMMMMMMMIIM:::
18 | ::MM:::M::MIIMMIIIIIM$M$$$$M$$$$$$$$$$$$$$$$$$$$$$$$$$$$MMMMMMMIIIIIMMMMMMM::::
19 | ::::MM::MMMMM:MIIIIIIMM$M$$M$$$$$$$$$$$$$$$$$$$$$$MMMMMMMIIIIIIIIIIIM::MMM:::::
20 | ::::::$MM:::::MIIIMMIIIMM$M$$$$$$$$$$$$$$$$MMMMMMIMMMIIIIM:::MMMIIIIM:::::MM:::
21 | ::::::$$$MM:::::M::MIIIMMMM$M$$$$$$$MMMMMMIIIIIIMMM:MMMMM:::::::::::::MMMMMM:::
22 | ::::::M$$$$MM:MMM::MMM:::MIMMMMMMMMMMIIMMIIIIIIIMM+M:::::MMMM::::MMMMM$M:::::::
23 | ::::::MM$M$$$M+$$M::::::MIIIIIIIMIIIIM::::MIIIIIM:MM::::M$$M+MM$$$$$$$$::::::::
24 | :::::::MMM$$$$$$$M:::::::MIIIIIM::MMM:::::::MMMM::::::::M$$M$$$$$$$$$$$M:::::::
25 | ::::::::::MM$$$$$$$MM::::MMMMMM:::::::::::::::::::MMMMMMM$$$$$$$$$$$$$$M:::::::
26 | ::::::::::::MM$M$$$$$MM:MM$$$$M::::::::::MMMMMMM$$$$$$$$$$$$$$$$$$MMMMM::::::::
27 | ::::::::::::::MMM$M$$$$MM$$$$$M:MMMMMMM$$$$$$$$$$$$$$$$$$$$$MMMMMM:::::::::::::
28 | :::::::::::::::::MMM$M$M$$$$$$MMM$$$$$$$$$$$$$$$$$$$$$$MMMMM:M:M:::::::::::::::
29 | :::::::::::::::::::MMMM$$M$$$$$$M$$$$$$$$$$$$$$$$$MMMMMM::::::M::::::::::::::::
30 | ::::::::::::::::::::::MMMMM$$$$$M$$$$$$$$$$$$$MMMMM::::::::::::::::::::::::::::
31 | :::::::::::::::::::::::::MMMM$M$M$$$$$$$$$MMMMM::::::::::::::::::::::::::::::::
32 | ::::::::::::::::::::::::::::MMMMM$$$$MMMM::::::::::::::::::::::::::::::::::::::
33 | :::::::::::::::::::::::::::::::MMMMM:::::::::::::::::::::::::::::::::::::::::::
34 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
35 |
--------------------------------------------------------------------------------
/tests/cacheCommandTest.php:
--------------------------------------------------------------------------------
1 | getSites()) {
14 | $this->setUpDrupal(1, TRUE);
15 | }
16 | }
17 |
18 | function testCacheGet() {
19 | $options = $this->getOptions();
20 | // Test the cache get command.
21 | $inputs = array(
22 | 6 => array('variables', NULL),
23 | 7 => array('schema', NULL),
24 | 8 => array('system.filter', 'config'),
25 | );
26 | list($key, $bin) = $inputs[UNISH_DRUPAL_MAJOR_VERSION];
27 | $this->drush('cache-get', array($key, $bin), $options + array('format' => 'json'));
28 | $schema = $this->getOutputFromJSON('data');
29 | $this->assertNotEmpty($schema);
30 |
31 | // Test that get-ing a non-existant cid fails.
32 | $this->drush('cache-get', array('test-failure-cid'), $options + array('format' => 'json'), NULL, NULL, self::EXIT_ERROR);
33 | }
34 |
35 | function testCacheSet() {
36 | $options = $this->getOptions();
37 | // Test setting a new cache item.
38 | $expected = 'cache test string';
39 | $this->drush('cache-set', array('cache-test-cid', $expected), $options);
40 | $this->drush('cache-get', array('cache-test-cid'), $options + array('format' => 'json'));
41 | $data = $this->getOutputFromJSON('data');
42 | $this->assertEquals($expected, $data);
43 |
44 | // Test cache-set using all arguments and many options.
45 | $expected = array('key' => 'value');
46 | $input = array('data'=> $expected);
47 | $stdin = json_encode($input);
48 | $bin = UNISH_DRUPAL_MAJOR_VERSION >= 8 ? 'default' : 'cache';
49 | $exec = sprintf('echo %s | %s cache-set %s %s my_cache_id - %s CACHE_PERMANENT --format=json --cache-get 2>/dev/null', self::escapeshellarg($stdin), UNISH_DRUSH, "--root=" . self::escapeshellarg($options['root']), '--uri=' . $options['uri'], $bin);
50 | $return = $this->execute($exec);
51 | $this->drush('cache-get', array('my_cache_id'), $options + array('format' => 'json'));
52 | $data = $this->getOutputFromJSON('data');
53 | $this->assertEquals((object)$expected, $data);
54 | }
55 |
56 | function testCacheRebuild() {
57 | $options = $this->getOptions();
58 | // Test cache-clear all and cache-rebuild (D8+).
59 | if (UNISH_DRUPAL_MAJOR_VERSION >= 8) {
60 | $this->drush('cache-rebuild', array(), $options);
61 | }
62 | else {
63 | $this->drush('cache-clear', array('all'), $options);
64 | }
65 | $this->drush('cache-get', array('cache-test-cid'), $options + array('format' => 'json'), NULL, NULL, self::EXIT_ERROR);
66 | }
67 |
68 | function getOptions() {
69 | return array(
70 | 'yes' => NULL,
71 | 'root' => $this->webroot(),
72 | 'uri' => key($this->getSites()),
73 | );
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/commands/core/drupal/cache.inc:
--------------------------------------------------------------------------------
1 | 'drush_cache_clear_drush',
42 | 'all' => 'drush_cache_clear_both',
43 | );
44 | if ($include_bootstrapped_types) {
45 | $types += array(
46 | 'theme-registry' => 'drush_cache_clear_theme_registry',
47 | 'menu' => 'menu_rebuild',
48 | 'css-js' => 'drush_cache_clear_css_js',
49 | 'block' => 'drush_cache_clear_block',
50 | 'module-list' => 'drush_get_modules',
51 | 'theme-list' => 'drush_get_themes',
52 | );
53 | }
54 | $drupal_version = drush_drupal_major_version();
55 |
56 | if ($drupal_version >= 7) {
57 | $types['registry'] = 'registry_update';
58 | }
59 | elseif ($drupal_version == 6 && function_exists('module_exists') && module_exists('autoload')) {
60 | // TODO: move this to autoload module.
61 | $types['registry'] = 'autoload_registry_update';
62 | }
63 |
64 | return $types;
65 | }
66 |
67 | function drush_cache_clear_theme_registry() {
68 | if (drush_drupal_major_version() >= 7) {
69 | drupal_theme_rebuild();
70 | }
71 | else {
72 | cache_clear_all('theme_registry', 'cache', TRUE);
73 | }
74 | }
75 |
76 | function drush_cache_clear_menu() {
77 | return menu_router_rebuild();
78 | }
79 |
80 | function drush_cache_clear_css_js() {
81 | _drupal_flush_css_js();
82 | drupal_clear_css_cache();
83 | drupal_clear_js_cache();
84 | }
85 |
86 | /**
87 | * Clear the cache of the block output.
88 | */
89 | function drush_cache_clear_block() {
90 | cache_clear_all(NULL, 'cache_block');
91 | }
92 |
93 | /**
94 | * Clear caches internal to Drush core and Drupal.
95 | */
96 | function drush_cache_clear_both() {
97 | drush_cache_clear_drush();
98 | if (drush_has_boostrapped(DRUSH_BOOTSTRAP_DRUPAL_FULL)) {
99 | drupal_flush_all_caches();
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/commands/core/outputformat/key_value.inc:
--------------------------------------------------------------------------------
1 | "Two B or ! Two B, that is the comparison",
21 | * "c" => "I see that C has gone to Sea"
22 | * );
23 | *
24 | * Output with --format=key-value:
25 | *
26 | * b : Two B or ! Two B,
27 | * that is the
28 | * comparison
29 | * c : I see that C has gone
30 | * to Sea
31 | *
32 | * Code:
33 | *
34 | * return array(
35 | * "a" => array(
36 | * "b" => "Two B or ! Two B, that is the comparison",
37 | * "c" => "I see that C has gone to Sea"
38 | * ),
39 | * "d" => array(
40 | * "e" => "Elephants and electron microscopes",
41 | * "f" => "My margin is too small"
42 | * )
43 | * );
44 | *
45 | * Output with --format=key-value-list:
46 | *
47 | * b : Two B or ! Two B,
48 | * that is the
49 | * comparison
50 | * c : I see that C has gone
51 | * to Sea
52 | *
53 | * e : Elephants and
54 | * electron microscopes
55 | * f : My margin is too
56 | * small
57 | */
58 | class drush_outputformat_key_value extends drush_outputformat {
59 | function format($input, $metadata) {
60 | if (!is_array($input)) {
61 | if (isset($metadata['label'])) {
62 | $input = array(dt($metadata['label']) => $input);
63 | }
64 | else {
65 | return $this->format_error(dt('No label provided.'));
66 | }
67 | }
68 | $kv_metadata = isset($metadata['table-metadata']) ? $metadata['table-metadata'] : array();
69 | if ((!isset($kv_metadata['key-value-item'])) && (isset($metadata['field-labels']))) {
70 | $input = drush_select_output_fields($input, $metadata['field-labels'], $metadata['field-mappings']);
71 | }
72 | if (isset($metadata['include-field-labels'])) {
73 | $kv_metadata['include-field-labels'] = $metadata['include-field-labels'];
74 | }
75 | $formatted_table = drush_key_value_to_array_table($input, $kv_metadata);
76 | if ($formatted_table === FALSE) {
77 | return FALSE;
78 | }
79 | return drush_format_table($formatted_table, FALSE, array());
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/tests/fieldTest.php:
--------------------------------------------------------------------------------
1 | markTestSkipped("Field API not available in Drupal 6.");
15 | }
16 |
17 | if (UNISH_DRUPAL_MAJOR_VERSION == 8) {
18 | $this->markTestSkipped("Field commands are not yet ported to D8.");
19 | }
20 |
21 | $sites = $this->setUpDrupal(1, TRUE);
22 | $options = array(
23 | 'yes' => NULL,
24 | 'root' => $this->webroot(),
25 | 'uri' => key($sites),
26 | );
27 |
28 | $expected_url = '/admin/config/people/accounts/fields/subtitle';
29 | if (UNISH_DRUPAL_MAJOR_VERSION >= 8) {
30 | // Prepend for D8. We might want to change setUpDrupal() to add clean url.
31 | $expected_url = '/index.php' . $expected_url;
32 | }
33 | // Create two field instances on article content type.
34 | $this->drush('field-create', array('user', 'city,text,text_textfield', 'subtitle,text,text_textfield'), $options + array('entity_type' => 'user'));
35 | $output = $this->getOutput();
36 | list($city, $subtitle) = explode(' ', $output);
37 | $url = parse_url($subtitle);
38 | $this->assertEquals($expected_url, $url['path']);
39 |
40 | // Assure that the second field instance was created correctly (subtitle).
41 | $this->verifyInstance('subtitle', $options);
42 |
43 | // Assure that field update URL looks correct.
44 | $this->drush('field-update', array('subtitle'), $options);
45 | $output = $this->getOutput();
46 | $url = parse_url($this->getOutput());
47 | $this->assertEquals($expected_url, $url['path']);
48 |
49 | // Assure that field-clone actually clones.
50 | $this->drush('field-clone', array('subtitle', 'subtitlecloned'), $options);
51 | $this->verifyInstance('subtitlecloned', $options);
52 |
53 | // Assure that delete works.
54 | $this->drush('field-delete', array('subtitlecloned'), $options);
55 | $this->verifyInstance('subtitlecloned', $options, FALSE);
56 | }
57 |
58 | function verifyInstance($name, $options, $expected = TRUE) {
59 | $this->drush('field-info', array('fields'), $options + array('format' => 'json'));
60 | $output = $this->getOutputFromJSON();
61 | $found = FALSE;
62 | foreach($output as $key => $field) {
63 | if ($key == $name) {
64 | $this->assertEquals('text', $field->type, $name . ' field is of type=text.');
65 | $this->assertEquals('user', current($field->bundle), $name . ' field was added to user bundle.');
66 | $found = TRUE;
67 | break;
68 | }
69 | }
70 | if ($expected) {
71 | $this->assertTrue($found, $name . ' field was created.');
72 | }
73 | else {
74 | $this->assertFalse($found, $name . ' field was not present.');
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/tests/siteSshTest.php:
--------------------------------------------------------------------------------
1 | is_windows()) {
18 | $this->markTestSkipped('ssh command not currently available on Windows.');
19 | }
20 |
21 | $options = array(
22 | 'simulate' => NULL,
23 | );
24 | $this->drush('ssh', array(), $options, 'user@server/path/to/drupal#sitename', NULL, self::EXIT_SUCCESS, '2>&1');
25 | $output = $this->getOutput();
26 | $expected = sprintf('Calling proc_open(ssh -o PasswordAuthentication=no -t %s@%s %s);', self::escapeshellarg('user'), self::escapeshellarg('server'), "'cd /path/to/drupal && bash -l'");
27 | $this->assertEquals($expected, $output);
28 | }
29 |
30 | /**
31 | * Test drush ssh --simulate 'date'.
32 | * @todo Run over a site list. drush_sitealias_get_record() currently cannot
33 | * handle a site list comprised of longhand site specifications.
34 | */
35 | public function testNonInteractive() {
36 | $options = array(
37 | 'cd' => '0',
38 | 'simulate' => NULL,
39 | );
40 | $this->drush('ssh', array('date'), $options, 'user@server/path/to/drupal#sitename', NULL, self::EXIT_SUCCESS, '2>&1');
41 | $output = $this->getOutput();
42 | $expected = sprintf('Calling proc_open(ssh -o PasswordAuthentication=no %s@%s %s);', self::escapeshellarg('user'), self::escapeshellarg('server'), self::escapeshellarg('date'));
43 | $this->assertEquals($expected, $output);
44 | }
45 |
46 | /**
47 | * Test drush ssh with multiple arguments (preferred form).
48 | */
49 | public function testSshMultipleArgs() {
50 | $options = array(
51 | 'cd' => '0',
52 | 'simulate' => NULL,
53 | );
54 | $this->drush('ssh', array('ls', '/path1', '/path2'), $options, 'user@server/path/to/drupal#sitename', NULL, self::EXIT_SUCCESS, '2>&1');
55 | $output = $this->getOutput();
56 | $expected = sprintf('Calling proc_open(ssh -o PasswordAuthentication=no %s@%s \'ls /path1 /path2\');', self::escapeshellarg('user'), self::escapeshellarg('server'));
57 | $this->assertEquals($expected, $output);
58 | }
59 |
60 | /**
61 | * Test drush ssh with multiple arguments (legacy form).
62 | */
63 | public function testSshMultipleArgsLegacy() {
64 | $options = array(
65 | 'cd' => '0',
66 | 'simulate' => NULL,
67 | );
68 | $this->drush('ssh', array('ls /path1 /path2'), $options, 'user@server/path/to/drupal#sitename', NULL, self::EXIT_SUCCESS, '2>&1');
69 | $output = $this->getOutput();
70 | $expected = sprintf('Calling proc_open(ssh -o PasswordAuthentication=no %s@%s \'ls /path1 /path2\');', self::escapeshellarg('user'), self::escapeshellarg('server'));
71 | $this->assertEquals($expected, $output);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/commands/pm/version_control/backup.inc:
--------------------------------------------------------------------------------
1 | prepare_backup_dir()) {
22 | if ($project['project_type'] != 'core') {
23 | $backup_target .= '/' . $project['project_type'] . 's';
24 | drush_mkdir($backup_target);
25 | }
26 | $backup_target .= '/'. $project['name'];
27 | // Save for rollback or notifications.
28 | $project['backup_target'] = $backup_target;
29 |
30 | // Move or copy to backup target based in package-handler.
31 | if (drush_get_option('package-handler', 'wget') == 'wget') {
32 | if (drush_move_dir($project['full_project_path'], $backup_target)) {
33 | return TRUE;
34 | }
35 | }
36 | // cvs or git.
37 | elseif (drush_copy_dir($project['full_project_path'], $backup_target)) {
38 | return TRUE;
39 | }
40 | return drush_set_error('DRUSH_PM_BACKUP_FAILED', dt('Failed to backup project directory !project to !backup_target', array('!project' => $project['full_project_path'], '!backup_target' => $backup_target)));
41 | }
42 | }
43 |
44 | /**
45 | * Implementation of rollback().
46 | */
47 | public function rollback($project) {
48 | if (drush_get_option('no-backup', FALSE)) {
49 | return;
50 | }
51 | if (drush_move_dir($project['backup_target'], $project['full_project_path'], TRUE)) {
52 | return drush_log(dt("Backups were restored successfully."), 'ok');
53 | }
54 | return drush_set_error('DRUSH_PM_BACKUP_ROLLBACK_FAILED', dt('Could not restore backup and rollback from failed upgrade. You will need to resolve manually.'));
55 | }
56 |
57 | /**
58 | * Implementation of post_update().
59 | */
60 | public function post_update($project) {
61 | if (drush_get_option('no-backup', FALSE)) {
62 | return;
63 | }
64 | if ($project['backup_target']) {
65 | drush_log(dt("Backups were saved into the directory !backup_target.", array('!backup_target' => $project['backup_target'])), 'ok');
66 | }
67 | }
68 |
69 | /**
70 | * Implementation of post_download().
71 | */
72 | public function post_download($project) {
73 | // NOOP
74 | }
75 |
76 | // Helper for pre_update.
77 | public function prepare_backup_dir($subdir = NULL) {
78 | return drush_prepare_backup_dir($subdir);
79 | }
80 |
81 | public static function reserved_files() {
82 | return array();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/commands/core/drupal/site_install.inc:
--------------------------------------------------------------------------------
1 | FALSE) + install_state_defaults();
14 | try {
15 | install_begin_request($class_loader, $install_state);
16 | $profile = _install_select_profile($install_state);
17 | }
18 | catch (\Exception $e) {
19 | // This is only a best effort to provide a better default, no harm done
20 | // if it fails.
21 | }
22 | if (empty($profile)) {
23 | $profile = 'standard';
24 | }
25 | }
26 |
27 | $sql = drush_sql_get_class();
28 | $db_spec = $sql->db_spec();
29 |
30 | $account_pass = drush_get_option('account-pass', drush_generate_password());
31 | $account_name = drush_get_option('account-name', 'admin');
32 | $settings = array(
33 | 'parameters' => array(
34 | 'profile' => $profile,
35 | 'langcode' => drush_get_option('locale', 'en'),
36 | ),
37 | 'forms' => array(
38 | 'install_settings_form' => array(
39 | 'driver' => $db_spec['driver'],
40 | $db_spec['driver'] => $db_spec,
41 | 'op' => dt('Save and continue'),
42 | ),
43 | 'install_configure_form' => array(
44 | 'site_name' => drush_get_option('site-name', 'Site-Install'),
45 | 'site_mail' => drush_get_option('site-mail', 'admin@example.com'),
46 | 'account' => array(
47 | 'name' => $account_name,
48 | 'mail' => drush_get_option('account-mail', 'admin@example.com'),
49 | 'pass' => array(
50 | 'pass1' => $account_pass,
51 | 'pass2' => $account_pass,
52 | ),
53 | ),
54 | 'update_status_module' => array(
55 | 1 => TRUE,
56 | 2 => TRUE,
57 | ),
58 | 'clean_url' => drush_get_option('clean-url', TRUE),
59 | 'op' => dt('Save and continue'),
60 | ),
61 | ),
62 | );
63 |
64 | // Merge in the additional options.
65 | foreach ($additional_form_options as $key => $value) {
66 | $current = &$settings['forms'];
67 | foreach (explode('.', $key) as $param) {
68 | $current = &$current[$param];
69 | }
70 | $current = $value;
71 | }
72 |
73 | $msg = 'Starting Drupal installation. This takes a while.';
74 | if (is_null(drush_get_option('notify'))) {
75 | $msg .= ' Consider using the --notify global option.';
76 | }
77 | drush_log(dt($msg), 'ok');
78 | drush_op('install_drupal', $class_loader, $settings);
79 | drush_log(dt('Installation complete. User name: @name User password: @pass', array('@name' => $account_name, '@pass' => $account_pass)), 'ok');
80 | }
81 |
--------------------------------------------------------------------------------
/commands/core/queue.drush.inc:
--------------------------------------------------------------------------------
1 | 'Run a specific queue by name',
19 | 'arguments' => array(
20 | 'queue_name' => 'The name of the queue to run, as defined in either hook_queue_info or hook_cron_queue_info.',
21 | ),
22 | 'required-arguments' => TRUE,
23 | 'options' => array(
24 | 'time-limit' => 'The maximum number of seconds allowed to run the queue',
25 | ),
26 | );
27 | $items['queue-list'] = array(
28 | 'description' => 'Returns a list of all defined queues',
29 | 'outputformat' => array(
30 | 'default' => 'table',
31 | 'pipe-format' => 'csv',
32 | 'field-labels' => array(
33 | 'queue' => 'Queue',
34 | 'items' => 'Items',
35 | 'class' => 'Class',
36 | ),
37 | 'ini-item' => 'items',
38 | 'table-metadata' => array(
39 | 'key-value-item' => 'items',
40 | ),
41 | 'output-data-type' => 'format-table',
42 | ),
43 | );
44 |
45 | return $items;
46 | }
47 |
48 | /**
49 | * Validation callback for drush queue-run.
50 | */
51 | function drush_queue_run_validate($queue_name) {
52 | try {
53 | $queue = drush_queue_get_class();
54 | $queue->getInfo($queue_name);
55 | }
56 | catch (\Drush\Queue\QueueException $exception) {
57 | return drush_set_error('DRUSH_QUEUE_RUN_VALIDATION_ERROR', $exception->getMessage());
58 | }
59 | }
60 |
61 | /**
62 | * Return the appropriate queue class.
63 | */
64 | function drush_queue_get_class() {
65 | return drush_get_class('Drush\Queue\Queue');
66 | }
67 |
68 | /**
69 | * Command callback for drush queue-run.
70 | *
71 | * Queue runner that is compatible with queues declared using both
72 | * hook_queue_info() and hook_cron_queue_info().
73 | *
74 | * @param $queue_name
75 | * Arbitrary string. The name of the queue to work with.
76 | */
77 | function drush_queue_run($queue_name) {
78 | $queue = drush_queue_get_class();
79 | $time_limit = (int) drush_get_option('time-limit');
80 | $start = microtime(TRUE);
81 | $count = $queue->run($queue_name, $time_limit);
82 | $elapsed = microtime(TRUE) - $start;
83 | drush_log(dt('Processed @count items from the @name queue in @elapsed sec.', array('@count' => $count, '@name' => $queue_name, '@elapsed' => round($elapsed, 2))), drush_get_error() ? 'warning' : 'ok');
84 | }
85 |
86 | /**
87 | * Command callback for drush queue-list.
88 | */
89 | function drush_queue_list() {
90 | $queue = drush_queue_get_class();
91 | return $queue->listQueues();
92 | }
93 |
94 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # Configuration file for unit test runner at http://travis-ci.org/#!/drush-ops/drush
2 | # whitelist
3 | branches:
4 | only:
5 | - master
6 | - 7.x
7 | - 6.x
8 | - 5.x
9 | language: php
10 | php:
11 | # See master-fulltest branch for broader PHP version testing.
12 | - 5.5
13 |
14 | # http://blog.travis-ci.com/2014-12-17-faster-builds-with-container-based-infrastructure/
15 | sudo: false
16 |
17 | env:
18 | matrix:
19 | #D7
20 | - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=make
21 | - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=base
22 | - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=commands
23 | - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=pm
24 | - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=quick-drupal
25 | - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal
26 | #D8
27 | - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=make
28 | - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=base
29 | - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=commands
30 | - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=pm
31 | - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=quick-drupal
32 | - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal TEST_CHILDREN="drush-ops/config-extra"
33 |
34 | # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--group=make
35 | # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--group=base
36 | # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--group=commands
37 | # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--group=pm
38 | # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--group=quick-drupal
39 | # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal
40 | # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--group=make
41 | # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--group=base
42 | # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--group=commands
43 | # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--group=pm
44 | # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--group=quick-drupal
45 | # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal
46 | global:
47 | - secure: VfYokT2CchfuBRJp9/gSwfVGPfsVfkZdDVEuNWEqxww3z4vq+5aLKqoCtPL54E5EIMjhyCE3GVo+biG35Gab1KOVgUs8zD1hAUWA1FPKfMFhoPDfI3ZJC2rX2T1iWK4ZR90pBtcPzS+2OObzTYz8go0PfeSTT6eq69Na1KcNLaE=
48 | - UNISH_NO_TIMEOUTS=y
49 | - UNISH_DB_URL=mysql://root:@127.0.0.1
50 | before_install: composer selfupdate
51 | install: composer install
52 |
53 | before_script:
54 | - echo "sendmail_path='true'" >> `php --ini | grep "Loaded Configuration" | awk '{print $4}'`
55 | - export UNISH_DRUSH="${PWD}/drush"
56 |
57 | script: ${PWD}/unish.sh $PHPUNIT_ARGS
58 |
59 | after_success: ${PWD}/tests/testChildren.sh
60 |
--------------------------------------------------------------------------------
/commands/core/drupal/site_install_7.inc:
--------------------------------------------------------------------------------
1 | db_spec();
31 |
32 | $account_pass = drush_get_option('account-pass', drush_generate_password());
33 | $account_name = drush_get_option('account-name', 'admin');
34 | $settings = array(
35 | 'parameters' => array(
36 | 'profile' => $profile,
37 | 'locale' => drush_get_option('locale', 'en'),
38 | ),
39 | 'forms' => array(
40 | 'install_settings_form' => array(
41 | 'driver' => $db_spec['driver'],
42 | $db_spec['driver'] => $db_spec,
43 | 'op' => dt('Save and continue'),
44 | ),
45 | 'install_configure_form' => array(
46 | 'site_name' => drush_get_option('site-name', 'Site-Install'),
47 | 'site_mail' => drush_get_option('site-mail', 'admin@example.com'),
48 | 'account' => array(
49 | 'name' => $account_name,
50 | 'mail' => drush_get_option('account-mail', 'admin@example.com'),
51 | 'pass' => array(
52 | 'pass1' => $account_pass,
53 | 'pass2' => $account_pass,
54 | ),
55 | ),
56 | 'update_status_module' => array(
57 | 1 => TRUE,
58 | 2 => TRUE,
59 | ),
60 | 'clean_url' => drush_get_option('clean-url', TRUE),
61 | 'op' => dt('Save and continue'),
62 | ),
63 | ),
64 | );
65 |
66 | // Merge in the additional options.
67 | foreach ($additional_form_options as $key => $value) {
68 | $current = &$settings['forms'];
69 | foreach (explode('.', $key) as $param) {
70 | $current = &$current[$param];
71 | }
72 | $current = $value;
73 | }
74 |
75 | $msg = 'Starting Drupal installation. This takes a while.';
76 | if (is_null(drush_get_option('notify'))) {
77 | $msg .= ' Consider using the --notify global option.';
78 | }
79 | drush_log(dt($msg), 'ok');
80 | drush_op('install_drupal', $settings);
81 | drush_log(dt('Installation complete. User name: @name User password: @pass', array('@name' => $account_name, '@pass' => $account_pass)), 'ok');
82 | }
83 |
--------------------------------------------------------------------------------
/commands/runserver/runserver-prepend.php:
--------------------------------------------------------------------------------
1 | uid;
41 | }
42 | else {
43 | $uid = $log_entry['user']->id();
44 | }
45 | $message = strtr('Watchdog: !message | severity: !severity | type: !type | uid: !uid | !ip | !request_uri | !referer | !link', array(
46 | '!message' => strip_tags(!isset($log_entry['variables']) ? $log_entry['message'] : strtr($log_entry['message'], $log_entry['variables'])),
47 | '!severity' => $log_entry['severity'],
48 | '!type' => $log_entry['type'],
49 | '!ip' => $log_entry['ip'],
50 | '!request_uri' => $log_entry['request_uri'],
51 | '!referer' => $log_entry['referer'],
52 | '!uid' => $uid,
53 | '!link' => strip_tags($log_entry['link']),
54 | ));
55 | error_log($message);
56 | }
57 | }
58 |
59 | // Get a $_SERVER key, or equivalent environment variable
60 | // if it is not set in $_SERVER.
61 | function runserver_env($key) {
62 | if (isset($_SERVER[$key])) {
63 | return $_SERVER[$key];
64 | }
65 | else {
66 | return getenv($key);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------