Skip to content

Commit 87b2d6b

Browse files
committed
Use new vcs* functions in load(), usage(), update cli args, pass loaded data to diff()
1 parent b505628 commit 87b2d6b

File tree

1 file changed

+71
-101
lines changed

1 file changed

+71
-101
lines changed

composer-lock-diff

Lines changed: 71 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
$opts = parseOpts();
55

66
$changes = array();
7+
$data_from = load($opts['from'], $opts['path'], $opts['vcs'], '');
8+
$data_to = load($opts['to'], $opts['path'], $opts['vcs'], 'composer.lock');
79

810
if (! $opts['only-dev']) {
9-
$changes['changes'] = diff('packages', $opts['from'], $opts['to'], $opts['path'], $opts['vcs']);
11+
$changes['changes'] = diff('packages', $data_from, $data_to);
1012
}
1113

1214
if (! $opts['only-prod']) {
13-
$changes['changes-dev'] = diff('packages-dev', $opts['from'], $opts['to'], $opts['path'], $opts['vcs']);
15+
$changes['changes-dev'] = diff('packages-dev', $data_from, $data_to);
1416
}
1517

1618
if ($opts['json']) {
@@ -31,28 +33,24 @@ if ($opts['md']) {
3133
));
3234
}
3335

34-
$table_titles = [
36+
$table_titles = array(
3537
'changes' => 'Production Changes',
3638
'changes-dev' => 'Dev Changes',
37-
];
39+
);
3840

3941
foreach($changes as $k => $diff) {
4042
print tableize($table_titles[$k], $diff, $table_opts);
4143
}
4244

43-
function diff($key, $from, $to, $base_path, $vcs) {
45+
function diff($key, $data_from, $data_to) {
4446

4547
$pkgs = array();
4648

47-
$data = load($from, $base_path, $vcs);
48-
49-
foreach($data->$key as $pkg) {
49+
foreach($data_from->$key as $pkg) {
5050
$pkgs[$pkg->name] = array(version($pkg), 'REMOVED', '');
5151
}
5252

53-
$data = load($to, $base_path, $vcs);
54-
55-
foreach($data->$key as $pkg) {
53+
foreach($data_to->$key as $pkg) {
5654
if (! array_key_exists($pkg->name, $pkgs)) {
5755
$pkgs[$pkg->name] = array('NEW', version($pkg), '');
5856
continue;
@@ -150,68 +148,72 @@ function urlFormatterMd($url, $text) {
150148
return sprintf('[%s](%s)', $text, $url);
151149
}
152150

153-
function load($fileish, $base_path = '', $vcs) {
154-
$orig = $fileish;
151+
// $fileish is what the user actually requested.
152+
// $default_fileish is what it should be if $fileish is empty
153+
function load($fileish, $base_path, $force_vcs, $default_fileish) {
154+
$loaders = ($force_vcs || (empty($fileish) && empty($default_fileish))) ? array() : array('loadFile');
155155

156-
if (empty($base_path)) {
157-
$base_path = '.' . DIRECTORY_SEPARATOR;
158-
} else {
159-
$base_path = rtrim($base_path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
160-
}
156+
$vcses = $force_vcs ? array($force_vcs) : getVcses();
157+
$errors = array();
161158

162-
if (empty($fileish)) {
163-
$fileish = $base_path . 'composer.lock';
159+
foreach($vcses as $vcs) {
160+
$detector = 'vcsDetect' . ucfirst($vcs);
161+
if($vcs != $force_vcs && function_exists($detector)) {
162+
list($available, $err) = call_user_func($detector, $fileish, $base_path, $default_fileish);
163+
if ($err) {
164+
$errors[] = $err;
165+
continue;
166+
}
167+
if (!$available) continue;
168+
}
169+
$loaders[] = 'vcsLoad' . ucfirst($vcs);
164170
}
165171

166-
if (strpos('svn://', $fileish) !== 0 && isUrl($fileish)) {
167-
if (! in_array(parse_url($fileish, PHP_URL_SCHEME), stream_get_wrappers())) {
168-
error_log("Error: no stream wrapper to open '$fileish'");
169-
exit(1);
172+
if (empty($loaders)) {
173+
error_log(implode("\n", $errors));
174+
if ($force_vcs) {
175+
error_log("Requested vcs '$force_vcs' not installed or otherwise unavailable");
176+
} else {
177+
error_log("No loaders were found; perhaps your vcs cli tools are not installed, not in PATH, or otherwise unavailable");
170178
}
171-
172-
return mustDecodeJson(file_get_contents($fileish), $fileish);
179+
exit(1);
173180
}
174181

175-
if (strpos('svn://', $fileish) !== 0 && file_exists($fileish)) {
176-
return mustDecodeJson(file_get_contents($fileish), $fileish);
182+
$errors = array();
183+
foreach($loaders as $loader) {
184+
list($result, $err) = call_user_func_array($loader, array($fileish, $base_path, $default_fileish));
185+
if (empty($err)) {
186+
return $result;
187+
}
188+
$errors[] = "Failed to find '$fileish' with '$loader'; $err";
177189
}
178190

179-
//try to find vcs revision
180-
if ($vcs == 'git'){
181-
if (strpos($orig, ':') === false) {
182-
$fileish .= ':' . $base_path . 'composer.lock';
183-
}
191+
foreach($errors as $e) {
192+
error_log($e);
193+
}
184194

185-
$lines = array();
186-
exec('git show '. escapeshellarg($fileish), $lines, $exit);
195+
exit(1);
196+
}
187197

188-
if ($exit !== 0) {
189-
error_log("Error: cannot open $orig or find it in git as $fileish");
190-
exit(1);
198+
function loadFile($fileish, $base_path, $default_fileish) {
199+
if (empty($fileish)) {
200+
$fileish = $default_fileish;
201+
if (!empty($base_path)) {
202+
$fileish = joinPath($base_path, $fileish);
191203
}
192-
193-
return mustDecodeJson(implode("\n", $lines), $fileish);
194204
}
195205

196-
elseif ($vcs == 'svn'){
197-
# explaination:
198-
# http:// https:// svn:// => absolute url of repository (http/https already handled before)
199-
# ^ => relative url from current workspace repository
200-
# @ => repository url with version
201-
if (preg_match('#^\^|^svn://|@#', $orig) === 0) {
202-
$fileish = $base_path . 'composer.lock@'.$fileish;
203-
}
204-
exec('svn cat '. escapeshellarg($fileish), $lines, $exit);
206+
// Does it look like a url that we can handle with stream wrappers?
207+
if (isUrl($fileish) && in_array(parse_url($fileish, PHP_URL_SCHEME), stream_get_wrappers())) {
208+
return array(mustDecodeJson(file_get_contents($fileish), $fileish), false);
209+
}
205210

206-
if ($exit !== 0) {
207-
error_log("Error: cannot open $orig or find it in svn as $fileish");
208-
exit(1);
209-
}
210-
return mustDecodeJson(implode("\n", $lines), $fileish);
211+
// Is it a file in the local filesystem?
212+
if (file_exists($fileish)) {
213+
return array(mustDecodeJson(file_get_contents($fileish), $fileish), false);
211214
}
212215

213-
error_log("Error: unhandled VCS $vcs");
214-
exit(1);
216+
return array(false, "Candidate '$fileish' does not look loadable from the fs or php stream wrappers");
215217
}
216218

217219
function isUrl($string) {
@@ -310,7 +312,7 @@ function getVcses() {
310312

311313
function vcsDetectGit($_fileish) {
312314
// Is there a git executable?
313-
exec('git --version', null, $exit);
315+
exec('sh -c "git --version" > /dev/null 2>&1', $_out, $exit);
314316
if ($exit !== 0) return array(false, "'git --version' exited with non-zero code '$exit'");
315317

316318
// Does this look like a git repo?
@@ -341,7 +343,7 @@ function vcsLoadGit($fileish, $base_path, $_default_fileish) {
341343

342344
function vcsDetectSvn($fileish, $base_path, $default_fileish) {
343345
// Is there a git executable?
344-
exec('svn --version', null, $exit);
346+
exec('sh -c "svn --version" > /dev/null 2>&1', $_out, $exit);
345347
if ($exit !== 0) return array(false, "'svn --version' exited with non-zero code '$exit'");
346348

347349
if (strpos('svn://', $fileish) === 0) {
@@ -428,13 +430,15 @@ function parseOpts() {
428430
usage();
429431
}
430432

431-
$path = array_key_exists('path', $given) ? $given['path'] : '';
432-
$vcs = array_key_exists('vcs', $given) ? strtolower($given['vcs']) : vcsDetect($path);
433-
$defaultFrom = $vcs == 'svn' ? "BASE" : "HEAD";
433+
$vcs = array_key_exists('vcs', $given) ? $given['vcs'] : '';
434+
if ($vcs && !function_exists('vcsLoad' . ucfirst($vcs))) {
435+
error_log("Unsupported vcs '$vcs'\n");
436+
usage();
437+
}
434438

435439
return array(
436-
'path' => $path,
437-
'from' => array_key_exists('from', $given) ? $given['from'] : $defaultFrom,
440+
'path' => array_key_exists('path', $given) ? $given['path'] : '',
441+
'from' => array_key_exists('from', $given) ? $given['from'] : '',
438442
'to' => array_key_exists('to', $given) ? $given['to'] : '',
439443
'md' => array_key_exists('md', $given),
440444
'json' => array_key_exists('json', $given),
@@ -446,59 +450,25 @@ function parseOpts() {
446450
);
447451
}
448452

449-
function dirnameSafe($path) {
450-
$parent = dirname($path);
451-
return ($parent != $path && !empty($parent)) ? $parent : false;
452-
}
453-
454-
function joinPath(/* path parts */) {
455-
return implode(DIRECTORY_SEPARATOR, array_map(function($part) {
456-
return trim($part, DIRECTORY_SEPARATOR);
457-
}, func_get_args()));
458-
}
459-
460-
function vcsDetect($base_path) {
461-
if (empty($base_path)) {
462-
$base_path = '.';
463-
}
464-
465-
// > Trailing delimiters, such as \ and /, are also removed
466-
// > returns false on failure, e.g. if the file does not exist.
467-
$base_path = realpath($base_path);
468-
if ($base_path === false) return 'unknown';
469-
470-
$tries = 10;
471-
do {
472-
if(is_dir(joinPath($base_path, '.git'))) {
473-
return 'git';
474-
} elseif(is_dir(joinPath($base_path, '.svn'))) {
475-
return 'svn';
476-
}
477-
478-
$base_path = dirnameSafe($base_path);
479-
} while($base_path !== false && --$tries > 0);
480-
481-
return 'unknown';
482-
}
483-
484453
function usage() {
454+
$vcses = implode(', ', getVcses());
485455
print <<<EOF
486456
Usage: composer-lock-diff [options]
487457
488458
Options:
489459
-h --help Print this message
490460
--path, -p Base to with which to prefix paths. Default "./"
491461
E.g. `-p app` would look for HEAD:app/composer.lock and app/composer.lock
492-
--from The file, git ref, or git ref with filename to compare from
493-
(git : HEAD:composer.lock, svn: composer.lock@BASE)
462+
--from The file, git ref, or git ref with filename to compare from
463+
(git: HEAD:composer.lock, svn: composer.lock@BASE)
494464
--to The file, git ref, or git ref with filename to compare to (composer.lock)
495465
--json Format output as JSON
496466
--pretty Pretty print JSON output (PHP >= 5.4.0)
497467
--md Use markdown instead of plain text
498468
--no-links Don't include Compare links in plain text or any links in markdown
499469
--only-prod Only include changes from `packages`
500470
--only-dev Only include changes from `packages-dev`
501-
--vcs Force vcs (git, svn, ...). Default auto-detect from path
471+
--vcs Force vcs ($vcses). Default: attempt to auto-detect
502472
503473
EOF;
504474

0 commit comments

Comments
 (0)