Mercurial > public > mercurial-scm > hg
diff mercurial/subrepo.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | f6540aba8e3e |
children | 687b865b95ad |
line wrap: on
line diff
--- a/mercurial/subrepo.py Sat Oct 05 10:29:34 2019 -0400 +++ b/mercurial/subrepo.py Sun Oct 06 09:45:02 2019 -0400 @@ -47,6 +47,7 @@ _abssource = subrepoutil._abssource propertycache = util.propertycache + def _expandedabspath(path): ''' get a path or url and if it is a path expand it and return an absolute path @@ -57,17 +58,21 @@ path = util.normpath(os.path.abspath(u.path)) return path + def _getstorehashcachename(remotepath): '''get a unique filename for the store hash cache of a remote repository''' return node.hex(hashlib.sha1(_expandedabspath(remotepath)).digest())[0:12] + class SubrepoAbort(error.Abort): """Exception class used to avoid handling a subrepo error more than once""" + def __init__(self, *args, **kw): self.subrepo = kw.pop(r'subrepo', None) self.cause = kw.pop(r'cause', None) error.Abort.__init__(self, *args, **kw) + def annotatesubrepoerror(func): def decoratedmethod(self, *args, **kargs): try: @@ -77,30 +82,39 @@ raise ex except error.Abort as ex: subrepo = subrelpath(self) - errormsg = (stringutil.forcebytestr(ex) + ' ' - + _('(in subrepository "%s")') % subrepo) + errormsg = ( + stringutil.forcebytestr(ex) + + ' ' + + _('(in subrepository "%s")') % subrepo + ) # avoid handling this exception by raising a SubrepoAbort exception - raise SubrepoAbort(errormsg, hint=ex.hint, subrepo=subrepo, - cause=sys.exc_info()) + raise SubrepoAbort( + errormsg, hint=ex.hint, subrepo=subrepo, cause=sys.exc_info() + ) return res + return decoratedmethod + def _updateprompt(ui, sub, dirty, local, remote): if dirty: - msg = (_(' subrepository sources for %s differ\n' - 'you can use (l)ocal source (%s) or (r)emote source (%s).\n' - 'what do you want to do?' - '$$ &Local $$ &Remote') - % (subrelpath(sub), local, remote)) + msg = _( + ' subrepository sources for %s differ\n' + 'you can use (l)ocal source (%s) or (r)emote source (%s).\n' + 'what do you want to do?' + '$$ &Local $$ &Remote' + ) % (subrelpath(sub), local, remote) else: - msg = (_(' subrepository sources for %s differ (in checked out ' - 'version)\n' - 'you can use (l)ocal source (%s) or (r)emote source (%s).\n' - 'what do you want to do?' - '$$ &Local $$ &Remote') - % (subrelpath(sub), local, remote)) + msg = _( + ' subrepository sources for %s differ (in checked out ' + 'version)\n' + 'you can use (l)ocal source (%s) or (r)emote source (%s).\n' + 'what do you want to do?' + '$$ &Local $$ &Remote' + ) % (subrelpath(sub), local, remote) return ui.promptchoice(msg, 0) + def _sanitize(ui, vfs, ignore): for dirname, dirs, names in vfs.walk(): for i, d in enumerate(dirs): @@ -111,41 +125,55 @@ continue for f in names: if f.lower() == 'hgrc': - ui.warn(_("warning: removing potentially hostile 'hgrc' " - "in '%s'\n") % vfs.join(dirname)) + ui.warn( + _( + "warning: removing potentially hostile 'hgrc' " + "in '%s'\n" + ) + % vfs.join(dirname) + ) vfs.unlink(vfs.reljoin(dirname, f)) + def _auditsubrepopath(repo, path): # sanity check for potentially unsafe paths such as '~' and '$FOO' if path.startswith('~') or '$' in path or util.expandpath(path) != path: - raise error.Abort(_('subrepo path contains illegal component: %s') - % path) + raise error.Abort( + _('subrepo path contains illegal component: %s') % path + ) # auditor doesn't check if the path itself is a symlink pathutil.pathauditor(repo.root)(path) if repo.wvfs.islink(path): raise error.Abort(_("subrepo '%s' traverses symbolic link") % path) + SUBREPO_ALLOWED_DEFAULTS = { 'hg': True, 'git': False, 'svn': False, } + def _checktype(ui, kind): # subrepos.allowed is a master kill switch. If disabled, subrepos are # disabled period. if not ui.configbool('subrepos', 'allowed', True): - raise error.Abort(_('subrepos not enabled'), - hint=_("see 'hg help config.subrepos' for details")) + raise error.Abort( + _('subrepos not enabled'), + hint=_("see 'hg help config.subrepos' for details"), + ) default = SUBREPO_ALLOWED_DEFAULTS.get(kind, False) if not ui.configbool('subrepos', '%s:allowed' % kind, default): - raise error.Abort(_('%s subrepos not allowed') % kind, - hint=_("see 'hg help config.subrepos' for details")) + raise error.Abort( + _('%s subrepos not allowed') % kind, + hint=_("see 'hg help config.subrepos' for details"), + ) if kind not in types: raise error.Abort(_('unknown subrepo type %s') % kind) + def subrepo(ctx, path, allowwdir=False, allowcreate=True): """return instance of the right subrepo class for subrepo in path""" # subrepo inherently violates our import layering rules @@ -154,6 +182,7 @@ # scripts that don't use our demand-loading global hg from . import hg as h + hg = h repo = ctx.repo() @@ -164,6 +193,7 @@ state = (state[0], ctx.subrev(path), state[2]) return types[state[2]](ctx, path, state[:2], allowcreate) + def nullsubrepo(ctx, path, pctx): """return an empty subrepo in pctx for the extant subrepo in ctx""" # subrepo inherently violates our import layering rules @@ -172,6 +202,7 @@ # scripts that don't use our demand-loading global hg from . import hg as h + hg = h repo = ctx.repo() @@ -183,10 +214,11 @@ subrev = "0" * 40 return types[state[2]](pctx, path, (state[0], subrev), True) + # subrepo classes need to implement the following abstract class: + class abstractsubrepo(object): - def __init__(self, ctx, path): """Initialize abstractsubrepo part @@ -233,14 +265,14 @@ This returns None, otherwise. """ if self.dirty(ignoreupdate=ignoreupdate, missing=missing): - return _('uncommitted changes in subrepository "%s"' - ) % subrelpath(self) + return _('uncommitted changes in subrepository "%s"') % subrelpath( + self + ) def bailifchanged(self, ignoreupdate=False, hint=None): """raise Abort if subrepository is ``dirty()`` """ - dirtyreason = self.dirtyreason(ignoreupdate=ignoreupdate, - missing=True) + dirtyreason = self.dirtyreason(ignoreupdate=ignoreupdate, missing=True) if dirtyreason: raise error.Abort(dirtyreason, hint=hint) @@ -338,15 +370,17 @@ files = self.files() total = len(files) relpath = subrelpath(self) - progress = self.ui.makeprogress(_('archiving (%s)') % relpath, - unit=_('files'), total=total) + progress = self.ui.makeprogress( + _('archiving (%s)') % relpath, unit=_('files'), total=total + ) progress.update(0) for name in files: flags = self.fileflags(name) mode = 'x' in flags and 0o755 or 0o644 symlink = 'l' in flags - archiver.addfile(prefix + name, mode, symlink, - self.filedata(name, decode)) + archiver.addfile( + prefix + name, mode, symlink, self.filedata(name, decode) + ) progress.increment() progress.complete() return total @@ -360,19 +394,31 @@ def forget(self, match, prefix, uipathfn, dryrun, interactive): return ([], []) - def removefiles(self, matcher, prefix, uipathfn, after, force, subrepos, - dryrun, warnings): + def removefiles( + self, + matcher, + prefix, + uipathfn, + after, + force, + subrepos, + dryrun, + warnings, + ): """remove the matched files from the subrepository and the filesystem, possibly by force and/or after the file has been removed from the filesystem. Return 0 on success, 1 on any warning. """ - warnings.append(_("warning: removefiles not implemented (%s)") - % self._path) + warnings.append( + _("warning: removefiles not implemented (%s)") % self._path + ) return 1 def revert(self, substate, *pats, **opts): - self.ui.warn(_('%s: reverting %s subrepos is unsupported\n') - % (substate[0], substate[2])) + self.ui.warn( + _('%s: reverting %s subrepos is unsupported\n') + % (substate[0], substate[2]) + ) return [] def shortid(self, revid): @@ -401,6 +447,7 @@ """ return self.wvfs.reljoin(reporelpath(self._ctx.repo()), self._path) + class hgsubrepo(abstractsubrepo): def __init__(self, ctx, path, state, allowcreate): super(hgsubrepo, self).__init__(ctx, path) @@ -411,13 +458,15 @@ # repository constructor does expand variables in path, which is # unsafe since subrepo path might come from untrusted source. if os.path.realpath(util.expandpath(root)) != root: - raise error.Abort(_('subrepo path contains illegal component: %s') - % path) + raise error.Abort( + _('subrepo path contains illegal component: %s') % path + ) self._repo = hg.repository(r.baseui, root, create=create) if self._repo.root != root: - raise error.ProgrammingError('failed to reject unsafe subrepo ' - 'path: %s (expanded to %s)' - % (root, self._repo.root)) + raise error.ProgrammingError( + 'failed to reject unsafe subrepo ' + 'path: %s (expanded to %s)' % (root, self._repo.root) + ) # Propagate the parent's --hidden option if r is r.unfiltered(): @@ -519,8 +568,9 @@ @annotatesubrepoerror def add(self, ui, match, prefix, uipathfn, explicitonly, **opts): - return cmdutil.add(ui, self._repo, match, prefix, uipathfn, - explicitonly, **opts) + return cmdutil.add( + ui, self._repo, match, prefix, uipathfn, explicitonly, **opts + ) @annotatesubrepoerror def addremove(self, m, prefix, uipathfn, opts): @@ -535,8 +585,9 @@ def cat(self, match, fm, fntemplate, prefix, **opts): rev = self._state[1] ctx = self._repo[rev] - return cmdutil.cat(self.ui, self._repo, ctx, match, fm, fntemplate, - prefix, **opts) + return cmdutil.cat( + self.ui, self._repo, ctx, match, fm, fntemplate, prefix, **opts + ) @annotatesubrepoerror def status(self, rev2, **opts): @@ -546,8 +597,10 @@ ctx2 = self._repo[rev2] return self._repo.status(ctx1, ctx2, **opts) except error.RepoLookupError as inst: - self.ui.warn(_('warning: error "%s" in subrepository "%s"\n') - % (inst, subrelpath(self))) + self.ui.warn( + _('warning: error "%s" in subrepository "%s"\n') + % (inst, subrelpath(self)) + ) return scmutil.status([], [], [], [], [], [], []) @annotatesubrepoerror @@ -558,12 +611,22 @@ # in hex format if node2 is not None: node2 = node.bin(node2) - logcmdutil.diffordiffstat(ui, self._repo, diffopts, node1, node2, - match, prefix=prefix, listsubrepos=True, - **opts) + logcmdutil.diffordiffstat( + ui, + self._repo, + diffopts, + node1, + node2, + match, + prefix=prefix, + listsubrepos=True, + **opts + ) except error.RepoLookupError as inst: - self.ui.warn(_('warning: error "%s" in subrepository "%s"\n') - % (inst, subrelpath(self))) + self.ui.warn( + _('warning: error "%s" in subrepository "%s"\n') + % (inst, subrelpath(self)) + ) @annotatesubrepoerror def archive(self, archiver, prefix, match=None, decode=True): @@ -573,27 +636,27 @@ files = [f for f in files if match(f)] rev = self._state[1] ctx = self._repo[rev] - scmutil.prefetchfiles(self._repo, [ctx.rev()], - scmutil.matchfiles(self._repo, files)) + scmutil.prefetchfiles( + self._repo, [ctx.rev()], scmutil.matchfiles(self._repo, files) + ) total = abstractsubrepo.archive(self, archiver, prefix, match) for subpath in ctx.substate: s = subrepo(ctx, subpath, True) submatch = matchmod.subdirmatcher(subpath, match) subprefix = prefix + subpath + '/' - total += s.archive(archiver, subprefix, submatch, - decode) + total += s.archive(archiver, subprefix, submatch, decode) return total @annotatesubrepoerror def dirty(self, ignoreupdate=False, missing=False): r = self._state[1] - if r == '' and not ignoreupdate: # no state recorded + if r == '' and not ignoreupdate: # no state recorded return True w = self._repo[None] if r != w.p1().hex() and not ignoreupdate: # different version checked out return True - return w.dirty(missing=missing) # working directory changed + return w.dirty(missing=missing) # working directory changed def basestate(self): return self._repo['.'].hex() @@ -610,7 +673,7 @@ self.ui.debug("committing subrepo %s\n" % subrelpath(self)) n = self._repo.commit(text, user, date) if not n: - return self._repo['.'].hex() # different version checked out + return self._repo['.'].hex() # different version checked out return node.hex(n) @annotatesubrepoerror @@ -649,11 +712,17 @@ # A simpler option is for the user to configure clone pooling, and # work with that. if parentrepo.shared() and hg.islocal(srcurl): - self.ui.status(_('sharing subrepo %s from %s\n') - % (subrelpath(self), srcurl)) - shared = hg.share(self._repo._subparent.baseui, - getpeer(), self._repo.root, - update=False, bookmarks=False) + self.ui.status( + _('sharing subrepo %s from %s\n') + % (subrelpath(self), srcurl) + ) + shared = hg.share( + self._repo._subparent.baseui, + getpeer(), + self._repo.root, + update=False, + bookmarks=False, + ) self._repo = shared.local() else: # TODO: find a common place for this and this code in the @@ -670,17 +739,26 @@ else: shareopts = {} - self.ui.status(_('cloning subrepo %s from %s\n') - % (subrelpath(self), util.hidepassword(srcurl))) - other, cloned = hg.clone(self._repo._subparent.baseui, {}, - getpeer(), self._repo.root, - update=False, shareopts=shareopts) + self.ui.status( + _('cloning subrepo %s from %s\n') + % (subrelpath(self), util.hidepassword(srcurl)) + ) + other, cloned = hg.clone( + self._repo._subparent.baseui, + {}, + getpeer(), + self._repo.root, + update=False, + shareopts=shareopts, + ) self._repo = cloned.local() self._initrepo(parentrepo, source, create=True) self._cachestorehash(srcurl) else: - self.ui.status(_('pulling subrepo %s from %s\n') - % (subrelpath(self), util.hidepassword(srcurl))) + self.ui.status( + _('pulling subrepo %s from %s\n') + % (subrelpath(self), util.hidepassword(srcurl)) + ) cleansub = self.storeclean(srcurl) exchange.pull(self._repo, getpeer()) if cleansub: @@ -700,7 +778,8 @@ if ctx.hidden(): urepo.ui.warn( _('revision %s in subrepository "%s" is hidden\n') - % (revision[0:12], self._path)) + % (revision[0:12], self._path) + ) repo = urepo hg.updaterepo(repo, revision, overwrite) @@ -713,12 +792,14 @@ def mergefunc(): if anc == cur and dst.branch() == cur.branch(): - self.ui.debug('updating subrepository "%s"\n' - % subrelpath(self)) + self.ui.debug( + 'updating subrepository "%s"\n' % subrelpath(self) + ) hg.update(self._repo, state[1]) elif anc == dst: - self.ui.debug('skipping subrepository "%s"\n' - % subrelpath(self)) + self.ui.debug( + 'skipping subrepository "%s"\n' % subrelpath(self) + ) else: self.ui.debug('merging subrepository "%s"\n' % subrelpath(self)) hg.merge(self._repo, state[1], remind=False) @@ -741,7 +822,7 @@ # push subrepos depth-first for coherent ordering c = self._repo['.'] - subs = c.substate # only repos that are committed + subs = c.substate # only repos that are committed for s in sorted(subs): if c.sub(s).push(opts) == 0: return False @@ -751,10 +832,13 @@ if self.storeclean(dsturl): self.ui.status( _('no changes made to subrepo %s since last push to %s\n') - % (subrelpath(self), util.hidepassword(dsturl))) + % (subrelpath(self), util.hidepassword(dsturl)) + ) return None - self.ui.status(_('pushing subrepo %s to %s\n') % - (subrelpath(self), util.hidepassword(dsturl))) + self.ui.status( + _('pushing subrepo %s to %s\n') + % (subrelpath(self), util.hidepassword(dsturl)) + ) other = hg.peer(self._repo, {'ssh': ssh}, dsturl) res = exchange.push(self._repo, other, force, newbranch=newbranch) @@ -825,8 +909,10 @@ pm = matchmod.prefixdirmatcher(subpath, sm, badfn=badfn) matchers.append(pm) except error.LookupError: - self.ui.status(_("skipping missing subrepository: %s\n") - % self.wvfs.reljoin(reporelpath(self), subpath)) + self.ui.status( + _("skipping missing subrepository: %s\n") + % self.wvfs.reljoin(reporelpath(self), subpath) + ) if len(matchers) == 1: return matchers[0] return matchmod.unionmatcher(matchers) @@ -837,14 +923,40 @@ @annotatesubrepoerror def forget(self, match, prefix, uipathfn, dryrun, interactive): - return cmdutil.forget(self.ui, self._repo, match, prefix, uipathfn, - True, dryrun=dryrun, interactive=interactive) + return cmdutil.forget( + self.ui, + self._repo, + match, + prefix, + uipathfn, + True, + dryrun=dryrun, + interactive=interactive, + ) @annotatesubrepoerror - def removefiles(self, matcher, prefix, uipathfn, after, force, subrepos, - dryrun, warnings): - return cmdutil.remove(self.ui, self._repo, matcher, prefix, uipathfn, - after, force, subrepos, dryrun) + def removefiles( + self, + matcher, + prefix, + uipathfn, + after, + force, + subrepos, + dryrun, + warnings, + ): + return cmdutil.remove( + self.ui, + self._repo, + matcher, + prefix, + uipathfn, + after, + force, + subrepos, + dryrun, + ) @annotatesubrepoerror def revert(self, substate, *pats, **opts): @@ -888,6 +1000,7 @@ # scripts that don't use our demand-loading global hg from . import hg as h + hg = h # Nothing prevents a user from sharing in a repo, and then making that a @@ -906,14 +1019,18 @@ # Since hidden revisions aren't pushed/pulled, it seems worth an # explicit warning. ui = self._repo.ui - ui.warn(_("subrepo '%s' is hidden in revision %s\n") % - (self._relpath, node.short(self._ctx.node()))) + ui.warn( + _("subrepo '%s' is hidden in revision %s\n") + % (self._relpath, node.short(self._ctx.node())) + ) return 0 except error.RepoLookupError: # A missing subrepo revision may be a case of needing to pull it, so # don't treat this as an error. - self._repo.ui.warn(_("subrepo '%s' not found in revision %s\n") % - (self._relpath, node.short(self._ctx.node()))) + self._repo.ui.warn( + _("subrepo '%s' not found in revision %s\n") + % (self._relpath, node.short(self._ctx.node())) + ) return 0 @propertycache @@ -929,14 +1046,16 @@ # Keep consistent dir separators by avoiding vfs.join(self._path) return reporelpath(self._repo) + class svnsubrepo(abstractsubrepo): def __init__(self, ctx, path, state, allowcreate): super(svnsubrepo, self).__init__(ctx, path) self._state = state self._exe = procutil.findexe('svn') if not self._exe: - raise error.Abort(_("'svn' executable not found for subrepo '%s'") - % self._path) + raise error.Abort( + _("'svn' executable not found for subrepo '%s'") % self._path + ) def _svncommand(self, commands, filename='', failok=False): cmd = [self._exe] @@ -953,8 +1072,9 @@ cmd.append('--non-interactive') cmd.extend(commands) if filename is not None: - path = self.wvfs.reljoin(self._ctx.repo().origroot, - self._path, filename) + path = self.wvfs.reljoin( + self._ctx.repo().origroot, self._path, filename + ) cmd.append(path) env = dict(encoding.environ) # Avoid localized output, preserve current locale for everything else. @@ -963,16 +1083,22 @@ env['LANG'] = lc_all del env['LC_ALL'] env['LC_MESSAGES'] = 'C' - p = subprocess.Popen(pycompat.rapply(procutil.tonativestr, cmd), - bufsize=-1, close_fds=procutil.closefds, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - env=procutil.tonativeenv(env), **extrakw) + p = subprocess.Popen( + pycompat.rapply(procutil.tonativestr, cmd), + bufsize=-1, + close_fds=procutil.closefds, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=procutil.tonativeenv(env), + **extrakw + ) stdout, stderr = map(util.fromnativeeol, p.communicate()) stderr = stderr.strip() if not failok: if p.returncode: - raise error.Abort(stderr or 'exited with code %d' - % p.returncode) + raise error.Abort( + stderr or 'exited with code %d' % p.returncode + ) if stderr: self.ui.warn(stderr + '\n') return stdout, stderr @@ -1000,8 +1126,10 @@ rev = pycompat.bytestr(entries[0].getAttribute(r'revision')) or '0' commits = entries[0].getElementsByTagName(r'commit') if commits: - lastrev = pycompat.bytestr( - commits[0].getAttribute(r'revision')) or '0' + lastrev = ( + pycompat.bytestr(commits[0].getAttribute(r'revision')) + or '0' + ) return (lastrev, rev) def _wcrev(self): @@ -1027,8 +1155,12 @@ externals.append(path) elif item == r'missing': missing.append(path) - if (item not in (r'', r'normal', r'unversioned', r'external') - or props not in (r'', r'none', r'normal')): + if item not in ( + r'', + r'normal', + r'unversioned', + r'external', + ) or props not in (r'', r'none', r'normal'): changes.append(path) for path in changes: for ext in externals: @@ -1092,8 +1224,10 @@ @annotatesubrepoerror def remove(self): if self.dirty(): - self.ui.warn(_('not removing repo %s because ' - 'it has changes.\n') % self._path) + self.ui.warn( + _('not removing repo %s because ' 'it has changes.\n') + % self._path + ) return self.ui.note(_('removing subrepo %s\n') % self._path) @@ -1121,8 +1255,9 @@ status, err = self._svncommand(args, failok=True) _sanitize(self.ui, self.wvfs, '.svn') if not re.search('Checked out revision [0-9]+.', status): - if ('is already a working copy for a different URL' in err - and (self._wcchanged()[:2] == (False, False))): + if 'is already a working copy for a different URL' in err and ( + self._wcchanged()[:2] == (False, False) + ): # obstructed but clean working copy, so just blow it away. self.remove() self.get(state, overwrite=False) @@ -1153,9 +1288,11 @@ kind = pycompat.bytestr(e.getAttribute(r'kind')) if kind != 'file': continue - name = r''.join(c.data for c - in e.getElementsByTagName(r'name')[0].childNodes - if c.nodeType == c.TEXT_NODE) + name = r''.join( + c.data + for c in e.getElementsByTagName(r'name')[0].childNodes + if c.nodeType == c.TEXT_NODE + ) paths.append(name.encode('utf8')) return paths @@ -1179,23 +1316,33 @@ genericerror = _("error executing git for subrepo '%s': %s") notfoundhint = _("check git is installed and in your PATH") if e.errno != errno.ENOENT: - raise error.Abort(genericerror % ( - self._path, encoding.strtolocal(e.strerror))) + raise error.Abort( + genericerror % (self._path, encoding.strtolocal(e.strerror)) + ) elif pycompat.iswindows: try: self._gitexecutable = 'git.cmd' out, err = self._gitnodir(['--version']) except OSError as e2: if e2.errno == errno.ENOENT: - raise error.Abort(_("couldn't find 'git' or 'git.cmd'" - " for subrepo '%s'") % self._path, - hint=notfoundhint) + raise error.Abort( + _( + "couldn't find 'git' or 'git.cmd'" + " for subrepo '%s'" + ) + % self._path, + hint=notfoundhint, + ) else: - raise error.Abort(genericerror % (self._path, - encoding.strtolocal(e2.strerror))) + raise error.Abort( + genericerror + % (self._path, encoding.strtolocal(e2.strerror)) + ) else: - raise error.Abort(_("couldn't find git for subrepo '%s'") - % self._path, hint=notfoundhint) + raise error.Abort( + _("couldn't find git for subrepo '%s'") % self._path, + hint=notfoundhint, + ) versionstatus = self._checkversion(out) if versionstatus == 'unknown': self.ui.warn(_('cannot retrieve git version\n')) @@ -1256,8 +1403,9 @@ return self._gitdir(commands, env=env, stream=stream)[0] def _gitdir(self, commands, env=None, stream=False): - return self._gitnodir(commands, env=env, stream=stream, - cwd=self._abspath) + return self._gitnodir( + commands, env=env, stream=stream, cwd=self._abspath + ) def _gitnodir(self, commands, env=None, stream=False, cwd=None): """Calls the git command @@ -1282,13 +1430,17 @@ # insert the argument in the front, # the end of git diff arguments is used for paths commands.insert(1, '--color') - p = subprocess.Popen(pycompat.rapply(procutil.tonativestr, - [self._gitexecutable] + commands), - bufsize=-1, - cwd=pycompat.rapply(procutil.tonativestr, cwd), - env=procutil.tonativeenv(env), - close_fds=procutil.closefds, - stdout=subprocess.PIPE, stderr=errpipe) + p = subprocess.Popen( + pycompat.rapply( + procutil.tonativestr, [self._gitexecutable] + commands + ), + bufsize=-1, + cwd=pycompat.rapply(procutil.tonativestr, cwd), + env=procutil.tonativeenv(env), + close_fds=procutil.closefds, + stdout=subprocess.PIPE, + stderr=errpipe, + ) if stream: return p.stdout, None @@ -1302,8 +1454,10 @@ if command in ('cat-file', 'symbolic-ref'): return retdata, p.returncode # for all others, abort - raise error.Abort(_('git %s error %d in %s') % - (command, p.returncode, self._relpath)) + raise error.Abort( + _('git %s error %d in %s') + % (command, p.returncode, self._relpath) + ) return retdata, p.returncode @@ -1349,15 +1503,17 @@ branch2rev = {} rev2branch = {} - out = self._gitcommand(['for-each-ref', '--format', - '%(objectname) %(refname)']) + out = self._gitcommand( + ['for-each-ref', '--format', '%(objectname) %(refname)'] + ) for line in out.split('\n'): revision, ref = line.split(' ') - if (not ref.startswith('refs/heads/') and - not ref.startswith('refs/remotes/')): + if not ref.startswith('refs/heads/') and not ref.startswith( + 'refs/remotes/' + ): continue if ref.startswith('refs/remotes/') and ref.endswith('/HEAD'): - continue # ignore remote/HEAD redirects + continue # ignore remote/HEAD redirects branch2rev[ref] = revision rev2branch.setdefault(revision, []).append(ref) return branch2rev, rev2branch @@ -1373,8 +1529,9 @@ remote = self._gitcommand(['config', 'branch.%s.remote' % bname]) if remote: ref = self._gitcommand(['config', 'branch.%s.merge' % bname]) - tracking['refs/remotes/%s/%s' % - (remote, ref.split('/', 2)[2])] = b + tracking[ + 'refs/remotes/%s/%s' % (remote, ref.split('/', 2)[2]) + ] = b return tracking def _abssource(self, source): @@ -1392,18 +1549,23 @@ util.checksafessh(source) source = self._abssource(source) - self.ui.status(_('cloning subrepo %s from %s\n') % - (self._relpath, source)) + self.ui.status( + _('cloning subrepo %s from %s\n') % (self._relpath, source) + ) self._gitnodir(['clone', source, self._abspath]) if self._githavelocally(revision): return - self.ui.status(_('pulling subrepo %s from %s\n') % - (self._relpath, self._gitremote('origin'))) + self.ui.status( + _('pulling subrepo %s from %s\n') + % (self._relpath, self._gitremote('origin')) + ) # try only origin: the originally cloned repo self._gitcommand(['fetch']) if not self._githavelocally(revision): - raise error.Abort(_('revision %s does not exist in subrepository ' - '"%s"\n') % (revision, self._relpath)) + raise error.Abort( + _('revision %s does not exist in subrepository ' '"%s"\n') + % (revision, self._relpath) + ) @annotatesubrepoerror def dirty(self, ignoreupdate=False, missing=False): @@ -1458,10 +1620,13 @@ def rawcheckout(): # no branch to checkout, check it out with no branch - self.ui.warn(_('checking out detached HEAD in ' - 'subrepository "%s"\n') % self._relpath) - self.ui.warn(_('check out a git branch if you intend ' - 'to make changes\n')) + self.ui.warn( + _('checking out detached HEAD in ' 'subrepository "%s"\n') + % self._relpath + ) + self.ui.warn( + _('check out a git branch if you intend ' 'to make changes\n') + ) checkout(['-q', revision]) if revision not in rev2branch: @@ -1519,8 +1684,9 @@ if date: # git's date parser silently ignores when seconds < 1e9 # convert to ISO8601 - env['GIT_AUTHOR_DATE'] = dateutil.datestr(date, - '%Y-%m-%dT%H:%M:%S %1%2') + env['GIT_AUTHOR_DATE'] = dateutil.datestr( + date, '%Y-%m-%dT%H:%M:%S %1%2' + ) self._gitcommand(cmd, env=env) # make sure commit works otherwise HEAD might not exist under certain # circumstances @@ -1536,7 +1702,7 @@ def mergefunc(): if base == revision: - self.get(state) # fast forward merge + self.get(state) # fast forward merge elif base != self._state[1]: self._gitcommand(['merge', '--no-commit', revision]) _sanitize(self.ui, self.wvfs, '.git') @@ -1544,8 +1710,9 @@ if self.dirty(): if self._gitstate() != revision: dirty = self._gitstate() == self._state[1] or code != 0 - if _updateprompt(self.ui, self, dirty, - self._state[1][:7], revision[:7]): + if _updateprompt( + self.ui, self, dirty, self._state[1][:7], revision[:7] + ): mergefunc() else: mergefunc() @@ -1577,17 +1744,28 @@ if current: # determine if the current branch is even useful if not self._gitisancestor(self._state[1], current): - self.ui.warn(_('unrelated git branch checked out ' - 'in subrepository "%s"\n') % self._relpath) + self.ui.warn( + _( + 'unrelated git branch checked out ' + 'in subrepository "%s"\n' + ) + % self._relpath + ) return False - self.ui.status(_('pushing branch %s of subrepository "%s"\n') % - (current.split('/', 2)[2], self._relpath)) + self.ui.status( + _('pushing branch %s of subrepository "%s"\n') + % (current.split('/', 2)[2], self._relpath) + ) ret = self._gitdir(cmd + ['origin', current]) return ret[1] == 0 else: - self.ui.warn(_('no branch checked out in subrepository "%s"\n' - 'cannot push revision %s\n') % - (self._relpath, self._state[1])) + self.ui.warn( + _( + 'no branch checked out in subrepository "%s"\n' + 'cannot push revision %s\n' + ) + % (self._relpath, self._state[1]) + ) return False @annotatesubrepoerror @@ -1613,7 +1791,7 @@ exact = match.exact(f) command = ["add"] if exact: - command.append("-f") #should be added, even if ignored + command.append("-f") # should be added, even if ignored if ui.verbose or not exact: ui.status(_('adding %s\n') % uipathfn(f)) @@ -1634,8 +1812,10 @@ if self._gitmissing(): return if self.dirty(): - self.ui.warn(_('not removing repo %s because ' - 'it has changes.\n') % self._relpath) + self.ui.warn( + _('not removing repo %s because ' 'it has changes.\n') + % self._relpath + ) return # we can't fully delete the repository as it may contain # local-only history @@ -1662,8 +1842,9 @@ tarstream = self._gitcommand(['archive', revision], stream=True) tar = tarfile.open(fileobj=tarstream, mode=r'r|') relpath = subrelpath(self) - progress = self.ui.makeprogress(_('archiving (%s)') % relpath, - unit=_('files')) + progress = self.ui.makeprogress( + _('archiving (%s)') % relpath, unit=_('files') + ) progress.update(0) for info in tar: if info.isdir(): @@ -1681,12 +1862,11 @@ progress.complete() return total - @annotatesubrepoerror def cat(self, match, fm, fntemplate, prefix, **opts): rev = self._state[1] if match.anypats(): - return 1 #No support for include/exclude yet + return 1 # No support for include/exclude yet if not match.files(): return 1 @@ -1694,13 +1874,13 @@ # TODO: add support for non-plain formatter (see cmdutil.cat()) for f in match.files(): output = self._gitcommand(["show", "%s:%s" % (rev, f)]) - fp = cmdutil.makefileobj(self._ctx, fntemplate, - pathname=self.wvfs.reljoin(prefix, f)) + fp = cmdutil.makefileobj( + self._ctx, fntemplate, pathname=self.wvfs.reljoin(prefix, f) + ) fp.write(output) fp.close() return 0 - @annotatesubrepoerror def status(self, rev2, **opts): rev1 = self._state[1] @@ -1718,7 +1898,7 @@ tab = line.find('\t') if tab == -1: continue - status, f = line[tab - 1:tab], line[tab + 1:] + status, f = line[tab - 1 : tab], line[tab + 1 :] if status == 'M': modified.append(f) elif status == 'A': @@ -1743,7 +1923,7 @@ if not line: continue st = line[0:2] - #moves and copies show 2 files on one line + # moves and copies show 2 files on one line if line.find('\0') >= 0: filename1, filename2 = line[3:].split('\0') else: @@ -1765,8 +1945,9 @@ if not f in changedfiles: clean.append(f) - return scmutil.status(modified, added, removed, deleted, - unknown, ignored, clean) + return scmutil.status( + modified, added, removed, deleted, unknown, ignored, clean + ) @annotatesubrepoerror def diff(self, ui, diffopts, node2, match, prefix, **opts): @@ -1779,18 +1960,22 @@ cmd.append('-U%d' % diffopts.context) if diffopts.noprefix: - cmd.extend(['--src-prefix=%s/' % prefix, - '--dst-prefix=%s/' % prefix]) + cmd.extend( + ['--src-prefix=%s/' % prefix, '--dst-prefix=%s/' % prefix] + ) else: - cmd.extend(['--src-prefix=a/%s/' % prefix, - '--dst-prefix=b/%s/' % prefix]) + cmd.extend( + ['--src-prefix=a/%s/' % prefix, '--dst-prefix=b/%s/' % prefix] + ) if diffopts.ignorews: cmd.append('--ignore-all-space') if diffopts.ignorewsamount: cmd.append('--ignore-space-change') - if (self._gitversion(self._gitcommand(['--version'])) >= (1, 8, 4) - and diffopts.ignoreblanklines): + if ( + self._gitversion(self._gitcommand(['--version'])) >= (1, 8, 4) + and diffopts.ignoreblanklines + ): cmd.append('--ignore-blank-lines') cmd.append(node1) @@ -1820,10 +2005,13 @@ # backuppath() expects a path relative to the parent repo (the # repo that ui.origbackuppath is relative to) parentname = os.path.join(self._path, name) - bakname = scmutil.backuppath(self.ui, self._subparent, - parentname) - self.ui.note(_('saving current version of %s as %s\n') % - (name, os.path.relpath(bakname))) + bakname = scmutil.backuppath( + self.ui, self._subparent, parentname + ) + self.ui.note( + _('saving current version of %s as %s\n') + % (name, os.path.relpath(bakname)) + ) util.rename(self.wvfs.join(name), bakname) if not opts.get(r'dry_run'): @@ -1833,8 +2021,9 @@ def shortid(self, revid): return revid[:7] + types = { 'hg': hgsubrepo, 'svn': svnsubrepo, 'git': gitsubrepo, - } +}