Merge "Fix checkout error when depth passed to repo init and revision is a sha1"
diff --git a/manifest_xml.py b/manifest_xml.py
index 9c882af..0859e1f 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -40,8 +40,18 @@
LOCAL_MANIFESTS_DIR_NAME = 'local_manifests'
# urljoin gets confused if the scheme is not known.
-urllib.parse.uses_relative.extend(['ssh', 'git', 'persistent-https', 'rpc'])
-urllib.parse.uses_netloc.extend(['ssh', 'git', 'persistent-https', 'rpc'])
+urllib.parse.uses_relative.extend([
+ 'ssh',
+ 'git',
+ 'persistent-https',
+ 'sso',
+ 'rpc'])
+urllib.parse.uses_netloc.extend([
+ 'ssh',
+ 'git',
+ 'persistent-https',
+ 'sso',
+ 'rpc'])
class _Default(object):
"""Project defaults within the manifest."""
diff --git a/project.py b/project.py
index cdb61c2..633ae07 100644
--- a/project.py
+++ b/project.py
@@ -911,11 +911,13 @@
else:
return False
- def PrintWorkTreeStatus(self, output_redir=None):
+ def PrintWorkTreeStatus(self, output_redir=None, quiet=False):
"""Prints the status of the repository to stdout.
Args:
output: If specified, redirect the output to this object.
+ quiet: If True then only print the project name. Do not print
+ the modified files, branch name, etc.
"""
if not os.path.isdir(self.worktree):
if output_redir is None:
@@ -941,6 +943,10 @@
out.redirect(output_redir)
out.project('project %-40s', self.relpath + '/ ')
+ if quiet:
+ out.nl()
+ return 'DIRTY'
+
branch = self.CurrentBranch
if branch is None:
out.nobranch('(*** NO BRANCH ***)')
@@ -2394,6 +2400,7 @@
src = os.path.realpath(os.path.join(srcdir, name))
# Fail if the links are pointing to the wrong place
if src != dst:
+ _error('%s is different in %s vs %s', name, destdir, srcdir)
raise GitError('--force-sync not enabled; cannot overwrite a local '
'work tree. If you\'re comfortable with the '
'possibility of losing the work tree\'s git metadata,'
diff --git a/subcmds/abandon.py b/subcmds/abandon.py
index b94ccdd..6f78da7 100644
--- a/subcmds/abandon.py
+++ b/subcmds/abandon.py
@@ -16,6 +16,7 @@
from __future__ import print_function
import sys
from command import Command
+from collections import defaultdict
from git_command import git
from progress import Progress
@@ -23,49 +24,75 @@
common = True
helpSummary = "Permanently abandon a development branch"
helpUsage = """
-%prog <branchname> [<project>...]
+%prog [--all | <branchname>] [<project>...]
This subcommand permanently abandons a development branch by
deleting it (and all its history) from your local repository.
It is equivalent to "git branch -D <branchname>".
"""
+ def _Options(self, p):
+ p.add_option('--all',
+ dest='all', action='store_true',
+ help='delete all branches in all projects')
def Execute(self, opt, args):
- if not args:
+ if not opt.all and not args:
self.Usage()
- nb = args[0]
- if not git.check_ref_format('heads/%s' % nb):
- print("error: '%s' is not a valid name" % nb, file=sys.stderr)
- sys.exit(1)
+ if not opt.all:
+ nb = args[0]
+ if not git.check_ref_format('heads/%s' % nb):
+ print("error: '%s' is not a valid name" % nb, file=sys.stderr)
+ sys.exit(1)
+ else:
+ args.insert(0,None)
+ nb = "'All local branches'"
- nb = args[0]
- err = []
- success = []
+ err = defaultdict(list)
+ success = defaultdict(list)
all_projects = self.GetProjects(args[1:])
pm = Progress('Abandon %s' % nb, len(all_projects))
for project in all_projects:
pm.update()
- status = project.AbandonBranch(nb)
- if status is not None:
- if status:
- success.append(project)
- else:
- err.append(project)
+ if opt.all:
+ branches = project.GetBranches().keys()
+ else:
+ branches = [nb]
+
+ for name in branches:
+ status = project.AbandonBranch(name)
+ if status is not None:
+ if status:
+ success[name].append(project)
+ else:
+ err[name].append(project)
pm.end()
+ width = 25
+ for name in branches:
+ if width < len(name):
+ width = len(name)
+
if err:
- for p in err:
- print("error: %s/: cannot abandon %s" % (p.relpath, nb),
- file=sys.stderr)
+ for br in err.keys():
+ err_msg = "error: cannot abandon %s" %br
+ print(err_msg, file=sys.stderr)
+ for proj in err[br]:
+ print(' '*len(err_msg) + " | %s" % p.relpath, file=sys.stderr)
sys.exit(1)
elif not success:
- print('error: no project has branch %s' % nb, file=sys.stderr)
+ print('error: no project has local branch(es) : %s' % nb,
+ file=sys.stderr)
sys.exit(1)
else:
- print('Abandoned in %d project(s):\n %s'
- % (len(success), '\n '.join(p.relpath for p in success)),
- file=sys.stderr)
+ print('Abandoned branches:', file=sys.stderr)
+ for br in success.keys():
+ if len(all_projects) > 1 and len(all_projects) == len(success[br]):
+ result = "all project"
+ else:
+ result = "%s" % (
+ ('\n'+' '*width + '| ').join(p.relpath for p in success[br]))
+ print("%s%s| %s\n" % (br,' '*(width-len(br)), result),file=sys.stderr)
diff --git a/subcmds/status.py b/subcmds/status.py
index 38c229b..60e26ff 100644
--- a/subcmds/status.py
+++ b/subcmds/status.py
@@ -89,8 +89,10 @@
p.add_option('-o', '--orphans',
dest='orphans', action='store_true',
help="include objects in working directory outside of repo projects")
+ p.add_option('-q', '--quiet', action='store_true',
+ help="only print the name of modified projects")
- def _StatusHelper(self, project, clean_counter, sem):
+ def _StatusHelper(self, project, clean_counter, sem, quiet):
"""Obtains the status for a specific project.
Obtains the status for a project, redirecting the output to
@@ -104,7 +106,7 @@
output: Where to output the status.
"""
try:
- state = project.PrintWorkTreeStatus()
+ state = project.PrintWorkTreeStatus(quiet=quiet)
if state == 'CLEAN':
next(clean_counter)
finally:
@@ -132,7 +134,7 @@
if opt.jobs == 1:
for project in all_projects:
- state = project.PrintWorkTreeStatus()
+ state = project.PrintWorkTreeStatus(quiet=opt.quiet)
if state == 'CLEAN':
next(counter)
else:
@@ -142,13 +144,13 @@
sem.acquire()
t = _threading.Thread(target=self._StatusHelper,
- args=(project, counter, sem))
+ args=(project, counter, sem, opt.quiet))
threads.append(t)
t.daemon = True
t.start()
for t in threads:
t.join()
- if len(all_projects) == next(counter):
+ if not opt.quiet and len(all_projects) == next(counter):
print('nothing to commit (working directory clean)')
if opt.orphans:
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 7ba9ebf..bbb166c 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -255,7 +255,7 @@
dest='repo_upgraded', action='store_true',
help=SUPPRESS_HELP)
- def _FetchProjectList(self, opt, projects, *args, **kwargs):
+ def _FetchProjectList(self, opt, projects, sem, *args, **kwargs):
"""Main function of the fetch threads when jobs are > 1.
Delegates most of the work to _FetchHelper.
@@ -263,15 +263,20 @@
Args:
opt: Program options returned from optparse. See _Options().
projects: Projects to fetch.
+ sem: We'll release() this semaphore when we exit so that another thread
+ can be started up.
*args, **kwargs: Remaining arguments to pass to _FetchHelper. See the
_FetchHelper docstring for details.
"""
- for project in projects:
- success = self._FetchHelper(opt, project, *args, **kwargs)
- if not success and not opt.force_broken:
- break
+ try:
+ for project in projects:
+ success = self._FetchHelper(opt, project, *args, **kwargs)
+ if not success and not opt.force_broken:
+ break
+ finally:
+ sem.release()
- def _FetchHelper(self, opt, project, lock, fetched, pm, sem, err_event):
+ def _FetchHelper(self, opt, project, lock, fetched, pm, err_event):
"""Fetch git objects for a single project.
Args:
@@ -283,8 +288,6 @@
(with our lock held).
pm: Instance of a Project object. We will call pm.update() (with our
lock held).
- sem: We'll release() this semaphore when we exit so that another thread
- can be started up.
err_event: We'll set this event in the case of an error (after printing
out info about the error).
@@ -340,7 +343,6 @@
finally:
if did_lock:
lock.release()
- sem.release()
return success
@@ -365,10 +367,10 @@
sem.acquire()
kwargs = dict(opt=opt,
projects=project_list,
+ sem=sem,
lock=lock,
fetched=fetched,
pm=pm,
- sem=sem,
err_event=err_event)
if self.jobs > 1:
t = _threading.Thread(target = self._FetchProjectList,