summaryrefslogtreecommitdiffstats
path: root/subcmds/init.py
diff options
context:
space:
mode:
Diffstat (limited to 'subcmds/init.py')
-rw-r--r--subcmds/init.py362
1 files changed, 216 insertions, 146 deletions
diff --git a/subcmds/init.py b/subcmds/init.py
index 6594a602..9c6b2ad9 100644
--- a/subcmds/init.py
+++ b/subcmds/init.py
@@ -1,5 +1,3 @@
1# -*- coding:utf-8 -*-
2#
3# Copyright (C) 2008 The Android Open Source Project 1# Copyright (C) 2008 The Android Open Source Project
4# 2#
5# Licensed under the Apache License, Version 2.0 (the "License"); 3# Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,34 +12,30 @@
14# See the License for the specific language governing permissions and 12# See the License for the specific language governing permissions and
15# limitations under the License. 13# limitations under the License.
16 14
17from __future__ import print_function
18import os 15import os
19import platform 16import platform
20import re 17import re
18import subprocess
21import sys 19import sys
22 20import urllib.parse
23from pyversion import is_python3
24if is_python3():
25 import urllib.parse
26else:
27 import imp
28 import urlparse
29 urllib = imp.new_module('urllib')
30 urllib.parse = urlparse
31 21
32from color import Coloring 22from color import Coloring
33from command import InteractiveCommand, MirrorSafeCommand 23from command import InteractiveCommand, MirrorSafeCommand
34from error import ManifestParseError 24from error import ManifestParseError
35from project import SyncBuffer 25from project import SyncBuffer
36from git_config import GitConfig 26from git_config import GitConfig
37from git_command import git_require, MIN_GIT_VERSION 27from git_command import git_require, MIN_GIT_VERSION_SOFT, MIN_GIT_VERSION_HARD
28import fetch
29import git_superproject
38import platform_utils 30import platform_utils
31from wrapper import Wrapper
32
39 33
40class Init(InteractiveCommand, MirrorSafeCommand): 34class Init(InteractiveCommand, MirrorSafeCommand):
41 common = True 35 COMMON = True
42 helpSummary = "Initialize repo in the current directory" 36 helpSummary = "Initialize a repo client checkout in the current directory"
43 helpUsage = """ 37 helpUsage = """
44%prog [options] 38%prog [options] [manifest url]
45""" 39"""
46 helpDescription = """ 40 helpDescription = """
47The '%prog' command is run once to install and initialize repo. 41The '%prog' command is run once to install and initialize repo.
@@ -49,13 +43,24 @@ The latest repo source code and manifest collection is downloaded
49from the server and is installed in the .repo/ directory in the 43from the server and is installed in the .repo/ directory in the
50current working directory. 44current working directory.
51 45
46When creating a new checkout, the manifest URL is the only required setting.
47It may be specified using the --manifest-url option, or as the first optional
48argument.
49
52The optional -b argument can be used to select the manifest branch 50The optional -b argument can be used to select the manifest branch
53to checkout and use. If no branch is specified, master is assumed. 51to checkout and use. If no branch is specified, the remote's default
52branch is used. This is equivalent to using -b HEAD.
54 53
55The optional -m argument can be used to specify an alternate manifest 54The optional -m argument can be used to specify an alternate manifest
56to be used. If no manifest is specified, the manifest default.xml 55to be used. If no manifest is specified, the manifest default.xml
57will be used. 56will be used.
58 57
58If the --standalone-manifest argument is set, the manifest will be downloaded
59directly from the specified --manifest-url as a static file (rather than
60setting up a manifest git checkout). With --standalone-manifest, the manifest
61will be fully static and will not be re-downloaded during subsesquent
62`repo init` and `repo sync` calls.
63
59The --reference option can be used to point to a directory that 64The --reference option can be used to point to a directory that
60has the content of a --mirror sync. This will make the working 65has the content of a --mirror sync. This will make the working
61directory use as much data as possible from the local reference 66directory use as much data as possible from the local reference
@@ -81,109 +86,64 @@ manifest, a subsequent `repo sync` (or `repo sync -d`) is necessary
81to update the working directory files. 86to update the working directory files.
82""" 87"""
83 88
89 def _CommonOptions(self, p):
90 """Disable due to re-use of Wrapper()."""
91
84 def _Options(self, p, gitc_init=False): 92 def _Options(self, p, gitc_init=False):
85 # Logging 93 Wrapper().InitParser(p, gitc_init=gitc_init)
86 g = p.add_option_group('Logging options')
87 g.add_option('-q', '--quiet',
88 dest="quiet", action="store_true", default=False,
89 help="be quiet")
90
91 # Manifest
92 g = p.add_option_group('Manifest options')
93 g.add_option('-u', '--manifest-url',
94 dest='manifest_url',
95 help='manifest repository location', metavar='URL')
96 g.add_option('-b', '--manifest-branch',
97 dest='manifest_branch',
98 help='manifest branch or revision', metavar='REVISION')
99 cbr_opts = ['--current-branch']
100 # The gitc-init subcommand allocates -c itself, but a lot of init users
101 # want -c, so try to satisfy both as best we can.
102 if not gitc_init:
103 cbr_opts += ['-c']
104 g.add_option(*cbr_opts,
105 dest='current_branch_only', action='store_true',
106 help='fetch only current manifest branch from server')
107 g.add_option('-m', '--manifest-name',
108 dest='manifest_name', default='default.xml',
109 help='initial manifest file', metavar='NAME.xml')
110 g.add_option('--mirror',
111 dest='mirror', action='store_true',
112 help='create a replica of the remote repositories '
113 'rather than a client working directory')
114 g.add_option('--reference',
115 dest='reference',
116 help='location of mirror directory', metavar='DIR')
117 g.add_option('--dissociate',
118 dest='dissociate', action='store_true',
119 help='dissociate from reference mirrors after clone')
120 g.add_option('--depth', type='int', default=None,
121 dest='depth',
122 help='create a shallow clone with given depth; see git clone')
123 g.add_option('--partial-clone', action='store_true',
124 dest='partial_clone',
125 help='perform partial clone (https://git-scm.com/'
126 'docs/gitrepository-layout#_code_partialclone_code)')
127 g.add_option('--clone-filter', action='store', default='blob:none',
128 dest='clone_filter',
129 help='filter for use with --partial-clone [default: %default]')
130 g.add_option('--archive',
131 dest='archive', action='store_true',
132 help='checkout an archive instead of a git repository for '
133 'each project. See git archive.')
134 g.add_option('--submodules',
135 dest='submodules', action='store_true',
136 help='sync any submodules associated with the manifest repo')
137 g.add_option('-g', '--groups',
138 dest='groups', default='default',
139 help='restrict manifest projects to ones with specified '
140 'group(s) [default|all|G1,G2,G3|G4,-G5,-G6]',
141 metavar='GROUP')
142 g.add_option('-p', '--platform',
143 dest='platform', default='auto',
144 help='restrict manifest projects to ones with a specified '
145 'platform group [auto|all|none|linux|darwin|...]',
146 metavar='PLATFORM')
147 g.add_option('--no-clone-bundle',
148 dest='no_clone_bundle', action='store_true',
149 help='disable use of /clone.bundle on HTTP/HTTPS')
150 g.add_option('--no-tags',
151 dest='no_tags', action='store_true',
152 help="don't fetch tags in the manifest")
153
154 # Tool
155 g = p.add_option_group('repo Version options')
156 g.add_option('--repo-url',
157 dest='repo_url',
158 help='repo repository location', metavar='URL')
159 g.add_option('--repo-branch',
160 dest='repo_branch',
161 help='repo branch or revision', metavar='REVISION')
162 g.add_option('--no-repo-verify',
163 dest='no_repo_verify', action='store_true',
164 help='do not verify repo source code')
165
166 # Other
167 g = p.add_option_group('Other options')
168 g.add_option('--config-name',
169 dest='config_name', action="store_true", default=False,
170 help='Always prompt for name/e-mail')
171 94
172 def _RegisteredEnvironmentOptions(self): 95 def _RegisteredEnvironmentOptions(self):
173 return {'REPO_MANIFEST_URL': 'manifest_url', 96 return {'REPO_MANIFEST_URL': 'manifest_url',
174 'REPO_MIRROR_LOCATION': 'reference'} 97 'REPO_MIRROR_LOCATION': 'reference'}
175 98
99 def _CloneSuperproject(self, opt):
100 """Clone the superproject based on the superproject's url and branch.
101
102 Args:
103 opt: Program options returned from optparse. See _Options().
104 """
105 superproject = git_superproject.Superproject(self.manifest,
106 self.repodir,
107 self.git_event_log,
108 quiet=opt.quiet)
109 sync_result = superproject.Sync()
110 if not sync_result.success:
111 print('warning: git update of superproject failed, repo sync will not '
112 'use superproject to fetch source; while this error is not fatal, '
113 'and you can continue to run repo sync, please run repo init with '
114 'the --no-use-superproject option to stop seeing this warning',
115 file=sys.stderr)
116 if sync_result.fatal and opt.use_superproject is not None:
117 sys.exit(1)
118
176 def _SyncManifest(self, opt): 119 def _SyncManifest(self, opt):
177 m = self.manifest.manifestProject 120 m = self.manifest.manifestProject
178 is_new = not m.Exists 121 is_new = not m.Exists
179 122
123 # If repo has already been initialized, we take -u with the absence of
124 # --standalone-manifest to mean "transition to a standard repo set up",
125 # which necessitates starting fresh.
126 # If --standalone-manifest is set, we always tear everything down and start
127 # anew.
128 if not is_new:
129 was_standalone_manifest = m.config.GetString('manifest.standalone')
130 if opt.standalone_manifest or (
131 was_standalone_manifest and opt.manifest_url):
132 m.config.ClearCache()
133 if m.gitdir and os.path.exists(m.gitdir):
134 platform_utils.rmtree(m.gitdir)
135 if m.worktree and os.path.exists(m.worktree):
136 platform_utils.rmtree(m.worktree)
137
138 is_new = not m.Exists
180 if is_new: 139 if is_new:
181 if not opt.manifest_url: 140 if not opt.manifest_url:
182 print('fatal: manifest url (-u) is required.', file=sys.stderr) 141 print('fatal: manifest url is required.', file=sys.stderr)
183 sys.exit(1) 142 sys.exit(1)
184 143
185 if not opt.quiet: 144 if not opt.quiet:
186 print('Get %s' % GitConfig.ForUser().UrlInsteadOf(opt.manifest_url), 145 print('Downloading manifest from %s' %
146 (GitConfig.ForUser().UrlInsteadOf(opt.manifest_url),),
187 file=sys.stderr) 147 file=sys.stderr)
188 148
189 # The manifest project object doesn't keep track of the path on the 149 # The manifest project object doesn't keep track of the path on the
@@ -200,30 +160,52 @@ to update the working directory files.
200 160
201 m._InitGitDir(mirror_git=mirrored_manifest_git) 161 m._InitGitDir(mirror_git=mirrored_manifest_git)
202 162
203 if opt.manifest_branch: 163 # If standalone_manifest is set, mark the project as "standalone" -- we'll
204 m.revisionExpr = opt.manifest_branch 164 # still do much of the manifests.git set up, but will avoid actual syncs to
205 else: 165 # a remote.
206 m.revisionExpr = 'refs/heads/master' 166 standalone_manifest = False
207 else: 167 if opt.standalone_manifest:
208 if opt.manifest_branch: 168 standalone_manifest = True
209 m.revisionExpr = opt.manifest_branch 169 elif not opt.manifest_url:
210 else: 170 # If -u is set and --standalone-manifest is not, then we're not in
211 m.PreSync() 171 # standalone mode. Otherwise, use config to infer what we were in the last
172 # init.
173 standalone_manifest = bool(m.config.GetString('manifest.standalone'))
174 m.config.SetString('manifest.standalone', opt.manifest_url)
212 175
213 self._ConfigureDepth(opt) 176 self._ConfigureDepth(opt)
214 177
178 # Set the remote URL before the remote branch as we might need it below.
215 if opt.manifest_url: 179 if opt.manifest_url:
216 r = m.GetRemote(m.remote.name) 180 r = m.GetRemote(m.remote.name)
217 r.url = opt.manifest_url 181 r.url = opt.manifest_url
218 r.ResetFetch() 182 r.ResetFetch()
219 r.Save() 183 r.Save()
220 184
185 if not standalone_manifest:
186 if opt.manifest_branch:
187 if opt.manifest_branch == 'HEAD':
188 opt.manifest_branch = m.ResolveRemoteHead()
189 if opt.manifest_branch is None:
190 print('fatal: unable to resolve HEAD', file=sys.stderr)
191 sys.exit(1)
192 m.revisionExpr = opt.manifest_branch
193 else:
194 if is_new:
195 default_branch = m.ResolveRemoteHead()
196 if default_branch is None:
197 # If the remote doesn't have HEAD configured, default to master.
198 default_branch = 'refs/heads/master'
199 m.revisionExpr = default_branch
200 else:
201 m.PreSync()
202
221 groups = re.split(r'[,\s]+', opt.groups) 203 groups = re.split(r'[,\s]+', opt.groups)
222 all_platforms = ['linux', 'darwin', 'windows'] 204 all_platforms = ['linux', 'darwin', 'windows']
223 platformize = lambda x: 'platform-' + x 205 platformize = lambda x: 'platform-' + x
224 if opt.platform == 'auto': 206 if opt.platform == 'auto':
225 if (not opt.mirror and 207 if (not opt.mirror and
226 not m.config.GetString('repo.mirror') == 'true'): 208 not m.config.GetString('repo.mirror') == 'true'):
227 groups.append(platformize(platform.system().lower())) 209 groups.append(platformize(platform.system().lower()))
228 elif opt.platform == 'all': 210 elif opt.platform == 'all':
229 groups.extend(map(platformize, all_platforms)) 211 groups.extend(map(platformize, all_platforms))
@@ -235,7 +217,7 @@ to update the working directory files.
235 217
236 groups = [x for x in groups if x] 218 groups = [x for x in groups if x]
237 groupstr = ','.join(groups) 219 groupstr = ','.join(groups)
238 if opt.platform == 'auto' and groupstr == 'default,platform-' + platform.system().lower(): 220 if opt.platform == 'auto' and groupstr == self.manifest.GetDefaultGroupsStr():
239 groupstr = None 221 groupstr = None
240 m.config.SetString('manifest.groups', groupstr) 222 m.config.SetString('manifest.groups', groupstr)
241 223
@@ -243,11 +225,25 @@ to update the working directory files.
243 m.config.SetString('repo.reference', opt.reference) 225 m.config.SetString('repo.reference', opt.reference)
244 226
245 if opt.dissociate: 227 if opt.dissociate:
246 m.config.SetString('repo.dissociate', 'true') 228 m.config.SetBoolean('repo.dissociate', opt.dissociate)
229
230 if opt.worktree:
231 if opt.mirror:
232 print('fatal: --mirror and --worktree are incompatible',
233 file=sys.stderr)
234 sys.exit(1)
235 if opt.submodules:
236 print('fatal: --submodules and --worktree are incompatible',
237 file=sys.stderr)
238 sys.exit(1)
239 m.config.SetBoolean('repo.worktree', opt.worktree)
240 if is_new:
241 m.use_git_worktrees = True
242 print('warning: --worktree is experimental!', file=sys.stderr)
247 243
248 if opt.archive: 244 if opt.archive:
249 if is_new: 245 if is_new:
250 m.config.SetString('repo.archive', 'true') 246 m.config.SetBoolean('repo.archive', opt.archive)
251 else: 247 else:
252 print('fatal: --archive is only supported when initializing a new ' 248 print('fatal: --archive is only supported when initializing a new '
253 'workspace.', file=sys.stderr) 249 'workspace.', file=sys.stderr)
@@ -257,7 +253,7 @@ to update the working directory files.
257 253
258 if opt.mirror: 254 if opt.mirror:
259 if is_new: 255 if is_new:
260 m.config.SetString('repo.mirror', 'true') 256 m.config.SetBoolean('repo.mirror', opt.mirror)
261 else: 257 else:
262 print('fatal: --mirror is only supported when initializing a new ' 258 print('fatal: --mirror is only supported when initializing a new '
263 'workspace.', file=sys.stderr) 259 'workspace.', file=sys.stderr)
@@ -265,25 +261,49 @@ to update the working directory files.
265 'in another location.', file=sys.stderr) 261 'in another location.', file=sys.stderr)
266 sys.exit(1) 262 sys.exit(1)
267 263
268 if opt.partial_clone: 264 if opt.partial_clone is not None:
269 if opt.mirror: 265 if opt.mirror:
270 print('fatal: --mirror and --partial-clone are mutually exclusive', 266 print('fatal: --mirror and --partial-clone are mutually exclusive',
271 file=sys.stderr) 267 file=sys.stderr)
272 sys.exit(1) 268 sys.exit(1)
273 m.config.SetString('repo.partialclone', 'true') 269 m.config.SetBoolean('repo.partialclone', opt.partial_clone)
274 if opt.clone_filter: 270 if opt.clone_filter:
275 m.config.SetString('repo.clonefilter', opt.clone_filter) 271 m.config.SetString('repo.clonefilter', opt.clone_filter)
272 elif m.config.GetBoolean('repo.partialclone'):
273 opt.clone_filter = m.config.GetString('repo.clonefilter')
276 else: 274 else:
277 opt.clone_filter = None 275 opt.clone_filter = None
278 276
277 if opt.partial_clone_exclude is not None:
278 m.config.SetString('repo.partialcloneexclude', opt.partial_clone_exclude)
279
280 if opt.clone_bundle is None:
281 opt.clone_bundle = False if opt.partial_clone else True
282 else:
283 m.config.SetBoolean('repo.clonebundle', opt.clone_bundle)
284
279 if opt.submodules: 285 if opt.submodules:
280 m.config.SetString('repo.submodules', 'true') 286 m.config.SetBoolean('repo.submodules', opt.submodules)
287
288 if opt.use_superproject is not None:
289 m.config.SetBoolean('repo.superproject', opt.use_superproject)
290
291 if standalone_manifest:
292 if is_new:
293 manifest_name = 'default.xml'
294 manifest_data = fetch.fetch_file(opt.manifest_url)
295 dest = os.path.join(m.worktree, manifest_name)
296 os.makedirs(os.path.dirname(dest), exist_ok=True)
297 with open(dest, 'wb') as f:
298 f.write(manifest_data)
299 return
281 300
282 if not m.Sync_NetworkHalf(is_new=is_new, quiet=opt.quiet, 301 if not m.Sync_NetworkHalf(is_new=is_new, quiet=opt.quiet, verbose=opt.verbose,
283 clone_bundle=not opt.no_clone_bundle, 302 clone_bundle=opt.clone_bundle,
284 current_branch_only=opt.current_branch_only, 303 current_branch_only=opt.current_branch_only,
285 no_tags=opt.no_tags, submodules=opt.submodules, 304 tags=opt.tags, submodules=opt.submodules,
286 clone_filter=opt.clone_filter): 305 clone_filter=opt.clone_filter,
306 partial_clone_exclude=self.manifest.PartialCloneExclude):
287 r = m.GetRemote(m.remote.name) 307 r = m.GetRemote(m.remote.name)
288 print('fatal: cannot obtain manifest %s' % r.url, file=sys.stderr) 308 print('fatal: cannot obtain manifest %s' % r.url, file=sys.stderr)
289 309
@@ -326,8 +346,8 @@ to update the working directory files.
326 return value 346 return value
327 return a 347 return a
328 348
329 def _ShouldConfigureUser(self): 349 def _ShouldConfigureUser(self, opt):
330 gc = self.manifest.globalConfig 350 gc = self.client.globalConfig
331 mp = self.manifest.manifestProject 351 mp = self.manifest.manifestProject
332 352
333 # If we don't have local settings, get from global. 353 # If we don't have local settings, get from global.
@@ -338,21 +358,24 @@ to update the working directory files.
338 mp.config.SetString('user.name', gc.GetString('user.name')) 358 mp.config.SetString('user.name', gc.GetString('user.name'))
339 mp.config.SetString('user.email', gc.GetString('user.email')) 359 mp.config.SetString('user.email', gc.GetString('user.email'))
340 360
341 print() 361 if not opt.quiet:
342 print('Your identity is: %s <%s>' % (mp.config.GetString('user.name'), 362 print()
343 mp.config.GetString('user.email'))) 363 print('Your identity is: %s <%s>' % (mp.config.GetString('user.name'),
344 print('If you want to change this, please re-run \'repo init\' with --config-name') 364 mp.config.GetString('user.email')))
365 print("If you want to change this, please re-run 'repo init' with --config-name")
345 return False 366 return False
346 367
347 def _ConfigureUser(self): 368 def _ConfigureUser(self, opt):
348 mp = self.manifest.manifestProject 369 mp = self.manifest.manifestProject
349 370
350 while True: 371 while True:
351 print() 372 if not opt.quiet:
352 name = self._Prompt('Your Name', mp.UserName) 373 print()
374 name = self._Prompt('Your Name', mp.UserName)
353 email = self._Prompt('Your Email', mp.UserEmail) 375 email = self._Prompt('Your Email', mp.UserEmail)
354 376
355 print() 377 if not opt.quiet:
378 print()
356 print('Your identity is: %s <%s>' % (name, email)) 379 print('Your identity is: %s <%s>' % (name, email))
357 print('is this correct [y/N]? ', end='') 380 print('is this correct [y/N]? ', end='')
358 # TODO: When we require Python 3, use flush=True w/print above. 381 # TODO: When we require Python 3, use flush=True w/print above.
@@ -373,7 +396,7 @@ to update the working directory files.
373 return False 396 return False
374 397
375 def _ConfigureColor(self): 398 def _ConfigureColor(self):
376 gc = self.manifest.globalConfig 399 gc = self.client.globalConfig
377 if self._HasColorSet(gc): 400 if self._HasColorSet(gc):
378 return 401 return
379 402
@@ -424,15 +447,16 @@ to update the working directory files.
424 # We store the depth in the main manifest project. 447 # We store the depth in the main manifest project.
425 self.manifest.manifestProject.config.SetString('repo.depth', depth) 448 self.manifest.manifestProject.config.SetString('repo.depth', depth)
426 449
427 def _DisplayResult(self): 450 def _DisplayResult(self, opt):
428 if self.manifest.IsMirror: 451 if self.manifest.IsMirror:
429 init_type = 'mirror ' 452 init_type = 'mirror '
430 else: 453 else:
431 init_type = '' 454 init_type = ''
432 455
433 print() 456 if not opt.quiet:
434 print('repo %shas been initialized in %s' 457 print()
435 % (init_type, self.manifest.topdir)) 458 print('repo %shas been initialized in %s' %
459 (init_type, self.manifest.topdir))
436 460
437 current_dir = os.getcwd() 461 current_dir = os.getcwd()
438 if current_dir != self.manifest.topdir: 462 if current_dir != self.manifest.topdir:
@@ -450,15 +474,61 @@ to update the working directory files.
450 if opt.archive and opt.mirror: 474 if opt.archive and opt.mirror:
451 self.OptionParser.error('--mirror and --archive cannot be used together.') 475 self.OptionParser.error('--mirror and --archive cannot be used together.')
452 476
477 if opt.standalone_manifest and (
478 opt.manifest_branch or opt.manifest_name != 'default.xml'):
479 self.OptionParser.error('--manifest-branch and --manifest-name cannot'
480 ' be used with --standalone-manifest.')
481
482 if args:
483 if opt.manifest_url:
484 self.OptionParser.error(
485 '--manifest-url option and URL argument both specified: only use '
486 'one to select the manifest URL.')
487
488 opt.manifest_url = args.pop(0)
489
490 if args:
491 self.OptionParser.error('too many arguments to init')
492
453 def Execute(self, opt, args): 493 def Execute(self, opt, args):
454 git_require(MIN_GIT_VERSION, fail=True) 494 git_require(MIN_GIT_VERSION_HARD, fail=True)
495 if not git_require(MIN_GIT_VERSION_SOFT):
496 print('repo: warning: git-%s+ will soon be required; please upgrade your '
497 'version of git to maintain support.'
498 % ('.'.join(str(x) for x in MIN_GIT_VERSION_SOFT),),
499 file=sys.stderr)
500
501 rp = self.manifest.repoProject
502
503 # Handle new --repo-url requests.
504 if opt.repo_url:
505 remote = rp.GetRemote('origin')
506 remote.url = opt.repo_url
507 remote.Save()
508
509 # Handle new --repo-rev requests.
510 if opt.repo_rev:
511 wrapper = Wrapper()
512 remote_ref, rev = wrapper.check_repo_rev(
513 rp.gitdir, opt.repo_rev, repo_verify=opt.repo_verify, quiet=opt.quiet)
514 branch = rp.GetBranch('default')
515 branch.merge = remote_ref
516 rp.work_git.reset('--hard', rev)
517 branch.Save()
518
519 if opt.worktree:
520 # Older versions of git supported worktree, but had dangerous gc bugs.
521 git_require((2, 15, 0), fail=True, msg='git gc worktree corruption')
455 522
456 self._SyncManifest(opt) 523 self._SyncManifest(opt)
457 self._LinkManifest(opt.manifest_name) 524 self._LinkManifest(opt.manifest_name)
458 525
526 if self.manifest.manifestProject.config.GetBoolean('repo.superproject'):
527 self._CloneSuperproject(opt)
528
459 if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror: 529 if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror:
460 if opt.config_name or self._ShouldConfigureUser(): 530 if opt.config_name or self._ShouldConfigureUser(opt):
461 self._ConfigureUser() 531 self._ConfigureUser(opt)
462 self._ConfigureColor() 532 self._ConfigureColor()
463 533
464 self._DisplayResult() 534 self._DisplayResult(opt)