1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Robo\Task\Base; |
4
|
|
|
|
5
|
|
|
use Robo\Common\ExecTrait; |
6
|
|
|
use Robo\Contract\CommandInterface; |
7
|
|
|
use Robo\Contract\PrintedInterface; |
8
|
|
|
use Robo\Contract\SimulatedInterface; |
9
|
|
|
use Robo\Task\BaseTask; |
10
|
|
|
use Symfony\Component\Process\Process; |
11
|
|
|
use Robo\Result; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Executes shell script. Closes it when running in background mode. |
15
|
|
|
* |
16
|
|
|
* ``` php |
17
|
|
|
* <?php |
18
|
|
|
* $this->taskExec('compass')->arg('watch')->run(); |
19
|
|
|
* // or use shortcut |
20
|
|
|
* $this->_exec('compass watch'); |
21
|
|
|
* |
22
|
|
|
* $this->taskExec('compass watch')->background()->run(); |
23
|
|
|
* |
24
|
|
|
* if ($this->taskExec('phpunit .')->run()->wasSuccessful()) { |
25
|
|
|
* $this->say('tests passed'); |
26
|
|
|
* } |
27
|
|
|
* |
28
|
|
|
* ?> |
29
|
|
|
* ``` |
30
|
|
|
*/ |
31
|
|
|
class Exec extends BaseTask implements CommandInterface, PrintedInterface, SimulatedInterface |
32
|
|
|
{ |
33
|
|
|
use \Robo\Common\CommandReceiver; |
34
|
|
|
use \Robo\Common\ExecOneCommand; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var static[] |
38
|
|
|
*/ |
39
|
|
|
protected static $instances = []; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var string|\Robo\Contract\CommandInterface |
43
|
|
|
*/ |
44
|
|
|
protected $command; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @param string|\Robo\Contract\CommandInterface $command |
48
|
|
|
*/ |
49
|
|
|
public function __construct($command) |
50
|
|
|
{ |
51
|
|
|
$this->command = $this->receiveCommand($command); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
public function __destruct() |
55
|
|
|
{ |
56
|
|
|
$this->stop(); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Executes command in background mode (asynchronously) |
61
|
|
|
* |
62
|
|
|
* @param bool $arg |
63
|
|
|
* |
64
|
|
|
* @return $this |
65
|
|
|
*/ |
66
|
|
|
public function background($arg = true) |
67
|
|
|
{ |
68
|
|
|
self::$instances[] = $this; |
69
|
|
|
$this->background = $arg; |
70
|
|
|
return $this; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* {@inheritdoc} |
75
|
|
|
*/ |
76
|
|
|
protected function getCommandDescription() |
77
|
|
|
{ |
78
|
|
|
return $this->getCommand(); |
79
|
|
|
} |
80
|
|
|
/** |
81
|
|
|
* {@inheritdoc} |
82
|
|
|
*/ |
83
|
|
|
public function getCommand() |
84
|
|
|
{ |
85
|
|
|
return trim($this->command . $this->arguments); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* {@inheritdoc} |
90
|
|
|
*/ |
91
|
|
|
public function simulate($context) |
92
|
|
|
{ |
93
|
|
|
$this->printAction($context); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
public static function stopRunningJobs() |
97
|
|
|
{ |
98
|
|
|
foreach (self::$instances as $instance) { |
99
|
|
|
if ($instance) { |
100
|
|
|
unset($instance); |
101
|
|
|
} |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* {@inheritdoc} |
107
|
|
|
*/ |
108
|
|
|
public function run() |
109
|
|
|
{ |
110
|
|
|
$this->hideProgressIndicator(); |
111
|
|
|
// TODO: Symfony 4 requires that we supply the working directory. |
112
|
|
|
$result_data = $this->execute(Process::fromShellCommandline($this->getCommand(), getcwd())); |
113
|
|
|
return new Result( |
114
|
|
|
$this, |
115
|
|
|
$result_data->getExitCode(), |
116
|
|
|
$result_data->getMessage(), |
117
|
|
|
$result_data->getData() |
118
|
|
|
); |
119
|
|
|
$this->showProgressIndicator(); |
|
|
|
|
120
|
|
|
} |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
if (function_exists('pcntl_signal')) { |
124
|
|
|
pcntl_signal(SIGTERM, ['Robo\Task\Base\Exec', 'stopRunningJobs']); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
register_shutdown_function(['Robo\Task\Base\Exec', 'stopRunningJobs']); |
128
|
|
|
|
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return
,die
orexit
statements that have been added for debug purposes.In the above example, the last
return false
will never be executed, because a return statement has already been met in every possible execution path.