2 # -*- coding: utf-8 -*-
4 """Wrapper for syncing CrOS code.
7 depot_tools clone depot_tools tree
8 int switch to internal tree
9 ext switch to external tree
11 Operates on the repo in the cwd.
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'
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)
32 assert 'stdout' not in kwargs
and 'stderr' not in kwargs
33 kwargs
['stdout'] = subprocess
.PIPE
34 kwargs
['stderr'] = subprocess
.PIPE
36 print(kwargs
.get('cwd', os
.getcwd()))
38 return subprocess
.run(cmd
, **kwargs
)
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()]
47 for branch
in branches
:
48 if branch
.lower() == opts
.branch
.lower():
51 elif fnmatch
.fnmatch(branch
.lower(), f
'*{opts.branch.lower()}*'):
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
)
58 print(f
'error: too many branches match {opts.branch}:\n{" ".join(sorted(ret))}',
61 print(f
'Expanded branch {opts.branch} into {ret[0]}')
65 def get_repo_topdir(opts
):
66 """Find the top dir of this repo client checkout."""
69 rdir
= os
.path
.join(topdir
, '.repo')
70 if os
.path
.exists(rdir
):
72 topdir
= os
.path
.dirname(topdir
)
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')
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()
87 current_email
= gcfg(os
.path
.join(rdir
, 'manifests.git'))
88 if current_email
== opts
.email
:
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
)
99 """Initialize CrOS checkout."""
100 cmd
= ['repo', 'init', '-c']
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
]
109 if opts
.ref
and os
.path
.realpath(opts
.ref
) != os
.path
.realpath(get_repo_topdir(opts
)):
110 cmd
+= ['--reference', opts
.ref
]
113 cmd
+= ['-m', opts
.manifest
]
116 cmd
+= ['-g', opts
.group
]
119 branch
= expand_branch(opts
)
120 cmd
+= ['-b', branch
]
124 return ret
.returncode
128 print('\ncros-repo: all done')
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
139 """Get command line parser."""
140 parser
= argparse
.ArgumentParser(
142 formatter_class
=argparse
.RawDescriptionHelpFormatter
)
143 parser
.add_argument('-b', '--branch',
144 help='Switch branches (use "main" to get to ToT)')
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'},
161 parser
= get_parser()
162 opts
= parser
.parse_args(argv
)
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'
170 opts
.ref
= os
.path
.expanduser(opts
.ref
)
172 if opts
.action
in {'depot_tools', 'dt'}:
173 return clone_depot_tools()
175 return init_repo(opts
)
178 if __name__
== '__main__':
179 sys
.exit(main(sys
.argv
[1:]))