Browse Source

Use git push-url instead of a second remote

Having a gerrit remote means that we fetch changes twice. It's also
not necessary since the push-url can be set on the origin remote. As
a first step, add a config option that changes the default for defaultremote
to origin and then reworks the logic to add the remote url to origin as a
push-url instead of creating a gerrit remote.

Since this will cause people with an existing gerrit remote to have a
push url added and the gerrit remote orpahned, a follow on commit will
come that will look for a gerrit remote and, if it exists, use it as the
source of url for the push-url and then delete the old remote.

Change-Id: Ief5d092a796516de9605b7df64e7b902c3b47351
tags/1.0.0
Cedric Brandily 4 years ago
parent
commit
44707a1e79
3 changed files with 147 additions and 78 deletions
  1. 60
    28
      git_review/cmd.py
  2. 11
    1
      git_review/tests/__init__.py
  3. 76
    49
      git_review/tests/test_git_review.py

+ 60
- 28
git_review/cmd.py View File

@@ -57,7 +57,7 @@ GLOBAL_CONFIG = "/etc/git-review/git-review.conf"
57 57
 USER_CONFIG = os.path.join(CONFIGDIR, "git-review.conf")
58 58
 DEFAULTS = dict(scheme='ssh', hostname=False, port=None, project=False,
59 59
                 branch='master', remote="gerrit", rebase="1",
60
-                track="0")
60
+                track="0", usepushurl="0")
61 61
 
62 62
 _branch_name = None
63 63
 _has_color = None
@@ -369,7 +369,7 @@ def make_remote_url(scheme, username, hostname, port, project):
369 369
         return "%s://%s@%s/%s" % (scheme, username, hostport, project)
370 370
 
371 371
 
372
-def add_remote(scheme, hostname, port, project, remote):
372
+def add_remote(scheme, hostname, port, project, remote, usepushurl):
373 373
     """Adds a gerrit remote."""
374 374
     asked_for_username = False
375 375
 
@@ -392,11 +392,15 @@ def add_remote(scheme, hostname, port, project, remote):
392 392
                                      "%s" % remote_url)
393 393
         asked_for_username = True
394 394
 
395
-    print("Creating a git remote called \"%s\" that maps to:" % remote)
395
+    if usepushurl:
396
+        cmd = "git remote set-url --push %s %s" % (remote, remote_url)
397
+        print("Adding a git push url to '%s' that maps to:" % remote)
398
+    else:
399
+        cmd = "git remote add -f %s %s" % (remote, remote_url)
400
+        print("Creating a git remote called '%s' that maps to:" % remote)
396 401
     print("\t%s" % remote_url)
397
-    cmd = "git remote add -f %s %s" % (remote, remote_url)
398
-    (status, remote_output) = run_command_status(cmd)
399 402
 
403
+    (status, remote_output) = run_command_status(cmd)
400 404
     if status != 0:
401 405
         raise CommandFailed(status, remote_output, cmd, {})
402 406
 
@@ -678,6 +682,7 @@ def load_config_file(config_file):
678 682
         'remote': 'defaultremote',
679 683
         'rebase': 'defaultrebase',
680 684
         'track': 'track',
685
+        'usepushurl': 'usepushurl',
681 686
     }
682 687
     config = {}
683 688
     for config_key, option_name in options.items():
@@ -732,42 +737,58 @@ def resolve_tracking(remote, branch):
732 737
     return remote, branch
733 738
 
734 739
 
735
-def check_remote(branch, remote, scheme, hostname, port, project):
740
+def check_remote(branch, remote, scheme, hostname, port, project,
741
+                 usepushurl=False):
736 742
     """Check that a Gerrit Git remote repo exists, if not, set one."""
737 743
 
738
-    has_color = check_color_support()
739
-    if has_color:
740
-        color_never = "--color=never"
744
+    if usepushurl:
745
+        push_url = git_config_get_value('remote.%s' % remote, 'pushurl', None)
746
+        if push_url:
747
+            return
741 748
     else:
742
-        color_never = ""
749
+        has_color = check_color_support()
750
+        if has_color:
751
+            color_never = "--color=never"
752
+        else:
753
+            color_never = ""
743 754
 
744
-    if remote in run_command("git remote").split("\n"):
755
+        if remote in run_command("git remote").split("\n"):
745 756
 
746
-        remotes = run_command("git branch -a %s" % color_never).split("\n")
747
-        for current_remote in remotes:
748
-            if (current_remote.strip() == "remotes/%s/%s" % (remote, branch)
749
-                    and not UPDATE):
750
-                return
751
-        # We have the remote, but aren't set up to fetch. Fix it
752
-        if VERBOSE:
753
-            print("Setting up gerrit branch tracking for better rebasing")
754
-        update_remote(remote)
755
-        return
757
+            remotes = run_command("git branch -a %s" % color_never).split("\n")
758
+            for current_remote in remotes:
759
+                remote_string = "remotes/%s/%s" % (remote, branch)
760
+                if (current_remote.strip() == remote_string and not UPDATE):
761
+                    return
762
+            # We have the remote, but aren't set up to fetch. Fix it
763
+            if VERBOSE:
764
+                print("Setting up gerrit branch tracking for better rebasing")
765
+            update_remote(remote)
766
+            return
756 767
 
757 768
     if hostname is False or project is False:
758 769
         # This means there was no .gitreview file
759 770
         printwrap("No '.gitreview' file found in this repository. We don't "
760
-                  "know where your gerrit is. Please manually create a remote "
761
-                  "named \"%s\" and try again." % remote)
771
+                  "know where your gerrit is.")
772
+        if usepushurl:
773
+            printwrap("Please set the push-url on your origin remote to the "
774
+                      "location of your gerrit server and try again")
775
+        else:
776
+            printwrap("Please manually create a remote "
777
+                      "named \"%s\" and try again." % remote)
762 778
         sys.exit(1)
763 779
 
764 780
     # Gerrit remote not present, try to add it
765 781
     try:
766
-        add_remote(scheme, hostname, port, project, remote)
782
+        add_remote(scheme, hostname, port, project, remote, usepushurl)
767 783
     except Exception:
768 784
         print(sys.exc_info()[2])
769
-        printwrap("We don't know where your gerrit is. Please manually create "
770
-                  "a remote named \"%s\" and try again." % remote)
785
+        if usepushurl:
786
+            printwrap("We don't know where your gerrit is. Please manually"
787
+                      " add a push-url to the '%s' remote and try again."
788
+                      % remote)
789
+        else:
790
+            printwrap("We don't know where your gerrit is. Please manually"
791
+                      " create a remote named '%s' and try again." % remote)
771 792
         raise
772 793
 
773 794
 
@@ -1294,6 +1315,10 @@ def _main():
1294 1315
                         help="Regenerate Change-id before submitting")
1295 1316
     parser.add_argument("-r", "--remote", dest="remote",
1296 1317
                         help="git remote to use for gerrit")
1318
+    parser.add_argument("--use-pushurl", dest="usepushurl",
1319
+                        action="store_true",
1320
+                        help="Use remote push-url logic instead of separate"
1321
+                             " remotes")
1297 1322
 
1298 1323
     rebase_group = parser.add_mutually_exclusive_group()
1299 1324
     rebase_group.add_argument("-R", "--no-rebase", dest="rebase",
@@ -1400,7 +1425,8 @@ def _main():
1400 1425
         config = Config(os.path.join(top_dir, ".gitreview"))
1401 1426
         parser.set_defaults(rebase=convert_bool(config['rebase']),
1402 1427
                             track=convert_bool(config['track']),
1403
-                            remote=config['remote'])
1428
+                            remote=None,
1429
+                            usepushurl=convert_bool(config['usepushurl']))
1404 1430
     options = parser.parse_args()
1405 1431
     if no_git_dir:
1406 1432
         raise no_git_dir
@@ -1421,6 +1447,11 @@ def _main():
1421 1447
     VERBOSE = options.verbose
1422 1448
     UPDATE = options.update
1423 1449
     remote = options.remote
1450
+    if not remote:
1451
+        if options.usepushurl:
1452
+            remote = 'origin'
1453
+        else:
1454
+            remote = config['remote']
1424 1455
     yes = options.yes
1425 1456
     status = 0
1426 1457
 
@@ -1428,7 +1459,8 @@ def _main():
1428 1459
         remote, branch = resolve_tracking(remote, branch)
1429 1460
 
1430 1461
     check_remote(branch, remote, config['scheme'],
1431
-                 config['hostname'], config['port'], config['project'])
1462
+                 config['hostname'], config['port'], config['project'],
1463
+                 usepushurl=options.usepushurl)
1432 1464
 
1433 1465
     if options.color:
1434 1466
         set_color_output(options.color)

+ 11
- 1
git_review/tests/__init__.py View File

@@ -131,6 +131,7 @@ class BaseGitReviewTestCase(testtools.TestCase, GerritHelpers):
131 131
     """Base class for the git-review tests."""
132 132
 
133 133
     _test_counter = 0
134
+    _remote = 'gerrit'
134 135
 
135 136
     @property
136 137
     def project_uri(self):
@@ -201,12 +202,18 @@ class BaseGitReviewTestCase(testtools.TestCase, GerritHelpers):
201 202
 
202 203
         # go to the just cloned test Git repository
203 204
         self._run_git('clone', self.project_uri)
204
-        self._run_git('remote', 'add', 'gerrit', self.project_uri)
205
+        self.configure_gerrit_remote()
205 206
         self.addCleanup(shutil.rmtree, self.test_dir)
206 207
 
207 208
         # ensure user is configured for all tests
208 209
         self._configure_gitreview_username()
209 210
 
211
+    def set_remote(self, uri):
212
+        self._run_git('remote', 'set-url', self._remote, uri)
213
+
214
+    def reset_remote(self):
215
+        self._run_git('remote', 'rm', self._remote)
216
+
210 217
     def attach_on_exception(self, filename):
211 218
         @self.addOnException
212 219
         def attach_file(exc_info):
@@ -290,6 +297,9 @@ class BaseGitReviewTestCase(testtools.TestCase, GerritHelpers):
290 297
         os.environ['PATH'] = self.ssh_dir + os.pathsep + os.environ['PATH']
291 298
         os.environ['GIT_SSH'] = self._dir('ssh', 'ssh')
292 299
 
300
+    def configure_gerrit_remote(self):
301
+        self._run_git('remote', 'add', self._remote, self.project_uri)
302
+
293 303
     def _configure_gitreview_username(self):
294 304
         self._run_git('config', 'gitreview.username', 'test_user')
295 305
 

+ 76
- 49
git_review/tests/test_git_review.py View File

@@ -23,6 +23,39 @@ from git_review import tests
23 23
 from git_review.tests import utils
24 24
 
25 25
 
26
+class ConfigTestCase(tests.BaseGitReviewTestCase):
27
+    """Class for config tests."""
28
+
29
+    def test_get_config_from_cli(self):
30
+        self.reset_remote()
31
+        self._run_git('remote', 'rm', 'origin')
32
+        self._create_gitreview_file(defaultremote='remote-file')
33
+        self._run_git('config', 'gitreview.remote', 'remote-gitconfig')
34
+        self._run_git_review('-s', '-r', 'remote-cli')
35
+
36
+        remote = self._run_git('remote').strip()
37
+        self.assertEqual('remote-cli', remote)
38
+
39
+    def test_get_config_from_gitconfig(self):
40
+        self.reset_remote()
41
+        self._run_git('remote', 'rm', 'origin')
42
+        self._create_gitreview_file(defaultremote='remote-file')
43
+        self._run_git('config', 'gitreview.remote', 'remote-gitconfig')
44
+        self._run_git_review('-s')
45
+
46
+        remote = self._run_git('remote').strip()
47
+        self.assertEqual('remote-gitconfig', remote)
48
+
49
+    def test_get_config_from_file(self):
50
+        self.reset_remote()
51
+        self._run_git('remote', 'rm', 'origin')
52
+        self._create_gitreview_file(defaultremote='remote-file')
53
+        self._run_git_review('-s')
54
+
55
+        remote = self._run_git('remote').strip()
56
+        self.assertEqual('remote-file', remote)
57
+
58
+
26 59
 class GitReviewTestCase(tests.BaseGitReviewTestCase):
27 60
     """Class for the git-review tests."""
28 61
 
@@ -35,14 +68,14 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
35 68
 
36 69
     def test_git_review_s(self):
37 70
         """Test git-review -s."""
38
-        self._run_git('remote', 'rm', 'gerrit')
71
+        self.reset_remote()
39 72
         self._run_git_review('-s')
40 73
         self._simple_change('test file modified', 'test commit message')
41 74
         self.assertIn('Change-Id:', self._run_git('log', '-1'))
42 75
 
43 76
     def test_git_review_s_in_detached_head(self):
44 77
         """Test git-review -s in detached HEAD state."""
45
-        self._run_git('remote', 'rm', 'gerrit')
78
+        self.reset_remote()
46 79
         master_sha1 = self._run_git('rev-parse', 'master')
47 80
         self._run_git('checkout', master_sha1)
48 81
         self._run_git_review('-s')
@@ -56,14 +89,14 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
56 89
         self._run_git('reset', '--hard', 'HEAD^')
57 90
 
58 91
         # Review setup with an outdated repo
59
-        self._run_git('remote', 'rm', 'gerrit')
92
+        self.reset_remote()
60 93
         self._run_git_review('-s')
61 94
         self._simple_change('test file modified', 'test commit message 2')
62 95
         self.assertIn('Change-Id:', self._run_git('log', '-1'))
63 96
 
64 97
     def test_git_review_s_from_subdirectory(self):
65 98
         """Test git-review -s from subdirectory."""
66
-        self._run_git('remote', 'rm', 'gerrit')
99
+        self.reset_remote()
67 100
         utils.run_cmd('mkdir', 'subdirectory', chdir=self.test_dir)
68 101
         self._run_git_review(
69 102
             '-s', chdir=os.path.join(self.test_dir, 'subdirectory'))
@@ -81,7 +114,7 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
81 114
 
82 115
         # download clean Git repository and fresh change from Gerrit to it
83 116
         self._run_git('clone', self.project_uri)
84
-        self._run_git('remote', 'add', 'gerrit', self.project_uri)
117
+        self.configure_gerrit_remote()
85 118
         self._run_git_review('-d', change_id)
86 119
         self.assertIn('test commit message', self._run_git('log', '-1'))
87 120
 
@@ -94,7 +127,7 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
94 127
         # and branch is tracking
95 128
         head = self._run_git('symbolic-ref', '-q', 'HEAD')
96 129
         self.assertIn(
97
-            'refs/remotes/gerrit/master',
130
+            'refs/remotes/%s/master' % self._remote,
98 131
             self._run_git("for-each-ref", "--format='%(upstream)'", head))
99 132
 
100 133
     def test_multiple_changes(self):
@@ -164,9 +197,11 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
164 197
         """Test message displayed where no remote branch exists."""
165 198
         self._run_git_review('-s')
166 199
         self._run_git('checkout', '-b', 'new_branch')
200
+        self._simple_change('simple message',
201
+                            'need to avoid noop message')
167 202
         exc = self.assertRaises(Exception, self._run_git_review, 'new_branch')
168 203
         self.assertIn("The branch 'new_branch' does not exist on the given "
169
-                      "remote 'gerrit'", exc.args[0])
204
+                      "remote '%s'" % self._remote, exc.args[0])
170 205
 
171 206
     def test_need_rebase_no_upload(self):
172 207
         """Test change needing a rebase does not upload."""
@@ -179,8 +214,9 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
179 214
                             'create conflict with master')
180 215
 
181 216
         exc = self.assertRaises(Exception, self._run_git_review)
182
-        self.assertIn("Errors running git rebase -p -i remotes/gerrit/master",
183
-                      exc.args[0])
217
+        self.assertIn(
218
+            "Errors running git rebase -p -i remotes/%s/master" % self._remote,
219
+            exc.args[0])
184 220
         self.assertIn("It is likely that your change has a merge conflict.",
185 221
                       exc.args[0])
186 222
 
@@ -196,8 +232,9 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
196 232
                             self._dir('test', 'new_test_file.txt'))
197 233
 
198 234
         review_res = self._run_git_review('-v')
199
-        self.assertIn("Running: git rebase -p -i remotes/gerrit/master",
200
-                      review_res)
235
+        self.assertIn(
236
+            "Running: git rebase -p -i remotes/%s/master" % self._remote,
237
+            review_res)
201 238
         self.assertEqual(self._run_git('rev-parse', 'HEAD^1'), head_1)
202 239
 
203 240
     def test_uploads_with_nondefault_rebase(self):
@@ -473,53 +510,43 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
473 510
     def test_git_review_F_R(self):
474 511
         self.assertRaises(Exception, self._run_git_review, '-F', '-R')
475 512
 
476
-    def test_get_config_from_cli(self):
477
-        self._run_git('remote', 'rm', 'origin')
478
-        self._run_git('remote', 'rm', 'gerrit')
479
-        self._create_gitreview_file(defaultremote='remote-file')
480
-        self._run_git('config', 'gitreview.remote', 'remote-gitconfig')
481
-        self._run_git_review('-s', '-r', 'remote-cli')
482
-
483
-        remote = self._run_git('remote').strip()
484
-        self.assertEqual('remote-cli', remote)
485
-
486
-    def test_get_config_from_gitconfig(self):
487
-        self._run_git('remote', 'rm', 'origin')
488
-        self._run_git('remote', 'rm', 'gerrit')
489
-        self._create_gitreview_file(defaultremote='remote-file')
490
-        self._run_git('config', 'gitreview.remote', 'remote-gitconfig')
491
-        self._run_git_review('-s')
492
-
493
-        remote = self._run_git('remote').strip()
494
-        self.assertEqual('remote-gitconfig', remote)
495
-
496
-    def test_get_config_from_file(self):
497
-        self._run_git('remote', 'rm', 'origin')
498
-        self._run_git('remote', 'rm', 'gerrit')
499
-        self._create_gitreview_file(defaultremote='remote-file')
500
-        self._run_git_review('-s')
501
-
502
-        remote = self._run_git('remote').strip()
503
-        self.assertEqual('remote-file', remote)
504
-
505 513
     def test_config_instead_of_honored(self):
506
-        self._run_git('remote', 'add', 'alias', 'test_project_url')
514
+        self.set_remote('test_project_url')
507 515
 
508
-        exc = self.assertRaises(Exception, self._run_git_review,
509
-                                '-l', '-r', 'alias')
510
-        self.assertIn("'test_project_url' does not appear to be a git "
511
-                      "repository", exc.args[0])
516
+        self.assertRaises(Exception, self._run_git_review, '-l')
512 517
 
513 518
         self._run_git('config', '--add', 'url.%s.insteadof' % self.project_uri,
514 519
                       'test_project_url')
515
-        self._run_git_review('-l', '-r', 'alias')
520
+        self._run_git_review('-l')
521
+
522
+    def test_config_pushinsteadof_honored(self):
523
+        self.set_remote('test_project_url')
524
+
525
+        self.assertRaises(Exception, self._run_git_review, '-l')
516 526
 
517
-        self._run_git('config', '--unset',
518
-                      'url.%s.insteadof' % self.project_uri)
519 527
         self._run_git('config', '--add',
520 528
                       'url.%s.pushinsteadof' % self.project_uri,
521 529
                       'test_project_url')
522
-        self._run_git_review('-l', '-r', 'alias')
530
+        self._run_git_review('-l')
531
+
532
+
533
+class PushUrlTestCase(GitReviewTestCase):
534
+    """Class for the git-review tests using origin push-url."""
535
+
536
+    _remote = 'origin'
537
+
538
+    def set_remote(self, uri):
539
+        self._run_git('remote', 'set-url', '--push', self._remote, uri)
540
+
541
+    def reset_remote(self):
542
+        self._run_git('config', '--unset', 'remote.%s.pushurl' % self._remote)
543
+
544
+    def configure_gerrit_remote(self):
545
+        self.set_remote(self.project_uri)
546
+        self._run_git('config', 'gitreview.usepushurl', '1')
547
+
548
+    def test_config_pushinsteadof_honored(self):
549
+        self.skipTest("pushinsteadof doesn't rewrite pushurls")
523 550
 
524 551
 
525 552
 class HttpGitReviewTestCase(tests.HttpMixin, GitReviewTestCase):

Loading…
Cancel
Save