mirror of
https://gerrit.googlesource.com/git-repo
synced 2025-06-26 20:17:52 +00:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
34fb20f67c | |||
ecff4f17b0 | |||
cc14fa9820 | |||
3ce2a6b46b | |||
841be34968 | |||
ee1c2f5717 | |||
6a1f737380 | |||
e9311273dd | |||
605a9a487b | |||
2a32f6afa6 | |||
498fe90b45 | |||
53d6f4d17e | |||
9d8f914fe8 | |||
ceea368e88 | |||
b660539c4a | |||
752371d91b |
@ -221,26 +221,10 @@ class GitCommand(object):
|
||||
self.stdin = p.stdin
|
||||
|
||||
def Wait(self):
|
||||
p = self.process
|
||||
|
||||
if p.stdin:
|
||||
p.stdin.close()
|
||||
self.stdin = None
|
||||
|
||||
if p.stdout:
|
||||
self.stdout = p.stdout.read()
|
||||
p.stdout.close()
|
||||
else:
|
||||
p.stdout = None
|
||||
|
||||
if p.stderr:
|
||||
self.stderr = p.stderr.read()
|
||||
p.stderr.close()
|
||||
else:
|
||||
p.stderr = None
|
||||
|
||||
try:
|
||||
rc = p.wait()
|
||||
p = self.process
|
||||
(self.stdout, self.stderr) = p.communicate()
|
||||
rc = p.returncode
|
||||
finally:
|
||||
_remove_ssh_client(p)
|
||||
return rc
|
||||
|
12
git_refs.py
12
git_refs.py
@ -139,13 +139,15 @@ class GitRefs(object):
|
||||
def _ReadLoose1(self, path, name):
|
||||
try:
|
||||
fd = open(path, 'rb')
|
||||
mtime = os.path.getmtime(path)
|
||||
except OSError:
|
||||
return
|
||||
except IOError:
|
||||
except:
|
||||
return
|
||||
|
||||
try:
|
||||
id = fd.readline()
|
||||
try:
|
||||
mtime = os.path.getmtime(path)
|
||||
id = fd.readline()
|
||||
except:
|
||||
return
|
||||
finally:
|
||||
fd.close()
|
||||
|
||||
|
33
main.py
33
main.py
@ -36,6 +36,7 @@ from git_config import init_ssh, close_ssh
|
||||
from command import InteractiveCommand
|
||||
from command import MirrorSafeCommand
|
||||
from command import PagedCommand
|
||||
from subcmds.version import Version
|
||||
from editor import Editor
|
||||
from error import DownloadError
|
||||
from error import ManifestInvalidRevisionError
|
||||
@ -73,6 +74,7 @@ class _Repo(object):
|
||||
all_commands['branch'] = all_commands['branches']
|
||||
|
||||
def _Run(self, argv):
|
||||
result = 0
|
||||
name = None
|
||||
glob = []
|
||||
|
||||
@ -96,7 +98,7 @@ class _Repo(object):
|
||||
name = 'version'
|
||||
else:
|
||||
print >>sys.stderr, 'fatal: invalid usage of --version'
|
||||
sys.exit(1)
|
||||
return 1
|
||||
|
||||
try:
|
||||
cmd = self.commands[name]
|
||||
@ -104,7 +106,7 @@ class _Repo(object):
|
||||
print >>sys.stderr,\
|
||||
"repo: '%s' is not a repo command. See 'repo help'."\
|
||||
% name
|
||||
sys.exit(1)
|
||||
return 1
|
||||
|
||||
cmd.repodir = self.repodir
|
||||
cmd.manifest = XmlManifest(cmd.repodir)
|
||||
@ -114,7 +116,7 @@ class _Repo(object):
|
||||
print >>sys.stderr, \
|
||||
"fatal: '%s' requires a working directory"\
|
||||
% name
|
||||
sys.exit(1)
|
||||
return 1
|
||||
|
||||
copts, cargs = cmd.OptionParser.parse_args(argv)
|
||||
|
||||
@ -132,7 +134,7 @@ class _Repo(object):
|
||||
try:
|
||||
start = time.time()
|
||||
try:
|
||||
cmd.Execute(copts, cargs)
|
||||
result = cmd.Execute(copts, cargs)
|
||||
finally:
|
||||
elapsed = time.time() - start
|
||||
hours, remainder = divmod(elapsed, 3600)
|
||||
@ -146,16 +148,18 @@ class _Repo(object):
|
||||
% (hours, minutes, seconds)
|
||||
except DownloadError, e:
|
||||
print >>sys.stderr, 'error: %s' % str(e)
|
||||
sys.exit(1)
|
||||
return 1
|
||||
except ManifestInvalidRevisionError, e:
|
||||
print >>sys.stderr, 'error: %s' % str(e)
|
||||
sys.exit(1)
|
||||
return 1
|
||||
except NoSuchProjectError, e:
|
||||
if e.name:
|
||||
print >>sys.stderr, 'error: project %s not found' % e.name
|
||||
else:
|
||||
print >>sys.stderr, 'error: no project in current directory'
|
||||
sys.exit(1)
|
||||
return 1
|
||||
|
||||
return result
|
||||
|
||||
def _MyRepoPath():
|
||||
return os.path.dirname(__file__)
|
||||
@ -287,6 +291,8 @@ class _BasicAuthHandler(urllib2.HTTPBasicAuthHandler):
|
||||
reset = getattr(self, 'reset_retry_count', None)
|
||||
if reset is not None:
|
||||
reset()
|
||||
elif getattr(self, 'retried', None):
|
||||
self.retried = 0
|
||||
raise
|
||||
|
||||
def init_http():
|
||||
@ -314,6 +320,8 @@ def init_http():
|
||||
urllib2.install_opener(urllib2.build_opener(*handlers))
|
||||
|
||||
def _Main(argv):
|
||||
result = 0
|
||||
|
||||
opt = optparse.OptionParser(usage="repo wrapperinfo -- ...")
|
||||
opt.add_option("--repo-dir", dest="repodir",
|
||||
help="path to .repo/")
|
||||
@ -327,16 +335,19 @@ def _Main(argv):
|
||||
_CheckWrapperVersion(opt.wrapper_version, opt.wrapper_path)
|
||||
_CheckRepoDir(opt.repodir)
|
||||
|
||||
Version.wrapper_version = opt.wrapper_version
|
||||
Version.wrapper_path = opt.wrapper_path
|
||||
|
||||
repo = _Repo(opt.repodir)
|
||||
try:
|
||||
try:
|
||||
init_ssh()
|
||||
init_http()
|
||||
repo._Run(argv)
|
||||
result = repo._Run(argv) or 0
|
||||
finally:
|
||||
close_ssh()
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
||||
result = 1
|
||||
except RepoChangedException, rce:
|
||||
# If repo changed, re-exec ourselves.
|
||||
#
|
||||
@ -347,7 +358,9 @@ def _Main(argv):
|
||||
except OSError, e:
|
||||
print >>sys.stderr, 'fatal: cannot restart repo after upgrade'
|
||||
print >>sys.stderr, 'fatal: %s' % e
|
||||
sys.exit(128)
|
||||
result = 128
|
||||
|
||||
sys.exit(result)
|
||||
|
||||
if __name__ == '__main__':
|
||||
_Main(sys.argv[1:])
|
||||
|
@ -46,16 +46,20 @@ class _XmlRemote(object):
|
||||
self.fetchUrl = fetch
|
||||
self.manifestUrl = manifestUrl
|
||||
self.reviewUrl = review
|
||||
self.resolvedFetchUrl = self._resolveFetchUrl()
|
||||
|
||||
def ToRemoteSpec(self, projectName):
|
||||
url = self.fetchUrl.rstrip('/') + '/' + projectName + '.git'
|
||||
def _resolveFetchUrl(self):
|
||||
url = self.fetchUrl.rstrip('/')
|
||||
manifestUrl = self.manifestUrl.rstrip('/')
|
||||
# urljoin will get confused if there is no scheme in the base url
|
||||
# ie, if manifestUrl is of the form <hostname:port>
|
||||
if manifestUrl.find(':') != manifestUrl.find('/') - 1:
|
||||
manifestUrl = 'gopher://' + manifestUrl
|
||||
url = urlparse.urljoin(manifestUrl, url)
|
||||
url = re.sub(r'^gopher://', '', url)
|
||||
return re.sub(r'^gopher://', '', url)
|
||||
|
||||
def ToRemoteSpec(self, projectName):
|
||||
url = self.resolvedFetchUrl.rstrip('/') + '/' + projectName
|
||||
return RemoteSpec(self.name, url, self.reviewUrl)
|
||||
|
||||
class XmlManifest(object):
|
||||
@ -368,7 +372,7 @@ class XmlManifest(object):
|
||||
raise ManifestParseError, 'refusing to mirror %s' % m_url
|
||||
|
||||
if self._default and self._default.remote:
|
||||
url = self._default.remote.fetchUrl
|
||||
url = self._default.remote.resolvedFetchUrl
|
||||
if not url.endswith('/'):
|
||||
url += '/'
|
||||
if m_url.startswith(url):
|
||||
|
57
project.py
57
project.py
@ -36,7 +36,7 @@ except ImportError:
|
||||
|
||||
from color import Coloring
|
||||
from git_command import GitCommand
|
||||
from git_config import GitConfig, IsId, GetSchemeFromUrl
|
||||
from git_config import GitConfig, IsId, GetSchemeFromUrl, ID_RE
|
||||
from error import DownloadError
|
||||
from error import GitError, HookError, ImportError, UploadError
|
||||
from error import ManifestInvalidRevisionError
|
||||
@ -900,7 +900,7 @@ class Project(object):
|
||||
|
||||
## Sync ##
|
||||
|
||||
def Sync_NetworkHalf(self, quiet=False, is_new=None):
|
||||
def Sync_NetworkHalf(self, quiet=False, is_new=None, current_branch_only=False):
|
||||
"""Perform only the network IO portion of the sync process.
|
||||
Local working directory/branch state is not affected.
|
||||
"""
|
||||
@ -926,21 +926,10 @@ class Project(object):
|
||||
if alt_dir is None and self._ApplyCloneBundle(initial=is_new, quiet=quiet):
|
||||
is_new = False
|
||||
|
||||
if not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir):
|
||||
if not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir,
|
||||
current_branch_only=current_branch_only):
|
||||
return False
|
||||
|
||||
#Check that the requested ref was found after fetch
|
||||
#
|
||||
try:
|
||||
self.GetRevisionId()
|
||||
except ManifestInvalidRevisionError:
|
||||
# if the ref is a tag. We can try fetching
|
||||
# the tag manually as a last resort
|
||||
#
|
||||
rev = self.revisionExpr
|
||||
if rev.startswith(R_TAGS):
|
||||
self._RemoteFetch(None, rev[len(R_TAGS):], quiet=quiet)
|
||||
|
||||
if self.worktree:
|
||||
self._InitMRef()
|
||||
else:
|
||||
@ -1027,7 +1016,7 @@ class Project(object):
|
||||
|
||||
if not branch.LocalMerge:
|
||||
# The current branch has no tracking configuration.
|
||||
# Jump off it to a deatched HEAD.
|
||||
# Jump off it to a detached HEAD.
|
||||
#
|
||||
syncbuf.info(self,
|
||||
"leaving %s; does not track upstream",
|
||||
@ -1335,10 +1324,30 @@ class Project(object):
|
||||
|
||||
## Direct Git Commands ##
|
||||
|
||||
def _RemoteFetch(self, name=None, tag=None,
|
||||
def _RemoteFetch(self, name=None,
|
||||
current_branch_only=False,
|
||||
initial=False,
|
||||
quiet=False,
|
||||
alt_dir=None):
|
||||
|
||||
is_sha1 = False
|
||||
tag_name = None
|
||||
|
||||
if current_branch_only:
|
||||
if ID_RE.match(self.revisionExpr) is not None:
|
||||
is_sha1 = True
|
||||
elif self.revisionExpr.startswith(R_TAGS):
|
||||
# this is a tag and its sha1 value should never change
|
||||
tag_name = self.revisionExpr[len(R_TAGS):]
|
||||
|
||||
if is_sha1 or tag_name is not None:
|
||||
try:
|
||||
self.GetRevisionId()
|
||||
return True
|
||||
except ManifestInvalidRevisionError:
|
||||
# There is no such persistent revision. We have to fetch it.
|
||||
pass
|
||||
|
||||
if not name:
|
||||
name = self.remote.name
|
||||
|
||||
@ -1401,9 +1410,19 @@ class Project(object):
|
||||
if not self.worktree:
|
||||
cmd.append('--update-head-ok')
|
||||
cmd.append(name)
|
||||
if tag is not None:
|
||||
|
||||
if not current_branch_only or is_sha1:
|
||||
# Fetch whole repo
|
||||
cmd.append('--tags')
|
||||
cmd.append((u'+refs/heads/*:') + remote.ToLocal('refs/heads/*'))
|
||||
elif tag_name is not None:
|
||||
cmd.append('tag')
|
||||
cmd.append(tag)
|
||||
cmd.append(tag_name)
|
||||
else:
|
||||
branch = self.revisionExpr
|
||||
if branch.startswith(R_HEADS):
|
||||
branch = branch[len(R_HEADS):]
|
||||
cmd.append((u'+refs/heads/%s:' % branch) + remote.ToLocal('refs/heads/%s' % branch))
|
||||
|
||||
ok = False
|
||||
for i in range(2):
|
||||
|
5
repo
5
repo
@ -139,6 +139,11 @@ group.add_option('--no-repo-verify',
|
||||
dest='no_repo_verify', action='store_true',
|
||||
help='do not verify repo source code')
|
||||
|
||||
# Other
|
||||
group = init_optparse.add_option_group('Other options')
|
||||
group.add_option('--config-name',
|
||||
dest='config_name', action="store_true", default=False,
|
||||
help='Always prompt for name/e-mail')
|
||||
|
||||
class CloneFailure(Exception):
|
||||
"""Indicate the remote clone of repo itself failed.
|
||||
|
@ -165,6 +165,7 @@ See 'repo help --all' for a complete list of recognized commands.
|
||||
print >>sys.stderr, "repo: '%s' is not a repo command." % name
|
||||
sys.exit(1)
|
||||
|
||||
cmd.manifest = self.manifest
|
||||
self._PrintCommandHelp(cmd)
|
||||
|
||||
else:
|
||||
|
@ -99,6 +99,12 @@ to update the working directory files.
|
||||
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
|
||||
@ -179,6 +185,24 @@ to update the working directory files.
|
||||
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
|
||||
|
||||
@ -189,7 +213,7 @@ to update the working directory files.
|
||||
|
||||
print ''
|
||||
print 'Your identity is: %s <%s>' % (name, email)
|
||||
sys.stdout.write('is this correct [y/n]? ')
|
||||
sys.stdout.write('is this correct [y/N]? ')
|
||||
a = sys.stdin.readline().strip()
|
||||
if a in ('yes', 'y', 't', 'true'):
|
||||
break
|
||||
@ -231,7 +255,7 @@ to update the working directory files.
|
||||
out.printer(fg='black', attr=c)(' %-6s ', c)
|
||||
out.nl()
|
||||
|
||||
sys.stdout.write('Enable color display in this user account (y/n)? ')
|
||||
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')
|
||||
@ -261,7 +285,8 @@ to update the working directory files.
|
||||
self._LinkManifest(opt.manifest_name)
|
||||
|
||||
if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror:
|
||||
self._ConfigureUser()
|
||||
if opt.config_name or self._ShouldConfigureUser():
|
||||
self._ConfigureUser()
|
||||
self._ConfigureColor()
|
||||
|
||||
self._ConfigureDepth(opt)
|
||||
|
@ -131,6 +131,9 @@ later is required to fix a server side protocol bug.
|
||||
p.add_option('-d','--detach',
|
||||
dest='detach_head', action='store_true',
|
||||
help='detach projects back to manifest revision')
|
||||
p.add_option('-c','--current-branch',
|
||||
dest='current_branch_only', action='store_true',
|
||||
help='fetch only current branch from server')
|
||||
p.add_option('-q','--quiet',
|
||||
dest='quiet', action='store_true',
|
||||
help='be more quiet')
|
||||
@ -179,7 +182,8 @@ later is required to fix a server side protocol bug.
|
||||
# - We always make sure we unlock the lock if we locked it.
|
||||
try:
|
||||
try:
|
||||
success = project.Sync_NetworkHalf(quiet=opt.quiet)
|
||||
success = project.Sync_NetworkHalf(quiet=opt.quiet,
|
||||
current_branch_only=opt.current_branch_only)
|
||||
|
||||
# Lock around all the rest of the code, since printing, updating a set
|
||||
# and Progress.update() are not thread safe.
|
||||
@ -212,7 +216,8 @@ later is required to fix a server side protocol bug.
|
||||
if self.jobs == 1:
|
||||
for project in projects:
|
||||
pm.update()
|
||||
if project.Sync_NetworkHalf(quiet=opt.quiet):
|
||||
if project.Sync_NetworkHalf(quiet=opt.quiet,
|
||||
current_branch_only=opt.current_branch_only):
|
||||
fetched.add(project.gitdir)
|
||||
else:
|
||||
print >>sys.stderr, 'error: Cannot fetch %s' % project.name
|
||||
@ -388,7 +393,8 @@ uncommitted changes are present' % project.relpath
|
||||
_PostRepoUpgrade(self.manifest)
|
||||
|
||||
if not opt.local_only:
|
||||
mp.Sync_NetworkHalf(quiet=opt.quiet)
|
||||
mp.Sync_NetworkHalf(quiet=opt.quiet,
|
||||
current_branch_only=opt.current_branch_only)
|
||||
|
||||
if mp.HasChanges:
|
||||
syncbuf = SyncBuffer(mp.config)
|
||||
|
@ -73,7 +73,7 @@ Configuration
|
||||
|
||||
review.URL.autoupload:
|
||||
|
||||
To disable the "Upload ... (y/n)?" prompt, you can set a per-project
|
||||
To disable the "Upload ... (y/N)?" prompt, you can set a per-project
|
||||
or global Git configuration option. If review.URL.autoupload is set
|
||||
to "true" then repo will assume you always answer "y" at the prompt,
|
||||
and will not prompt you further. If it is set to "false" then repo
|
||||
@ -162,7 +162,7 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
||||
date = branch.date
|
||||
list = branch.commits
|
||||
|
||||
print 'Upload project %s/:' % project.relpath
|
||||
print 'Upload project %s/ to remote branch %s:' % (project.relpath, project.revisionExpr)
|
||||
print ' branch %s (%2d commit%s, %s):' % (
|
||||
name,
|
||||
len(list),
|
||||
@ -171,7 +171,7 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
||||
for commit in list:
|
||||
print ' %s' % commit
|
||||
|
||||
sys.stdout.write('to %s (y/n)? ' % remote.review)
|
||||
sys.stdout.write('to %s (y/N)? ' % remote.review)
|
||||
answer = sys.stdin.readline().strip()
|
||||
answer = answer in ('y', 'Y', 'yes', '1', 'true', 't')
|
||||
|
||||
@ -202,11 +202,12 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
||||
|
||||
if b:
|
||||
script.append('#')
|
||||
script.append('# branch %s (%2d commit%s, %s):' % (
|
||||
script.append('# branch %s (%2d commit%s, %s) to remote branch %s:' % (
|
||||
name,
|
||||
len(list),
|
||||
len(list) != 1 and 's' or '',
|
||||
date))
|
||||
date,
|
||||
project.revisionExpr))
|
||||
for commit in list:
|
||||
script.append('# %s' % commit)
|
||||
b[name] = branch
|
||||
@ -215,6 +216,11 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
||||
branches[project.name] = b
|
||||
script.append('')
|
||||
|
||||
script = [ x.encode('utf-8')
|
||||
if issubclass(type(x), unicode)
|
||||
else x
|
||||
for x in script ]
|
||||
|
||||
script = Editor.EditString("\n".join(script)).split("\n")
|
||||
|
||||
project_re = re.compile(r'^#?\s*project\s*([^\s]+)/:$')
|
||||
@ -294,7 +300,7 @@ Gerrit Code Review: http://code.google.com/p/gerrit/
|
||||
|
||||
# if they want to auto upload, let's not ask because it could be automated
|
||||
if answer is None:
|
||||
sys.stdout.write('Uncommitted changes in ' + branch.project.name + ' (did you forget to amend?). Continue uploading? (y/n) ')
|
||||
sys.stdout.write('Uncommitted changes in ' + branch.project.name + ' (did you forget to amend?). Continue uploading? (y/N) ')
|
||||
a = sys.stdin.readline().strip().lower()
|
||||
if a not in ('y', 'yes', 't', 'true', 'on'):
|
||||
print >>sys.stderr, "skipping upload"
|
||||
|
@ -19,6 +19,9 @@ from git_command import git
|
||||
from project import HEAD
|
||||
|
||||
class Version(Command, MirrorSafeCommand):
|
||||
wrapper_version = None
|
||||
wrapper_path = None
|
||||
|
||||
common = False
|
||||
helpSummary = "Display the version of repo"
|
||||
helpUsage = """
|
||||
@ -31,5 +34,10 @@ class Version(Command, MirrorSafeCommand):
|
||||
|
||||
print 'repo version %s' % rp.work_git.describe(HEAD)
|
||||
print ' (from %s)' % rem.url
|
||||
|
||||
if Version.wrapper_path is not None:
|
||||
print 'repo launcher version %s' % Version.wrapper_version
|
||||
print ' (from %s)' % Version.wrapper_path
|
||||
|
||||
print git.version().strip()
|
||||
print 'Python %s' % sys.version
|
||||
|
Reference in New Issue
Block a user