Browse Source

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
tags/1.0.0
Anders Kaseorg 4 years ago
parent
commit
ae4b4f2f90
2 changed files with 50 additions and 23 deletions
  1. 43
    23
      git_review/cmd.py
  2. 7
    0
      git_review/tests/test_git_review.py

+ 43
- 23
git_review/cmd.py View File

@@ -63,6 +63,7 @@ _has_color = None
63 63
 _use_color = None
64 64
 _orig_head = None
65 65
 _rewrites = None
66
+_rewrites_push = None
66 67
 
67 68
 
68 69
 class colors:
@@ -387,59 +388,78 @@ def add_remote(scheme, hostname, port, project, remote):
387 388
 
388 389
 
389 390
 def populate_rewrites():
390
-    """Populate the global _rewrites map based on the output of "git-config".
391
+    """Populate the global _rewrites and _rewrites_push maps based on the
392
+    output of "git-config".
391 393
     """
392 394
 
393 395
     cmd = ['git', 'config', '--list']
394 396
     out = run_command_exc(CommandFailed, *cmd).strip()
395 397
 
396
-    global _rewrites
398
+    global _rewrites, _rewrites_push
397 399
     _rewrites = {}
400
+    _rewrites_push = {}
398 401
 
399 402
     for entry in out.splitlines():
400 403
         key, _, value = entry.partition('=')
401 404
         key = key.lower()
402 405
 
403 406
         if key.startswith('url.') and key.endswith('.insteadof'):
404
-            rewrite = key[4:-10]
407
+            rewrite = key[len('url.'):-len('.insteadof')]
405 408
             if rewrite:
406 409
                 _rewrites[value] = rewrite
410
+        elif key.startswith('url.') and key.endswith('.pushinsteadof'):
411
+            rewrite = key[len('url.'):-len('.pushinsteadof')]
412
+            if rewrite:
413
+                _rewrites_push[value] = rewrite
407 414
 
408 415
 
409
-def alias_url(url):
416
+def alias_url(url, rewrite_push):
410 417
     """Expand a remote URL. Use the global map _rewrites to replace the
411
-    longest match with its equivalent.
418
+    longest match with its equivalent. If rewrite_push is True, try
419
+    _rewrites_push before _rewrites.
412 420
     """
413 421
 
414 422
     if _rewrites is None:
415 423
         populate_rewrites()
416 424
 
417
-    longest = None
418
-    for alias in _rewrites:
419
-        if (url.startswith(alias)
420
-                and (longest is None or len(longest) < len(alias))):
421
-            longest = alias
425
+    if rewrite_push:
426
+        maps = [_rewrites_push, _rewrites]
427
+    else:
428
+        maps = [_rewrites]
429
+
430
+    for rewrites in maps:
431
+        # If Git finds a pushInsteadOf alias, it uses that even if
432
+        # there is a longer insteadOf alias.
433
+        longest = None
434
+        for alias in rewrites:
435
+            if (url.startswith(alias)
436
+                    and (longest is None or len(longest) < len(alias))):
437
+                longest = alias
438
+
439
+        if longest:
440
+            return url.replace(longest, rewrites[longest])
422 441
 
423
-    if longest:
424
-        url = url.replace(longest, _rewrites[longest])
425 442
     return url
426 443
 
427 444
 
428 445
 def get_remote_url(remote):
429 446
     """Retrieve the remote URL. Read the configuration to expand the URL of a
430
-    remote repository taking into account any "url.<base>.insteadOf" config
431
-    setting.
432
-
433
-    TODO: Replace current code with "git ls-remote --get-url" when the
434
-    continuous builders will support it. It requires the use of Git v1.7.5
435
-    or above. Beware that option "--get-url" of "git-ls-remote" is
436
-    supported since v1.7.5 (see https://github.com/git/git/commit/45781ad) but
437
-    was not properly documented until v1.7.12.2.
447
+    remote repository taking into account any "url.<base>.insteadOf" or
448
+    "url.<base>.pushInsteadOf" config setting.
449
+
450
+    TODO: Replace current code with something like "git ls-remote
451
+    --get-url" after Git grows a version of it that returns the push
452
+    URL rather than the fetch URL.
438 453
     """
439 454
 
440
-    url = git_config_get_value('remote.%s' % remote, 'url', '')
441
-    push_url = git_config_get_value('remote.%s' % remote, 'pushurl', url)
442
-    push_url = alias_url(push_url)
455
+    push_url = git_config_get_value('remote.%s' % remote, 'pushurl')
456
+    if push_url is not None:
457
+        # Git rewrites pushurl using insteadOf but not pushInsteadOf.
458
+        push_url = alias_url(push_url, False)
459
+    else:
460
+        url = git_config_get_value('remote.%s' % remote, 'url')
461
+        # Git rewrites url using pushInsteadOf or insteadOf.
462
+        push_url = alias_url(url, True)
443 463
     if VERBOSE:
444 464
         print("Found origin Push URL:", push_url)
445 465
     return push_url

+ 7
- 0
git_review/tests/test_git_review.py View File

@@ -343,6 +343,13 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
343 343
                       'test_project_url')
344 344
         self._run_git_review('-l', '-r', 'alias')
345 345
 
346
+        self._run_git('config', '--unset',
347
+                      'url.%s.insteadof' % self.project_uri)
348
+        self._run_git('config', '--add',
349
+                      'url.%s.pushinsteadof' % self.project_uri,
350
+                      'test_project_url')
351
+        self._run_git_review('-l', '-r', 'alias')
352
+
346 353
 
347 354
 class HttpGitReviewTestCase(tests.HttpMixin, GitReviewTestCase):
348 355
     """Class for the git-review tests over HTTP(S)."""

Loading…
Cancel
Save