Skip to content

Commit cd4a8c5

Browse files
committed
Merge branch 'boedah-feature/rsync-task'
2 parents 4f624ee + 35c48b0 commit cd4a8c5

File tree

4 files changed

+310
-3
lines changed

4 files changed

+310
-3
lines changed

robo.phar

-1.32 MB
Binary file not shown.

src/Task/Development.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ protected function documentMethodDocBlock(\ReflectionMethod $reflectedMethod)
463463
$methodDoc = call_user_func($this->processMethodDocBlock, $reflectedMethod, $methodDoc);
464464
}
465465

466-
return trim($methodDoc);
466+
return $methodDoc;
467467
}
468468

469469
}

src/Task/Rsync.php

+306
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
<?php
2+
namespace Robo\Task;
3+
4+
use Robo\Output;
5+
use Robo\Task\Shared\CommandInterface;
6+
use Robo\Task\Shared\DynamicConfig;
7+
use Robo\Task\Shared\Executable;
8+
use Robo\Task\Shared\TaskException;
9+
use Robo\Task\Shared\TaskInterface;
10+
11+
trait Rsync
12+
{
13+
protected function taskRsync()
14+
{
15+
return new RsyncTask();
16+
}
17+
}
18+
19+
/**
20+
* Executes rsync in a flexible manner.
21+
*
22+
* ``` php
23+
* $this->taskRsync()
24+
* ->fromPath('src/')
25+
* ->toHost('localhost')
26+
* ->toUser('dev')
27+
* ->toPath('/var/www/html/app/')
28+
* ->recursive()
29+
* ->excludeVcs()
30+
* ->checksum()
31+
* ->wholeFile()
32+
* ->verbose()
33+
* ->progress()
34+
* ->humanReadable()
35+
* ->stats()
36+
* ->run();
37+
* ```
38+
*
39+
* You could also clone the task and do a dry-run first:
40+
*
41+
* ``` php
42+
* $rsync = $this->taskRsync()
43+
* ->fromPath('src/')
44+
* ->toPath('example.com:/var/www/html/app/')
45+
* ->archive()
46+
* ->excludeVcs()
47+
* ->progress()
48+
* ->stats();
49+
*
50+
* $dryRun = clone $rsync;
51+
* $dryRun->dryRun()->run();
52+
* if ('y' === $this->ask('Do you want to run (y/n)')) {
53+
* $rsync->run();
54+
* }
55+
* ```
56+
*
57+
* @method RsyncTask fromUser(string $user)
58+
* @method RsyncTask fromHost(string $hostname)
59+
* @method RsyncTask toUser(string $user)
60+
* @method RsyncTask toHost(string $hostname)
61+
*/
62+
class RsyncTask implements TaskInterface, CommandInterface
63+
{
64+
use Executable;
65+
use Output;
66+
use DynamicConfig;
67+
68+
protected $fromUser;
69+
70+
protected $fromHost;
71+
72+
protected $fromPath;
73+
74+
protected $toUser;
75+
76+
protected $toHost;
77+
78+
protected $toPath;
79+
80+
public function __construct()
81+
{
82+
$this->command = 'rsync';
83+
}
84+
85+
/**
86+
* This can either be a full rsync path spec (user@host:path) or just a path.
87+
* In case of the former do not specify host and user.
88+
*
89+
* @param string $path
90+
* @return $this
91+
*/
92+
public function fromPath($path)
93+
{
94+
$this->fromPath = $path;
95+
96+
return $this;
97+
}
98+
99+
/**
100+
* This can either be a full rsync path spec (user@host:path) or just a path.
101+
* In case of the former do not specify host and user.
102+
*
103+
* @param string $path
104+
* @return $this
105+
*/
106+
public function toPath($path)
107+
{
108+
$this->toPath = $path;
109+
110+
return $this;
111+
}
112+
113+
public function progress()
114+
{
115+
$this->option(__FUNCTION__);
116+
117+
return $this;
118+
}
119+
120+
public function stats()
121+
{
122+
$this->option(__FUNCTION__);
123+
124+
return $this;
125+
}
126+
127+
public function recursive()
128+
{
129+
$this->option(__FUNCTION__);
130+
131+
return $this;
132+
}
133+
134+
public function verbose()
135+
{
136+
$this->option(__FUNCTION__);
137+
138+
return $this;
139+
}
140+
141+
public function checksum()
142+
{
143+
$this->option(__FUNCTION__);
144+
145+
return $this;
146+
}
147+
148+
public function archive()
149+
{
150+
$this->option(__FUNCTION__);
151+
152+
return $this;
153+
}
154+
155+
public function compress()
156+
{
157+
$this->option(__FUNCTION__);
158+
159+
return $this;
160+
}
161+
162+
public function owner()
163+
{
164+
$this->option(__FUNCTION__);
165+
166+
return $this;
167+
}
168+
169+
public function group()
170+
{
171+
$this->option(__FUNCTION__);
172+
173+
return $this;
174+
}
175+
176+
public function times()
177+
{
178+
$this->option(__FUNCTION__);
179+
180+
return $this;
181+
}
182+
183+
public function delete()
184+
{
185+
$this->option(__FUNCTION__);
186+
187+
return $this;
188+
}
189+
190+
public function timeout($seconds)
191+
{
192+
$this->option(__FUNCTION__, $seconds);
193+
194+
return $this;
195+
}
196+
197+
public function humanReadable()
198+
{
199+
$this->option('human-readable');
200+
201+
return $this;
202+
}
203+
204+
public function wholeFile()
205+
{
206+
$this->option('whole-file');
207+
208+
return $this;
209+
}
210+
211+
public function dryRun()
212+
{
213+
$this->option('dry-run');
214+
215+
return $this;
216+
}
217+
218+
public function itemizeChanges()
219+
{
220+
$this->option('itemize-changes');
221+
222+
return $this;
223+
}
224+
225+
/**
226+
* Excludes .git/, .svn/ and .hg/ folders.
227+
*
228+
* @return $this
229+
*/
230+
public function excludeVcs()
231+
{
232+
$this->exclude('.git/')
233+
->exclude('.svn/')
234+
->exclude('.hg/');
235+
236+
return $this;
237+
}
238+
239+
public function exclude($pattern)
240+
{
241+
return $this->option('exclude', $pattern);
242+
}
243+
244+
public function excludeFrom($file)
245+
{
246+
if (!is_readable($file)) {
247+
throw new TaskException($this, "Exclude file $file is not readable");
248+
}
249+
250+
return $this->option('exclude-from', $file);
251+
}
252+
253+
public function filesFrom($file)
254+
{
255+
if (!is_readable($file)) {
256+
throw new TaskException($this, "Files-from file $file is not readable");
257+
}
258+
259+
return $this->option('files-from', $file);
260+
}
261+
262+
/**
263+
* @return \Robo\Result
264+
*/
265+
public function run()
266+
{
267+
$command = $this->getCommand();
268+
$this->printTaskInfo("running <info>{$command}</info>");
269+
270+
return $this->executeCommand($command);
271+
}
272+
273+
/**
274+
* Returns command that can be executed.
275+
* This method is used to pass generated command from one task to another.
276+
*
277+
* @return string
278+
*/
279+
public function getCommand()
280+
{
281+
$this->option(null, $this->getPathSpec('from'))
282+
->option(null, $this->getPathSpec('to'));
283+
284+
return $this->command . $this->arguments;
285+
}
286+
287+
protected function getPathSpec($type)
288+
{
289+
if ($type !== 'from' && $type !== 'to') {
290+
throw new TaskException($this, 'Type must be "from" or "to".');
291+
}
292+
foreach (['host', 'user', 'path'] as $part) {
293+
$varName = $type . ucfirst($part);
294+
$$part = $this->$varName;
295+
}
296+
$spec = isset($path) ? $path : '';
297+
if (!empty($host)) {
298+
$spec = "{$host}:{$spec}";
299+
}
300+
if (!empty($user)) {
301+
$spec = "{$user}@{$spec}";
302+
}
303+
304+
return $spec;
305+
}
306+
}

src/Tasks.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ class Tasks
1919
use Task\Concat;
2020
use Task\Bower;
2121
use Task\SshExec;
22+
use Task\Rsync;
2223
use Output;
2324

24-
protected function stopOnFail()
25+
protected function stopOnFail($stopOnFail = true)
2526
{
26-
Result::$stopOnFail = true;
27+
Result::$stopOnFail = $stopOnFail;
2728
}
2829
}

0 commit comments

Comments
 (0)