blob: 8ed147dfdb944d2c41e1d5fc06b95e8c050dd0bd [file] [log] [blame]
David Pursehouse8898e2f2012-11-14 07:51:03 +09001#!/usr/bin/env python
Mike Frysingerf6013762019-06-13 02:30:51 -04002# -*- coding:utf-8 -*-
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07003
Mike Frysinger87fb5a12019-06-13 01:54:46 -04004"""Repo launcher.
5
6This is a standalone tool that people may copy to anywhere in their system.
7It is used to get an initial repo client checkout, and after that it runs the
8copy of repo in the checkout.
9"""
10
Mike Frysingerc92ce5c2019-06-13 01:14:23 -040011from __future__ import print_function
12
Mark E. Hamilton4088eb42016-02-10 10:44:30 -070013# repo default configuration
14#
Mark E. Hamilton55536282016-02-03 15:49:43 -070015import os
16REPO_URL = os.environ.get('REPO_URL', None)
17if not REPO_URL:
18 REPO_URL = 'https://gerrit.googlesource.com/git-repo'
David Pursehouse8f62fb72012-11-14 12:09:38 +090019REPO_REV = 'stable'
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070020
21# Copyright (C) 2008 Google Inc.
22#
23# Licensed under the Apache License, Version 2.0 (the "License");
24# you may not use this file except in compliance with the License.
25# You may obtain a copy of the License at
26#
27# http://www.apache.org/licenses/LICENSE-2.0
28#
29# Unless required by applicable law or agreed to in writing, software
30# distributed under the License is distributed on an "AS IS" BASIS,
31# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32# See the License for the specific language governing permissions and
33# limitations under the License.
34
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070035# increment this whenever we make important changes to this script
Ereth McKnight-MacNeil12ee5442018-12-19 21:28:35 -080036VERSION = (1, 25)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070037
38# increment this if the MAINTAINER_KEYS block is modified
Conley Owensbc030842013-07-01 11:05:32 -070039KEYRING_VERSION = (1, 2)
Mike Frysingere4433652016-09-13 18:06:07 -040040
41# Each individual key entry is created by using:
42# gpg --armor --export keyid
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070043MAINTAINER_KEYS = """
44
45 Repo Maintainer <repo@android.kernel.org>
46-----BEGIN PGP PUBLIC KEY BLOCK-----
47Version: GnuPG v1.4.2.2 (GNU/Linux)
48
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
84=CMiZ
85-----END PGP PUBLIC KEY BLOCK-----
Conley Owens55e4d462012-10-01 16:12:28 -070086
87 Conley Owens <cco3@android.com>
88-----BEGIN PGP PUBLIC KEY BLOCK-----
89Version: GnuPG v1.4.11 (GNU/Linux)
90
Conley Owensbc030842013-07-01 11:05:32 -070091mQENBFHRvc8BCADFg45Xx/y6QDC+T7Y/gGc7vx0ww7qfOwIKlAZ9xG3qKunMxo+S
92hPCnzEl3cq+6I1Ww/ndop/HB3N3toPXRCoN8Vs4/Hc7by+SnaLFnacrm+tV5/OgT
93V37Lzt8lhay1Kl+YfpFwHYYpIEBLFV9knyfRXS/428W2qhdzYfvB15/AasRmwmor
94py4NIzSs8UD/SPr1ihqNCdZM76+MQyN5HMYXW/ALZXUFG0pwluHFA7hrfPG74i8C
95zMiP7qvMWIl/r/jtzHioH1dRKgbod+LZsrDJ8mBaqsZaDmNJMhss9g76XvfMyLra
969DI9/iFuBpGzeqBv0hwOGQspLRrEoyTeR6n1ABEBAAG0H0NvbmxleSBPd2VucyA8
97Y2NvM0BhbmRyb2lkLmNvbT6JATgEEwECACIFAlHRvc8CGwMGCwkIBwMCBhUIAgkK
98CwQWAgMBAh4BAheAAAoJEGe35EhpKzgsP6AIAJKJmNtn4l7hkYHKHFSo3egb6RjQ
99zEIP3MFTcu8HFX1kF1ZFbrp7xqurLaE53kEkKuAAvjJDAgI8mcZHP1JyplubqjQA
100xvv84gK+OGP3Xk+QK1ZjUQSbjOpjEiSZpRhWcHci3dgOUH4blJfByHw25hlgHowd
101a/2PrNKZVcJ92YienaxxGjcXEUcd0uYEG2+rwllQigFcnMFDhr9B71MfalRHjFKE
102fmdoypqLrri61YBc59P88Rw2/WUpTQjgNubSqa3A2+CKdaRyaRw+2fdF4TdR0h8W
103zbg+lbaPtJHsV+3mJC7fq26MiJDRJa5ZztpMn8su20gbLgi2ShBOaHAYDDi5AQ0E
104UdG9zwEIAMoOBq+QLNozAhxOOl5GL3StTStGRgPRXINfmViTsihrqGCWBBUfXlUE
105OytC0mYcrDUQev/8ToVoyqw+iGSwDkcSXkrEUCKFtHV/GECWtk1keyHgR10YKI1R
106mquSXoubWGqPeG1PAI74XWaRx8UrL8uCXUtmD8Q5J7mDjKR5NpxaXrwlA0bKsf2E
107Gp9tu1kKauuToZhWHMRMqYSOGikQJwWSFYKT1KdNcOXLQF6+bfoJ6sjVYdwfmNQL
108Ixn8QVhoTDedcqClSWB17VDEFDFa7MmqXZz2qtM3X1R/MUMHqPtegQzBGNhRdnI2
109V45+1Nnx/uuCxDbeI4RbHzujnxDiq70AEQEAAYkBHwQYAQIACQUCUdG9zwIbDAAK
110CRBnt+RIaSs4LNVeB/0Y2pZ8I7gAAcEM0Xw8drr4omg2fUoK1J33ozlA/RxeA/lJ
111I3KnyCDTpXuIeBKPGkdL8uMATC9Z8DnBBajRlftNDVZS3Hz4G09G9QpMojvJkFJV
112By+01Flw/X+eeN8NpqSuLV4W+AjEO8at/VvgKr1AFvBRdZ7GkpI1o6DgPe7ZqX+1
113dzQZt3e13W0rVBb/bUgx9iSLoeWP3aq/k+/GRGOR+S6F6BBSl0SQ2EF2+dIywb1x
114JuinEP+AwLAUZ1Bsx9ISC0Agpk2VeHXPL3FGhroEmoMvBzO0kTFGyoeT7PR/BfKv
115+H/g3HsL2LOB9uoIm8/5p2TTU5ttYCXMHhQZ81AY
116=AUp4
Conley Owens55e4d462012-10-01 16:12:28 -0700117-----END PGP PUBLIC KEY BLOCK-----
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700118"""
119
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700120GIT = 'git' # our git command
121MIN_GIT_VERSION = (1, 7, 2) # minimum supported git version
122repodir = '.repo' # name of repo's private directory
123S_repo = 'repo' # special repo repository
124S_manifests = 'manifests' # special manifest repository
125REPO_MAIN = S_repo + '/main.py' # main script
Eli Ribbled4b13c22018-12-18 21:21:12 -0800126MIN_PYTHON_VERSION = (2, 7) # minimum supported python version
Simran Basi8ce50412015-08-28 14:25:44 -0700127GITC_CONFIG_FILE = '/gitc/.config'
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700128GITC_FS_ROOT_DIR = '/gitc/manifest-rw/'
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700129
130
Mike Frysinger6db1b9e2019-07-10 15:32:36 -0400131import collections
David Jamesbf79c662013-12-26 14:20:13 -0800132import errno
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700133import optparse
Renaud Paquay35d22212016-11-01 11:24:52 -0700134import platform
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700135import re
Mitchel Humpheryseb5acc92014-03-12 10:48:15 -0700136import shutil
Sarah Owens60798a32012-10-25 17:53:09 -0700137import stat
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700138import subprocess
139import sys
David Pursehouse59bbb582013-05-17 10:49:33 +0900140
141if sys.version_info[0] == 3:
Sarah Owens1f7627f2012-10-31 09:21:55 -0700142 import urllib.request
143 import urllib.error
144else:
Sarah Owens1f7627f2012-10-31 09:21:55 -0700145 import imp
David Pursehouse59bbb582013-05-17 10:49:33 +0900146 import urllib2
Sarah Owens1f7627f2012-10-31 09:21:55 -0700147 urllib = imp.new_module('urllib')
148 urllib.request = urllib2
149 urllib.error = urllib2
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700150
Conley Owens5e0ee142013-09-26 15:50:49 -0700151
Chirayu Desai51813df2013-04-16 19:36:09 +0530152# Python version check
153ver = sys.version_info
Chirayu Desai51813df2013-04-16 19:36:09 +0530154if (ver[0], ver[1]) < MIN_PYTHON_VERSION:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400155 print('error: Python version {} unsupported.\n'
156 'Please use Python {}.{} instead.'.format(
157 sys.version.split(' ')[0],
158 MIN_PYTHON_VERSION[0],
159 MIN_PYTHON_VERSION[1],
160 ), file=sys.stderr)
Chirayu Desai51813df2013-04-16 19:36:09 +0530161 sys.exit(1)
162
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700163home_dot_repo = os.path.expanduser('~/.repoconfig')
164gpg_dir = os.path.join(home_dot_repo, 'gnupg')
165
166extra_args = []
167init_optparse = optparse.OptionParser(usage="repo init -u url [options]")
168
169# Logging
170group = init_optparse.add_option_group('Logging options')
171group.add_option('-q', '--quiet',
172 dest="quiet", action="store_true", default=False,
173 help="be quiet")
174
175# Manifest
176group = init_optparse.add_option_group('Manifest options')
177group.add_option('-u', '--manifest-url',
178 dest='manifest_url',
179 help='manifest repository location', metavar='URL')
180group.add_option('-b', '--manifest-branch',
181 dest='manifest_branch',
182 help='manifest branch or revision', metavar='REVISION')
183group.add_option('-m', '--manifest-name',
184 dest='manifest_name',
185 help='initial manifest file', metavar='NAME.xml')
Ereth McKnight-MacNeil12ee5442018-12-19 21:28:35 -0800186group.add_option('--current-branch',
Naseer Ahmedf4dda9a2016-12-01 18:49:54 -0500187 dest='current_branch_only', action='store_true',
188 help='fetch only current manifest branch from server')
Shawn O. Pearcee284ad12008-11-04 07:37:10 -0800189group.add_option('--mirror',
190 dest='mirror', action='store_true',
David Pursehouse3794a782012-11-15 06:17:30 +0900191 help='create a replica of the remote repositories '
192 'rather than a client working directory')
Shawn O. Pearce88443382010-10-08 10:02:09 +0200193group.add_option('--reference',
194 dest='reference',
195 help='location of mirror directory', metavar='DIR')
Nikolai Merinov09f0abb2018-10-19 15:07:05 +0500196group.add_option('--dissociate',
197 dest='dissociate', action='store_true',
198 help='dissociate from reference mirrors after clone')
Doug Anderson49cd59b2011-06-13 21:42:06 -0700199group.add_option('--depth', type='int', default=None,
200 dest='depth',
201 help='create a shallow clone with given depth; see git clone')
Julien Campergue335f5ef2013-10-16 11:02:35 +0200202group.add_option('--archive',
203 dest='archive', action='store_true',
204 help='checkout an archive instead of a git repository for '
205 'each project. See git archive.')
Martin Kellye4e94d22017-03-21 16:05:12 -0700206group.add_option('--submodules',
207 dest='submodules', action='store_true',
208 help='sync any submodules associated with the manifest repo')
Colin Cross5acde752012-03-28 20:15:45 -0700209group.add_option('-g', '--groups',
Conley Owens971de8e2012-04-16 10:36:08 -0700210 dest='groups', default='default',
David Holmer0a1c6a12012-11-14 19:19:00 -0500211 help='restrict manifest projects to ones with specified '
212 'group(s) [default|all|G1,G2,G3|G4,-G5,-G6]',
Colin Cross5acde752012-03-28 20:15:45 -0700213 metavar='GROUP')
Conley Owensd21720d2012-04-16 11:02:21 -0700214group.add_option('-p', '--platform',
215 dest='platform', default="auto",
Conley Owensc9129d92012-10-01 16:12:28 -0700216 help='restrict manifest projects to ones with a specified '
Conley Owensd21720d2012-04-16 11:02:21 -0700217 'platform group [auto|all|none|linux|darwin|...]',
218 metavar='PLATFORM')
Hu xiuyun9711a982015-12-11 11:16:41 +0800219group.add_option('--no-clone-bundle',
220 dest='no_clone_bundle', action='store_true',
221 help='disable use of /clone.bundle on HTTP/HTTPS')
Naseer Ahmedf4dda9a2016-12-01 18:49:54 -0500222group.add_option('--no-tags',
223 dest='no_tags', action='store_true',
224 help="don't fetch tags in the manifest")
Doug Anderson49cd59b2011-06-13 21:42:06 -0700225
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700226
227# Tool
Shawn O. Pearcefd89b672009-04-18 11:28:57 -0700228group = init_optparse.add_option_group('repo Version options')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700229group.add_option('--repo-url',
230 dest='repo_url',
231 help='repo repository location', metavar='URL')
232group.add_option('--repo-branch',
233 dest='repo_branch',
234 help='repo branch or revision', metavar='REVISION')
235group.add_option('--no-repo-verify',
236 dest='no_repo_verify', action='store_true',
237 help='do not verify repo source code')
238
Victor Boivie841be342011-04-05 11:31:10 +0200239# Other
240group = init_optparse.add_option_group('Other options')
241group.add_option('--config-name',
242 dest='config_name', action="store_true", default=False,
243 help='Always prompt for name/e-mail')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700244
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700245
246def _GitcInitOptions(init_optparse_arg):
247 init_optparse_arg.set_usage("repo gitc-init -u url -c client [options]")
248 g = init_optparse_arg.add_option_group('GITC options')
Simran Basi1efc2b42015-08-05 15:04:22 -0700249 g.add_option('-f', '--manifest-file',
250 dest='manifest_file',
251 help='Optional manifest file to use for this GITC client.')
252 g.add_option('-c', '--gitc-client',
253 dest='gitc_client',
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700254 help='The name of the gitc_client instance to create or modify.')
Simran Basi1efc2b42015-08-05 15:04:22 -0700255
Simran Basi8ce50412015-08-28 14:25:44 -0700256_gitc_manifest_dir = None
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700257
258
Simran Basi8ce50412015-08-28 14:25:44 -0700259def get_gitc_manifest_dir():
260 global _gitc_manifest_dir
261 if _gitc_manifest_dir is None:
Dan Willemsen2487cb72015-08-31 15:45:06 -0700262 _gitc_manifest_dir = ''
Simran Basi8ce50412015-08-28 14:25:44 -0700263 try:
264 with open(GITC_CONFIG_FILE, 'r') as gitc_config:
265 for line in gitc_config:
266 match = re.match('gitc_dir=(?P<gitc_manifest_dir>.*)', line)
267 if match:
268 _gitc_manifest_dir = match.group('gitc_manifest_dir')
269 except IOError:
Dan Willemsen2487cb72015-08-31 15:45:06 -0700270 pass
Simran Basi8ce50412015-08-28 14:25:44 -0700271 return _gitc_manifest_dir
272
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700273
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700274def gitc_parse_clientdir(gitc_fs_path):
275 """Parse a path in the GITC FS and return its client name.
276
277 @param gitc_fs_path: A subdirectory path within the GITC_FS_ROOT_DIR.
278
279 @returns: The GITC client name
280 """
281 if gitc_fs_path == GITC_FS_ROOT_DIR:
282 return None
283 if not gitc_fs_path.startswith(GITC_FS_ROOT_DIR):
284 manifest_dir = get_gitc_manifest_dir()
285 if manifest_dir == '':
286 return None
287 if manifest_dir[-1] != '/':
288 manifest_dir += '/'
289 if gitc_fs_path == manifest_dir:
290 return None
291 if not gitc_fs_path.startswith(manifest_dir):
292 return None
293 return gitc_fs_path.split(manifest_dir)[1].split('/')[0]
294 return gitc_fs_path.split(GITC_FS_ROOT_DIR)[1].split('/')[0]
295
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700296
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700297class CloneFailure(Exception):
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700298
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700299 """Indicate the remote clone of repo itself failed.
300 """
301
302
Simran Basi1efc2b42015-08-05 15:04:22 -0700303def _Init(args, gitc_init=False):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700304 """Installs repo by cloning it over the network.
305 """
Simran Basi1efc2b42015-08-05 15:04:22 -0700306 if gitc_init:
307 _GitcInitOptions(init_optparse)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700308 opt, args = init_optparse.parse_args(args)
Xiaodong Xuae0a36c2012-01-31 11:10:09 +0800309 if args:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700310 init_optparse.print_usage()
311 sys.exit(1)
312
313 url = opt.repo_url
314 if not url:
315 url = REPO_URL
316 extra_args.append('--repo-url=%s' % url)
317
318 branch = opt.repo_branch
319 if not branch:
320 branch = REPO_REV
321 extra_args.append('--repo-branch=%s' % branch)
322
323 if branch.startswith('refs/heads/'):
324 branch = branch[len('refs/heads/'):]
325 if branch.startswith('refs/'):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400326 print("fatal: invalid branch name '%s'" % branch, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700327 raise CloneFailure()
328
David Jamesbf79c662013-12-26 14:20:13 -0800329 try:
Simran Basi1efc2b42015-08-05 15:04:22 -0700330 if gitc_init:
Simran Basi8ce50412015-08-28 14:25:44 -0700331 gitc_manifest_dir = get_gitc_manifest_dir()
332 if not gitc_manifest_dir:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400333 print('fatal: GITC filesystem is not available. Exiting...',
334 file=sys.stderr)
Simran Basi8ce50412015-08-28 14:25:44 -0700335 sys.exit(1)
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700336 gitc_client = opt.gitc_client
337 if not gitc_client:
338 gitc_client = gitc_parse_clientdir(os.getcwd())
339 if not gitc_client:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400340 print('fatal: GITC client (-c) is required.', file=sys.stderr)
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700341 sys.exit(1)
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700342 client_dir = os.path.join(gitc_manifest_dir, gitc_client)
Simran Basi1efc2b42015-08-05 15:04:22 -0700343 if not os.path.exists(client_dir):
344 os.makedirs(client_dir)
345 os.chdir(client_dir)
346 if os.path.exists(repodir):
347 # This GITC Client has already initialized repo so continue.
348 return
349
David Jamesbf79c662013-12-26 14:20:13 -0800350 os.mkdir(repodir)
351 except OSError as e:
352 if e.errno != errno.EEXIST:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400353 print('fatal: cannot make %s directory: %s'
354 % (repodir, e.strerror), file=sys.stderr)
David Pursehouse3794a782012-11-15 06:17:30 +0900355 # Don't raise CloneFailure; that would delete the
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700356 # name. Instead exit immediately.
357 #
358 sys.exit(1)
359
360 _CheckGitVersion()
361 try:
Conley Owensc9129d92012-10-01 16:12:28 -0700362 if NeedSetupGnuPG():
363 can_verify = SetupGnuPG(opt.quiet)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700364 else:
365 can_verify = True
366
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700367 dst = os.path.abspath(os.path.join(repodir, S_repo))
Hu xiuyun9711a982015-12-11 11:16:41 +0800368 _Clone(url, dst, opt.quiet, not opt.no_clone_bundle)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700369
370 if can_verify and not opt.no_repo_verify:
371 rev = _Verify(dst, branch, opt.quiet)
372 else:
373 rev = 'refs/remotes/origin/%s^0' % branch
374
375 _Checkout(dst, branch, rev, opt.quiet)
Sebastian Schuberth993dcac2018-07-13 10:25:52 +0200376
377 if not os.path.isfile(os.path.join(dst, 'repo')):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400378 print("warning: '%s' does not look like a git-repo repository, is "
379 "REPO_URL set correctly?" % url, file=sys.stderr)
Sebastian Schuberth993dcac2018-07-13 10:25:52 +0200380
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700381 except CloneFailure:
382 if opt.quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400383 print('fatal: repo init failed; run without --quiet to see why',
384 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700385 raise
386
387
Mike Frysinger6db1b9e2019-07-10 15:32:36 -0400388# The git version info broken down into components for easy analysis.
389# Similar to Python's sys.version_info.
390GitVersion = collections.namedtuple(
391 'GitVersion', ('major', 'minor', 'micro', 'full'))
392
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400393def ParseGitVersion(ver_str=None):
394 if ver_str is None:
395 # Load the version ourselves.
396 ver_str = _GetGitVersion()
397
Conley Owensff0a3c82014-01-30 14:46:03 -0800398 if not ver_str.startswith('git version '):
399 return None
400
Mike Frysinger6db1b9e2019-07-10 15:32:36 -0400401 full_version = ver_str[len('git version '):].strip()
402 num_ver_str = full_version.split('-')[0]
Conley Owensff0a3c82014-01-30 14:46:03 -0800403 to_tuple = []
404 for num_str in num_ver_str.split('.')[:3]:
405 if num_str.isdigit():
406 to_tuple.append(int(num_str))
407 else:
408 to_tuple.append(0)
Mike Frysinger6db1b9e2019-07-10 15:32:36 -0400409 to_tuple.append(full_version)
410 return GitVersion(*to_tuple)
Conley Owensff0a3c82014-01-30 14:46:03 -0800411
412
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400413def _GetGitVersion():
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700414 cmd = [GIT, '--version']
Shawn O. Pearce4fd38ec2012-06-05 07:55:07 -0700415 try:
416 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700417 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400418 print(file=sys.stderr)
419 print("fatal: '%s' is not available" % GIT, file=sys.stderr)
420 print('fatal: %s' % e, file=sys.stderr)
421 print(file=sys.stderr)
422 print('Please make sure %s is installed and in your path.' % GIT,
423 file=sys.stderr)
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400424 raise
Shawn O. Pearce4fd38ec2012-06-05 07:55:07 -0700425
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700426 ver_str = proc.stdout.read().strip()
427 proc.stdout.close()
Shawn O. Pearce16191342008-10-28 08:33:34 -0700428 proc.wait()
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400429 return ver_str.decode('utf-8')
430
431
432def _CheckGitVersion():
433 try:
434 ver_act = ParseGitVersion()
435 except OSError:
436 raise CloneFailure()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700437
Conley Owensff0a3c82014-01-30 14:46:03 -0800438 if ver_act is None:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400439 print('error: "%s" unsupported' % ver_str, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700440 raise CloneFailure()
441
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700442 if ver_act < MIN_GIT_VERSION:
David Pursehouse685f0802012-11-14 08:34:39 +0900443 need = '.'.join(map(str, MIN_GIT_VERSION))
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400444 print('fatal: git %s or later required' % need, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700445 raise CloneFailure()
446
447
Conley Owensc9129d92012-10-01 16:12:28 -0700448def NeedSetupGnuPG():
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700449 if not os.path.isdir(home_dot_repo):
450 return True
451
452 kv = os.path.join(home_dot_repo, 'keyring-version')
453 if not os.path.exists(kv):
454 return True
455
456 kv = open(kv).read()
457 if not kv:
458 return True
459
David Pursehouse685f0802012-11-14 08:34:39 +0900460 kv = tuple(map(int, kv.split('.')))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700461 if kv < KEYRING_VERSION:
462 return True
463 return False
464
465
Conley Owensc9129d92012-10-01 16:12:28 -0700466def SetupGnuPG(quiet):
David Jamesbf79c662013-12-26 14:20:13 -0800467 try:
468 os.mkdir(home_dot_repo)
469 except OSError as e:
470 if e.errno != errno.EEXIST:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400471 print('fatal: cannot make %s directory: %s'
472 % (home_dot_repo, e.strerror), file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700473 sys.exit(1)
474
David Jamesbf79c662013-12-26 14:20:13 -0800475 try:
476 os.mkdir(gpg_dir, stat.S_IRWXU)
477 except OSError as e:
478 if e.errno != errno.EEXIST:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400479 print('fatal: cannot make %s directory: %s' % (gpg_dir, e.strerror),
480 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700481 sys.exit(1)
482
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800483 env = os.environ.copy()
Dāvis Mosāns631d0ec2016-07-16 21:11:11 +0300484 try:
485 env['GNUPGHOME'] = gpg_dir
486 except UnicodeEncodeError:
487 env['GNUPGHOME'] = gpg_dir.encode()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700488
489 cmd = ['gpg', '--import']
490 try:
491 proc = subprocess.Popen(cmd,
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700492 env=env,
493 stdin=subprocess.PIPE)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700494 except OSError as e:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700495 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400496 print('warning: gpg (GnuPG) is not available.', file=sys.stderr)
497 print('warning: Installing it is strongly encouraged.', file=sys.stderr)
498 print(file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700499 return False
500
501 proc.stdin.write(MAINTAINER_KEYS)
502 proc.stdin.close()
503
504 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400505 print('fatal: registering repo maintainer keys failed', file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700506 sys.exit(1)
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400507 print()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700508
509 fd = open(os.path.join(home_dot_repo, 'keyring-version'), 'w')
David Pursehouse685f0802012-11-14 08:34:39 +0900510 fd.write('.'.join(map(str, KEYRING_VERSION)) + '\n')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700511 fd.close()
512 return True
513
514
515def _SetConfig(local, name, value):
516 """Set a git configuration option to the specified value.
517 """
518 cmd = [GIT, 'config', name, value]
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700519 if subprocess.Popen(cmd, cwd=local).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700520 raise CloneFailure()
521
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700522
523def _InitHttp():
524 handlers = []
525
Sarah Owens1f7627f2012-10-31 09:21:55 -0700526 mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700527 try:
528 import netrc
529 n = netrc.netrc()
530 for host in n.hosts:
531 p = n.hosts[host]
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700532 mgr.add_password(p[1], 'http://%s/' % host, p[0], p[2])
Xiaodong Xuae0a36c2012-01-31 11:10:09 +0800533 mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2])
David Pursehouse65b0ba52018-06-24 16:21:51 +0900534 except:
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700535 pass
Sarah Owens1f7627f2012-10-31 09:21:55 -0700536 handlers.append(urllib.request.HTTPBasicAuthHandler(mgr))
537 handlers.append(urllib.request.HTTPDigestAuthHandler(mgr))
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700538
539 if 'http_proxy' in os.environ:
540 url = os.environ['http_proxy']
Sarah Owens1f7627f2012-10-31 09:21:55 -0700541 handlers.append(urllib.request.ProxyHandler({'http': url, 'https': url}))
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700542 if 'REPO_CURL_VERBOSE' in os.environ:
Sarah Owens1f7627f2012-10-31 09:21:55 -0700543 handlers.append(urllib.request.HTTPHandler(debuglevel=1))
544 handlers.append(urllib.request.HTTPSHandler(debuglevel=1))
545 urllib.request.install_opener(urllib.request.build_opener(*handlers))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700546
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700547
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700548def _Fetch(url, local, src, quiet):
549 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400550 print('Get %s' % url, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700551
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700552 cmd = [GIT, 'fetch']
553 if quiet:
554 cmd.append('--quiet')
555 err = subprocess.PIPE
556 else:
557 err = None
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700558 cmd.append(src)
559 cmd.append('+refs/heads/*:refs/remotes/origin/*')
Xin Li6e538442018-12-10 11:33:16 -0800560 cmd.append('+refs/tags/*:refs/tags/*')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700561
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700562 proc = subprocess.Popen(cmd, cwd=local, stderr=err)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700563 if err:
564 proc.stderr.read()
565 proc.stderr.close()
566 if proc.wait() != 0:
567 raise CloneFailure()
568
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700569
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700570def _DownloadBundle(url, local, quiet):
571 if not url.endswith('/'):
572 url += '/'
573 url += 'clone.bundle'
574
575 proc = subprocess.Popen(
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700576 [GIT, 'config', '--get-regexp', 'url.*.insteadof'],
577 cwd=local,
578 stdout=subprocess.PIPE)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700579 for line in proc.stdout:
580 m = re.compile(r'^url\.(.*)\.insteadof (.*)$').match(line)
581 if m:
582 new_url = m.group(1)
583 old_url = m.group(2)
584 if url.startswith(old_url):
585 url = new_url + url[len(old_url):]
586 break
587 proc.stdout.close()
588 proc.wait()
589
590 if not url.startswith('http:') and not url.startswith('https:'):
591 return False
592
593 dest = open(os.path.join(local, '.git', 'clone.bundle'), 'w+b')
594 try:
595 try:
Sarah Owens1f7627f2012-10-31 09:21:55 -0700596 r = urllib.request.urlopen(url)
597 except urllib.error.HTTPError as e:
John Törnblomd3ddcdb2015-08-12 20:12:51 +0200598 if e.code in [401, 403, 404, 501]:
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700599 return False
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400600 print('fatal: Cannot get %s' % url, file=sys.stderr)
601 print('fatal: HTTP error %s' % e.code, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700602 raise CloneFailure()
Sarah Owens1f7627f2012-10-31 09:21:55 -0700603 except urllib.error.URLError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400604 print('fatal: Cannot get %s' % url, file=sys.stderr)
605 print('fatal: error %s' % e.reason, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700606 raise CloneFailure()
607 try:
608 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400609 print('Get %s' % url, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700610 while True:
611 buf = r.read(8192)
Mike Frysinger1b9adab2019-07-04 17:54:54 -0400612 if not buf:
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700613 return True
614 dest.write(buf)
615 finally:
616 r.close()
617 finally:
618 dest.close()
619
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700620
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700621def _ImportBundle(local):
622 path = os.path.join(local, '.git', 'clone.bundle')
623 try:
624 _Fetch(local, local, path, True)
625 finally:
626 os.remove(path)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700627
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700628
Hu xiuyun9711a982015-12-11 11:16:41 +0800629def _Clone(url, local, quiet, clone_bundle):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700630 """Clones a git repository to a new subdirectory of repodir
631 """
632 try:
633 os.mkdir(local)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700634 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400635 print('fatal: cannot make %s directory: %s' % (local, e.strerror),
636 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700637 raise CloneFailure()
638
639 cmd = [GIT, 'init', '--quiet']
640 try:
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700641 proc = subprocess.Popen(cmd, cwd=local)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700642 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400643 print(file=sys.stderr)
644 print("fatal: '%s' is not available" % GIT, file=sys.stderr)
645 print('fatal: %s' % e, file=sys.stderr)
646 print(file=sys.stderr)
647 print('Please make sure %s is installed and in your path.' % GIT,
648 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700649 raise CloneFailure()
650 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400651 print('fatal: could not create %s' % local, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700652 raise CloneFailure()
653
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700654 _InitHttp()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700655 _SetConfig(local, 'remote.origin.url', url)
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700656 _SetConfig(local,
657 'remote.origin.fetch',
658 '+refs/heads/*:refs/remotes/origin/*')
Hu xiuyun9711a982015-12-11 11:16:41 +0800659 if clone_bundle and _DownloadBundle(url, local, quiet):
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700660 _ImportBundle(local)
Dan Willemsenfee390e2015-09-02 12:36:30 -0700661 _Fetch(url, local, 'origin', quiet)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700662
663
664def _Verify(cwd, branch, quiet):
665 """Verify the branch has been signed by a tag.
666 """
667 cmd = [GIT, 'describe', 'origin/%s' % branch]
668 proc = subprocess.Popen(cmd,
669 stdout=subprocess.PIPE,
670 stderr=subprocess.PIPE,
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700671 cwd=cwd)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700672 cur = proc.stdout.read().strip()
673 proc.stdout.close()
674
675 proc.stderr.read()
676 proc.stderr.close()
677
678 if proc.wait() != 0 or not cur:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400679 print(file=sys.stderr)
680 print("fatal: branch '%s' has not been signed" % branch, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700681 raise CloneFailure()
682
683 m = re.compile(r'^(.*)-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur)
684 if m:
685 cur = m.group(1)
686 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400687 print(file=sys.stderr)
688 print("info: Ignoring branch '%s'; using tagged release '%s'"
689 % (branch, cur), file=sys.stderr)
690 print(file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700691
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800692 env = os.environ.copy()
Dāvis Mosāns631d0ec2016-07-16 21:11:11 +0300693 try:
694 env['GNUPGHOME'] = gpg_dir
695 except UnicodeEncodeError:
696 env['GNUPGHOME'] = gpg_dir.encode()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700697
698 cmd = [GIT, 'tag', '-v', cur]
699 proc = subprocess.Popen(cmd,
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700700 stdout=subprocess.PIPE,
701 stderr=subprocess.PIPE,
702 cwd=cwd,
703 env=env)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700704 out = proc.stdout.read()
705 proc.stdout.close()
706
707 err = proc.stderr.read()
708 proc.stderr.close()
709
710 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400711 print(file=sys.stderr)
712 print(out, file=sys.stderr)
713 print(err, file=sys.stderr)
714 print(file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700715 raise CloneFailure()
716 return '%s^0' % cur
717
718
719def _Checkout(cwd, branch, rev, quiet):
720 """Checkout an upstream branch into the repository and track it.
721 """
722 cmd = [GIT, 'update-ref', 'refs/heads/default', rev]
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700723 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700724 raise CloneFailure()
725
726 _SetConfig(cwd, 'branch.default.remote', 'origin')
727 _SetConfig(cwd, 'branch.default.merge', 'refs/heads/%s' % branch)
728
729 cmd = [GIT, 'symbolic-ref', 'HEAD', 'refs/heads/default']
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700730 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700731 raise CloneFailure()
732
733 cmd = [GIT, 'read-tree', '--reset', '-u']
734 if not quiet:
735 cmd.append('-v')
736 cmd.append('HEAD')
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700737 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700738 raise CloneFailure()
739
740
741def _FindRepo():
742 """Look for a repo installation, starting at the current directory.
743 """
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200744 curdir = os.getcwd()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700745 repo = None
746
Anthony Newnamdf14a702011-01-09 17:31:57 -0800747 olddir = None
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200748 while curdir != '/' \
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700749 and curdir != olddir \
750 and not repo:
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200751 repo = os.path.join(curdir, repodir, REPO_MAIN)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700752 if not os.path.isfile(repo):
753 repo = None
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200754 olddir = curdir
755 curdir = os.path.dirname(curdir)
756 return (repo, os.path.join(curdir, repodir))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700757
758
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700759class _Options(object):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700760 help = False
761
762
763def _ParseArguments(args):
764 cmd = None
765 opt = _Options()
766 arg = []
767
Sarah Owensa6053d52012-11-01 13:36:50 -0700768 for i in range(len(args)):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700769 a = args[i]
770 if a == '-h' or a == '--help':
771 opt.help = True
772
773 elif not a.startswith('-'):
774 cmd = a
775 arg = args[i + 1:]
776 break
777 return cmd, opt, arg
778
779
780def _Usage():
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700781 gitc_usage = ""
782 if get_gitc_manifest_dir():
783 gitc_usage = " gitc-init Initialize a GITC Client.\n"
784
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400785 print(
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700786 """usage: repo COMMAND [ARGS]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700787
788repo is not yet installed. Use "repo init" to install it here.
789
790The most commonly used repo commands are:
791
792 init Install repo in the current working directory
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700793""" + gitc_usage +
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700794 """ help Display detailed help on a command
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700795
796For access to the full online help, install repo ("repo init").
Mike Frysinger35159ab2019-06-13 00:07:13 -0400797""")
798 sys.exit(0)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700799
800
801def _Help(args):
802 if args:
803 if args[0] == 'init':
804 init_optparse.print_help()
Trond Norbyed3fd5372011-01-03 11:35:15 +0100805 sys.exit(0)
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700806 elif args[0] == 'gitc-init':
807 _GitcInitOptions(init_optparse)
808 init_optparse.print_help()
809 sys.exit(0)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700810 else:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400811 print("error: '%s' is not a bootstrap command.\n"
812 ' For access to online help, install repo ("repo init").'
813 % args[0], file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700814 else:
815 _Usage()
816 sys.exit(1)
817
818
819def _NotInstalled():
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400820 print('error: repo is not installed. Use "repo init" to install it here.',
821 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700822 sys.exit(1)
823
824
825def _NoCommands(cmd):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400826 print("""error: command '%s' requires repo to be installed first.
827 Use "repo init" to install it here.""" % cmd, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700828 sys.exit(1)
829
830
831def _RunSelf(wrapper_path):
832 my_dir = os.path.dirname(wrapper_path)
833 my_main = os.path.join(my_dir, 'main.py')
834 my_git = os.path.join(my_dir, '.git')
835
836 if os.path.isfile(my_main) and os.path.isdir(my_git):
Shawn O. Pearcec8a300f2009-05-18 13:19:57 -0700837 for name in ['git_config.py',
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700838 'project.py',
839 'subcmds']:
840 if not os.path.exists(os.path.join(my_dir, name)):
841 return None, None
842 return my_main, my_git
843 return None, None
844
845
846def _SetDefaultsTo(gitdir):
847 global REPO_URL
848 global REPO_REV
849
850 REPO_URL = gitdir
851 proc = subprocess.Popen([GIT,
852 '--git-dir=%s' % gitdir,
853 'symbolic-ref',
854 'HEAD'],
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700855 stdout=subprocess.PIPE,
856 stderr=subprocess.PIPE)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700857 REPO_REV = proc.stdout.read().strip()
858 proc.stdout.close()
859
860 proc.stderr.read()
861 proc.stderr.close()
862
863 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400864 print('fatal: %s has no current branch' % gitdir, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700865 sys.exit(1)
866
867
868def main(orig_args):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700869 cmd, opt, args = _ParseArguments(orig_args)
870
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700871 repo_main, rel_repo_dir = None, None
872 # Don't use the local repo copy, make sure to switch to the gitc client first.
873 if cmd != 'gitc-init':
874 repo_main, rel_repo_dir = _FindRepo()
875
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700876 wrapper_path = os.path.abspath(__file__)
877 my_main, my_git = _RunSelf(wrapper_path)
878
Simran Basi8ce50412015-08-28 14:25:44 -0700879 cwd = os.getcwd()
Dan Willemsen2487cb72015-08-31 15:45:06 -0700880 if get_gitc_manifest_dir() and cwd.startswith(get_gitc_manifest_dir()):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400881 print('error: repo cannot be used in the GITC local manifest directory.'
882 '\nIf you want to work on this GITC client please rerun this '
883 'command from the corresponding client under /gitc/',
884 file=sys.stderr)
Simran Basi8ce50412015-08-28 14:25:44 -0700885 sys.exit(1)
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200886 if not repo_main:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700887 if opt.help:
888 _Usage()
889 if cmd == 'help':
890 _Help(args)
891 if not cmd:
892 _NotInstalled()
Simran Basi1efc2b42015-08-05 15:04:22 -0700893 if cmd == 'init' or cmd == 'gitc-init':
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700894 if my_git:
895 _SetDefaultsTo(my_git)
896 try:
Simran Basi1efc2b42015-08-05 15:04:22 -0700897 _Init(args, gitc_init=(cmd == 'gitc-init'))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700898 except CloneFailure:
Sebastian Schuberth27226e72016-10-28 14:27:43 +0200899 path = os.path.join(repodir, S_repo)
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400900 print("fatal: cloning the git-repo repository failed, will remove "
901 "'%s' " % path, file=sys.stderr)
Sebastian Schuberth27226e72016-10-28 14:27:43 +0200902 shutil.rmtree(path, ignore_errors=True)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700903 sys.exit(1)
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200904 repo_main, rel_repo_dir = _FindRepo()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700905 else:
906 _NoCommands(cmd)
907
908 if my_main:
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200909 repo_main = my_main
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700910
David Pursehouse685f0802012-11-14 08:34:39 +0900911 ver_str = '.'.join(map(str, VERSION))
anatoly techtonik3a2a59e2013-09-21 19:29:10 +0300912 me = [sys.executable, repo_main,
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200913 '--repo-dir=%s' % rel_repo_dir,
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700914 '--wrapper-version=%s' % ver_str,
915 '--wrapper-path=%s' % wrapper_path,
916 '--']
917 me.extend(orig_args)
918 me.extend(extra_args)
919 try:
Renaud Paquay35d22212016-11-01 11:24:52 -0700920 if platform.system() == "Windows":
921 sys.exit(subprocess.call(me))
922 else:
923 os.execv(sys.executable, me)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700924 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400925 print("fatal: unable to start %s" % repo_main, file=sys.stderr)
926 print("fatal: %s" % e, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700927 sys.exit(148)
928
929
930if __name__ == '__main__':
931 main(sys.argv[1:])