Ver Fonte

Support main as default branch

R=apolito@google.com

Change-Id: Ic338c698b8eb8d2e04fc1ef23ae4b13cae08b80f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2404701
Reviewed-by: Anthony Polito <apolito@google.com>
Commit-Queue: Josip Sokcevic <sokcevic@google.com>
Josip Sokcevic há 4 anos atrás
pai
commit
c39ab997ba
4 ficheiros alterados com 96 adições e 25 exclusões
  1. 26 0
      gerrit_client.py
  2. 9 0
      gerrit_util.py
  3. 23 10
      git_cl.py
  4. 38 15
      tests/git_cl_test.py

+ 26 - 0
gerrit_client.py

@@ -37,6 +37,32 @@ def write_result(result, opt):
       json_file.write(json.dumps(result))
       json_file.write(json.dumps(result))
 
 
 
 
+@subcommand.usage('[args ...]')
+def CMDmovechanges(parser, args):
+  parser.add_option('-p', '--param', dest='params', action='append',
+                    help='repeatable query parameter, format: -p key=value')
+  parser.add_option('--destination_branch', dest='destination_branch',
+                    help='where to move changes to')
+
+  (opt, args) = parser.parse_args(args)
+  assert opt.destination_branch, "--destination_branch not defined"
+  host = urlparse.urlparse(opt.host).netloc
+
+  limit = 100
+  while True:
+    result = gerrit_util.QueryChanges(
+        host,
+        list(tuple(p.split('=', 1)) for p in opt.params),
+        limit=limit,
+    )
+    for change in result:
+      gerrit_util.MoveChange(host, change['id'], opt.destination_branch)
+
+    if len(result) < limit:
+      break
+  logging.info("Done")
+
+
 @subcommand.usage('[args ...]')
 @subcommand.usage('[args ...]')
 def CMDbranchinfo(parser, args):
 def CMDbranchinfo(parser, args):
   parser.add_option('--branch', dest='branch', help='branch name')
   parser.add_option('--branch', dest='branch', help='branch name')

+ 9 - 0
gerrit_util.py

@@ -706,6 +706,15 @@ def AbandonChange(host, change, msg=''):
   return ReadHttpJsonResponse(conn)
   return ReadHttpJsonResponse(conn)
 
 
 
 
+def MoveChange(host, change, destination_branch):
+  """Move a Gerrit change to different destination branch."""
+  path = 'changes/%s/move' % change
+  body = {'destination_branch': destination_branch}
+  conn = CreateHttpConn(host, path, reqtype='POST', body=body)
+  return ReadHttpJsonResponse(conn)
+
+
+
 def RestoreChange(host, change, msg=''):
 def RestoreChange(host, change, msg=''):
   """Restores a previously abandoned change."""
   """Restores a previously abandoned change."""
   path = 'changes/%s/restore' % change
   path = 'changes/%s/restore' % change

+ 23 - 10
git_cl.py

@@ -108,6 +108,9 @@ REFS_THAT_ALIAS_TO_OTHER_REFS = {
     'refs/remotes/origin/lkcr': 'refs/remotes/origin/master',
     'refs/remotes/origin/lkcr': 'refs/remotes/origin/master',
 }
 }
 
 
+DEFAULT_OLD_BRANCH = 'refs/remotes/origin/master'
+DEFAULT_NEW_BRANCH = 'refs/remotes/origin/main'
+
 # Valid extensions for files we want to lint.
 # Valid extensions for files we want to lint.
 DEFAULT_LINT_REGEX = r"(.*\.cpp|.*\.cc|.*\.h)"
 DEFAULT_LINT_REGEX = r"(.*\.cpp|.*\.cc|.*\.h)"
 DEFAULT_LINT_IGNORE_REGEX = r"$^"
 DEFAULT_LINT_IGNORE_REGEX = r"$^"
@@ -641,7 +644,7 @@ def _GetYapfIgnorePatterns(top_dir):
   yapf is supposed to handle the ignoring of files listed in .yapfignore itself,
   yapf is supposed to handle the ignoring of files listed in .yapfignore itself,
   but this functionality appears to break when explicitly passing files to
   but this functionality appears to break when explicitly passing files to
   yapf for formatting. According to
   yapf for formatting. According to
-  https://github.com/google/yapf/blob/master/README.rst#excluding-files-from-formatting-yapfignore,
+  https://github.com/google/yapf/blob/HEAD/README.rst#excluding-files-from-formatting-yapfignore,
   the .yapfignore file should be in the directory that yapf is invoked from,
   the .yapfignore file should be in the directory that yapf is invoked from,
   which we assume to be the top level directory in this case.
   which we assume to be the top level directory in this case.
 
 
@@ -987,7 +990,7 @@ class Changelist(object):
     self.more_cc.extend(more_cc)
     self.more_cc.extend(more_cc)
 
 
   def GetBranch(self):
   def GetBranch(self):
-    """Returns the short branch name, e.g. 'master'."""
+    """Returns the short branch name, e.g. 'main'."""
     if not self.branch:
     if not self.branch:
       branchref = scm.GIT.GetBranchRef(settings.GetRoot())
       branchref = scm.GIT.GetBranchRef(settings.GetRoot())
       if not branchref:
       if not branchref:
@@ -997,7 +1000,7 @@ class Changelist(object):
     return self.branch
     return self.branch
 
 
   def GetBranchRef(self):
   def GetBranchRef(self):
-    """Returns the full branch name, e.g. 'refs/heads/master'."""
+    """Returns the full branch name, e.g. 'refs/heads/main'."""
     self.GetBranch()  # Poke the lazy loader.
     self.GetBranch()  # Poke the lazy loader.
     return self.branchref
     return self.branchref
 
 
@@ -1016,7 +1019,7 @@ class Changelist(object):
   @staticmethod
   @staticmethod
   def FetchUpstreamTuple(branch):
   def FetchUpstreamTuple(branch):
     """Returns a tuple containing remote and remote ref,
     """Returns a tuple containing remote and remote ref,
-       e.g. 'origin', 'refs/heads/master'
+       e.g. 'origin', 'refs/heads/main'
     """
     """
     remote, upstream_branch = scm.GIT.FetchUpstreamTuple(
     remote, upstream_branch = scm.GIT.FetchUpstreamTuple(
         settings.GetRoot(), branch)
         settings.GetRoot(), branch)
@@ -1024,7 +1027,7 @@ class Changelist(object):
       DieWithError(
       DieWithError(
          'Unable to determine default branch to diff against.\n'
          'Unable to determine default branch to diff against.\n'
          'Either pass complete "git diff"-style arguments, like\n'
          'Either pass complete "git diff"-style arguments, like\n'
-         '  git cl upload origin/master\n'
+         '  git cl upload origin/main\n'
          'or verify this branch is set up to track another \n'
          'or verify this branch is set up to track another \n'
          '(via the --track argument to "git checkout -b ...").')
          '(via the --track argument to "git checkout -b ...").')
 
 
@@ -1226,8 +1229,8 @@ class Changelist(object):
           ('\nFailed to diff against upstream branch %s\n\n'
           ('\nFailed to diff against upstream branch %s\n\n'
            'This branch probably doesn\'t exist anymore. To reset the\n'
            'This branch probably doesn\'t exist anymore. To reset the\n'
            'tracking branch, please run\n'
            'tracking branch, please run\n'
-           '    git branch --set-upstream-to origin/master %s\n'
-           'or replace origin/master with the relevant branch') %
+           '    git branch --set-upstream-to origin/main %s\n'
+           'or replace origin/main with the relevant branch') %
           (upstream, self.GetBranch()))
           (upstream, self.GetBranch()))
 
 
   def UpdateDescription(self, description, force=False):
   def UpdateDescription(self, description, force=False):
@@ -3939,10 +3942,20 @@ def GetTargetRef(remote, remote_branch, target_branch):
     # Handle the refs that need to land in different refs.
     # Handle the refs that need to land in different refs.
     remote_branch = REFS_THAT_ALIAS_TO_OTHER_REFS[remote_branch]
     remote_branch = REFS_THAT_ALIAS_TO_OTHER_REFS[remote_branch]
 
 
+  # Migration to new default branch, only if available on remote.
+  allow_push_on_master = bool(os.environ.get("ALLOW_PUSH_TO_MASTER", None))
+  if remote_branch == DEFAULT_OLD_BRANCH and not allow_push_on_master:
+    if RunGit(['show-branch', DEFAULT_NEW_BRANCH], error_ok=True,
+              stderr=subprocess2.PIPE):
+      # TODO(crbug.com/ID): Print location to local git migration script.
+      print("WARNING: Using new branch name %s instead of %s" % (
+          DEFAULT_NEW_BRANCH, DEFAULT_OLD_BRANCH))
+      remote_branch = DEFAULT_NEW_BRANCH
+
   # Create the true path to the remote branch.
   # Create the true path to the remote branch.
   # Does the following translation:
   # Does the following translation:
   # * refs/remotes/origin/refs/diff/test -> refs/diff/test
   # * refs/remotes/origin/refs/diff/test -> refs/diff/test
-  # * refs/remotes/origin/master -> refs/heads/master
+  # * refs/remotes/origin/main -> refs/heads/main
   # * refs/remotes/branch-heads/test -> refs/branch-heads/test
   # * refs/remotes/branch-heads/test -> refs/branch-heads/test
   if remote_branch.startswith('refs/remotes/%s/refs/' % remote):
   if remote_branch.startswith('refs/remotes/%s/refs/' % remote):
     remote_branch = remote_branch.replace('refs/remotes/%s/' % remote, '')
     remote_branch = remote_branch.replace('refs/remotes/%s/' % remote, '')
@@ -4026,7 +4039,7 @@ def CMDupload(parser, args):
                     '--target-branch',
                     '--target-branch',
                     metavar='TARGET',
                     metavar='TARGET',
                     help='Apply CL to remote ref TARGET.  ' +
                     help='Apply CL to remote ref TARGET.  ' +
-                         'Default: remote branch head, or master')
+                         'Default: remote branch head, or main')
   parser.add_option('--squash', action='store_true',
   parser.add_option('--squash', action='store_true',
                     help='Squash multiple commits into one')
                     help='Squash multiple commits into one')
   parser.add_option('--no-squash', action='store_false', dest='squash',
   parser.add_option('--no-squash', action='store_false', dest='squash',
@@ -4382,7 +4395,7 @@ def CMDtry(parser, args):
       '-r', '--revision',
       '-r', '--revision',
       help='Revision to use for the tryjob; default: the revision will '
       help='Revision to use for the tryjob; default: the revision will '
            'be determined by the try recipe that builder runs, which usually '
            'be determined by the try recipe that builder runs, which usually '
-           'defaults to HEAD of origin/master')
+           'defaults to HEAD of origin/master or origin/main')
   group.add_option(
   group.add_option(
       '-c', '--clobber', action='store_true', default=False,
       '-c', '--clobber', action='store_true', default=False,
       help='Force a clobber before building; that is don\'t do an '
       help='Force a clobber before building; that is don\'t do an '

+ 38 - 15
tests/git_cl_test.py

@@ -647,7 +647,7 @@ class TestGitCl(unittest.TestCase):
   def _gerrit_base_calls(cls, issue=None, fetched_description=None,
   def _gerrit_base_calls(cls, issue=None, fetched_description=None,
                          fetched_status=None, other_cl_owner=None,
                          fetched_status=None, other_cl_owner=None,
                          custom_cl_base=None, short_hostname='chromium',
                          custom_cl_base=None, short_hostname='chromium',
-                         change_id=None):
+                         change_id=None, new_default=False):
     calls = []
     calls = []
     if custom_cl_base:
     if custom_cl_base:
       ancestor_revision = custom_cl_base
       ancestor_revision = custom_cl_base
@@ -655,8 +655,8 @@ class TestGitCl(unittest.TestCase):
       # Determine ancestor_revision to be merge base.
       # Determine ancestor_revision to be merge base.
       ancestor_revision = 'fake_ancestor_sha'
       ancestor_revision = 'fake_ancestor_sha'
       calls += [
       calls += [
-        (('get_or_create_merge_base', 'master', 'refs/remotes/origin/master'),
-         ancestor_revision),
+        (('get_or_create_merge_base', 'master',
+          'refs/remotes/origin/master'), ancestor_revision),
       ]
       ]
 
 
     if issue:
     if issue:
@@ -682,6 +682,10 @@ class TestGitCl(unittest.TestCase):
           [ancestor_revision, 'HEAD']),),
           [ancestor_revision, 'HEAD']),),
        '+dat'),
        '+dat'),
     ]
     ]
+    calls += [
+      ((['git', 'show-branch', 'refs/remotes/origin/main'], ),
+         '1' if new_default else callError(1)),
+    ]
 
 
     return calls
     return calls
 
 
@@ -693,7 +697,9 @@ class TestGitCl(unittest.TestCase):
                            short_hostname='chromium',
                            short_hostname='chromium',
                            labels=None, change_id=None,
                            labels=None, change_id=None,
                            final_description=None, gitcookies_exists=True,
                            final_description=None, gitcookies_exists=True,
-                           force=False, edit_description=None):
+                           force=False, edit_description=None,
+                           new_default=False):
+    default_branch = 'main' if new_default else 'master';
     if post_amend_description is None:
     if post_amend_description is None:
       post_amend_description = description
       post_amend_description = description
     cc = cc or []
     cc = cc or []
@@ -722,14 +728,14 @@ class TestGitCl(unittest.TestCase):
 
 
       if custom_cl_base is None:
       if custom_cl_base is None:
         calls += [
         calls += [
-          (('get_or_create_merge_base', 'master', 'refs/remotes/origin/master'),
-           'origin/master'),
+          (('get_or_create_merge_base', 'master',
+            'refs/remotes/origin/master'), 'origin/' + default_branch),
         ]
         ]
-        parent = 'origin/master'
+        parent = 'origin/' + default_branch
       else:
       else:
         calls += [
         calls += [
           ((['git', 'merge-base', '--is-ancestor', custom_cl_base,
           ((['git', 'merge-base', '--is-ancestor', custom_cl_base,
-             'refs/remotes/origin/master'],),
+             'refs/remotes/origin/' + default_branch],),
            callError(1)),   # Means not ancenstor.
            callError(1)),   # Means not ancenstor.
           (('ask_for_data',
           (('ask_for_data',
             'Do you take responsibility for cleaning up potential mess '
             'Do you take responsibility for cleaning up potential mess '
@@ -748,7 +754,7 @@ class TestGitCl(unittest.TestCase):
       ]
       ]
     else:
     else:
       ref_to_push = 'HEAD'
       ref_to_push = 'HEAD'
-      parent = 'origin/refs/heads/master'
+      parent = 'origin/refs/heads/' + default_branch
 
 
     calls += [
     calls += [
       (('SaveDescriptionBackup',), None),
       (('SaveDescriptionBackup',), None),
@@ -834,7 +840,7 @@ class TestGitCl(unittest.TestCase):
       (('time.time',), 1000,),
       (('time.time',), 1000,),
       ((['git', 'push',
       ((['git', 'push',
          'https://%s.googlesource.com/my/repo' % short_hostname,
          'https://%s.googlesource.com/my/repo' % short_hostname,
-         ref_to_push + ':refs/for/refs/heads/master' + ref_suffix],),
+         ref_to_push + ':refs/for/refs/heads/' + default_branch + ref_suffix],),
        (('remote:\n'
        (('remote:\n'
          'remote: Processing changes: (\)\n'
          'remote: Processing changes: (\)\n'
          'remote: Processing changes: (|)\n'
          'remote: Processing changes: (|)\n'
@@ -848,8 +854,8 @@ class TestGitCl(unittest.TestCase):
              ' XXX\n'
              ' XXX\n'
          'remote:\n'
          'remote:\n'
          'To https://%s.googlesource.com/my/repo\n'
          'To https://%s.googlesource.com/my/repo\n'
-         ' * [new branch]      hhhh -> refs/for/refs/heads/master\n'
-         ) % (short_hostname, short_hostname)),),
+         ' * [new branch]      hhhh -> refs/for/refs/heads/%s\n'
+         ) % (short_hostname, short_hostname, default_branch)),),
       (('time.time',), 2000,),
       (('time.time',), 2000,),
       (('add_repeated',
       (('add_repeated',
         'sub_commands',
         'sub_commands',
@@ -990,7 +996,8 @@ class TestGitCl(unittest.TestCase):
       force=False,
       force=False,
       log_description=None,
       log_description=None,
       edit_description=None,
       edit_description=None,
-      fetched_description=None):
+      fetched_description=None,
+      new_default=False):
     """Generic gerrit upload test framework."""
     """Generic gerrit upload test framework."""
     if squash_mode is None:
     if squash_mode is None:
       if '--no-squash' in upload_args:
       if '--no-squash' in upload_args:
@@ -1060,7 +1067,8 @@ class TestGitCl(unittest.TestCase):
         other_cl_owner=other_cl_owner,
         other_cl_owner=other_cl_owner,
         custom_cl_base=custom_cl_base,
         custom_cl_base=custom_cl_base,
         short_hostname=short_hostname,
         short_hostname=short_hostname,
-        change_id=change_id)
+        change_id=change_id,
+        new_default=new_default)
     if fetched_status != 'ABANDONED':
     if fetched_status != 'ABANDONED':
       mock.patch(
       mock.patch(
           'gclient_utils.temporary_file', TemporaryFileMock()).start()
           'gclient_utils.temporary_file', TemporaryFileMock()).start()
@@ -1078,7 +1086,8 @@ class TestGitCl(unittest.TestCase):
           final_description=final_description,
           final_description=final_description,
           gitcookies_exists=gitcookies_exists,
           gitcookies_exists=gitcookies_exists,
           force=force,
           force=force,
-          edit_description=edit_description)
+          edit_description=edit_description,
+          new_default=new_default)
     # Uncomment when debugging.
     # Uncomment when debugging.
     # print('\n'.join(map(lambda x: '%2i: %s' % x, enumerate(self.calls))))
     # print('\n'.join(map(lambda x: '%2i: %s' % x, enumerate(self.calls))))
     git_cl.main(['upload'] + upload_args)
     git_cl.main(['upload'] + upload_args)
@@ -1444,6 +1453,10 @@ class TestGitCl(unittest.TestCase):
     self.assertEqual(expected, actual)
     self.assertEqual(expected, actual)
 
 
   def test_get_hash_tags(self):
   def test_get_hash_tags(self):
+    self.calls = [
+        ((['git', 'show-branch', 'refs/remotes/origin/main'], ),
+            callError(1)),
+    ] * 9
     cases = [
     cases = [
       ('', []),
       ('', []),
       ('a', []),
       ('a', []),
@@ -2659,6 +2672,16 @@ class TestGitCl(unittest.TestCase):
     cl = git_cl.Changelist(issue=123456)
     cl = git_cl.Changelist(issue=123456)
     self.assertEqual(cl._GerritChangeIdentifier(), '123456')
     self.assertEqual(cl._GerritChangeIdentifier(), '123456')
 
 
+  def test_gerrit_new_default(self):
+    self._run_gerrit_upload_test(
+        [],
+        'desc ✔\n\nBUG=\n\nChange-Id: I123456789\n',
+        [],
+        squash=False,
+        squash_mode='override_nosquash',
+        change_id='I123456789',
+        new_default=True)
+
 
 
 class ChangelistTest(unittest.TestCase):
 class ChangelistTest(unittest.TestCase):
   def setUp(self):
   def setUp(self):