--- a/mercurial/cmdutil.py Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/cmdutil.py Sun Oct 06 09:45:02 2019 -0400
@@ -61,69 +61,81 @@
# templates of common command options
dryrunopts = [
- ('n', 'dry-run', None,
- _('do not perform actions, just print output')),
+ ('n', 'dry-run', None, _('do not perform actions, just print output')),
]
confirmopts = [
- ('', 'confirm', None,
- _('ask before applying actions')),
+ ('', 'confirm', None, _('ask before applying actions')),
]
remoteopts = [
- ('e', 'ssh', '',
- _('specify ssh command to use'), _('CMD')),
- ('', 'remotecmd', '',
- _('specify hg command to run on the remote side'), _('CMD')),
- ('', 'insecure', None,
- _('do not verify server certificate (ignoring web.cacerts config)')),
+ ('e', 'ssh', '', _('specify ssh command to use'), _('CMD')),
+ (
+ '',
+ 'remotecmd',
+ '',
+ _('specify hg command to run on the remote side'),
+ _('CMD'),
+ ),
+ (
+ '',
+ 'insecure',
+ None,
+ _('do not verify server certificate (ignoring web.cacerts config)'),
+ ),
]
walkopts = [
- ('I', 'include', [],
- _('include names matching the given patterns'), _('PATTERN')),
- ('X', 'exclude', [],
- _('exclude names matching the given patterns'), _('PATTERN')),
+ (
+ 'I',
+ 'include',
+ [],
+ _('include names matching the given patterns'),
+ _('PATTERN'),
+ ),
+ (
+ 'X',
+ 'exclude',
+ [],
+ _('exclude names matching the given patterns'),
+ _('PATTERN'),
+ ),
]
commitopts = [
- ('m', 'message', '',
- _('use text as commit message'), _('TEXT')),
- ('l', 'logfile', '',
- _('read commit message from file'), _('FILE')),
+ ('m', 'message', '', _('use text as commit message'), _('TEXT')),
+ ('l', 'logfile', '', _('read commit message from file'), _('FILE')),
]
commitopts2 = [
- ('d', 'date', '',
- _('record the specified date as commit date'), _('DATE')),
- ('u', 'user', '',
- _('record the specified user as committer'), _('USER')),
+ ('d', 'date', '', _('record the specified date as commit date'), _('DATE')),
+ ('u', 'user', '', _('record the specified user as committer'), _('USER')),
]
commitopts3 = [
- (b'D', b'currentdate', None,
- _(b'record the current date as commit date')),
- (b'U', b'currentuser', None,
- _(b'record the current user as committer')),
+ (b'D', b'currentdate', None, _(b'record the current date as commit date')),
+ (b'U', b'currentuser', None, _(b'record the current user as committer')),
]
formatteropts = [
- ('T', 'template', '',
- _('display with template'), _('TEMPLATE')),
+ ('T', 'template', '', _('display with template'), _('TEMPLATE')),
]
templateopts = [
- ('', 'style', '',
- _('display using template map file (DEPRECATED)'), _('STYLE')),
- ('T', 'template', '',
- _('display with template'), _('TEMPLATE')),
+ (
+ '',
+ 'style',
+ '',
+ _('display using template map file (DEPRECATED)'),
+ _('STYLE'),
+ ),
+ ('T', 'template', '', _('display with template'), _('TEMPLATE')),
]
logopts = [
('p', 'patch', None, _('show patch')),
('g', 'git', None, _('use git extended diff format')),
- ('l', 'limit', '',
- _('limit number of changes displayed'), _('NUM')),
+ ('l', 'limit', '', _('limit number of changes displayed'), _('NUM')),
('M', 'no-merges', None, _('do not show merges')),
('', 'stat', None, _('output diffstat-style summary of changes')),
('G', 'graph', None, _("show the revision DAG")),
@@ -133,44 +145,70 @@
('a', 'text', None, _('treat all files as text')),
('g', 'git', None, _('use git extended diff format')),
('', 'binary', None, _('generate binary diffs in git mode (default)')),
- ('', 'nodates', None, _('omit dates from diff headers'))
+ ('', 'nodates', None, _('omit dates from diff headers')),
]
diffwsopts = [
- ('w', 'ignore-all-space', None,
- _('ignore white space when comparing lines')),
- ('b', 'ignore-space-change', None,
- _('ignore changes in the amount of white space')),
- ('B', 'ignore-blank-lines', None,
- _('ignore changes whose lines are all blank')),
- ('Z', 'ignore-space-at-eol', None,
- _('ignore changes in whitespace at EOL')),
+ (
+ 'w',
+ 'ignore-all-space',
+ None,
+ _('ignore white space when comparing lines'),
+ ),
+ (
+ 'b',
+ 'ignore-space-change',
+ None,
+ _('ignore changes in the amount of white space'),
+ ),
+ (
+ 'B',
+ 'ignore-blank-lines',
+ None,
+ _('ignore changes whose lines are all blank'),
+ ),
+ (
+ 'Z',
+ 'ignore-space-at-eol',
+ None,
+ _('ignore changes in whitespace at EOL'),
+ ),
]
-diffopts2 = [
- ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
- ('p', 'show-function', None, _('show which function each change is in')),
- ('', 'reverse', None, _('produce a diff that undoes the changes')),
-] + diffwsopts + [
- ('U', 'unified', '',
- _('number of lines of context to show'), _('NUM')),
- ('', 'stat', None, _('output diffstat-style summary of changes')),
- ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
-]
+diffopts2 = (
+ [
+ ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
+ (
+ 'p',
+ 'show-function',
+ None,
+ _('show which function each change is in'),
+ ),
+ ('', 'reverse', None, _('produce a diff that undoes the changes')),
+ ]
+ + diffwsopts
+ + [
+ ('U', 'unified', '', _('number of lines of context to show'), _('NUM')),
+ ('', 'stat', None, _('output diffstat-style summary of changes')),
+ ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
+ ]
+)
mergetoolopts = [
('t', 'tool', '', _('specify merge tool'), _('TOOL')),
]
similarityopts = [
- ('s', 'similarity', '',
- _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
+ (
+ 's',
+ 'similarity',
+ '',
+ _('guess renamed files by similarity (0<=s<=100)'),
+ _('SIMILARITY'),
+ )
]
-subrepoopts = [
- ('S', 'subrepos', None,
- _('recurse into subrepositories'))
-]
+subrepoopts = [('S', 'subrepos', None, _('recurse into subrepositories'))]
debugrevlogopts = [
('c', 'changelog', False, _('open changelog')),
@@ -182,6 +220,7 @@
# editor text
_linebelow = "^HG: ------------------------ >8 ------------------------$"
+
def resolvecommitoptions(ui, opts):
"""modify commit options dict to handle related options
@@ -189,19 +228,23 @@
the ``date`` option is set.
"""
if opts.get('date') and opts.get('currentdate'):
- raise error.Abort(_('--date and --currentdate are mutually '
- 'exclusive'))
+ raise error.Abort(
+ _('--date and --currentdate are mutually ' 'exclusive')
+ )
if opts.get(b'user') and opts.get(b'currentuser'):
- raise error.Abort(_('--user and --currentuser are mutually '
- 'exclusive'))
+ raise error.Abort(
+ _('--user and --currentuser are mutually ' 'exclusive')
+ )
datemaydiffer = False # date-only change should be ignored?
if opts.get(b'currentdate'):
opts[b'date'] = b'%d %d' % dateutil.makedate()
- elif (not opts.get('date')
- and ui.configbool('rewrite', 'update-timestamp')
- and opts.get('currentdate') is None):
+ elif (
+ not opts.get('date')
+ and ui.configbool('rewrite', 'update-timestamp')
+ and opts.get('currentdate') is None
+ ):
opts[b'date'] = b'%d %d' % dateutil.makedate()
datemaydiffer = True
@@ -210,6 +253,7 @@
return datemaydiffer
+
def checknotesize(ui, opts):
""" make sure note is of valid format """
@@ -222,24 +266,32 @@
if b'\n' in note:
raise error.Abort(_(b"note cannot contain a newline"))
+
def ishunk(x):
hunkclasses = (crecordmod.uihunk, patch.recordhunk)
return isinstance(x, hunkclasses)
+
def newandmodified(chunks, originalchunks):
newlyaddedandmodifiedfiles = set()
alsorestore = set()
for chunk in chunks:
- if (ishunk(chunk) and chunk.header.isnewfile() and chunk not in
- originalchunks):
+ if (
+ ishunk(chunk)
+ and chunk.header.isnewfile()
+ and chunk not in originalchunks
+ ):
newlyaddedandmodifiedfiles.add(chunk.header.filename())
- alsorestore.update(set(chunk.header.files()) -
- {chunk.header.filename()})
+ alsorestore.update(
+ set(chunk.header.files()) - {chunk.header.filename()}
+ )
return newlyaddedandmodifiedfiles, alsorestore
+
def parsealiases(cmd):
return cmd.split("|")
+
def setupwrapcolorwrite(ui):
# wrap ui.write so diff output can be labeled/colorized
def wrapwrite(orig, *args, **kw):
@@ -248,29 +300,34 @@
orig(chunk, label=label + l)
oldwrite = ui.write
+
def wrap(*args, **kwargs):
return wrapwrite(oldwrite, *args, **kwargs)
+
setattr(ui, 'write', wrap)
return oldwrite
-def filterchunks(ui, originalhunks, usecurses, testfile, match,
- operation=None):
+
+def filterchunks(ui, originalhunks, usecurses, testfile, match, operation=None):
try:
if usecurses:
if testfile:
recordfn = crecordmod.testdecorator(
- testfile, crecordmod.testchunkselector)
+ testfile, crecordmod.testchunkselector
+ )
else:
recordfn = crecordmod.chunkselector
- return crecordmod.filterpatch(ui, originalhunks, recordfn,
- operation)
+ return crecordmod.filterpatch(
+ ui, originalhunks, recordfn, operation
+ )
except crecordmod.fallbackerror as e:
ui.warn('%s\n' % e.message)
ui.warn(_('falling back to text mode\n'))
return patch.filterpatch(ui, originalhunks, match, operation)
+
def recordfilter(ui, originalhunks, match, operation=None):
""" Prompts the user to filter the originalhunks and return a list of
selected hunks.
@@ -282,14 +339,17 @@
testfile = ui.config('experimental', 'crecordtest')
oldwrite = setupwrapcolorwrite(ui)
try:
- newchunks, newopts = filterchunks(ui, originalhunks, usecurses,
- testfile, match, operation)
+ newchunks, newopts = filterchunks(
+ ui, originalhunks, usecurses, testfile, match, operation
+ )
finally:
ui.write = oldwrite
return newchunks, newopts
-def dorecord(ui, repo, commitfunc, cmdsuggest, backupall,
- filterfn, *pats, **opts):
+
+def dorecord(
+ ui, repo, commitfunc, cmdsuggest, backupall, filterfn, *pats, **opts
+):
opts = pycompat.byteskwargs(opts)
if not ui.interactive():
if cmdsuggest:
@@ -300,7 +360,7 @@
# make sure username is set before going interactive
if not opts.get('user'):
- ui.username() # raise exception, username not provided
+ ui.username() # raise exception, username not provided
def recordfunc(ui, repo, message, match, opts):
"""This is generic record driver.
@@ -321,8 +381,12 @@
wctx = repo[None]
merge = len(wctx.parents()) > 1
if merge:
- raise error.Abort(_('cannot partially commit a merge '
- '(use "hg commit" instead)'))
+ raise error.Abort(
+ _(
+ 'cannot partially commit a merge '
+ '(use "hg commit" instead)'
+ )
+ )
def fail(f, msg):
raise error.Abort('%s: %s' % (f, msg))
@@ -339,17 +403,20 @@
with repo.ui.configoverride(overrides, b'record'):
# subrepoutil.precommit() modifies the status
- tmpstatus = scmutil.status(copymod.copy(status[0]),
- copymod.copy(status[1]),
- copymod.copy(status[2]),
- copymod.copy(status[3]),
- copymod.copy(status[4]),
- copymod.copy(status[5]),
- copymod.copy(status[6]))
+ tmpstatus = scmutil.status(
+ copymod.copy(status[0]),
+ copymod.copy(status[1]),
+ copymod.copy(status[2]),
+ copymod.copy(status[3]),
+ copymod.copy(status[4]),
+ copymod.copy(status[5]),
+ copymod.copy(status[6]),
+ )
# Force allows -X subrepo to skip the subrepo.
subs, commitsubs, newstate = subrepoutil.precommit(
- repo.ui, wctx, tmpstatus, match, force=True)
+ repo.ui, wctx, tmpstatus, match, force=True
+ )
for s in subs:
if s in commitsubs:
dirtyreason = wctx.sub(s).dirtyreason(True)
@@ -357,9 +424,13 @@
if not force:
repo.checkcommitpatterns(wctx, vdirs, match, status, fail)
- diffopts = patch.difffeatureopts(ui, opts=opts, whitespace=True,
- section='commands',
- configprefix='commit.interactive.')
+ diffopts = patch.difffeatureopts(
+ ui,
+ opts=opts,
+ whitespace=True,
+ section='commands',
+ configprefix='commit.interactive.',
+ )
diffopts.nodates = True
diffopts.git = True
diffopts.showfunc = True
@@ -379,8 +450,9 @@
# version without the edit in the workdir. We also will need to restore
# files that were the sources of renames so that the patch application
# works.
- newlyaddedandmodifiedfiles, alsorestore = newandmodified(chunks,
- originalchunks)
+ newlyaddedandmodifiedfiles, alsorestore = newandmodified(
+ chunks, originalchunks
+ )
contenders = set()
for h in chunks:
try:
@@ -401,8 +473,11 @@
if backupall:
tobackup = changed
else:
- tobackup = [f for f in newfiles if f in modified or f in
- newlyaddedandmodifiedfiles]
+ tobackup = [
+ f
+ for f in newfiles
+ if f in modified or f in newlyaddedandmodifiedfiles
+ ]
backups = {}
if tobackup:
backupdir = repo.vfs.join('record-backups')
@@ -414,8 +489,9 @@
try:
# backup continues
for f in tobackup:
- fd, tmpname = pycompat.mkstemp(prefix=f.replace('/', '_') + '.',
- dir=backupdir)
+ fd, tmpname = pycompat.mkstemp(
+ prefix=f.replace('/', '_') + '.', dir=backupdir
+ )
os.close(fd)
ui.debug('backup %r as %r\n' % (f, tmpname))
util.copyfile(repo.wjoin(f), tmpname, copystat=True)
@@ -431,12 +507,14 @@
# 2.5 optionally review / modify patch in text editor
if opts.get('review', False):
- patchtext = (crecordmod.diffhelptext
- + crecordmod.patchhelptext
- + fp.read())
- reviewedpatch = ui.edit(patchtext, "",
- action="diff",
- repopath=repo.path)
+ patchtext = (
+ crecordmod.diffhelptext
+ + crecordmod.patchhelptext
+ + fp.read()
+ )
+ reviewedpatch = ui.edit(
+ patchtext, "", action="diff", repopath=repo.path
+ )
fp.truncate(0)
fp.write(reviewedpatch)
fp.seek(0)
@@ -446,8 +524,13 @@
if backups:
# Equivalent to hg.revert
m = scmutil.matchfiles(repo, set(backups.keys()) | alsorestore)
- mergemod.update(repo, repo.dirstate.p1(), branchmerge=False,
- force=True, matcher=m)
+ mergemod.update(
+ repo,
+ repo.dirstate.p1(),
+ branchmerge=False,
+ force=True,
+ matcher=m,
+ )
# 3b. (apply)
if dopatch:
@@ -497,6 +580,7 @@
return commit(ui, repo, recordinwlock, pats, opts)
+
class dirnode(object):
"""
Represent a directory in user working copy with information required for
@@ -592,11 +676,12 @@
for st, fpath in self.iterfilepaths():
yield st, fpath
- #recurse on the subdirs
+ # recurse on the subdirs
for dirobj in self.subdirs.values():
for st, fpath in dirobj.tersewalk(terseargs):
yield st, fpath
+
def tersedir(statuslist, terseargs):
"""
Terse the status if all the files in a directory shares the same status.
@@ -620,8 +705,15 @@
# creating a dirnode object for the root of the repo
rootobj = dirnode('')
- pstatus = ('modified', 'added', 'deleted', 'clean', 'unknown',
- 'ignored', 'removed')
+ pstatus = (
+ 'modified',
+ 'added',
+ 'deleted',
+ 'clean',
+ 'unknown',
+ 'ignored',
+ 'removed',
+ )
tersedict = {}
for attrname in pstatus:
@@ -646,12 +738,14 @@
return tersedlist
+
def _commentlines(raw):
'''Surround lineswith a comment char and a new line'''
lines = raw.splitlines()
commentedlines = ['# %s' % line for line in lines]
return '\n'.join(commentedlines) + '\n'
+
def _conflictsmsg(repo):
mergestate = mergemod.mergestate.read(repo)
if not mergestate.active():
@@ -661,18 +755,27 @@
unresolvedlist = [f for f in mergestate.unresolved() if m(f)]
if unresolvedlist:
mergeliststr = '\n'.join(
- [' %s' % util.pathto(repo.root, encoding.getcwd(), path)
- for path in sorted(unresolvedlist)])
- msg = _('''Unresolved merge conflicts:
+ [
+ ' %s' % util.pathto(repo.root, encoding.getcwd(), path)
+ for path in sorted(unresolvedlist)
+ ]
+ )
+ msg = (
+ _(
+ '''Unresolved merge conflicts:
%s
-To mark files as resolved: hg resolve --mark FILE''') % mergeliststr
+To mark files as resolved: hg resolve --mark FILE'''
+ )
+ % mergeliststr
+ )
else:
msg = _('No unresolved merge conflicts.')
return _commentlines(msg)
+
def morestatus(repo, fm):
statetuple = statemod.getrepostate(repo)
label = 'status.morestatus'
@@ -686,6 +789,7 @@
if helpfulmsg:
fm.plain('%s\n' % _commentlines(helpfulmsg), label=label)
+
def findpossible(cmd, table, strict=False):
"""
Return cmd -> (aliases, command table entry)
@@ -724,6 +828,7 @@
return choice, allcmds
+
def findcmd(cmd, table, strict=True):
"""Return (aliases, command table entry) for command string."""
choice, allcmds = findpossible(cmd, table, strict)
@@ -740,6 +845,7 @@
raise error.UnknownCommand(cmd, allcmds)
+
def changebranch(ui, repo, revs, label):
""" Change the branch name of given revs to label """
@@ -770,6 +876,7 @@
# avoid import cycle mercurial.cmdutil -> mercurial.context ->
# mercurial.subrepo -> mercurial.cmdutil
from . import context
+
for rev in revs:
ctx = repo[rev]
oldbranch = ctx.branch()
@@ -783,8 +890,10 @@
except error.ManifestLookupError:
return None
- ui.debug("changing branch of '%s' from '%s' to '%s'\n"
- % (hex(ctx.node()), oldbranch, label))
+ ui.debug(
+ "changing branch of '%s' from '%s' to '%s'\n"
+ % (hex(ctx.node()), oldbranch, label)
+ )
extra = ctx.extra()
extra['branch_change'] = hex(ctx.node())
# While changing branch of set of linear commits, make sure that
@@ -797,14 +906,17 @@
if p2 in replacements:
p2 = replacements[p2][0]
- mc = context.memctx(repo, (p1, p2),
- ctx.description(),
- ctx.files(),
- filectxfn,
- user=ctx.user(),
- date=ctx.date(),
- extra=extra,
- branch=label)
+ mc = context.memctx(
+ repo,
+ (p1, p2),
+ ctx.description(),
+ ctx.files(),
+ filectxfn,
+ user=ctx.user(),
+ date=ctx.date(),
+ extra=extra,
+ branch=label,
+ )
newnode = repo.commitctx(mc)
replacements[ctx.node()] = (newnode,)
@@ -822,10 +934,12 @@
# avoid import cycle mercurial.cmdutil -> mercurial.hg ->
# mercurial.cmdutil
from . import hg
+
hg.update(repo, newid[0], quietempty=True)
ui.status(_("changed branch on %d changesets\n") % len(replacements))
+
def findrepo(p):
while not os.path.isdir(os.path.join(p, ".hg")):
oldp, p = p, os.path.dirname(p)
@@ -834,6 +948,7 @@
return p
+
def bailifchanged(repo, merge=True, hint=None):
""" enforce the precondition that working directory must be clean.
@@ -852,14 +967,16 @@
for s in sorted(ctx.substate):
ctx.sub(s).bailifchanged(hint=hint)
+
def logmessage(ui, opts):
""" get the log message according to -m and -l option """
message = opts.get('message')
logfile = opts.get('logfile')
if message and logfile:
- raise error.Abort(_('options --message and --logfile are mutually '
- 'exclusive'))
+ raise error.Abort(
+ _('options --message and --logfile are mutually ' 'exclusive')
+ )
if not message and logfile:
try:
if isstdiofilename(logfile):
@@ -867,10 +984,13 @@
else:
message = '\n'.join(util.readfile(logfile).splitlines())
except IOError as inst:
- raise error.Abort(_("can't read commit message '%s': %s") %
- (logfile, encoding.strtolocal(inst.strerror)))
+ raise error.Abort(
+ _("can't read commit message '%s': %s")
+ % (logfile, encoding.strtolocal(inst.strerror))
+ )
return message
+
def mergeeditform(ctxorbool, baseformname):
"""return appropriate editform name (referencing a committemplate)
@@ -888,8 +1008,10 @@
return baseformname + ".normal"
-def getcommiteditor(edit=False, finishdesc=None, extramsg=None,
- editform='', **opts):
+
+def getcommiteditor(
+ edit=False, finishdesc=None, extramsg=None, editform='', **opts
+):
"""get appropriate commit message editor according to '--edit' option
'finishdesc' is a function to be called with edited commit message
@@ -910,15 +1032,15 @@
they are specific for usage in MQ.
"""
if edit or finishdesc or extramsg:
- return lambda r, c, s: commitforceeditor(r, c, s,
- finishdesc=finishdesc,
- extramsg=extramsg,
- editform=editform)
+ return lambda r, c, s: commitforceeditor(
+ r, c, s, finishdesc=finishdesc, extramsg=extramsg, editform=editform
+ )
elif editform:
return lambda r, c, s: commiteditor(r, c, s, editform=editform)
else:
return commiteditor
+
def _escapecommandtemplate(tmpl):
parts = []
for typ, start, end in templater.scantemplate(tmpl, raw=True):
@@ -928,6 +1050,7 @@
parts.append(tmpl[start:end])
return b''.join(parts)
+
def rendercommandtemplate(ui, tmpl, props):
r"""Expand a literal template 'tmpl' in a way suitable for command line
@@ -946,6 +1069,7 @@
t = formatter.maketemplater(ui, _escapecommandtemplate(tmpl))
return t.renderdefault(props)
+
def rendertemplate(ctx, tmpl, props=None):
"""Expand a literal template 'tmpl' byte-string against one changeset
@@ -954,13 +1078,15 @@
"""
repo = ctx.repo()
tres = formatter.templateresources(repo.ui, repo)
- t = formatter.maketemplater(repo.ui, tmpl, defaults=templatekw.keywords,
- resources=tres)
+ t = formatter.maketemplater(
+ repo.ui, tmpl, defaults=templatekw.keywords, resources=tres
+ )
mapping = {'ctx': ctx}
if props:
mapping.update(props)
return t.renderdefault(mapping)
+
def _buildfntemplate(pat, total=None, seqno=None, revwidth=None, pathname=None):
r"""Convert old-style filename format string to template string
@@ -1018,17 +1144,20 @@
break
newname.append(stringutil.escapestr(pat[i:n]))
if n + 2 > end:
- raise error.Abort(_("incomplete format spec in output "
- "filename"))
- c = pat[n + 1:n + 2]
+ raise error.Abort(
+ _("incomplete format spec in output " "filename")
+ )
+ c = pat[n + 1 : n + 2]
i = n + 2
try:
newname.append(expander[c])
except KeyError:
- raise error.Abort(_("invalid format spec '%%%s' in output "
- "filename") % c)
+ raise error.Abort(
+ _("invalid format spec '%%%s' in output " "filename") % c
+ )
return ''.join(newname)
+
def makefilename(ctx, pat, **props):
if not pat:
return pat
@@ -1038,10 +1167,12 @@
# disable the expansion.
return rendertemplate(ctx, tmpl, pycompat.byteskwargs(props))
+
def isstdiofilename(pat):
"""True if the given pat looks like a filename denoting stdin/stdout"""
return not pat or pat == '-'
+
class _unclosablefile(object):
def __init__(self, fp):
self._fp = fp
@@ -1061,6 +1192,7 @@
def __exit__(self, exc_type, exc_value, exc_tb):
pass
+
def makefileobj(ctx, pat, mode='wb', **props):
writable = mode not in ('r', 'rb')
@@ -1074,6 +1206,7 @@
fn = makefilename(ctx, pat, **props)
return open(fn, mode)
+
def openstorage(repo, cmd, file_, opts, returnrevlog=False):
"""opens the changelog, manifest, a filelog or a given revlog"""
cl = opts['changelog']
@@ -1088,8 +1221,10 @@
if file_:
msg = _('cannot specify filename with --changelog or --manifest')
elif not repo:
- msg = _('cannot specify --changelog or --manifest or --dir '
- 'without a repository')
+ msg = _(
+ 'cannot specify --changelog or --manifest or --dir '
+ 'without a repository'
+ )
if msg:
raise error.Abort(msg)
@@ -1099,8 +1234,12 @@
r = repo.unfiltered().changelog
elif dir:
if 'treemanifest' not in repo.requirements:
- raise error.Abort(_("--dir can only be used on repos with "
- "treemanifest enabled"))
+ raise error.Abort(
+ _(
+ "--dir can only be used on repos with "
+ "treemanifest enabled"
+ )
+ )
if not dir.endswith('/'):
dir = dir + '/'
dirlog = repo.manifestlog.getstorage(dir)
@@ -1131,10 +1270,12 @@
raise error.CommandError(cmd, _('invalid arguments'))
if not os.path.isfile(file_):
raise error.Abort(_("revlog '%s' not found") % file_)
- r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False),
- file_[:-2] + ".i")
+ r = revlog.revlog(
+ vfsmod.vfs(encoding.getcwd(), audit=False), file_[:-2] + ".i"
+ )
return r
+
def openrevlog(repo, cmd, file_, opts):
"""Obtain a revlog backing storage of an item.
@@ -1147,6 +1288,7 @@
"""
return openstorage(repo, cmd, file_, opts, returnrevlog=True)
+
def copy(ui, repo, pats, opts, rename=False):
# called with the repo lock held
#
@@ -1159,6 +1301,7 @@
wctx = repo[None]
uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
+
def walkpat(pat):
srcs = []
if after:
@@ -1174,8 +1317,13 @@
if exact and state == '?':
ui.warn(_('%s: not copying - file is not managed\n') % rel)
if exact and state == 'r':
- ui.warn(_('%s: not copying - file has been marked for'
- ' remove\n') % rel)
+ ui.warn(
+ _(
+ '%s: not copying - file has been marked for'
+ ' remove\n'
+ )
+ % rel
+ )
continue
# abs: hgsep
# rel: ossep
@@ -1202,20 +1350,26 @@
# check for collisions
prevsrc = targets.get(abstarget)
if prevsrc is not None:
- ui.warn(_('%s: not overwriting - %s collides with %s\n') %
- (reltarget, repo.pathto(abssrc, cwd),
- repo.pathto(prevsrc, cwd)))
- return True # report a failure
+ ui.warn(
+ _('%s: not overwriting - %s collides with %s\n')
+ % (
+ reltarget,
+ repo.pathto(abssrc, cwd),
+ repo.pathto(prevsrc, cwd),
+ )
+ )
+ return True # report a failure
# check for overwrites
exists = os.path.lexists(target)
samefile = False
if exists and abssrc != abstarget:
- if (repo.dirstate.normalize(abssrc) ==
- repo.dirstate.normalize(abstarget)):
+ if repo.dirstate.normalize(abssrc) == repo.dirstate.normalize(
+ abstarget
+ ):
if not rename:
ui.warn(_("%s: can't copy - same file\n") % reltarget)
- return True # report a failure
+ return True # report a failure
exists = False
samefile = True
@@ -1228,11 +1382,21 @@
else:
flags = '--force'
if rename:
- hint = _("('hg rename %s' to replace the file by "
- 'recording a rename)\n') % flags
+ hint = (
+ _(
+ "('hg rename %s' to replace the file by "
+ 'recording a rename)\n'
+ )
+ % flags
+ )
else:
- hint = _("('hg copy %s' to replace the file by "
- 'recording a copy)\n') % flags
+ hint = (
+ _(
+ "('hg copy %s' to replace the file by "
+ 'recording a copy)\n'
+ )
+ % flags
+ )
else:
msg = _('%s: not overwriting - file exists\n')
if rename:
@@ -1241,17 +1405,21 @@
hint = _("('hg copy --after' to record the copy)\n")
ui.warn(msg % reltarget)
ui.warn(hint)
- return True # report a failure
+ return True # report a failure
if after:
if not exists:
if rename:
- ui.warn(_('%s: not recording move - %s does not exist\n') %
- (relsrc, reltarget))
+ ui.warn(
+ _('%s: not recording move - %s does not exist\n')
+ % (relsrc, reltarget)
+ )
else:
- ui.warn(_('%s: not recording copy - %s does not exist\n') %
- (relsrc, reltarget))
- return True # report a failure
+ ui.warn(
+ _('%s: not recording copy - %s does not exist\n')
+ % (relsrc, reltarget)
+ )
+ return True # report a failure
elif not dryrun:
try:
if exists:
@@ -1273,9 +1441,11 @@
ui.warn(_('%s: deleted in working directory\n') % relsrc)
srcexists = False
else:
- ui.warn(_('%s: cannot copy - %s\n') %
- (relsrc, encoding.strtolocal(inst.strerror)))
- return True # report a failure
+ ui.warn(
+ _('%s: cannot copy - %s\n')
+ % (relsrc, encoding.strtolocal(inst.strerror))
+ )
+ return True # report a failure
if ui.verbose or not exact:
if rename:
@@ -1286,8 +1456,9 @@
targets[abstarget] = abssrc
# fix up dirstate
- scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
- dryrun=dryrun, cwd=cwd)
+ scmutil.dirstatecopy(
+ ui, repo, wctx, abssrc, abstarget, dryrun=dryrun, cwd=cwd
+ )
if rename and not dryrun:
if not after and srcexists and not samefile:
rmdir = repo.ui.configbool('experimental', 'removeemptydirs')
@@ -1310,8 +1481,9 @@
striplen += len(pycompat.ossep)
res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
elif destdirexists:
- res = lambda p: os.path.join(dest,
- os.path.basename(util.localpath(p)))
+ res = lambda p: os.path.join(
+ dest, os.path.basename(util.localpath(p))
+ )
else:
res = lambda p: dest
return res
@@ -1323,8 +1495,9 @@
def targetpathafterfn(pat, dest, srcs):
if matchmod.patkind(pat):
# a mercurial pattern
- res = lambda p: os.path.join(dest,
- os.path.basename(util.localpath(p)))
+ res = lambda p: os.path.join(
+ dest, os.path.basename(util.localpath(p))
+ )
else:
abspfx = pathutil.canonpath(repo.root, cwd, pat)
if len(abspfx) < len(srcs[0][0]):
@@ -1349,13 +1522,13 @@
striplen1 += len(pycompat.ossep)
if evalpath(striplen1) > score:
striplen = striplen1
- res = lambda p: os.path.join(dest,
- util.localpath(p)[striplen:])
+ res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
else:
# a file
if destdirexists:
- res = lambda p: os.path.join(dest,
- os.path.basename(util.localpath(p)))
+ res = lambda p: os.path.join(
+ dest, os.path.basename(util.localpath(p))
+ )
else:
res = lambda p: dest
return res
@@ -1369,8 +1542,12 @@
destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
if not destdirexists:
if len(pats) > 1 or matchmod.patkind(pats[0]):
- raise error.Abort(_('with multiple sources, destination must be an '
- 'existing directory'))
+ raise error.Abort(
+ _(
+ 'with multiple sources, destination must be an '
+ 'existing directory'
+ )
+ )
if util.endswithsep(dest):
raise error.Abort(_('destination %s is not a directory') % dest)
@@ -1394,10 +1571,11 @@
return errors != 0
+
## facility to let extension process additional data into an import patch
# list of identifier to be executed in order
extrapreimport = [] # run before commit
-extrapostimport = [] # run after commit
+extrapostimport = [] # run after commit
# mapping from identifier to actual import function
#
# 'preimport' are run before the commit is made and are provided the following
@@ -1415,6 +1593,7 @@
# - ctx: the changectx created by import.
extrapostimportmap = {}
+
def tryimportone(ui, repo, patchdata, parents, opts, msgs, updatefunc):
"""Utility function used by commands.import to import a single patch
@@ -1489,8 +1668,12 @@
except error.RepoError:
p1, p2 = parents
if p2.node() == nullid:
- ui.warn(_("warning: import the patch as a normal revision\n"
- "(use --exact to import the patch as a merge)\n"))
+ ui.warn(
+ _(
+ "warning: import the patch as a normal revision\n"
+ "(use --exact to import the patch as a merge)\n"
+ )
+ )
else:
p1, p2 = parents
@@ -1507,8 +1690,16 @@
partial = opts.get('partial', False)
files = set()
try:
- patch.patch(ui, repo, tmpname, strip=strip, prefix=prefix,
- files=files, eolmode=None, similarity=sim / 100.0)
+ patch.patch(
+ ui,
+ repo,
+ tmpname,
+ strip=strip,
+ prefix=prefix,
+ files=files,
+ eolmode=None,
+ similarity=sim / 100.0,
+ )
except error.PatchError as e:
if not partial:
raise error.Abort(pycompat.bytestr(e))
@@ -1531,8 +1722,9 @@
if opts.get('exact'):
editor = None
else:
- editor = getcommiteditor(editform=editform,
- **pycompat.strkwargs(opts))
+ editor = getcommiteditor(
+ editform=editform, **pycompat.strkwargs(opts)
+ )
extra = {}
for idfunc in extrapreimport:
extrapreimportmap[idfunc](repo, patchdata, extra, opts)
@@ -1540,9 +1732,9 @@
if partial:
overrides[('ui', 'allowemptycommit')] = True
with repo.ui.configoverride(overrides, 'import'):
- n = repo.commit(message, user,
- date, match=m,
- editor=editor, extra=extra)
+ n = repo.commit(
+ message, user, date, match=m, editor=editor, extra=extra
+ )
for idfunc in extrapostimport:
extrapostimportmap[idfunc](repo[n])
else:
@@ -1554,22 +1746,34 @@
try:
files = set()
try:
- patch.patchrepo(ui, repo, p1, store, tmpname, strip, prefix,
- files, eolmode=None)
+ patch.patchrepo(
+ ui,
+ repo,
+ p1,
+ store,
+ tmpname,
+ strip,
+ prefix,
+ files,
+ eolmode=None,
+ )
except error.PatchError as e:
raise error.Abort(stringutil.forcebytestr(e))
if opts.get('exact'):
editor = None
else:
editor = getcommiteditor(editform='import.bypass')
- memctx = context.memctx(repo, (p1.node(), p2.node()),
- message,
- files=files,
- filectxfn=store,
- user=user,
- date=date,
- branch=branch,
- editor=editor)
+ memctx = context.memctx(
+ repo,
+ (p1.node(), p2.node()),
+ message,
+ files=files,
+ filectxfn=store,
+ user=user,
+ date=date,
+ branch=branch,
+ editor=editor,
+ )
n = memctx.commit()
finally:
store.close()
@@ -1585,6 +1789,7 @@
msg = _('created %s') % short(n)
return msg, n, rejects
+
# facility to let extensions include additional data in an exported patch
# list of identifiers to be executed in order
extraexport = []
@@ -1593,6 +1798,7 @@
# it is given two arguments (sequencenumber, changectx)
extraexportmap = {}
+
def _exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts):
node = scmutil.binnode(ctx)
parents = [p.node() for p in ctx.parents() if p]
@@ -1610,8 +1816,9 @@
fm.write('user', '# User %s\n', ctx.user())
fm.plain('# Date %d %d\n' % ctx.date())
fm.write('date', '# %s\n', fm.formatdate(ctx.date()))
- fm.condwrite(branch and branch != 'default',
- 'branch', '# Branch %s\n', branch)
+ fm.condwrite(
+ branch and branch != 'default', 'branch', '# Branch %s\n', branch
+ )
fm.write('node', '# Node ID %s\n', hex(node))
fm.plain('# Parent %s\n' % hex(prev))
if len(parents) > 1:
@@ -1636,6 +1843,7 @@
# TODO: make it structured?
fm.data(diff=b''.join(chunkiter))
+
def _exportfile(repo, revs, fm, dest, switch_parent, diffopts, match):
"""Export changesets to stdout or a single file"""
for seqno, rev in enumerate(revs, 1):
@@ -1645,8 +1853,10 @@
fm.startitem()
_exportsingle(repo, ctx, fm, match, switch_parent, seqno, diffopts)
-def _exportfntemplate(repo, revs, basefm, fntemplate, switch_parent, diffopts,
- match):
+
+def _exportfntemplate(
+ repo, revs, basefm, fntemplate, switch_parent, diffopts, match
+):
"""Export changesets to possibly multiple files"""
total = len(revs)
revwidth = max(len(str(rev)) for rev in revs)
@@ -1654,8 +1864,9 @@
for seqno, rev in enumerate(revs, 1):
ctx = repo[rev]
- dest = makefilename(ctx, fntemplate,
- total=total, seqno=seqno, revwidth=revwidth)
+ dest = makefilename(
+ ctx, fntemplate, total=total, seqno=seqno, revwidth=revwidth
+ )
filemap.setdefault(dest, []).append((seqno, rev))
for dest in filemap:
@@ -1664,8 +1875,10 @@
for seqno, rev in filemap[dest]:
fm.startitem()
ctx = repo[rev]
- _exportsingle(repo, ctx, fm, match, switch_parent, seqno,
- diffopts)
+ _exportsingle(
+ repo, ctx, fm, match, switch_parent, seqno, diffopts
+ )
+
def _prefetchchangedfiles(repo, revs, match):
allfiles = set()
@@ -1675,8 +1888,16 @@
allfiles.add(file)
scmutil.prefetchfiles(repo, revs, scmutil.matchfiles(repo, allfiles))
-def export(repo, revs, basefm, fntemplate='hg-%h.patch', switch_parent=False,
- opts=None, match=None):
+
+def export(
+ repo,
+ revs,
+ basefm,
+ fntemplate='hg-%h.patch',
+ switch_parent=False,
+ opts=None,
+ match=None,
+):
'''export changesets as hg patches
Args:
@@ -1704,8 +1925,10 @@
if not fntemplate:
_exportfile(repo, revs, basefm, '<unnamed>', switch_parent, opts, match)
else:
- _exportfntemplate(repo, revs, basefm, fntemplate, switch_parent, opts,
- match)
+ _exportfntemplate(
+ repo, revs, basefm, fntemplate, switch_parent, opts, match
+ )
+
def exportfile(repo, revs, fp, switch_parent=False, opts=None, match=None):
"""Export changesets to the given file stream"""
@@ -1715,6 +1938,7 @@
with formatter.formatter(repo.ui, fp, 'export', {}) as fm:
_exportfile(repo, revs, fm, dest, switch_parent, opts, match)
+
def showmarker(fm, marker, index=None):
"""utility function to display obsolescence marker in a readable way
@@ -1723,13 +1947,17 @@
fm.write('index', '%i ', index)
fm.write('prednode', '%s ', hex(marker.prednode()))
succs = marker.succnodes()
- fm.condwrite(succs, 'succnodes', '%s ',
- fm.formatlist(map(hex, succs), name='node'))
+ fm.condwrite(
+ succs, 'succnodes', '%s ', fm.formatlist(map(hex, succs), name='node')
+ )
fm.write('flag', '%X ', marker.flags())
parents = marker.parentnodes()
if parents is not None:
- fm.write('parentnodes', '{%s} ',
- fm.formatlist(map(hex, parents), name='node', sep=', '))
+ fm.write(
+ 'parentnodes',
+ '{%s} ',
+ fm.formatlist(map(hex, parents), name='node', sep=', '),
+ )
fm.write('date', '(%s) ', fm.formatdate(marker.date()))
meta = marker.metadata().copy()
meta.pop('date', None)
@@ -1737,6 +1965,7 @@
fm.write('metadata', '{%s}', fm.formatdict(smeta, fmt='%r: %r', sep=', '))
fm.plain('\n')
+
def finddate(ui, repo, date):
"""Find the tipmost changeset that matches the given date spec"""
@@ -1752,18 +1981,22 @@
for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
rev = ctx.rev()
if rev in results:
- ui.status(_("found revision %s from %s\n") %
- (rev, dateutil.datestr(results[rev])))
+ ui.status(
+ _("found revision %s from %s\n")
+ % (rev, dateutil.datestr(results[rev]))
+ )
return '%d' % rev
raise error.Abort(_("revision matching date not found"))
+
def increasingwindows(windowsize=8, sizelimit=512):
while True:
yield windowsize
if windowsize < sizelimit:
windowsize *= 2
+
def _walkrevs(repo, opts):
# Default --rev value depends on --follow but --follow behavior
# depends on revisions resolved from --rev...
@@ -1779,9 +2012,11 @@
revs.reverse()
return revs
+
class FileWalkError(Exception):
pass
+
def walkfilerevs(repo, match, follow, revs, fncache):
'''Walks the file history for the matched files.
@@ -1793,6 +2028,7 @@
wanted = set()
copies = []
minrev, maxrev = min(revs), max(revs)
+
def filerevs(filelog, last):
"""
Only files, no patterns. Check the history of each file.
@@ -1817,17 +2053,21 @@
if p != nullrev:
parentlinkrevs.append(filelog.linkrev(p))
n = filelog.node(j)
- revs.append((linkrev, parentlinkrevs,
- follow and filelog.renamed(n)))
+ revs.append(
+ (linkrev, parentlinkrevs, follow and filelog.renamed(n))
+ )
return reversed(revs)
+
def iterfiles():
pctx = repo['.']
for filename in match.files():
if follow:
if filename not in pctx:
- raise error.Abort(_('cannot follow file not in parent '
- 'revision: "%s"') % filename)
+ raise error.Abort(
+ _('cannot follow file not in parent ' 'revision: "%s"')
+ % filename
+ )
yield filename, pctx[filename].filenode()
else:
yield filename, None
@@ -1842,7 +2082,8 @@
# try to find matching entries on the slow path.
if follow:
raise error.Abort(
- _('cannot follow nonexistent file: "%s"') % file_)
+ _('cannot follow nonexistent file: "%s"') % file_
+ )
raise FileWalkError("Cannot walk via filelog")
else:
continue
@@ -1879,6 +2120,7 @@
return wanted
+
class _followfilter(object):
def __init__(self, repo, onlyfirst=False):
self.repo = repo
@@ -1891,8 +2133,9 @@
if self.onlyfirst:
return self.repo.changelog.parentrevs(rev)[0:1]
else:
- return filter(lambda x: x != nullrev,
- self.repo.changelog.parentrevs(rev))
+ return filter(
+ lambda x: x != nullrev, self.repo.changelog.parentrevs(rev)
+ )
if self.startrev == nullrev:
self.startrev = rev
@@ -1917,6 +2160,7 @@
return False
+
def walkchangerevs(repo, match, opts, prepare):
'''Iterate over files and the revs in which they changed.
@@ -1972,8 +2216,9 @@
# changed files
if follow:
- raise error.Abort(_('can only follow copies/renames for explicit '
- 'filenames'))
+ raise error.Abort(
+ _('can only follow copies/renames for explicit ' 'filenames')
+ )
# The slow path checks files modified in every changeset.
# This is really slow on large repos, so compute the set lazily.
@@ -2023,9 +2268,12 @@
def iterate():
if follow and match.always():
ff = _followfilter(repo, onlyfirst=opts.get('follow_first'))
+
def want(rev):
return ff.match(rev) and rev in wanted
+
else:
+
def want(rev):
return rev in wanted
@@ -2044,6 +2292,7 @@
fns = fncache.get(rev)
ctx = change(rev)
if not fns:
+
def fns_generator():
if allfiles:
fiter = iter(ctx)
@@ -2052,6 +2301,7 @@
for f in fiter:
if match(f):
yield f
+
fns = fns_generator()
prepare(ctx, fns)
for rev in nrevs:
@@ -2062,6 +2312,7 @@
return iterate()
+
def add(ui, repo, match, prefix, uipathfn, explicitonly, **opts):
bad = []
@@ -2078,16 +2329,24 @@
dirstate = repo.dirstate
# We don't want to just call wctx.walk here, since it would return a lot of
# clean files, which we aren't interested in and takes time.
- for f in sorted(dirstate.walk(badmatch, subrepos=sorted(wctx.substate),
- unknown=True, ignored=False, full=False)):
+ for f in sorted(
+ dirstate.walk(
+ badmatch,
+ subrepos=sorted(wctx.substate),
+ unknown=True,
+ ignored=False,
+ full=False,
+ )
+ ):
exact = match.exact(f)
if exact or not explicitonly and f not in wctx and repo.wvfs.lexists(f):
if cca:
cca(f)
names.append(f)
if ui.verbose or not exact:
- ui.status(_('adding %s\n') % uipathfn(f),
- label='ui.addremove.added')
+ ui.status(
+ _('adding %s\n') % uipathfn(f), label='ui.addremove.added'
+ )
for subpath in sorted(wctx.substate):
sub = wctx.sub(subpath)
@@ -2096,20 +2355,24 @@
subprefix = repo.wvfs.reljoin(prefix, subpath)
subuipathfn = scmutil.subdiruipathfn(subpath, uipathfn)
if opts.get(r'subrepos'):
- bad.extend(sub.add(ui, submatch, subprefix, subuipathfn, False,
- **opts))
+ bad.extend(
+ sub.add(ui, submatch, subprefix, subuipathfn, False, **opts)
+ )
else:
- bad.extend(sub.add(ui, submatch, subprefix, subuipathfn, True,
- **opts))
+ bad.extend(
+ sub.add(ui, submatch, subprefix, subuipathfn, True, **opts)
+ )
except error.LookupError:
- ui.status(_("skipping missing subrepository: %s\n")
- % uipathfn(subpath))
+ ui.status(
+ _("skipping missing subrepository: %s\n") % uipathfn(subpath)
+ )
if not opts.get(r'dry_run'):
rejected = wctx.add(names, prefix)
bad.extend(f for f in rejected if f in match.files())
return bad
+
def addwebdirpath(repo, serverpath, webconf):
webconf[serverpath] = repo.root
repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root))
@@ -2119,8 +2382,10 @@
for subpath in ctx.substate:
ctx.sub(subpath).addwebdirpath(serverpath, webconf)
-def forget(ui, repo, match, prefix, uipathfn, explicitonly, dryrun,
- interactive):
+
+def forget(
+ ui, repo, match, prefix, uipathfn, explicitonly, dryrun, interactive
+):
if dryrun and interactive:
raise error.Abort(_("cannot specify both --dry-run and --interactive"))
bad = []
@@ -2139,14 +2404,19 @@
subprefix = repo.wvfs.reljoin(prefix, subpath)
subuipathfn = scmutil.subdiruipathfn(subpath, uipathfn)
try:
- subbad, subforgot = sub.forget(submatch, subprefix, subuipathfn,
- dryrun=dryrun,
- interactive=interactive)
+ subbad, subforgot = sub.forget(
+ submatch,
+ subprefix,
+ subuipathfn,
+ dryrun=dryrun,
+ interactive=interactive,
+ )
bad.extend([subpath + '/' + f for f in subbad])
forgot.extend([subpath + '/' + f for f in subforgot])
except error.LookupError:
- ui.status(_("skipping missing subrepository: %s\n")
- % uipathfn(subpath))
+ ui.status(
+ _("skipping missing subrepository: %s\n") % uipathfn(subpath)
+ )
if not explicitonly:
for f in match.files():
@@ -2159,42 +2429,48 @@
# purely from data cached by the status walk above.
if repo.dirstate.normalize(f) in repo.dirstate:
continue
- ui.warn(_('not removing %s: '
- 'file is already untracked\n')
- % uipathfn(f))
+ ui.warn(
+ _('not removing %s: ' 'file is already untracked\n')
+ % uipathfn(f)
+ )
bad.append(f)
if interactive:
- responses = _('[Ynsa?]'
- '$$ &Yes, forget this file'
- '$$ &No, skip this file'
- '$$ &Skip remaining files'
- '$$ Include &all remaining files'
- '$$ &? (display help)')
+ responses = _(
+ '[Ynsa?]'
+ '$$ &Yes, forget this file'
+ '$$ &No, skip this file'
+ '$$ &Skip remaining files'
+ '$$ Include &all remaining files'
+ '$$ &? (display help)'
+ )
for filename in forget[:]:
- r = ui.promptchoice(_('forget %s %s') %
- (uipathfn(filename), responses))
- if r == 4: # ?
+ r = ui.promptchoice(
+ _('forget %s %s') % (uipathfn(filename), responses)
+ )
+ if r == 4: # ?
while r == 4:
for c, t in ui.extractchoices(responses)[1]:
ui.write('%s - %s\n' % (c, encoding.lower(t)))
- r = ui.promptchoice(_('forget %s %s') %
- (uipathfn(filename), responses))
- if r == 0: # yes
+ r = ui.promptchoice(
+ _('forget %s %s') % (uipathfn(filename), responses)
+ )
+ if r == 0: # yes
continue
- elif r == 1: # no
+ elif r == 1: # no
forget.remove(filename)
- elif r == 2: # Skip
+ elif r == 2: # Skip
fnindex = forget.index(filename)
del forget[fnindex:]
break
- elif r == 3: # All
+ elif r == 3: # All
break
for f in forget:
if ui.verbose or not match.exact(f) or interactive:
- ui.status(_('removing %s\n') % uipathfn(f),
- label='ui.addremove.removed')
+ ui.status(
+ _('removing %s\n') % uipathfn(f), label='ui.addremove.removed'
+ )
if not dryrun:
rejected = wctx.forget(forget, prefix)
@@ -2202,6 +2478,7 @@
forgot.extend(f for f in forget if f not in rejected)
return bad, forgot
+
def files(ui, ctx, m, uipathfn, fm, fmt, subrepos):
ret = 1
@@ -2219,21 +2496,27 @@
for subpath in sorted(ctx.substate):
submatch = matchmod.subdirmatcher(subpath, m)
subuipathfn = scmutil.subdiruipathfn(subpath, uipathfn)
- if (subrepos or m.exact(subpath) or any(submatch.files())):
+ if subrepos or m.exact(subpath) or any(submatch.files()):
sub = ctx.sub(subpath)
try:
recurse = m.exact(subpath) or subrepos
- if sub.printfiles(ui, submatch, subuipathfn, fm, fmt,
- recurse) == 0:
+ if (
+ sub.printfiles(ui, submatch, subuipathfn, fm, fmt, recurse)
+ == 0
+ ):
ret = 0
except error.LookupError:
- ui.status(_("skipping missing subrepository: %s\n")
- % uipathfn(subpath))
+ ui.status(
+ _("skipping missing subrepository: %s\n")
+ % uipathfn(subpath)
+ )
return ret
-def remove(ui, repo, m, prefix, uipathfn, after, force, subrepos, dryrun,
- warnings=None):
+
+def remove(
+ ui, repo, m, prefix, uipathfn, after, force, subrepos, dryrun, warnings=None
+):
ret = 0
s = repo.status(match=m, clean=True)
modified, added, deleted, clean = s[0], s[1], s[3], s[6]
@@ -2247,8 +2530,9 @@
warn = False
subs = sorted(wctx.substate)
- progress = ui.makeprogress(_('searching'), total=len(subs),
- unit=_('subrepos'))
+ progress = ui.makeprogress(
+ _('searching'), total=len(subs), unit=_('subrepos')
+ )
for subpath in subs:
submatch = matchmod.subdirmatcher(subpath, m)
subprefix = repo.wvfs.reljoin(prefix, subpath)
@@ -2257,20 +2541,30 @@
progress.increment()
sub = wctx.sub(subpath)
try:
- if sub.removefiles(submatch, subprefix, subuipathfn, after,
- force, subrepos, dryrun, warnings):
+ if sub.removefiles(
+ submatch,
+ subprefix,
+ subuipathfn,
+ after,
+ force,
+ subrepos,
+ dryrun,
+ warnings,
+ ):
ret = 1
except error.LookupError:
- warnings.append(_("skipping missing subrepository: %s\n")
- % uipathfn(subpath))
+ warnings.append(
+ _("skipping missing subrepository: %s\n")
+ % uipathfn(subpath)
+ )
progress.complete()
# warn about failure to delete explicit files/dirs
deleteddirs = util.dirs(deleted)
files = m.files()
- progress = ui.makeprogress(_('deleting'), total=len(files),
- unit=_('files'))
+ progress = ui.makeprogress(_('deleting'), total=len(files), unit=_('files'))
for f in files:
+
def insubrepo():
for subpath in wctx.substate:
if f.startswith(subpath + '/'):
@@ -2279,17 +2573,18 @@
progress.increment()
isdir = f in deleteddirs or wctx.hasdir(f)
- if (f in repo.dirstate or isdir or f == '.'
- or insubrepo() or f in subs):
+ if f in repo.dirstate or isdir or f == '.' or insubrepo() or f in subs:
continue
if repo.wvfs.exists(f):
if repo.wvfs.isdir(f):
- warnings.append(_('not removing %s: no tracked files\n')
- % uipathfn(f))
+ warnings.append(
+ _('not removing %s: no tracked files\n') % uipathfn(f)
+ )
else:
- warnings.append(_('not removing %s: file is untracked\n')
- % uipathfn(f))
+ warnings.append(
+ _('not removing %s: file is untracked\n') % uipathfn(f)
+ )
# missing files will generate a warning elsewhere
ret = 1
progress.complete()
@@ -2299,40 +2594,52 @@
elif after:
list = deleted
remaining = modified + added + clean
- progress = ui.makeprogress(_('skipping'), total=len(remaining),
- unit=_('files'))
+ progress = ui.makeprogress(
+ _('skipping'), total=len(remaining), unit=_('files')
+ )
for f in remaining:
progress.increment()
if ui.verbose or (f in files):
- warnings.append(_('not removing %s: file still exists\n')
- % uipathfn(f))
+ warnings.append(
+ _('not removing %s: file still exists\n') % uipathfn(f)
+ )
ret = 1
progress.complete()
else:
list = deleted + clean
- progress = ui.makeprogress(_('skipping'),
- total=(len(modified) + len(added)),
- unit=_('files'))
+ progress = ui.makeprogress(
+ _('skipping'), total=(len(modified) + len(added)), unit=_('files')
+ )
for f in modified:
progress.increment()
- warnings.append(_('not removing %s: file is modified (use -f'
- ' to force removal)\n') % uipathfn(f))
+ warnings.append(
+ _(
+ 'not removing %s: file is modified (use -f'
+ ' to force removal)\n'
+ )
+ % uipathfn(f)
+ )
ret = 1
for f in added:
progress.increment()
- warnings.append(_("not removing %s: file has been marked for add"
- " (use 'hg forget' to undo add)\n") % uipathfn(f))
+ warnings.append(
+ _(
+ "not removing %s: file has been marked for add"
+ " (use 'hg forget' to undo add)\n"
+ )
+ % uipathfn(f)
+ )
ret = 1
progress.complete()
list = sorted(list)
- progress = ui.makeprogress(_('deleting'), total=len(list),
- unit=_('files'))
+ progress = ui.makeprogress(_('deleting'), total=len(list), unit=_('files'))
for f in list:
if ui.verbose or not m.exact(f):
progress.increment()
- ui.status(_('removing %s\n') % uipathfn(f),
- label='ui.addremove.removed')
+ ui.status(
+ _('removing %s\n') % uipathfn(f), label='ui.addremove.removed'
+ )
progress.complete()
if not dryrun:
@@ -2340,9 +2647,10 @@
if not after:
for f in list:
if f in added:
- continue # we never unlink added files on remove
- rmdir = repo.ui.configbool('experimental',
- 'removeemptydirs')
+ continue # we never unlink added files on remove
+ rmdir = repo.ui.configbool(
+ 'experimental', 'removeemptydirs'
+ )
repo.wvfs.unlinkpath(f, ignoremissing=True, rmdir=rmdir)
repo[None].forget(list)
@@ -2352,9 +2660,11 @@
return ret
+
def _catfmtneedsdata(fm):
return not fm.datahint() or 'data' in fm.datahint()
+
def _updatecatformatter(fm, ctx, matcher, path, decode):
"""Hook for adding data to the formatter used by ``hg cat``.
@@ -2373,6 +2683,7 @@
fm.write('data', '%s', data)
fm.data(path=path)
+
def cat(ui, repo, ctx, matcher, basefm, fntemplate, prefix, **opts):
err = 1
opts = pycompat.byteskwargs(opts)
@@ -2380,8 +2691,9 @@
def write(path):
filename = None
if fntemplate:
- filename = makefilename(ctx, fntemplate,
- pathname=os.path.join(prefix, path))
+ filename = makefilename(
+ ctx, fntemplate, pathname=os.path.join(prefix, path)
+ )
# attempt to create the directory if it does not already exist
try:
os.makedirs(os.path.dirname(filename))
@@ -2418,15 +2730,22 @@
try:
submatch = matchmod.subdirmatcher(subpath, matcher)
subprefix = os.path.join(prefix, subpath)
- if not sub.cat(submatch, basefm, fntemplate, subprefix,
- **pycompat.strkwargs(opts)):
+ if not sub.cat(
+ submatch,
+ basefm,
+ fntemplate,
+ subprefix,
+ **pycompat.strkwargs(opts)
+ ):
err = 0
except error.RepoLookupError:
- ui.status(_("skipping missing subrepository: %s\n") %
- uipathfn(subpath))
+ ui.status(
+ _("skipping missing subrepository: %s\n") % uipathfn(subpath)
+ )
return err
+
def commit(ui, repo, commitfunc, pats, opts):
'''commit the specified files or all outstanding changes'''
date = opts.get('date')
@@ -2446,22 +2765,24 @@
uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
if scmutil.addremove(repo, matcher, "", uipathfn, opts) != 0:
raise error.Abort(
- _("failed to mark all new/missing files as added/removed"))
+ _("failed to mark all new/missing files as added/removed")
+ )
return commitfunc(ui, repo, message, matcher, opts)
+
def samefile(f, ctx1, ctx2):
if f in ctx1.manifest():
a = ctx1.filectx(f)
if f in ctx2.manifest():
b = ctx2.filectx(f)
- return (not a.cmp(b)
- and a.flags() == b.flags())
+ return not a.cmp(b) and a.flags() == b.flags()
else:
return False
else:
return f not in ctx2.manifest()
+
def amend(ui, repo, old, extra, pats, opts):
# avoid cycle context -> subrepo -> cmdutil
from . import context
@@ -2469,7 +2790,7 @@
# amend will reuse the existing user if not specified, but the obsolete
# marker creation requires that the current user's name is specified.
if obsolete.isenabled(repo, obsolete.createmarkersopt):
- ui.username() # raise exception if username not set
+ ui.username() # raise exception if username not set
ui.note(_('amending changeset %s\n') % old)
base = old.p1()
@@ -2514,17 +2835,20 @@
matcher = scmutil.match(wctx, pats, opts)
relative = scmutil.anypats(pats, opts)
uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
- if (opts.get('addremove')
- and scmutil.addremove(repo, matcher, "", uipathfn, opts)):
+ if opts.get('addremove') and scmutil.addremove(
+ repo, matcher, "", uipathfn, opts
+ ):
raise error.Abort(
- _("failed to mark all new/missing files as added/removed"))
+ _("failed to mark all new/missing files as added/removed")
+ )
# Check subrepos. This depends on in-place wctx._status update in
# subrepo.precommit(). To minimize the risk of this hack, we do
# nothing if .hgsub does not exist.
if '.hgsub' in wctx or '.hgsub' in old:
subs, commitsubs, newsubstate = subrepoutil.precommit(
- ui, wctx, wctx._status, matcher)
+ ui, wctx, wctx._status, matcher
+ )
# amend should abort if commitsubrepos is enabled
assert not commitsubs
if subs:
@@ -2535,7 +2859,7 @@
filestoamend = set(f for f in wctx.files() if matcher(f))
- changes = (len(filestoamend) > 0)
+ changes = len(filestoamend) > 0
if changes:
# Recompute copies (avoid recording a -> b -> a)
copied = copies.pathcopies(base, wctx, matcher)
@@ -2549,8 +2873,11 @@
# was removed, it's no longer relevant. If X is missing (aka
# deleted), old X must be preserved.
files.update(filestoamend)
- files = [f for f in files if (f not in filestoamend
- or not samefile(f, wctx, base))]
+ files = [
+ f
+ for f in files
+ if (f not in filestoamend or not samefile(f, wctx, base))
+ ]
def filectxfn(repo, ctx_, path):
try:
@@ -2568,14 +2895,19 @@
fctx = wctx[path]
flags = fctx.flags()
- mctx = context.memfilectx(repo, ctx_,
- fctx.path(), fctx.data(),
- islink='l' in flags,
- isexec='x' in flags,
- copysource=copied.get(path))
+ mctx = context.memfilectx(
+ repo,
+ ctx_,
+ fctx.path(),
+ fctx.data(),
+ islink='l' in flags,
+ isexec='x' in flags,
+ copysource=copied.get(path),
+ )
return mctx
except KeyError:
return None
+
else:
ui.note(_('copying changeset %s to %s\n') % (old, base))
@@ -2607,22 +2939,26 @@
pureextra = extra.copy()
extra['amend_source'] = old.hex()
- new = context.memctx(repo,
- parents=[base.node(), old.p2().node()],
- text=message,
- files=files,
- filectxfn=filectxfn,
- user=user,
- date=date,
- extra=extra,
- editor=editor)
+ new = context.memctx(
+ repo,
+ parents=[base.node(), old.p2().node()],
+ text=message,
+ files=files,
+ filectxfn=filectxfn,
+ user=user,
+ date=date,
+ extra=extra,
+ editor=editor,
+ )
newdesc = changelog.stripdesc(new.description())
- if ((not changes)
+ if (
+ (not changes)
and newdesc == old.description()
and user == old.user()
and (date == old.date() or datemaydiffer)
- and pureextra == old.extra()):
+ and pureextra == old.extra()
+ ):
# nothing changed. continuing here would create a new node
# anyway because of the amend_source noise.
#
@@ -2641,9 +2977,15 @@
if opts.get('note'):
obsmetadata = {'note': encoding.fromlocal(opts['note'])}
backup = ui.configbool('rewrite', 'backup-bundle')
- scmutil.cleanupnodes(repo, mapping, 'amend', metadata=obsmetadata,
- fixphase=True, targetphase=commitphase,
- backup=backup)
+ scmutil.cleanupnodes(
+ repo,
+ mapping,
+ 'amend',
+ metadata=obsmetadata,
+ fixphase=True,
+ targetphase=commitphase,
+ backup=backup,
+ )
# Fixing the dirstate because localrepo.commitctx does not update
# it. This is rather convenient because we did not need to update
@@ -2666,14 +3008,24 @@
return newid
+
def commiteditor(repo, ctx, subs, editform=''):
if ctx.description():
return ctx.description()
- return commitforceeditor(repo, ctx, subs, editform=editform,
- unchangedmessagedetection=True)
-
-def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None,
- editform='', unchangedmessagedetection=False):
+ return commitforceeditor(
+ repo, ctx, subs, editform=editform, unchangedmessagedetection=True
+ )
+
+
+def commitforceeditor(
+ repo,
+ ctx,
+ subs,
+ finishdesc=None,
+ extramsg=None,
+ editform='',
+ unchangedmessagedetection=False,
+):
if not extramsg:
extramsg = _("Leave message empty to abort commit.")
@@ -2684,7 +3036,8 @@
ref = '.'.join(forms)
if repo.ui.config('committemplate', ref):
templatetext = committext = buildcommittemplate(
- repo, ctx, subs, extramsg, ref)
+ repo, ctx, subs, extramsg, ref
+ )
break
forms.pop()
else:
@@ -2699,16 +3052,22 @@
repo.dirstate.write(tr)
pending = tr and tr.writepending() and repo.root
- editortext = repo.ui.edit(committext, ctx.user(), ctx.extra(),
- editform=editform, pending=pending,
- repopath=repo.path, action='commit')
+ editortext = repo.ui.edit(
+ committext,
+ ctx.user(),
+ ctx.extra(),
+ editform=editform,
+ pending=pending,
+ repopath=repo.path,
+ action='commit',
+ )
text = editortext
# strip away anything below this special string (used for editors that want
# to display the diff)
stripbelow = re.search(_linebelow, text, flags=re.MULTILINE)
if stripbelow:
- text = text[:stripbelow.start()]
+ text = text[: stripbelow.start()]
text = re.sub("(?m)^HG:.*(\n|$)", "", text)
os.chdir(olddir)
@@ -2722,32 +3081,43 @@
return text
+
def buildcommittemplate(repo, ctx, subs, extramsg, ref):
ui = repo.ui
spec = formatter.templatespec(ref, None, None)
t = logcmdutil.changesettemplater(ui, repo, spec)
- t.t.cache.update((k, templater.unquotestring(v))
- for k, v in repo.ui.configitems('committemplate'))
+ t.t.cache.update(
+ (k, templater.unquotestring(v))
+ for k, v in repo.ui.configitems('committemplate')
+ )
if not extramsg:
- extramsg = '' # ensure that extramsg is string
+ extramsg = '' # ensure that extramsg is string
ui.pushbuffer()
t.show(ctx, extramsg=extramsg)
return ui.popbuffer()
+
def hgprefix(msg):
return "\n".join(["HG: %s" % a for a in msg.split("\n") if a])
+
def buildcommittext(repo, ctx, subs, extramsg):
edittext = []
modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
if ctx.description():
edittext.append(ctx.description())
edittext.append("")
- edittext.append("") # Empty line between message and comments.
- edittext.append(hgprefix(_("Enter commit message."
- " Lines beginning with 'HG:' are removed.")))
+ edittext.append("") # Empty line between message and comments.
+ edittext.append(
+ hgprefix(
+ _(
+ "Enter commit message."
+ " Lines beginning with 'HG:' are removed."
+ )
+ )
+ )
edittext.append(hgprefix(extramsg))
edittext.append("HG: --")
edittext.append(hgprefix(_("user: %s") % ctx.user()))
@@ -2767,14 +3137,21 @@
return "\n".join(edittext)
+
def commitstatus(repo, node, branch, bheads=None, opts=None):
if opts is None:
opts = {}
ctx = repo[node]
parents = ctx.parents()
- if (not opts.get('amend') and bheads and node not in bheads and not
- [x for x in parents if x.node() in bheads and x.branch() == branch]):
+ if (
+ not opts.get('amend')
+ and bheads
+ and node not in bheads
+ and not [
+ x for x in parents if x.node() in bheads and x.branch() == branch
+ ]
+ ):
repo.ui.status(_('created new head\n'))
# The message is not printed for initial roots. For the other
# changesets, it is printed in the following situations:
@@ -2815,9 +3192,11 @@
elif repo.ui.verbose:
repo.ui.write(_('committed changeset %d:%s\n') % (ctx.rev(), ctx))
+
def postcommitstatus(repo, pats, opts):
return repo.status(match=scmutil.match(repo[None], pats, opts))
+
def revert(ui, repo, ctx, parents, *pats, **opts):
opts = pycompat.byteskwargs(opts)
parent, p2 = parents
@@ -2875,8 +3254,9 @@
# Find status of all file in `names`.
m = scmutil.matchfiles(repo, names)
- changes = repo.status(node1=node, match=m,
- unknown=True, ignored=True, clean=True)
+ changes = repo.status(
+ node1=node, match=m, unknown=True, ignored=True, clean=True
+ )
else:
changes = repo.status(node1=node, match=m)
for kind in changes:
@@ -2886,12 +3266,12 @@
m = scmutil.matchfiles(repo, names)
modified = set(changes.modified)
- added = set(changes.added)
- removed = set(changes.removed)
+ added = set(changes.added)
+ removed = set(changes.removed)
_deleted = set(changes.deleted)
- unknown = set(changes.unknown)
+ unknown = set(changes.unknown)
unknown.update(changes.ignored)
- clean = set(changes.clean)
+ clean = set(changes.clean)
modadded = set()
# We need to account for the state of the file in the dirstate,
@@ -2908,8 +3288,8 @@
else:
changes = repo.status(node1=parent, match=m)
dsmodified = set(changes.modified)
- dsadded = set(changes.added)
- dsremoved = set(changes.removed)
+ dsadded = set(changes.added)
+ dsremoved = set(changes.removed)
# store all local modifications, useful later for rename detection
localchanges = dsmodified | dsadded
@@ -2924,7 +3304,7 @@
# tell newly modified apart.
dsmodified &= modified
- dsmodified |= modified & dsadded # dirstate added may need backup
+ dsmodified |= modified & dsadded # dirstate added may need backup
modified -= dsmodified
# We need to wait for some post-processing to update this set
@@ -2989,24 +3369,25 @@
# action to be actually performed by revert
# (<list of file>, message>) tuple
- actions = {'revert': ([], _('reverting %s\n')),
- 'add': ([], _('adding %s\n')),
- 'remove': ([], _('removing %s\n')),
- 'drop': ([], _('removing %s\n')),
- 'forget': ([], _('forgetting %s\n')),
- 'undelete': ([], _('undeleting %s\n')),
- 'noop': (None, _('no changes needed to %s\n')),
- 'unknown': (None, _('file not managed: %s\n')),
- }
+ actions = {
+ 'revert': ([], _('reverting %s\n')),
+ 'add': ([], _('adding %s\n')),
+ 'remove': ([], _('removing %s\n')),
+ 'drop': ([], _('removing %s\n')),
+ 'forget': ([], _('forgetting %s\n')),
+ 'undelete': ([], _('undeleting %s\n')),
+ 'noop': (None, _('no changes needed to %s\n')),
+ 'unknown': (None, _('file not managed: %s\n')),
+ }
# "constant" that convey the backup strategy.
# All set to `discard` if `no-backup` is set do avoid checking
# no_backup lower in the code.
# These values are ordered for comparison purposes
- backupinteractive = 3 # do backup if interactively modified
+ backupinteractive = 3 # do backup if interactively modified
backup = 2 # unconditionally do backup
- check = 1 # check if the existing file differs from target
- discard = 0 # never do backup
+ check = 1 # check if the existing file differs from target
+ discard = 0 # never do backup
if opts.get('no_backup'):
backupinteractive = backup = check = discard
if interactive:
@@ -3024,36 +3405,35 @@
# file state
# action
# make backup
-
## Sets that results that will change file on disk
# Modified compared to target, no local change
- (modified, actions['revert'], discard),
+ (modified, actions['revert'], discard),
# Modified compared to target, but local file is deleted
- (deleted, actions['revert'], discard),
+ (deleted, actions['revert'], discard),
# Modified compared to target, local change
- (dsmodified, actions['revert'], dsmodifiedbackup),
+ (dsmodified, actions['revert'], dsmodifiedbackup),
# Added since target
- (added, actions['remove'], discard),
+ (added, actions['remove'], discard),
# Added in working directory
- (dsadded, actions['forget'], discard),
+ (dsadded, actions['forget'], discard),
# Added since target, have local modification
- (modadded, backupanddel, backup),
+ (modadded, backupanddel, backup),
# Added since target but file is missing in working directory
- (deladded, actions['drop'], discard),
+ (deladded, actions['drop'], discard),
# Removed since target, before working copy parent
- (removed, actions['add'], discard),
+ (removed, actions['add'], discard),
# Same as `removed` but an unknown file exists at the same path
- (removunk, actions['add'], check),
+ (removunk, actions['add'], check),
# Removed since targe, marked as such in working copy parent
- (dsremoved, actions['undelete'], discard),
+ (dsremoved, actions['undelete'], discard),
# Same as `dsremoved` but an unknown file exists at the same path
- (dsremovunk, actions['undelete'], check),
+ (dsremovunk, actions['undelete'], check),
## the following sets does not result in any file changes
# File with no modification
- (clean, actions['noop'], discard),
+ (clean, actions['noop'], discard),
# Existing file, not tracked anywhere
- (unknown, actions['unknown'], discard),
- )
+ (unknown, actions['unknown'], discard),
+ )
for abs, exact in sorted(names.items()):
# target file to be touch on disk (relative to cwd)
@@ -3071,12 +3451,15 @@
# .orig files (issue4793)
if dobackup == backupinteractive:
tobackup.add(abs)
- elif (backup <= dobackup or wctx[abs].cmp(ctx[abs])):
+ elif backup <= dobackup or wctx[abs].cmp(ctx[abs]):
absbakname = scmutil.backuppath(ui, repo, abs)
- bakname = os.path.relpath(absbakname,
- start=repo.root)
- ui.note(_('saving current version of %s as %s\n') %
- (uipathfn(abs), uipathfn(bakname)))
+ bakname = os.path.relpath(
+ absbakname, start=repo.root
+ )
+ ui.note(
+ _('saving current version of %s as %s\n')
+ % (uipathfn(abs), uipathfn(bakname))
+ )
if not opts.get('dry_run'):
if interactive:
util.copyfile(target, absbakname)
@@ -3094,25 +3477,49 @@
oplist = [actions[name][0] for name in needdata]
prefetch = scmutil.prefetchfiles
matchfiles = scmutil.matchfiles
- prefetch(repo, [ctx.rev()],
- matchfiles(repo,
- [f for sublist in oplist for f in sublist]))
+ prefetch(
+ repo,
+ [ctx.rev()],
+ matchfiles(repo, [f for sublist in oplist for f in sublist]),
+ )
match = scmutil.match(repo[None], pats)
- _performrevert(repo, parents, ctx, names, uipathfn, actions,
- match, interactive, tobackup)
+ _performrevert(
+ repo,
+ parents,
+ ctx,
+ names,
+ uipathfn,
+ actions,
+ match,
+ interactive,
+ tobackup,
+ )
if targetsubs:
# Revert the subrepos on the revert list
for sub in targetsubs:
try:
- wctx.sub(sub).revert(ctx.substate[sub], *pats,
- **pycompat.strkwargs(opts))
+ wctx.sub(sub).revert(
+ ctx.substate[sub], *pats, **pycompat.strkwargs(opts)
+ )
except KeyError:
- raise error.Abort("subrepository '%s' does not exist in %s!"
- % (sub, short(ctx.node())))
-
-def _performrevert(repo, parents, ctx, names, uipathfn, actions,
- match, interactive=False, tobackup=None):
+ raise error.Abort(
+ "subrepository '%s' does not exist in %s!"
+ % (sub, short(ctx.node()))
+ )
+
+
+def _performrevert(
+ repo,
+ parents,
+ ctx,
+ names,
+ uipathfn,
+ actions,
+ match,
+ interactive=False,
+ tobackup=None,
+):
"""function that actually perform all the actions computed for revert
This is an independent function to let extension to plug in and react to
@@ -3145,7 +3552,8 @@
for f in actions['forget'][0]:
if interactive:
choice = repo.ui.promptchoice(
- _("forget added file %s (Yn)?$$ &Yes $$ &No") % uipathfn(f))
+ _("forget added file %s (Yn)?$$ &Yes $$ &No") % uipathfn(f)
+ )
if choice == 0:
prntstatusmsg('forget', f)
repo.dirstate.drop(f)
@@ -3158,7 +3566,8 @@
audit_path(f)
if interactive:
choice = repo.ui.promptchoice(
- _("remove added file %s (Yn)?$$ &Yes $$ &No") % uipathfn(f))
+ _("remove added file %s (Yn)?$$ &Yes $$ &No") % uipathfn(f)
+ )
if choice == 0:
prntstatusmsg('remove', f)
doremove(f)
@@ -3187,15 +3596,19 @@
# Prompt the user for changes to revert
torevert = [f for f in actions['revert'][0] if f not in excluded_files]
m = scmutil.matchfiles(repo, torevert)
- diffopts = patch.difffeatureopts(repo.ui, whitespace=True,
- section='commands',
- configprefix='revert.interactive.')
+ diffopts = patch.difffeatureopts(
+ repo.ui,
+ whitespace=True,
+ section='commands',
+ configprefix='revert.interactive.',
+ )
diffopts.nodates = True
diffopts.git = True
operation = 'apply'
if node == parent:
- if repo.ui.configbool('experimental',
- 'revert.interactive.select-to-keep'):
+ if repo.ui.configbool(
+ 'experimental', 'revert.interactive.select-to-keep'
+ ):
operation = 'keep'
else:
operation = 'discard'
@@ -3208,8 +3621,9 @@
try:
- chunks, opts = recordfilter(repo.ui, originalchunks, match,
- operation=operation)
+ chunks, opts = recordfilter(
+ repo.ui, originalchunks, match, operation=operation
+ )
if operation == 'discard':
chunks = patch.reversehunks(chunks)
@@ -3222,7 +3636,8 @@
# alsorestore value. Ideally we'd be able to partially revert
# copied/renamed files.
newlyaddedandmodifiedfiles, unusedalsorestore = newandmodified(
- chunks, originalchunks)
+ chunks, originalchunks
+ )
if tobackup is None:
tobackup = set()
# Apply changes
@@ -3273,7 +3688,8 @@
for f in actions['undelete'][0]:
if interactive:
choice = repo.ui.promptchoice(
- _("add back removed file %s (Yn)?$$ &Yes $$ &No") % f)
+ _("add back removed file %s (Yn)?$$ &Yes $$ &No") % f
+ )
if choice == 0:
prntstatusmsg('undelete', f)
checkout(f)
@@ -3291,6 +3707,7 @@
if f in copied:
repo.dirstate.copy(copied[f], f)
+
# a list of (ui, repo, otherpeer, opts, missing) functions called by
# commands.outgoing. "missing" is "missing" of the result of
# "findcommonoutgoing()"
@@ -3318,19 +3735,27 @@
# Check for non-clearable states first, so things like rebase will take
# precedence over update.
for state in statemod._unfinishedstates:
- if (state._clearable or (commit and state._allowcommit) or
- state._reportonly):
+ if (
+ state._clearable
+ or (commit and state._allowcommit)
+ or state._reportonly
+ ):
continue
if state.isunfinished(repo):
raise error.Abort(state.msg(), hint=state.hint())
for s in statemod._unfinishedstates:
- if (not s._clearable or (commit and s._allowcommit) or
- (s._opname == 'merge' and skipmerge) or s._reportonly):
+ if (
+ not s._clearable
+ or (commit and s._allowcommit)
+ or (s._opname == 'merge' and skipmerge)
+ or s._reportonly
+ ):
continue
if s.isunfinished(repo):
raise error.Abort(s.msg(), hint=s.hint())
+
def clearunfinished(repo):
'''Check for unfinished operations (as above), and clear the ones
that are clearable.
@@ -3347,6 +3772,7 @@
if s._clearable and s.isunfinished(repo):
util.unlink(repo.vfs.join(s._fname))
+
def getunfinishedstate(repo):
''' Checks for unfinished operations and returns statecheck object
for it'''
@@ -3355,6 +3781,7 @@
return state
return None
+
def howtocontinue(repo):
'''Check for an unfinished operation and return the command to finish
it.
@@ -3376,6 +3803,7 @@
return contmsg % _("hg commit"), False
return None, None
+
def checkafterresolved(repo):
'''Inform the user about the next action after completing hg resolve
@@ -3391,6 +3819,7 @@
else:
repo.ui.note("%s\n" % msg)
+
def wrongtooltocontinue(repo, task):
'''Raise an abort suggesting how to properly continue if there is an
active task.
@@ -3406,6 +3835,7 @@
hint = after[0]
raise error.Abort(_('no %s in progress') % task, hint=hint)
+
def abortgraft(ui, repo, graftstate):
"""abort the interrupted graft and rollbacks to the state before interrupted
graft"""
@@ -3426,30 +3856,38 @@
# whether to strip or not
cleanup = False
from . import hg
+
if newnodes:
newnodes = [repo[r].rev() for r in newnodes]
cleanup = True
# checking that none of the newnodes turned public or is public
immutable = [c for c in newnodes if not repo[c].mutable()]
if immutable:
- repo.ui.warn(_("cannot clean up public changesets %s\n")
- % ', '.join(bytes(repo[r]) for r in immutable),
- hint=_("see 'hg help phases' for details"))
+ repo.ui.warn(
+ _("cannot clean up public changesets %s\n")
+ % ', '.join(bytes(repo[r]) for r in immutable),
+ hint=_("see 'hg help phases' for details"),
+ )
cleanup = False
# checking that no new nodes are created on top of grafted revs
desc = set(repo.changelog.descendants(newnodes))
if desc - set(newnodes):
- repo.ui.warn(_("new changesets detected on destination "
- "branch, can't strip\n"))
+ repo.ui.warn(
+ _(
+ "new changesets detected on destination "
+ "branch, can't strip\n"
+ )
+ )
cleanup = False
if cleanup:
with repo.wlock(), repo.lock():
hg.updaterepo(repo, startctx.node(), overwrite=True)
# stripping the new nodes created
- strippoints = [c.node() for c in repo.set("roots(%ld)",
- newnodes)]
+ strippoints = [
+ c.node() for c in repo.set("roots(%ld)", newnodes)
+ ]
repair.strip(repo.ui, repo, strippoints, backup=False)
if not cleanup:
@@ -3462,6 +3900,7 @@
graftstate.delete()
return 0
+
def readgraftstate(repo, graftstate):
"""read the graft state file and return a dict of the data stored in it"""
try:
@@ -3470,6 +3909,7 @@
nodes = repo.vfs.read('graftstate').splitlines()
return {'nodes': nodes}
+
def hgabortgraft(ui, repo):
""" abort logic for aborting graft using 'hg abort'"""
with repo.wlock():