mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-08 07:52:39 +01:00
(stable) Promote 2020 Week 5
This commit is contained in:
commit
7291009551
1 changed files with 111 additions and 23 deletions
|
@ -554,27 +554,7 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "git ls-remote --get-url" is the appropriate plumbing to get the remote
|
return $this->getGitRemoteFetchURI($remote);
|
||||||
// URI. "git config remote.origin.url", on the other hand, may not be as
|
|
||||||
// accurate (for example, it does not take into account possible URL
|
|
||||||
// rewriting rules set by the user through "url.<base>.insteadOf"). However,
|
|
||||||
// the --get-url flag requires git 1.7.5.
|
|
||||||
$version = $this->getGitVersion();
|
|
||||||
if (version_compare($version, '1.7.5', '>=')) {
|
|
||||||
list($stdout) = $this->execxLocal('ls-remote --get-url %s', $remote);
|
|
||||||
} else {
|
|
||||||
list($stdout) = $this->execxLocal('config %s', "remote.{$remote}.url");
|
|
||||||
}
|
|
||||||
|
|
||||||
$uri = rtrim($stdout);
|
|
||||||
// ls-remote echos the remote name (ie 'origin') if no remote URI is found
|
|
||||||
// TODO: In 2.7.0 (circa 2016) git introduced `git remote get-url`
|
|
||||||
// with saner error handling.
|
|
||||||
if (!$uri || $uri === $remote) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $uri;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSourceControlPath() {
|
public function getSourceControlPath() {
|
||||||
|
@ -1583,10 +1563,118 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isPushableRemote($remote_name) {
|
public function isPushableRemote($remote_name) {
|
||||||
|
$uri = $this->getGitRemotePushURI($remote_name);
|
||||||
|
return ($uri !== null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getGitRemoteFetchURI($remote_name) {
|
||||||
|
return $this->getGitRemoteURI($remote_name, $for_push = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getGitRemotePushURI($remote_name) {
|
||||||
|
return $this->getGitRemoteURI($remote_name, $for_push = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getGitRemoteURI($remote_name, $for_push) {
|
||||||
|
$remote_uri = $this->loadGitRemoteURI($remote_name, $for_push);
|
||||||
|
|
||||||
|
if ($remote_uri !== null) {
|
||||||
|
$remote_uri = rtrim($remote_uri);
|
||||||
|
if (!strlen($remote_uri)) {
|
||||||
|
$remote_uri = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $remote_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadGitRemoteURI($remote_name, $for_push) {
|
||||||
|
// Try to identify the best URI for a given remote. This is complicated
|
||||||
|
// because remotes may have different "push" and "fetch" URIs, may
|
||||||
|
// rewrite URIs with "insteadOf" configuration, and different versions
|
||||||
|
// of Git support different URI resolution commands.
|
||||||
|
|
||||||
|
// Remotes may also have more than one URI of a given type, but we ignore
|
||||||
|
// those cases here.
|
||||||
|
|
||||||
|
// Start with "git remote get-url [--push]". This is the simplest and
|
||||||
|
// most accurate command, but was introduced most recently in Git's
|
||||||
|
// history.
|
||||||
|
|
||||||
|
$argv = array();
|
||||||
|
if ($for_push) {
|
||||||
|
$argv[] = '--push';
|
||||||
|
}
|
||||||
|
|
||||||
list($err, $stdout) = $this->execManualLocal(
|
list($err, $stdout) = $this->execManualLocal(
|
||||||
'remote get-url --push -- %s',
|
'remote get-url %Ls -- %s',
|
||||||
|
$argv,
|
||||||
$remote_name);
|
$remote_name);
|
||||||
return !$err;
|
if (!$err) {
|
||||||
|
return $stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See T13481. If "git remote get-url [--push]" failed, it might be because
|
||||||
|
// the remote does not exist, but it might also be because the version of
|
||||||
|
// Git is too old to support "git remote get-url", which was introduced
|
||||||
|
// in Git 2.7 (circa late 2015).
|
||||||
|
|
||||||
|
$git_version = $this->getGitVersion();
|
||||||
|
if (version_compare($git_version, '2.7', '>=')) {
|
||||||
|
// This version of Git should support "git remote get-url --push", but
|
||||||
|
// the command failed, so conclude this is not a valid remote and thus
|
||||||
|
// there is no remote URI.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we arrive here, we're in a version of Git which is too old to
|
||||||
|
// support "git remote get-url [--push]". We're going to fall back to
|
||||||
|
// older and less accurate mechanisms for figuring out the remote URI.
|
||||||
|
|
||||||
|
// The first mechanism we try is "git ls-remote --get-url". This exists
|
||||||
|
// in Git 1.7.5 or newer. It only gives us the fetch URI, so this result
|
||||||
|
// will be incorrect if a remote has different fetch and push URIs.
|
||||||
|
// However, this is very rare, and this result is almost always correct.
|
||||||
|
|
||||||
|
// Note that some old versions of Git do not parse "--" in this command
|
||||||
|
// properly. We omit it since it doesn't seem like there's anything
|
||||||
|
// dangerous an attacker can do even if they can choose a remote name to
|
||||||
|
// intentionally cause an argument misparse.
|
||||||
|
|
||||||
|
// This will cause the command to behave incorrectly for remotes with
|
||||||
|
// names which are also valid flags, like "--quiet".
|
||||||
|
|
||||||
|
list($err, $stdout) = $this->execManualLocal(
|
||||||
|
'ls-remote --get-url %s',
|
||||||
|
$remote_name);
|
||||||
|
if (!$err) {
|
||||||
|
// The "git ls-remote --get-url" command just echoes the remote name
|
||||||
|
// (like "origin") if no remote URI is found. Treat this like a failure.
|
||||||
|
$output_is_input = (rtrim($stdout) === $remote_name);
|
||||||
|
if (!$output_is_input) {
|
||||||
|
return $stdout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version_compare($git_version, '1.7.5', '>=')) {
|
||||||
|
// This version of Git should support "git ls-remote --get-url", but
|
||||||
|
// the command failed (or echoed the input), so conclude the remote
|
||||||
|
// really does not exist.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to the very old "git config -- remote.origin.url" command.
|
||||||
|
// This does not give us push URLs and does not resolve "insteadOf"
|
||||||
|
// aliases, but still works in the simplest (and most common) cases.
|
||||||
|
|
||||||
|
list($err, $stdout) = $this->execManualLocal(
|
||||||
|
'config -- %s',
|
||||||
|
sprintf('remote.%s.url', $remote_name));
|
||||||
|
if (!$err) {
|
||||||
|
return $stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue