Merge changes from topic 'pylint-pep8-cleanup'

* changes:
  command.py: Cleaned up pylint/pep8 violations
  project.py: Cleaned up pylint/pep8 violations
This commit is contained in:
David Pursehouse 2016-03-15 00:31:12 +00:00 committed by Gerrit Code Review
commit 936d6185eb
2 changed files with 165 additions and 122 deletions

View File

@ -31,7 +31,7 @@ class Command(object):
manifest = None manifest = None
_optparse = None _optparse = None
def WantPager(self, opt): def WantPager(self, _opt):
return False return False
def ReadEnvironmentOptions(self, opts): def ReadEnvironmentOptions(self, opts):
@ -63,7 +63,7 @@ class Command(object):
usage = self.helpUsage.strip().replace('%prog', me) usage = self.helpUsage.strip().replace('%prog', me)
except AttributeError: except AttributeError:
usage = 'repo %s' % self.NAME usage = 'repo %s' % self.NAME
self._optparse = optparse.OptionParser(usage = usage) self._optparse = optparse.OptionParser(usage=usage)
self._Options(self._optparse) self._Options(self._optparse)
return self._optparse return self._optparse
@ -110,9 +110,9 @@ class Command(object):
project = None project = None
if os.path.exists(path): if os.path.exists(path):
oldpath = None oldpath = None
while path \ while path and \
and path != oldpath \ path != oldpath and \
and path != manifest.topdir: path != manifest.topdir:
try: try:
project = self._by_path[path] project = self._by_path[path]
break break
@ -138,7 +138,7 @@ class Command(object):
mp = manifest.manifestProject mp = manifest.manifestProject
if not groups: if not groups:
groups = mp.config.GetString('manifest.groups') groups = mp.config.GetString('manifest.groups')
if not groups: if not groups:
groups = 'default,platform-' + platform.system().lower() groups = 'default,platform-' + platform.system().lower()
groups = [x for x in re.split(r'[,\s]+', groups) if x] groups = [x for x in re.split(r'[,\s]+', groups) if x]
@ -151,8 +151,7 @@ class Command(object):
for p in project.GetDerivedSubprojects()) for p in project.GetDerivedSubprojects())
all_projects_list.extend(derived_projects.values()) all_projects_list.extend(derived_projects.values())
for project in all_projects_list: for project in all_projects_list:
if ((missing_ok or project.Exists) and if (missing_ok or project.Exists) and project.MatchesGroups(groups):
project.MatchesGroups(groups)):
result.append(project) result.append(project)
else: else:
self._ResetPathToProjectMap(all_projects_list) self._ResetPathToProjectMap(all_projects_list)
@ -166,8 +165,8 @@ class Command(object):
# If it's not a derived project, update path->project mapping and # If it's not a derived project, update path->project mapping and
# search again, as arg might actually point to a derived subproject. # search again, as arg might actually point to a derived subproject.
if (project and not project.Derived and if (project and not project.Derived and (submodules_ok or
(submodules_ok or project.sync_s)): project.sync_s)):
search_again = False search_again = False
for subproject in project.GetDerivedSubprojects(): for subproject in project.GetDerivedSubprojects():
self._UpdatePathToProjectMap(subproject) self._UpdatePathToProjectMap(subproject)
@ -205,6 +204,7 @@ class Command(object):
result.sort(key=lambda project: project.relpath) result.sort(key=lambda project: project.relpath)
return result return result
# pylint: disable=W0223 # pylint: disable=W0223
# Pylint warns that the `InteractiveCommand` and `PagedCommand` classes do not # Pylint warns that the `InteractiveCommand` and `PagedCommand` classes do not
# override method `Execute` which is abstract in `Command`. Since that method # override method `Execute` which is abstract in `Command`. Since that method
@ -214,28 +214,32 @@ class InteractiveCommand(Command):
"""Command which requires user interaction on the tty and """Command which requires user interaction on the tty and
must not run within a pager, even if the user asks to. must not run within a pager, even if the user asks to.
""" """
def WantPager(self, opt): def WantPager(self, _opt):
return False return False
class PagedCommand(Command): class PagedCommand(Command):
"""Command which defaults to output in a pager, as its """Command which defaults to output in a pager, as its
display tends to be larger than one screen full. display tends to be larger than one screen full.
""" """
def WantPager(self, opt): def WantPager(self, _opt):
return True return True
# pylint: enable=W0223 # pylint: enable=W0223
class MirrorSafeCommand(object): class MirrorSafeCommand(object):
"""Command permits itself to run within a mirror, """Command permits itself to run within a mirror,
and does not require a working directory. and does not require a working directory.
""" """
class GitcAvailableCommand(object): class GitcAvailableCommand(object):
"""Command that requires GITC to be available, but does """Command that requires GITC to be available, but does
not require the local client to be a GITC client. not require the local client to be a GITC client.
""" """
class GitcClientCommand(object): class GitcClientCommand(object):
"""Command that requires the local client to be a GITC """Command that requires the local client to be a GITC
client. client.

View File

@ -30,7 +30,8 @@ import traceback
from color import Coloring from color import Coloring
from git_command import GitCommand, git_require 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 GitError, HookError, UploadError, DownloadError
from error import ManifestInvalidRevisionError from error import ManifestInvalidRevisionError
from error import NoManifestException from error import NoManifestException
@ -44,6 +45,7 @@ if not is_python3():
input = raw_input input = raw_input
# pylint:enable=W0622 # pylint:enable=W0622
def _lwrite(path, content): def _lwrite(path, content):
lock = '%s.lock' % path lock = '%s.lock' % path
@ -59,21 +61,27 @@ def _lwrite(path, content):
os.remove(lock) os.remove(lock)
raise raise
def _error(fmt, *args): def _error(fmt, *args):
msg = fmt % args msg = fmt % args
print('error: %s' % msg, file=sys.stderr) print('error: %s' % msg, file=sys.stderr)
def _warn(fmt, *args): def _warn(fmt, *args):
msg = fmt % args msg = fmt % args
print('warn: %s' % msg, file=sys.stderr) print('warn: %s' % msg, file=sys.stderr)
def not_rev(r): def not_rev(r):
return '^' + r return '^' + r
def sq(r): def sq(r):
return "'" + r.replace("'", "'\''") + "'" return "'" + r.replace("'", "'\''") + "'"
_project_hook_list = None _project_hook_list = None
def _ProjectHooks(): def _ProjectHooks():
"""List the hooks present in the 'hooks' directory. """List the hooks present in the 'hooks' directory.
@ -107,15 +115,14 @@ class DownloadedChange(object):
@property @property
def commits(self): def commits(self):
if self._commit_cache is None: if self._commit_cache is None:
self._commit_cache = self.project.bare_git.rev_list( self._commit_cache = self.project.bare_git.rev_list('--abbrev=8',
'--abbrev=8', '--abbrev-commit',
'--abbrev-commit', '--pretty=oneline',
'--pretty=oneline', '--reverse',
'--reverse', '--date-order',
'--date-order', not_rev(self.base),
not_rev(self.base), self.commit,
self.commit, '--')
'--')
return self._commit_cache return self._commit_cache
@ -134,36 +141,36 @@ class ReviewableBranch(object):
@property @property
def commits(self): def commits(self):
if self._commit_cache is None: if self._commit_cache is None:
self._commit_cache = self.project.bare_git.rev_list( self._commit_cache = self.project.bare_git.rev_list('--abbrev=8',
'--abbrev=8', '--abbrev-commit',
'--abbrev-commit', '--pretty=oneline',
'--pretty=oneline', '--reverse',
'--reverse', '--date-order',
'--date-order', not_rev(self.base),
not_rev(self.base), R_HEADS + self.name,
R_HEADS + self.name, '--')
'--')
return self._commit_cache return self._commit_cache
@property @property
def unabbrev_commits(self): def unabbrev_commits(self):
r = dict() r = dict()
for commit in self.project.bare_git.rev_list( for commit in self.project.bare_git.rev_list(not_rev(self.base),
not_rev(self.base), R_HEADS + self.name,
R_HEADS + self.name, '--'):
'--'):
r[commit[0:8]] = commit r[commit[0:8]] = commit
return r return r
@property @property
def date(self): def date(self):
return self.project.bare_git.log( return self.project.bare_git.log('--pretty=format:%cd',
'--pretty=format:%cd', '-n', '1',
'-n', '1', R_HEADS + self.name,
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, self.project.UploadForReview(self.name,
people, people,
auto_topic=auto_topic, auto_topic=auto_topic,
@ -173,8 +180,8 @@ class ReviewableBranch(object):
def GetPublishedRefs(self): def GetPublishedRefs(self):
refs = {} refs = {}
output = self.project.bare_git.ls_remote( output = self.project.bare_git.ls_remote(
self.branch.remote.SshReviewUrl(self.project.UserEmail), self.branch.remote.SshReviewUrl(self.project.UserEmail),
'refs/changes/*') 'refs/changes/*')
for line in output.split('\n'): for line in output.split('\n'):
try: try:
(sha, ref) = line.split() (sha, ref) = line.split()
@ -184,7 +191,9 @@ class ReviewableBranch(object):
return refs return refs
class StatusColoring(Coloring): class StatusColoring(Coloring):
def __init__(self, config): def __init__(self, config):
Coloring.__init__(self, config, 'status') Coloring.__init__(self, config, 'status')
self.project = self.printer('header', attr='bold') self.project = self.printer('header', attr='bold')
@ -198,17 +207,22 @@ class StatusColoring(Coloring):
class DiffColoring(Coloring): class DiffColoring(Coloring):
def __init__(self, config): def __init__(self, config):
Coloring.__init__(self, config, 'diff') Coloring.__init__(self, config, 'diff')
self.project = self.printer('header', attr='bold') self.project = self.printer('header', attr='bold')
class _Annotation(object): class _Annotation(object):
def __init__(self, name, value, keep): def __init__(self, name, value, keep):
self.name = name self.name = name
self.value = value self.value = value
self.keep = keep self.keep = keep
class _CopyFile(object): class _CopyFile(object):
def __init__(self, src, dest, abssrc, absdest): def __init__(self, src, dest, abssrc, absdest):
self.src = src self.src = src
self.dest = dest self.dest = dest
@ -236,7 +250,9 @@ class _CopyFile(object):
except IOError: except IOError:
_error('Cannot copy file %s to %s', src, dest) _error('Cannot copy file %s to %s', src, dest)
class _LinkFile(object): class _LinkFile(object):
def __init__(self, git_worktree, src, dest, relsrc, absdest): def __init__(self, git_worktree, src, dest, relsrc, absdest):
self.git_worktree = git_worktree self.git_worktree = git_worktree
self.src = src self.src = src
@ -275,7 +291,7 @@ class _LinkFile(object):
absDestDir = self.abs_dest absDestDir = self.abs_dest
if os.path.exists(absDestDir) and not os.path.isdir(absDestDir): if os.path.exists(absDestDir) and not os.path.isdir(absDestDir):
_error('Link error: src with wildcard, %s must be a directory', _error('Link error: src with wildcard, %s must be a directory',
absDestDir) absDestDir)
else: else:
absSrcFiles = glob.glob(absSrc) absSrcFiles = glob.glob(absSrc)
for absSrcFile in absSrcFiles: for absSrcFile in absSrcFiles:
@ -292,7 +308,9 @@ class _LinkFile(object):
relSrc = os.path.join(relSrcDir, srcFile) relSrc = os.path.join(relSrcDir, srcFile)
self.__linkIt(relSrc, absDest) self.__linkIt(relSrc, absDest)
class RemoteSpec(object): class RemoteSpec(object):
def __init__(self, def __init__(self,
name, name,
url=None, url=None,
@ -303,7 +321,9 @@ class RemoteSpec(object):
self.review = review self.review = review
self.revision = revision self.revision = revision
class RepoHook(object): class RepoHook(object):
"""A RepoHook contains information about a script to run as a hook. """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, Hooks are used to run a python script before running an upload (for instance,
@ -316,6 +336,7 @@ class RepoHook(object):
Hooks are always python. When a hook is run, we will load the hook into the Hooks are always python. When a hook is run, we will load the hook into the
interpreter and execute its main() function. interpreter and execute its main() function.
""" """
def __init__(self, def __init__(self,
hook_type, hook_type,
hooks_project, hooks_project,
@ -430,8 +451,8 @@ class RepoHook(object):
' %s\n' ' %s\n'
'\n' '\n'
'Do you want to allow this script to run ' 'Do you want to allow this script to run '
'(yes/yes-never-ask-again/NO)? ') % ( '(yes/yes-never-ask-again/NO)? ') % (self._GetMustVerb(),
self._GetMustVerb(), self._script_fullpath) self._script_fullpath)
response = input(prompt).lower() response = input(prompt).lower()
print() print()
@ -480,14 +501,13 @@ class RepoHook(object):
exec(compile(open(self._script_fullpath).read(), exec(compile(open(self._script_fullpath).read(),
self._script_fullpath, 'exec'), context) self._script_fullpath, 'exec'), context)
except Exception: except Exception:
raise HookError('%s\nFailed to import %s hook; see traceback above.' % ( raise HookError('%s\nFailed to import %s hook; see traceback above.' %
traceback.format_exc(), self._hook_type)) (traceback.format_exc(), self._hook_type))
# Running the script should have defined a main() function. # Running the script should have defined a main() function.
if 'main' not in context: if 'main' not in context:
raise HookError('Missing main() in: "%s"' % self._script_fullpath) raise HookError('Missing main() in: "%s"' % self._script_fullpath)
# Add 'hook_should_take_kwargs' to the arguments to be passed to main. # 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-- # 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. # it's there to remind them that their hook should always take **kwargs.
@ -505,8 +525,8 @@ class RepoHook(object):
context['main'](**kwargs) context['main'](**kwargs)
except Exception: except Exception:
raise HookError('%s\nFailed to run main() for %s hook; see traceback ' raise HookError('%s\nFailed to run main() for %s hook; see traceback '
'above.' % ( 'above.' % (traceback.format_exc(),
traceback.format_exc(), self._hook_type)) self._hook_type))
finally: finally:
# Restore sys.path and CWD. # Restore sys.path and CWD.
sys.path = orig_syspath sys.path = orig_syspath
@ -530,8 +550,8 @@ class RepoHook(object):
to run a required hook (from _CheckForHookApproval). to run a required hook (from _CheckForHookApproval).
""" """
# No-op if there is no hooks project or if hook is disabled. # No-op if there is no hooks project or if hook is disabled.
if ((not self._hooks_project) or if ((not self._hooks_project) or (self._hook_type not in
(self._hook_type not in self._hooks_project.enabled_repo_hooks)): self._hooks_project.enabled_repo_hooks)):
return return
# Bail with a nice error if we can't find the hook. # Bail with a nice error if we can't find the hook.
@ -553,6 +573,7 @@ class Project(object):
# These objects can only be used by a single working tree. # These objects can only be used by a single working tree.
working_tree_files = ['config', 'packed-refs', 'shallow'] working_tree_files = ['config', 'packed-refs', 'shallow']
working_tree_dirs = ['logs', 'refs'] working_tree_dirs = ['logs', 'refs']
def __init__(self, def __init__(self,
manifest, manifest,
name, name,
@ -611,9 +632,9 @@ class Project(object):
self.relpath = relpath self.relpath = relpath
self.revisionExpr = revisionExpr self.revisionExpr = revisionExpr
if revisionId is None \ if revisionId is None \
and revisionExpr \ and revisionExpr \
and IsId(revisionExpr): and IsId(revisionExpr):
self.revisionId = revisionExpr self.revisionId = revisionExpr
else: else:
self.revisionId = revisionId self.revisionId = revisionId
@ -633,9 +654,8 @@ class Project(object):
self.copyfiles = [] self.copyfiles = []
self.linkfiles = [] self.linkfiles = []
self.annotations = [] self.annotations = []
self.config = GitConfig.ForRepository( self.config = GitConfig.ForRepository(gitdir=self.gitdir,
gitdir=self.gitdir, defaults=self.manifest.globalConfig)
defaults=self.manifest.globalConfig)
if self.worktree: if self.worktree:
self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir) self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir)
@ -773,7 +793,7 @@ class Project(object):
""" """
expanded_manifest_groups = manifest_groups or ['default'] expanded_manifest_groups = manifest_groups or ['default']
expanded_project_groups = ['all'] + (self.groups or []) 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'] expanded_project_groups += ['default']
matched = False matched = False
@ -785,7 +805,7 @@ class Project(object):
return matched return matched
## Status Display ## # Status Display ##
def UncommitedFiles(self, get_all=True): def UncommitedFiles(self, get_all=True):
"""Returns a list of strings, uncommitted files in the git tree. """Returns a list of strings, uncommitted files in the git tree.
@ -837,7 +857,7 @@ class Project(object):
output: If specified, redirect the output to this object. output: If specified, redirect the output to this object.
""" """
if not os.path.isdir(self.worktree): if not os.path.isdir(self.worktree):
if output_redir == None: if output_redir is None:
output_redir = sys.stdout output_redir = sys.stdout
print(file=output_redir) print(file=output_redir)
print('project %s/' % self.relpath, file=output_redir) print('project %s/' % self.relpath, file=output_redir)
@ -856,7 +876,7 @@ class Project(object):
return 'CLEAN' return 'CLEAN'
out = StatusColoring(self.config) out = StatusColoring(self.config)
if not output_redir == None: if output_redir is not None:
out.redirect(output_redir) out.redirect(output_redir)
out.project('project %-40s', self.relpath + '/ ') out.project('project %-40s', self.relpath + '/ ')
@ -899,7 +919,7 @@ class Project(object):
if i and i.src_path: if i and i.src_path:
line = ' %s%s\t%s => %s (%s%%)' % (i_status, f_status, line = ' %s%s\t%s => %s (%s%%)' % (i_status, f_status,
i.src_path, p, i.level) i.src_path, p, i.level)
else: else:
line = ' %s%s\t%s' % (i_status, f_status, p) line = ' %s%s\t%s' % (i_status, f_status, p)
@ -942,7 +962,7 @@ class Project(object):
p.Wait() p.Wait()
## Publish / Upload ## # Publish / Upload ##
def WasPublished(self, branch, all_refs=None): def WasPublished(self, branch, all_refs=None):
"""Was the branch published (uploaded) for code review? """Was the branch published (uploaded) for code review?
@ -1085,7 +1105,7 @@ class Project(object):
message=msg) message=msg)
## Sync ## # Sync ##
def _ExtractArchive(self, tarpath, path=None): def _ExtractArchive(self, tarpath, path=None):
"""Extract the given tar on its current location """Extract the given tar on its current location
@ -1103,15 +1123,15 @@ class Project(object):
return False return False
def Sync_NetworkHalf(self, def Sync_NetworkHalf(self,
quiet=False, quiet=False,
is_new=None, is_new=None,
current_branch_only=False, current_branch_only=False,
force_sync=False, force_sync=False,
clone_bundle=True, clone_bundle=True,
no_tags=False, no_tags=False,
archive=False, archive=False,
optimized_fetch=False, optimized_fetch=False,
prune=False): prune=False):
"""Perform only the network IO portion of the sync process. """Perform only the network IO portion of the sync process.
Local working directory/branch state is not affected. Local working directory/branch state is not affected.
""" """
@ -1164,8 +1184,8 @@ class Project(object):
alt_dir = None alt_dir = None
if clone_bundle \ if clone_bundle \
and alt_dir is None \ and alt_dir is None \
and self._ApplyCloneBundle(initial=is_new, quiet=quiet): and self._ApplyCloneBundle(initial=is_new, quiet=quiet):
is_new = False is_new = False
if not current_branch_only: if not current_branch_only:
@ -1177,12 +1197,13 @@ class Project(object):
elif self.manifest.default.sync_c: elif self.manifest.default.sync_c:
current_branch_only = True current_branch_only = True
need_to_fetch = not (optimized_fetch and \ need_to_fetch = not (optimized_fetch and
(ID_RE.match(self.revisionExpr) and self._CheckForSha1())) (ID_RE.match(self.revisionExpr) and
if (need_to_fetch self._CheckForSha1()))
and not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir, if (need_to_fetch and
current_branch_only=current_branch_only, not self._RemoteFetch(initial=is_new, quiet=quiet, alt_dir=alt_dir,
no_tags=no_tags, prune=prune)): current_branch_only=current_branch_only,
no_tags=no_tags, prune=prune)):
return False return False
if self.worktree: if self.worktree:
@ -1219,9 +1240,8 @@ class Project(object):
try: try:
return self.bare_git.rev_list(self.revisionExpr, '-1')[0] return self.bare_git.rev_list(self.revisionExpr, '-1')[0]
except GitError: except GitError:
raise ManifestInvalidRevisionError( raise ManifestInvalidRevisionError('revision %s in %s not found' %
'revision %s in %s not found' % (self.revisionExpr, (self.revisionExpr, self.name))
self.name))
def GetRevisionId(self, all_refs=None): def GetRevisionId(self, all_refs=None):
if self.revisionId: if self.revisionId:
@ -1236,9 +1256,8 @@ class Project(object):
try: try:
return self.bare_git.rev_parse('--verify', '%s^0' % rev) return self.bare_git.rev_parse('--verify', '%s^0' % rev)
except GitError: except GitError:
raise ManifestInvalidRevisionError( raise ManifestInvalidRevisionError('revision %s in %s not found' %
'revision %s in %s not found' % (self.revisionExpr, (self.revisionExpr, self.name))
self.name))
def Sync_LocalHalf(self, syncbuf, force_sync=False): def Sync_LocalHalf(self, syncbuf, force_sync=False):
"""Perform only the local IO portion of the sync process. """Perform only the local IO portion of the sync process.
@ -1327,8 +1346,8 @@ class Project(object):
# to rewrite the published commits so we punt. # to rewrite the published commits so we punt.
# #
syncbuf.fail(self, syncbuf.fail(self,
"branch %s is published (but not merged) and is now %d commits behind" "branch %s is published (but not merged) and is now "
% (branch.name, len(upstream_gain))) "%d commits behind" % (branch.name, len(upstream_gain)))
return return
elif pub == head: elif pub == head:
# All published commits are merged, and thus we are a # All published commits are merged, and thus we are a
@ -1422,7 +1441,7 @@ class Project(object):
remote = self.GetRemote(self.remote.name) remote = self.GetRemote(self.remote.name)
cmd = ['fetch', 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)) % (change_id % 100, change_id, patch_id))
if GitCommand(self, cmd, bare=True).Wait() != 0: if GitCommand(self, cmd, bare=True).Wait() != 0:
return None return None
@ -1433,7 +1452,7 @@ class Project(object):
self.bare_git.rev_parse('FETCH_HEAD')) self.bare_git.rev_parse('FETCH_HEAD'))
## Branch Management ## # Branch Management ##
def StartBranch(self, name, branch_merge=''): def StartBranch(self, name, branch_merge=''):
"""Create a new branch off the manifest's revision. """Create a new branch off the manifest's revision.
@ -1620,10 +1639,11 @@ class Project(object):
return kept return kept
## Submodule Management ## # Submodule Management ##
def GetRegisteredSubprojects(self): def GetRegisteredSubprojects(self):
result = [] result = []
def rec(subprojects): def rec(subprojects):
if not subprojects: if not subprojects:
return return
@ -1658,6 +1678,7 @@ class Project(object):
re_path = re.compile(r'^submodule\.([^.]+)\.path=(.*)$') re_path = re.compile(r'^submodule\.([^.]+)\.path=(.*)$')
re_url = re.compile(r'^submodule\.([^.]+)\.url=(.*)$') re_url = re.compile(r'^submodule\.([^.]+)\.url=(.*)$')
def parse_gitmodules(gitdir, rev): def parse_gitmodules(gitdir, rev):
cmd = ['cat-file', 'blob', '%s:.gitmodules' % rev] cmd = ['cat-file', 'blob', '%s:.gitmodules' % rev]
try: try:
@ -1767,7 +1788,7 @@ class Project(object):
return result return result
## Direct Git Commands ## # Direct Git Commands ##
def _CheckForSha1(self): def _CheckForSha1(self):
try: try:
# if revision (sha or tag) is not present then following function # if revision (sha or tag) is not present then following function
@ -1791,7 +1812,6 @@ class Project(object):
if command.Wait() != 0: if command.Wait() != 0:
raise GitError('git archive %s: %s' % (self.name, command.stderr)) raise GitError('git archive %s: %s' % (self.name, command.stderr))
def _RemoteFetch(self, name=None, def _RemoteFetch(self, name=None,
current_branch_only=False, current_branch_only=False,
initial=False, initial=False,
@ -1955,9 +1975,9 @@ class Project(object):
break break
continue continue
elif current_branch_only and is_sha1 and ret == 128: 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 # Exit code 128 means "couldn't find the ref you asked for"; if we're
# mode, we just tried sync'ing from the upstream field; it doesn't exist, thus # in sha1 mode, we just tried sync'ing from the upstream field; it
# abort the optimization attempt and do a full sync. # doesn't exist, thus abort the optimization attempt and do a full sync.
break break
elif ret < 0: elif ret < 0:
# Git died with a signal, exit immediately # Git died with a signal, exit immediately
@ -1984,20 +2004,24 @@ class Project(object):
initial=False, quiet=quiet, alt_dir=alt_dir) initial=False, quiet=quiet, alt_dir=alt_dir)
if self.clone_depth: if self.clone_depth:
self.clone_depth = None 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) initial=False, quiet=quiet, alt_dir=alt_dir)
return ok return ok
def _ApplyCloneBundle(self, initial=False, quiet=False): 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 return False
remote = self.GetRemote(self.remote.name) remote = self.GetRemote(self.remote.name)
bundle_url = remote.url + '/clone.bundle' bundle_url = remote.url + '/clone.bundle'
bundle_url = GitConfig.ForUser().UrlInsteadOf(bundle_url) bundle_url = GitConfig.ForUser().UrlInsteadOf(bundle_url)
if GetSchemeFromUrl(bundle_url) not in ( if GetSchemeFromUrl(bundle_url) not in ('http', 'https',
'http', 'https', 'persistent-http', 'persistent-https'): 'persistent-http',
'persistent-https'):
return False return False
bundle_dst = os.path.join(self.gitdir, 'clone.bundle') bundle_dst = os.path.join(self.gitdir, 'clone.bundle')
@ -2046,7 +2070,7 @@ class Project(object):
os.remove(tmpPath) os.remove(tmpPath)
if 'http_proxy' in os.environ and 'darwin' == sys.platform: if 'http_proxy' in os.environ and 'darwin' == sys.platform:
cmd += ['--proxy', os.environ['http_proxy']] cmd += ['--proxy', os.environ['http_proxy']]
with GetUrlCookieFile(srcUrl, quiet) as (cookiefile, proxy): with GetUrlCookieFile(srcUrl, quiet) as (cookiefile, _proxy):
if cookiefile: if cookiefile:
cmd += ['--cookie', cookiefile, '--cookie-jar', cookiefile] cmd += ['--cookie', cookiefile, '--cookie-jar', cookiefile]
if srcUrl.startswith('persistent-'): if srcUrl.startswith('persistent-'):
@ -2165,11 +2189,12 @@ class Project(object):
self._CheckDirReference(self.objdir, self.gitdir, share_refs=False) self._CheckDirReference(self.objdir, self.gitdir, share_refs=False)
except GitError as e: except GitError as e:
if force_sync: 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: try:
shutil.rmtree(os.path.realpath(self.gitdir)) shutil.rmtree(os.path.realpath(self.gitdir))
if self.worktree and os.path.exists( if self.worktree and os.path.exists(os.path.realpath
os.path.realpath(self.worktree)): (self.worktree)):
shutil.rmtree(os.path.realpath(self.worktree)) shutil.rmtree(os.path.realpath(self.worktree))
return self._InitGitDir(mirror_git=mirror_git, force_sync=False) return self._InitGitDir(mirror_git=mirror_git, force_sync=False)
except: except:
@ -2228,7 +2253,7 @@ class Project(object):
name = os.path.basename(stock_hook) name = os.path.basename(stock_hook)
if name in ('commit-msg',) and not self.remote.review \ 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 # Don't install a Gerrit Code Review hook if this
# project does not appear to use it for reviews. # project does not appear to use it for reviews.
# #
@ -2243,7 +2268,8 @@ class Project(object):
if filecmp.cmp(stock_hook, dst, shallow=False): if filecmp.cmp(stock_hook, dst, shallow=False):
os.remove(dst) os.remove(dst)
else: else:
_warn("%s: Not replacing locally modified %s hook", self.relpath, name) _warn("%s: Not replacing locally modified %s hook",
self.relpath, name)
continue continue
try: try:
os.symlink(os.path.relpath(stock_hook, os.path.dirname(dst)), dst) os.symlink(os.path.relpath(stock_hook, os.path.dirname(dst)), dst)
@ -2449,6 +2475,7 @@ class Project(object):
return logs return logs
class _GitGetByExec(object): class _GitGetByExec(object):
def __init__(self, project, bare, gitdir): def __init__(self, project, bare, gitdir):
self._project = project self._project = project
self._bare = bare self._bare = bare
@ -2467,8 +2494,8 @@ class Project(object):
if p.Wait() == 0: if p.Wait() == 0:
out = p.stdout out = p.stdout
if out: if out:
# Backslash is not anomalous
return out[:-1].split('\0') # pylint: disable=W1401 return out[:-1].split('\0') # pylint: disable=W1401
# Backslash is not anomalous
return [] return []
def DiffZ(self, name, *args): def DiffZ(self, name, *args):
@ -2494,6 +2521,7 @@ class Project(object):
break break
class _Info(object): class _Info(object):
def __init__(self, path, omode, nmode, oid, nid, state): def __init__(self, path, omode, nmode, oid, nid, state):
self.path = path self.path = path
self.src_path = None self.src_path = None
@ -2596,10 +2624,8 @@ class Project(object):
line = line[:-1] line = line[:-1]
r.append(line) r.append(line)
if p.Wait() != 0: if p.Wait() != 0:
raise GitError('%s rev-list %s: %s' % ( raise GitError('%s rev-list %s: %s' %
self._project.name, (self._project.name, str(args), p.stderr))
str(args),
p.stderr))
return r return r
def __getattr__(self, name): def __getattr__(self, name):
@ -2622,6 +2648,7 @@ class Project(object):
A callable object that will try to call git with the named command. A callable object that will try to call git with the named command.
""" """
name = name.replace('_', '-') name = name.replace('_', '-')
def runner(*args, **kwargs): def runner(*args, **kwargs):
cmdv = [] cmdv = []
config = kwargs.pop('config', None) config = kwargs.pop('config', None)
@ -2644,10 +2671,8 @@ class Project(object):
capture_stdout=True, capture_stdout=True,
capture_stderr=True) capture_stderr=True)
if p.Wait() != 0: if p.Wait() != 0:
raise GitError('%s %s: %s' % ( raise GitError('%s %s: %s' %
self._project.name, (self._project.name, name, p.stderr))
name,
p.stderr))
r = p.stdout r = p.stdout
try: try:
r = r.decode('utf-8') r = r.decode('utf-8')
@ -2660,14 +2685,19 @@ class Project(object):
class _PriorSyncFailedError(Exception): class _PriorSyncFailedError(Exception):
def __str__(self): def __str__(self):
return 'prior sync failed; rebase still in progress' return 'prior sync failed; rebase still in progress'
class _DirtyError(Exception): class _DirtyError(Exception):
def __str__(self): def __str__(self):
return 'contains uncommitted changes' return 'contains uncommitted changes'
class _InfoMessage(object): class _InfoMessage(object):
def __init__(self, project, text): def __init__(self, project, text):
self.project = project self.project = project
self.text = text self.text = text
@ -2676,7 +2706,9 @@ class _InfoMessage(object):
syncbuf.out.info('%s/: %s', self.project.relpath, self.text) syncbuf.out.info('%s/: %s', self.project.relpath, self.text)
syncbuf.out.nl() syncbuf.out.nl()
class _Failure(object): class _Failure(object):
def __init__(self, project, why): def __init__(self, project, why):
self.project = project self.project = project
self.why = why self.why = why
@ -2687,7 +2719,9 @@ class _Failure(object):
str(self.why)) str(self.why))
syncbuf.out.nl() syncbuf.out.nl()
class _Later(object): class _Later(object):
def __init__(self, project, action): def __init__(self, project, action):
self.project = project self.project = project
self.action = action self.action = action
@ -2704,14 +2738,18 @@ class _Later(object):
out.nl() out.nl()
return False return False
class _SyncColoring(Coloring): class _SyncColoring(Coloring):
def __init__(self, config): def __init__(self, config):
Coloring.__init__(self, config, 'reposync') Coloring.__init__(self, config, 'reposync')
self.project = self.printer('header', attr='bold') self.project = self.printer('header', attr='bold')
self.info = self.printer('info') self.info = self.printer('info')
self.fail = self.printer('fail', fg='red') self.fail = self.printer('fail', fg='red')
class SyncBuffer(object): class SyncBuffer(object):
def __init__(self, config, detach_head=False): def __init__(self, config, detach_head=False):
self._messages = [] self._messages = []
self._failures = [] self._failures = []
@ -2767,8 +2805,10 @@ class SyncBuffer(object):
class MetaProject(Project): class MetaProject(Project):
"""A special project housed under .repo. """A special project housed under .repo.
""" """
def __init__(self, manifest, name, gitdir, worktree): def __init__(self, manifest, name, gitdir, worktree):
Project.__init__(self, Project.__init__(self,
manifest=manifest, manifest=manifest,
@ -2802,10 +2842,9 @@ class MetaProject(Project):
syncbuf.Finish() syncbuf.Finish()
return GitCommand(self, return GitCommand(self,
['update-ref', '-d', 'refs/heads/default'], ['update-ref', '-d', 'refs/heads/default'],
capture_stdout=True, capture_stdout=True,
capture_stderr=True).Wait() == 0 capture_stderr=True).Wait() == 0
@property @property
def LastFetch(self): def LastFetch(self):