Add git-migrate-default-branch
R=ehmaldonado@chromium.org
Change-Id: Ib43132afd914bc3ea66f8a634ce8ead9bf2d3b4b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2496064
Commit-Queue: Josip Sokcevic <sokcevic@google.com>
Reviewed-by: Edward Lesmes <ehmaldonado@chromium.org>
diff --git a/git_migrate_default_branch.py b/git_migrate_default_branch.py
new file mode 100644
index 0000000..a605059
--- /dev/null
+++ b/git_migrate_default_branch.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env vpython3
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Migrate local repository onto new default branch."""
+
+import fix_encoding
+import gerrit_util
+import git_common
+import metrics
+import scm
+import sys
+import logging
+from six.moves import urllib
+
+
+def GetGerritProject(remote_url):
+ """Returns Gerrit project name based on remote git URL."""
+ if remote_url is None:
+ raise RuntimeError('can\'t detect Gerrit project.')
+ project = urllib.parse.urlparse(remote_url).path.strip('/')
+ if project.endswith('.git'):
+ project = project[:-len('.git')]
+ # *.googlesource.com hosts ensure that Git/Gerrit projects don't start with
+ # 'a/' prefix, because 'a/' prefix is used to force authentication in
+ # gitiles/git-over-https protocol. E.g.,
+ # https://chromium.googlesource.com/a/v8/v8 refers to the same repo/project
+ # as
+ # https://chromium.googlesource.com/v8/v8
+ if project.startswith('a/'):
+ project = project[len('a/'):]
+ return project
+
+
+def GetGerritHost(git_host):
+ parts = git_host.split('.')
+ parts[0] = parts[0] + '-review'
+ return '.'.join(parts)
+
+
+def main():
+ remote = git_common.run('remote')
+ # Use first remote as source of truth
+ remote = remote.split("\n")[0]
+ if not remote:
+ raise RuntimeError('Could not find any remote')
+ url = scm.GIT.GetConfig(git_common.repo_root(), 'remote.%s.url' % remote)
+ host = urllib.parse.urlparse(url).netloc
+ if not host:
+ raise RuntimeError('Could not find remote host')
+
+ project_head = gerrit_util.GetProjectHead(GetGerritHost(host),
+ GetGerritProject(url))
+ if project_head != 'refs/heads/main':
+ raise RuntimeError("The repository is not migrated yet.")
+
+ git_common.run('fetch', remote)
+
+ branches = git_common.get_branches_info(True)
+
+ if 'master' in branches:
+ logging.info("Migrating master branch...")
+ if 'main' in branches:
+ logging.info('You already have master and main branch, consider removing '
+ 'master manually:\n'
+ ' $ git branch -d master\n')
+ else:
+ git_common.run('branch', '-m', 'master', 'main')
+ branches = git_common.get_branches_info(True)
+
+ for name in branches:
+ branch = branches[name]
+ if not branch:
+ continue
+
+ if 'master' in branch.upstream:
+ logging.info("Migrating %s branch..." % name)
+ new_upstream = branch.upstream.replace('master', 'main')
+ git_common.run('branch', '--set-upstream-to', new_upstream, name)
+ git_common.remove_merge_base(name)
+
+
+if __name__ == '__main__':
+ fix_encoding.fix_encoding()
+ logging.basicConfig(level=logging.INFO)
+ with metrics.collector.print_notice_and_exit():
+ try:
+ logging.info("Starting migration")
+ main()
+ logging.info("Migration completed")
+ except RuntimeError as e:
+ logging.error("Error %s" % str(e))
+ sys.exit(1)