Merge "Fix variable assignment"
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..f070b49
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,8 @@
+Anthony Newnam <anthony.newnam@garmin.com> Anthony <anthony@bnovc.com>
+Shawn Pearce <sop@google.com> Shawn O. Pearce <sop@google.com>
+Jia Bi <bijia@xiaomi.com> bijia <bijia@xiaomi.com>
+JoonCheol Park <jooncheol@gmail.com> Jooncheol Park <jooncheol@gmail.com>
+Sergii Pylypenko <x.pelya.x@gmail.com> pelya <x.pelya.x@gmail.com>
+Ulrik Sjölin <ulrik.sjolin@sonyericsson.com> Ulrik Sjolin <ulrik.sjolin@gmail.com>
+Ulrik Sjölin <ulrik.sjolin@sonyericsson.com> Ulrik Sjolin <ulrik.sjolin@sonyericsson.com>
+Ulrik Sjölin <ulrik.sjolin@sonyericsson.com> Ulrik Sjölin <ulrik.sjolin@sonyericsson.com>
diff --git a/.pylintrc b/.pylintrc
index c6be743..413d66a 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -53,7 +53,7 @@
enable=RP0004
# Disable the message(s) with the given id(s).
-disable=R0903,R0912,R0913,R0914,R0915,W0141,C0111,C0103,W0603,W0703,R0911,C0301,C0302,R0902,R0904,W0142,W0212,E1101,E1103,R0201,W0201,W0122,W0232,RP0001,RP0003,RP0101,RP0002,RP0401,RP0701,RP0801,F0401,E0611,R0801,I0011
+disable=C0326,R0903,R0912,R0913,R0914,R0915,W0141,C0111,C0103,W0603,W0703,R0911,C0301,C0302,R0902,R0904,W0142,W0212,E1101,E1103,R0201,W0201,W0122,W0232,RP0001,RP0003,RP0101,RP0002,RP0401,RP0701,RP0801,F0401,E0611,R0801,I0011
[REPORTS]
diff --git a/command.py b/command.py
index cd5e3c3..bc2f950 100644
--- a/command.py
+++ b/command.py
@@ -31,7 +31,7 @@
manifest = None
_optparse = None
- def WantPager(self, opt):
+ def WantPager(self, _opt):
return False
def ReadEnvironmentOptions(self, opts):
@@ -63,7 +63,7 @@
usage = self.helpUsage.strip().replace('%prog', me)
except AttributeError:
usage = 'repo %s' % self.NAME
- self._optparse = optparse.OptionParser(usage = usage)
+ self._optparse = optparse.OptionParser(usage=usage)
self._Options(self._optparse)
return self._optparse
@@ -110,9 +110,9 @@
project = None
if os.path.exists(path):
oldpath = None
- while path \
- and path != oldpath \
- and path != manifest.topdir:
+ while path and \
+ path != oldpath and \
+ path != manifest.topdir:
try:
project = self._by_path[path]
break
@@ -138,7 +138,7 @@
mp = manifest.manifestProject
if not groups:
- groups = mp.config.GetString('manifest.groups')
+ groups = mp.config.GetString('manifest.groups')
if not groups:
groups = 'default,platform-' + platform.system().lower()
groups = [x for x in re.split(r'[,\s]+', groups) if x]
@@ -151,8 +151,7 @@
for p in project.GetDerivedSubprojects())
all_projects_list.extend(derived_projects.values())
for project in all_projects_list:
- if ((missing_ok or project.Exists) and
- project.MatchesGroups(groups)):
+ if (missing_ok or project.Exists) and project.MatchesGroups(groups):
result.append(project)
else:
self._ResetPathToProjectMap(all_projects_list)
@@ -166,8 +165,8 @@
# If it's not a derived project, update path->project mapping and
# search again, as arg might actually point to a derived subproject.
- if (project and not project.Derived and
- (submodules_ok or project.sync_s)):
+ if (project and not project.Derived and (submodules_ok or
+ project.sync_s)):
search_again = False
for subproject in project.GetDerivedSubprojects():
self._UpdatePathToProjectMap(subproject)
@@ -194,17 +193,24 @@
result.sort(key=_getpath)
return result
- def FindProjects(self, args):
+ def FindProjects(self, args, inverse=False):
result = []
patterns = [re.compile(r'%s' % a, re.IGNORECASE) for a in args]
for project in self.GetProjects(''):
for pattern in patterns:
- if pattern.search(project.name) or pattern.search(project.relpath):
+ match = pattern.search(project.name) or pattern.search(project.relpath)
+ if not inverse and match:
result.append(project)
break
+ if inverse and match:
+ break
+ else:
+ if inverse:
+ result.append(project)
result.sort(key=lambda project: project.relpath)
return result
+
# pylint: disable=W0223
# Pylint warns that the `InteractiveCommand` and `PagedCommand` classes do not
# override method `Execute` which is abstract in `Command`. Since that method
@@ -214,28 +220,32 @@
"""Command which requires user interaction on the tty and
must not run within a pager, even if the user asks to.
"""
- def WantPager(self, opt):
+ def WantPager(self, _opt):
return False
+
class PagedCommand(Command):
"""Command which defaults to output in a pager, as its
display tends to be larger than one screen full.
"""
- def WantPager(self, opt):
+ def WantPager(self, _opt):
return True
# pylint: enable=W0223
+
class MirrorSafeCommand(object):
"""Command permits itself to run within a mirror,
and does not require a working directory.
"""
+
class GitcAvailableCommand(object):
"""Command that requires GITC to be available, but does
not require the local client to be a GITC client.
"""
+
class GitcClientCommand(object):
"""Command that requires the local client to be a GITC
client.
diff --git a/docs/manifest-format.txt b/docs/manifest-format.txt
index 140a782..8fd9137 100644
--- a/docs/manifest-format.txt
+++ b/docs/manifest-format.txt
@@ -175,7 +175,8 @@
GetApprovedManifest(branch, target)
Return a manifest in which each project is pegged to a known good revision
-for the current branch and target.
+for the current branch and target. This is used by repo sync when the
+--smart-sync option is given.
The target to use is defined by environment variables TARGET_PRODUCT
and TARGET_BUILD_VARIANT. These variables are used to create a string
@@ -187,7 +188,8 @@
GetManifest(tag)
Return a manifest in which each project is pegged to the revision at
-the specified tag.
+the specified tag. This is used by repo sync when the --smart-tag option
+is given.
Element project
diff --git a/gitc_utils.py b/gitc_utils.py
index 0f3e181..a388dc2 100644
--- a/gitc_utils.py
+++ b/gitc_utils.py
@@ -127,7 +127,7 @@
repo_proj.revisionExpr = None
# Convert URLs from relative to absolute.
- for name, remote in manifest.remotes.iteritems():
+ for _name, remote in manifest.remotes.iteritems():
remote.fetchUrl = remote.resolvedFetchUrl
# Save the manifest.
diff --git a/hooks/commit-msg b/hooks/commit-msg
index d8f009b..40ac237 100755
--- a/hooks/commit-msg
+++ b/hooks/commit-msg
@@ -1,6 +1,7 @@
#!/bin/sh
+# From Gerrit Code Review 2.12.1
#
-# Part of Gerrit Code Review (http://code.google.com/p/gerrit/)
+# Part of Gerrit Code Review (https://www.gerritcodereview.com/)
#
# Copyright (C) 2009 The Android Open Source Project
#
@@ -19,7 +20,7 @@
unset GREP_OPTIONS
-CHANGE_ID_AFTER="Bug|Issue"
+CHANGE_ID_AFTER="Bug|Issue|Test"
MSG="$1"
# Check for, and add if missing, a unique Change-Id
@@ -38,6 +39,12 @@
return
fi
+ # Do not add Change-Id to temp commits
+ if echo "$clean_message" | head -1 | grep -q '^\(fixup\|squash\)!'
+ then
+ return
+ fi
+
if test "false" = "`git config --bool --get gerrit.createChangeId`"
then
return
@@ -57,6 +64,10 @@
AWK=/usr/xpg4/bin/awk
fi
+ # Get core.commentChar from git config or use default symbol
+ commentChar=`git config --get core.commentChar`
+ commentChar=${commentChar:-#}
+
# How this works:
# - parse the commit message as (textLine+ blankLine*)*
# - assume textLine+ to be a footer until proven otherwise
@@ -75,8 +86,8 @@
blankLines = 0
}
- # Skip lines starting with "#" without any spaces before it.
- /^#/ { next }
+ # Skip lines starting with commentChar without any spaces before it.
+ /^'"$commentChar"'/ { next }
# Skip the line starting with the diff command and everything after it,
# up to the end of the file, assuming it is only patch data.
diff --git a/main.py b/main.py
index 4f4eb9f..c5f1e9c 100755
--- a/main.py
+++ b/main.py
@@ -379,7 +379,7 @@
self.context = None
self.handler_order = urllib.request.BaseHandler.handler_order - 50
- def http_error_401(self, req, fp, code, msg, headers):
+ def http_error_401(self, req, fp, code, msg, headers): # pylint:disable=unused-argument
host = req.get_host()
retry = self.http_error_auth_reqed('www-authenticate', host, req, headers)
return retry
diff --git a/manifest_xml.py b/manifest_xml.py
index 3ac607e..295493d 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -102,7 +102,10 @@
remoteName = self.name
if self.remoteAlias:
remoteName = self.remoteAlias
- return RemoteSpec(remoteName, url, self.reviewUrl)
+ return RemoteSpec(remoteName,
+ url=url,
+ review=self.reviewUrl,
+ orig_name=self.name)
class XmlManifest(object):
"""manages the repo configuration file"""
@@ -249,9 +252,9 @@
e.setAttribute('path', relpath)
remoteName = None
if d.remote:
- remoteName = d.remote.remoteAlias or d.remote.name
- if not d.remote or p.remote.name != remoteName:
- remoteName = p.remote.name
+ remoteName = d.remote.name
+ if not d.remote or p.remote.orig_name != remoteName:
+ remoteName = p.remote.orig_name
e.setAttribute('remote', remoteName)
if peg_rev:
if self.IsMirror:
@@ -267,7 +270,7 @@
# isn't our value
e.setAttribute('upstream', p.revisionExpr)
else:
- revision = self.remotes[remoteName].revision or d.revisionExpr
+ revision = self.remotes[p.remote.orig_name].revision or d.revisionExpr
if not revision or revision != p.revisionExpr:
e.setAttribute('revision', p.revisionExpr)
if p.upstream and p.upstream != p.revisionExpr:
@@ -969,5 +972,5 @@
def _output_manifest_project_extras(self, p, e):
"""Output GITC Specific Project attributes"""
if p.old_revision:
- e.setAttribute('old-revision', str(p.old_revision))
+ e.setAttribute('old-revision', str(p.old_revision))
diff --git a/project.py b/project.py
index 6dfb31c..c91085c 100644
--- a/project.py
+++ b/project.py
@@ -30,7 +30,8 @@
from color import Coloring
from git_command import GitCommand, git_require
-from git_config import GitConfig, IsId, GetSchemeFromUrl, GetUrlCookieFile, ID_RE
+from git_config import GitConfig, IsId, GetSchemeFromUrl, GetUrlCookieFile, \
+ ID_RE
from error import GitError, HookError, UploadError, DownloadError
from error import ManifestInvalidRevisionError
from error import NoManifestException
@@ -44,6 +45,7 @@
input = raw_input
# pylint:enable=W0622
+
def _lwrite(path, content):
lock = '%s.lock' % path
@@ -59,21 +61,27 @@
os.remove(lock)
raise
+
def _error(fmt, *args):
msg = fmt % args
print('error: %s' % msg, file=sys.stderr)
+
def _warn(fmt, *args):
msg = fmt % args
print('warn: %s' % msg, file=sys.stderr)
+
def not_rev(r):
return '^' + r
+
def sq(r):
return "'" + r.replace("'", "'\''") + "'"
_project_hook_list = None
+
+
def _ProjectHooks():
"""List the hooks present in the 'hooks' directory.
@@ -107,15 +115,14 @@
@property
def commits(self):
if self._commit_cache is None:
- self._commit_cache = self.project.bare_git.rev_list(
- '--abbrev=8',
- '--abbrev-commit',
- '--pretty=oneline',
- '--reverse',
- '--date-order',
- not_rev(self.base),
- self.commit,
- '--')
+ self._commit_cache = self.project.bare_git.rev_list('--abbrev=8',
+ '--abbrev-commit',
+ '--pretty=oneline',
+ '--reverse',
+ '--date-order',
+ not_rev(self.base),
+ self.commit,
+ '--')
return self._commit_cache
@@ -134,36 +141,36 @@
@property
def commits(self):
if self._commit_cache is None:
- self._commit_cache = self.project.bare_git.rev_list(
- '--abbrev=8',
- '--abbrev-commit',
- '--pretty=oneline',
- '--reverse',
- '--date-order',
- not_rev(self.base),
- R_HEADS + self.name,
- '--')
+ self._commit_cache = self.project.bare_git.rev_list('--abbrev=8',
+ '--abbrev-commit',
+ '--pretty=oneline',
+ '--reverse',
+ '--date-order',
+ not_rev(self.base),
+ R_HEADS + self.name,
+ '--')
return self._commit_cache
@property
def unabbrev_commits(self):
r = dict()
- for commit in self.project.bare_git.rev_list(
- not_rev(self.base),
- R_HEADS + self.name,
- '--'):
+ for commit in self.project.bare_git.rev_list(not_rev(self.base),
+ R_HEADS + self.name,
+ '--'):
r[commit[0:8]] = commit
return r
@property
def date(self):
- return self.project.bare_git.log(
- '--pretty=format:%cd',
- '-n', '1',
- R_HEADS + self.name,
- '--')
+ return self.project.bare_git.log('--pretty=format:%cd',
+ '-n', '1',
+ R_HEADS + self.name,
+ '--')
- def UploadForReview(self, people, auto_topic=False, draft=False, dest_branch=None):
+ def UploadForReview(self, people,
+ auto_topic=False,
+ draft=False,
+ dest_branch=None):
self.project.UploadForReview(self.name,
people,
auto_topic=auto_topic,
@@ -173,8 +180,8 @@
def GetPublishedRefs(self):
refs = {}
output = self.project.bare_git.ls_remote(
- self.branch.remote.SshReviewUrl(self.project.UserEmail),
- 'refs/changes/*')
+ self.branch.remote.SshReviewUrl(self.project.UserEmail),
+ 'refs/changes/*')
for line in output.split('\n'):
try:
(sha, ref) = line.split()
@@ -184,7 +191,9 @@
return refs
+
class StatusColoring(Coloring):
+
def __init__(self, config):
Coloring.__init__(self, config, 'status')
self.project = self.printer('header', attr='bold')
@@ -198,17 +207,22 @@
class DiffColoring(Coloring):
+
def __init__(self, config):
Coloring.__init__(self, config, 'diff')
self.project = self.printer('header', attr='bold')
+
class _Annotation(object):
+
def __init__(self, name, value, keep):
self.name = name
self.value = value
self.keep = keep
+
class _CopyFile(object):
+
def __init__(self, src, dest, abssrc, absdest):
self.src = src
self.dest = dest
@@ -236,7 +250,9 @@
except IOError:
_error('Cannot copy file %s to %s', src, dest)
+
class _LinkFile(object):
+
def __init__(self, git_worktree, src, dest, relsrc, absdest):
self.git_worktree = git_worktree
self.src = src
@@ -275,7 +291,7 @@
absDestDir = self.abs_dest
if os.path.exists(absDestDir) and not os.path.isdir(absDestDir):
_error('Link error: src with wildcard, %s must be a directory',
- absDestDir)
+ absDestDir)
else:
absSrcFiles = glob.glob(absSrc)
for absSrcFile in absSrcFiles:
@@ -292,18 +308,24 @@
relSrc = os.path.join(relSrcDir, srcFile)
self.__linkIt(relSrc, absDest)
+
class RemoteSpec(object):
+
def __init__(self,
name,
url=None,
review=None,
- revision=None):
+ revision=None,
+ orig_name=None):
self.name = name
self.url = url
self.review = review
self.revision = revision
+ self.orig_name = orig_name
+
class RepoHook(object):
+
"""A RepoHook contains information about a script to run as a hook.
Hooks are used to run a python script before running an upload (for instance,
@@ -316,6 +338,7 @@
Hooks are always python. When a hook is run, we will load the hook into the
interpreter and execute its main() function.
"""
+
def __init__(self,
hook_type,
hooks_project,
@@ -430,8 +453,8 @@
' %s\n'
'\n'
'Do you want to allow this script to run '
- '(yes/yes-never-ask-again/NO)? ') % (
- self._GetMustVerb(), self._script_fullpath)
+ '(yes/yes-never-ask-again/NO)? ') % (self._GetMustVerb(),
+ self._script_fullpath)
response = input(prompt).lower()
print()
@@ -475,19 +498,18 @@
# Exec, storing global context in the context dict. We catch exceptions
# and convert to a HookError w/ just the failing traceback.
- context = {}
+ context = {'__file__': self._script_fullpath}
try:
exec(compile(open(self._script_fullpath).read(),
self._script_fullpath, 'exec'), context)
except Exception:
- raise HookError('%s\nFailed to import %s hook; see traceback above.' % (
- traceback.format_exc(), self._hook_type))
+ raise HookError('%s\nFailed to import %s hook; see traceback above.' %
+ (traceback.format_exc(), self._hook_type))
# Running the script should have defined a main() function.
if 'main' not in context:
raise HookError('Missing main() in: "%s"' % self._script_fullpath)
-
# Add 'hook_should_take_kwargs' to the arguments to be passed to main.
# We don't actually want hooks to define their main with this argument--
# it's there to remind them that their hook should always take **kwargs.
@@ -505,8 +527,8 @@
context['main'](**kwargs)
except Exception:
raise HookError('%s\nFailed to run main() for %s hook; see traceback '
- 'above.' % (
- traceback.format_exc(), self._hook_type))
+ 'above.' % (traceback.format_exc(),
+ self._hook_type))
finally:
# Restore sys.path and CWD.
sys.path = orig_syspath
@@ -530,8 +552,8 @@
to run a required hook (from _CheckForHookApproval).
"""
# No-op if there is no hooks project or if hook is disabled.
- if ((not self._hooks_project) or
- (self._hook_type not in self._hooks_project.enabled_repo_hooks)):
+ if ((not self._hooks_project) or (self._hook_type not in
+ self._hooks_project.enabled_repo_hooks)):
return
# Bail with a nice error if we can't find the hook.
@@ -553,6 +575,7 @@
# These objects can only be used by a single working tree.
working_tree_files = ['config', 'packed-refs', 'shallow']
working_tree_dirs = ['logs', 'refs']
+
def __init__(self,
manifest,
name,
@@ -611,9 +634,9 @@
self.relpath = relpath
self.revisionExpr = revisionExpr
- if revisionId is None \
- and revisionExpr \
- and IsId(revisionExpr):
+ if revisionId is None \
+ and revisionExpr \
+ and IsId(revisionExpr):
self.revisionId = revisionExpr
else:
self.revisionId = revisionId
@@ -633,9 +656,8 @@
self.copyfiles = []
self.linkfiles = []
self.annotations = []
- self.config = GitConfig.ForRepository(
- gitdir=self.gitdir,
- defaults=self.manifest.globalConfig)
+ self.config = GitConfig.ForRepository(gitdir=self.gitdir,
+ defaults=self.manifest.globalConfig)
if self.worktree:
self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir)
@@ -773,7 +795,7 @@
"""
expanded_manifest_groups = manifest_groups or ['default']
expanded_project_groups = ['all'] + (self.groups or [])
- if not 'notdefault' in expanded_project_groups:
+ if 'notdefault' not in expanded_project_groups:
expanded_project_groups += ['default']
matched = False
@@ -785,7 +807,7 @@
return matched
-## Status Display ##
+# Status Display ##
def UncommitedFiles(self, get_all=True):
"""Returns a list of strings, uncommitted files in the git tree.
@@ -837,7 +859,7 @@
output: If specified, redirect the output to this object.
"""
if not os.path.isdir(self.worktree):
- if output_redir == None:
+ if output_redir is None:
output_redir = sys.stdout
print(file=output_redir)
print('project %s/' % self.relpath, file=output_redir)
@@ -856,7 +878,7 @@
return 'CLEAN'
out = StatusColoring(self.config)
- if not output_redir == None:
+ if output_redir is not None:
out.redirect(output_redir)
out.project('project %-40s', self.relpath + '/ ')
@@ -899,7 +921,7 @@
if i and i.src_path:
line = ' %s%s\t%s => %s (%s%%)' % (i_status, f_status,
- i.src_path, p, i.level)
+ i.src_path, p, i.level)
else:
line = ' %s%s\t%s' % (i_status, f_status, p)
@@ -942,7 +964,7 @@
p.Wait()
-## Publish / Upload ##
+# Publish / Upload ##
def WasPublished(self, branch, all_refs=None):
"""Was the branch published (uploaded) for code review?
@@ -1085,7 +1107,7 @@
message=msg)
-## Sync ##
+# Sync ##
def _ExtractArchive(self, tarpath, path=None):
"""Extract the given tar on its current location
@@ -1103,15 +1125,15 @@
return False
def Sync_NetworkHalf(self,
- quiet=False,
- is_new=None,
- current_branch_only=False,
- force_sync=False,
- clone_bundle=True,
- no_tags=False,
- archive=False,
- optimized_fetch=False,
- prune=False):
+ quiet=False,
+ is_new=None,
+ current_branch_only=False,
+ force_sync=False,
+ clone_bundle=True,
+ no_tags=False,
+ archive=False,
+ optimized_fetch=False,
+ prune=False):
"""Perform only the network IO portion of the sync process.
Local working directory/branch state is not affected.
"""
@@ -1164,8 +1186,8 @@
alt_dir = None
if clone_bundle \
- and alt_dir is None \
- and self._ApplyCloneBundle(initial=is_new, quiet=quiet):
+ and alt_dir is None \
+ and self._ApplyCloneBundle(initial=is_new, quiet=quiet):
is_new = False
if not current_branch_only:
@@ -1177,12 +1199,13 @@
elif self.manifest.default.sync_c:
current_branch_only = True
- need_to_fetch = not (optimized_fetch and \
- (ID_RE.match(self.revisionExpr) and self._CheckForSha1()))
- if (need_to_fetch
- and not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir,
- current_branch_only=current_branch_only,
- no_tags=no_tags, prune=prune)):
+ need_to_fetch = not (optimized_fetch and
+ (ID_RE.match(self.revisionExpr) and
+ self._CheckForSha1()))
+ if (need_to_fetch and
+ not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir,
+ current_branch_only=current_branch_only,
+ no_tags=no_tags, prune=prune)):
return False
if self.worktree:
@@ -1219,9 +1242,8 @@
try:
return self.bare_git.rev_list(self.revisionExpr, '-1')[0]
except GitError:
- raise ManifestInvalidRevisionError(
- 'revision %s in %s not found' % (self.revisionExpr,
- self.name))
+ raise ManifestInvalidRevisionError('revision %s in %s not found' %
+ (self.revisionExpr, self.name))
def GetRevisionId(self, all_refs=None):
if self.revisionId:
@@ -1236,9 +1258,8 @@
try:
return self.bare_git.rev_parse('--verify', '%s^0' % rev)
except GitError:
- raise ManifestInvalidRevisionError(
- 'revision %s in %s not found' % (self.revisionExpr,
- self.name))
+ raise ManifestInvalidRevisionError('revision %s in %s not found' %
+ (self.revisionExpr, self.name))
def Sync_LocalHalf(self, syncbuf, force_sync=False):
"""Perform only the local IO portion of the sync process.
@@ -1327,8 +1348,8 @@
# to rewrite the published commits so we punt.
#
syncbuf.fail(self,
- "branch %s is published (but not merged) and is now %d commits behind"
- % (branch.name, len(upstream_gain)))
+ "branch %s is published (but not merged) and is now "
+ "%d commits behind" % (branch.name, len(upstream_gain)))
return
elif pub == head:
# All published commits are merged, and thus we are a
@@ -1422,7 +1443,7 @@
remote = self.GetRemote(self.remote.name)
cmd = ['fetch', remote.name]
- cmd.append('refs/changes/%2.2d/%d/%d' \
+ cmd.append('refs/changes/%2.2d/%d/%d'
% (change_id % 100, change_id, patch_id))
if GitCommand(self, cmd, bare=True).Wait() != 0:
return None
@@ -1433,7 +1454,7 @@
self.bare_git.rev_parse('FETCH_HEAD'))
-## Branch Management ##
+# Branch Management ##
def StartBranch(self, name, branch_merge=''):
"""Create a new branch off the manifest's revision.
@@ -1620,10 +1641,11 @@
return kept
-## Submodule Management ##
+# Submodule Management ##
def GetRegisteredSubprojects(self):
result = []
+
def rec(subprojects):
if not subprojects:
return
@@ -1658,6 +1680,7 @@
re_path = re.compile(r'^submodule\.([^.]+)\.path=(.*)$')
re_url = re.compile(r'^submodule\.([^.]+)\.url=(.*)$')
+
def parse_gitmodules(gitdir, rev):
cmd = ['cat-file', 'blob', '%s:.gitmodules' % rev]
try:
@@ -1767,7 +1790,7 @@
return result
-## Direct Git Commands ##
+# Direct Git Commands ##
def _CheckForSha1(self):
try:
# if revision (sha or tag) is not present then following function
@@ -1791,7 +1814,6 @@
if command.Wait() != 0:
raise GitError('git archive %s: %s' % (self.name, command.stderr))
-
def _RemoteFetch(self, name=None,
current_branch_only=False,
initial=False,
@@ -1958,9 +1980,9 @@
break
continue
elif current_branch_only and is_sha1 and ret == 128:
- # Exit code 128 means "couldn't find the ref you asked for"; if we're in sha1
- # mode, we just tried sync'ing from the upstream field; it doesn't exist, thus
- # abort the optimization attempt and do a full sync.
+ # Exit code 128 means "couldn't find the ref you asked for"; if we're
+ # in sha1 mode, we just tried sync'ing from the upstream field; it
+ # doesn't exist, thus abort the optimization attempt and do a full sync.
break
elif ret < 0:
# Git died with a signal, exit immediately
@@ -1987,20 +2009,24 @@
initial=False, quiet=quiet, alt_dir=alt_dir)
if self.clone_depth:
self.clone_depth = None
- return self._RemoteFetch(name=name, current_branch_only=current_branch_only,
+ return self._RemoteFetch(name=name,
+ current_branch_only=current_branch_only,
initial=False, quiet=quiet, alt_dir=alt_dir)
return ok
def _ApplyCloneBundle(self, initial=False, quiet=False):
- if initial and (self.manifest.manifestProject.config.GetString('repo.depth') or self.clone_depth):
+ if initial and \
+ (self.manifest.manifestProject.config.GetString('repo.depth') or
+ self.clone_depth):
return False
remote = self.GetRemote(self.remote.name)
bundle_url = remote.url + '/clone.bundle'
bundle_url = GitConfig.ForUser().UrlInsteadOf(bundle_url)
- if GetSchemeFromUrl(bundle_url) not in (
- 'http', 'https', 'persistent-http', 'persistent-https'):
+ if GetSchemeFromUrl(bundle_url) not in ('http', 'https',
+ 'persistent-http',
+ 'persistent-https'):
return False
bundle_dst = os.path.join(self.gitdir, 'clone.bundle')
@@ -2049,7 +2075,7 @@
os.remove(tmpPath)
if 'http_proxy' in os.environ and 'darwin' == sys.platform:
cmd += ['--proxy', os.environ['http_proxy']]
- with GetUrlCookieFile(srcUrl, quiet) as (cookiefile, proxy):
+ with GetUrlCookieFile(srcUrl, quiet) as (cookiefile, _proxy):
if cookiefile:
cmd += ['--cookie', cookiefile, '--cookie-jar', cookiefile]
if srcUrl.startswith('persistent-'):
@@ -2168,11 +2194,12 @@
self._CheckDirReference(self.objdir, self.gitdir, share_refs=False)
except GitError as e:
if force_sync:
- print("Retrying clone after deleting %s" % self.gitdir, file=sys.stderr)
+ print("Retrying clone after deleting %s" %
+ self.gitdir, file=sys.stderr)
try:
shutil.rmtree(os.path.realpath(self.gitdir))
- if self.worktree and os.path.exists(
- os.path.realpath(self.worktree)):
+ if self.worktree and os.path.exists(os.path.realpath
+ (self.worktree)):
shutil.rmtree(os.path.realpath(self.worktree))
return self._InitGitDir(mirror_git=mirror_git, force_sync=False)
except:
@@ -2231,7 +2258,7 @@
name = os.path.basename(stock_hook)
if name in ('commit-msg',) and not self.remote.review \
- and not self is self.manifest.manifestProject:
+ and self is not self.manifest.manifestProject:
# Don't install a Gerrit Code Review hook if this
# project does not appear to use it for reviews.
#
@@ -2246,7 +2273,8 @@
if filecmp.cmp(stock_hook, dst, shallow=False):
os.remove(dst)
else:
- _warn("%s: Not replacing locally modified %s hook", self.relpath, name)
+ _warn("%s: Not replacing locally modified %s hook",
+ self.relpath, name)
continue
try:
os.symlink(os.path.relpath(stock_hook, os.path.dirname(dst)), dst)
@@ -2292,8 +2320,8 @@
self.bare_git.symbolic_ref('-m', msg, ref, dst)
def _CheckDirReference(self, srcdir, destdir, share_refs):
- symlink_files = self.shareable_files
- symlink_dirs = self.shareable_dirs
+ symlink_files = self.shareable_files[:]
+ symlink_dirs = self.shareable_dirs[:]
if share_refs:
symlink_files += self.working_tree_files
symlink_dirs += self.working_tree_dirs
@@ -2321,8 +2349,8 @@
copy_all: If true, copy all remaining files from |gitdir| -> |dotgit|.
This saves you the effort of initializing |dotgit| yourself.
"""
- symlink_files = self.shareable_files
- symlink_dirs = self.shareable_dirs
+ symlink_files = self.shareable_files[:]
+ symlink_dirs = self.shareable_dirs[:]
if share_refs:
symlink_files += self.working_tree_files
symlink_dirs += self.working_tree_dirs
@@ -2414,7 +2442,7 @@
def _allrefs(self):
return self.bare_ref.all
- def _getLogs(self, rev1, rev2, oneline=False, color=True):
+ def _getLogs(self, rev1, rev2, oneline=False, color=True, pretty_format=None):
"""Get logs between two revisions of this project."""
comp = '..'
if rev1:
@@ -2425,6 +2453,8 @@
out = DiffColoring(self.config)
if out.is_on and color:
cmd.append('--color')
+ if pretty_format is not None:
+ cmd.append('--pretty=format:%s' % pretty_format)
if oneline:
cmd.append('--oneline')
@@ -2441,17 +2471,21 @@
raise
return None
- def getAddedAndRemovedLogs(self, toProject, oneline=False, color=True):
+ def getAddedAndRemovedLogs(self, toProject, oneline=False, color=True,
+ pretty_format=None):
"""Get the list of logs from this revision to given revisionId"""
logs = {}
selfId = self.GetRevisionId(self._allrefs)
toId = toProject.GetRevisionId(toProject._allrefs)
- logs['added'] = self._getLogs(selfId, toId, oneline=oneline, color=color)
- logs['removed'] = self._getLogs(toId, selfId, oneline=oneline, color=color)
+ logs['added'] = self._getLogs(selfId, toId, oneline=oneline, color=color,
+ pretty_format=pretty_format)
+ logs['removed'] = self._getLogs(toId, selfId, oneline=oneline, color=color,
+ pretty_format=pretty_format)
return logs
class _GitGetByExec(object):
+
def __init__(self, project, bare, gitdir):
self._project = project
self._bare = bare
@@ -2470,8 +2504,8 @@
if p.Wait() == 0:
out = p.stdout
if out:
+ # Backslash is not anomalous
return out[:-1].split('\0') # pylint: disable=W1401
- # Backslash is not anomalous
return []
def DiffZ(self, name, *args):
@@ -2497,6 +2531,7 @@
break
class _Info(object):
+
def __init__(self, path, omode, nmode, oid, nid, state):
self.path = path
self.src_path = None
@@ -2599,10 +2634,8 @@
line = line[:-1]
r.append(line)
if p.Wait() != 0:
- raise GitError('%s rev-list %s: %s' % (
- self._project.name,
- str(args),
- p.stderr))
+ raise GitError('%s rev-list %s: %s' %
+ (self._project.name, str(args), p.stderr))
return r
def __getattr__(self, name):
@@ -2625,6 +2658,7 @@
A callable object that will try to call git with the named command.
"""
name = name.replace('_', '-')
+
def runner(*args, **kwargs):
cmdv = []
config = kwargs.pop('config', None)
@@ -2647,10 +2681,8 @@
capture_stdout=True,
capture_stderr=True)
if p.Wait() != 0:
- raise GitError('%s %s: %s' % (
- self._project.name,
- name,
- p.stderr))
+ raise GitError('%s %s: %s' %
+ (self._project.name, name, p.stderr))
r = p.stdout
try:
r = r.decode('utf-8')
@@ -2663,14 +2695,19 @@
class _PriorSyncFailedError(Exception):
+
def __str__(self):
return 'prior sync failed; rebase still in progress'
+
class _DirtyError(Exception):
+
def __str__(self):
return 'contains uncommitted changes'
+
class _InfoMessage(object):
+
def __init__(self, project, text):
self.project = project
self.text = text
@@ -2679,7 +2716,9 @@
syncbuf.out.info('%s/: %s', self.project.relpath, self.text)
syncbuf.out.nl()
+
class _Failure(object):
+
def __init__(self, project, why):
self.project = project
self.why = why
@@ -2690,7 +2729,9 @@
str(self.why))
syncbuf.out.nl()
+
class _Later(object):
+
def __init__(self, project, action):
self.project = project
self.action = action
@@ -2707,14 +2748,18 @@
out.nl()
return False
+
class _SyncColoring(Coloring):
+
def __init__(self, config):
Coloring.__init__(self, config, 'reposync')
self.project = self.printer('header', attr='bold')
self.info = self.printer('info')
self.fail = self.printer('fail', fg='red')
+
class SyncBuffer(object):
+
def __init__(self, config, detach_head=False):
self._messages = []
self._failures = []
@@ -2770,8 +2815,10 @@
class MetaProject(Project):
+
"""A special project housed under .repo.
"""
+
def __init__(self, manifest, name, gitdir, worktree):
Project.__init__(self,
manifest=manifest,
@@ -2805,10 +2852,9 @@
syncbuf.Finish()
return GitCommand(self,
- ['update-ref', '-d', 'refs/heads/default'],
- capture_stdout=True,
- capture_stderr=True).Wait() == 0
-
+ ['update-ref', '-d', 'refs/heads/default'],
+ capture_stdout=True,
+ capture_stderr=True).Wait() == 0
@property
def LastFetch(self):
diff --git a/repo b/repo
index 4721174..e5cb890 100755
--- a/repo
+++ b/repo
@@ -543,7 +543,7 @@
try:
r = urllib.request.urlopen(url)
except urllib.error.HTTPError as e:
- if e.code in [401, 403, 404]:
+ if e.code in [401, 403, 404, 501]:
return False
_print('fatal: Cannot get %s' % url, file=sys.stderr)
_print('fatal: HTTP error %s' % e.code, file=sys.stderr)
diff --git a/subcmds/diffmanifests.py b/subcmds/diffmanifests.py
index 0599868..751a202 100644
--- a/subcmds/diffmanifests.py
+++ b/subcmds/diffmanifests.py
@@ -71,6 +71,10 @@
p.add_option('--no-color',
dest='color', action='store_false', default=True,
help='does not display the diff in color.')
+ p.add_option('--pretty-format',
+ dest='pretty_format', action='store',
+ metavar='<FORMAT>',
+ help='print the log using a custom git pretty format string')
def _printRawDiff(self, diff):
for project in diff['added']:
@@ -92,7 +96,7 @@
otherProject.revisionExpr))
self.out.nl()
- def _printDiff(self, diff, color=True):
+ def _printDiff(self, diff, color=True, pretty_format=None):
if diff['added']:
self.out.nl()
self.printText('added projects : \n')
@@ -124,7 +128,8 @@
self.printText(' to ')
self.printRevision(otherProject.revisionExpr)
self.out.nl()
- self._printLogs(project, otherProject, raw=False, color=color)
+ self._printLogs(project, otherProject, raw=False, color=color,
+ pretty_format=pretty_format)
self.out.nl()
if diff['unreachable']:
@@ -139,9 +144,13 @@
self.printText(' not found')
self.out.nl()
- def _printLogs(self, project, otherProject, raw=False, color=True):
- logs = project.getAddedAndRemovedLogs(otherProject, oneline=True,
- color=color)
+ def _printLogs(self, project, otherProject, raw=False, color=True,
+ pretty_format=None):
+
+ logs = project.getAddedAndRemovedLogs(otherProject,
+ oneline=(pretty_format is None),
+ color=color,
+ pretty_format=pretty_format)
if logs['removed']:
removedLogs = logs['removed'].split('\n')
for log in removedLogs:
@@ -192,4 +201,4 @@
if opt.raw:
self._printRawDiff(diff)
else:
- self._printDiff(diff, color=opt.color)
+ self._printDiff(diff, color=opt.color, pretty_format=opt.pretty_format)
diff --git a/subcmds/forall.py b/subcmds/forall.py
index b10f34b..07ee8d5 100644
--- a/subcmds/forall.py
+++ b/subcmds/forall.py
@@ -120,6 +120,9 @@
p.add_option('-r', '--regex',
dest='regex', action='store_true',
help="Execute the command only on projects matching regex or wildcard expression")
+ p.add_option('-i', '--inverse-regex',
+ dest='inverse_regex', action='store_true',
+ help="Execute the command only on projects not matching regex or wildcard expression")
p.add_option('-g', '--groups',
dest='groups',
help="Execute the command only on projects matching the specified groups")
@@ -215,10 +218,12 @@
if os.path.isfile(smart_sync_manifest_path):
self.manifest.Override(smart_sync_manifest_path)
- if not opt.regex:
- projects = self.GetProjects(args, groups=opt.groups)
- else:
+ if opt.regex:
projects = self.FindProjects(args)
+ elif opt.inverse_regex:
+ projects = self.FindProjects(args, inverse=True)
+ else:
+ projects = self.GetProjects(args, groups=opt.groups)
os.environ['REPO_COUNT'] = str(len(projects))
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 4af411c..9124a65 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -242,7 +242,7 @@
if show_smart:
p.add_option('-s', '--smart-sync',
dest='smart_sync', action='store_true',
- help='smart sync using manifest from a known good build')
+ help='smart sync using manifest from the latest known good build')
p.add_option('-t', '--smart-tag',
dest='smart_tag', action='store',
help='smart sync using manifest from a known tag')