blob: 7ca16b0dfa7b5e5fdca70901ccb6d7383c5aa268 [file] [log] [blame]
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +00001#!/usr/bin/env python
Mike Frysingerafe292c2019-08-05 19:15:18 +00002# -*- coding:utf-8 -*-
3
4"""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
11from __future__ import print_function
msb@chromium.org38b04f82010-07-13 23:03:34 +000012
vapierae39f562016-10-10 19:08:17 -070013# repo default configuration
14#
15import os
16REPO_URL = os.environ.get('REPO_URL', None)
17if not REPO_URL:
18 REPO_URL = 'https://chromium.googlesource.com/external/repo'
19REPO_REV = 'stable'
msb@chromium.org38b04f82010-07-13 23:03:34 +000020
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
msb@chromium.org38b04f82010-07-13 23:03:34 +000035# increment this whenever we make important changes to this script
Mike Frysinger58649e32018-12-20 21:53:50 +000036VERSION = (1, 25)
msb@chromium.org38b04f82010-07-13 23:03:34 +000037
38# increment this if the MAINTAINER_KEYS block is modified
vapier74751962016-09-14 16:08:34 -070039KEYRING_VERSION = (1, 5)
Don Garrett24f2cc02018-12-18 18:07:17 +000040
41# Each individual key entry is created by using:
42# gpg --armor --export keyid
msb@chromium.org38b04f82010-07-13 23:03:34 +000043MAINTAINER_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-----
ferringb@google.com8db6c882012-12-25 17:02:37 +000086
87 Conley Owens <cco3@android.com>
88-----BEGIN PGP PUBLIC KEY BLOCK-----
89Version: GnuPG v1.4.11 (GNU/Linux)
90
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +000091mQENBFHRvc8BCADFg45Xx/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
ferringb@google.com8db6c882012-12-25 17:02:37 +0000117-----END PGP PUBLIC KEY BLOCK-----
szager@chromium.org538283f2013-08-13 21:37:50 +0000118
119 Stefan Zager <szager@chromium.org>
120-----BEGIN PGP PUBLIC KEY BLOCK-----
121Version: GnuPG v1.4.11 (GNU/Linux)
122
123mQINBFIJOcgBEADwZIq4GRGoO1RJFKlrtVK501cwT5H+Acbizc9N5RxTkFmqxDjb
1249ApUaPW6S1b8+nrzE9P1Ri5erfzipuStfaZ/Wl3mP1JjKulibddmgnPOEbAJ673k
125Vj85RUO4rt2oZAHnZN3D3gFJzVY8JVlZ47Enj9fTqzcW78FVsPCpIT9P2LpTLWeE
126jX9Cjxeimy6VvyJstIcDLYhlpUN5UWen79L4LFAkHf3luLuU4W3p9NriqUsy5UG2
1278vO6QdhKrCr5wsjDFFeVnpMtjlSeZJAWH+XhFFibMX1xP5R9BTuJfzw3kOVKvcE0
128e9ClxgoulepXPv2xnDkqO3pG2gQVzl8LA+Aol8/IXfa7KP5FBkxK/g1cDuDtXRk4
129YLpLaLYeeKEhhOHLpsKYkK2DXTIcN+56UnTLGolummpZnCM8UUSZxQgbkFgk4YJL
130Elip0hgLZzqEl5h9vjmnQp89AZIHKcgNmzn+szLTOR9x24joaLyQ534x8OSC8lmu
131tJv2tQjDOVGWVwvY4gOTpyxCWMwur6WOiMk/TPWdiVRFWAGrAHwf0/CTBEqNhosh
132sVXfPeMADBA0PorDbJ6kwcOkLUTGf8CT7OG1R9TuKPEmSjK7BYu/pT4DXitaRCiv
133uPVlwbVFpLFr0/jwaKJVMLUjL5MaYwzjJqI2c4RdROZhpMhkn4LvCMmFSQARAQAB
134tCJTdGVmYW4gWmFnZXIgPHN6YWdlckBjaHJvbWl1bS5vcmc+iQI4BBMBAgAiBQJS
135CTnIAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRDcuoHPGCdZNU0UD/9y
1360zwwOJH2UGPAzZ0YVzr7p0HtKedoxuFvPkdQxlBIaUOueMzFRmNQu3GI9irAu3MQ
137Jkip8/gi7dnLVmJyS/zWARBaRGwSVd1++87XDjw8n7l181p7394X0Agq/heri599
138YheHXkxXKVMPqByWNEPHu4eDbxeJTaDIjcKC2pzKQkm6HbWgW4wA9gCh1TRki8FP
139LMv1Fu/dr13STCR9P2evsTRZ+ZSJhTSboHNHeEAJGiGZQAsN94oht7647lYj+AyR
140ThzyHDMXXiDr8jPJIkyRilY+y82bCOatOfPoCkce3VI+LRUGJ19hJY01m4RRneIE
14155l7fXR3zggcsONjV5b+oLcGQPGgX9w64BJ7khT7Wb9+kuyrdJBIBzJsaACFEbri
142pPi02FS/HahYpLC3J66REAeNyofgVXau6WQsHrHMGsBTL9aAr0nrCrkF4Nyyc2Jd
143do6nYuljuUhORqbEECmmBM2eBtkL6Ac92D6WMBIwBOC5tCNHO2YFIvi8Y8EuE8sc
1441zB5U5Ai4SIu2icRAhzAhCRaUq02cMWuELKH6Vuh9nzgEefFWty6vPbKEyZLu19D
145B80aqP1cTN88FjtKQ/eTF29TUB6AefUeBS17e2e3WUMy4nc8tduuOFYfiHP40ScP
146wOoatwfzpiTIPGbocUEPL+pS0O/Xy8SINxFMCud3zA==
147=Vd2S
148-----END PGP PUBLIC KEY BLOCK-----
szager@chromium.org33c182b2014-09-08 17:50:45 +0000149
150 David James <davidjames@google.com>
151-----BEGIN PGP PUBLIC KEY BLOCK-----
152Version: GnuPG v1
153
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
200IM4=
201=6VNc
202-----END PGP PUBLIC KEY BLOCK-----
vapier74751962016-09-14 16:08:34 -0700203
204 Mike Frysinger <vapier@chromium.org>
205-----BEGIN PGP PUBLIC KEY BLOCK-----
206Version: GnuPG v1
207
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
243=i88c
244-----END PGP PUBLIC KEY BLOCK-----
msb@chromium.org38b04f82010-07-13 23:03:34 +0000245"""
246
vapierae39f562016-10-10 19:08:17 -0700247GIT = 'git' # our git command
248MIN_GIT_VERSION = (1, 7, 2) # minimum supported git version
249repodir = '.repo' # name of repo's private directory
250S_repo = 'repo' # special repo repository
251S_manifests = 'manifests' # special manifest repository
252REPO_MAIN = S_repo + '/main.py' # main script
Mike Frysinger58649e32018-12-20 21:53:50 +0000253MIN_PYTHON_VERSION = (2, 7) # minimum supported python version
vapierae39f562016-10-10 19:08:17 -0700254GITC_CONFIG_FILE = '/gitc/.config'
255GITC_FS_ROOT_DIR = '/gitc/manifest-rw/'
msb@chromium.org38b04f82010-07-13 23:03:34 +0000256
257
Mike Frysingerafe292c2019-08-05 19:15:18 +0000258import collections
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000259import errno
msb@chromium.org38b04f82010-07-13 23:03:34 +0000260import optparse
Don Garrett24f2cc02018-12-18 18:07:17 +0000261import platform
msb@chromium.org38b04f82010-07-13 23:03:34 +0000262import re
vapier74751962016-09-14 16:08:34 -0700263import shutil
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000264import stat
msb@chromium.org38b04f82010-07-13 23:03:34 +0000265import subprocess
266import sys
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000267
268if sys.version_info[0] == 3:
269 import urllib.request
270 import urllib.error
271else:
272 import imp
273 import urllib2
274 urllib = imp.new_module('urllib')
275 urllib.request = urllib2
276 urllib.error = urllib2
277
278
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000279# Python version check
280ver = sys.version_info
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000281if (ver[0], ver[1]) < MIN_PYTHON_VERSION:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000282 print('error: Python version {} unsupported.\n'
283 'Please use Python {}.{} instead.'.format(
284 sys.version.split(' ')[0],
285 MIN_PYTHON_VERSION[0],
286 MIN_PYTHON_VERSION[1],
287 ), file=sys.stderr)
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000288 sys.exit(1)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000289
vapier74751962016-09-14 16:08:34 -0700290home_dot_repo = os.path.expanduser('~/.repoconfig')
msb@chromium.org38b04f82010-07-13 23:03:34 +0000291gpg_dir = os.path.join(home_dot_repo, 'gnupg')
292
293extra_args = []
294init_optparse = optparse.OptionParser(usage="repo init -u url [options]")
295
296# Logging
297group = init_optparse.add_option_group('Logging options')
298group.add_option('-q', '--quiet',
299 dest="quiet", action="store_true", default=False,
300 help="be quiet")
301
302# Manifest
303group = init_optparse.add_option_group('Manifest options')
304group.add_option('-u', '--manifest-url',
305 dest='manifest_url',
306 help='manifest repository location', metavar='URL')
msb@chromium.org38b04f82010-07-13 23:03:34 +0000307group.add_option('-b', '--manifest-branch',
308 dest='manifest_branch',
309 help='manifest branch or revision', metavar='REVISION')
310group.add_option('-m', '--manifest-name',
311 dest='manifest_name',
maruel@chromium.orgb25b69b2011-06-16 17:41:05 +0000312 help='initial manifest file', metavar='NAME.xml')
Mike Frysinger58649e32018-12-20 21:53:50 +0000313group.add_option('--current-branch',
Don Garrett24f2cc02018-12-18 18:07:17 +0000314 dest='current_branch_only', action='store_true',
315 help='fetch only current manifest branch from server')
msb@chromium.org38b04f82010-07-13 23:03:34 +0000316group.add_option('--mirror',
317 dest='mirror', action='store_true',
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000318 help='create a replica of the remote repositories '
319 'rather than a client working directory')
msb@chromium.org2c64b712011-01-11 22:57:47 +0000320group.add_option('--reference',
321 dest='reference',
322 help='location of mirror directory', metavar='DIR')
Mike Frysingerafe292c2019-08-05 19:15:18 +0000323group.add_option('--dissociate',
324 dest='dissociate', action='store_true',
325 help='dissociate from reference mirrors after clone')
maruel@chromium.orgb25b69b2011-06-16 17:41:05 +0000326group.add_option('--depth', type='int', default=None,
327 dest='depth',
328 help='create a shallow clone with given depth; see git clone')
Mike Frysingerafe292c2019-08-05 19:15:18 +0000329group.add_option('--partial-clone', action='store_true',
330 dest='partial_clone',
331 help='perform partial clone (https://git-scm.com/'
332 'docs/gitrepository-layout#_code_partialclone_code)')
333group.add_option('--clone-filter', action='store', default='blob:none',
334 dest='clone_filter',
335 help='filter for use with --partial-clone [default: %default]')
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000336group.add_option('--archive',
337 dest='archive', action='store_true',
338 help='checkout an archive instead of a git repository for '
339 'each project. See git archive.')
Don Garrett24f2cc02018-12-18 18:07:17 +0000340group.add_option('--submodules',
341 dest='submodules', action='store_true',
342 help='sync any submodules associated with the manifest repo')
ferringb@google.com79245bf2012-06-14 21:22:01 +0000343group.add_option('-g', '--groups',
344 dest='groups', default='default',
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000345 help='restrict manifest projects to ones with specified '
346 'group(s) [default|all|G1,G2,G3|G4,-G5,-G6]',
ferringb@google.com79245bf2012-06-14 21:22:01 +0000347 metavar='GROUP')
348group.add_option('-p', '--platform',
349 dest='platform', default="auto",
ferringb@google.com8db6c882012-12-25 17:02:37 +0000350 help='restrict manifest projects to ones with a specified '
ferringb@google.com79245bf2012-06-14 21:22:01 +0000351 'platform group [auto|all|none|linux|darwin|...]',
352 metavar='PLATFORM')
vapierae39f562016-10-10 19:08:17 -0700353group.add_option('--no-clone-bundle',
354 dest='no_clone_bundle', action='store_true',
355 help='disable use of /clone.bundle on HTTP/HTTPS')
Don Garrett24f2cc02018-12-18 18:07:17 +0000356group.add_option('--no-tags',
357 dest='no_tags', action='store_true',
358 help="don't fetch tags in the manifest")
maruel@chromium.orgb25b69b2011-06-16 17:41:05 +0000359
msb@chromium.org38b04f82010-07-13 23:03:34 +0000360
361# Tool
362group = init_optparse.add_option_group('repo Version options')
363group.add_option('--repo-url',
364 dest='repo_url',
365 help='repo repository location', metavar='URL')
366group.add_option('--repo-branch',
367 dest='repo_branch',
368 help='repo branch or revision', metavar='REVISION')
369group.add_option('--no-repo-verify',
370 dest='no_repo_verify', action='store_true',
371 help='do not verify repo source code')
372
ferringb@google.com79245bf2012-06-14 21:22:01 +0000373# Other
374group = init_optparse.add_option_group('Other options')
375group.add_option('--config-name',
376 dest='config_name', action="store_true", default=False,
377 help='Always prompt for name/e-mail')
msb@chromium.org38b04f82010-07-13 23:03:34 +0000378
vapierae39f562016-10-10 19:08:17 -0700379
380def _GitcInitOptions(init_optparse_arg):
381 init_optparse_arg.set_usage("repo gitc-init -u url -c client [options]")
382 g = init_optparse_arg.add_option_group('GITC options')
383 g.add_option('-f', '--manifest-file',
384 dest='manifest_file',
385 help='Optional manifest file to use for this GITC client.')
386 g.add_option('-c', '--gitc-client',
387 dest='gitc_client',
388 help='The name of the gitc_client instance to create or modify.')
389
390_gitc_manifest_dir = None
391
392
393def get_gitc_manifest_dir():
394 global _gitc_manifest_dir
395 if _gitc_manifest_dir is None:
396 _gitc_manifest_dir = ''
397 try:
398 with open(GITC_CONFIG_FILE, 'r') as gitc_config:
399 for line in gitc_config:
400 match = re.match('gitc_dir=(?P<gitc_manifest_dir>.*)', line)
401 if match:
402 _gitc_manifest_dir = match.group('gitc_manifest_dir')
403 except IOError:
404 pass
405 return _gitc_manifest_dir
406
407
408def gitc_parse_clientdir(gitc_fs_path):
409 """Parse a path in the GITC FS and return its client name.
410
411 @param gitc_fs_path: A subdirectory path within the GITC_FS_ROOT_DIR.
412
413 @returns: The GITC client name
414 """
415 if gitc_fs_path == GITC_FS_ROOT_DIR:
416 return None
417 if not gitc_fs_path.startswith(GITC_FS_ROOT_DIR):
418 manifest_dir = get_gitc_manifest_dir()
419 if manifest_dir == '':
420 return None
421 if manifest_dir[-1] != '/':
422 manifest_dir += '/'
423 if gitc_fs_path == manifest_dir:
424 return None
425 if not gitc_fs_path.startswith(manifest_dir):
426 return None
427 return gitc_fs_path.split(manifest_dir)[1].split('/')[0]
428 return gitc_fs_path.split(GITC_FS_ROOT_DIR)[1].split('/')[0]
429
430
msb@chromium.org38b04f82010-07-13 23:03:34 +0000431class CloneFailure(Exception):
vapierae39f562016-10-10 19:08:17 -0700432
msb@chromium.org38b04f82010-07-13 23:03:34 +0000433 """Indicate the remote clone of repo itself failed.
434 """
435
436
vapierae39f562016-10-10 19:08:17 -0700437def _Init(args, gitc_init=False):
msb@chromium.org38b04f82010-07-13 23:03:34 +0000438 """Installs repo by cloning it over the network.
439 """
vapierae39f562016-10-10 19:08:17 -0700440 if gitc_init:
441 _GitcInitOptions(init_optparse)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000442 opt, args = init_optparse.parse_args(args)
ferringb@google.com79245bf2012-06-14 21:22:01 +0000443 if args:
msb@chromium.org38b04f82010-07-13 23:03:34 +0000444 init_optparse.print_usage()
445 sys.exit(1)
446
447 url = opt.repo_url
448 if not url:
449 url = REPO_URL
450 extra_args.append('--repo-url=%s' % url)
451
452 branch = opt.repo_branch
453 if not branch:
454 branch = REPO_REV
455 extra_args.append('--repo-branch=%s' % branch)
456
457 if branch.startswith('refs/heads/'):
458 branch = branch[len('refs/heads/'):]
459 if branch.startswith('refs/'):
Mike Frysingerafe292c2019-08-05 19:15:18 +0000460 print("fatal: invalid branch name '%s'" % branch, file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000461 raise CloneFailure()
462
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000463 try:
vapierae39f562016-10-10 19:08:17 -0700464 if gitc_init:
465 gitc_manifest_dir = get_gitc_manifest_dir()
466 if not gitc_manifest_dir:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000467 print('fatal: GITC filesystem is not available. Exiting...',
468 file=sys.stderr)
vapierae39f562016-10-10 19:08:17 -0700469 sys.exit(1)
470 gitc_client = opt.gitc_client
471 if not gitc_client:
472 gitc_client = gitc_parse_clientdir(os.getcwd())
473 if not gitc_client:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000474 print('fatal: GITC client (-c) is required.', file=sys.stderr)
vapierae39f562016-10-10 19:08:17 -0700475 sys.exit(1)
476 client_dir = os.path.join(gitc_manifest_dir, gitc_client)
477 if not os.path.exists(client_dir):
478 os.makedirs(client_dir)
479 os.chdir(client_dir)
480 if os.path.exists(repodir):
481 # This GITC Client has already initialized repo so continue.
482 return
483
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000484 os.mkdir(repodir)
485 except OSError as e:
486 if e.errno != errno.EEXIST:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000487 print('fatal: cannot make %s directory: %s'
488 % (repodir, e.strerror), file=sys.stderr)
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000489 # Don't raise CloneFailure; that would delete the
msb@chromium.org38b04f82010-07-13 23:03:34 +0000490 # name. Instead exit immediately.
491 #
492 sys.exit(1)
493
494 _CheckGitVersion()
495 try:
ferringb@google.com8db6c882012-12-25 17:02:37 +0000496 if NeedSetupGnuPG():
497 can_verify = SetupGnuPG(opt.quiet)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000498 else:
499 can_verify = True
500
msb@chromium.org38b04f82010-07-13 23:03:34 +0000501 dst = os.path.abspath(os.path.join(repodir, S_repo))
vapierae39f562016-10-10 19:08:17 -0700502 _Clone(url, dst, opt.quiet, not opt.no_clone_bundle)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000503
504 if can_verify and not opt.no_repo_verify:
505 rev = _Verify(dst, branch, opt.quiet)
506 else:
507 rev = 'refs/remotes/origin/%s^0' % branch
508
509 _Checkout(dst, branch, rev, opt.quiet)
Mike Frysingerafe292c2019-08-05 19:15:18 +0000510
511 if not os.path.isfile(os.path.join(dst, 'repo')):
512 print("warning: '%s' does not look like a git-repo repository, is "
513 "REPO_URL set correctly?" % url, file=sys.stderr)
514
msb@chromium.org38b04f82010-07-13 23:03:34 +0000515 except CloneFailure:
516 if opt.quiet:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000517 print('fatal: repo init failed; run without --quiet to see why',
518 file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000519 raise
520
521
Mike Frysingerafe292c2019-08-05 19:15:18 +0000522# The git version info broken down into components for easy analysis.
523# Similar to Python's sys.version_info.
524GitVersion = collections.namedtuple(
525 'GitVersion', ('major', 'minor', 'micro', 'full'))
526
527def ParseGitVersion(ver_str=None):
528 if ver_str is None:
529 # Load the version ourselves.
530 ver_str = _GetGitVersion()
531
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000532 if not ver_str.startswith('git version '):
533 return None
534
Mike Frysingerafe292c2019-08-05 19:15:18 +0000535 full_version = ver_str[len('git version '):].strip()
536 num_ver_str = full_version.split('-')[0]
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000537 to_tuple = []
538 for num_str in num_ver_str.split('.')[:3]:
539 if num_str.isdigit():
540 to_tuple.append(int(num_str))
541 else:
542 to_tuple.append(0)
Mike Frysingerafe292c2019-08-05 19:15:18 +0000543 to_tuple.append(full_version)
544 return GitVersion(*to_tuple)
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000545
546
Mike Frysingerafe292c2019-08-05 19:15:18 +0000547def _GetGitVersion():
msb@chromium.org38b04f82010-07-13 23:03:34 +0000548 cmd = [GIT, '--version']
ferringb@google.com79245bf2012-06-14 21:22:01 +0000549 try:
550 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
ferringb@google.com8db6c882012-12-25 17:02:37 +0000551 except OSError as e:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000552 print(file=sys.stderr)
553 print("fatal: '%s' is not available" % GIT, file=sys.stderr)
554 print('fatal: %s' % e, file=sys.stderr)
555 print(file=sys.stderr)
556 print('Please make sure %s is installed and in your path.' % GIT,
557 file=sys.stderr)
558 raise
ferringb@google.com79245bf2012-06-14 21:22:01 +0000559
msb@chromium.org38b04f82010-07-13 23:03:34 +0000560 ver_str = proc.stdout.read().strip()
561 proc.stdout.close()
562 proc.wait()
Mike Frysingerafe292c2019-08-05 19:15:18 +0000563 return ver_str.decode('utf-8')
msb@chromium.org38b04f82010-07-13 23:03:34 +0000564
Mike Frysingerafe292c2019-08-05 19:15:18 +0000565
566def _CheckGitVersion():
567 try:
568 ver_act = ParseGitVersion()
569 except OSError:
570 raise CloneFailure()
571
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000572 if ver_act is None:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000573 print('error: "%s" unsupported' % ver_str, file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000574 raise CloneFailure()
575
msb@chromium.org38b04f82010-07-13 23:03:34 +0000576 if ver_act < MIN_GIT_VERSION:
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000577 need = '.'.join(map(str, MIN_GIT_VERSION))
Mike Frysingerafe292c2019-08-05 19:15:18 +0000578 print('fatal: git %s or later required' % need, file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000579 raise CloneFailure()
580
581
ferringb@google.com8db6c882012-12-25 17:02:37 +0000582def NeedSetupGnuPG():
msb@chromium.org38b04f82010-07-13 23:03:34 +0000583 if not os.path.isdir(home_dot_repo):
584 return True
585
586 kv = os.path.join(home_dot_repo, 'keyring-version')
587 if not os.path.exists(kv):
588 return True
589
590 kv = open(kv).read()
591 if not kv:
592 return True
593
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000594 kv = tuple(map(int, kv.split('.')))
msb@chromium.org38b04f82010-07-13 23:03:34 +0000595 if kv < KEYRING_VERSION:
596 return True
597 return False
598
599
ferringb@google.com8db6c882012-12-25 17:02:37 +0000600def SetupGnuPG(quiet):
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000601 try:
602 os.mkdir(home_dot_repo)
603 except OSError as e:
604 if e.errno != errno.EEXIST:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000605 print('fatal: cannot make %s directory: %s'
606 % (home_dot_repo, e.strerror), file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000607 sys.exit(1)
608
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000609 try:
610 os.mkdir(gpg_dir, stat.S_IRWXU)
611 except OSError as e:
612 if e.errno != errno.EEXIST:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000613 print('fatal: cannot make %s directory: %s' % (gpg_dir, e.strerror),
614 file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000615 sys.exit(1)
616
msb@chromium.org2c64b712011-01-11 22:57:47 +0000617 env = os.environ.copy()
vapierae39f562016-10-10 19:08:17 -0700618 try:
619 env['GNUPGHOME'] = gpg_dir
620 except UnicodeEncodeError:
621 env['GNUPGHOME'] = gpg_dir.encode()
msb@chromium.org38b04f82010-07-13 23:03:34 +0000622
623 cmd = ['gpg', '--import']
624 try:
625 proc = subprocess.Popen(cmd,
vapierae39f562016-10-10 19:08:17 -0700626 env=env,
627 stdin=subprocess.PIPE)
ferringb@google.com8db6c882012-12-25 17:02:37 +0000628 except OSError as e:
msb@chromium.org38b04f82010-07-13 23:03:34 +0000629 if not quiet:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000630 print('warning: gpg (GnuPG) is not available.', file=sys.stderr)
631 print('warning: Installing it is strongly encouraged.', file=sys.stderr)
632 print(file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000633 return False
634
635 proc.stdin.write(MAINTAINER_KEYS)
636 proc.stdin.close()
637
638 if proc.wait() != 0:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000639 print('fatal: registering repo maintainer keys failed', file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000640 sys.exit(1)
Mike Frysingerafe292c2019-08-05 19:15:18 +0000641 print()
msb@chromium.org38b04f82010-07-13 23:03:34 +0000642
643 fd = open(os.path.join(home_dot_repo, 'keyring-version'), 'w')
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000644 fd.write('.'.join(map(str, KEYRING_VERSION)) + '\n')
msb@chromium.org38b04f82010-07-13 23:03:34 +0000645 fd.close()
646 return True
647
648
649def _SetConfig(local, name, value):
650 """Set a git configuration option to the specified value.
651 """
652 cmd = [GIT, 'config', name, value]
vapierae39f562016-10-10 19:08:17 -0700653 if subprocess.Popen(cmd, cwd=local).wait() != 0:
msb@chromium.org38b04f82010-07-13 23:03:34 +0000654 raise CloneFailure()
655
656
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000657def _InitHttp():
658 handlers = []
659
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000660 mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000661 try:
662 import netrc
663 n = netrc.netrc()
664 for host in n.hosts:
665 p = n.hosts[host]
vapierae39f562016-10-10 19:08:17 -0700666 mgr.add_password(p[1], 'http://%s/' % host, p[0], p[2])
ferringb@google.com79245bf2012-06-14 21:22:01 +0000667 mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2])
Mike Frysingerafe292c2019-08-05 19:15:18 +0000668 except:
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000669 pass
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000670 handlers.append(urllib.request.HTTPBasicAuthHandler(mgr))
671 handlers.append(urllib.request.HTTPDigestAuthHandler(mgr))
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000672
673 if 'http_proxy' in os.environ:
674 url = os.environ['http_proxy']
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000675 handlers.append(urllib.request.ProxyHandler({'http': url, 'https': url}))
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000676 if 'REPO_CURL_VERBOSE' in os.environ:
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000677 handlers.append(urllib.request.HTTPHandler(debuglevel=1))
678 handlers.append(urllib.request.HTTPSHandler(debuglevel=1))
679 urllib.request.install_opener(urllib.request.build_opener(*handlers))
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000680
vapierae39f562016-10-10 19:08:17 -0700681
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000682def _Fetch(url, local, src, quiet):
683 if not quiet:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000684 print('Get %s' % url, file=sys.stderr)
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000685
msb@chromium.org38b04f82010-07-13 23:03:34 +0000686 cmd = [GIT, 'fetch']
687 if quiet:
688 cmd.append('--quiet')
689 err = subprocess.PIPE
690 else:
691 err = None
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000692 cmd.append(src)
693 cmd.append('+refs/heads/*:refs/remotes/origin/*')
Mike Frysingerafe292c2019-08-05 19:15:18 +0000694 cmd.append('+refs/tags/*:refs/tags/*')
msb@chromium.org38b04f82010-07-13 23:03:34 +0000695
vapierae39f562016-10-10 19:08:17 -0700696 proc = subprocess.Popen(cmd, cwd=local, stderr=err)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000697 if err:
698 proc.stderr.read()
699 proc.stderr.close()
700 if proc.wait() != 0:
701 raise CloneFailure()
702
vapierae39f562016-10-10 19:08:17 -0700703
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000704def _DownloadBundle(url, local, quiet):
705 if not url.endswith('/'):
706 url += '/'
707 url += 'clone.bundle'
708
709 proc = subprocess.Popen(
vapierae39f562016-10-10 19:08:17 -0700710 [GIT, 'config', '--get-regexp', 'url.*.insteadof'],
711 cwd=local,
712 stdout=subprocess.PIPE)
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000713 for line in proc.stdout:
714 m = re.compile(r'^url\.(.*)\.insteadof (.*)$').match(line)
715 if m:
716 new_url = m.group(1)
717 old_url = m.group(2)
718 if url.startswith(old_url):
719 url = new_url + url[len(old_url):]
720 break
721 proc.stdout.close()
722 proc.wait()
723
724 if not url.startswith('http:') and not url.startswith('https:'):
725 return False
726
727 dest = open(os.path.join(local, '.git', 'clone.bundle'), 'w+b')
728 try:
729 try:
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000730 r = urllib.request.urlopen(url)
731 except urllib.error.HTTPError as e:
vapierae39f562016-10-10 19:08:17 -0700732 if e.code in [401, 403, 404, 501]:
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000733 return False
Mike Frysingerafe292c2019-08-05 19:15:18 +0000734 print('fatal: Cannot get %s' % url, file=sys.stderr)
735 print('fatal: HTTP error %s' % e.code, file=sys.stderr)
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000736 raise CloneFailure()
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000737 except urllib.error.URLError as e:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000738 print('fatal: Cannot get %s' % url, file=sys.stderr)
739 print('fatal: error %s' % e.reason, file=sys.stderr)
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000740 raise CloneFailure()
741 try:
742 if not quiet:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000743 print('Get %s' % url, file=sys.stderr)
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000744 while True:
745 buf = r.read(8192)
Mike Frysingerafe292c2019-08-05 19:15:18 +0000746 if not buf:
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000747 return True
748 dest.write(buf)
749 finally:
750 r.close()
751 finally:
752 dest.close()
753
vapierae39f562016-10-10 19:08:17 -0700754
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000755def _ImportBundle(local):
756 path = os.path.join(local, '.git', 'clone.bundle')
757 try:
758 _Fetch(local, local, path, True)
759 finally:
760 os.remove(path)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000761
vapierae39f562016-10-10 19:08:17 -0700762
763def _Clone(url, local, quiet, clone_bundle):
msb@chromium.org38b04f82010-07-13 23:03:34 +0000764 """Clones a git repository to a new subdirectory of repodir
765 """
766 try:
767 os.mkdir(local)
ferringb@google.com8db6c882012-12-25 17:02:37 +0000768 except OSError as e:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000769 print('fatal: cannot make %s directory: %s' % (local, e.strerror),
770 file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000771 raise CloneFailure()
772
773 cmd = [GIT, 'init', '--quiet']
774 try:
vapierae39f562016-10-10 19:08:17 -0700775 proc = subprocess.Popen(cmd, cwd=local)
ferringb@google.com8db6c882012-12-25 17:02:37 +0000776 except OSError as e:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000777 print(file=sys.stderr)
778 print("fatal: '%s' is not available" % GIT, file=sys.stderr)
779 print('fatal: %s' % e, file=sys.stderr)
780 print(file=sys.stderr)
781 print('Please make sure %s is installed and in your path.' % GIT,
782 file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000783 raise CloneFailure()
784 if proc.wait() != 0:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000785 print('fatal: could not create %s' % local, file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000786 raise CloneFailure()
787
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000788 _InitHttp()
msb@chromium.org38b04f82010-07-13 23:03:34 +0000789 _SetConfig(local, 'remote.origin.url', url)
vapierae39f562016-10-10 19:08:17 -0700790 _SetConfig(local,
791 'remote.origin.fetch',
792 '+refs/heads/*:refs/remotes/origin/*')
793 if clone_bundle and _DownloadBundle(url, local, quiet):
jeffbailey@chromium.orgad390562011-11-12 00:37:07 +0000794 _ImportBundle(local)
vapierae39f562016-10-10 19:08:17 -0700795 _Fetch(url, local, 'origin', quiet)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000796
797
798def _Verify(cwd, branch, quiet):
799 """Verify the branch has been signed by a tag.
800 """
801 cmd = [GIT, 'describe', 'origin/%s' % branch]
802 proc = subprocess.Popen(cmd,
803 stdout=subprocess.PIPE,
804 stderr=subprocess.PIPE,
vapierae39f562016-10-10 19:08:17 -0700805 cwd=cwd)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000806 cur = proc.stdout.read().strip()
807 proc.stdout.close()
808
809 proc.stderr.read()
810 proc.stderr.close()
811
812 if proc.wait() != 0 or not cur:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000813 print(file=sys.stderr)
814 print("fatal: branch '%s' has not been signed" % branch, file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000815 raise CloneFailure()
816
817 m = re.compile(r'^(.*)-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur)
818 if m:
819 cur = m.group(1)
820 if not quiet:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000821 print(file=sys.stderr)
822 print("info: Ignoring branch '%s'; using tagged release '%s'"
823 % (branch, cur), file=sys.stderr)
824 print(file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000825
msb@chromium.org2c64b712011-01-11 22:57:47 +0000826 env = os.environ.copy()
vapierae39f562016-10-10 19:08:17 -0700827 try:
828 env['GNUPGHOME'] = gpg_dir
829 except UnicodeEncodeError:
830 env['GNUPGHOME'] = gpg_dir.encode()
msb@chromium.org38b04f82010-07-13 23:03:34 +0000831
832 cmd = [GIT, 'tag', '-v', cur]
833 proc = subprocess.Popen(cmd,
vapierae39f562016-10-10 19:08:17 -0700834 stdout=subprocess.PIPE,
835 stderr=subprocess.PIPE,
836 cwd=cwd,
837 env=env)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000838 out = proc.stdout.read()
839 proc.stdout.close()
840
841 err = proc.stderr.read()
842 proc.stderr.close()
843
844 if proc.wait() != 0:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000845 print(file=sys.stderr)
846 print(out, file=sys.stderr)
847 print(err, file=sys.stderr)
848 print(file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000849 raise CloneFailure()
850 return '%s^0' % cur
851
852
853def _Checkout(cwd, branch, rev, quiet):
854 """Checkout an upstream branch into the repository and track it.
855 """
856 cmd = [GIT, 'update-ref', 'refs/heads/default', rev]
vapierae39f562016-10-10 19:08:17 -0700857 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
msb@chromium.org38b04f82010-07-13 23:03:34 +0000858 raise CloneFailure()
859
860 _SetConfig(cwd, 'branch.default.remote', 'origin')
861 _SetConfig(cwd, 'branch.default.merge', 'refs/heads/%s' % branch)
862
863 cmd = [GIT, 'symbolic-ref', 'HEAD', 'refs/heads/default']
vapierae39f562016-10-10 19:08:17 -0700864 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
msb@chromium.org38b04f82010-07-13 23:03:34 +0000865 raise CloneFailure()
866
867 cmd = [GIT, 'read-tree', '--reset', '-u']
868 if not quiet:
869 cmd.append('-v')
870 cmd.append('HEAD')
vapierae39f562016-10-10 19:08:17 -0700871 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
msb@chromium.org38b04f82010-07-13 23:03:34 +0000872 raise CloneFailure()
873
874
875def _FindRepo():
876 """Look for a repo installation, starting at the current directory.
877 """
ferringb@google.com8db6c882012-12-25 17:02:37 +0000878 curdir = os.getcwd()
msb@chromium.org38b04f82010-07-13 23:03:34 +0000879 repo = None
880
msb@chromium.org2c64b712011-01-11 22:57:47 +0000881 olddir = None
ferringb@google.com8db6c882012-12-25 17:02:37 +0000882 while curdir != '/' \
vapierae39f562016-10-10 19:08:17 -0700883 and curdir != olddir \
884 and not repo:
ferringb@google.com8db6c882012-12-25 17:02:37 +0000885 repo = os.path.join(curdir, repodir, REPO_MAIN)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000886 if not os.path.isfile(repo):
887 repo = None
ferringb@google.com8db6c882012-12-25 17:02:37 +0000888 olddir = curdir
889 curdir = os.path.dirname(curdir)
890 return (repo, os.path.join(curdir, repodir))
msb@chromium.org38b04f82010-07-13 23:03:34 +0000891
892
vapierae39f562016-10-10 19:08:17 -0700893class _Options(object):
msb@chromium.org38b04f82010-07-13 23:03:34 +0000894 help = False
895
896
897def _ParseArguments(args):
898 cmd = None
899 opt = _Options()
900 arg = []
901
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +0000902 for i in range(len(args)):
msb@chromium.org38b04f82010-07-13 23:03:34 +0000903 a = args[i]
904 if a == '-h' or a == '--help':
905 opt.help = True
906
907 elif not a.startswith('-'):
908 cmd = a
909 arg = args[i + 1:]
910 break
911 return cmd, opt, arg
912
913
914def _Usage():
vapierae39f562016-10-10 19:08:17 -0700915 gitc_usage = ""
916 if get_gitc_manifest_dir():
917 gitc_usage = " gitc-init Initialize a GITC Client.\n"
918
Mike Frysingerafe292c2019-08-05 19:15:18 +0000919 print(
vapierae39f562016-10-10 19:08:17 -0700920 """usage: repo COMMAND [ARGS]
msb@chromium.org38b04f82010-07-13 23:03:34 +0000921
922repo is not yet installed. Use "repo init" to install it here.
923
924The most commonly used repo commands are:
925
926 init Install repo in the current working directory
vapierae39f562016-10-10 19:08:17 -0700927""" + gitc_usage +
928 """ help Display detailed help on a command
msb@chromium.org38b04f82010-07-13 23:03:34 +0000929
930For access to the full online help, install repo ("repo init").
Mike Frysingerafe292c2019-08-05 19:15:18 +0000931""")
932 sys.exit(0)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000933
934
935def _Help(args):
936 if args:
937 if args[0] == 'init':
938 init_optparse.print_help()
msb@chromium.org2c64b712011-01-11 22:57:47 +0000939 sys.exit(0)
vapierae39f562016-10-10 19:08:17 -0700940 elif args[0] == 'gitc-init':
941 _GitcInitOptions(init_optparse)
942 init_optparse.print_help()
943 sys.exit(0)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000944 else:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000945 print("error: '%s' is not a bootstrap command.\n"
946 ' For access to online help, install repo ("repo init").'
947 % args[0], file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000948 else:
949 _Usage()
950 sys.exit(1)
951
952
953def _NotInstalled():
Mike Frysingerafe292c2019-08-05 19:15:18 +0000954 print('error: repo is not installed. Use "repo init" to install it here.',
955 file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000956 sys.exit(1)
957
958
959def _NoCommands(cmd):
Mike Frysingerafe292c2019-08-05 19:15:18 +0000960 print("""error: command '%s' requires repo to be installed first.
961 Use "repo init" to install it here.""" % cmd, file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000962 sys.exit(1)
963
964
965def _RunSelf(wrapper_path):
966 my_dir = os.path.dirname(wrapper_path)
967 my_main = os.path.join(my_dir, 'main.py')
968 my_git = os.path.join(my_dir, '.git')
969
970 if os.path.isfile(my_main) and os.path.isdir(my_git):
971 for name in ['git_config.py',
972 'project.py',
973 'subcmds']:
974 if not os.path.exists(os.path.join(my_dir, name)):
975 return None, None
976 return my_main, my_git
977 return None, None
978
979
980def _SetDefaultsTo(gitdir):
981 global REPO_URL
982 global REPO_REV
983
984 REPO_URL = gitdir
985 proc = subprocess.Popen([GIT,
986 '--git-dir=%s' % gitdir,
987 'symbolic-ref',
988 'HEAD'],
vapierae39f562016-10-10 19:08:17 -0700989 stdout=subprocess.PIPE,
990 stderr=subprocess.PIPE)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000991 REPO_REV = proc.stdout.read().strip()
992 proc.stdout.close()
993
994 proc.stderr.read()
995 proc.stderr.close()
996
997 if proc.wait() != 0:
Mike Frysingerafe292c2019-08-05 19:15:18 +0000998 print('fatal: %s has no current branch' % gitdir, file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +0000999 sys.exit(1)
1000
1001
1002def main(orig_args):
msb@chromium.org38b04f82010-07-13 23:03:34 +00001003 cmd, opt, args = _ParseArguments(orig_args)
1004
vapierae39f562016-10-10 19:08:17 -07001005 repo_main, rel_repo_dir = None, None
1006 # Don't use the local repo copy, make sure to switch to the gitc client first.
1007 if cmd != 'gitc-init':
1008 repo_main, rel_repo_dir = _FindRepo()
1009
msb@chromium.org38b04f82010-07-13 23:03:34 +00001010 wrapper_path = os.path.abspath(__file__)
1011 my_main, my_git = _RunSelf(wrapper_path)
1012
vapierae39f562016-10-10 19:08:17 -07001013 cwd = os.getcwd()
1014 if get_gitc_manifest_dir() and cwd.startswith(get_gitc_manifest_dir()):
Mike Frysingerafe292c2019-08-05 19:15:18 +00001015 print('error: repo cannot be used in the GITC local manifest directory.'
1016 '\nIf you want to work on this GITC client please rerun this '
1017 'command from the corresponding client under /gitc/',
1018 file=sys.stderr)
vapierae39f562016-10-10 19:08:17 -07001019 sys.exit(1)
ferringb@google.com8db6c882012-12-25 17:02:37 +00001020 if not repo_main:
msb@chromium.org38b04f82010-07-13 23:03:34 +00001021 if opt.help:
1022 _Usage()
1023 if cmd == 'help':
1024 _Help(args)
1025 if not cmd:
1026 _NotInstalled()
vapierae39f562016-10-10 19:08:17 -07001027 if cmd == 'init' or cmd == 'gitc-init':
msb@chromium.org38b04f82010-07-13 23:03:34 +00001028 if my_git:
1029 _SetDefaultsTo(my_git)
1030 try:
vapierae39f562016-10-10 19:08:17 -07001031 _Init(args, gitc_init=(cmd == 'gitc-init'))
msb@chromium.org38b04f82010-07-13 23:03:34 +00001032 except CloneFailure:
Don Garrett24f2cc02018-12-18 18:07:17 +00001033 path = os.path.join(repodir, S_repo)
Mike Frysingerafe292c2019-08-05 19:15:18 +00001034 print("fatal: cloning the git-repo repository failed, will remove "
1035 "'%s' " % path, file=sys.stderr)
Don Garrett24f2cc02018-12-18 18:07:17 +00001036 shutil.rmtree(path, ignore_errors=True)
msb@chromium.org38b04f82010-07-13 23:03:34 +00001037 sys.exit(1)
ferringb@google.com8db6c882012-12-25 17:02:37 +00001038 repo_main, rel_repo_dir = _FindRepo()
msb@chromium.org38b04f82010-07-13 23:03:34 +00001039 else:
1040 _NoCommands(cmd)
1041
1042 if my_main:
ferringb@google.com8db6c882012-12-25 17:02:37 +00001043 repo_main = my_main
msb@chromium.org38b04f82010-07-13 23:03:34 +00001044
akeshet@google.com3bdfbeb2014-02-06 04:52:54 +00001045 ver_str = '.'.join(map(str, VERSION))
1046 me = [sys.executable, repo_main,
ferringb@google.com8db6c882012-12-25 17:02:37 +00001047 '--repo-dir=%s' % rel_repo_dir,
msb@chromium.org38b04f82010-07-13 23:03:34 +00001048 '--wrapper-version=%s' % ver_str,
1049 '--wrapper-path=%s' % wrapper_path,
1050 '--']
1051 me.extend(orig_args)
1052 me.extend(extra_args)
1053 try:
Don Garrett24f2cc02018-12-18 18:07:17 +00001054 if platform.system() == "Windows":
1055 sys.exit(subprocess.call(me))
1056 else:
1057 os.execv(sys.executable, me)
ferringb@google.com8db6c882012-12-25 17:02:37 +00001058 except OSError as e:
Mike Frysingerafe292c2019-08-05 19:15:18 +00001059 print("fatal: unable to start %s" % repo_main, file=sys.stderr)
1060 print("fatal: %s" % e, file=sys.stderr)
msb@chromium.org38b04f82010-07-13 23:03:34 +00001061 sys.exit(148)
1062
1063
1064if __name__ == '__main__':
1065 main(sys.argv[1:])