Chris@5
|
1 <?php
|
Chris@5
|
2 namespace Consolidation\SiteProcess;
|
Chris@5
|
3
|
Chris@5
|
4 use Consolidation\SiteAlias\SiteAliasInterface;
|
Chris@5
|
5 use Consolidation\SiteProcess\Transport\DockerComposeTransport;
|
Chris@5
|
6 use Consolidation\SiteProcess\Util\ArgumentProcessor;
|
Chris@5
|
7 use Consolidation\SiteProcess\Transport\LocalTransport;
|
Chris@5
|
8 use Consolidation\SiteProcess\Transport\SshTransport;
|
Chris@5
|
9 use Consolidation\SiteProcess\Transport\TransportInterface;
|
Chris@5
|
10 use Consolidation\Config\Util\Interpolator;
|
Chris@5
|
11 use Consolidation\SiteProcess\Util\ShellOperatorInterface;
|
Chris@5
|
12 use Consolidation\SiteProcess\Util\Escape;
|
Chris@5
|
13
|
Chris@5
|
14 /**
|
Chris@5
|
15 * A wrapper around Symfony Process that uses site aliases
|
Chris@5
|
16 * (https://github.com/consolidation/site-alias)
|
Chris@5
|
17 *
|
Chris@5
|
18 * - Interpolate arguments using values from the alias
|
Chris@5
|
19 * e.g. `$process = new SiteProcess($alias, ['git', '-C', '{{root}}']);`
|
Chris@5
|
20 * - Make remote calls via ssh as if they were local.
|
Chris@5
|
21 */
|
Chris@5
|
22 class SiteProcess extends ProcessBase
|
Chris@5
|
23 {
|
Chris@5
|
24 /** @var SiteAliasInterface */
|
Chris@5
|
25 protected $siteAlias;
|
Chris@5
|
26 /** @var string[] */
|
Chris@5
|
27 protected $args;
|
Chris@5
|
28 /** @var string[] */
|
Chris@5
|
29 protected $options;
|
Chris@5
|
30 /** @var string[] */
|
Chris@5
|
31 protected $optionsPassedAsArgs;
|
Chris@5
|
32 /** @var string */
|
Chris@5
|
33 protected $cd_remote;
|
Chris@5
|
34 /** @var TransportInterface */
|
Chris@5
|
35 protected $transport;
|
Chris@5
|
36
|
Chris@5
|
37 /**
|
Chris@5
|
38 * Process arguments and options per the site alias and build the
|
Chris@5
|
39 * actual command to run.
|
Chris@5
|
40 */
|
Chris@5
|
41 public function __construct(SiteAliasInterface $siteAlias, TransportInterface $transport, $args, $options = [], $optionsPassedAsArgs = [])
|
Chris@5
|
42 {
|
Chris@5
|
43 $this->siteAlias = $siteAlias;
|
Chris@5
|
44 $this->transport = $transport;
|
Chris@5
|
45 $this->args = $args;
|
Chris@5
|
46 $this->options = $options;
|
Chris@5
|
47 $this->optionsPassedAsArgs = $optionsPassedAsArgs;
|
Chris@5
|
48
|
Chris@5
|
49 parent::__construct([]);
|
Chris@5
|
50 }
|
Chris@5
|
51
|
Chris@5
|
52 /**
|
Chris@5
|
53 * Get a starting directory for the remote process.
|
Chris@5
|
54 *
|
Chris@5
|
55 * @return string|null
|
Chris@5
|
56 */
|
Chris@5
|
57 public function getWorkingDirectory()
|
Chris@5
|
58 {
|
Chris@5
|
59 return $this->cd_remote;
|
Chris@5
|
60 }
|
Chris@5
|
61
|
Chris@5
|
62 /**
|
Chris@5
|
63 * Set a starting directory for the remote process.
|
Chris@5
|
64 *
|
Chris@5
|
65 * @param string $cd_remote
|
Chris@5
|
66 *
|
Chris@5
|
67 * @return \Consolidation\SiteProcess\SiteProcess
|
Chris@5
|
68 */
|
Chris@5
|
69 public function setWorkingDirectory($cd_remote)
|
Chris@5
|
70 {
|
Chris@5
|
71 $this->cd_remote = $cd_remote;
|
Chris@5
|
72 return $this;
|
Chris@5
|
73 }
|
Chris@5
|
74
|
Chris@5
|
75 /**
|
Chris@5
|
76 * Set a starting directory for the initial/local process.
|
Chris@5
|
77 *
|
Chris@5
|
78 * @param string $cd
|
Chris@5
|
79 *
|
Chris@5
|
80 * @return \Consolidation\SiteProcess\SiteProcess
|
Chris@5
|
81 */
|
Chris@5
|
82 public function setWorkingDirectoryLocal($cd)
|
Chris@5
|
83 {
|
Chris@5
|
84 return parent::setWorkingDirectory($cd);
|
Chris@5
|
85 }
|
Chris@5
|
86
|
Chris@5
|
87 /**
|
Chris@5
|
88 * Get the starting directory for the initial/local process.
|
Chris@5
|
89 *
|
Chris@5
|
90 * @return string|null;
|
Chris@5
|
91 */
|
Chris@5
|
92 public function getWorkingDirectoryLocal()
|
Chris@5
|
93 {
|
Chris@5
|
94 return parent::getWorkingDirectory();
|
Chris@5
|
95 }
|
Chris@5
|
96
|
Chris@5
|
97 /**
|
Chris@5
|
98 *
|
Chris@5
|
99 * @param bool $shouldUseSiteRoot
|
Chris@5
|
100 * @return $this|\Symfony\Component\Process\Process
|
Chris@5
|
101 * @throws \Exception
|
Chris@5
|
102 */
|
Chris@5
|
103 public function chdirToSiteRoot($shouldUseSiteRoot = true)
|
Chris@5
|
104 {
|
Chris@5
|
105 if (!$shouldUseSiteRoot || !$this->siteAlias->hasRoot()) {
|
Chris@5
|
106 return $this;
|
Chris@5
|
107 }
|
Chris@5
|
108
|
Chris@5
|
109 return $this->setWorkingDirectory($this->siteAlias->root());
|
Chris@5
|
110 }
|
Chris@5
|
111
|
Chris@5
|
112 /**
|
Chris@5
|
113 * Take all of our individual arguments and process them for use.
|
Chris@5
|
114 */
|
Chris@5
|
115 protected function processArgs()
|
Chris@5
|
116 {
|
Chris@5
|
117 $transport = $this->getTransport($this->siteAlias);
|
Chris@5
|
118 $transport->configure($this);
|
Chris@5
|
119
|
Chris@5
|
120 $processor = new ArgumentProcessor();
|
Chris@5
|
121 $selectedArgs = $processor->selectArgs(
|
Chris@5
|
122 $this->siteAlias,
|
Chris@5
|
123 $this->args,
|
Chris@5
|
124 $this->options,
|
Chris@5
|
125 $this->optionsPassedAsArgs
|
Chris@5
|
126 );
|
Chris@5
|
127
|
Chris@5
|
128 // Ask the transport to drop in a 'cd' if needed.
|
Chris@5
|
129 if ($this->getWorkingDirectory()) {
|
Chris@5
|
130 $selectedArgs = $transport->addChdir($this->getWorkingDirectory(), $selectedArgs);
|
Chris@5
|
131 }
|
Chris@5
|
132
|
Chris@5
|
133 // Do any necessary interpolation on the selected arguments.
|
Chris@5
|
134 $processedArgs = $this->interpolate($selectedArgs);
|
Chris@5
|
135
|
Chris@5
|
136 // Wrap the command with 'ssh' or some other transport if this is
|
Chris@5
|
137 // a remote command; otherwise, leave it as-is.
|
Chris@5
|
138 return $transport->wrap($processedArgs);
|
Chris@5
|
139 }
|
Chris@5
|
140
|
Chris@5
|
141 public function setTransport($transport)
|
Chris@5
|
142 {
|
Chris@5
|
143 $this->transport = $transport;
|
Chris@5
|
144 }
|
Chris@5
|
145
|
Chris@5
|
146 /**
|
Chris@5
|
147 * Ask the transport manager for the correct transport for the
|
Chris@5
|
148 * provided alias.
|
Chris@5
|
149 */
|
Chris@5
|
150 protected function getTransport(SiteAliasInterface $siteAlias)
|
Chris@5
|
151 {
|
Chris@5
|
152 return $this->transport;
|
Chris@5
|
153 }
|
Chris@5
|
154
|
Chris@5
|
155 /**
|
Chris@5
|
156 * @inheritDoc
|
Chris@5
|
157 */
|
Chris@5
|
158 public function getCommandLine()
|
Chris@5
|
159 {
|
Chris@5
|
160 $commandLine = parent::getCommandLine();
|
Chris@5
|
161 if (empty($commandLine)) {
|
Chris@5
|
162 $processedArgs = $this->processArgs();
|
Chris@5
|
163 $commandLine = Escape::argsForSite($this->siteAlias, $processedArgs);
|
Chris@5
|
164 $commandLine = implode(' ', $commandLine);
|
Chris@5
|
165 $this->setCommandLine($commandLine);
|
Chris@5
|
166 }
|
Chris@5
|
167 return $commandLine;
|
Chris@5
|
168 }
|
Chris@5
|
169
|
Chris@5
|
170 /**
|
Chris@5
|
171 * @inheritDoc
|
Chris@5
|
172 */
|
Chris@5
|
173 public function start(callable $callback = null, $env = array())
|
Chris@5
|
174 {
|
Chris@5
|
175 $cmd = $this->getCommandLine();
|
Chris@5
|
176 parent::start($callback, $env);
|
Chris@5
|
177 }
|
Chris@5
|
178
|
Chris@5
|
179 /**
|
Chris@5
|
180 * @inheritDoc
|
Chris@5
|
181 */
|
Chris@5
|
182 public function wait(callable $callback = null)
|
Chris@5
|
183 {
|
Chris@5
|
184 $return = parent::wait($callback);
|
Chris@5
|
185 return $return;
|
Chris@5
|
186 }
|
Chris@5
|
187
|
Chris@5
|
188 /**
|
Chris@5
|
189 * interpolate examines each of the arguments in the provided argument list
|
Chris@5
|
190 * and replaces any token found therein with the value for that key as
|
Chris@5
|
191 * pulled from the given site alias.
|
Chris@5
|
192 *
|
Chris@5
|
193 * Example: "git -C {{root}} status"
|
Chris@5
|
194 *
|
Chris@5
|
195 * The token "{{root}}" will be converted to a value via $siteAlias->get('root').
|
Chris@5
|
196 * The result will replace the token.
|
Chris@5
|
197 *
|
Chris@5
|
198 * It is possible to use dot notation in the keys to access nested elements
|
Chris@5
|
199 * within the site alias record.
|
Chris@5
|
200 *
|
Chris@5
|
201 * @param SiteAliasInterface $siteAlias
|
Chris@5
|
202 * @param type $args
|
Chris@5
|
203 * @return type
|
Chris@5
|
204 */
|
Chris@5
|
205 protected function interpolate($args)
|
Chris@5
|
206 {
|
Chris@5
|
207 $interpolator = new Interpolator();
|
Chris@5
|
208 return array_map(
|
Chris@5
|
209 function ($arg) use ($interpolator) {
|
Chris@5
|
210 if ($arg instanceof ShellOperatorInterface) {
|
Chris@5
|
211 return $arg;
|
Chris@5
|
212 }
|
Chris@5
|
213 return $interpolator->interpolate($this->siteAlias, $arg, false);
|
Chris@5
|
214 },
|
Chris@5
|
215 $args
|
Chris@5
|
216 );
|
Chris@5
|
217 }
|
Chris@5
|
218 }
|