1 |
efrain |
1 |
<?php
|
|
|
2 |
// This file is part of Moodle - http://moodle.org/
|
|
|
3 |
//
|
|
|
4 |
// Moodle is free software: you can redistribute it and/or modify
|
|
|
5 |
// it under the terms of the GNU General Public License as published by
|
|
|
6 |
// the Free Software Foundation, either version 3 of the License, or
|
|
|
7 |
// (at your option) any later version.
|
|
|
8 |
//
|
|
|
9 |
// Moodle is distributed in the hope that it will be useful,
|
|
|
10 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
11 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
12 |
// GNU General Public License for more details.
|
|
|
13 |
//
|
|
|
14 |
// You should have received a copy of the GNU General Public License
|
|
|
15 |
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
16 |
|
|
|
17 |
/**
|
|
|
18 |
* CLI tool with utilities to manage parallel Behat integration in Moodle
|
|
|
19 |
*
|
|
|
20 |
* All CLI utilities uses $CFG->behat_dataroot and $CFG->prefix_dataroot as
|
|
|
21 |
* $CFG->dataroot and $CFG->prefix
|
|
|
22 |
* Same applies for $CFG->behat_dbname, $CFG->behat_dbuser, $CFG->behat_dbpass
|
|
|
23 |
* and $CFG->behat_dbhost. But if any of those is not defined $CFG->dbname,
|
|
|
24 |
* $CFG->dbuser, $CFG->dbpass and/or $CFG->dbhost will be used.
|
|
|
25 |
*
|
|
|
26 |
* @package tool_behat
|
|
|
27 |
* @copyright 2012 David Monllaó
|
|
|
28 |
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
29 |
*/
|
|
|
30 |
|
|
|
31 |
|
|
|
32 |
if (isset($_SERVER['REMOTE_ADDR'])) {
|
|
|
33 |
die(); // No access from web!.
|
|
|
34 |
}
|
|
|
35 |
|
|
|
36 |
define('BEHAT_UTIL', true);
|
|
|
37 |
define('CLI_SCRIPT', true);
|
|
|
38 |
define('NO_OUTPUT_BUFFERING', true);
|
|
|
39 |
define('IGNORE_COMPONENT_CACHE', true);
|
|
|
40 |
define('ABORT_AFTER_CONFIG', true);
|
|
|
41 |
|
|
|
42 |
require_once(__DIR__ . '/../../../../lib/clilib.php');
|
|
|
43 |
|
|
|
44 |
// CLI options.
|
|
|
45 |
list($options, $unrecognized) = cli_get_params(
|
|
|
46 |
array(
|
|
|
47 |
'help' => false,
|
|
|
48 |
'install' => false,
|
|
|
49 |
'drop' => false,
|
|
|
50 |
'enable' => false,
|
|
|
51 |
'disable' => false,
|
|
|
52 |
'diag' => false,
|
|
|
53 |
'parallel' => 0,
|
|
|
54 |
'maxruns' => false,
|
|
|
55 |
'updatesteps' => false,
|
|
|
56 |
'fromrun' => 1,
|
|
|
57 |
'torun' => 0,
|
|
|
58 |
'optimize-runs' => '',
|
|
|
59 |
'add-core-features-to-theme' => false,
|
|
|
60 |
'axe' => true,
|
|
|
61 |
'scss-deprecations' => false,
|
|
|
62 |
),
|
|
|
63 |
array(
|
|
|
64 |
'h' => 'help',
|
|
|
65 |
'j' => 'parallel',
|
|
|
66 |
'm' => 'maxruns',
|
|
|
67 |
'o' => 'optimize-runs',
|
|
|
68 |
'a' => 'add-core-features-to-theme',
|
|
|
69 |
)
|
|
|
70 |
);
|
|
|
71 |
|
|
|
72 |
// Checking util.php CLI script usage.
|
|
|
73 |
$help = "
|
|
|
74 |
Behat utilities to manage the test environment
|
|
|
75 |
|
|
|
76 |
Usage:
|
|
|
77 |
php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--no-axe|--scss-deprecations|--help]
|
|
|
78 |
[--parallel=value [--maxruns=value]]
|
|
|
79 |
|
|
|
80 |
Options:
|
|
|
81 |
--install Installs the test environment for acceptance tests
|
|
|
82 |
--drop Drops the database tables and the dataroot contents
|
|
|
83 |
--enable Enables test environment and updates tests list
|
|
|
84 |
--disable Disables test environment
|
|
|
85 |
--diag Get behat test environment status code
|
|
|
86 |
--updatesteps Update feature step file.
|
|
|
87 |
--no-axe Disable axe accessibility tests.
|
|
|
88 |
--scss-deprecations Enable SCSS deprecation checks.
|
|
|
89 |
|
|
|
90 |
-j, --parallel Number of parallel behat run operation
|
|
|
91 |
-m, --maxruns Max parallel processes to be executed at one time.
|
|
|
92 |
-o, --optimize-runs Split features with specified tags in all parallel runs.
|
|
|
93 |
-a, --add-core-features-to-theme Add all core features to specified theme's
|
|
|
94 |
|
|
|
95 |
-h, --help Print out this help
|
|
|
96 |
|
|
|
97 |
Example from Moodle root directory:
|
|
|
98 |
\$ php admin/tool/behat/cli/util.php --enable --parallel=4
|
|
|
99 |
|
|
|
100 |
More info in https://moodledev.io/general/development/tools/behat/running
|
|
|
101 |
";
|
|
|
102 |
|
|
|
103 |
if (!empty($options['help'])) {
|
|
|
104 |
echo $help;
|
|
|
105 |
exit(0);
|
|
|
106 |
}
|
|
|
107 |
|
|
|
108 |
$cwd = getcwd();
|
|
|
109 |
|
|
|
110 |
// If Behat parallel site is being initiliased, then define a param to be used to ignore single run install.
|
|
|
111 |
if (!empty($options['parallel'])) {
|
|
|
112 |
define('BEHAT_PARALLEL_UTIL', true);
|
|
|
113 |
}
|
|
|
114 |
|
|
|
115 |
require_once(__DIR__ . '/../../../../config.php');
|
|
|
116 |
require_once(__DIR__ . '/../../../../lib/behat/lib.php');
|
|
|
117 |
require_once(__DIR__ . '/../../../../lib/behat/classes/behat_command.php');
|
|
|
118 |
require_once(__DIR__ . '/../../../../lib/behat/classes/behat_config_manager.php');
|
|
|
119 |
|
|
|
120 |
// Remove error handling overrides done in config.php. This is consistent with admin/tool/behat/cli/util_single_run.php.
|
|
|
121 |
$CFG->debug = (E_ALL | E_STRICT);
|
|
|
122 |
$CFG->debugdisplay = 1;
|
|
|
123 |
error_reporting($CFG->debug);
|
|
|
124 |
ini_set('display_errors', '1');
|
|
|
125 |
ini_set('log_errors', '1');
|
|
|
126 |
|
|
|
127 |
// Import the necessary libraries.
|
|
|
128 |
require_once($CFG->libdir . '/setuplib.php');
|
|
|
129 |
require_once($CFG->libdir . '/behat/classes/util.php');
|
|
|
130 |
|
|
|
131 |
// For drop option check if parallel site.
|
|
|
132 |
if ((empty($options['parallel'])) && ($options['drop']) || $options['updatesteps']) {
|
|
|
133 |
$options['parallel'] = behat_config_manager::get_behat_run_config_value('parallel');
|
|
|
134 |
}
|
|
|
135 |
|
|
|
136 |
// If not a parallel site then open single run.
|
|
|
137 |
if (empty($options['parallel'])) {
|
|
|
138 |
// Set run config value for single run.
|
|
|
139 |
behat_config_manager::set_behat_run_config_value('singlerun', 1);
|
|
|
140 |
|
|
|
141 |
chdir(__DIR__);
|
|
|
142 |
// Check if behat is initialised, if not exit.
|
|
|
143 |
passthru("php util_single_run.php --diag", $status);
|
|
|
144 |
if ($status) {
|
|
|
145 |
exit ($status);
|
|
|
146 |
}
|
|
|
147 |
$cmd = commands_to_execute($options);
|
|
|
148 |
$processes = cli_execute_parallel(array($cmd), __DIR__);
|
|
|
149 |
$status = print_sequential_output($processes, false);
|
|
|
150 |
chdir($cwd);
|
|
|
151 |
exit($status);
|
|
|
152 |
}
|
|
|
153 |
|
|
|
154 |
// Default torun is maximum parallel runs.
|
|
|
155 |
if (empty($options['torun'])) {
|
|
|
156 |
$options['torun'] = $options['parallel'];
|
|
|
157 |
}
|
|
|
158 |
|
|
|
159 |
$status = false;
|
|
|
160 |
$cmds = commands_to_execute($options);
|
|
|
161 |
|
|
|
162 |
// Start executing commands either sequential/parallel for options provided.
|
|
|
163 |
if ($options['diag'] || $options['enable'] || $options['disable']) {
|
|
|
164 |
// Do it sequentially as it's fast and need to be displayed nicely.
|
|
|
165 |
foreach (array_chunk($cmds, 1, true) as $cmd) {
|
|
|
166 |
$processes = cli_execute_parallel($cmd, __DIR__);
|
|
|
167 |
print_sequential_output($processes);
|
|
|
168 |
}
|
|
|
169 |
|
|
|
170 |
} else if ($options['drop']) {
|
|
|
171 |
$processes = cli_execute_parallel($cmds, __DIR__);
|
|
|
172 |
$exitcodes = print_combined_drop_output($processes);
|
|
|
173 |
foreach ($exitcodes as $exitcode) {
|
|
|
174 |
$status = (bool)$status || (bool)$exitcode;
|
|
|
175 |
}
|
|
|
176 |
|
|
|
177 |
// Remove run config file.
|
|
|
178 |
$behatrunconfigfile = behat_config_manager::get_behat_run_config_file_path();
|
|
|
179 |
if (file_exists($behatrunconfigfile)) {
|
|
|
180 |
if (!unlink($behatrunconfigfile)) {
|
|
|
181 |
behat_error(BEHAT_EXITCODE_PERMISSIONS, 'Can not delete behat run config file');
|
|
|
182 |
}
|
|
|
183 |
}
|
|
|
184 |
|
|
|
185 |
// Remove test file path.
|
|
|
186 |
if (file_exists(behat_util::get_test_file_path())) {
|
|
|
187 |
if (!unlink(behat_util::get_test_file_path())) {
|
|
|
188 |
behat_error(BEHAT_EXITCODE_PERMISSIONS, 'Can not delete test file enable info');
|
|
|
189 |
}
|
|
|
190 |
}
|
|
|
191 |
|
|
|
192 |
} else if ($options['install']) {
|
|
|
193 |
// This is intensive compared to behat itself so run them in chunk if option maxruns not set.
|
|
|
194 |
if ($options['maxruns']) {
|
|
|
195 |
foreach (array_chunk($cmds, $options['maxruns'], true) as $chunk) {
|
|
|
196 |
$processes = cli_execute_parallel($chunk, __DIR__);
|
|
|
197 |
$exitcodes = print_combined_install_output($processes);
|
|
|
198 |
foreach ($exitcodes as $name => $exitcode) {
|
|
|
199 |
if ($exitcode != 0) {
|
|
|
200 |
echo "Failed process [[$name]]" . PHP_EOL;
|
|
|
201 |
echo $processes[$name]->getOutput();
|
|
|
202 |
echo PHP_EOL;
|
|
|
203 |
echo $processes[$name]->getErrorOutput();
|
|
|
204 |
echo PHP_EOL . PHP_EOL;
|
|
|
205 |
}
|
|
|
206 |
$status = (bool)$status || (bool)$exitcode;
|
|
|
207 |
}
|
|
|
208 |
}
|
|
|
209 |
} else {
|
|
|
210 |
$processes = cli_execute_parallel($cmds, __DIR__);
|
|
|
211 |
$exitcodes = print_combined_install_output($processes);
|
|
|
212 |
foreach ($exitcodes as $name => $exitcode) {
|
|
|
213 |
if ($exitcode != 0) {
|
|
|
214 |
echo "Failed process [[$name]]" . PHP_EOL;
|
|
|
215 |
echo $processes[$name]->getOutput();
|
|
|
216 |
echo PHP_EOL;
|
|
|
217 |
echo $processes[$name]->getErrorOutput();
|
|
|
218 |
echo PHP_EOL . PHP_EOL;
|
|
|
219 |
}
|
|
|
220 |
$status = (bool)$status || (bool)$exitcode;
|
|
|
221 |
}
|
|
|
222 |
}
|
|
|
223 |
|
|
|
224 |
} else if ($options['updatesteps']) {
|
|
|
225 |
// Rewrite config file to ensure we have all the features covered.
|
|
|
226 |
if (empty($options['parallel'])) {
|
|
|
227 |
behat_config_manager::update_config_file('', true, '', $options['add-core-features-to-theme'], false, false);
|
|
|
228 |
} else {
|
|
|
229 |
// Update config file, ensuring we have up-to-date behat.yml.
|
|
|
230 |
for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
|
|
|
231 |
$CFG->behatrunprocess = $i;
|
|
|
232 |
|
|
|
233 |
// Update config file for each run.
|
|
|
234 |
behat_config_manager::update_config_file('', true, $options['optimize-runs'], $options['add-core-features-to-theme'],
|
|
|
235 |
$options['parallel'], $i);
|
|
|
236 |
}
|
|
|
237 |
unset($CFG->behatrunprocess);
|
|
|
238 |
}
|
|
|
239 |
|
|
|
240 |
// Do it sequentially as it's fast and need to be displayed nicely.
|
|
|
241 |
foreach (array_chunk($cmds, 1, true) as $cmd) {
|
|
|
242 |
$processes = cli_execute_parallel($cmd, __DIR__);
|
|
|
243 |
print_sequential_output($processes);
|
|
|
244 |
}
|
|
|
245 |
exit(0);
|
|
|
246 |
|
|
|
247 |
} else {
|
|
|
248 |
// We should never reach here.
|
|
|
249 |
echo $help;
|
|
|
250 |
exit(1);
|
|
|
251 |
}
|
|
|
252 |
|
|
|
253 |
// Ensure we have success status to show following information.
|
|
|
254 |
if ($status) {
|
|
|
255 |
echo "Unknown failure $status" . PHP_EOL;
|
|
|
256 |
exit((int)$status);
|
|
|
257 |
}
|
|
|
258 |
|
|
|
259 |
// Show command o/p (only one per time).
|
|
|
260 |
if ($options['install']) {
|
|
|
261 |
echo "Acceptance tests site installed for sites:".PHP_EOL;
|
|
|
262 |
|
|
|
263 |
// Display all sites which are installed/drop/diabled.
|
|
|
264 |
for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
|
|
|
265 |
if (empty($CFG->behat_parallel_run[$i - 1]['behat_wwwroot'])) {
|
|
|
266 |
echo $CFG->behat_wwwroot . "/" . BEHAT_PARALLEL_SITE_NAME . $i . PHP_EOL;
|
|
|
267 |
} else {
|
|
|
268 |
echo $CFG->behat_parallel_run[$i - 1]['behat_wwwroot'] . PHP_EOL;
|
|
|
269 |
}
|
|
|
270 |
|
|
|
271 |
}
|
|
|
272 |
} else if ($options['drop']) {
|
|
|
273 |
echo "Acceptance tests site dropped for " . $options['parallel'] . " parallel sites" . PHP_EOL;
|
|
|
274 |
|
|
|
275 |
} else if ($options['enable']) {
|
|
|
276 |
echo "Acceptance tests environment enabled on $CFG->behat_wwwroot, to run the tests use:" . PHP_EOL;
|
|
|
277 |
echo behat_command::get_behat_command(true, true);
|
|
|
278 |
|
|
|
279 |
// Save fromrun and to run information.
|
|
|
280 |
if (isset($options['fromrun'])) {
|
|
|
281 |
behat_config_manager::set_behat_run_config_value('fromrun', $options['fromrun']);
|
|
|
282 |
}
|
|
|
283 |
|
|
|
284 |
if (isset($options['torun'])) {
|
|
|
285 |
behat_config_manager::set_behat_run_config_value('torun', $options['torun']);
|
|
|
286 |
}
|
|
|
287 |
if (isset($options['parallel'])) {
|
|
|
288 |
behat_config_manager::set_behat_run_config_value('parallel', $options['parallel']);
|
|
|
289 |
}
|
|
|
290 |
|
|
|
291 |
echo PHP_EOL;
|
|
|
292 |
|
|
|
293 |
} else if ($options['disable']) {
|
|
|
294 |
echo "Acceptance tests environment disabled for " . $options['parallel'] . " parallel sites" . PHP_EOL;
|
|
|
295 |
|
|
|
296 |
} else if ($options['diag']) {
|
|
|
297 |
// Valid option, so nothing to do.
|
|
|
298 |
} else {
|
|
|
299 |
echo $help;
|
|
|
300 |
chdir($cwd);
|
|
|
301 |
exit(1);
|
|
|
302 |
}
|
|
|
303 |
|
|
|
304 |
chdir($cwd);
|
|
|
305 |
exit(0);
|
|
|
306 |
|
|
|
307 |
/**
|
|
|
308 |
* Create commands to be executed for parallel run.
|
|
|
309 |
*
|
|
|
310 |
* @param array $options options provided by user.
|
|
|
311 |
* @return array commands to be executed.
|
|
|
312 |
*/
|
|
|
313 |
function commands_to_execute($options) {
|
|
|
314 |
$removeoptions = array('maxruns', 'fromrun', 'torun');
|
|
|
315 |
$cmds = array();
|
|
|
316 |
$extraoptions = $options;
|
|
|
317 |
$extra = "";
|
|
|
318 |
|
|
|
319 |
// Remove extra options not in util_single_run.php.
|
|
|
320 |
foreach ($removeoptions as $ro) {
|
|
|
321 |
$extraoptions[$ro] = null;
|
|
|
322 |
unset($extraoptions[$ro]);
|
|
|
323 |
}
|
|
|
324 |
|
|
|
325 |
foreach ($extraoptions as $option => $value) {
|
|
|
326 |
$extra .= behat_get_command_flags($option, $value);
|
|
|
327 |
}
|
|
|
328 |
|
|
|
329 |
if (empty($options['parallel'])) {
|
|
|
330 |
$cmds = "php util_single_run.php " . $extra;
|
|
|
331 |
} else {
|
|
|
332 |
// Create commands which has to be executed for parallel site.
|
|
|
333 |
for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
|
|
|
334 |
$prefix = BEHAT_PARALLEL_SITE_NAME . $i;
|
|
|
335 |
$cmds[$prefix] = "php util_single_run.php " . $extra . " --run=" . $i . " 2>&1";
|
|
|
336 |
}
|
|
|
337 |
}
|
|
|
338 |
return $cmds;
|
|
|
339 |
}
|
|
|
340 |
|
|
|
341 |
/**
|
|
|
342 |
* Print drop output merging each run.
|
|
|
343 |
*
|
|
|
344 |
* @param array $processes list of processes.
|
|
|
345 |
* @return array exit codes of each process.
|
|
|
346 |
*/
|
|
|
347 |
function print_combined_drop_output($processes) {
|
|
|
348 |
$exitcodes = array();
|
|
|
349 |
$maxdotsonline = 70;
|
|
|
350 |
$remainingprintlen = $maxdotsonline;
|
|
|
351 |
$progresscount = 0;
|
|
|
352 |
echo "Dropping tables:" . PHP_EOL;
|
|
|
353 |
|
|
|
354 |
while (count($exitcodes) != count($processes)) {
|
|
|
355 |
usleep(10000);
|
|
|
356 |
foreach ($processes as $name => $process) {
|
|
|
357 |
if ($process->isRunning()) {
|
|
|
358 |
$op = $process->getIncrementalOutput();
|
|
|
359 |
if (trim($op)) {
|
|
|
360 |
$update = preg_filter('#^\s*([FS\.\-]+)(?:\s+\d+)?\s*$#', '$1', $op);
|
|
|
361 |
$strlentoprint = $update ? strlen($update) : 0;
|
|
|
362 |
|
|
|
363 |
// If not enough dots printed on line then just print.
|
|
|
364 |
if ($strlentoprint < $remainingprintlen) {
|
|
|
365 |
echo $update;
|
|
|
366 |
$remainingprintlen = $remainingprintlen - $strlentoprint;
|
|
|
367 |
} else if ($strlentoprint == $remainingprintlen) {
|
|
|
368 |
$progresscount += $maxdotsonline;
|
|
|
369 |
echo $update . " " . $progresscount . PHP_EOL;
|
|
|
370 |
$remainingprintlen = $maxdotsonline;
|
|
|
371 |
} else {
|
|
|
372 |
while ($part = substr($update, 0, $remainingprintlen) > 0) {
|
|
|
373 |
$progresscount += $maxdotsonline;
|
|
|
374 |
echo $part . " " . $progresscount . PHP_EOL;
|
|
|
375 |
$update = substr($update, $remainingprintlen);
|
|
|
376 |
$remainingprintlen = $maxdotsonline;
|
|
|
377 |
}
|
|
|
378 |
}
|
|
|
379 |
}
|
|
|
380 |
} else {
|
|
|
381 |
// Process exited.
|
|
|
382 |
$process->clearOutput();
|
|
|
383 |
$exitcodes[$name] = $process->getExitCode();
|
|
|
384 |
}
|
|
|
385 |
}
|
|
|
386 |
}
|
|
|
387 |
|
|
|
388 |
echo PHP_EOL;
|
|
|
389 |
return $exitcodes;
|
|
|
390 |
}
|
|
|
391 |
|
|
|
392 |
/**
|
|
|
393 |
* Print install output merging each run.
|
|
|
394 |
*
|
|
|
395 |
* @param array $processes list of processes.
|
|
|
396 |
* @return array exit codes of each process.
|
|
|
397 |
*/
|
|
|
398 |
function print_combined_install_output($processes) {
|
|
|
399 |
$exitcodes = array();
|
|
|
400 |
$line = array();
|
|
|
401 |
|
|
|
402 |
// Check what best we can do to accommodate all parallel run o/p on single line.
|
|
|
403 |
// Windows command line has length of 80 chars, so default we will try fit o/p in 80 chars.
|
|
|
404 |
if (defined('BEHAT_MAX_CMD_LINE_OUTPUT') && BEHAT_MAX_CMD_LINE_OUTPUT) {
|
|
|
405 |
$lengthofprocessline = (int)max(10, BEHAT_MAX_CMD_LINE_OUTPUT / count($processes));
|
|
|
406 |
} else {
|
|
|
407 |
$lengthofprocessline = (int)max(10, 80 / count($processes));
|
|
|
408 |
}
|
|
|
409 |
|
|
|
410 |
echo "Installing behat site for " . count($processes) . " parallel behat run" . PHP_EOL;
|
|
|
411 |
|
|
|
412 |
// Show process name in first row.
|
|
|
413 |
foreach ($processes as $name => $process) {
|
|
|
414 |
// If we don't have enough space to show full run name then show runX.
|
|
|
415 |
if ($lengthofprocessline < strlen($name) + 2) {
|
|
|
416 |
$name = substr($name, -5);
|
|
|
417 |
}
|
|
|
418 |
// One extra padding as we are adding | separator for rest of the data.
|
|
|
419 |
$line[$name] = str_pad('[' . $name . '] ', $lengthofprocessline + 1);
|
|
|
420 |
}
|
|
|
421 |
ksort($line);
|
|
|
422 |
$tableheader = array_keys($line);
|
|
|
423 |
echo implode("", $line) . PHP_EOL;
|
|
|
424 |
|
|
|
425 |
// Now print o/p from each process.
|
|
|
426 |
while (count($exitcodes) != count($processes)) {
|
|
|
427 |
usleep(50000);
|
|
|
428 |
$poutput = array();
|
|
|
429 |
// Create child process.
|
|
|
430 |
foreach ($processes as $name => $process) {
|
|
|
431 |
if ($process->isRunning()) {
|
|
|
432 |
$output = $process->getIncrementalOutput();
|
|
|
433 |
if (trim($output)) {
|
|
|
434 |
$poutput[$name] = explode(PHP_EOL, $output);
|
|
|
435 |
}
|
|
|
436 |
} else {
|
|
|
437 |
// Process exited.
|
|
|
438 |
$exitcodes[$name] = $process->getExitCode();
|
|
|
439 |
}
|
|
|
440 |
}
|
|
|
441 |
ksort($poutput);
|
|
|
442 |
|
|
|
443 |
// Get max depth of o/p before displaying.
|
|
|
444 |
$maxdepth = 0;
|
|
|
445 |
foreach ($poutput as $pout) {
|
|
|
446 |
$pdepth = count($pout);
|
|
|
447 |
$maxdepth = $pdepth >= $maxdepth ? $pdepth : $maxdepth;
|
|
|
448 |
}
|
|
|
449 |
|
|
|
450 |
// Iterate over each process to get line to print.
|
|
|
451 |
for ($i = 0; $i <= $maxdepth; $i++) {
|
|
|
452 |
$pline = "";
|
|
|
453 |
foreach ($tableheader as $name) {
|
|
|
454 |
$po = empty($poutput[$name][$i]) ? "" : substr($poutput[$name][$i], 0, $lengthofprocessline - 1);
|
|
|
455 |
$po = str_pad($po, $lengthofprocessline);
|
|
|
456 |
$pline .= "|". $po;
|
|
|
457 |
}
|
|
|
458 |
if (trim(str_replace("|", "", $pline))) {
|
|
|
459 |
echo $pline . PHP_EOL;
|
|
|
460 |
}
|
|
|
461 |
}
|
|
|
462 |
unset($poutput);
|
|
|
463 |
$poutput = null;
|
|
|
464 |
|
|
|
465 |
}
|
|
|
466 |
echo PHP_EOL;
|
|
|
467 |
return $exitcodes;
|
|
|
468 |
}
|
|
|
469 |
|
|
|
470 |
/**
|
|
|
471 |
* Print install output merging showing one run at a time.
|
|
|
472 |
* If any process fail then exit.
|
|
|
473 |
*
|
|
|
474 |
* @param array $processes list of processes.
|
|
|
475 |
* @param bool $showprefix show prefix.
|
|
|
476 |
* @return bool exitcode.
|
|
|
477 |
*/
|
|
|
478 |
function print_sequential_output($processes, $showprefix = true) {
|
|
|
479 |
$status = false;
|
|
|
480 |
foreach ($processes as $name => $process) {
|
|
|
481 |
$shownname = false;
|
|
|
482 |
while ($process->isRunning()) {
|
|
|
483 |
$op = $process->getIncrementalOutput();
|
|
|
484 |
if (trim($op)) {
|
|
|
485 |
// Show name of the run once for sequential.
|
|
|
486 |
if ($showprefix && !$shownname) {
|
|
|
487 |
echo '[' . $name . '] ';
|
|
|
488 |
$shownname = true;
|
|
|
489 |
}
|
|
|
490 |
echo $op;
|
|
|
491 |
}
|
|
|
492 |
}
|
|
|
493 |
// If any error then exit.
|
|
|
494 |
$exitcode = $process->getExitCode();
|
|
|
495 |
if ($exitcode != 0) {
|
|
|
496 |
exit($exitcode);
|
|
|
497 |
}
|
|
|
498 |
$status = $status || (bool)$exitcode;
|
|
|
499 |
}
|
|
|
500 |
return $status;
|
|
|
501 |
}
|