blob: 2f634d9e76efa3a51588615d6bb5cdc2e17fc25c [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
Mike Frysinger6be76332019-09-17 16:27:18 -040036VERSION = (1, 26)
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')
Xin Li745be2e2019-06-03 11:24:30 -0700202group.add_option('--partial-clone', action='store_true',
203 dest='partial_clone',
204 help='perform partial clone (https://git-scm.com/'
205 'docs/gitrepository-layout#_code_partialclone_code)')
206group.add_option('--clone-filter', action='store', default='blob:none',
207 dest='clone_filter',
208 help='filter for use with --partial-clone [default: %default]')
Julien Campergue335f5ef2013-10-16 11:02:35 +0200209group.add_option('--archive',
210 dest='archive', action='store_true',
211 help='checkout an archive instead of a git repository for '
212 'each project. See git archive.')
Martin Kellye4e94d22017-03-21 16:05:12 -0700213group.add_option('--submodules',
214 dest='submodules', action='store_true',
215 help='sync any submodules associated with the manifest repo')
Colin Cross5acde752012-03-28 20:15:45 -0700216group.add_option('-g', '--groups',
Conley Owens971de8e2012-04-16 10:36:08 -0700217 dest='groups', default='default',
David Holmer0a1c6a12012-11-14 19:19:00 -0500218 help='restrict manifest projects to ones with specified '
219 'group(s) [default|all|G1,G2,G3|G4,-G5,-G6]',
Colin Cross5acde752012-03-28 20:15:45 -0700220 metavar='GROUP')
Conley Owensd21720d2012-04-16 11:02:21 -0700221group.add_option('-p', '--platform',
222 dest='platform', default="auto",
Conley Owensc9129d92012-10-01 16:12:28 -0700223 help='restrict manifest projects to ones with a specified '
Conley Owensd21720d2012-04-16 11:02:21 -0700224 'platform group [auto|all|none|linux|darwin|...]',
225 metavar='PLATFORM')
Hu xiuyun9711a982015-12-11 11:16:41 +0800226group.add_option('--no-clone-bundle',
227 dest='no_clone_bundle', action='store_true',
228 help='disable use of /clone.bundle on HTTP/HTTPS')
Naseer Ahmedf4dda9a2016-12-01 18:49:54 -0500229group.add_option('--no-tags',
230 dest='no_tags', action='store_true',
231 help="don't fetch tags in the manifest")
Doug Anderson49cd59b2011-06-13 21:42:06 -0700232
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700233
234# Tool
Shawn O. Pearcefd89b672009-04-18 11:28:57 -0700235group = init_optparse.add_option_group('repo Version options')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700236group.add_option('--repo-url',
237 dest='repo_url',
238 help='repo repository location', metavar='URL')
239group.add_option('--repo-branch',
240 dest='repo_branch',
241 help='repo branch or revision', metavar='REVISION')
242group.add_option('--no-repo-verify',
243 dest='no_repo_verify', action='store_true',
244 help='do not verify repo source code')
245
Victor Boivie841be342011-04-05 11:31:10 +0200246# Other
247group = init_optparse.add_option_group('Other options')
248group.add_option('--config-name',
249 dest='config_name', action="store_true", default=False,
250 help='Always prompt for name/e-mail')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700251
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700252
253def _GitcInitOptions(init_optparse_arg):
254 init_optparse_arg.set_usage("repo gitc-init -u url -c client [options]")
255 g = init_optparse_arg.add_option_group('GITC options')
Simran Basi1efc2b42015-08-05 15:04:22 -0700256 g.add_option('-f', '--manifest-file',
257 dest='manifest_file',
258 help='Optional manifest file to use for this GITC client.')
259 g.add_option('-c', '--gitc-client',
260 dest='gitc_client',
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700261 help='The name of the gitc_client instance to create or modify.')
Simran Basi1efc2b42015-08-05 15:04:22 -0700262
Simran Basi8ce50412015-08-28 14:25:44 -0700263_gitc_manifest_dir = None
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700264
265
Simran Basi8ce50412015-08-28 14:25:44 -0700266def get_gitc_manifest_dir():
267 global _gitc_manifest_dir
268 if _gitc_manifest_dir is None:
Dan Willemsen2487cb72015-08-31 15:45:06 -0700269 _gitc_manifest_dir = ''
Simran Basi8ce50412015-08-28 14:25:44 -0700270 try:
271 with open(GITC_CONFIG_FILE, 'r') as gitc_config:
272 for line in gitc_config:
273 match = re.match('gitc_dir=(?P<gitc_manifest_dir>.*)', line)
274 if match:
275 _gitc_manifest_dir = match.group('gitc_manifest_dir')
276 except IOError:
Dan Willemsen2487cb72015-08-31 15:45:06 -0700277 pass
Simran Basi8ce50412015-08-28 14:25:44 -0700278 return _gitc_manifest_dir
279
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700280
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700281def gitc_parse_clientdir(gitc_fs_path):
282 """Parse a path in the GITC FS and return its client name.
283
284 @param gitc_fs_path: A subdirectory path within the GITC_FS_ROOT_DIR.
285
286 @returns: The GITC client name
287 """
288 if gitc_fs_path == GITC_FS_ROOT_DIR:
289 return None
290 if not gitc_fs_path.startswith(GITC_FS_ROOT_DIR):
291 manifest_dir = get_gitc_manifest_dir()
292 if manifest_dir == '':
293 return None
294 if manifest_dir[-1] != '/':
295 manifest_dir += '/'
296 if gitc_fs_path == manifest_dir:
297 return None
298 if not gitc_fs_path.startswith(manifest_dir):
299 return None
300 return gitc_fs_path.split(manifest_dir)[1].split('/')[0]
301 return gitc_fs_path.split(GITC_FS_ROOT_DIR)[1].split('/')[0]
302
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700303
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700304class CloneFailure(Exception):
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700305
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700306 """Indicate the remote clone of repo itself failed.
307 """
308
309
Simran Basi1efc2b42015-08-05 15:04:22 -0700310def _Init(args, gitc_init=False):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700311 """Installs repo by cloning it over the network.
312 """
Simran Basi1efc2b42015-08-05 15:04:22 -0700313 if gitc_init:
314 _GitcInitOptions(init_optparse)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700315 opt, args = init_optparse.parse_args(args)
Xiaodong Xuae0a36c2012-01-31 11:10:09 +0800316 if args:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700317 init_optparse.print_usage()
318 sys.exit(1)
319
320 url = opt.repo_url
321 if not url:
322 url = REPO_URL
323 extra_args.append('--repo-url=%s' % url)
324
325 branch = opt.repo_branch
326 if not branch:
327 branch = REPO_REV
328 extra_args.append('--repo-branch=%s' % branch)
329
330 if branch.startswith('refs/heads/'):
331 branch = branch[len('refs/heads/'):]
332 if branch.startswith('refs/'):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400333 print("fatal: invalid branch name '%s'" % branch, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700334 raise CloneFailure()
335
David Jamesbf79c662013-12-26 14:20:13 -0800336 try:
Simran Basi1efc2b42015-08-05 15:04:22 -0700337 if gitc_init:
Simran Basi8ce50412015-08-28 14:25:44 -0700338 gitc_manifest_dir = get_gitc_manifest_dir()
339 if not gitc_manifest_dir:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400340 print('fatal: GITC filesystem is not available. Exiting...',
341 file=sys.stderr)
Simran Basi8ce50412015-08-28 14:25:44 -0700342 sys.exit(1)
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700343 gitc_client = opt.gitc_client
344 if not gitc_client:
345 gitc_client = gitc_parse_clientdir(os.getcwd())
346 if not gitc_client:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400347 print('fatal: GITC client (-c) is required.', file=sys.stderr)
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700348 sys.exit(1)
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700349 client_dir = os.path.join(gitc_manifest_dir, gitc_client)
Simran Basi1efc2b42015-08-05 15:04:22 -0700350 if not os.path.exists(client_dir):
351 os.makedirs(client_dir)
352 os.chdir(client_dir)
353 if os.path.exists(repodir):
354 # This GITC Client has already initialized repo so continue.
355 return
356
David Jamesbf79c662013-12-26 14:20:13 -0800357 os.mkdir(repodir)
358 except OSError as e:
359 if e.errno != errno.EEXIST:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400360 print('fatal: cannot make %s directory: %s'
361 % (repodir, e.strerror), file=sys.stderr)
David Pursehouse3794a782012-11-15 06:17:30 +0900362 # Don't raise CloneFailure; that would delete the
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700363 # name. Instead exit immediately.
364 #
365 sys.exit(1)
366
367 _CheckGitVersion()
368 try:
Conley Owensc9129d92012-10-01 16:12:28 -0700369 if NeedSetupGnuPG():
370 can_verify = SetupGnuPG(opt.quiet)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700371 else:
372 can_verify = True
373
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700374 dst = os.path.abspath(os.path.join(repodir, S_repo))
Hu xiuyun9711a982015-12-11 11:16:41 +0800375 _Clone(url, dst, opt.quiet, not opt.no_clone_bundle)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700376
377 if can_verify and not opt.no_repo_verify:
378 rev = _Verify(dst, branch, opt.quiet)
379 else:
380 rev = 'refs/remotes/origin/%s^0' % branch
381
382 _Checkout(dst, branch, rev, opt.quiet)
Sebastian Schuberth993dcac2018-07-13 10:25:52 +0200383
384 if not os.path.isfile(os.path.join(dst, 'repo')):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400385 print("warning: '%s' does not look like a git-repo repository, is "
386 "REPO_URL set correctly?" % url, file=sys.stderr)
Sebastian Schuberth993dcac2018-07-13 10:25:52 +0200387
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700388 except CloneFailure:
389 if opt.quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400390 print('fatal: repo init failed; run without --quiet to see why',
391 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700392 raise
393
394
Mike Frysinger6db1b9e2019-07-10 15:32:36 -0400395# The git version info broken down into components for easy analysis.
396# Similar to Python's sys.version_info.
397GitVersion = collections.namedtuple(
398 'GitVersion', ('major', 'minor', 'micro', 'full'))
399
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400400def ParseGitVersion(ver_str=None):
401 if ver_str is None:
402 # Load the version ourselves.
403 ver_str = _GetGitVersion()
404
Conley Owensff0a3c82014-01-30 14:46:03 -0800405 if not ver_str.startswith('git version '):
406 return None
407
Mike Frysinger6db1b9e2019-07-10 15:32:36 -0400408 full_version = ver_str[len('git version '):].strip()
409 num_ver_str = full_version.split('-')[0]
Conley Owensff0a3c82014-01-30 14:46:03 -0800410 to_tuple = []
411 for num_str in num_ver_str.split('.')[:3]:
412 if num_str.isdigit():
413 to_tuple.append(int(num_str))
414 else:
415 to_tuple.append(0)
Mike Frysinger6db1b9e2019-07-10 15:32:36 -0400416 to_tuple.append(full_version)
417 return GitVersion(*to_tuple)
Conley Owensff0a3c82014-01-30 14:46:03 -0800418
419
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400420def _GetGitVersion():
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700421 cmd = [GIT, '--version']
Shawn O. Pearce4fd38ec2012-06-05 07:55:07 -0700422 try:
423 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700424 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400425 print(file=sys.stderr)
426 print("fatal: '%s' is not available" % GIT, file=sys.stderr)
427 print('fatal: %s' % e, file=sys.stderr)
428 print(file=sys.stderr)
429 print('Please make sure %s is installed and in your path.' % GIT,
430 file=sys.stderr)
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400431 raise
Shawn O. Pearce4fd38ec2012-06-05 07:55:07 -0700432
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700433 ver_str = proc.stdout.read().strip()
434 proc.stdout.close()
Shawn O. Pearce16191342008-10-28 08:33:34 -0700435 proc.wait()
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400436 return ver_str.decode('utf-8')
437
438
439def _CheckGitVersion():
440 try:
441 ver_act = ParseGitVersion()
442 except OSError:
443 raise CloneFailure()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700444
Conley Owensff0a3c82014-01-30 14:46:03 -0800445 if ver_act is None:
Mike Frysinger4c263b52019-09-11 04:04:16 -0400446 print('fatal: unable to detect git version', file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700447 raise CloneFailure()
448
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700449 if ver_act < MIN_GIT_VERSION:
David Pursehouse685f0802012-11-14 08:34:39 +0900450 need = '.'.join(map(str, MIN_GIT_VERSION))
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400451 print('fatal: git %s or later required' % need, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700452 raise CloneFailure()
453
454
Conley Owensc9129d92012-10-01 16:12:28 -0700455def NeedSetupGnuPG():
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700456 if not os.path.isdir(home_dot_repo):
457 return True
458
459 kv = os.path.join(home_dot_repo, 'keyring-version')
460 if not os.path.exists(kv):
461 return True
462
463 kv = open(kv).read()
464 if not kv:
465 return True
466
David Pursehouse685f0802012-11-14 08:34:39 +0900467 kv = tuple(map(int, kv.split('.')))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700468 if kv < KEYRING_VERSION:
469 return True
470 return False
471
472
Conley Owensc9129d92012-10-01 16:12:28 -0700473def SetupGnuPG(quiet):
David Jamesbf79c662013-12-26 14:20:13 -0800474 try:
475 os.mkdir(home_dot_repo)
476 except OSError as e:
477 if e.errno != errno.EEXIST:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400478 print('fatal: cannot make %s directory: %s'
479 % (home_dot_repo, e.strerror), file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700480 sys.exit(1)
481
David Jamesbf79c662013-12-26 14:20:13 -0800482 try:
483 os.mkdir(gpg_dir, stat.S_IRWXU)
484 except OSError as e:
485 if e.errno != errno.EEXIST:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400486 print('fatal: cannot make %s directory: %s' % (gpg_dir, e.strerror),
487 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700488 sys.exit(1)
489
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800490 env = os.environ.copy()
Dāvis Mosāns631d0ec2016-07-16 21:11:11 +0300491 try:
492 env['GNUPGHOME'] = gpg_dir
493 except UnicodeEncodeError:
494 env['GNUPGHOME'] = gpg_dir.encode()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700495
496 cmd = ['gpg', '--import']
497 try:
498 proc = subprocess.Popen(cmd,
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700499 env=env,
500 stdin=subprocess.PIPE)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700501 except OSError as e:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700502 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400503 print('warning: gpg (GnuPG) is not available.', file=sys.stderr)
504 print('warning: Installing it is strongly encouraged.', file=sys.stderr)
505 print(file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700506 return False
507
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400508 proc.stdin.write(MAINTAINER_KEYS.encode('utf-8'))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700509 proc.stdin.close()
510
511 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400512 print('fatal: registering repo maintainer keys failed', file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700513 sys.exit(1)
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400514 print()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700515
516 fd = open(os.path.join(home_dot_repo, 'keyring-version'), 'w')
David Pursehouse685f0802012-11-14 08:34:39 +0900517 fd.write('.'.join(map(str, KEYRING_VERSION)) + '\n')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700518 fd.close()
519 return True
520
521
522def _SetConfig(local, name, value):
523 """Set a git configuration option to the specified value.
524 """
525 cmd = [GIT, 'config', name, value]
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700526 if subprocess.Popen(cmd, cwd=local).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700527 raise CloneFailure()
528
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700529
530def _InitHttp():
531 handlers = []
532
Sarah Owens1f7627f2012-10-31 09:21:55 -0700533 mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700534 try:
535 import netrc
536 n = netrc.netrc()
537 for host in n.hosts:
538 p = n.hosts[host]
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700539 mgr.add_password(p[1], 'http://%s/' % host, p[0], p[2])
Xiaodong Xuae0a36c2012-01-31 11:10:09 +0800540 mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2])
David Pursehouse65b0ba52018-06-24 16:21:51 +0900541 except:
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700542 pass
Sarah Owens1f7627f2012-10-31 09:21:55 -0700543 handlers.append(urllib.request.HTTPBasicAuthHandler(mgr))
544 handlers.append(urllib.request.HTTPDigestAuthHandler(mgr))
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700545
546 if 'http_proxy' in os.environ:
547 url = os.environ['http_proxy']
Sarah Owens1f7627f2012-10-31 09:21:55 -0700548 handlers.append(urllib.request.ProxyHandler({'http': url, 'https': url}))
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700549 if 'REPO_CURL_VERBOSE' in os.environ:
Sarah Owens1f7627f2012-10-31 09:21:55 -0700550 handlers.append(urllib.request.HTTPHandler(debuglevel=1))
551 handlers.append(urllib.request.HTTPSHandler(debuglevel=1))
552 urllib.request.install_opener(urllib.request.build_opener(*handlers))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700553
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700554
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700555def _Fetch(url, local, src, quiet):
556 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400557 print('Get %s' % url, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700558
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700559 cmd = [GIT, 'fetch']
560 if quiet:
561 cmd.append('--quiet')
562 err = subprocess.PIPE
563 else:
564 err = None
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700565 cmd.append(src)
566 cmd.append('+refs/heads/*:refs/remotes/origin/*')
Xin Li6e538442018-12-10 11:33:16 -0800567 cmd.append('+refs/tags/*:refs/tags/*')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700568
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700569 proc = subprocess.Popen(cmd, cwd=local, stderr=err)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700570 if err:
571 proc.stderr.read()
572 proc.stderr.close()
573 if proc.wait() != 0:
574 raise CloneFailure()
575
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700576
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700577def _DownloadBundle(url, local, quiet):
578 if not url.endswith('/'):
579 url += '/'
580 url += 'clone.bundle'
581
582 proc = subprocess.Popen(
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700583 [GIT, 'config', '--get-regexp', 'url.*.insteadof'],
584 cwd=local,
585 stdout=subprocess.PIPE)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700586 for line in proc.stdout:
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400587 line = line.decode('utf-8')
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700588 m = re.compile(r'^url\.(.*)\.insteadof (.*)$').match(line)
589 if m:
590 new_url = m.group(1)
591 old_url = m.group(2)
592 if url.startswith(old_url):
593 url = new_url + url[len(old_url):]
594 break
595 proc.stdout.close()
596 proc.wait()
597
598 if not url.startswith('http:') and not url.startswith('https:'):
599 return False
600
601 dest = open(os.path.join(local, '.git', 'clone.bundle'), 'w+b')
602 try:
603 try:
Sarah Owens1f7627f2012-10-31 09:21:55 -0700604 r = urllib.request.urlopen(url)
605 except urllib.error.HTTPError as e:
John Törnblomd3ddcdb2015-08-12 20:12:51 +0200606 if e.code in [401, 403, 404, 501]:
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700607 return False
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400608 print('fatal: Cannot get %s' % url, file=sys.stderr)
609 print('fatal: HTTP error %s' % e.code, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700610 raise CloneFailure()
Sarah Owens1f7627f2012-10-31 09:21:55 -0700611 except urllib.error.URLError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400612 print('fatal: Cannot get %s' % url, file=sys.stderr)
613 print('fatal: error %s' % e.reason, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700614 raise CloneFailure()
615 try:
616 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400617 print('Get %s' % url, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700618 while True:
619 buf = r.read(8192)
Mike Frysinger1b9adab2019-07-04 17:54:54 -0400620 if not buf:
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700621 return True
622 dest.write(buf)
623 finally:
624 r.close()
625 finally:
626 dest.close()
627
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700628
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700629def _ImportBundle(local):
630 path = os.path.join(local, '.git', 'clone.bundle')
631 try:
632 _Fetch(local, local, path, True)
633 finally:
634 os.remove(path)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700635
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700636
Hu xiuyun9711a982015-12-11 11:16:41 +0800637def _Clone(url, local, quiet, clone_bundle):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700638 """Clones a git repository to a new subdirectory of repodir
639 """
640 try:
641 os.mkdir(local)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700642 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400643 print('fatal: cannot make %s directory: %s' % (local, e.strerror),
644 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700645 raise CloneFailure()
646
647 cmd = [GIT, 'init', '--quiet']
648 try:
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700649 proc = subprocess.Popen(cmd, cwd=local)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700650 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400651 print(file=sys.stderr)
652 print("fatal: '%s' is not available" % GIT, file=sys.stderr)
653 print('fatal: %s' % e, file=sys.stderr)
654 print(file=sys.stderr)
655 print('Please make sure %s is installed and in your path.' % GIT,
656 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700657 raise CloneFailure()
658 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400659 print('fatal: could not create %s' % local, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700660 raise CloneFailure()
661
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700662 _InitHttp()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700663 _SetConfig(local, 'remote.origin.url', url)
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700664 _SetConfig(local,
665 'remote.origin.fetch',
666 '+refs/heads/*:refs/remotes/origin/*')
Hu xiuyun9711a982015-12-11 11:16:41 +0800667 if clone_bundle and _DownloadBundle(url, local, quiet):
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700668 _ImportBundle(local)
Dan Willemsenfee390e2015-09-02 12:36:30 -0700669 _Fetch(url, local, 'origin', quiet)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700670
671
672def _Verify(cwd, branch, quiet):
673 """Verify the branch has been signed by a tag.
674 """
675 cmd = [GIT, 'describe', 'origin/%s' % branch]
676 proc = subprocess.Popen(cmd,
677 stdout=subprocess.PIPE,
678 stderr=subprocess.PIPE,
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700679 cwd=cwd)
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400680 cur = proc.stdout.read().strip().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700681 proc.stdout.close()
682
683 proc.stderr.read()
684 proc.stderr.close()
685
686 if proc.wait() != 0 or not cur:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400687 print(file=sys.stderr)
688 print("fatal: branch '%s' has not been signed" % branch, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700689 raise CloneFailure()
690
691 m = re.compile(r'^(.*)-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur)
692 if m:
693 cur = m.group(1)
694 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400695 print(file=sys.stderr)
696 print("info: Ignoring branch '%s'; using tagged release '%s'"
697 % (branch, cur), file=sys.stderr)
698 print(file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700699
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800700 env = os.environ.copy()
Dāvis Mosāns631d0ec2016-07-16 21:11:11 +0300701 try:
702 env['GNUPGHOME'] = gpg_dir
703 except UnicodeEncodeError:
704 env['GNUPGHOME'] = gpg_dir.encode()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700705
706 cmd = [GIT, 'tag', '-v', cur]
707 proc = subprocess.Popen(cmd,
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700708 stdout=subprocess.PIPE,
709 stderr=subprocess.PIPE,
710 cwd=cwd,
711 env=env)
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400712 out = proc.stdout.read().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700713 proc.stdout.close()
714
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400715 err = proc.stderr.read().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700716 proc.stderr.close()
717
718 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400719 print(file=sys.stderr)
720 print(out, file=sys.stderr)
721 print(err, file=sys.stderr)
722 print(file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700723 raise CloneFailure()
724 return '%s^0' % cur
725
726
727def _Checkout(cwd, branch, rev, quiet):
728 """Checkout an upstream branch into the repository and track it.
729 """
730 cmd = [GIT, 'update-ref', 'refs/heads/default', rev]
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700731 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700732 raise CloneFailure()
733
734 _SetConfig(cwd, 'branch.default.remote', 'origin')
735 _SetConfig(cwd, 'branch.default.merge', 'refs/heads/%s' % branch)
736
737 cmd = [GIT, 'symbolic-ref', 'HEAD', 'refs/heads/default']
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700738 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700739 raise CloneFailure()
740
741 cmd = [GIT, 'read-tree', '--reset', '-u']
742 if not quiet:
743 cmd.append('-v')
744 cmd.append('HEAD')
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700745 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700746 raise CloneFailure()
747
748
749def _FindRepo():
750 """Look for a repo installation, starting at the current directory.
751 """
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200752 curdir = os.getcwd()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700753 repo = None
754
Anthony Newnamdf14a702011-01-09 17:31:57 -0800755 olddir = None
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200756 while curdir != '/' \
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700757 and curdir != olddir \
758 and not repo:
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200759 repo = os.path.join(curdir, repodir, REPO_MAIN)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700760 if not os.path.isfile(repo):
761 repo = None
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200762 olddir = curdir
763 curdir = os.path.dirname(curdir)
764 return (repo, os.path.join(curdir, repodir))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700765
766
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700767class _Options(object):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700768 help = False
769
770
771def _ParseArguments(args):
772 cmd = None
773 opt = _Options()
774 arg = []
775
Sarah Owensa6053d52012-11-01 13:36:50 -0700776 for i in range(len(args)):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700777 a = args[i]
778 if a == '-h' or a == '--help':
779 opt.help = True
780
781 elif not a.startswith('-'):
782 cmd = a
783 arg = args[i + 1:]
784 break
785 return cmd, opt, arg
786
787
788def _Usage():
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700789 gitc_usage = ""
790 if get_gitc_manifest_dir():
791 gitc_usage = " gitc-init Initialize a GITC Client.\n"
792
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400793 print(
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700794 """usage: repo COMMAND [ARGS]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700795
796repo is not yet installed. Use "repo init" to install it here.
797
798The most commonly used repo commands are:
799
800 init Install repo in the current working directory
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700801""" + gitc_usage +
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700802 """ help Display detailed help on a command
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700803
804For access to the full online help, install repo ("repo init").
Mike Frysinger35159ab2019-06-13 00:07:13 -0400805""")
806 sys.exit(0)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700807
808
809def _Help(args):
810 if args:
811 if args[0] == 'init':
812 init_optparse.print_help()
Trond Norbyed3fd5372011-01-03 11:35:15 +0100813 sys.exit(0)
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700814 elif args[0] == 'gitc-init':
815 _GitcInitOptions(init_optparse)
816 init_optparse.print_help()
817 sys.exit(0)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700818 else:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400819 print("error: '%s' is not a bootstrap command.\n"
820 ' For access to online help, install repo ("repo init").'
821 % args[0], file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700822 else:
823 _Usage()
824 sys.exit(1)
825
826
827def _NotInstalled():
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400828 print('error: repo is not installed. Use "repo init" to install it here.',
829 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700830 sys.exit(1)
831
832
833def _NoCommands(cmd):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400834 print("""error: command '%s' requires repo to be installed first.
835 Use "repo init" to install it here.""" % cmd, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700836 sys.exit(1)
837
838
839def _RunSelf(wrapper_path):
840 my_dir = os.path.dirname(wrapper_path)
841 my_main = os.path.join(my_dir, 'main.py')
842 my_git = os.path.join(my_dir, '.git')
843
844 if os.path.isfile(my_main) and os.path.isdir(my_git):
Shawn O. Pearcec8a300f2009-05-18 13:19:57 -0700845 for name in ['git_config.py',
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700846 'project.py',
847 'subcmds']:
848 if not os.path.exists(os.path.join(my_dir, name)):
849 return None, None
850 return my_main, my_git
851 return None, None
852
853
854def _SetDefaultsTo(gitdir):
855 global REPO_URL
856 global REPO_REV
857
858 REPO_URL = gitdir
859 proc = subprocess.Popen([GIT,
860 '--git-dir=%s' % gitdir,
861 'symbolic-ref',
862 'HEAD'],
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700863 stdout=subprocess.PIPE,
864 stderr=subprocess.PIPE)
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400865 REPO_REV = proc.stdout.read().strip().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700866 proc.stdout.close()
867
868 proc.stderr.read()
869 proc.stderr.close()
870
871 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400872 print('fatal: %s has no current branch' % gitdir, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700873 sys.exit(1)
874
875
876def main(orig_args):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700877 cmd, opt, args = _ParseArguments(orig_args)
878
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700879 repo_main, rel_repo_dir = None, None
880 # Don't use the local repo copy, make sure to switch to the gitc client first.
881 if cmd != 'gitc-init':
882 repo_main, rel_repo_dir = _FindRepo()
883
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700884 wrapper_path = os.path.abspath(__file__)
885 my_main, my_git = _RunSelf(wrapper_path)
886
Simran Basi8ce50412015-08-28 14:25:44 -0700887 cwd = os.getcwd()
Dan Willemsen2487cb72015-08-31 15:45:06 -0700888 if get_gitc_manifest_dir() and cwd.startswith(get_gitc_manifest_dir()):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400889 print('error: repo cannot be used in the GITC local manifest directory.'
890 '\nIf you want to work on this GITC client please rerun this '
891 'command from the corresponding client under /gitc/',
892 file=sys.stderr)
Simran Basi8ce50412015-08-28 14:25:44 -0700893 sys.exit(1)
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200894 if not repo_main:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700895 if opt.help:
896 _Usage()
897 if cmd == 'help':
898 _Help(args)
899 if not cmd:
900 _NotInstalled()
Simran Basi1efc2b42015-08-05 15:04:22 -0700901 if cmd == 'init' or cmd == 'gitc-init':
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700902 if my_git:
903 _SetDefaultsTo(my_git)
904 try:
Simran Basi1efc2b42015-08-05 15:04:22 -0700905 _Init(args, gitc_init=(cmd == 'gitc-init'))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700906 except CloneFailure:
Sebastian Schuberth27226e72016-10-28 14:27:43 +0200907 path = os.path.join(repodir, S_repo)
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400908 print("fatal: cloning the git-repo repository failed, will remove "
909 "'%s' " % path, file=sys.stderr)
Sebastian Schuberth27226e72016-10-28 14:27:43 +0200910 shutil.rmtree(path, ignore_errors=True)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700911 sys.exit(1)
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200912 repo_main, rel_repo_dir = _FindRepo()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700913 else:
914 _NoCommands(cmd)
915
916 if my_main:
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200917 repo_main = my_main
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700918
David Pursehouse685f0802012-11-14 08:34:39 +0900919 ver_str = '.'.join(map(str, VERSION))
anatoly techtonik3a2a59e2013-09-21 19:29:10 +0300920 me = [sys.executable, repo_main,
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200921 '--repo-dir=%s' % rel_repo_dir,
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700922 '--wrapper-version=%s' % ver_str,
923 '--wrapper-path=%s' % wrapper_path,
924 '--']
925 me.extend(orig_args)
926 me.extend(extra_args)
927 try:
Renaud Paquay35d22212016-11-01 11:24:52 -0700928 if platform.system() == "Windows":
929 sys.exit(subprocess.call(me))
930 else:
931 os.execv(sys.executable, me)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700932 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400933 print("fatal: unable to start %s" % repo_main, file=sys.stderr)
934 print("fatal: %s" % e, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700935 sys.exit(148)
936
937
938if __name__ == '__main__':
939 main(sys.argv[1:])