get_remote_url(): also honor url.*.pushInsteadOf

As a follow up to https://review.openstack.org/109851, we also need to
respect the "url.<base>.pushInsteadOf" setting like git remote show
did.

Change-Id: I6c4cb9e11dcc5f096af03b2b2356216365eaf111
This commit is contained in:
Anders Kaseorg 2015-03-01 00:00:06 -05:00
parent 80f7cd2c0a
commit ae4b4f2f90
2 changed files with 49 additions and 22 deletions

View File

@ -63,6 +63,7 @@ _has_color = None
_use_color = None _use_color = None
_orig_head = None _orig_head = None
_rewrites = None _rewrites = None
_rewrites_push = None
class colors: class colors:
@ -387,59 +388,78 @@ def add_remote(scheme, hostname, port, project, remote):
def populate_rewrites(): def populate_rewrites():
"""Populate the global _rewrites map based on the output of "git-config". """Populate the global _rewrites and _rewrites_push maps based on the
output of "git-config".
""" """
cmd = ['git', 'config', '--list'] cmd = ['git', 'config', '--list']
out = run_command_exc(CommandFailed, *cmd).strip() out = run_command_exc(CommandFailed, *cmd).strip()
global _rewrites global _rewrites, _rewrites_push
_rewrites = {} _rewrites = {}
_rewrites_push = {}
for entry in out.splitlines(): for entry in out.splitlines():
key, _, value = entry.partition('=') key, _, value = entry.partition('=')
key = key.lower() key = key.lower()
if key.startswith('url.') and key.endswith('.insteadof'): if key.startswith('url.') and key.endswith('.insteadof'):
rewrite = key[4:-10] rewrite = key[len('url.'):-len('.insteadof')]
if rewrite: if rewrite:
_rewrites[value] = rewrite _rewrites[value] = rewrite
elif key.startswith('url.') and key.endswith('.pushinsteadof'):
rewrite = key[len('url.'):-len('.pushinsteadof')]
if rewrite:
_rewrites_push[value] = rewrite
def alias_url(url): def alias_url(url, rewrite_push):
"""Expand a remote URL. Use the global map _rewrites to replace the """Expand a remote URL. Use the global map _rewrites to replace the
longest match with its equivalent. longest match with its equivalent. If rewrite_push is True, try
_rewrites_push before _rewrites.
""" """
if _rewrites is None: if _rewrites is None:
populate_rewrites() populate_rewrites()
longest = None if rewrite_push:
for alias in _rewrites: maps = [_rewrites_push, _rewrites]
if (url.startswith(alias) else:
and (longest is None or len(longest) < len(alias))): maps = [_rewrites]
longest = alias
for rewrites in maps:
# If Git finds a pushInsteadOf alias, it uses that even if
# there is a longer insteadOf alias.
longest = None
for alias in rewrites:
if (url.startswith(alias)
and (longest is None or len(longest) < len(alias))):
longest = alias
if longest:
return url.replace(longest, rewrites[longest])
if longest:
url = url.replace(longest, _rewrites[longest])
return url return url
def get_remote_url(remote): def get_remote_url(remote):
"""Retrieve the remote URL. Read the configuration to expand the URL of a """Retrieve the remote URL. Read the configuration to expand the URL of a
remote repository taking into account any "url.<base>.insteadOf" config remote repository taking into account any "url.<base>.insteadOf" or
setting. "url.<base>.pushInsteadOf" config setting.
TODO: Replace current code with "git ls-remote --get-url" when the TODO: Replace current code with something like "git ls-remote
continuous builders will support it. It requires the use of Git v1.7.5 --get-url" after Git grows a version of it that returns the push
or above. Beware that option "--get-url" of "git-ls-remote" is URL rather than the fetch URL.
supported since v1.7.5 (see https://github.com/git/git/commit/45781ad) but
was not properly documented until v1.7.12.2.
""" """
url = git_config_get_value('remote.%s' % remote, 'url', '') push_url = git_config_get_value('remote.%s' % remote, 'pushurl')
push_url = git_config_get_value('remote.%s' % remote, 'pushurl', url) if push_url is not None:
push_url = alias_url(push_url) # Git rewrites pushurl using insteadOf but not pushInsteadOf.
push_url = alias_url(push_url, False)
else:
url = git_config_get_value('remote.%s' % remote, 'url')
# Git rewrites url using pushInsteadOf or insteadOf.
push_url = alias_url(url, True)
if VERBOSE: if VERBOSE:
print("Found origin Push URL:", push_url) print("Found origin Push URL:", push_url)
return push_url return push_url

View File

@ -343,6 +343,13 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
'test_project_url') 'test_project_url')
self._run_git_review('-l', '-r', 'alias') self._run_git_review('-l', '-r', 'alias')
self._run_git('config', '--unset',
'url.%s.insteadof' % self.project_uri)
self._run_git('config', '--add',
'url.%s.pushinsteadof' % self.project_uri,
'test_project_url')
self._run_git_review('-l', '-r', 'alias')
class HttpGitReviewTestCase(tests.HttpMixin, GitReviewTestCase): class HttpGitReviewTestCase(tests.HttpMixin, GitReviewTestCase):
"""Class for the git-review tests over HTTP(S).""" """Class for the git-review tests over HTTP(S)."""