1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* See class comment |
4
|
|
|
* |
5
|
|
|
* PHP Version 5 |
6
|
|
|
* |
7
|
|
|
* @category Netresearch |
8
|
|
|
* @package Netresearch\Kite\Workflow\Composer |
9
|
|
|
* @author Christian Opitz <[email protected]> |
10
|
|
|
* @license http://www.netresearch.de Netresearch Copyright |
11
|
|
|
* @link http://www.netresearch.de |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
namespace Netresearch\Kite\Workflow\Composer; |
15
|
|
|
use Netresearch\Kite\Exception; |
16
|
|
|
|
17
|
|
|
use Netresearch\Kite\Workflow; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Workflow to diagnose packages and fix found problems |
21
|
|
|
* |
22
|
|
|
* @category Netresearch |
23
|
|
|
* @package Netresearch\Kite\Workflow\Composer |
24
|
|
|
* @author Christian Opitz <[email protected]> |
25
|
|
|
* @license http://www.netresearch.de Netresearch Copyright |
26
|
|
|
* @link http://www.netresearch.de |
27
|
|
|
*/ |
28
|
|
|
class Diagnose extends Base |
29
|
|
|
{ |
30
|
|
|
/** |
31
|
|
|
* @var array |
32
|
|
|
*/ |
33
|
|
|
protected $checks = array(); |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var array |
37
|
|
|
*/ |
38
|
|
|
protected $fixes = array(); |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @var bool |
42
|
|
|
*/ |
43
|
|
|
protected $composerUpdateRequired = false; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var bool |
47
|
|
|
*/ |
48
|
|
|
protected $dontCheckCurrentPackageAgain = false; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Configure the options |
52
|
|
|
* |
53
|
|
|
* @return array |
54
|
|
|
*/ |
55
|
|
|
protected function configureVariables() |
56
|
|
|
{ |
57
|
|
|
foreach (get_class_methods($this) as $method) { |
58
|
|
|
if (substr($method, 0, 5) === 'check' && $method[5] === strtoupper($method[5])) { |
59
|
|
|
$check = substr($method, 5); |
60
|
|
|
$this->checks[] = $check; |
61
|
|
|
if (method_exists($this, 'fix' . $check)) { |
62
|
|
|
$this->fixes[] = $check; |
63
|
|
|
} |
64
|
|
|
} |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
return array( |
68
|
|
|
'check' => array( |
69
|
|
|
'type' => 'array', |
70
|
|
|
'option' => true, |
71
|
|
|
'label' => 'Only execute these checks - available checks are ' . implode(', ', $this->checks), |
72
|
|
|
), |
73
|
|
|
'fix' => array( |
74
|
|
|
'type' => 'boolean|array', |
75
|
|
|
'option' => true, |
76
|
|
|
'label' => 'Enable fixes and optionally reduce to certain fixes - available fixes are ' . implode(', ', $this->fixes), |
77
|
|
|
), |
78
|
|
|
) + parent::configureVariables(); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Override to assemble the tasks |
83
|
|
|
* |
84
|
|
|
* @return void |
85
|
|
|
*/ |
86
|
|
|
public function assemble() |
87
|
|
|
{ |
88
|
|
|
$this->callback( |
89
|
|
|
function () { |
90
|
|
|
$fix = $this->get('fix'); |
91
|
|
|
$fixes = ($fix === true) ? $this->fixes : (array) $fix; |
92
|
|
|
$checks = $this->get('check') ?: $this->checks; |
93
|
|
|
foreach ($checks as $check) { |
94
|
|
|
$this->doCheck($check, in_array($check, $fixes, true)); |
95
|
|
|
} |
96
|
|
|
} |
97
|
|
|
); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Run the checks |
102
|
|
|
* |
103
|
|
|
* @param string $check The check to execute |
104
|
|
|
* @param boolean $fix Whether to fix found problems |
105
|
|
|
* @param array $packageNames Package names to filter this one |
106
|
|
|
* (for recursive calls only) |
107
|
|
|
* |
108
|
|
|
* @return void |
109
|
|
|
*/ |
110
|
|
|
public function doCheck($check, $fix, array $packageNames = array()) |
111
|
|
|
{ |
112
|
|
|
$packages = $this->getPackages(false); |
113
|
|
|
$errors = 0; |
114
|
|
|
if (!$packageNames) { |
|
|
|
|
115
|
|
|
$this->console->output($check, false); |
116
|
|
|
$this->console->indent(); |
117
|
|
|
} |
118
|
|
|
$rerunForPackages = array(); |
119
|
|
|
foreach ($packages as $package) { |
120
|
|
|
if ($packageNames && !in_array($package->name, $packageNames, true)) { |
|
|
|
|
121
|
|
|
continue; |
122
|
|
|
} |
123
|
|
|
if (is_string($message = $this->{'check' . $check}($package))) { |
124
|
|
View Code Duplication |
if (!$packageNames && !$errors) { |
|
|
|
|
125
|
|
|
$this->console->output( |
126
|
|
|
str_repeat(chr(8), strlen($check)) |
127
|
|
|
. '<fg=red;bg=black>' . $check . '</>' |
128
|
|
|
); |
129
|
|
|
} |
130
|
|
|
$message = sprintf($message, "package <comment>$package->name</>"); |
131
|
|
|
$this->console->output(ucfirst($message)); |
132
|
|
|
$errors++; |
133
|
|
|
if ($fix) { |
134
|
|
|
$this->dontCheckCurrentPackageAgain = false; |
135
|
|
|
$this->console->indent(); |
136
|
|
|
$this->{'fix' . $check}($package); |
137
|
|
|
$this->console->outdent(); |
138
|
|
|
if (!$this->dontCheckCurrentPackageAgain) { |
139
|
|
|
$rerunForPackages[] = $package->name; |
140
|
|
|
} |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
$this->pushPackages(); |
144
|
|
|
if ($this->composerUpdateRequired) { |
145
|
|
|
$this->composerUpdateRequired = false; |
146
|
|
|
$this->doComposerUpdate(); |
147
|
|
|
$this->doCheck($check, $fix); |
148
|
|
|
return; |
149
|
|
|
} |
150
|
|
|
} |
151
|
|
|
if ($rerunForPackages) { |
|
|
|
|
152
|
|
|
$this->doCheck($check, $fix, $rerunForPackages); |
153
|
|
|
} |
154
|
|
View Code Duplication |
if (!$packageNames) { |
|
|
|
|
155
|
|
|
if (!$errors) { |
156
|
|
|
$this->console->output( |
157
|
|
|
str_repeat(chr(8), strlen($check)) |
158
|
|
|
. '<fg=green;bg=black>' . $check . '</>' |
159
|
|
|
); |
160
|
|
|
} |
161
|
|
|
$this->console->outdent(); |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Check for unstaged changes |
167
|
|
|
* |
168
|
|
|
* @param object $package The package |
169
|
|
|
* |
170
|
|
|
* @return null|string message string on problems, null otherwise |
171
|
|
|
*/ |
172
|
|
|
protected function checkUnstagedChanges($package) |
173
|
|
|
{ |
174
|
|
|
if ($package->git) { |
175
|
|
|
$status = $this->git('status', $package->path, array('porcelain' => true)); |
176
|
|
|
if (trim($status)) { |
177
|
|
|
return '%s has uncommited changes'; |
178
|
|
|
} |
179
|
|
|
} |
180
|
|
|
return null; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Fix unstaged changes |
185
|
|
|
* |
186
|
|
|
* @param object $package The package |
187
|
|
|
* |
188
|
|
|
* @return void |
189
|
|
|
*/ |
190
|
|
|
protected function fixUnstagedChanges($package) |
191
|
|
|
{ |
192
|
|
|
$fix = $this->selectFixes( |
193
|
|
|
array( |
194
|
|
|
1 => 'Show diff (and ask again)', |
195
|
|
|
2 => 'Withdraw changes', |
196
|
|
|
3 => 'Stash changes', |
197
|
|
|
) |
198
|
|
|
); |
199
|
|
|
switch ($fix) { |
200
|
|
|
case 1: |
201
|
|
|
$this->git('add', $package->path, array('N' => true, 'A' => true)); |
202
|
|
|
$this->console->output(''); |
203
|
|
|
$this->git('diff', $package->path, 'HEAD', array('tty' => true)); |
204
|
|
|
$this->console->output(''); |
205
|
|
|
$this->fixUnstagedChanges($package); |
206
|
|
|
break; |
207
|
|
|
case 2: |
208
|
|
|
$this->git('reset', $package->path, array('hard' => true)); |
209
|
|
|
$this->git('clean', $package->path, array('i' => true, 'd' => true), array('tty' => true)); |
210
|
|
|
break; |
211
|
|
|
case 3: |
212
|
|
|
$this->git('reset', $package->path); |
213
|
|
|
$args = 'save -u'; |
214
|
|
|
if ($message = $this->answer('Message for stash:')) { |
215
|
|
|
$args .= ' ' . escapeshellarg($message); |
216
|
|
|
} |
217
|
|
|
$this->git('stash', $package->path, $args); |
218
|
|
|
break; |
219
|
|
|
} |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* Check if package is ahead and/or behind remote tracking branch |
224
|
|
|
* |
225
|
|
|
* @param object $package The package |
226
|
|
|
* |
227
|
|
|
* @return null|string message string on problems, null otherwise |
228
|
|
|
*/ |
229
|
|
|
protected function checkRemoteSynchronicity($package) |
230
|
|
|
{ |
231
|
|
|
if ($package->git) { |
232
|
|
|
$status = $this->git('status', $package->path, '--branch --porcelain -u no'); |
233
|
|
|
list($branchInfo) = explode("\n", $status, 2); |
234
|
|
|
preg_match('/ \[(ahead|behind) [0-9]+(?:, (ahead|behind) [0-9]+)?\]$/', $branchInfo, $matches); |
235
|
|
|
array_shift($matches); |
236
|
|
|
$package->ahead = in_array('ahead', $matches, true); |
237
|
|
|
$package->behind = in_array('behind', $matches, true); |
238
|
|
|
if ($package->ahead && $package->behind) { |
239
|
|
|
$type = 'has diverged from'; |
240
|
|
|
} elseif ($package->ahead) { |
241
|
|
|
$type = 'is ahead of'; |
242
|
|
|
} elseif ($package->behind) { |
243
|
|
|
$type = 'is behind'; |
244
|
|
|
} else { |
245
|
|
|
return null; |
246
|
|
|
} |
247
|
|
|
return "%s $type remote tracking branch"; |
248
|
|
|
} |
249
|
|
|
return null; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Push and/or pull or show the differences |
254
|
|
|
* |
255
|
|
|
* @param object $package The package |
256
|
|
|
* |
257
|
|
|
* @return void |
258
|
|
|
*/ |
259
|
|
|
protected function fixRemoteSynchronicity($package) |
260
|
|
|
{ |
261
|
|
|
$commands = array(); |
262
|
|
|
if ($package->behind) { |
263
|
|
|
$commands[] = 'pull'; |
264
|
|
|
} |
265
|
|
|
if ($package->ahead) { |
266
|
|
|
$commands[] = 'push'; |
267
|
|
|
} |
268
|
|
|
$fixes = array( |
269
|
|
|
1 => 'Show incoming/outgoing commits (and ask again)', |
270
|
|
|
2 => ucfirst(implode(' and ', $commands)), |
271
|
|
|
); |
272
|
|
|
if (count($commands) > 1 && $package->branch !== 'master') { |
273
|
|
|
$fixes[3] = 'Push with <comment>--force</comment>'; |
274
|
|
|
} |
275
|
|
|
switch ($this->selectFixes($fixes)) { |
276
|
|
|
case 1: |
277
|
|
|
$this->gitRevDiff($package, '@\{u\}', 'Remote', 'Local'); |
278
|
|
|
$this->fixRemoteSynchronicity($package); |
279
|
|
|
break; |
280
|
|
|
case 3: |
|
|
|
|
281
|
|
|
$commands = array('push'); |
282
|
|
|
$options = '--force'; |
283
|
|
|
case 2: |
284
|
|
|
foreach ($commands as $command) { |
285
|
|
|
$pck = "<comment>{$package->name}</comment>"; |
286
|
|
|
$this->console->output($msg = ucfirst($command) . "ing $pck...", false); |
287
|
|
|
$this->git($command, $package->path, isset($options) ? $options : null); |
288
|
|
|
$this->console->output( |
289
|
|
|
str_repeat(chr(8), strlen(strip_tags($msg))) |
290
|
|
|
. "<fg=green>Sucessfully {$command}ed $pck</>" |
291
|
|
|
); |
292
|
|
|
} |
293
|
|
|
break; |
294
|
|
|
} |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* Checks for packages that require the package in another branch than the |
299
|
|
|
* current - or for packages that require the package in a version when |
300
|
|
|
* the package is checked out at a branch |
301
|
|
|
* |
302
|
|
|
* Further requirements checks are left to composer |
303
|
|
|
* |
304
|
|
|
* @param object $package The package |
305
|
|
|
* |
306
|
|
|
* @return null|string message string on problems, null otherwise |
307
|
|
|
*/ |
308
|
|
|
protected function checkRequirementsMatch($package) |
309
|
|
|
{ |
310
|
|
|
if ($package->git && !$package->isRoot) { |
311
|
|
|
$package->requiredBranch = null; |
312
|
|
|
$package->unsatisfiedDependentPackages = array(); |
313
|
|
|
$package->invalidRequirements = false; |
314
|
|
|
$dependentPackages = []; |
315
|
|
|
foreach ($this->get('composer.packages') as $dependentPackage) { |
316
|
|
|
if (!isset($dependentPackage->requiresUpToDate)) { |
317
|
|
|
$this->reloadRequires($dependentPackage); |
|
|
|
|
318
|
|
|
$dependentPackage->requiresUpToDate = true; |
319
|
|
|
} |
320
|
|
|
if (array_key_exists($package->name, $dependentPackage->requires)) { |
321
|
|
|
if (substr($dependentPackage->requires[$package->name], 0, 4) === 'dev-') { |
322
|
|
|
$dependentPackages[] = $dependentPackage->name; |
323
|
|
|
$requiredBranch = substr($dependentPackage->requires[$package->name], 4); |
324
|
|
|
if (strpos($requiredBranch, '#')) { |
325
|
|
|
$otherHash = isset($hash) ? $hash : null; |
326
|
|
|
list($requiredBranch, $hash) = explode('#', $requiredBranch); |
327
|
|
|
if ($otherHash && $otherHash !== $hash) { |
328
|
|
|
return '<error>Two or more packages require %s in different commits</error>'; |
329
|
|
|
} |
330
|
|
|
} |
331
|
|
|
if ($package->requiredBranch && $package->requiredBranch !== $requiredBranch) { |
332
|
|
|
$package->invalidRequirements = true; |
333
|
|
|
return '<error>' . array_pop($dependentPackages) |
334
|
|
|
. ' and ' . array_pop($dependentPackages) |
335
|
|
|
. ' require %s in different branches</error>'; |
336
|
|
|
} |
337
|
|
|
$package->requiredBranch = $requiredBranch; |
338
|
|
|
if ($requiredBranch !== $package->branch) { |
339
|
|
|
$package->unsatisfiedDependentPackages[$package->name] = $dependentPackage; |
340
|
|
|
} |
341
|
|
|
} elseif ($package->branch) { |
342
|
|
|
$package->unsatisfiedDependentPackages[$package->name] = $dependentPackage; |
343
|
|
|
} |
344
|
|
|
} |
345
|
|
|
} |
346
|
|
|
$constraint = $package->tag ?: 'dev-' . $package->branch; |
347
|
|
|
if ($package->requiredBranch && $package->requiredBranch !== $package->branch) { |
348
|
|
|
return "%s is at <comment>$constraint</comment> but is required at <comment>dev-{$package->requiredBranch}</comment>"; |
349
|
|
|
} |
350
|
|
|
if (isset($hash) && substr($package->source->reference, 0, strlen($hash)) !== $hash) { |
351
|
|
|
return "%s is at <comment>{$constraint}#{$package->source->reference}</comment> but is required at <comment>dev-{$package->requiredBranch}#{$hash}</comment>"; |
352
|
|
|
} |
353
|
|
|
} |
354
|
|
|
return null; |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
/** |
358
|
|
|
* Checkout package at required branch or make dependent packages require the |
359
|
|
|
* current branch of the package. |
360
|
|
|
* |
361
|
|
|
* @param object $package The package |
362
|
|
|
* |
363
|
|
|
* @return void |
364
|
|
|
*/ |
365
|
|
|
protected function fixRequirementsMatch($package) |
366
|
|
|
{ |
367
|
|
|
if ($package->invalidRequirements) { |
368
|
|
|
$this->doExit('Can not fix that', 1); |
369
|
|
|
} |
370
|
|
|
$currentConstraint = $package->tag ?: 'dev-' . $package->branch; |
371
|
|
|
$requiredConstraint = 'dev-' . $package->requiredBranch; |
372
|
|
|
if ($package->requiredBranch) { |
373
|
|
|
$actions = array( |
374
|
|
|
1 => "Show divergent commits between <comment>$currentConstraint</comment> and <comment>$requiredConstraint</comment> (and ask again)", |
375
|
|
|
2 => "Checkout package at <comment>$requiredConstraint</comment>" |
376
|
|
|
); |
377
|
|
|
} else { |
378
|
|
|
$actions = array(); |
379
|
|
|
} |
380
|
|
|
if ($count = count($package->unsatisfiedDependentPackages)) { |
381
|
|
|
$actions[3] = "Make "; |
382
|
|
|
$git = true; |
383
|
|
|
foreach ($package->unsatisfiedDependentPackages as $i => $requirePackage) { |
384
|
|
|
$git &= $requirePackage->git; |
385
|
|
|
if ($i === $count - 1 && $i > 0) { |
386
|
|
|
$actions[3] .= 'and '; |
387
|
|
|
} |
388
|
|
|
$actions[3] .= "<comment>{$requirePackage->name}</comment> "; |
389
|
|
|
} |
390
|
|
|
$actions[3] .= "require <comment>{$currentConstraint}</comment>"; |
391
|
|
|
if (!$git) { |
392
|
|
|
unset($actions[3]); |
393
|
|
|
} |
394
|
|
|
} |
395
|
|
|
switch ($this->selectFixes($actions)) { |
396
|
|
|
case 1: |
397
|
|
|
$this->gitRevDiff($package, $package->requiredBranch, $requiredConstraint, $currentConstraint); |
398
|
|
|
$this->fixRequirementsMatch($package); |
399
|
|
|
break; |
400
|
|
|
case 2: |
401
|
|
|
$this->checkoutPackage($package, $package->requiredBranch); |
402
|
|
|
$this->reloadRequires($package); |
|
|
|
|
403
|
|
|
break; |
404
|
|
|
case 3: |
405
|
|
|
foreach ($package->unsatisfiedDependentPackages as $dependentPackage) { |
406
|
|
|
$this->rewriteRequirement($dependentPackage, $package->name, $currentConstraint); |
407
|
|
|
} |
408
|
|
|
break; |
409
|
|
|
} |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
/** |
413
|
|
|
* Check if package is on another branch/tag or another commit than locked |
414
|
|
|
* |
415
|
|
|
* @param object $package The package |
416
|
|
|
* |
417
|
|
|
* @return null|string message string on problems, null otherwise |
418
|
|
|
*/ |
419
|
|
|
protected function checkDivergeFromLock($package) |
420
|
|
|
{ |
421
|
|
|
if ($package->git && !$package->isRoot) { |
422
|
|
|
$remote = false; |
423
|
|
|
do { |
424
|
|
|
$reference = ($remote ? 'origin/' : '') . $package->source->reference; |
425
|
|
|
try { |
426
|
|
|
$rawCounts = $this->git('rev-list', $package->path, "--count --left-right --cherry-pick {$reference}..."); |
427
|
|
|
break; |
428
|
|
|
} catch (Exception\ProcessFailedException $e) { |
429
|
|
|
if ($remote) { |
430
|
|
|
return "The locked reference {$package->source->reference} in %s is not available"; |
431
|
|
|
} |
432
|
|
|
$remote = true; |
433
|
|
|
} |
434
|
|
|
} while ($remote); |
435
|
|
|
$counts = explode("\t", $rawCounts); |
436
|
|
|
if ($counts[0] || $counts[1]) { |
437
|
|
|
$num = $counts[0] ?: $counts[1]; |
438
|
|
|
$type = $counts[0] ? 'behind</>' : 'ahead</> of'; |
439
|
|
|
return '%s is <comment>' . $num . ' commit' . ($num > 1 ? 's ' : ' ') |
440
|
|
|
. $type . ' locked commit <comment>' |
441
|
|
|
. substr($package->source->reference, 0, 7) . '</>'; |
442
|
|
|
} |
443
|
|
|
} |
444
|
|
|
return null; |
445
|
|
|
} |
446
|
|
|
|
447
|
|
|
/** |
448
|
|
|
* Run composer update or checkout the package at locked state |
449
|
|
|
* |
450
|
|
|
* @param object $package The package |
451
|
|
|
* |
452
|
|
|
* @return void |
453
|
|
|
*/ |
454
|
|
|
protected function fixDivergeFromLock($package) |
455
|
|
|
{ |
456
|
|
|
$fix = $this->selectFixes( |
457
|
|
|
array( |
458
|
|
|
1 => 'Show commits between locked and current commit (and ask again)', |
459
|
|
|
2 => 'Run <info>composer update</info> (you may loose local changes)', |
460
|
|
|
3 => 'Checkout package at locked commit <comment>' |
461
|
|
|
. substr($package->source->reference, 0, 7) |
462
|
|
|
. "</comment> (<comment>{$package->version}</comment>)", |
463
|
|
|
) |
464
|
|
|
); |
465
|
|
|
|
466
|
|
|
switch ($fix) { |
467
|
|
|
case 1: |
468
|
|
|
$this->gitRevDiff($package, $package->source->reference, 'Locked', 'Current'); |
469
|
|
|
$this->fixDivergeFromLock($package); |
470
|
|
|
break; |
471
|
|
|
case 2: |
472
|
|
|
$this->composerUpdateRequired = true; |
473
|
|
|
break; |
474
|
|
|
case 3: |
475
|
|
|
$this->git('checkout', $package->path, $package->source->reference); |
476
|
|
|
$this->reloadRequires($package); |
|
|
|
|
477
|
|
|
break; |
478
|
|
|
} |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
/** |
482
|
|
|
* Check if composer lock is up to date |
483
|
|
|
* |
484
|
|
|
* @param object $package The package |
485
|
|
|
* |
486
|
|
|
* @return null|string message string on problems, null otherwise |
487
|
|
|
*/ |
488
|
|
|
protected function checkComposerLockActuality($package) |
489
|
|
|
{ |
490
|
|
|
if ($package->isRoot) { |
491
|
|
|
$lock = json_decode(file_get_contents('composer.lock')); |
492
|
|
|
if (md5_file('composer.json') !== $lock->{'hash'}) { |
493
|
|
|
return 'The lock file is not up to date with the latest changes in root composer.json'; |
494
|
|
|
} |
495
|
|
|
} |
496
|
|
|
return null; |
497
|
|
|
} |
498
|
|
|
|
499
|
|
|
/** |
500
|
|
|
* Run composer update (--lock) |
501
|
|
|
* |
502
|
|
|
* @param object $package The package |
503
|
|
|
* |
504
|
|
|
* @return void |
505
|
|
|
*/ |
506
|
|
|
protected function fixComposerLockActuality($package) |
|
|
|
|
507
|
|
|
{ |
508
|
|
|
$fix = $this->selectFixes( |
509
|
|
|
array( |
510
|
|
|
1 => 'Run <info>composer update</info> (you may loose local changes)', |
511
|
|
|
) |
512
|
|
|
); |
513
|
|
|
if ($fix === 1) { |
514
|
|
|
$this->composerUpdateRequired = true; |
515
|
|
|
} |
516
|
|
|
} |
517
|
|
|
|
518
|
|
|
/** |
519
|
|
|
* Select from the available fixes |
520
|
|
|
* |
521
|
|
|
* @param array $fixes The fixes |
522
|
|
|
* |
523
|
|
|
* @return int|null |
524
|
|
|
*/ |
525
|
|
|
protected function selectFixes($fixes) |
526
|
|
|
{ |
527
|
|
|
$this->console->outdent(); |
528
|
|
|
$fixes['n'] = 'Nothing for now, ask again later'; |
529
|
|
|
$fixes['i'] = 'Ignore'; |
530
|
|
|
$fixes['x'] = 'Exit'; |
531
|
|
|
$result = $this->choose('What do you want to do?', $fixes); |
532
|
|
|
$this->console->indent(); |
533
|
|
|
if ($result == 'i' || $result == 'n') { |
534
|
|
|
$this->dontCheckCurrentPackageAgain = ($result === 'i'); |
535
|
|
|
return null; |
536
|
|
|
} |
537
|
|
|
if ($result == 'x') { |
538
|
|
|
$this->doExit(); |
539
|
|
|
} |
540
|
|
|
return (int) $result; |
541
|
|
|
} |
542
|
|
|
|
543
|
|
|
/** |
544
|
|
|
* Show commits that are not in the HEAD but in ref and vice versa |
545
|
|
|
* |
546
|
|
|
* @param object $package The package |
547
|
|
|
* @param string $ref The ref name |
548
|
|
|
* @param string $leftTitle The title of the ref name |
549
|
|
|
* @param string $rightTitle The title of HEAD |
550
|
|
|
* |
551
|
|
|
* @return void |
552
|
|
|
*/ |
553
|
|
|
protected function gitRevDiff($package, $ref, $leftTitle, $rightTitle) |
554
|
|
|
{ |
555
|
|
|
for ($i = 0; $i <= 1; $i++) { |
556
|
|
|
$side = $i ? 'left' : 'right'; |
557
|
|
|
$otherSide = $i ? 'right' : 'left'; |
558
|
|
|
$args = "--$side-only --cherry-pick --pretty=format:'%C(yellow)%h %Cgreen%cd %an%Creset%n %s' --abbrev-commit --date=local "; |
559
|
|
|
$args .= $ref . '...'; |
560
|
|
|
$log = $this->git('log', $package->path, $args, array('shy' => true)); |
561
|
|
|
if ($log) { |
562
|
|
|
$this->console->output(''); |
563
|
|
|
|
564
|
|
|
$title = "<info>{${$side . 'Title'}}</info> > <info>{${$otherSide . 'Title'}}</info>"; |
565
|
|
|
$this->output($title); |
566
|
|
|
$this->console->output(str_repeat('-', strlen(strip_tags($title)))); |
567
|
|
|
|
568
|
|
|
$this->console->output($log); |
569
|
|
|
|
570
|
|
|
$this->console->output(''); |
571
|
|
|
} |
572
|
|
|
} |
573
|
|
|
} |
574
|
|
|
} |
575
|
|
|
?> |
576
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.