-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
InitCommands.php
191 lines (169 loc) · 7.56 KB
/
InitCommands.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<?php
namespace Drush\Commands\core;
use Consolidation\SiteProcess\Util\Escape;
use Drush\Drush;
use Drush\Commands\DrushCommands;
use Drush\Exceptions\UserAbortException;
use Drush\Exec\ExecTrait;
use Drush\Log\LogLevel;
use Robo\LoadAllTasks;
use Robo\Contract\IOAwareInterface;
use Robo\Contract\BuilderAwareInterface;
class InitCommands extends DrushCommands implements BuilderAwareInterface, IOAwareInterface
{
use LoadAllTasks;
use ExecTrait;
/**
* Enrich the bash startup file with bash aliases and a smart command prompt.
*
* @command core:init
*
* @option $edit Open the new config file in an editor.
* @option $add-path Always add Drush to the $PATH in the user's .bashrc
* file, even if it is already in the $PATH. Use --no-add-path to skip
* updating .bashrc with the Drush $PATH. Default is to update .bashrc
* only if Drush is not already in the $PATH.
* @optionset_get_editor
* @aliases init,core-init
* @usage core-init --edit
* Enrich Bash and open drush config file in editor.
* @usage core-init --edit --bg
* Return to shell prompt as soon as the editor window opens
*/
public function initializeDrush($options = ['edit' => false, 'add-path' => ''])
{
$home = $this->getConfig()->home();
$drush_config_dir = $home . "/.drush";
$drush_config_file = $drush_config_dir . "/drush.yml";
$drush_bashrc = $drush_config_dir . "/drush.bashrc";
$drush_prompt = $drush_config_dir . "/drush.prompt.sh";
$examples_dir = DRUSH_BASE_PATH . "/examples";
$example_configuration = $examples_dir . "/example.drush.yml";
$example_bashrc = $examples_dir . "/example.bashrc";
$example_prompt = $examples_dir . "/example.prompt.sh";
/**
* That's right. Robo collections and tasks are usable in Drush.
*/
$collection = $this->collectionBuilder();
// Create a ~/.drush directory if it does not yet exist
$collection->taskFilesystemStack()->mkdir($drush_config_dir);
// If there is no ~/.drush/drush.yml, copy example there.
if (!is_file($drush_config_file)) {
$collection->taskWriteToFile($drush_config_file)->textFromFile($example_configuration);
$collection->progressMessage('Copied example.drush.yml to {path}', ['path' => $drush_config_file], LogLevel::OK);
$this->logger()->notice('Copied drush.yml to ' . $drush_config_file);
} else {
$this->logger()->debug($drush_config_file . ' already exists. Skip copy.');
}
// Decide whether we want to add our Bash commands to
// ~/.bashrc or ~/.bash_profile, and create a task to
// update it with includes of the various files we write,
// as needed. If it is, then we will add it to the collection.
$bashrc = $this->findBashrc($home);
$taskUpdateBashrc = $this->taskWriteToFile($bashrc)->append();
// List of Drush bash configuration files, and
// their source templates.
$drushBashFiles = [
$drush_bashrc => $example_bashrc,
$drush_prompt => $example_prompt,
];
// Mapping from Drush bash configuration files
// to a description of what each one is.
$drushBashFileDescriptions = [
$drush_bashrc => 'Drush bash customizations',
$drush_prompt => 'Drush prompt customizations',
];
foreach ($drushBashFiles as $destFile => $sourceFile) {
// If the destination file does not exist, then
// copy the example file there.
if (!is_file($destFile)) {
$collection->taskWriteToFile($destFile)->textFromFile($sourceFile);
$description = $drushBashFileDescriptions[$destFile];
$collection->progressMessage('Copied {description} to {path}', ['description' => $description, 'path' => $destFile], LogLevel::OK);
$pattern = basename($destFile);
$taskUpdateBashrc->appendUnlessMatches("#$pattern#", "\n# Include $description.". $this->bashAddition($destFile));
}
}
// If Drush is not in the $PATH, then figure out which
// path to add so that Drush can be found globally.
$add_path = $options['add-path'];
if ((!self::programExists('drush') || $add_path) && ($add_path !== false)) {
$drush_path = $this->findPathToDrush();
$drush_path = preg_replace("%^" . preg_quote($home) . "/%", '$HOME/', $drush_path);
$pattern = "$drush_path";
$taskUpdateBashrc->appendUnlessMatches("#$pattern#", "\n# Path to Drush, added by 'drush init'.\nexport PATH=\"\$PATH:$drush_path\"\n\n");
}
$openEditor = false;
if ($taskUpdateBashrc->wouldChange()) {
if ($this->io()->confirm(dt("Modify !file to include Drush configuration files?", ['!file' => $bashrc]))) {
$collection->addTask($taskUpdateBashrc);
$collection->progressMessage('Updated bash configuration file {path}', ['path' => $bashrc], LogLevel::OK);
$collection->progressMessage('Start a new shell in order to experience the improvements (e.g. `{shell}`).', ['shell' => 'bash'], LogLevel::OK);
$openEditor = $options['edit'];
} else {
throw new UserAbortException();
}
} else {
$collection->progressMessage('No code added to {path}', ['path' => $bashrc]);
}
$result = $collection->run();
if ($result->wasSuccessful() && $openEditor) {
$editor = self::getEditor();
// A bit awkward due to backward compat.
$cmd = sprintf($editor, Escape::shellArg($drush_config_file));
$process = $this->processManager()->shell($cmd);
$process->setTty(true);
$process->mustRun();
}
return $result;
}
/**
* Determine which .bashrc file is best to use on this platform.
*/
protected function findBashrc($home)
{
# Set a default value in case nothing else exists.
$file = $home . '/.bashrc';
if (!empty($_ENV['SHELL']) && strstr($_ENV['SHELL'], 'zsh')) {
$file = $home . '/.zshrc';
} elseif (file_exists($home . '/.bash_profile')) {
$file = $home . '/.bash_profile';
} elseif (file_exists($home . '/.bashrc')) {
$file = $home . '/.bashrc';
} elseif (file_exists($home . '/.profile')) {
$file = $home . '/.profile';
} elseif (file_exists($home . '/.functions')) {
$file = $home . '/.functions';
}
return $file;
}
/**
* Determine where Drush is located, so that we can add
* that location to the $PATH.
*/
protected function findPathToDrush()
{
// First test: is Drush inside a vendor directory?
// Does vendor/bin exist? If so, use that. We do
// not have a good way to locate the 'bin' directory
// if it has been relocated in the composer.json config
// section.
if ($vendor_pos = strpos(DRUSH_BASE_PATH, "/vendor/")) {
$vendor_dir = substr(DRUSH_BASE_PATH, 0, $vendor_pos + 7);
$vendor_bin = $vendor_dir . '/bin';
if (is_dir($vendor_bin)) {
return $vendor_bin;
}
}
// Fallback is to use the directory that Drush is in.
return DRUSH_BASE_PATH;
}
protected function bashAddition($file)
{
return <<<EOD
if [ -f "$file" ] ; then
source $file
fi
EOD;
}
}