blob: fec10fb6ec266cc981ab5c08edea720546cd4b4d [file] [log] [blame]
Josip Sokcevicdfa44da2020-10-27 22:34:08 +00001#!/usr/bin/env vpython3
2# Copyright 2020 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5"""Migrate local repository onto new default branch."""
6
7import fix_encoding
8import gerrit_util
9import git_common
10import metrics
Josip Sokcevic688adfe2023-03-01 22:46:12 +000011from lib import scm
Josip Sokcevicdfa44da2020-10-27 22:34:08 +000012import sys
13import logging
14from six.moves import urllib
15
16
17def GetGerritProject(remote_url):
18 """Returns Gerrit project name based on remote git URL."""
19 if remote_url is None:
20 raise RuntimeError('can\'t detect Gerrit project.')
21 project = urllib.parse.urlparse(remote_url).path.strip('/')
22 if project.endswith('.git'):
23 project = project[:-len('.git')]
24 # *.googlesource.com hosts ensure that Git/Gerrit projects don't start with
25 # 'a/' prefix, because 'a/' prefix is used to force authentication in
26 # gitiles/git-over-https protocol. E.g.,
27 # https://chromium.googlesource.com/a/v8/v8 refers to the same repo/project
28 # as
29 # https://chromium.googlesource.com/v8/v8
30 if project.startswith('a/'):
31 project = project[len('a/'):]
32 return project
33
34
35def GetGerritHost(git_host):
36 parts = git_host.split('.')
37 parts[0] = parts[0] + '-review'
38 return '.'.join(parts)
39
40
41def main():
42 remote = git_common.run('remote')
43 # Use first remote as source of truth
44 remote = remote.split("\n")[0]
45 if not remote:
46 raise RuntimeError('Could not find any remote')
47 url = scm.GIT.GetConfig(git_common.repo_root(), 'remote.%s.url' % remote)
48 host = urllib.parse.urlparse(url).netloc
49 if not host:
50 raise RuntimeError('Could not find remote host')
51
52 project_head = gerrit_util.GetProjectHead(GetGerritHost(host),
53 GetGerritProject(url))
54 if project_head != 'refs/heads/main':
55 raise RuntimeError("The repository is not migrated yet.")
56
Josip Sokcevicc08f84e2021-11-11 01:52:18 +000057 # User may have set to fetch only old default branch. Ensure fetch is tracking
58 # main too.
59 git_common.run('config', '--unset-all',
60 'remote.origin.fetch', 'refs/heads/*')
61 git_common.run('config', '--add',
62 'remote.origin.fetch', '+refs/heads/*:refs/remotes/origin/*')
Josip Sokcevic94ba8a22021-03-02 23:56:34 +000063 logging.info("Running fetch...")
Josip Sokcevicdfa44da2020-10-27 22:34:08 +000064 git_common.run('fetch', remote)
Josip Sokcevic94ba8a22021-03-02 23:56:34 +000065 logging.info("Updating remote HEAD...")
66 git_common.run('remote', 'set-head', '-a', remote)
Josip Sokcevicdfa44da2020-10-27 22:34:08 +000067
68 branches = git_common.get_branches_info(True)
69
70 if 'master' in branches:
71 logging.info("Migrating master branch...")
72 if 'main' in branches:
73 logging.info('You already have master and main branch, consider removing '
74 'master manually:\n'
75 ' $ git branch -d master\n')
76 else:
77 git_common.run('branch', '-m', 'master', 'main')
78 branches = git_common.get_branches_info(True)
79
80 for name in branches:
81 branch = branches[name]
82 if not branch:
83 continue
84
85 if 'master' in branch.upstream:
86 logging.info("Migrating %s branch..." % name)
87 new_upstream = branch.upstream.replace('master', 'main')
88 git_common.run('branch', '--set-upstream-to', new_upstream, name)
89 git_common.remove_merge_base(name)
90
91
92if __name__ == '__main__':
93 fix_encoding.fix_encoding()
94 logging.basicConfig(level=logging.INFO)
95 with metrics.collector.print_notice_and_exit():
96 try:
97 logging.info("Starting migration")
98 main()
99 logging.info("Migration completed")
100 except RuntimeError as e:
101 logging.error("Error %s" % str(e))
102 sys.exit(1)