| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- #
- # Copyright (C) 2008 The Android Open Source Project
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import os
- import shutil
- import sys
- from color import Coloring
- from command import InteractiveCommand, MirrorSafeCommand
- from error import ManifestParseError
- from project import SyncBuffer
- from git_config import GitConfig
- from git_command import git_require, MIN_GIT_VERSION
- from git_config import GitConfig
- class Init(InteractiveCommand, MirrorSafeCommand):
- common = True
- helpSummary = "Initialize repo in the current directory"
- helpUsage = """
- %prog [options]
- """
- helpDescription = """
- The '%prog' command is run once to install and initialize repo.
- The latest repo source code and manifest collection is downloaded
- from the server and is installed in the .repo/ directory in the
- current working directory.
- The optional -u argument can be used to specify a URL to the
- manifest project. It is also possible to have a git configuration
- section as below to use 'identifier' as argument to -u:
- [repo-manifest "identifier"]
- url = ...
- server = ...
- reference = ...
- Only the url is required - the others are optional.
- If no -u argument is specified, the 'repo-manifest' section named
- 'default' will be used if present.
- The optional -b argument can be used to select the manifest branch
- to checkout and use. If no branch is specified, master is assumed.
- The optional -m argument can be used to specify an alternate manifest
- to be used. If no manifest is specified, the manifest default.xml
- will be used.
- The --reference option can be used to point to a directory that
- has the content of a --mirror sync. This will make the working
- directory use as much data as possible from the local reference
- directory when fetching from the server. This will make the sync
- go a lot faster by reducing data traffic on the network.
- Switching Manifest Branches
- ---------------------------
- To switch to another manifest branch, `repo init -b otherbranch`
- may be used in an existing client. However, as this only updates the
- manifest, a subsequent `repo sync` (or `repo sync -d`) is necessary
- to update the working directory files.
- """
- def _Options(self, p):
- # Logging
- g = p.add_option_group('Logging options')
- g.add_option('-q', '--quiet',
- dest="quiet", action="store_true", default=False,
- help="be quiet")
- # Manifest
- g = p.add_option_group('Manifest options')
- g.add_option('-u', '--manifest-url',
- dest='manifest_url', default='default',
- help='manifest repository location', metavar='URL')
- g.add_option('-b', '--manifest-branch',
- dest='manifest_branch',
- help='manifest branch or revision', metavar='REVISION')
- g.add_option('-m', '--manifest-name',
- dest='manifest_name', default='default.xml',
- help='initial manifest file', metavar='NAME.xml')
- g.add_option('--mirror',
- dest='mirror', action='store_true',
- help='mirror the forrest')
- g.add_option('--reference',
- dest='reference',
- help='location of mirror directory', metavar='DIR')
- g.add_option('--depth', type='int', default=None,
- dest='depth',
- help='create a shallow clone with given depth; see git clone')
- # Tool
- g = p.add_option_group('repo Version options')
- g.add_option('--repo-url',
- dest='repo_url',
- help='repo repository location', metavar='URL')
- g.add_option('--repo-branch',
- dest='repo_branch',
- help='repo branch or revision', metavar='REVISION')
- g.add_option('--no-repo-verify',
- dest='no_repo_verify', action='store_true',
- help='do not verify repo source code')
- # Other
- g = p.add_option_group('Other options')
- g.add_option('--config-name',
- dest='config_name', action="store_true", default=False,
- help='Always prompt for name/e-mail')
- def _SyncManifest(self, opt):
- m = self.manifest.manifestProject
- is_new = not m.Exists
- manifest_server = None
- # The manifest url may point out a manifest section in the config
- key = 'repo-manifest.%s.' % opt.manifest_url
- if GitConfig.ForUser().GetString(key + 'url'):
- opt.manifest_url = GitConfig.ForUser().GetString(key + 'url')
- # Also copy other options to the manifest config if not specified already.
- if not opt.reference:
- opt.reference = GitConfig.ForUser().GetString(key + 'reference')
- manifest_server = GitConfig.ForUser().GetString(key + 'server')
- if is_new:
- if not opt.manifest_url or opt.manifest_url == 'default':
- print >>sys.stderr, """\
- fatal: missing manifest url (-u) and no default found.
- tip: The global git configuration key 'repo-manifest.default.url' can
- be used to specify a default url."""
- sys.exit(1)
- if not opt.quiet:
- print >>sys.stderr, 'Get %s' \
- % GitConfig.ForUser().UrlInsteadOf(opt.manifest_url)
- m._InitGitDir()
- if opt.manifest_branch:
- m.revisionExpr = opt.manifest_branch
- else:
- m.revisionExpr = 'refs/heads/master'
- else:
- if opt.manifest_branch:
- m.revisionExpr = opt.manifest_branch
- else:
- m.PreSync()
- if opt.manifest_url:
- r = m.GetRemote(m.remote.name)
- r.url = opt.manifest_url
- r.ResetFetch()
- r.Save()
- if manifest_server:
- m.config.SetString('repo.manifest-server', manifest_server)
- if opt.reference:
- m.config.SetString('repo.reference', opt.reference)
- if opt.mirror:
- if is_new:
- m.config.SetString('repo.mirror', 'true')
- else:
- print >>sys.stderr, 'fatal: --mirror not supported on existing client'
- sys.exit(1)
- if not m.Sync_NetworkHalf(is_new=is_new):
- r = m.GetRemote(m.remote.name)
- print >>sys.stderr, 'fatal: cannot obtain manifest %s' % r.url
- # Better delete the manifest git dir if we created it; otherwise next
- # time (when user fixes problems) we won't go through the "is_new" logic.
- if is_new:
- shutil.rmtree(m.gitdir)
- sys.exit(1)
- syncbuf = SyncBuffer(m.config)
- m.Sync_LocalHalf(syncbuf)
- syncbuf.Finish()
- if is_new or m.CurrentBranch is None:
- if not m.StartBranch('default'):
- print >>sys.stderr, 'fatal: cannot create default in manifest'
- sys.exit(1)
- def _LinkManifest(self, name):
- if not name:
- print >>sys.stderr, 'fatal: manifest name (-m) is required.'
- sys.exit(1)
- try:
- self.manifest.Link(name)
- except ManifestParseError, e:
- print >>sys.stderr, "fatal: manifest '%s' not available" % name
- print >>sys.stderr, 'fatal: %s' % str(e)
- sys.exit(1)
- def _Prompt(self, prompt, value):
- mp = self.manifest.manifestProject
- sys.stdout.write('%-10s [%s]: ' % (prompt, value))
- a = sys.stdin.readline().strip()
- if a == '':
- return value
- return a
- def _ShouldConfigureUser(self):
- gc = self.manifest.globalConfig
- mp = self.manifest.manifestProject
- # If we don't have local settings, get from global.
- if not mp.config.Has('user.name') or not mp.config.Has('user.email'):
- if not gc.Has('user.name') or not gc.Has('user.email'):
- return True
- mp.config.SetString('user.name', gc.GetString('user.name'))
- mp.config.SetString('user.email', gc.GetString('user.email'))
- print ''
- print 'Your identity is: %s <%s>' % (mp.config.GetString('user.name'),
- mp.config.GetString('user.email'))
- print 'If you want to change this, please re-run \'repo init\' with --config-name'
- return False
- def _ConfigureUser(self):
- mp = self.manifest.manifestProject
- while True:
- print ''
- name = self._Prompt('Your Name', mp.UserName)
- email = self._Prompt('Your Email', mp.UserEmail)
- print ''
- print 'Your identity is: %s <%s>' % (name, email)
- sys.stdout.write('is this correct [y/N]? ')
- a = sys.stdin.readline().strip()
- if a in ('yes', 'y', 't', 'true'):
- break
- if name != mp.UserName:
- mp.config.SetString('user.name', name)
- if email != mp.UserEmail:
- mp.config.SetString('user.email', email)
- def _HasColorSet(self, gc):
- for n in ['ui', 'diff', 'status']:
- if gc.Has('color.%s' % n):
- return True
- return False
- def _ConfigureColor(self):
- gc = self.manifest.globalConfig
- if self._HasColorSet(gc):
- return
- class _Test(Coloring):
- def __init__(self):
- Coloring.__init__(self, gc, 'test color display')
- self._on = True
- out = _Test()
- print ''
- print "Testing colorized output (for 'repo diff', 'repo status'):"
- for c in ['black','red','green','yellow','blue','magenta','cyan']:
- out.write(' ')
- out.printer(fg=c)(' %-6s ', c)
- out.write(' ')
- out.printer(fg='white', bg='black')(' %s ' % 'white')
- out.nl()
- for c in ['bold','dim','ul','reverse']:
- out.write(' ')
- out.printer(fg='black', attr=c)(' %-6s ', c)
- out.nl()
- sys.stdout.write('Enable color display in this user account (y/N)? ')
- a = sys.stdin.readline().strip().lower()
- if a in ('y', 'yes', 't', 'true', 'on'):
- gc.SetString('color.ui', 'auto')
- def _ConfigureDepth(self, opt):
- """Configure the depth we'll sync down.
- Args:
- opt: Options from optparse. We care about opt.depth.
- """
- # Opt.depth will be non-None if user actually passed --depth to repo init.
- if opt.depth is not None:
- if opt.depth > 0:
- # Positive values will set the depth.
- depth = str(opt.depth)
- else:
- # Negative numbers will clear the depth; passing None to SetString
- # will do that.
- depth = None
- # We store the depth in the main manifest project.
- self.manifest.manifestProject.config.SetString('repo.depth', depth)
- def Execute(self, opt, args):
- git_require(MIN_GIT_VERSION, fail=True)
- self._SyncManifest(opt)
- self._LinkManifest(opt.manifest_name)
- if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror:
- if opt.config_name or self._ShouldConfigureUser():
- self._ConfigureUser()
- self._ConfigureColor()
- self._ConfigureDepth(opt)
- if self.manifest.IsMirror:
- type = 'mirror '
- else:
- type = ''
- print ''
- print 'repo %sinitialized in %s' % (type, self.manifest.topdir)
|