]>
Commit | Line | Data |
---|---|---|
6c6826b7 MF |
1 | #!/usr/bin/python3 |
2 | # -*- coding: utf-8 -*- | |
3 | ||
4 | """Wrapper for syncing CrOS code. | |
5 | ||
6 | Actions: | |
7 | depot_tools clone depot_tools tree | |
8 | int switch to internal tree | |
9 | ext switch to external tree | |
10 | ||
11 | Operates on the repo in the cwd. | |
12 | """ | |
13 | ||
14 | import argparse | |
15 | import fnmatch | |
16 | import os | |
17 | import subprocess | |
18 | import sys | |
19 | ||
20 | ||
21 | REPO_URL = 'https://chromium.googlesource.com/external/repo' | |
22 | INT_MANIFEST = 'https://chrome-internal.googlesource.com/chromeos/manifest-internal' | |
23 | EXT_MANIFEST = 'https://chromium.googlesource.com/chromiumos/manifest' | |
24 | ||
25 | ||
26 | def run(cmd, **kwargs): | |
27 | """Run with command tracing.""" | |
28 | # Python 3.6 doesn't support capture_output. | |
29 | if sys.version_info < (3, 7): | |
30 | capture_output = kwargs.pop('capture_output', None) | |
31 | if capture_output: | |
32 | assert 'stdout' not in kwargs and 'stderr' not in kwargs | |
33 | kwargs['stdout'] = subprocess.PIPE | |
34 | kwargs['stderr'] = subprocess.PIPE | |
35 | ||
36 | print(kwargs.get('cwd', os.getcwd())) | |
37 | print(' '.join(cmd)) | |
38 | return subprocess.run(cmd, **kwargs) | |
39 | ||
40 | ||
41 | def expand_branch(opts): | |
42 | """Support branch shortnames.""" | |
43 | url = INT_MANIFEST if opts.action == 'int' else EXT_MANIFEST | |
44 | ret = run(['git', 'ls-remote', url, 'refs/heads/*'], capture_output=True, encoding='utf-8') | |
45 | branches = [x.split()[-1].split('/')[-1] for x in ret.stdout.splitlines()] | |
46 | ret = [] | |
47 | for branch in branches: | |
90340618 MF |
48 | if branch.lower() == opts.branch.lower(): |
49 | ret = [branch] | |
50 | break | |
51 | elif fnmatch.fnmatch(branch.lower(), f'*{opts.branch.lower()}*'): | |
6c6826b7 MF |
52 | ret.append(branch) |
53 | if not ret: | |
54 | print(f'error: could not match branch {opts.branch}', file=sys.stderr) | |
55 | print(f'Available branches:\n{" ".join(sorted(branches))}', file=sys.stderr) | |
56 | sys.exit(1) | |
57 | if len(ret) > 1: | |
58 | print(f'error: too many branches match {opts.branch}:\n{" ".join(sorted(ret))}', | |
59 | file=sys.stderr) | |
60 | sys.exit(1) | |
61 | print(f'Expanded branch {opts.branch} into {ret[0]}') | |
62 | return ret[0] | |
63 | ||
64 | ||
90340618 MF |
65 | def get_repo_topdir(opts): |
66 | """Find the top dir of this repo client checkout.""" | |
6c6826b7 MF |
67 | topdir = os.getcwd() |
68 | while True: | |
69 | rdir = os.path.join(topdir, '.repo') | |
70 | if os.path.exists(rdir): | |
71 | break | |
72 | topdir = os.path.dirname(topdir) | |
73 | assert topdir != '/' | |
90340618 MF |
74 | return topdir |
75 | ||
76 | ||
77 | def set_git_config(opts): | |
78 | """Set .git/config settings in all the repos.""" | |
79 | topdir = get_repo_topdir(opts) | |
80 | rdir = os.path.join(topdir, '.repo') | |
6c6826b7 MF |
81 | |
82 | def gcfg(path, *args): | |
83 | cmd = ['git', f'--git-dir={path}', 'config', 'user.email'] + list(args) | |
84 | ret = run(cmd, capture_output=True, encoding='utf-8') | |
85 | return ret.stdout.strip() | |
86 | ||
87 | current_email = gcfg(os.path.join(rdir, 'manifests.git')) | |
88 | if current_email == opts.email: | |
89 | return | |
90 | ||
91 | print(f'Setting e-mail to {opts.email}') | |
92 | for root, dirs, files in os.walk(rdir): | |
93 | if root.endswith('.git') and not os.path.islink(os.path.join(root, 'config')): | |
94 | gcfg(root, opts.email) | |
95 | del dirs[:] | |
96 | ||
97 | ||
98 | def init_repo(opts): | |
99 | """Initialize CrOS checkout.""" | |
4712112f | 100 | cmd = ['repo', 'init', '-c'] |
6c6826b7 MF |
101 | |
102 | if opts.action == 'int': | |
103 | cmd += ['-u', INT_MANIFEST] | |
104 | cmd += ['--repo-url', REPO_URL] | |
105 | elif opts.action == 'ext': | |
106 | cmd += ['-u', EXT_MANIFEST] | |
107 | cmd += ['--repo-url', REPO_URL] | |
108 | ||
90340618 | 109 | if opts.ref and os.path.realpath(opts.ref) != os.path.realpath(get_repo_topdir(opts)): |
6c6826b7 MF |
110 | cmd += ['--reference', opts.ref] |
111 | ||
112 | if opts.manifest: | |
113 | cmd += ['-m', opts.manifest] | |
114 | ||
115 | if opts.group: | |
116 | cmd += ['-g', opts.group] | |
117 | ||
118 | if opts.branch: | |
119 | branch = expand_branch(opts) | |
120 | cmd += ['-b', branch] | |
121 | ||
122 | ret = run(cmd) | |
123 | if ret.returncode: | |
124 | return ret.returncode | |
125 | ||
126 | set_git_config(opts) | |
127 | ||
128 | print('\ncros-repo: all done') | |
129 | return 0 | |
130 | ||
131 | ||
132 | def clone_depot_tools(): | |
133 | """Clone depot_tools repo.""" | |
134 | ret = run(['git', 'clone', 'https://chromium.googlesource.com/chromium/tools/depot_tools']) | |
135 | return ret.returncode | |
136 | ||
137 | ||
138 | def get_parser(): | |
139 | """Get command line parser.""" | |
140 | parser = argparse.ArgumentParser( | |
141 | description=__doc__, | |
142 | formatter_class=argparse.RawDescriptionHelpFormatter) | |
143 | parser.add_argument('-b', '--branch', | |
be550c8e | 144 | help='Switch branches (use "main" to get to ToT)') |
6c6826b7 MF |
145 | parser.add_argument('-r', '--ref', '--reference', default='~/chromiumos/', |
146 | help='Patch to reference repo (default: %(default)s)') | |
147 | parser.add_argument('-g', '--group', | |
148 | help='Manifest group to use (e.g. "minilayout")') | |
149 | parser.add_argument('-m', '--manifest', | |
150 | help='Manifest file name to use (e.g. "full.xml")') | |
151 | parser.add_argument('-e', '--email', default='vapier@chromium.org', | |
152 | help='E-mail address to force (default: %(default)s)') | |
153 | parser.add_argument('action', nargs='?', | |
154 | choices={'depot_tools', 'dt', 'int', 'ext'}, | |
155 | help='What to do!') | |
156 | return parser | |
157 | ||
158 | ||
159 | def main(argv): | |
160 | """The main func.""" | |
161 | parser = get_parser() | |
162 | opts = parser.parse_args(argv) | |
163 | if opts.manifest: | |
164 | if '/' in opts.manifest: | |
165 | parser.error('manifest should be basename like "full.xml"') | |
166 | if opts.manifest.endswith('.xml'): | |
167 | opts.manifest = opts.manifest[:-4] | |
168 | opts.manifest += '.xml' | |
169 | if opts.ref: | |
170 | opts.ref = os.path.expanduser(opts.ref) | |
171 | ||
172 | if opts.action in {'depot_tools', 'dt'}: | |
173 | return clone_depot_tools() | |
174 | else: | |
175 | return init_repo(opts) | |
176 | ||
177 | ||
178 | if __name__ == '__main__': | |
179 | sys.exit(main(sys.argv[1:])) |