##// END OF EJS Templates
rebase: refer to checkunresolved by its new name
rebase: refer to checkunresolved by its new name

File last commit:

r30494:c1149533 default
r30495:d528ddc1 default
Show More
cmdutil.py
3525 lines | 128.1 KiB | text/x-python | PythonLexer
Vadim Gelfer
fix comment.
r2957 # cmdutil.py - help for command processing in mercurial
Vadim Gelfer
refactor text diff/patch code....
r2874 #
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
Vadim Gelfer
refactor text diff/patch code....
r2874 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Vadim Gelfer
refactor text diff/patch code....
r2874
Gregory Szorc
cmdutil: use absolute_import...
r28322 from __future__ import absolute_import
import errno
import os
import re
import sys
import tempfile
from .i18n import _
from .node import (
bin,
hex,
nullid,
nullrev,
short,
)
from . import (
bookmarks,
changelog,
copies,
crecord as crecordmod,
Augie Fackler
dirstateguard: move to new module so I can break some layering violations...
r30488 dirstateguard as dirstateguardmod,
Gregory Szorc
cmdutil: use absolute_import...
r28322 encoding,
error,
formatter,
graphmod,
lock as lockmod,
match as matchmod,
Augie Fackler
checkunresolved: move to new package to help avoid import cycles...
r30494 mergeutil,
Gregory Szorc
cmdutil: use absolute_import...
r28322 obsolete,
patch,
pathutil,
phases,
repair,
revlog,
revset,
scmutil,
templatekw,
templater,
util,
)
timeless
pycompat: switch to util.stringio for py3 compat
r28861 stringio = util.stringio
Vadim Gelfer
refactor text diff/patch code....
r2874
Laurent Charignon
record: extract ishunk to a function...
r25256 def ishunk(x):
hunkclasses = (crecordmod.uihunk, patch.recordhunk)
return isinstance(x, hunkclasses)
Laurent Charignon
record: extract code to compute newly added and modified files...
r25257 def newandmodified(chunks, originalchunks):
newlyaddedandmodifiedfiles = set()
for chunk in chunks:
if ishunk(chunk) and chunk.header.isnewfile() and chunk not in \
originalchunks:
newlyaddedandmodifiedfiles.add(chunk.header.filename())
return newlyaddedandmodifiedfiles
Brendan Cully
mq: add -Q option to all commands not in norepo
r10401 def parsealiases(cmd):
return cmd.lstrip("^").split("|")
Laurent Charignon
record: consolidate ui.write wrapping in a function
r24356 def setupwrapcolorwrite(ui):
# wrap ui.write so diff output can be labeled/colorized
def wrapwrite(orig, *args, **kw):
label = kw.pop('label', '')
for chunk, l in patch.difflabel(lambda: args):
orig(chunk, label=label + l)
oldwrite = ui.write
def wrap(*args, **kwargs):
return wrapwrite(oldwrite, *args, **kwargs)
setattr(ui, 'write', wrap)
return oldwrite
Laurent Charignon
record: add an operation arguments to customize recording ui...
r25310 def filterchunks(ui, originalhunks, usecurses, testfile, operation=None):
Laurent Charignon
record: enable curses recording logic with experimental flag
r24343 if usecurses:
if testfile:
recordfn = crecordmod.testdecorator(testfile,
crecordmod.testchunkselector)
else:
recordfn = crecordmod.chunkselector
Denis Laxalde
crecord: drop unused "operation" parameter from filterpatch function
r29327 return crecordmod.filterpatch(ui, originalhunks, recordfn)
Laurent Charignon
record: enable curses recording logic with experimental flag
r24343
else:
Laurent Charignon
record: add an operation arguments to customize recording ui...
r25310 return patch.filterpatch(ui, originalhunks, operation)
def recordfilter(ui, originalhunks, operation=None):
""" Prompts the user to filter the originalhunks and return a list of
selected hunks.
Denis Laxalde
patch: define full messages for interactive record/revert...
r29326 *operation* is used for to build ui messages to indicate the user what
kind of filtering they are doing: reverting, committing, shelving, etc.
(see patch.filterpatch).
Laurent Charignon
record: add an operation arguments to customize recording ui...
r25310 """
Sean Farley
cmdutil: use crecordmod.checkcurses...
r27531 usecurses = crecordmod.checkcurses(ui)
Laurent Charignon
record: refactor the filtering code
r24357 testfile = ui.config('experimental', 'crecordtest', None)
Laurent Charignon
record: move ui.write wrapping where it should be...
r24358 oldwrite = setupwrapcolorwrite(ui)
try:
Laurent Charignon
commit: add a way to return more information from the chunkselector...
r27155 newchunks, newopts = filterchunks(ui, originalhunks, usecurses,
testfile, operation)
Laurent Charignon
record: move ui.write wrapping where it should be...
r24358 finally:
ui.write = oldwrite
Laurent Charignon
commit: add a way to return more information from the chunkselector...
r27155 return newchunks, newopts
Laurent Charignon
record: refactor the filtering code
r24357
Laurent Charignon
record: change interface of dorecord to accept new filters...
r24309 def dorecord(ui, repo, commitfunc, cmdsuggest, backupall,
filterfn, *pats, **opts):
Gregory Szorc
cmdutil: use absolute_import...
r28322 from . import merge as mergemod
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 if not ui.interactive():
FUJIWARA Katsunori
cmdutil: allow callers of cmdutil.dorecord to omit suggestion...
r25795 if cmdsuggest:
msg = _('running non-interactively, use %s instead') % cmdsuggest
else:
msg = _('running non-interactively')
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(msg)
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272
# make sure username is set before going interactive
if not opts.get('user'):
ui.username() # raise exception, username not provided
def recordfunc(ui, repo, message, match, opts):
"""This is generic record driver.
Its job is to interactively filter local changes, and
accordingly prepare working directory into a state in which the
job can be delegated to a non-interactive commit command such as
'commit' or 'qrefresh'.
After the actual job is done by non-interactive command, the
working directory is restored to its original state.
In the end we'll record interesting changes, and everything else
will be left in place, so the user can continue working.
"""
checkunfinished(repo, commit=True)
timeless
crecord: check for untracked arguments...
r28815 wctx = repo[None]
merge = len(wctx.parents()) > 1
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 if merge:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot partially commit a merge '
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 '(use "hg commit" instead)'))
timeless
crecord: check for untracked arguments...
r28815 def fail(f, msg):
raise error.Abort('%s: %s' % (f, msg))
force = opts.get('force')
if not force:
vdirs = []
match.explicitdir = vdirs.append
match.bad = fail
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 status = repo.status(match=match)
timeless
crecord: check for untracked arguments...
r28815 if not force:
repo.checkcommitpatterns(wctx, vdirs, match, status, fail)
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 diffopts = patch.difffeatureopts(ui, opts=opts, whitespace=True)
diffopts.nodates = True
diffopts.git = True
timeless
record: turn on showfunc...
r27411 diffopts.showfunc = True
timeless
cleanup: remove superfluous space after space after equals (python)
r27637 originaldiff = patch.diff(repo, changes=status, opts=diffopts)
Laurent Charignon
record: change interface of the filtering function...
r24341 originalchunks = patch.parsepatch(originaldiff)
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272
Jordi Gutiérrez Hermoso
crecord: rewrite a comment about filtering patches...
r28570 # 1. filter patch, since we are intending to apply subset of it
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 try:
Laurent Charignon
commit: add a way to return more information from the chunkselector...
r27155 chunks, newopts = filterfn(ui, originalchunks)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except patch.PatchError as err:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('error parsing patch: %s') % err)
Laurent Charignon
commit: add a way to return more information from the chunkselector...
r27155 opts.update(newopts)
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272
Laurent Charignon
record: edit patch of newly added files (issue4304)...
r24845 # We need to keep a backup of files that have been newly added and
# modified during the recording process because there is a previous
# version without the edit in the workdir
Laurent Charignon
record: extract code to compute newly added and modified files...
r25257 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 contenders = set()
for h in chunks:
try:
contenders.update(set(h.files()))
except AttributeError:
pass
changed = status.modified + status.added + status.removed
newfiles = [f for f in changed if f in contenders]
if not newfiles:
ui.status(_('no changes to record\n'))
return 0
modified = set(status.modified)
# 2. backup changed files, so we can restore them in the end
if backupall:
tobackup = changed
else:
Laurent Charignon
record: edit patch of newly added files (issue4304)...
r24845 tobackup = [f for f in newfiles if f in modified or f in \
newlyaddedandmodifiedfiles]
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 backups = {}
if tobackup:
backupdir = repo.join('record-backups')
try:
os.mkdir(backupdir)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as err:
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 if err.errno != errno.EEXIST:
raise
try:
# backup continues
for f in tobackup:
fd, tmpname = tempfile.mkstemp(prefix=f.replace('/', '_')+'.',
dir=backupdir)
os.close(fd)
ui.debug('backup %r as %r\n' % (f, tmpname))
Siddharth Agarwal
record: don't dereference symlinks while copying over stat data...
r27370 util.copyfile(repo.wjoin(f), tmpname, copystat=True)
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 backups[f] = tmpname
timeless
pycompat: switch to util.stringio for py3 compat
r28861 fp = stringio()
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 for c in chunks:
fname = c.filename()
Laurent Charignon
record: fix record with change on moved file crashes (issue4619)...
r24837 if fname in backups:
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 c.write(fp)
dopatch = fp.tell()
fp.seek(0)
Jordi Gutiérrez Hermoso
crecord: re-enable reviewing a patch before comitting it...
r28638 # 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, "",
extra={"suffix": ".diff"})
fp.truncate(0)
fp.write(reviewedpatch)
fp.seek(0)
Laurent Charignon
record: fix adding new file with record from within a subdir (issue4626)...
r24866 [os.unlink(repo.wjoin(c)) for c in newlyaddedandmodifiedfiles]
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 # 3a. apply filtered patch to clean repo (clean)
if backups:
# Equivalent to hg.revert
Augie Fackler
merge: have merge.update use a matcher instead of partial fn...
r27344 m = scmutil.matchfiles(repo, backups.keys())
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 mergemod.update(repo, repo.dirstate.p1(),
Augie Fackler
merge: have merge.update use a matcher instead of partial fn...
r27344 False, True, matcher=m)
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272
# 3b. (apply)
if dopatch:
try:
ui.debug('applying patch\n')
ui.debug(fp.getvalue())
patch.internalpatch(ui, repo, fp, 1, eolmode=None)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except patch.PatchError as err:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(str(err))
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 del fp
# 4. We prepared working directory according to filtered
# patch. Now is the time to delegate the job to
# commit/qrefresh or the like!
# Make all of the pathnames absolute.
newfiles = [repo.wjoin(nf) for nf in newfiles]
Laurent Charignon
record: change return value of recording code...
r24476 return commitfunc(ui, repo, *newfiles, **opts)
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 finally:
# 5. finally restore backed-up files
try:
FUJIWARA Katsunori
cmdutil: apply dirstate.normallookup on (maybe partially) committed files...
r25759 dirstate = repo.dirstate
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 for realname, tmpname in backups.iteritems():
ui.debug('restoring %r to %r\n' % (tmpname, realname))
FUJIWARA Katsunori
cmdutil: apply dirstate.normallookup on (maybe partially) committed files...
r25759
if dirstate[realname] == 'n':
# without normallookup, restoring timestamp
# may cause partially committed files
# to be treated as unmodified
dirstate.normallookup(realname)
Siddharth Agarwal
record: don't dereference symlinks while copying over stat data...
r27370 # copystat=True here and above are a hack to trick any
# editors that have f open that we haven't modified them.
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 #
Siddharth Agarwal
record: don't dereference symlinks while copying over stat data...
r27370 # Also note that this racy as an editor could notice the
# file's mtime before we've finished writing it.
util.copyfile(tmpname, repo.wjoin(realname), copystat=True)
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272 os.unlink(tmpname)
if tobackup:
os.rmdir(backupdir)
except OSError:
pass
FUJIWARA Katsunori
cmdutil: put recordfunc invocation into wlock scope for consistency...
r25758 def recordinwlock(ui, repo, message, match, opts):
Bryan O'Sullivan
with: use context manager for wlock in recordinwlock
r27801 with repo.wlock():
FUJIWARA Katsunori
cmdutil: put recordfunc invocation into wlock scope for consistency...
r25758 return recordfunc(ui, repo, message, match, opts)
return commit(ui, repo, recordinwlock, pats, opts)
Laurent Charignon
record: move dorecord from record to cmdutil...
r24272
Matt Mackall
findcmd: have dispatch look up strict flag
r7213 def findpossible(cmd, table, strict=False):
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 """
Return cmd -> (aliases, command table entry)
for each matching command.
Return debug commands (or their aliases) only if no normal command matches.
"""
choice = {}
debugchoice = {}
Matt Mackall
alias: shortcut command matching show shadowing works properly (issue3104)...
r15600
if cmd in table:
# short-circuit exact matches, "log" alias beats "^log|history"
keys = [cmd]
else:
keys = table.keys()
Augie Fackler
dispatch: offer suggestions of similar-named commands...
r24222 allcmds = []
Matt Mackall
alias: shortcut command matching show shadowing works properly (issue3104)...
r15600 for e in keys:
Brendan Cully
mq: add -Q option to all commands not in norepo
r10401 aliases = parsealiases(e)
Augie Fackler
dispatch: offer suggestions of similar-named commands...
r24222 allcmds.extend(aliases)
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 found = None
if cmd in aliases:
found = cmd
Matt Mackall
findcmd: have dispatch look up strict flag
r7213 elif not strict:
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 for a in aliases:
if a.startswith(cmd):
found = a
break
if found is not None:
if aliases[0].startswith("debug") or found.startswith("debug"):
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 debugchoice[found] = (aliases, table[e])
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 else:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 choice[found] = (aliases, table[e])
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549
if not choice and debugchoice:
choice = debugchoice
Augie Fackler
dispatch: offer suggestions of similar-named commands...
r24222 return choice, allcmds
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549
Matt Mackall
findcmd: have dispatch look up strict flag
r7213 def findcmd(cmd, table, strict=True):
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 """Return (aliases, command table entry) for command string."""
Augie Fackler
dispatch: offer suggestions of similar-named commands...
r24222 choice, allcmds = findpossible(cmd, table, strict)
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549
Christian Ebert
Prefer i in d over d.has_key(i)
r5915 if cmd in choice:
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 return choice[cmd]
if len(choice) > 1:
clist = choice.keys()
clist.sort()
Matt Mackall
error: move UnknownCommand and AmbiguousCommand
r7643 raise error.AmbiguousCommand(cmd, clist)
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549
if choice:
return choice.values()[0]
Augie Fackler
dispatch: offer suggestions of similar-named commands...
r24222 raise error.UnknownCommand(cmd, allcmds)
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549
Brendan Cully
mq: make init -Q do what qinit -c did
r10402 def findrepo(p):
while not os.path.isdir(os.path.join(p, ".hg")):
oldp, p = p, os.path.dirname(p)
if p == oldp:
return None
return p
FUJIWARA Katsunori
cmdutil: allow bailifchanged to ignore merging in progress...
r24472 def bailifchanged(repo, merge=True):
if merge and repo.dirstate.p2() != nullid:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('outstanding uncommitted merge'))
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 modified, added, removed, deleted = repo.status()[:4]
if modified or added or removed or deleted:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('uncommitted changes'))
Eric Roshan Eisner
cmdutil.bailifchanged: abort for dirty subrepos
r15231 ctx = repo[None]
Mads Kiilerich
subrepos: process subrepos in sorted order...
r18364 for s in sorted(ctx.substate):
FUJIWARA Katsunori
subrepo: add bailifchanged to centralize raising Abort if subrepo is dirty...
r24471 ctx.sub(s).bailifchanged()
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549
Idan Kamara
cmdutil, logmessage: use ui.fin when reading from '-'
r14635 def logmessage(ui, opts):
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 """ get the log message according to -m and -l option """
Alexander Solovyov
cmdutil.logmessage: options should be optional
r7667 message = opts.get('message')
logfile = opts.get('logfile')
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549
if message and logfile:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('options --message and --logfile are mutually '
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 'exclusive'))
if not message and logfile:
try:
if logfile == '-':
Idan Kamara
cmdutil, logmessage: use ui.fin when reading from '-'
r14635 message = ui.fin.read()
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 else:
Patrick Mezard
cmdutil: normalize log message eols when reading from file...
r14249 message = '\n'.join(util.readfile(logfile).splitlines())
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("can't read commit message '%s': %s") %
Matt Mackall
dispatch: move dispatching code to cmdutil
r4549 (logfile, inst.strerror))
return message
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r24180 def mergeeditform(ctxorbool, baseformname):
"""return appropriate editform name (referencing a committemplate)
'ctxorbool' is either a ctx to be committed, or a bool indicating whether
FUJIWARA Katsunori
commit: change "editform" to distinguish merge commits from others...
r22248 merging is committed.
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r24180 This returns baseformname with '.merge' appended if it is a merge,
otherwise '.normal' is appended.
FUJIWARA Katsunori
commit: change "editform" to distinguish merge commits from others...
r22248 """
if isinstance(ctxorbool, bool):
if ctxorbool:
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r24180 return baseformname + ".merge"
FUJIWARA Katsunori
commit: change "editform" to distinguish merge commits from others...
r22248 elif 1 < len(ctxorbool.parents()):
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r24180 return baseformname + ".merge"
return baseformname + ".normal"
FUJIWARA Katsunori
commit: change "editform" to distinguish merge commits from others...
r22248
FUJIWARA Katsunori
cmdutil: introduce 'editform' to distinguish the purpose of commit text editing...
r21999 def getcommiteditor(edit=False, finishdesc=None, extramsg=None,
editform='', **opts):
FUJIWARA Katsunori
cmdutil: enhance "getcommiteditor()" for specific usages in MQ...
r21419 """get appropriate commit message editor according to '--edit' option
'finishdesc' is a function to be called with edited commit message
(= 'description' of the new changeset) just after editing, but
before checking empty-ness. It should return actual text to be
stored into history. This allows to change description before
storing.
'extramsg' is a extra message to be shown in the editor instead of
'Leave message empty to abort commit' line. 'HG: ' prefix and EOL
is automatically added.
FUJIWARA Katsunori
cmdutil: introduce 'editform' to distinguish the purpose of commit text editing...
r21999 'editform' is a dot-separated list of names, to distinguish
the purpose of commit text editing.
FUJIWARA Katsunori
cmdutil: enhance "getcommiteditor()" for specific usages in MQ...
r21419 'getcommiteditor' returns 'commitforceeditor' regardless of
'edit', if one of 'finishdesc' or 'extramsg' is specified, because
they are specific for usage in MQ.
"""
if edit or finishdesc or extramsg:
return lambda r, c, s: commitforceeditor(r, c, s,
finishdesc=finishdesc,
FUJIWARA Katsunori
cmdutil: introduce 'editform' to distinguish the purpose of commit text editing...
r21999 extramsg=extramsg,
editform=editform)
elif editform:
return lambda r, c, s: commiteditor(r, c, s, editform=editform)
FUJIWARA Katsunori
cmdutil: introduce "getcommiteditor()" to simplify code paths to choose editor...
r21405 else:
return commiteditor
Thomas Arendsen Hein
Move finding/checking the log limit to cmdutil
r6190 def loglimit(opts):
"""get the log limit according to option -l/--limit"""
limit = opts.get('limit')
if limit:
try:
limit = int(limit)
except ValueError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('limit must be a positive integer'))
Matt Mackall
many, many trivial check-code fixups
r10282 if limit <= 0:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('limit must be positive'))
Thomas Arendsen Hein
Move finding/checking the log limit to cmdutil
r6190 else:
Nicolas Dumazet
cmdutil: replace sys.maxint with None as default value in loglimit...
r10111 limit = None
Thomas Arendsen Hein
Move finding/checking the log limit to cmdutil
r6190 return limit
Andrzej Bieniek
export: add %m to file format string (first line of the commit message)...
r14986 def makefilename(repo, pat, node, desc=None,
Vadim Gelfer
refactor text diff/patch code....
r2874 total=None, seqno=None, revwidth=None, pathname=None):
node_expander = {
'H': lambda: hex(node),
'R': lambda: str(repo.changelog.rev(node)),
'h': lambda: short(node),
Andrzej Bieniek
export: add %m to file format string (first line of the commit message)...
r14986 'm': lambda: re.sub('[^\w]', '_', str(desc))
Vadim Gelfer
refactor text diff/patch code....
r2874 }
expander = {
'%': lambda: '%',
'b': lambda: os.path.basename(repo.root),
}
try:
if node:
expander.update(node_expander)
Alexis S. L. Carvalho
archive: make the %r escape work.
r4836 if node:
Vadim Gelfer
refactor text diff/patch code....
r2874 expander['r'] = (lambda:
Alexis S. L. Carvalho
archive: make the %r escape work.
r4836 str(repo.changelog.rev(node)).zfill(revwidth or 0))
Vadim Gelfer
refactor text diff/patch code....
r2874 if total is not None:
expander['N'] = lambda: str(total)
if seqno is not None:
expander['n'] = lambda: str(seqno)
if total is not None and seqno is not None:
Thomas Arendsen Hein
white space and line break cleanups
r3673 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
Vadim Gelfer
refactor text diff/patch code....
r2874 if pathname is not None:
expander['s'] = lambda: os.path.basename(pathname)
expander['d'] = lambda: os.path.dirname(pathname) or '.'
expander['p'] = lambda: pathname
newname = []
patlen = len(pat)
i = 0
while i < patlen:
c = pat[i]
if c == '%':
i += 1
c = pat[i]
c = expander[c]()
newname.append(c)
i += 1
return ''.join(newname)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except KeyError as inst:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("invalid format spec '%%%s' in output filename") %
Thomas Arendsen Hein
Never apply string formatting to generated errors with util.Abort....
r3072 inst.args[0])
Vadim Gelfer
refactor text diff/patch code....
r2874
Yuya Nishihara
cmdutil: reimplement file wrapper that disables close()...
r27418 class _unclosablefile(object):
def __init__(self, fp):
self._fp = fp
def close(self):
pass
def __iter__(self):
return iter(self._fp)
def __getattr__(self, attr):
return getattr(self._fp, attr)
Mads Kiilerich
largefiles: use context for file closing...
r30142 def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, exc_tb):
pass
Andrzej Bieniek
export: add %m to file format string (first line of the commit message)...
r14986 def makefileobj(repo, pat, node=None, desc=None, total=None,
Yuya Nishihara
cmdutil: fix makefileobj not to clobber default modemap dict...
r19944 seqno=None, revwidth=None, mode='wb', modemap=None,
Augie Fackler
export: clobber files with -o (bc) (issue3652)...
r18613 pathname=None):
Ronny Pfannschmidt
export: fixed silent output file overwriting...
r7319
Adrian Buehlmann
cmdutil: fix mode handling in make_file
r13769 writable = mode not in ('r', 'rb')
Ronny Pfannschmidt
export: fixed silent output file overwriting...
r7319
Vadim Gelfer
refactor text diff/patch code....
r2874 if not pat or pat == '-':
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if writable:
fp = repo.ui.fout
else:
fp = repo.ui.fin
Yuya Nishihara
cmdutil: do not duplicate stdout by makefileobj()...
r27419 return _unclosablefile(fp)
Augie Fackler
cmdutil: use safehasattr instead of hasattr
r14948 if util.safehasattr(pat, 'write') and writable:
Vadim Gelfer
refactor text diff/patch code....
r2874 return pat
Augie Fackler
cmdutil: use safehasattr instead of hasattr
r14948 if util.safehasattr(pat, 'read') and 'r' in mode:
Vadim Gelfer
refactor text diff/patch code....
r2874 return pat
Augie Fackler
export: clobber files with -o (bc) (issue3652)...
r18613 fn = makefilename(repo, pat, node, desc, total, seqno, revwidth, pathname)
Yuya Nishihara
cmdutil: fix makefileobj not to clobber default modemap dict...
r19944 if modemap is not None:
mode = modemap.get(fn, mode)
if mode == 'wb':
modemap[fn] = 'ab'
Augie Fackler
export: clobber files with -o (bc) (issue3652)...
r18613 return open(fn, mode)
Vadim Gelfer
move walk and matchpats from commands to cmdutil.
r2882
Sune Foldager
debugindex etc.: add --changelog and --manifest options...
r14323 def openrevlog(repo, cmd, file_, opts):
"""opens the changelog, manifest, a filelog or a given revlog"""
cl = opts['changelog']
mf = opts['manifest']
Martin von Zweigbergk
treemanifest: add --dir option to debug{revlog,data,index}...
r25119 dir = opts['dir']
Sune Foldager
debugindex etc.: add --changelog and --manifest options...
r14323 msg = None
if cl and mf:
msg = _('cannot specify --changelog and --manifest at the same time')
Martin von Zweigbergk
treemanifest: add --dir option to debug{revlog,data,index}...
r25119 elif cl and dir:
msg = _('cannot specify --changelog and --dir at the same time')
Martin von Zweigbergk
debug: make debug{revlog,index,data} --dir not just a flag...
r29427 elif cl or mf or dir:
Sune Foldager
debugindex etc.: add --changelog and --manifest options...
r14323 if file_:
msg = _('cannot specify filename with --changelog or --manifest')
elif not repo:
Martin von Zweigbergk
treemanifest: add --dir option to debug{revlog,data,index}...
r25119 msg = _('cannot specify --changelog or --manifest or --dir '
Sune Foldager
debugindex etc.: add --changelog and --manifest options...
r14323 'without a repository')
if msg:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(msg)
Sune Foldager
debugindex etc.: add --changelog and --manifest options...
r14323
r = None
if repo:
if cl:
Matt Mackall
debugrevlog: use unfiltered view for changelog
r21033 r = repo.unfiltered().changelog
Martin von Zweigbergk
treemanifest: add --dir option to debug{revlog,data,index}...
r25119 elif dir:
if 'treemanifest' not in repo.requirements:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("--dir can only be used on repos with "
Martin von Zweigbergk
treemanifest: add --dir option to debug{revlog,data,index}...
r25119 "treemanifest enabled"))
Durham Goode
manifest: delete unused dirlog and _newmanifest functions...
r30371 dirlog = repo.manifestlog._revlog.dirlog(dir)
Martin von Zweigbergk
treemanifest: add --dir option to debug{revlog,data,index}...
r25119 if len(dirlog):
r = dirlog
Sune Foldager
debugindex etc.: add --changelog and --manifest options...
r14323 elif mf:
Durham Goode
manifest: remove last uses of repo.manifest...
r30375 r = repo.manifestlog._revlog
Sune Foldager
debugindex etc.: add --changelog and --manifest options...
r14323 elif file_:
filelog = repo.file(file_)
if len(filelog):
r = filelog
if not r:
if not file_:
raise error.CommandError(cmd, _('invalid arguments'))
if not os.path.isfile(file_):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("revlog '%s' not found") % file_)
Sune Foldager
debugindex etc.: add --changelog and --manifest options...
r14323 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False),
file_[:-2] + ".i")
return r
Matt Mackall
copy: handle rename internally...
r5610 def copy(ui, repo, pats, opts, rename=False):
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 # called with the repo lock held
#
# hgsep => pathname that uses "/" to separate directories
# ossep => pathname that uses os.sep to separate directories
cwd = repo.getcwd()
targets = {}
Matt Mackall
copy: minor cleanups...
r5607 after = opts.get("after")
dryrun = opts.get("dry_run")
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 wctx = repo[None]
Matt Mackall
move commands.docopy to cmdutil.copy
r5589
Matt Mackall
copy: refactor okaytocopy into walkpat...
r5605 def walkpat(pat):
srcs = []
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if after:
badstates = '?'
else:
badstates = '?r'
Matt Mackall
scmutil: switch match users to supplying contexts...
r14671 m = scmutil.match(repo[None], [pat], opts, globbed=True)
Matt Mackall
walk: return a single value
r6586 for abs in repo.walk(m):
Matt Mackall
copy: refactor okaytocopy into walkpat...
r5605 state = repo.dirstate[abs]
Matt Mackall
walk: remove rel and exact returns
r6584 rel = m.rel(abs)
exact = m.exact(abs)
Peter Arrenbrecht
rename: make --after work if source is already in R state...
r11223 if state in badstates:
Matt Mackall
copy: refactor okaytocopy into walkpat...
r5605 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)
continue
# abs: hgsep
# rel: ossep
srcs.append((abs, rel, exact))
return srcs
Matt Mackall
move commands.docopy to cmdutil.copy
r5589
# abssrc: hgsep
# relsrc: ossep
# otarget: ossep
Matt Mackall
copy: refactor okaytocopy into walkpat...
r5605 def copyfile(abssrc, relsrc, otarget, exact):
Augie Fackler
pathutil: tease out a new library to break an import cycle from canonpath use
r20033 abstarget = pathutil.canonpath(repo.root, cwd, otarget)
Patrick Mezard
dirstate: preserve path components case on renames (issue3402)...
r16542 if '/' in abstarget:
# We cannot normalize abstarget itself, this would prevent
# case only renames, like a => A.
abspath, absname = abstarget.rsplit('/', 1)
abstarget = repo.dirstate.normalize(abspath) + '/' + absname
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 reltarget = repo.pathto(abstarget, cwd)
Matt Mackall
copy: minor cleanups...
r5607 target = repo.wjoin(abstarget)
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 src = repo.wjoin(abssrc)
Matt Mackall
copy: simplify inner copy...
r5608 state = repo.dirstate[abstarget]
Matt Mackall
copy: minor cleanups...
r5607
Adrian Buehlmann
add: introduce a warning message for non-portable filenames (issue2756) (BC)...
r13962 scmutil.checkportable(ui, abstarget)
Adrian Buehlmann
copy: do not copy file if name is disallowed anyway
r13945
Matt Mackall
copy: minor cleanups...
r5607 # check for collisions
prevsrc = targets.get(abstarget)
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 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
Matt Mackall
copy: minor cleanups...
r5607
# check for overwrites
Patrick Mezard
rename: do not overwrite existing broken symlinks
r12342 exists = os.path.lexists(target)
Matt Mackall
rename: handle case-changing (issue1717)
r16283 samefile = False
if exists and abssrc != abstarget:
if (repo.dirstate.normalize(abssrc) ==
repo.dirstate.normalize(abstarget)):
if not rename:
ui.warn(_("%s: can't copy - same file\n") % reltarget)
return
exists = False
samefile = True
Martin Geisler
remove unnecessary outer parenthesis in if-statements
r8117 if not after and exists or after and state in 'mn':
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 if not opts['force']:
Augie Fackler
copy: distinguish "file exists" cases and add a hint (BC)...
r30151 if state in 'mn':
msg = _('%s: not overwriting - file already committed\n')
if after:
flags = '--after --force'
else:
flags = '--force'
if rename:
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
else:
msg = _('%s: not overwriting - file exists\n')
if rename:
hint = _('(hg rename --after to record the rename)\n')
else:
hint = _('(hg copy --after to record the copy)\n')
ui.warn(msg % reltarget)
ui.warn(hint)
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 return
Matt Mackall
copy: minor cleanups...
r5607
if after:
Matt Mackall
copy: simplify inner copy...
r5608 if not exists:
Steve Losh
cmdutil: Warn when trying to copy/rename --after to a nonexistant file....
r11152 if rename:
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))
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 return
Matt Mackall
copy: simplify inner copy...
r5608 elif not dryrun:
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 try:
Matt Mackall
copy: simplify inner copy...
r5608 if exists:
os.unlink(target)
targetdir = os.path.dirname(target) or '.'
if not os.path.isdir(targetdir):
os.makedirs(targetdir)
Matt Mackall
rename: handle case-changing (issue1717)
r16283 if samefile:
tmp = target + "~hgrename"
os.rename(src, tmp)
os.rename(tmp, target)
else:
util.copyfile(src, target)
Adrian Buehlmann
workingctx: eliminate remove function...
r14518 srcexists = True
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 if inst.errno == errno.ENOENT:
Yuya Nishihara
commands: replace "working copy" with "working directory" in help/messages...
r24364 ui.warn(_('%s: deleted in working directory\n') % relsrc)
Adrian Buehlmann
workingctx: eliminate remove function...
r14518 srcexists = False
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 else:
ui.warn(_('%s: cannot copy - %s\n') %
(relsrc, inst.strerror))
Matt Mackall
copy: propagate errors properly
r5606 return True # report a failure
Matt Mackall
copy: minor cleanups...
r5607
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 if ui.verbose or not exact:
Martin Geisler
cmdutil: fix untranslatable string in copy
r7894 if rename:
ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
else:
ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
Matt Mackall
copy: simplify inner copy...
r5608
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 targets[abstarget] = abssrc
Matt Mackall
copy: minor cleanups...
r5607
# fix up dirstate
Matt Mackall
scmutil: drop some aliases in cmdutil
r14321 scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
dryrun=dryrun, cwd=cwd)
Matt Mackall
copy: handle rename internally...
r5610 if rename and not dryrun:
Matt Mackall
rename: handle case-changing (issue1717)
r16283 if not after and srcexists and not samefile:
Adrian Buehlmann
workingctx: eliminate remove function...
r14518 util.unlinkpath(repo.wjoin(abssrc))
wctx.forget([abssrc])
Matt Mackall
move commands.docopy to cmdutil.copy
r5589
# pat: ossep
# dest ossep
# srcs: list of (hgsep, hgsep, ossep, bool)
# return: function that takes hgsep and returns ossep
def targetpathfn(pat, dest, srcs):
if os.path.isdir(pat):
Augie Fackler
pathutil: tease out a new library to break an import cycle from canonpath use
r20033 abspfx = pathutil.canonpath(repo.root, cwd, pat)
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 abspfx = util.localpath(abspfx)
if destdirexists:
striplen = len(os.path.split(abspfx)[0])
else:
striplen = len(abspfx)
if striplen:
striplen += len(os.sep)
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)))
else:
res = lambda p: dest
return res
# pat: ossep
# dest ossep
# srcs: list of (hgsep, hgsep, ossep, bool)
# return: function that takes hgsep and returns ossep
def targetpathafterfn(pat, dest, srcs):
Martin Geisler
Consistently import foo as foomod when foo to avoid shadowing...
r12085 if matchmod.patkind(pat):
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 # a mercurial pattern
res = lambda p: os.path.join(dest,
os.path.basename(util.localpath(p)))
else:
Augie Fackler
pathutil: tease out a new library to break an import cycle from canonpath use
r20033 abspfx = pathutil.canonpath(repo.root, cwd, pat)
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 if len(abspfx) < len(srcs[0][0]):
# A directory. Either the target path contains the last
# component of the source path or it does not.
def evalpath(striplen):
score = 0
for s in srcs:
t = os.path.join(dest, util.localpath(s[0])[striplen:])
Patrick Mezard
Restore lexists() changes lost in e0ee3e822a9a merge
r12357 if os.path.lexists(t):
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 score += 1
return score
abspfx = util.localpath(abspfx)
striplen = len(abspfx)
if striplen:
striplen += len(os.sep)
if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
score = evalpath(striplen)
striplen1 = len(os.path.split(abspfx)[0])
if striplen1:
striplen1 += len(os.sep)
if evalpath(striplen1) > score:
striplen = striplen1
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)))
else:
res = lambda p: dest
return res
Matt Mackall
scmutil: drop some aliases in cmdutil
r14321 pats = scmutil.expandpats(pats)
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 if not pats:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('no source or destination specified'))
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 if len(pats) == 1:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('no destination specified'))
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 dest = pats.pop()
Alexis S. L. Carvalho
Fix issue995 (copy --after and symlinks pointing to a directory)...
r6258 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 if not destdirexists:
Martin Geisler
Consistently import foo as foomod when foo to avoid shadowing...
r12085 if len(pats) > 1 or matchmod.patkind(pats[0]):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('with multiple sources, destination must be an '
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 'existing directory'))
Shun-ichi GOTO
Add endswithsep() and use it instead of using os.sep and os.altsep directly....
r5843 if util.endswithsep(dest):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('destination %s is not a directory') % dest)
Matt Mackall
copy: minor cleanups...
r5607
tfn = targetpathfn
if after:
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 tfn = targetpathafterfn
copylist = []
for pat in pats:
Matt Mackall
copy: refactor okaytocopy into walkpat...
r5605 srcs = walkpat(pat)
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 if not srcs:
continue
copylist.append((tfn(pat, dest, srcs), srcs))
if not copylist:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('no files to copy'))
Matt Mackall
move commands.docopy to cmdutil.copy
r5589
Matt Mackall
copy: propagate errors properly
r5606 errors = 0
Matt Mackall
move commands.docopy to cmdutil.copy
r5589 for targetpath, srcs in copylist:
Matt Mackall
copy: refactor okaytocopy into walkpat...
r5605 for abssrc, relsrc, exact in srcs:
Matt Mackall
copy: propagate errors properly
r5606 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
errors += 1
Matt Mackall
move commands.docopy to cmdutil.copy
r5589
if errors:
ui.warn(_('(consider using --after)\n'))
Matt Mackall
copy: move rename logic
r5609
Matt Mackall
commands: initial audit of exit codes...
r11177 return errors != 0
Matt Mackall
move commands.docopy to cmdutil.copy
r5589
Nicolas Dumazet
cmdutil: service: add an optional runargs argument to pass the command to run...
r9513 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
Nicolas Dumazet
cmdutil: service: add appendpid parameter to append pids to pid file
r10012 runargs=None, appendpid=False):
Bryan O'Sullivan
Refactor commands.serve to allow other commands to run as services....
r4380 '''Run a command as a service.'''
Siddharth Agarwal
cmdutil.service: move pidfile writing to a local function...
r19867 def writepid(pid):
if opts['pid_file']:
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if appendpid:
mode = 'a'
else:
mode = 'w'
Siddharth Agarwal
cmdutil.service: move pidfile writing to a local function...
r19867 fp = open(opts['pid_file'], mode)
fp.write(str(pid) + '\n')
fp.close()
Jun Wu
serve: rename --daemon-pipefds to --daemon-postexec (BC)...
r28194 if opts['daemon'] and not opts['daemon_postexec']:
Patrick Mezard
cmdutil: replace unix pipe handshake with file lock...
r10238 # Signal child process startup with file removal
lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
Matt Mackall
many, many trivial check-code fixups
r10282 os.close(lockfd)
Patrick Mezard
cmdutil: replace unix pipe handshake with file lock...
r10238 try:
if not runargs:
Patrick Mezard
Find right hg command for detached process...
r10239 runargs = util.hgcmd() + sys.argv[1:]
Jun Wu
serve: allow --daemon-postexec to be 'unlink:path' or 'none'...
r28195 runargs.append('--daemon-postexec=unlink:%s' % lockpath)
Patrick Mezard
cmdutil: replace unix pipe handshake with file lock...
r10238 # Don't pass --cwd to the child process, because we've already
# changed directory.
Matt Mackall
many, many trivial check-code fixups
r10282 for i in xrange(1, len(runargs)):
Patrick Mezard
cmdutil: replace unix pipe handshake with file lock...
r10238 if runargs[i].startswith('--cwd='):
del runargs[i]
break
elif runargs[i].startswith('--cwd'):
Matt Mackall
many, many trivial check-code fixups
r10282 del runargs[i:i + 2]
Patrick Mezard
cmdutil: replace unix pipe handshake with file lock...
r10238 break
Patrick Mezard
util: make spawndetached() handle subprocess early terminations...
r10344 def condfn():
return not os.path.exists(lockpath)
pid = util.rundetached(runargs, condfn)
if pid < 0:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('child process failed to start'))
Siddharth Agarwal
cmdutil.service: move pidfile writing to the parent in daemon mode...
r19868 writepid(pid)
Patrick Mezard
cmdutil: replace unix pipe handshake with file lock...
r10238 finally:
try:
os.unlink(lockpath)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as e:
Patrick Mezard
cmdutil: replace unix pipe handshake with file lock...
r10238 if e.errno != errno.ENOENT:
raise
Bryan O'Sullivan
Refactor commands.serve to allow other commands to run as services....
r4380 if parentfn:
return parentfn(pid)
else:
Nicolas Dumazet
cmdutil.service: do not _exit(0) in the parent process...
r9896 return
Bryan O'Sullivan
Refactor commands.serve to allow other commands to run as services....
r4380
if initfn:
initfn()
Siddharth Agarwal
cmdutil.service: move pidfile writing to the parent in daemon mode...
r19868 if not opts['daemon']:
timeless
util: enable getpid to be replaced...
r28027 writepid(util.getpid())
Bryan O'Sullivan
Refactor commands.serve to allow other commands to run as services....
r4380
Jun Wu
serve: rename --daemon-pipefds to --daemon-postexec (BC)...
r28194 if opts['daemon_postexec']:
Bryan O'Sullivan
Refactor commands.serve to allow other commands to run as services....
r4380 try:
os.setsid()
except AttributeError:
pass
Jun Wu
serve: accept multiple values for --daemon-postexec...
r28451 for inst in opts['daemon_postexec']:
if inst.startswith('unlink:'):
lockpath = inst[7:]
os.unlink(lockpath)
Jun Wu
serve: add chdir command for --daemon-postexec...
r28452 elif inst.startswith('chdir:'):
os.chdir(inst[6:])
Jun Wu
serve: accept multiple values for --daemon-postexec...
r28451 elif inst != 'none':
raise error.Abort(_('invalid value for --daemon-postexec: %s')
% inst)
Patrick Mezard
cmdutil: hide child window created by win32 spawndetached()...
r10240 util.hidewindow()
Yuya Nishihara
py3: bulk replace sys.stdin/out/err by util's...
r30473 util.stdout.flush()
util.stderr.flush()
Nicolas Dumazet
cmdutil: service: logfile option to redirect stdout & stderr in a file
r8789
Ross Lagerwall
util: replace util.nulldev with os.devnull...
r17391 nullfd = os.open(os.devnull, os.O_RDWR)
Nicolas Dumazet
cmdutil: service: logfile option to redirect stdout & stderr in a file
r8789 logfilefd = nullfd
if logfile:
logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
os.dup2(nullfd, 0)
os.dup2(logfilefd, 1)
os.dup2(logfilefd, 2)
if nullfd not in (0, 1, 2):
os.close(nullfd)
if logfile and logfilefd not in (0, 1, 2):
os.close(logfilefd)
Bryan O'Sullivan
Refactor commands.serve to allow other commands to run as services....
r4380
if runfn:
return runfn()
Pierre-Yves David
import: allow processing of extra part header during import...
r26561 ## facility to let extension process additional data into an import patch
# list of identifier to be executed in order
extrapreimport = [] # run before commit
Pierre-Yves David
import: allow processing of extra part header after import...
r26562 extrapostimport = [] # run after commit
Pierre-Yves David
import: allow processing of extra part header during import...
r26561 # mapping from identifier to actual import function
#
# 'preimport' are run before the commit is made and are provided the following
# arguments:
# - repo: the localrepository instance,
# - patchdata: data extracted from patch header (cf m.patch.patchheadermap),
Mads Kiilerich
spelling: trivial spell checking
r26781 # - extra: the future extra dictionary of the changeset, please mutate it,
Pierre-Yves David
import: allow processing of extra part header during import...
r26561 # - opts: the import options.
# XXX ideally, we would just pass an ctx ready to be computed, that would allow
# mutation of in memory commit and more. Feel free to rework the code to get
# there.
extrapreimportmap = {}
Pierre-Yves David
import: allow processing of extra part header after import...
r26562 # 'postimport' are run after the commit is made and are provided the following
# argument:
# - ctx: the changectx created by import.
extrapostimportmap = {}
Pierre-Yves David
import: allow processing of extra part header during import...
r26561
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 def tryimportone(ui, repo, hunk, parents, opts, msgs, updatefunc):
"""Utility function used by commands.import to import a single patch
This function is explicitly defined here to help the evolve extension to
wrap this part of the import logic.
The API is currently a bit ugly because it a simple code translation from
the import command. Feel free to make it better.
:hunk: a patch (as a binary string)
:parents: nodes that will be parent of the created commit
:opts: the full dict of option passed to the import command
:msgs: list to save commit message to.
(used in case we need to save it when failing)
:updatefunc: a function that update a repo to a given node
updatefunc(<repo>, <node>)
"""
Gregory Szorc
cmdutil: break import cycle...
r25930 # avoid cycle context -> subrepo -> cmdutil
Gregory Szorc
cmdutil: use absolute_import...
r28322 from . import context
Pierre-Yves David
patch: move 'extract' return to a dictionnary...
r26547 extractdata = patch.extract(ui, hunk)
tmpname = extractdata.get('filename')
message = extractdata.get('message')
timeless
import: refactor date and user handling
r27612 user = opts.get('user') or extractdata.get('user')
date = opts.get('date') or extractdata.get('date')
Pierre-Yves David
patch: move 'extract' return to a dictionnary...
r26547 branch = extractdata.get('branch')
nodeid = extractdata.get('nodeid')
p1 = extractdata.get('p1')
p2 = extractdata.get('p2')
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500
timeless
import: refactor nocommit and importbranch handling
r27613 nocommit = opts.get('no_commit')
importbranch = opts.get('import_branch')
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 update = not opts.get('bypass')
strip = opts["strip"]
Siddharth Agarwal
cmdutil.tryimportone: allow importing relative patches into the working dir...
r24259 prefix = opts["prefix"]
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 sim = float(opts.get('similarity') or 0)
if not tmpname:
Pierre-Yves David
import: add --partial flag to create a changeset despite failed hunks...
r21553 return (None, None, False)
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500
Pierre-Yves David
import: add --partial flag to create a changeset despite failed hunks...
r21553 rejects = False
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 try:
cmdline_message = logmessage(ui, opts)
if cmdline_message:
# pickup the cmdline msg
message = cmdline_message
elif message:
# pickup the patch msg
message = message.strip()
else:
# launch the editor
message = None
ui.debug('message:\n%s\n' % message)
if len(parents) == 1:
parents.append(repo[nullid])
if opts.get('exact'):
if not nodeid or not p1:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('not a Mercurial patch'))
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 p1 = repo[p1]
p2 = repo[p2 or nullid]
elif p2:
try:
p1 = repo[p1]
p2 = repo[p2]
# Without any options, consider p2 only if the
# patch is being applied on top of the recorded
# first parent.
if p1 != parents[0]:
p1 = parents[0]
p2 = repo[nullid]
except error.RepoError:
p1, p2 = parents
FUJIWARA Katsunori
import: show the warning message for failure of merging...
r22303 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"))
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 else:
p1, p2 = parents
n = None
if update:
if p1 != parents[0]:
updatefunc(repo, p1.node())
if p2 != parents[1]:
repo.setparents(p1.node(), p2.node())
timeless
import: refactor nocommit and importbranch handling
r27613 if opts.get('exact') or importbranch:
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 repo.dirstate.setbranch(branch or 'default')
Pierre-Yves David
import: add --partial flag to create a changeset despite failed hunks...
r21553 partial = opts.get('partial', False)
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 files = set()
Pierre-Yves David
import: add --partial flag to create a changeset despite failed hunks...
r21553 try:
Siddharth Agarwal
cmdutil.tryimportone: allow importing relative patches into the working dir...
r24259 patch.patch(ui, repo, tmpname, strip=strip, prefix=prefix,
files=files, eolmode=None, similarity=sim / 100.0)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except patch.PatchError as e:
Pierre-Yves David
import: add --partial flag to create a changeset despite failed hunks...
r21553 if not partial:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(str(e))
Pierre-Yves David
import: add --partial flag to create a changeset despite failed hunks...
r21553 if partial:
rejects = True
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 files = list(files)
timeless
import: refactor nocommit and importbranch handling
r27613 if nocommit:
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 if message:
msgs.append(message)
else:
if opts.get('exact') or p2:
# If you got here, you either use --force and know what
# you are doing or used --exact or a merge patch while
# being updated to its first parent.
m = None
else:
m = scmutil.matchfiles(repo, files or [])
FUJIWARA Katsunori
import: change "editform" to distinguish merge commits from others...
r22250 editform = mergeeditform(repo[None], 'import.normal')
FUJIWARA Katsunori
import: avoid editor invocation when importing with "--exact" for exact-ness...
r22278 if opts.get('exact'):
editor = None
else:
editor = getcommiteditor(editform=editform, **opts)
Durham Goode
import: use ui.allowemptycommit to allow empty commits...
r25020 allowemptyback = repo.ui.backupconfig('ui', 'allowemptycommit')
Pierre-Yves David
import: allow processing of extra part header during import...
r26561 extra = {}
for idfunc in extrapreimport:
extrapreimportmap[idfunc](repo, extractdata, extra, opts)
Durham Goode
import: use ui.allowemptycommit to allow empty commits...
r25020 try:
if partial:
repo.ui.setconfig('ui', 'allowemptycommit', True)
timeless
import: refactor date and user handling
r27612 n = repo.commit(message, user,
date, match=m,
Pierre-Yves David
import: allow processing of extra part header during import...
r26561 editor=editor, extra=extra)
Pierre-Yves David
import: allow processing of extra part header after import...
r26562 for idfunc in extrapostimport:
extrapostimportmap[idfunc](repo[n])
Durham Goode
import: use ui.allowemptycommit to allow empty commits...
r25020 finally:
repo.ui.restoreconfig(allowemptyback)
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 else:
timeless
import: refactor nocommit and importbranch handling
r27613 if opts.get('exact') or importbranch:
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 branch = branch or 'default'
else:
branch = p1.branch()
store = patch.filestore()
try:
files = set()
try:
Siddharth Agarwal
cmdutil.tryimportone: allow importing relative patches with --bypass
r24260 patch.patchrepo(ui, repo, p1, store, tmpname, strip, prefix,
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 files, eolmode=None)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except patch.PatchError as e:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(str(e))
FUJIWARA Katsunori
import: avoid editor invocation when importing with "--exact" for exact-ness...
r22278 if opts.get('exact'):
editor = None
else:
editor = getcommiteditor(editform='import.bypass')
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 memctx = context.makememctx(repo, (p1.node(), p2.node()),
message,
timeless
import: refactor date and user handling
r27612 user,
date,
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 branch, files, store,
FUJIWARA Katsunori
import: pass 'editform' argument to 'cmdutil.getcommiteditor'...
r22011 editor=editor)
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 n = memctx.commit()
finally:
store.close()
timeless
import: refactor nocommit and importbranch handling
r27613 if opts.get('exact') and nocommit:
Matt Mackall
import: let --exact 'work' with --no-commit (issue4376)
r22485 # --exact with --no-commit is still useful in that it does merge
# and branch bits
ui.warn(_("warning: can't check exact import with --no-commit\n"))
elif opts.get('exact') and hex(n) != nodeid:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('patch is damaged or loses information'))
timeless
import: limit scope of msg in tryimportone
r27611 msg = _('applied to working directory')
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 if n:
# i18n: refers to a short changeset id
msg = _('created %s') % short(n)
Pierre-Yves David
import: add --partial flag to create a changeset despite failed hunks...
r21553 return (msg, n, rejects)
Pierre-Yves David
import: move tryone closure in cmdutil...
r20500 finally:
os.unlink(tmpname)
Pierre-Yves David
export: introduce a generic way to add patch header on export...
r26545 # facility to let extensions include additional data in an exported patch
# list of identifiers to be executed in order
extraexport = []
# mapping from identifier to actual export function
# function as to return a string to be added to the header or None
# it is given two arguments (sequencenumber, changectx)
extraexportmap = {}
Benoit Boissinot
patch/diff: move patch.export() to cmdutil.export()...
r10611 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
Matt Harbison
extdiff: enable -I/-X with --patch...
r26229 opts=None, match=None):
Benoit Boissinot
patch/diff: move patch.export() to cmdutil.export()...
r10611 '''export changesets as hg patches.'''
total = len(revs)
revwidth = max([len(str(rev)) for rev in revs])
Augie Fackler
export: clobber files with -o (bc) (issue3652)...
r18613 filemode = {}
Benoit Boissinot
patch/diff: move patch.export() to cmdutil.export()...
r10611
def single(rev, seqno, fp):
ctx = repo[rev]
node = ctx.node()
parents = [p.node() for p in ctx.parents() if p]
branch = ctx.branch()
if switch_parent:
parents.reverse()
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306
if parents:
prev = parents[0]
else:
prev = nullid
Benoit Boissinot
patch/diff: move patch.export() to cmdutil.export()...
r10611
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 shouldclose = False
Ankur Dahiya
color: enabled color support for export command (issue1507)...
r17460 if not fp and len(template) > 0:
Andrzej Bieniek
export: add %m to file format string (first line of the commit message)...
r14986 desc_lines = ctx.description().rstrip().split('\n')
desc = desc_lines[0] #Commit always has a first line.
fp = makefileobj(repo, template, node, desc=desc, total=total,
Augie Fackler
export: clobber files with -o (bc) (issue3652)...
r18613 seqno=seqno, revwidth=revwidth, mode='wb',
modemap=filemode)
Yuya Nishihara
export: remove useless comparison between file object and string...
r27417 shouldclose = True
Yuya Nishihara
export: do not print '<fdopen>' as an output filename...
r27416 if fp and not getattr(fp, 'name', '<unnamed>').startswith('<'):
Benoit Boissinot
patch/diff: move patch.export() to cmdutil.export()...
r10611 repo.ui.note("%s\n" % fp.name)
Ankur Dahiya
color: enabled color support for export command (issue1507)...
r17460 if not fp:
write = repo.ui.write
else:
def write(s, **kw):
fp.write(s)
write("# HG changeset patch\n")
write("# User %s\n" % ctx.user())
write("# Date %d %d\n" % ctx.date())
Mads Kiilerich
export: show 'Date' header in a format that also is readable for humans...
r18648 write("# %s\n" % util.datestr(ctx.date()))
Martin Geisler
cmdutil: remove unnecessary parenthesis
r11821 if branch and branch != 'default':
Ankur Dahiya
color: enabled color support for export command (issue1507)...
r17460 write("# Branch %s\n" % branch)
write("# Node ID %s\n" % hex(node))
write("# Parent %s\n" % hex(prev))
Benoit Boissinot
patch/diff: move patch.export() to cmdutil.export()...
r10611 if len(parents) > 1:
Ankur Dahiya
color: enabled color support for export command (issue1507)...
r17460 write("# Parent %s\n" % hex(parents[1]))
Pierre-Yves David
export: introduce a generic way to add patch header on export...
r26545
for headerid in extraexport:
header = extraexportmap[headerid](seqno, ctx)
if header is not None:
write('# %s\n' % header)
Ankur Dahiya
color: enabled color support for export command (issue1507)...
r17460 write(ctx.description().rstrip())
write("\n\n")
Benoit Boissinot
patch/diff: move patch.export() to cmdutil.export()...
r10611
Matt Harbison
extdiff: enable -I/-X with --patch...
r26229 for chunk, label in patch.diffui(repo, prev, node, match, opts=opts):
Ankur Dahiya
color: enabled color support for export command (issue1507)...
r17460 write(chunk, label=label)
Benoit Boissinot
patch/diff: move patch.export() to cmdutil.export()...
r10611
Dan Villiom Podlaski Christiansen
explicitly close files...
r13400 if shouldclose:
fp.close()
Dan Villiom Podlaski Christiansen
export: flush the file pointer between patches
r13081
Benoit Boissinot
patch/diff: move patch.export() to cmdutil.export()...
r10611 for seqno, rev in enumerate(revs):
single(rev, seqno + 1, fp)
Yuya Nishihara
commands: refactor diff --stat and qdiff --stat...
r11050 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
Martin Geisler
diff: recurse into subrepositories with --subrepos/-S flag
r12167 changes=None, stat=False, fp=None, prefix='',
Sean Farley
diff: rename --relative option to --root...
r24455 root='', listsubrepos=False):
Yuya Nishihara
commands: refactor diff --stat and qdiff --stat...
r11050 '''show diff or diffstat.'''
if fp is None:
write = ui.write
else:
def write(s, **kw):
fp.write(s)
Sean Farley
diff: rename --relative option to --root...
r24455 if root:
relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
Siddharth Agarwal
cmdutil.diffordiffstat: add support for diffs relative to a subdirectory...
r24431 else:
relroot = ''
if relroot != '':
# XXX relative roots currently don't work if the root is within a
# subrepo
uirelroot = match.uipath(relroot)
relroot += '/'
for matchroot in match.files():
if not matchroot.startswith(relroot):
ui.warn(_('warning: %s not inside relative root %s\n') % (
match.uipath(matchroot), uirelroot))
Yuya Nishihara
commands: refactor diff --stat and qdiff --stat...
r11050 if stat:
Alecs King
log: fix the bug 'hg log --stat -p == hg log --stat'...
r11950 diffopts = diffopts.copy(context=0)
Yuya Nishihara
commands: refactor diff --stat and qdiff --stat...
r11050 width = 80
if not ui.plain():
Augie Fackler
termwidth: move to ui.ui from util
r12689 width = ui.termwidth()
Martin Geisler
diff: recurse into subrepositories with --subrepos/-S flag
r12167 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
Siddharth Agarwal
cmdutil.diffordiffstat: add support for diffs relative to a subdirectory...
r24431 prefix=prefix, relroot=relroot)
Yuya Nishihara
commands: refactor diff --stat and qdiff --stat...
r11050 for chunk, label in patch.diffstatui(util.iterlines(chunks),
Henning Schild
patch: remove unused git parameter from patch.diffstat()...
r30407 width=width):
Yuya Nishihara
commands: refactor diff --stat and qdiff --stat...
r11050 write(chunk, label=label)
else:
for chunk, label in patch.diffui(repo, node1, node2, match,
Siddharth Agarwal
cmdutil.diffordiffstat: add support for diffs relative to a subdirectory...
r24431 changes, diffopts, prefix=prefix,
relroot=relroot):
Yuya Nishihara
commands: refactor diff --stat and qdiff --stat...
r11050 write(chunk, label=label)
Martin Geisler
diff: recurse into subrepositories with --subrepos/-S flag
r12167 if listsubrepos:
ctx1 = repo[node1]
Martin Geisler
subrepos: handle modified but uncommitted .hgsub
r12175 ctx2 = repo[node2]
Augie Fackler
itersubrepos: move to scmutil to break a direct import cycle
r20392 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
Alistair Bell
diff: when diffing a revision with a deleted subrepo, maintain the node context (issue3153)
r15698 tempnode2 = node2
Renato Cunha
diff: don't crash when diffing a revision with a deleted subrepo (issue3153)...
r15634 try:
if node2 is not None:
Alistair Bell
diff: when diffing a revision with a deleted subrepo, maintain the node context (issue3153)
r15698 tempnode2 = ctx2.substate[subpath][1]
Renato Cunha
diff: don't crash when diffing a revision with a deleted subrepo (issue3153)...
r15634 except KeyError:
# A subrepo that existed in node1 was deleted between node1 and
# node2 (inclusive). Thus, ctx2's substate won't contain that
# subpath. The best we can do is to ignore it.
Alistair Bell
diff: when diffing a revision with a deleted subrepo, maintain the node context (issue3153)
r15698 tempnode2 = None
Martin von Zweigbergk
match: rename "narrowmatcher" to "subdirmatcher" (API)...
r28017 submatch = matchmod.subdirmatcher(subpath, match)
FUJIWARA Katsunori
subrepo: add argument to "diff()" to pass "ui" of caller side (issue3712) (API)...
r18006 sub.diff(ui, diffopts, tempnode2, submatch, changes=changes,
Martin Geisler
diff: recurse into subrepositories with --subrepos/-S flag
r12167 stat=stat, fp=fp, prefix=prefix)
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 class changeset_printer(object):
'''show changeset information when templating not requested.'''
Martin von Zweigbergk
cmdutil: avoid the confusing name 'patch' for a matcher
r22386 def __init__(self, ui, repo, matchfn, diffopts, buffered):
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 self.ui = ui
self.repo = repo
Matt Mackall
Refactor log ui buffering and patch display
r3645 self.buffered = buffered
Martin von Zweigbergk
cmdutil: avoid the confusing name 'patch' for a matcher
r22386 self.matchfn = matchfn
Jim Correia
add --git option to commands supporting --patch (log, incoming, history, tip)...
r7762 self.diffopts = diffopts
Matt Mackall
use ui buffering in changeset printer...
r3738 self.header = {}
self.hunk = {}
self.lastheader = None
Robert Bachmann
Added support for templatevar "footer" to cmdutil.py
r10152 self.footer = None
Matt Mackall
Refactor log ui buffering and patch display
r3645
Yuya Nishihara
changeset_printer: change flush() to accept ctx instead of rev...
r25763 def flush(self, ctx):
rev = ctx.rev()
Matt Mackall
use ui buffering in changeset printer...
r3738 if rev in self.header:
h = self.header[rev]
if h != self.lastheader:
self.lastheader = h
self.ui.write(h)
del self.header[rev]
if rev in self.hunk:
self.ui.write(self.hunk[rev])
del self.hunk[rev]
return 1
return 0
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Robert Bachmann
Added support for templatevar "footer" to cmdutil.py
r10152 def close(self):
if self.footer:
self.ui.write(self.footer)
Mads Kiilerich
log: follow filenames through renames (issue647)...
r11488 def show(self, ctx, copies=None, matchfn=None, **props):
Matt Mackall
use ui buffering in changeset printer...
r3738 if self.buffered:
Gregory Szorc
cmdutil: pass labeled=True to pushbuffer()...
r27107 self.ui.pushbuffer(labeled=True)
Mads Kiilerich
log: follow filenames through renames (issue647)...
r11488 self._show(ctx, copies, matchfn, props)
Gregory Szorc
ui: remove labeled argument from popbuffer...
r27109 self.hunk[ctx.rev()] = self.ui.popbuffer()
Matt Mackall
use ui buffering in changeset printer...
r3738 else:
Mads Kiilerich
log: follow filenames through renames (issue647)...
r11488 self._show(ctx, copies, matchfn, props)
Matt Mackall
use ui buffering in changeset printer...
r3738
Mads Kiilerich
log: follow filenames through renames (issue647)...
r11488 def _show(self, ctx, copies, matchfn, props):
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 '''show a single changeset or file revision'''
Dirkjan Ochtman
cmdutil: use change contexts for cset-printer and cset-templater
r7369 changenode = ctx.node()
rev = ctx.rev()
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if self.ui.debugflag:
hexfunc = hex
else:
hexfunc = short
Yuya Nishihara
changeset_printer: display wdirrev/wdirnode values for workingctx...
r25762 # as of now, wctx.node() and wctx.rev() return None, but we want to
# show the same values as {node} and {rev} templatekw
revnode = (scmutil.intrev(rev), hexfunc(bin(ctx.hex())))
Yuya Nishihara
changeset_printer: display p1rev:p1node with "+" suffix for workingctx...
r24584
if self.ui.quiet:
self.ui.write("%d:%s\n" % revnode, label='log.node')
return
date = util.datestr(ctx.date())
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
Yuya Nishihara
changeset_printer: display p1rev:p1node with "+" suffix for workingctx...
r24584 self.ui.write(_("changeset: %d:%s\n") % revnode,
Sean Farley
color: add additional changeset.phase label to log.changeset and log.parent...
r17788 label='log.changeset changeset.%s' % ctx.phasestr())
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Sean Farley
log: use new namespaces api to display names...
r23772 # branches are shown first before any other names due to backwards
# compatibility
Adrian Buehlmann
cmdutil: minor refactoring of changeset_printer._show...
r9637 branch = ctx.branch()
Alexis S. L. Carvalho
"default" is the default branch name
r4176 # don't show the default branch name
if branch != 'default':
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
Brodie Rao
cmdutil: make use of output labeling in changeset_printer
r10819 self.ui.write(_("branch: %s\n") % branch,
label='log.branch')
Sean Farley
log: use new namespaces api to display names...
r23772
Nathaniel Manista
cmdutil: avoid recycling variable name "name" in namespaces code...
r28904 for nsname, ns in self.repo.names.iteritems():
Sean Farley
log: use new namespaces api to display names...
r23772 # branches has special logic already handled above, so here we just
# skip it
Nathaniel Manista
cmdutil: avoid recycling variable name "name" in namespaces code...
r28904 if nsname == 'branches':
Sean Farley
log: use new namespaces api to display names...
r23772 continue
# we will use the templatename as the color name since those two
# should be the same
for name in ns.names(self.repo, changenode):
FUJIWARA Katsunori
namespace: introduce logfmt to show l10n-ed messages for hg log correctly...
r23967 self.ui.write(ns.logfmt % name,
label='log.%s' % ns.colorname)
Jordi Gutiérrez Hermoso
log: do not hide the public phase in debug mode (BC)...
r22765 if self.ui.debugflag:
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
FUJIWARA Katsunori
cmdutil: avoid wrapping ctx.phasestr() by _()...
r24864 self.ui.write(_("phase: %s\n") % ctx.phasestr(),
Pierre-Yves David
changeset_printer: display changeset phase on debug level...
r15907 label='log.phase')
Yuya Nishihara
changeset_printer: move _meaningful_parentrevs() to scmutil...
r26433 for pctx in scmutil.meaningfulparents(self.repo, ctx):
Yuya Nishihara
changeset_printer: use context objects consistently to show parents...
r24483 label = 'log.parent changeset.%s' % pctx.phasestr()
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
Yuya Nishihara
changeset_printer: use context objects consistently to show parents...
r24483 self.ui.write(_("parent: %d:%s\n")
% (pctx.rev(), hexfunc(pctx.node())),
Sean Farley
log: use correct phase info for parent field (issue4347)...
r22301 label=label)
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Yuya Nishihara
changeset_printer: hide manifest node for workingctx...
r24585 if self.ui.debugflag and rev is not None:
Greg Ward
cmdutil: changeset_printer: use methods of filectx/changectx....
r9547 mnode = ctx.manifestnode()
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 self.ui.write(_("manifest: %d:%s\n") %
Durham Goode
manifest: remove last uses of repo.manifest...
r30375 (self.repo.manifestlog._revlog.rev(mnode),
hex(mnode)),
Brodie Rao
cmdutil: make use of output labeling in changeset_printer
r10819 label='ui.debug log.manifest')
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
Brodie Rao
cmdutil: make use of output labeling in changeset_printer
r10819 self.ui.write(_("user: %s\n") % ctx.user(),
label='log.user')
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
Brodie Rao
cmdutil: make use of output labeling in changeset_printer
r10819 self.ui.write(_("date: %s\n") % date,
label='log.date')
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
if self.ui.debugflag:
Yuya Nishihara
changeset_printer: use changectx to get status tuple...
r24485 files = ctx.p1().status(ctx)[:3]
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 for key, value in zip([# i18n: column positioning for "hg log"
_("files:"),
# i18n: column positioning for "hg log"
_("files+:"),
# i18n: column positioning for "hg log"
_("files-:")], files):
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 if value:
Brodie Rao
cmdutil: make use of output labeling in changeset_printer
r10819 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
label='ui.debug log.files')
Greg Ward
cmdutil: changeset_printer: use methods of filectx/changectx....
r9547 elif ctx.files() and self.ui.verbose:
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
Brodie Rao
cmdutil: make use of output labeling in changeset_printer
r10819 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
label='ui.note log.files')
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 if copies and self.ui.verbose:
copies = ['%s (%s)' % c for c in copies]
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
Brodie Rao
cmdutil: make use of output labeling in changeset_printer
r10819 self.ui.write(_("copies: %s\n") % ' '.join(copies),
label='ui.note log.copies')
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Adrian Buehlmann
cmdutil: minor refactoring of changeset_printer._show...
r9637 extra = ctx.extra()
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 if extra and self.ui.debugflag:
Matt Mackall
replace util.sort with sorted built-in...
r8209 for key, value in sorted(extra.items()):
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 self.ui.write(_("extra: %s=%s\n")
Brodie Rao
cmdutil: make use of output labeling in changeset_printer
r10819 % (key, value.encode('string_escape')),
label='ui.debug log.extra')
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Greg Ward
cmdutil: changeset_printer: use methods of filectx/changectx....
r9547 description = ctx.description().strip()
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 if description:
if self.ui.verbose:
Brodie Rao
cmdutil: make use of output labeling in changeset_printer
r10819 self.ui.write(_("description:\n"),
label='ui.note log.description')
self.ui.write(description,
label='ui.note log.description')
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 self.ui.write("\n\n")
else:
FUJIWARA Katsunori
i18n: add "i18n" comment to column positioning messages of "hg log"...
r17891 # i18n: column positioning for "hg log"
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 self.ui.write(_("summary: %s\n") %
Brodie Rao
cmdutil: make use of output labeling in changeset_printer
r10819 description.splitlines()[0],
label='log.summary')
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 self.ui.write("\n")
Gregory Szorc
cmdutil.changeset_printer: pass context into showpatch()...
r27065 self.showpatch(ctx, matchfn)
def showpatch(self, ctx, matchfn):
Mads Kiilerich
log: follow filenames through renames (issue647)...
r11488 if not matchfn:
Martin von Zweigbergk
cmdutil: avoid the confusing name 'patch' for a matcher
r22386 matchfn = self.matchfn
Mads Kiilerich
log: follow filenames through renames (issue647)...
r11488 if matchfn:
Yuya Nishihara
log: add --stat for diffstat output...
r11061 stat = self.diffopts.get('stat')
Alecs King
log: fix the bug 'hg log --stat -p == hg log --stat'...
r11950 diff = self.diffopts.get('patch')
Siddharth Agarwal
cmdutil.changeset_printer: explicitly honor all diffopts...
r23691 diffopts = patch.diffallopts(self.ui, self.diffopts)
Gregory Szorc
cmdutil.changeset_printer: pass context into showpatch()...
r27065 node = ctx.node()
Durham Goode
cmdutil: pass node instead of ctx to diffordiffstat...
r27622 prev = ctx.p1().node()
Alecs King
log: fix the bug 'hg log --stat -p == hg log --stat'...
r11950 if stat:
diffordiffstat(self.ui, self.repo, diffopts, prev, node,
match=matchfn, stat=True)
if diff:
if stat:
self.ui.write("\n")
diffordiffstat(self.ui, self.repo, diffopts, prev, node,
match=matchfn, stat=False)
Matt Mackall
Refactor log ui buffering and patch display
r3645 self.ui.write("\n")
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 class jsonchangeset(changeset_printer):
'''format changeset information.'''
def __init__(self, ui, repo, matchfn, diffopts, buffered):
changeset_printer.__init__(self, ui, repo, matchfn, diffopts, buffered)
self.cache = {}
self._first = True
def close(self):
if not self._first:
self.ui.write("\n]\n")
else:
self.ui.write("[]\n")
def _show(self, ctx, copies, matchfn, props):
'''show a single changeset or file revision'''
rev = ctx.rev()
Yuya Nishihara
jsonchangeset: set rev and node to "null" for workingctx
r24602 if rev is None:
jrev = jnode = 'null'
else:
jrev = str(rev)
jnode = '"%s"' % hex(ctx.node())
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 j = encoding.jsonescape
if self._first:
self.ui.write("[\n {")
self._first = False
else:
self.ui.write(",\n {")
if self.ui.quiet:
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write(('\n "rev": %s') % jrev)
self.ui.write((',\n "node": %s') % jnode)
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 self.ui.write('\n }')
return
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write(('\n "rev": %s') % jrev)
self.ui.write((',\n "node": %s') % jnode)
self.ui.write((',\n "branch": "%s"') % j(ctx.branch()))
self.ui.write((',\n "phase": "%s"') % ctx.phasestr())
self.ui.write((',\n "user": "%s"') % j(ctx.user()))
self.ui.write((',\n "date": [%d, %d]') % ctx.date())
self.ui.write((',\n "desc": "%s"') % j(ctx.description()))
self.ui.write((',\n "bookmarks": [%s]') %
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 ", ".join('"%s"' % j(b) for b in ctx.bookmarks()))
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write((',\n "tags": [%s]') %
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 ", ".join('"%s"' % j(t) for t in ctx.tags()))
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write((',\n "parents": [%s]') %
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 ", ".join('"%s"' % c.hex() for c in ctx.parents()))
if self.ui.debugflag:
Yuya Nishihara
jsonchangeset: set manifest node to "null" for workingctx...
r24603 if rev is None:
jmanifestnode = 'null'
else:
jmanifestnode = '"%s"' % hex(ctx.manifestnode())
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write((',\n "manifest": %s') % jmanifestnode)
self.ui.write((',\n "extra": {%s}') %
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 ", ".join('"%s": "%s"' % (j(k), j(v))
for k, v in ctx.extra().items()))
Gregory Szorc
cmdutil.jsonchangeset: properly compute added and removed files...
r23734 files = ctx.p1().status(ctx)
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write((',\n "modified": [%s]') %
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 ", ".join('"%s"' % j(f) for f in files[0]))
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write((',\n "added": [%s]') %
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 ", ".join('"%s"' % j(f) for f in files[1]))
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write((',\n "removed": [%s]') %
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 ", ".join('"%s"' % j(f) for f in files[2]))
elif self.ui.verbose:
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write((',\n "files": [%s]') %
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 ", ".join('"%s"' % j(f) for f in ctx.files()))
if copies:
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write((',\n "copies": {%s}') %
Augie Fackler
log: fix json-formatted output when file copies are listed (issue4523)
r24013 ", ".join('"%s": "%s"' % (j(k), j(v))
for k, v in copies))
Matt Mackall
cmdutil: add json style to log-like commands...
r22427
matchfn = self.matchfn
if matchfn:
stat = self.diffopts.get('stat')
diff = self.diffopts.get('patch')
Siddharth Agarwal
jsonchangeset: don't honor whitespace and format-changing diffopts...
r23453 diffopts = patch.difffeatureopts(self.ui, self.diffopts, git=True)
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 node, prev = ctx.node(), ctx.p1().node()
if stat:
self.ui.pushbuffer()
diffordiffstat(self.ui, self.repo, diffopts, prev, node,
match=matchfn, stat=True)
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write((',\n "diffstat": "%s"')
% j(self.ui.popbuffer()))
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 if diff:
self.ui.pushbuffer()
diffordiffstat(self.ui, self.repo, diffopts, prev, node,
match=matchfn, stat=False)
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 self.ui.write((',\n "diff": "%s"') % j(self.ui.popbuffer()))
Matt Mackall
cmdutil: add json style to log-like commands...
r22427
self.ui.write("\n }")
Thomas Arendsen Hein
hg log: Move filtering implicit parents to own method and use it in templater....
r4825
Matt Mackall
Refactor log ui buffering and patch display
r3645 class changeset_templater(changeset_printer):
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 '''format changeset information.'''
Martin von Zweigbergk
cmdutil: avoid the confusing name 'patch' for a matcher
r22386 def __init__(self, ui, repo, matchfn, diffopts, tmpl, mapfile, buffered):
changeset_printer.__init__(self, ui, repo, matchfn, diffopts, buffered)
Dirkjan Ochtman
templater: provide the standard template filters by default
r8360 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
Yuya Nishihara
templater: separate function to create templater from map file (API)...
r28954 filters = {'formatnode': formatnode}
Patrick Mezard
Make {file_copies} usable as a --template key...
r10061 defaulttempl = {
'parent': '{rev}:{node|formatnode} ',
'manifest': '{rev}:{node|formatnode}',
'file_copy': '{name} ({source})',
'extra': '{key}={value|stringescape}'
}
# filecopy is preserved for compatibility reasons
defaulttempl['filecopy'] = defaulttempl['file_copy']
Yuya Nishihara
templater: separate function to create templater from map file (API)...
r28954 assert not (tmpl and mapfile)
if mapfile:
self.t = templater.templater.frommapfile(mapfile, filters=filters,
cache=defaulttempl)
else:
Yuya Nishihara
templater: factor out function that creates templater from string template...
r28955 self.t = formatter.maketemplater(ui, 'changeset', tmpl,
filters=filters,
cache=defaulttempl)
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Matt Mackall
changeset_templater: remove use_template method
r20667 self.cache = {}
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Matt Mackall
templater: move verbosity-to-template matcher to constructor...
r26086 # find correct templates for current mode
tmplmodes = [
(True, None),
(self.ui.verbose, 'verbose'),
(self.ui.quiet, 'quiet'),
(self.ui.debugflag, 'debug'),
]
Matt Mackall
templater: add new docheader/footer components for XML (issue4135)...
r26222 self._parts = {'header': '', 'footer': '', 'changeset': 'changeset',
'docheader': '', 'docfooter': ''}
Matt Mackall
templater: move verbosity-to-template matcher to constructor...
r26086 for mode, postfix in tmplmodes:
for t in self._parts:
cur = t
if postfix:
cur += "_" + postfix
if mode and cur in self.t:
self._parts[t] = cur
Matt Mackall
templater: add new docheader/footer components for XML (issue4135)...
r26222 if self._parts['docheader']:
self.ui.write(templater.stringify(self.t(self._parts['docheader'])))
def close(self):
if self._parts['docfooter']:
if not self.footer:
self.footer = ""
self.footer += templater.stringify(self.t(self._parts['docfooter']))
return super(changeset_templater, self).close()
Mads Kiilerich
log: follow filenames through renames (issue647)...
r11488 def _show(self, ctx, copies, matchfn, props):
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 '''show a single changeset or file revision'''
props = props.copy()
Patrick Mezard
cmdutil: extract ctx dependent closures into templatekw
r10054 props.update(templatekw.keywords)
Patrick Mezard
cmdutil: replace showlist() closure with a function
r10053 props['templ'] = self.t
Patrick Mezard
cmdutil: extract ctx dependent closures into templatekw
r10054 props['ctx'] = ctx
Patrick Mezard
cmdutil: extract repo dependent closures in templatekw
r10055 props['repo'] = self.repo
Kostia Balytskyi
formatter: make labels work with templated output...
r28384 props['ui'] = self.repo.ui
Patrick Mezard
cmdutil: extract file copies closure into templatekw
r10058 props['revcache'] = {'copies': copies}
Patrick Mezard
cmdutil: extract latest tags closures in templatekw
r10057 props['cache'] = self.cache
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Yuya Nishihara
templater: drop deprecated handling of KeyError from changeset_templater...
r28837 # write header
if self._parts['header']:
h = templater.stringify(self.t(self._parts['header'], **props))
if self.buffered:
self.header[ctx.rev()] = h
else:
if self.lastheader != h:
self.lastheader = h
self.ui.write(h)
# write changeset metadata, then patch if requested
key = self._parts['changeset']
self.ui.write(templater.stringify(self.t(key, **props)))
self.showpatch(ctx, matchfn)
if self._parts['footer']:
if not self.footer:
self.footer = templater.stringify(
self.t(self._parts['footer'], **props))
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Matt Mackall
cmdutil: make helper function to process template args
r20666 def gettemplate(ui, tmpl, style):
"""
Find the template matching the given template spec or style.
"""
# ui settings
Yuya Nishihara
templater: fix precedence of --style and --template options...
r22582 if not tmpl and not style: # template are stronger than style
Matt Mackall
cmdutil: make helper function to process template args
r20666 tmpl = ui.config('ui', 'logtemplate')
if tmpl:
Yuya Nishihara
templater: relax unquotestring() to fall back to bare string...
r28630 return templater.unquotestring(tmpl), None
Matt Mackall
cmdutil: make helper function to process template args
r20666 else:
style = util.expandpath(ui.config('ui', 'style', ''))
Yuya Nishihara
templater: fix precedence of --style and --template options...
r22582 if not tmpl and style:
Matt Mackall
cmdutil: make helper function to process template args
r20666 mapfile = style
if not os.path.split(mapfile)[0]:
mapname = (templater.templatepath('map-cmdline.' + mapfile)
or templater.templatepath(mapfile))
if mapname:
mapfile = mapname
return None, mapfile
Matt Mackall
templating: make -T much more flexible...
r20668 if not tmpl:
return None, None
Matt Mackall
formatter: move most of template option helper to formatter...
r25511 return formatter.lookuptemplate(ui, 'changeset', tmpl)
Matt Mackall
cmdutil: make helper function to process template args
r20666
Mads Kiilerich
log: follow filenames through renames (issue647)...
r11488 def show_changeset(ui, repo, opts, buffered=False):
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643 """show one changeset using template or regular display.
Display format will be the first non-empty hit of:
1. option 'template'
2. option 'style'
3. [ui] setting 'logtemplate'
4. [ui] setting 'style'
If all of these values are either the unset or the empty string,
regular display via changeset_printer() is done.
"""
# options
Martin von Zweigbergk
cmdutil: avoid the confusing name 'patch' for a matcher
r22386 matchfn = None
Yuya Nishihara
log: add --stat for diffstat output...
r11061 if opts.get('patch') or opts.get('stat'):
Martin von Zweigbergk
cmdutil: avoid the confusing name 'patch' for a matcher
r22386 matchfn = scmutil.matchall(repo)
Matt Mackall
Fix log regression where log -p file showed diffs for other files
r3837
Matt Mackall
cmdutil: add json style to log-like commands...
r22427 if opts.get('template') == 'json':
return jsonchangeset(ui, repo, matchfn, opts, buffered)
Matt Mackall
Fix log regression where log -p file showed diffs for other files
r3837
Matt Mackall
cmdutil: make helper function to process template args
r20666 tmpl, mapfile = gettemplate(ui, opts.get('template'), opts.get('style'))
Dirkjan Ochtman
cmdutil: refactor handling of templating in show_changeset()
r7967
Matt Mackall
cmdutil: make helper function to process template args
r20666 if not tmpl and not mapfile:
Martin von Zweigbergk
cmdutil: avoid the confusing name 'patch' for a matcher
r22386 return changeset_printer(ui, repo, matchfn, opts, buffered)
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Yuya Nishihara
templater: do not abuse SyntaxError to report errors in template map file...
r28628 return changeset_templater(ui, repo, matchfn, opts, tmpl, mapfile, buffered)
Matt Mackall
templates: move changeset templating bits to cmdutils
r3643
Yuya Nishihara
debugobsolete: add formatter support (issue5134)...
r29795 def showmarker(fm, marker, index=None):
Pierre-Yves David
debugobsolete: extract marker display in a dedicated function...
r20470 """utility function to display obsolescence marker in a readable way
To be used by debug function."""
Kostia Balytskyi
debugobsolete: add an option to show marker index...
r28613 if index is not None:
Yuya Nishihara
debugobsolete: add formatter support (issue5134)...
r29795 fm.write('index', '%i ', index)
fm.write('precnode', '%s ', hex(marker.precnode()))
succs = marker.succnodes()
fm.condwrite(succs, 'succnodes', '%s ',
fm.formatlist(map(hex, succs), name='node'))
fm.write('flag', '%X ', marker.flags())
Pierre-Yves David
debugobsolete: display parents information from markers...
r22260 parents = marker.parentnodes()
if parents is not None:
Yuya Nishihara
debugobsolete: add formatter support (issue5134)...
r29795 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)
fm.write('metadata', '{%s}', fm.formatdict(meta, fmt='%r: %r', sep=', '))
fm.plain('\n')
Pierre-Yves David
debugobsolete: extract marker display in a dedicated function...
r20470
Matt Mackall
Add --date support to update and revert...
r3814 def finddate(ui, repo, date):
"""Find the tipmost changeset that matches the given date spec"""
Dirkjan Ochtman
merge changes from mpm
r9667
mark.williamson@cl.cam.ac.uk
Tweak finddate to pass date directly....
r5836 df = util.matchdate(date)
Matt Mackall
scmutil: drop aliases in cmdutil for match functions
r14322 m = scmutil.matchall(repo)
Matt Mackall
Add --date support to update and revert...
r3814 results = {}
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662
def prep(ctx, fns):
d = ctx.date()
if df(d[0]):
Dirkjan Ochtman
cmdutil: fix bug in finddate() implementation
r9668 results[ctx.rev()] = d
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662
Dirkjan Ochtman
merge changes from mpm
r9667 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662 rev = ctx.rev()
if rev in results:
Martin Geisler
cmdutil: lowercase finddate status message...
r16937 ui.status(_("found revision %s from %s\n") %
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662 (rev, util.datestr(results[rev])))
return str(rev)
Matt Mackall
Add --date support to update and revert...
r3814
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("revision matching date not found"))
Matt Mackall
Add --date support to update and revert...
r3814
Lucas Moscovicz
cmdutil: implemented new lazy increasingwindows...
r20553 def increasingwindows(windowsize=8, sizelimit=512):
while True:
yield windowsize
if windowsize < sizelimit:
windowsize *= 2
Patrick Mezard
cmdutil: extract increasing_windows() from walkchangerevs()...
r16776
Durham Goode
log: move log file walk to its own function...
r19290 class FileWalkError(Exception):
pass
def walkfilerevs(repo, match, follow, revs, fncache):
'''Walks the file history for the matched files.
Returns the changeset revs that are involved in the file history.
Throws FileWalkError if the file history can't be walked using
filelogs alone.
'''
wanted = set()
copies = []
minrev, maxrev = min(revs), max(revs)
def filerevgen(filelog, last):
"""
Only files, no patterns. Check the history of each file.
Examines filelog entries within minrev, maxrev linkrev range
Returns an iterator yielding (linkrev, parentlinkrevs, copied)
tuples in backwards order
"""
cl_count = len(repo)
revs = []
for j in xrange(0, last + 1):
linkrev = filelog.linkrev(j)
if linkrev < minrev:
continue
# only yield rev for which we have the changelog, it can
# happen while doing "hg log" during a pull or commit
if linkrev >= cl_count:
break
parentlinkrevs = []
for p in filelog.parentrevs(j):
if p != nullrev:
parentlinkrevs.append(filelog.linkrev(p))
n = filelog.node(j)
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:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot follow file not in parent '
Durham Goode
log: move log file walk to its own function...
r19290 'revision: "%s"') % filename)
yield filename, pctx[filename].filenode()
else:
yield filename, None
for filename_node in copies:
yield filename_node
for file_, node in iterfiles():
filelog = repo.file(file_)
if not len(filelog):
if node is None:
# A zero count may be a directory or deleted file, so
# try to find matching entries on the slow path.
if follow:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Durham Goode
log: move log file walk to its own function...
r19290 _('cannot follow nonexistent file: "%s"') % file_)
raise FileWalkError("Cannot walk via filelog")
else:
continue
if node is None:
last = len(filelog) - 1
else:
last = filelog.rev(node)
# keep track of all ancestors of the file
ancestors = set([filelog.linkrev(last)])
# iterate from latest to oldest revision
for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
if not follow:
if rev > maxrev:
continue
else:
# Note that last might not be the first interesting
# rev to us:
# if the file has been changed after maxrev, we'll
# have linkrev(last) > maxrev, and we still need
# to explore the file graph
if rev not in ancestors:
continue
# XXX insert 1327 fix here
if flparentlinkrevs:
ancestors.update(flparentlinkrevs)
fncache.setdefault(rev, []).append(file_)
wanted.add(rev)
if copied:
copies.append(copied)
return wanted
Martin von Zweigbergk
walkchangerevs: make followfilter a top-level class...
r24391 class _followfilter(object):
def __init__(self, repo, onlyfirst=False):
self.repo = repo
self.startrev = nullrev
self.roots = set()
self.onlyfirst = onlyfirst
def match(self, rev):
def realparents(rev):
if self.onlyfirst:
return self.repo.changelog.parentrevs(rev)[0:1]
else:
return filter(lambda x: x != nullrev,
self.repo.changelog.parentrevs(rev))
if self.startrev == nullrev:
self.startrev = rev
return True
if rev > self.startrev:
# forward: all descendants
if not self.roots:
self.roots.add(self.startrev)
for parent in realparents(rev):
if parent in self.roots:
self.roots.add(rev)
return True
else:
# backwards: all parents
if not self.roots:
self.roots.update(realparents(self.startrev))
if rev in self.roots:
self.roots.remove(rev)
self.roots.update(realparents(rev))
return True
return False
Matt Mackall
walkchangerevs: drop ui arg
r9665 def walkchangerevs(repo, match, opts, prepare):
timeless
help: miscellaneous language fixes
r7807 '''Iterate over files and the revs in which they changed.
Matt Mackall
move walkchangerevs to cmdutils
r3650
Callers most commonly need to iterate backwards over the history
timeless
help: miscellaneous language fixes
r7807 in which they are interested. Doing so has awful (quadratic-looking)
Matt Mackall
move walkchangerevs to cmdutils
r3650 performance, so we use iterators in a "windowed" way.
We walk a window of revisions in the desired order. Within the
window, we first walk forwards to gather data, then in the desired
order (usually backwards) to display it.
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662 This function returns an iterator yielding contexts. Before
yielding each context, the iterator will first call the prepare
function on each context in the window in forward order.'''
Matt Mackall
move walkchangerevs to cmdutils
r3650
follow = opts.get('follow') or opts.get('follow_first')
Yuya Nishihara
cmdutil: have walkchangerevs utilize common function to build revs
r24063 revs = _logrevs(repo, opts)
Matt Mackall
walkchangerevs: allow empty query sets
r11281 if not revs:
return []
Martin Geisler
replace set-like dictionaries with real sets...
r8152 wanted = set()
Martin von Zweigbergk
walkchangerevs: avoid match.files() in conditions...
r25272 slowpath = match.anypats() or ((match.isexact() or match.prefix()) and
opts.get('removed'))
Matt Mackall
move walkchangerevs to cmdutils
r3650 fncache = {}
Matt Mackall
log: remove caching of all visited revisions (issue3253)...
r16108 change = repo.changectx
Matt Mackall
move walkchangerevs to cmdutils
r3650
Nicolas Dumazet
log: document the different phases in walkchangerevs
r11632 # First step is to fill wanted, the set of revisions that we want to yield.
# When it does not induce extra cost, we also fill fncache for revisions in
# wanted: a cache of filenames that were changed (ctx.files()) and that
# match the file filtering conditions.
Martin von Zweigbergk
walkchangerevs: simplify by using match.always() method...
r24384 if match.always():
Matt Mackall
move walkchangerevs to cmdutils
r3650 # No files, no patterns. Display all revs.
Lucas Moscovicz
cmdutil: implemented new lazy increasingwindows...
r20553 wanted = revs
Martin von Zweigbergk
walkchangerevs: simplify with an 'elif'...
r25271 elif not slowpath:
Nicolas Dumazet
log: document the different phases in walkchangerevs
r11632 # We only have to read through the filelog to find wanted revisions
Durham Goode
log: move log file walk to its own function...
r19290 try:
wanted = walkfilerevs(repo, match, follow, revs, fncache)
except FileWalkError:
slowpath = True
Nicolas Dumazet
log: remove increasing windows usage in fastpath...
r11608
Durham Goode
log: move log file walk to its own function...
r19290 # We decided to fall back to the slowpath because at least one
# of the paths was not a file. Check to see if at least one of them
# existed in history, otherwise simply return
smuralid
log: speed up hg log for untracked files (issue1340)...
r17746 for path in match.files():
if path == '.' or path in repo.store:
break
Mads Kiilerich
log: make log work even if first parameter doesn't exist...
r18340 else:
return []
smuralid
log: speed up hg log for untracked files (issue1340)...
r17746
Matt Mackall
move walkchangerevs to cmdutils
r3650 if slowpath:
Nicolas Dumazet
log: document the different phases in walkchangerevs
r11632 # We have to read the changelog to match filenames against
# changed files
Matt Mackall
move walkchangerevs to cmdutils
r3650 if follow:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('can only follow copies/renames for explicit '
timeless
Generally replace "file name" with "filename" in help and comments.
r8761 'filenames'))
Matt Mackall
move walkchangerevs to cmdutils
r3650
# The slow path checks files modified in every changeset.
Durham Goode
log: make file log slow path usable on large repos...
r19730 # This is really slow on large repos, so compute the set lazily.
class lazywantedset(object):
def __init__(self):
self.set = set()
self.revs = set(revs)
# No need to worry about locality here because it will be accessed
# in the same order as the increasing window below.
def __contains__(self, value):
if value in self.set:
return True
elif not value in self.revs:
return False
else:
self.revs.discard(value)
ctx = change(value)
matches = filter(match, ctx.files())
if matches:
fncache[value] = matches
self.set.add(value)
return True
return False
def discard(self, value):
self.revs.discard(value)
self.set.discard(value)
wanted = lazywantedset()
Matt Mackall
move walkchangerevs to cmdutils
r3650
# it might be worthwhile to do this in the iterator if the rev range
# is descending and the prune args are all within that range
for rev in opts.get('prune', ()):
Matt Mackall
cmdutil: use context instead of lookup
r16380 rev = repo[rev].rev()
Martin von Zweigbergk
walkchangerevs: make followfilter a top-level class...
r24391 ff = _followfilter(repo)
Matt Mackall
move walkchangerevs to cmdutils
r3650 stop = min(revs[0], revs[-1])
Matt Mackall
many, many trivial check-code fixups
r10282 for x in xrange(rev, stop - 1, -1):
Martin Geisler
replace set-like dictionaries with real sets...
r8152 if ff.match(x):
Lucas Moscovicz
cmdutil: implemented new lazy increasingwindows...
r20553 wanted = wanted - [x]
Bryan O'Sullivan
cmdutil: use a small initial window with --limit...
r18710
Nicolas Dumazet
log: document the different phases in walkchangerevs
r11632 # Now that wanted is correctly initialized, we can iterate over the
# revision range, yielding only revisions in wanted.
Matt Mackall
move walkchangerevs to cmdutils
r3650 def iterate():
Martin von Zweigbergk
walkchangerevs: avoid match.files() in conditions...
r25272 if follow and match.always():
Martin von Zweigbergk
walkchangerevs: make followfilter a top-level class...
r24391 ff = _followfilter(repo, onlyfirst=opts.get('follow_first'))
Matt Mackall
move walkchangerevs to cmdutils
r3650 def want(rev):
Martin Geisler
cmdutil: return boolean result directly in want function
r8119 return ff.match(rev) and rev in wanted
Matt Mackall
move walkchangerevs to cmdutils
r3650 else:
def want(rev):
return rev in wanted
Lucas Moscovicz
cmdutil: implemented new lazy increasingwindows...
r20553 it = iter(revs)
stopiteration = False
for windowsize in increasingwindows():
nrevs = []
for i in xrange(windowsize):
Pierre-Yves David
walkchangerevs: replace try/except with 'next'...
r25147 rev = next(it, None)
if rev is None:
Lucas Moscovicz
cmdutil: implemented new lazy increasingwindows...
r20553 stopiteration = True
break
Pierre-Yves David
walkchangerevs: replace try/except with 'next'...
r25147 elif want(rev):
nrevs.append(rev)
Matt Mackall
replace util.sort with sorted built-in...
r8209 for rev in sorted(nrevs):
Matt Mackall
move walkchangerevs to cmdutils
r3650 fns = fncache.get(rev)
Matt Mackall
walkchangerevs: yield contexts
r9654 ctx = change(rev)
Matt Mackall
move walkchangerevs to cmdutils
r3650 if not fns:
def fns_generator():
Matt Mackall
walkchangerevs: yield contexts
r9654 for f in ctx.files():
Matt Mackall
walkchangerevs: pull out matchfn...
r9652 if match(f):
Matt Mackall
move walkchangerevs to cmdutils
r3650 yield f
fns = fns_generator()
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662 prepare(ctx, fns)
Matt Mackall
move walkchangerevs to cmdutils
r3650 for rev in nrevs:
Matt Mackall
walkchangerevs: move 'add' to callback...
r9662 yield change(rev)
Lucas Moscovicz
cmdutil: implemented new lazy increasingwindows...
r20553
if stopiteration:
break
Matt Mackall
walkchangerevs: pull out matchfn...
r9652 return iterate()
Bryan O'Sullivan
commands: move commit to cmdutil as wrapper for commit-like functions
r5034
Siddharth Agarwal
cmdutil: rename _makelogfilematcher to _makefollowlogfilematcher...
r22166 def _makefollowlogfilematcher(repo, files, followfirst):
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 # When displaying a revision with --patch --follow FILE, we have
# to know which file of the revision must be diffed. With
# --follow, we want the names of the ancestors of FILE in the
# revision, stored in "fcache". "fcache" is populated by
# reproducing the graph traversal already done by --follow revset
Yuya Nishihara
log: copy the way of ancestor traversal to --follow matcher (issue5376)...
r30016 # and relating revs to file names (which is not "correct" but
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 # good enough).
fcache = {}
fcacheready = [False]
pctx = repo['.']
def populate():
Siddharth Agarwal
log: make --patch --follow work inside a subdirectory...
r21876 for fn in files:
Yuya Nishihara
log: unroll loop that populates file paths for --patch --follow matcher...
r30015 fctx = pctx[fn]
Yuya Nishihara
log: copy the way of ancestor traversal to --follow matcher (issue5376)...
r30016 fcache.setdefault(fctx.introrev(), set()).add(fctx.path())
Yuya Nishihara
log: unroll loop that populates file paths for --patch --follow matcher...
r30015 for c in fctx.ancestors(followfirst=followfirst):
Yuya Nishihara
log: copy the way of ancestor traversal to --follow matcher (issue5376)...
r30016 fcache.setdefault(c.rev(), set()).add(c.path())
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180
def filematcher(rev):
if not fcacheready[0]:
# Lazy initialization
fcacheready[0] = True
populate()
Siddharth Agarwal
log: use an exact matcher for --patch --follow...
r21878 return scmutil.matchfiles(repo, fcache.get(rev, []))
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180
return filematcher
Siddharth Agarwal
cmdutil: add a hook for making custom non-follow log file matchers...
r22167 def _makenofollowlogfilematcher(repo, pats, opts):
'''hook for extensions to override the filematcher for non-follow cases'''
return None
Lucas Moscovicz
cmdutil: changed _makegraphlogrevset to _makelogrevset...
r21108 def _makelogrevset(repo, pats, opts, revs):
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 """Return (expr, filematcher) where expr is a revset string built
from log options and file patterns or None. If --stat or --patch
are not passed filematcher is None. Otherwise it is a callable
taking a revision number and returning a match objects filtering
the files to be detailed when displaying the revision.
"""
opt2revset = {
'no_merges': ('not merge()', None),
'only_merges': ('merge()', None),
'_ancestors': ('ancestors(%(val)s)', None),
'_fancestors': ('_firstancestors(%(val)s)', None),
'_descendants': ('descendants(%(val)s)', None),
'_fdescendants': ('_firstdescendants(%(val)s)', None),
'_matchfiles': ('_matchfiles(%(val)s)', None),
'date': ('date(%(val)r)', None),
'branch': ('branch(%(val)r)', ' or '),
'_patslog': ('filelog(%(val)r)', ' or '),
'_patsfollow': ('follow(%(val)r)', ' or '),
'_patsfollowfirst': ('_followfirst(%(val)r)', ' or '),
'keyword': ('keyword(%(val)r)', ' or '),
'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
'user': ('user(%(val)r)', ' or '),
}
opts = dict(opts)
# follow or not follow?
follow = opts.get('follow') or opts.get('follow_first')
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if opts.get('follow_first'):
followfirst = 1
else:
followfirst = 0
timeless@mozdev.org
spelling: behaviour -> behavior
r26098 # --follow with FILE behavior depends on revs...
Lucas Moscovicz
cmdutil: changed code in _makegraphlogrevset not to use getitem...
r20756 it = iter(revs)
timeless
py3: convert to next() function...
r29216 startrev = next(it)
Pierre-Yves David
_makelogrevset: replace try/except with 'next' usage...
r25168 followdescendants = startrev < next(it, startrev)
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180
# branch and only_branch are really aliases and must be handled at
# the same time
opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
# pats/include/exclude are passed to match.match() directly in
Mads Kiilerich
fix trivial spelling errors
r17424 # _matchfiles() revset but walkchangerevs() builds its matcher with
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 # scmutil.match(). The difference is input pats are globbed on
# platforms without shell expansion (windows).
Martin von Zweigbergk
log: prefer 'wctx' over 'pctx' for working context
r24534 wctx = repo[None]
match, pats = scmutil.matchandpats(wctx, pats, opts)
Martin von Zweigbergk
_makelogrevset: avoid match.files() in conditions...
r25273 slowpath = match.anypats() or ((match.isexact() or match.prefix()) and
opts.get('removed'))
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 if not slowpath:
for f in match.files():
Martin von Zweigbergk
log: prefer 'wctx' over 'pctx' for working context
r24534 if follow and f not in wctx:
Durham Goode
log: allow patterns with -f...
r21998 # If the file exists, it may be a directory, so let it
# take the slow path.
if os.path.exists(repo.wjoin(f)):
slowpath = True
continue
else:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot follow file not in parent '
Durham Goode
log: allow patterns with -f...
r21998 'revision: "%s"') % f)
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 filelog = repo.file(f)
Durham Goode
filelog: switch 'not len(filerevlog)' to 'not filerevlog'...
r19293 if not filelog:
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 # A zero count may be a directory or deleted file, so
# try to find matching entries on the slow path.
if follow:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 _('cannot follow nonexistent file: "%s"') % f)
slowpath = True
smuralid
log: speed up hg log for untracked files (issue1340)...
r17746
# We decided to fall back to the slowpath because at least one
# of the paths was not a file. Check to see if at least one of them
# existed in history - in that case, we'll continue down the
# slowpath; otherwise, we can turn off the slowpath
if slowpath:
for path in match.files():
if path == '.' or path in repo.store:
break
else:
slowpath = False
Durham Goode
log: fix log -f slow path to actually follow history...
r23500 fpats = ('_patsfollow', '_patsfollowfirst')
fnopats = (('_ancestors', '_fancestors'),
('_descendants', '_fdescendants'))
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 if slowpath:
# See walkchangerevs() slow path.
#
# pats/include/exclude cannot be represented as separate
# revset expressions as their filtering logic applies at file
# level. For instance "-I a -X a" matches a revision touching
# "a" and "b" while "file(a) and not file(b)" does
# not. Besides, filesets are evaluated against the working
# directory.
matchargs = ['r:', 'd:relpath']
for p in pats:
matchargs.append('p:' + p)
for p in opts.get('include', []):
matchargs.append('i:' + p)
for p in opts.get('exclude', []):
matchargs.append('x:' + p)
matchargs = ','.join(('%r' % p) for p in matchargs)
opts['_matchfiles'] = matchargs
Durham Goode
log: fix log -f slow path to actually follow history...
r23500 if follow:
opts[fnopats[0][followfirst]] = '.'
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 else:
if follow:
if pats:
Mads Kiilerich
fix trivial spelling errors
r17424 # follow() revset interprets its file argument as a
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 # manifest entry, so use match.files(), not pats.
opts[fpats[followfirst]] = list(match.files())
else:
Yuya Nishihara
log: use rev() to build revset of --follow option from numeric revision...
r23955 op = fnopats[followdescendants][followfirst]
opts[op] = 'rev(%d)' % startrev
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 else:
opts['_patslog'] = list(pats)
filematcher = None
if opts.get('patch') or opts.get('stat'):
Durham Goode
log: allow patterns with -f...
r21998 # When following files, track renames via a special matcher.
# If we're forced to take the slowpath it means we're following
# at least one pattern/directory, so don't bother with rename tracking.
if follow and not match.always() and not slowpath:
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23139 # _makefollowlogfilematcher expects its files argument to be
# relative to the repo root, so use match.files(), not pats.
Siddharth Agarwal
cmdutil: rename _makelogfilematcher to _makefollowlogfilematcher...
r22166 filematcher = _makefollowlogfilematcher(repo, match.files(),
followfirst)
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 else:
Siddharth Agarwal
cmdutil: add a hook for making custom non-follow log file matchers...
r22167 filematcher = _makenofollowlogfilematcher(repo, pats, opts)
if filematcher is None:
filematcher = lambda rev: match
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180
expr = []
Durham Goode
log: fix log revset instability...
r23501 for op, val in sorted(opts.iteritems()):
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 if not val:
continue
if op not in opt2revset:
continue
revop, andor = opt2revset[op]
if '%(val)' not in revop:
expr.append(revop)
else:
if not isinstance(val, list):
e = revop % {'val': val}
else:
e = '(' + andor.join((revop % {'val': v}) for v in val) + ')'
expr.append(e)
if expr:
expr = '(' + ' and '.join(expr) + ')'
else:
expr = None
return expr, filematcher
Yuya Nishihara
log: extract common part from getgraphlogrevs() and getlogrevs()
r24062 def _logrevs(repo, opts):
timeless@mozdev.org
spelling: behaviour -> behavior
r26098 # Default --rev value depends on --follow but --follow behavior
Yuya Nishihara
log: extract common part from getgraphlogrevs() and getlogrevs()
r24062 # depends on revisions resolved from --rev...
follow = opts.get('follow') or opts.get('follow_first')
if opts.get('rev'):
revs = scmutil.revrange(repo, opts['rev'])
Yuya Nishihara
log: fix --follow null parent not to include revision 0...
r24064 elif follow and repo.dirstate.p1() == nullid:
revs = revset.baseset()
Yuya Nishihara
log: extract common part from getgraphlogrevs() and getlogrevs()
r24062 elif follow:
revs = repo.revs('reverse(:.)')
else:
revs = revset.spanset(repo)
revs.reverse()
return revs
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 def getgraphlogrevs(repo, pats, opts):
"""Return (revs, expr, filematcher) where revs is an iterable of
revision numbers, expr is a revset string built from log options
and file patterns or None, and used to filter 'revs'. If --stat or
--patch are not passed filematcher is None. Otherwise it is a
callable taking a revision number and returning a match objects
filtering the files to be detailed when displaying the revision.
"""
Siddharth Agarwal
cmdutil: make getgraphlogrevs limit-aware...
r18172 limit = loglimit(opts)
Yuya Nishihara
log: extract common part from getgraphlogrevs() and getlogrevs()
r24062 revs = _logrevs(repo, opts)
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 if not revs:
Lucas Moscovicz
getgraphlogrevs: return an empty baseset instead of a empty list...
r20759 return revset.baseset(), None, None
Lucas Moscovicz
cmdutil: changed _makegraphlogrevset to _makelogrevset...
r21108 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
Yuya Nishihara
graphlog: move comment and flag denoting revs might be unsorted...
r24060 if opts.get('rev'):
# User-specified revs might be unsorted, but don't sort before
# _makelogrevset because it might depend on the order of revs
Martijn Pieters
revset: record if a set is in topographical order...
r29346 if not (revs.isdescending() or revs.istopo()):
Martijn Pieters
graphmod: avoid sorting when already sorted...
r29335 revs.sort(reverse=True)
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 if expr:
Yuya Nishihara
graphlog: preserve topo sort even if additional filter options specified...
r30003 matcher = revset.match(repo.ui, expr, order=revset.followorder)
Siddharth Agarwal
cmdutil: stop pretending we can calculate revs for graphlog lazily...
r18171 revs = matcher(repo, revs)
Pierre-Yves David
log: use "hidden" filtering instead of manual check at display time...
r18243 if limit is not None:
Pierre-Yves David
getgraphlogrevs: remove user of baseset.append...
r22807 limitedrevs = []
Lucas Moscovicz
cmdutil: changed code in getgraphlogrevs not to use getitem...
r20755 for idx, rev in enumerate(revs):
if idx >= limit:
break
limitedrevs.append(rev)
Pierre-Yves David
getgraphlogrevs: remove user of baseset.append...
r22807 revs = revset.baseset(limitedrevs)
Siddharth Agarwal
cmdutil: make getgraphlogrevs limit-aware...
r18172
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 return revs, expr, filematcher
Lucas Moscovicz
log: changed implementation to use graphlog code...
r21127 def getlogrevs(repo, pats, opts):
"""Return (revs, expr, filematcher) where revs is an iterable of
revision numbers, expr is a revset string built from log options
and file patterns or None, and used to filter 'revs'. If --stat or
--patch are not passed filematcher is None. Otherwise it is a
callable taking a revision number and returning a match objects
filtering the files to be detailed when displaying the revision.
"""
limit = loglimit(opts)
Yuya Nishihara
log: extract common part from getgraphlogrevs() and getlogrevs()
r24062 revs = _logrevs(repo, opts)
Lucas Moscovicz
log: changed implementation to use graphlog code...
r21127 if not revs:
return revset.baseset([]), None, None
expr, filematcher = _makelogrevset(repo, pats, opts, revs)
if expr:
Yuya Nishihara
log: drop hack to fix order of revset (issue5100)...
r29956 matcher = revset.match(repo.ui, expr, order=revset.followorder)
Lucas Moscovicz
log: changed implementation to use graphlog code...
r21127 revs = matcher(repo, revs)
if limit is not None:
Pierre-Yves David
getlogrevs: remove user of baseset.append...
r22806 limitedrevs = []
Pierre-Yves David
getlogrevs: rewrite a loop to get read of try/except...
r25169 for idx, r in enumerate(revs):
if limit <= idx:
Lucas Moscovicz
log: changed implementation to use graphlog code...
r21127 break
Pierre-Yves David
getlogrevs: rewrite a loop to get read of try/except...
r25169 limitedrevs.append(r)
Pierre-Yves David
getlogrevs: remove user of baseset.append...
r22806 revs = revset.baseset(limitedrevs)
Lucas Moscovicz
log: changed implementation to use graphlog code...
r21127
return revs, expr, filematcher
Yuya Nishihara
graphlog: make node symbol templatable by ui.graphnodetemplate option...
r27216 def _graphnodeformatter(ui, displayer):
spec = ui.config('ui', 'graphnodetemplate')
if not spec:
return templatekw.showgraphnode # fast path for "{graphnode}"
templ = formatter.gettemplater(ui, 'graphnode', spec)
cache = {}
if isinstance(displayer, changeset_templater):
cache = displayer.cache # reuse cache of slow templates
props = templatekw.keywords.copy()
props['templ'] = templ
props['cache'] = cache
def formatnode(repo, ctx):
props['ctx'] = ctx
props['repo'] = repo
Yuya Nishihara
graphlog: bring back color to node symbol template...
r28428 props['ui'] = repo.ui
Yuya Nishihara
graphlog: make node symbol templatable by ui.graphnodetemplate option...
r27216 props['revcache'] = {}
return templater.stringify(templ('graphnode', **props))
return formatnode
Yuya Nishihara
graphlog: move creation of workingdir-parent nodes to displaygraph()...
r27213 def displaygraph(ui, repo, dag, displayer, edgefn, getrenamed=None,
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 filematcher=None):
Yuya Nishihara
graphlog: make node symbol templatable by ui.graphnodetemplate option...
r27216 formatnode = _graphnodeformatter(ui, displayer)
Martijn Pieters
graphmod: refactor state handling...
r28375 state = graphmod.asciistate()
Martijn Pieters
graphmod: allow for different styles for different edge types...
r28600 styles = state['styles']
Martijn Pieters
graphmod: disable graph styling when HGPLAIN is set (issue5212)...
r28999
# only set graph styling if HGPLAIN is not set.
if ui.plain('graph'):
# set all edge styles to |, the default pre-3.8 behaviour
styles.update(dict.fromkeys(styles, '|'))
else:
edgetypes = {
'parent': graphmod.PARENT,
'grandparent': graphmod.GRANDPARENT,
'missing': graphmod.MISSINGPARENT
}
for name, key in edgetypes.items():
# experimental config: experimental.graphstyle.*
styles[key] = ui.config('experimental', 'graphstyle.%s' % name,
styles[key])
if not styles[key]:
styles[key] = None
# experimental config: experimental.graphshorten
state['graphshorten'] = ui.configbool('experimental', 'graphshorten')
santiagopim
graphmod: shorten graph...
r28891
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 for rev, type, ctx, parents in dag:
Yuya Nishihara
graphlog: make node symbol templatable by ui.graphnodetemplate option...
r27216 char = formatnode(repo, ctx)
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 copies = None
if getrenamed and ctx.rev():
copies = []
for fn in ctx.files():
rename = getrenamed(fn, ctx.rev())
if rename:
copies.append((fn, rename[0]))
revmatchfn = None
if filematcher is not None:
revmatchfn = filematcher(ctx.rev())
displayer.show(ctx, copies=copies, matchfn=revmatchfn)
lines = displayer.hunk.pop(rev).split('\n')
if not lines[-1]:
del lines[-1]
Yuya Nishihara
changeset_printer: change flush() to accept ctx instead of rev...
r25763 displayer.flush(ctx)
Martijn Pieters
graphmod: refactor state handling...
r28375 edges = edgefn(type, char, lines, state, rev, parents)
Patrick Mezard
graphlog: extract revset/support functions into cmdutil
r17180 for type, char, lines, coldata in edges:
graphmod.ascii(ui, state, type, char, lines, coldata)
displayer.close()
Patrick Mezard
log: support --graph without graphlog extension...
r17181 def graphlog(ui, repo, *pats, **opts):
# Parameters are identical to log command ones
revs, expr, filematcher = getgraphlogrevs(repo, pats, opts)
revdag = graphmod.dagwalker(repo, revs)
getrenamed = None
if opts.get('copies'):
endrev = None
if opts.get('rev'):
Lucas Moscovicz
cmdutil: changed max method for lazy call...
r20760 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
Patrick Mezard
log: support --graph without graphlog extension...
r17181 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
displayer = show_changeset(ui, repo, opts, buffered=True)
Yuya Nishihara
graphlog: move creation of workingdir-parent nodes to displaygraph()...
r27213 displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, getrenamed,
filematcher)
Patrick Mezard
log: support --graph without graphlog extension...
r17181
Patrick Mezard
incoming/outgoing: handle --graph in core
r17182 def checkunsupportedgraphflags(pats, opts):
for op in ["newest_first"]:
if op in opts and opts[op]:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("-G/--graph option is incompatible with --%s")
Patrick Mezard
incoming/outgoing: handle --graph in core
r17182 % op.replace("_", "-"))
def graphrevs(repo, nodes, opts):
limit = loglimit(opts)
nodes.reverse()
if limit is not None:
nodes = nodes[:limit]
return graphmod.nodes(repo, nodes)
Matt Harbison
add: pass options via keyword args...
r23885 def add(ui, repo, match, prefix, explicitonly, **opts):
Martin Geisler
add: recurse into subrepositories with --subrepos/-S flag
r12270 join = lambda f: os.path.join(prefix, f)
Martin Geisler
add: move main part to cmdutil to make it easier to reuse
r12269 bad = []
Matt Harbison
add: replace match.bad() monkey patching with match.badmatch()...
r25436
badfn = lambda x, y: bad.append(x) or match.bad(x, y)
Martin Geisler
add: move main part to cmdutil to make it easier to reuse
r12269 names = []
Martin Geisler
add: recurse into subrepositories with --subrepos/-S flag
r12270 wctx = repo[None]
Adrian Buehlmann
scmutil: introduce casecollisionauditor...
r14138 cca = None
abort, warn = scmutil.checkportabilityalert(ui)
if abort or warn:
Joshua Redstone
scmutil: 25% speedup in casecollisionauditor...
r17201 cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
Matt Harbison
add: replace match.bad() monkey patching with match.badmatch()...
r25436
Durham Goode
add: pass full=False to dirstate walk...
r26206 badmatch = matchmod.badmatch(match, badfn)
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, sorted(wctx.substate),
True, False, full=False)):
Martin Geisler
add: move main part to cmdutil to make it easier to reuse
r12269 exact = match.exact(f)
John Coomes
add: use lexists so that broken symbolic links are added...
r23462 if exact or not explicitonly and f not in wctx and repo.wvfs.lexists(f):
Adrian Buehlmann
scmutil: introduce casecollisionauditor...
r14138 if cca:
cca(f)
Martin Geisler
add: move main part to cmdutil to make it easier to reuse
r12269 names.append(f)
if ui.verbose or not exact:
Matt Harbison
narrowmatcher: propagate the rel() method...
r23686 ui.status(_('adding %s\n') % match.rel(f))
Martin Geisler
add: recurse into subrepositories with --subrepos/-S flag
r12270
Mads Kiilerich
subrepos: process subrepos in sorted order...
r18364 for subpath in sorted(wctx.substate):
David M. Carr
add: support adding explicit files in subrepos...
r15410 sub = wctx.sub(subpath)
try:
Martin von Zweigbergk
match: rename "narrowmatcher" to "subdirmatcher" (API)...
r28017 submatch = matchmod.subdirmatcher(subpath, match)
Matt Harbison
add: pass options via keyword args...
r23885 if opts.get('subrepos'):
bad.extend(sub.add(ui, submatch, prefix, False, **opts))
David M. Carr
add: support adding explicit files in subrepos...
r15410 else:
Matt Harbison
add: pass options via keyword args...
r23885 bad.extend(sub.add(ui, submatch, prefix, True, **opts))
David M. Carr
add: support adding explicit files in subrepos...
r15410 except error.LookupError:
ui.status(_("skipping missing subrepository: %s\n")
% join(subpath))
Martin Geisler
add: recurse into subrepositories with --subrepos/-S flag
r12270
Matt Harbison
add: pass options via keyword args...
r23885 if not opts.get('dry_run'):
Martin Geisler
add: recurse into subrepositories with --subrepos/-S flag
r12270 rejected = wctx.add(names, prefix)
Martin Geisler
add: move main part to cmdutil to make it easier to reuse
r12269 bad.extend(f for f in rejected if f in match.files())
return bad
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 def forget(ui, repo, match, prefix, explicitonly):
join = lambda f: os.path.join(prefix, f)
bad = []
Matt Harbison
forget: replace match.bad() monkey patching with match.badmatch()...
r25437 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 wctx = repo[None]
forgot = []
Matt Harbison
forget: replace match.bad() monkey patching with match.badmatch()...
r25437
s = repo.status(match=matchmod.badmatch(match, badfn), clean=True)
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 forget = sorted(s[0] + s[1] + s[3] + s[6])
if explicitonly:
forget = [f for f in forget if match.exact(f)]
Mads Kiilerich
subrepos: process subrepos in sorted order...
r18364 for subpath in sorted(wctx.substate):
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 sub = wctx.sub(subpath)
try:
Martin von Zweigbergk
match: rename "narrowmatcher" to "subdirmatcher" (API)...
r28017 submatch = matchmod.subdirmatcher(subpath, match)
Matt Harbison
subrepo: drop the 'ui' parameter to forget()...
r23577 subbad, subforgot = sub.forget(submatch, prefix)
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 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")
% join(subpath))
FUJIWARA Katsunori
forget: show warning messages for forgetting in subrepo correctly...
r16070 if not explicitonly:
for f in match.files():
Matt Harbison
forget: use vfs instead of os.path + match.rel() for filesystem checks
r23673 if f not in repo.dirstate and not repo.wvfs.isdir(f):
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 if f not in forgot:
Matt Harbison
forget: use vfs instead of os.path + match.rel() for filesystem checks
r23673 if repo.wvfs.exists(f):
Matt Harbison
forget: cleanup the output for an inexact case match on icasefs...
r24548 # Don't complain if the exact case match wasn't given.
# But don't do this until after checking 'forgot', so
# that subrepo files aren't normalized, and this op is
# purely from data cached by the status walk above.
if repo.dirstate.normalize(f) in repo.dirstate:
continue
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 ui.warn(_('not removing %s: '
'file is already untracked\n')
Matt Harbison
narrowmatcher: propagate the rel() method...
r23686 % match.rel(f))
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 bad.append(f)
for f in forget:
if ui.verbose or not match.exact(f):
Matt Harbison
narrowmatcher: propagate the rel() method...
r23686 ui.status(_('removing %s\n') % match.rel(f))
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912
rejected = wctx.forget(forget, prefix)
bad.extend(f for f in rejected if f in match.files())
Matt Harbison
forget: don't report rejected files as forgotten as well...
r23838 forgot.extend(f for f in forget if f not in rejected)
David M. Carr
forget: fix subrepo recursion for explicit path handling...
r15912 return bad, forgot
Matt Harbison
subrepo: add basic support to hgsubrepo for the files command...
r24413 def files(ui, ctx, m, fm, fmt, subrepos):
Matt Harbison
files: split reusable implementation into cmdutil for subrepo support
r24275 rev = ctx.rev()
ret = 1
Matt Harbison
files: replace 'ctx._repo' with 'ctx.repo()'
r24301 ds = ctx.repo().dirstate
Matt Harbison
files: split reusable implementation into cmdutil for subrepo support
r24275
for f in ctx.matches(m):
if rev is None and ds[f] == 'r':
continue
fm.startitem()
if ui.verbose:
fc = ctx[f]
fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
fm.data(abspath=f)
fm.write('path', fmt, m.rel(f))
ret = 0
Matt Harbison
files: recurse into subrepos automatically with an explicit path
r25228 for subpath in sorted(ctx.substate):
Hannes Oldenburg
subrepo: cleanup of subrepo filematcher logic...
r29802 submatch = matchmod.subdirmatcher(subpath, m)
if (subrepos or m.exact(subpath) or any(submatch.files())):
Matt Harbison
subrepo: add basic support to hgsubrepo for the files command...
r24413 sub = ctx.sub(subpath)
try:
Matt Harbison
files: don't recurse into subrepos without a path or -S (issue5127)...
r28387 recurse = m.exact(subpath) or subrepos
if sub.printfiles(ui, submatch, fm, fmt, recurse) == 0:
Matt Harbison
subrepo: add basic support to hgsubrepo for the files command...
r24413 ret = 0
except error.LookupError:
ui.status(_("skipping missing subrepository: %s\n")
% m.abs(subpath))
Matt Harbison
files: split reusable implementation into cmdutil for subrepo support
r24275 return ret
timeless
remove: queue warnings until after status messages (issue5140) (API)...
r28607 def remove(ui, repo, m, prefix, after, force, subrepos, warnings=None):
Matt Harbison
remove: recurse into subrepositories with --subrepos/-S flag...
r23325 join = lambda f: os.path.join(prefix, f)
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 ret = 0
s = repo.status(match=m, clean=True)
modified, added, deleted, clean = s[0], s[1], s[3], s[6]
Matt Harbison
remove: recurse into subrepositories with --subrepos/-S flag...
r23325 wctx = repo[None]
timeless
remove: queue warnings until after status messages (issue5140) (API)...
r28607 if warnings is None:
warnings = []
warn = True
else:
warn = False
timeless
remove: add progress support
r28608 subs = sorted(wctx.substate)
total = len(subs)
count = 0
for subpath in subs:
count += 1
Hannes Oldenburg
subrepo: cleanup of subrepo filematcher logic...
r29802 submatch = matchmod.subdirmatcher(subpath, m)
if subrepos or m.exact(subpath) or any(submatch.files()):
timeless
remove: add progress support
r28608 ui.progress(_('searching'), count, total=total, unit=_('subrepos'))
Matt Harbison
remove: recurse into subrepositories with --subrepos/-S flag...
r23325 sub = wctx.sub(subpath)
try:
timeless
remove: queue warnings until after status messages (issue5140) (API)...
r28607 if sub.removefiles(submatch, prefix, after, force, subrepos,
warnings):
Matt Harbison
remove: recurse into subrepositories with --subrepos/-S flag...
r23325 ret = 1
except error.LookupError:
timeless
remove: queue warnings until after status messages (issue5140) (API)...
r28607 warnings.append(_("skipping missing subrepository: %s\n")
Matt Harbison
remove: recurse into subrepositories with --subrepos/-S flag...
r23325 % join(subpath))
timeless
remove: add progress support
r28608 ui.progress(_('searching'), None)
Matt Harbison
remove: recurse into subrepositories with --subrepos/-S flag...
r23325
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 # warn about failure to delete explicit files/dirs
Drew Gottlieb
util: move dirs() and finddirs() from scmutil to util...
r24635 deleteddirs = util.dirs(deleted)
timeless
remove: add progress support
r28608 files = m.files()
total = len(files)
count = 0
for f in files:
Matt Harbison
remove: recurse into subrepositories with --subrepos/-S flag...
r23325 def insubrepo():
for subpath in wctx.substate:
Hannes Oldenburg
cmdutil: warnings not issued in remove if subrepopath overlaps...
r29622 if f.startswith(subpath + '/'):
Matt Harbison
remove: recurse into subrepositories with --subrepos/-S flag...
r23325 return True
return False
timeless
remove: add progress support
r28608 count += 1
ui.progress(_('deleting'), count, total=total, unit=_('files'))
Martin von Zweigbergk
remove: use ctx.hasdir(f) instead of 'f in ctx.dirs()'...
r24955 isdir = f in deleteddirs or wctx.hasdir(f)
Hannes Oldenburg
cmdutil: warnings not issued in remove if subrepopath overlaps...
r29622 if (f in repo.dirstate or isdir or f == '.'
or insubrepo() or f in subs):
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 continue
Matt Harbison
remove: recurse into subrepositories with --subrepos/-S flag...
r23325
Matt Harbison
remove: use vfs instead of os.path + match.rel() for filesystem checks
r23674 if repo.wvfs.exists(f):
if repo.wvfs.isdir(f):
timeless
remove: queue warnings until after status messages (issue5140) (API)...
r28607 warnings.append(_('not removing %s: no tracked files\n')
Matt Harbison
narrowmatcher: propagate the rel() method...
r23686 % m.rel(f))
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 else:
timeless
remove: queue warnings until after status messages (issue5140) (API)...
r28607 warnings.append(_('not removing %s: file is untracked\n')
Matt Harbison
narrowmatcher: propagate the rel() method...
r23686 % m.rel(f))
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 # missing files will generate a warning elsewhere
ret = 1
timeless
remove: add progress support
r28608 ui.progress(_('deleting'), None)
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289
if force:
list = modified + deleted + clean + added
elif after:
list = deleted
timeless
remove: add progress support
r28608 remaining = modified + added + clean
total = len(remaining)
count = 0
for f in remaining:
count += 1
ui.progress(_('skipping'), count, total=total, unit=_('files'))
warnings.append(_('not removing %s: file still exists\n')
% m.rel(f))
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 ret = 1
timeless
remove: add progress support
r28608 ui.progress(_('skipping'), None)
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 else:
list = deleted + clean
timeless
remove: add progress support
r28608 total = len(modified) + len(added)
count = 0
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 for f in modified:
timeless
remove: add progress support
r28608 count += 1
ui.progress(_('skipping'), count, total=total, unit=_('files'))
timeless
remove: queue warnings until after status messages (issue5140) (API)...
r28607 warnings.append(_('not removing %s: file is modified (use -f'
Matt Harbison
narrowmatcher: propagate the rel() method...
r23686 ' to force removal)\n') % m.rel(f))
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 ret = 1
for f in added:
timeless
remove: add progress support
r28608 count += 1
ui.progress(_('skipping'), count, total=total, unit=_('files'))
timeless
remove: specify hg in added warning
r29963 warnings.append(_("not removing %s: file has been marked for add"
" (use 'hg forget' to undo add)\n") % m.rel(f))
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 ret = 1
timeless
remove: add progress support
r28608 ui.progress(_('skipping'), None)
list = sorted(list)
total = len(list)
count = 0
for f in list:
count += 1
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 if ui.verbose or not m.exact(f):
timeless
remove: add progress support
r28608 ui.progress(_('deleting'), count, total=total, unit=_('files'))
Matt Harbison
narrowmatcher: propagate the rel() method...
r23686 ui.status(_('removing %s\n') % m.rel(f))
timeless
remove: add progress support
r28608 ui.progress(_('deleting'), None)
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289
Bryan O'Sullivan
with: use context manager for wlock in remove
r27802 with repo.wlock():
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 if not after:
for f in list:
if f in added:
continue # we never unlink added files on remove
util.unlinkpath(repo.wjoin(f), ignoremissing=True)
repo[None].forget(list)
timeless
remove: queue warnings until after status messages (issue5140) (API)...
r28607 if warn:
for warning in warnings:
ui.warn(warning)
Matt Harbison
remove: move most of the implementation into cmdutils.remove()...
r23289 return ret
Matt Harbison
cat: support cat with explicit paths in subrepos...
r21041 def cat(ui, repo, ctx, matcher, prefix, **opts):
Matt Harbison
cat: move most of the implementation into cmdutils.cat()...
r21040 err = 1
def write(path):
Matt Harbison
cat: support cat with explicit paths in subrepos...
r21041 fp = makefileobj(repo, opts.get('output'), ctx.node(),
pathname=os.path.join(prefix, path))
Matt Harbison
cat: move most of the implementation into cmdutils.cat()...
r21040 data = ctx[path].data()
if opts.get('decode'):
data = repo.wwritedata(path, data)
fp.write(data)
fp.close()
# Automation often uses hg cat on single files, so special case it
# for performance to avoid the cost of parsing the manifest.
if len(matcher.files()) == 1 and not matcher.anypats():
file = matcher.files()[0]
Durham Goode
manifest: remove manifest.find...
r30340 mfl = repo.manifestlog
Yuya Nishihara
cat: use ctx.manifestnode() in place of ctx._changeset[0]
r24718 mfnode = ctx.manifestnode()
Durham Goode
manifest: remove manifest.find...
r30340 try:
if mfnode and mfl[mfnode].find(file)[0]:
write(file)
return 0
except KeyError:
pass
Matt Harbison
cat: move most of the implementation into cmdutils.cat()...
r21040
Hannes Oldenburg
cmdutil: remove duplicated badmatch call in cat()...
r29739 for abs in ctx.walk(matcher):
Matt Harbison
cat: move most of the implementation into cmdutils.cat()...
r21040 write(abs)
err = 0
Matt Harbison
cat: support cat with explicit paths in subrepos...
r21041
for subpath in sorted(ctx.substate):
sub = ctx.sub(subpath)
try:
Martin von Zweigbergk
match: rename "narrowmatcher" to "subdirmatcher" (API)...
r28017 submatch = matchmod.subdirmatcher(subpath, matcher)
Matt Harbison
cat: support cat with explicit paths in subrepos...
r21041
Matt Harbison
subrepo: drop the 'ui' parameter to cat()...
r23576 if not sub.cat(submatch, os.path.join(prefix, sub._path),
Matt Harbison
cat: support cat with explicit paths in subrepos...
r21041 **opts):
err = 0
except error.RepoLookupError:
ui.status(_("skipping missing subrepository: %s\n")
% os.path.join(prefix, subpath))
Matt Harbison
cat: move most of the implementation into cmdutils.cat()...
r21040 return err
Bryan O'Sullivan
commands: move commit to cmdutil as wrapper for commit-like functions
r5034 def commit(ui, repo, commitfunc, pats, opts):
'''commit the specified files or all outstanding changes'''
Thomas Arendsen Hein
Fix bad behaviour when specifying an invalid date (issue700)...
r6139 date = opts.get('date')
if date:
opts['date'] = util.parsedate(date)
Idan Kamara
cmdutil, logmessage: use ui.fin when reading from '-'
r14635 message = logmessage(ui, opts)
Matt Harbison
scmutil: pass a matcher to scmutil.addremove() instead of a list of patterns...
r23533 matcher = scmutil.match(repo[None], pats, opts)
Bryan O'Sullivan
commands: move commit to cmdutil as wrapper for commit-like functions
r5034
Kirill Smelkov
cmdutil.commit: extract 'addremove' from opts carefully...
r5829 # extract addremove carefully -- this function can be called from a command
# that doesn't support addremove
if opts.get('addremove'):
Matt Harbison
commit: propagate --addremove to subrepos if -S is specified (issue3759)...
r23537 if scmutil.addremove(repo, matcher, "", opts) != 0:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(
Matt Harbison
commit: abort if --addremove is specified, but fails...
r23535 _("failed to mark all new/missing files as added/removed"))
Matt Harbison
scmutil: pass a matcher to scmutil.addremove() instead of a list of patterns...
r23533
return commitfunc(ui, repo, message, matcher, opts)
Matt Mackall
commit: move commit editor to cmdutil, pass as function
r8407
Hannes Oldenburg
cmdutil: extract samefile function from amend()
r29819 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())
else:
return False
else:
return f not in ctx2.manifest()
Idan Kamara
commit: add option to amend the working dir parent...
r16458 def amend(ui, repo, commitfunc, old, extra, pats, opts):
Gregory Szorc
cmdutil: break import cycle...
r25930 # avoid cycle context -> subrepo -> cmdutil
Gregory Szorc
cmdutil: use absolute_import...
r28322 from . import context
Gregory Szorc
cmdutil: break import cycle...
r25930
Matt Harbison
amend: abort early if no username is configured with evolve enabled (issue4211)...
r23101 # amend will reuse the existing user if not specified, but the obsolete
# marker creation requires that the current user's name is specified.
Durham Goode
obsolete: remove last instance of _enabled...
r24379 if obsolete.isenabled(repo, obsolete.createmarkersopt):
Matt Harbison
amend: abort early if no username is configured with evolve enabled (issue4211)...
r23101 ui.username() # raise exception if username not set
Idan Kamara
commit: add option to amend the working dir parent...
r16458 ui.note(_('amending changeset %s\n') % old)
base = old.p1()
Pierre-Yves David
amend: move createmarkers evaluation earlier...
r25709 createmarkers = obsolete.isenabled(repo, obsolete.createmarkersopt)
Idan Kamara
commit: add option to amend the working dir parent...
r16458
FUJIWARA Katsunori
dirstate: remove meaningless dirstateguard...
r26578 wlock = lock = newid = None
Idan Kamara
commit: add option to amend the working dir parent...
r16458 try:
Pierre-Yves David
amend: lock the repository during the whole process...
r17471 wlock = repo.wlock()
lock = repo.lock()
Bryan O'Sullivan
with: use context manager in amend
r27868 with repo.transaction('amend') as tr:
Pierre-Yves David
amend: use an explicit commit message for temporary amending commit...
r17473 # See if we got a message from -m or -l, if not, open the editor
# with the message of the changeset to amend
message = logmessage(ui, opts)
Pierre-Yves David
amend: fix incompatibity between logfile and message option (issue3675)...
r17863 # ensure logfile does not conflict with later enforcement of the
# message. potential logfile content has been processed by
# `logmessage` anyway.
opts.pop('logfile')
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 # First, do a regular commit to record all changes in the working
# directory (if there are any)
ui.callhooks = False
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 activebookmark = repo._bookmarks.active
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 try:
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 repo._bookmarks.active = None
Pierre-Yves David
amend: use an explicit commit message for temporary amending commit...
r17473 opts['message'] = 'temporary amend commit for %s' % old
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 node = commit(ui, repo, commitfunc, pats, opts)
finally:
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 repo._bookmarks.active = activebookmark
repo._bookmarks.recordchange(tr)
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 ui.callhooks = True
ctx = repo[node]
Idan Kamara
commit: add option to amend the working dir parent...
r16458
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 # Participating changesets:
#
# node/ctx o - new (intermediate) commit that contains changes
# | from working dir to go into amending commit
# | (or a workingctx if there were no changes)
# |
# old o - changeset to amend
# |
# base o - parent of amending changeset
Idan Kamara
commit: add option to amend the working dir parent...
r16458
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 # Update extra dict from amended commit (e.g. to preserve graft
# source)
extra.update(old.extra())
Idan Kamara
amend: preserve extra dict (issue3430)
r16630
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 # Also update it from the intermediate commit or from the wctx
extra.update(ctx.extra())
Idan Kamara
amend: preserve extra dict (issue3430)
r16630
Brodie Rao
amend: support amending merge changesets (issue3778)
r18909 if len(old.parents()) > 1:
# ctx.files() isn't reliable for merges, so fall back to the
# slower repo.status() method
files = set([fn for st in repo.status(base, old)[:3]
for fn in st])
else:
files = set(old.files())
Idan Kamara
commit: add option to amend the working dir parent...
r16458
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 # Second, we use either the commit we just did, or if there were no
# changes the parent of the working directory as the version of the
# files in the final amend commit
if node:
ui.note(_('copying changeset %s to %s\n') % (ctx, base))
Idan Kamara
commit: add option to amend the working dir parent...
r16458
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 user = ctx.user()
date = ctx.date()
# Recompute copies (avoid recording a -> b -> a)
copied = copies.pathcopies(base, ctx)
Pierre-Yves David
amend: check for directory renames for both merge parents (issue4516)...
r24169 if old.p2:
copied.update(copies.pathcopies(old.p2(), ctx))
Idan Kamara
commit: add option to amend the working dir parent...
r16458
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 # Prune files which were reverted by the updates: if old
# introduced file X and our intermediate commit, node,
# renamed that file, then those two files are the same and
# we can discard X from our list of files. Likewise if X
# was deleted, it's no longer relevant
files.update(ctx.files())
Hannes Oldenburg
cmdutil: extract samefile function from amend()
r29819 files = [f for f in files if not samefile(f, ctx, base)]
Idan Kamara
commit: add option to amend the working dir parent...
r16458
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 def filectxfn(repo, ctx_, path):
try:
fctx = ctx[path]
flags = fctx.flags()
Sean Farley
memfilectx: call super.__init__ instead of duplicating code...
r21689 mctx = context.memfilectx(repo,
fctx.path(), fctx.data(),
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 islink='l' in flags,
isexec='x' in flags,
copied=copied.get(path))
return mctx
except KeyError:
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 return None
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 else:
ui.note(_('copying changeset %s to %s\n') % (old, base))
Idan Kamara
commit: add option to amend the working dir parent...
r16458
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 # Use version of files as in the old cset
def filectxfn(repo, ctx_, path):
try:
return old.filectx(path)
except KeyError:
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 return None
Idan Kamara
commit: add option to amend the working dir parent...
r16458
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 user = opts.get('user') or old.user()
date = opts.get('date') or old.date()
FUJIWARA Katsunori
commit: change "editform" to distinguish merge commits from other (--amend)...
r22249 editform = mergeeditform(old, 'commit.amend')
FUJIWARA Katsunori
commit: pass 'editform' argument to 'cmdutil.getcommiteditor'...
r22010 editor = getcommiteditor(editform=editform, **opts)
Pierre-Yves David
amend: use an explicit commit message for temporary amending commit...
r17473 if not message:
FUJIWARA Katsunori
commit: pass 'editform' argument to 'cmdutil.getcommiteditor'...
r22010 editor = getcommiteditor(edit=True, editform=editform)
Pierre-Yves David
amend: use an explicit commit message for temporary amending commit...
r17473 message = old.description()
Idan Kamara
commit: add option to amend the working dir parent...
r16458
Pierre-Yves David
amend: add noise in extra to avoid creating obsolescence cycle (issue3664)...
r17811 pureextra = extra.copy()
extra['amend_source'] = old.hex()
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 new = context.memctx(repo,
Brodie Rao
amend: support amending merge changesets (issue3778)
r18909 parents=[base.node(), old.p2().node()],
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 text=message,
files=files,
filectxfn=filectxfn,
user=user,
date=date,
FUJIWARA Katsunori
amend: use "editor" argument for "memctx.__init__" to save commit message...
r21240 extra=extra,
editor=editor)
Pierre-Yves David
amend: add noise in extra to avoid creating obsolescence cycle (issue3664)...
r17811
timeless
cleanup: remove superfluous space after space after equals (python)
r27637 newdesc = changelog.stripdesc(new.description())
Pierre-Yves David
amend: add noise in extra to avoid creating obsolescence cycle (issue3664)...
r17811 if ((not node)
and newdesc == old.description()
and user == old.user()
and date == old.date()
Siddharth Agarwal
amend: don't preserve most extra fields...
r27973 and pureextra == old.extra()):
Pierre-Yves David
amend: add noise in extra to avoid creating obsolescence cycle (issue3664)...
r17811 # nothing changed. continuing here would create a new node
# anyway because of the amend_source noise.
#
# This not what we expect from amend.
return old.node()
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 ph = repo.ui.config('phases', 'new-commit', phases.draft)
try:
FUJIWARA Katsunori
commit: create new amend changeset as secret correctly for "--secret" option...
r20700 if opts.get('secret'):
commitphase = 'secret'
else:
commitphase = old.phase()
Mads Kiilerich
config: set a 'source' in most cases where config don't come from file but code...
r20790 repo.ui.setconfig('phases', 'new-commit', commitphase, 'amend')
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 newid = repo.commitctx(new)
finally:
Mads Kiilerich
config: set a 'source' in most cases where config don't come from file but code...
r20790 repo.ui.setconfig('phases', 'new-commit', ph, 'amend')
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 if newid != old.node():
# Reroute the working copy parent to the new changeset
repo.setparents(newid, nullid)
# Move bookmarks from old parent to amend commit
bms = repo.nodebookmarks(old.node())
if bms:
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 marks = repo._bookmarks
Pierre-Yves David
amend: wrap all commit operations in a single transaction...
r17472 for bm in bms:
Pierre-Yves David
amend: stop updating the bookmarks twice...
r25694 ui.debug('moving bookmarks %r from %s to %s\n' %
(marks, old.hex(), hex(newid)))
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 marks[bm] = newid
Pierre-Yves David
amend: collaborate with the transaction when moving bookmarks...
r25693 marks.recordchange(tr)
Pierre-Yves David
amend: move obsmarkers creation in the "new changeset" conditional...
r25710 #commit the whole amend process
if createmarkers:
# mark the new changeset as successor of the rewritten one
new = repo[newid]
obs = [(old, (new,))]
if node:
obs.append((ctx, ()))
obsolete.createmarkers(repo, obs)
Durham Goode
obsolete: add createmarkers option...
r22951 if not createmarkers and newid != old.node():
Pierre-Yves David
amend: add obsolete support...
r17475 # Strip the intermediate commit (if there was one) and the amended
# commit
Pierre-Yves David
amend: lock the repository during the whole process...
r17471 if node:
ui.note(_('stripping intermediate changeset %s\n') % ctx)
ui.note(_('stripping amended changeset %s\n') % old)
repair.strip(ui, repo, old.node(), topic='amend-backup')
Idan Kamara
commit: add option to amend the working dir parent...
r16458 finally:
FUJIWARA Katsunori
dirstate: remove meaningless dirstateguard...
r26578 lockmod.release(lock, wlock)
Idan Kamara
commit: add option to amend the working dir parent...
r16458 return newid
FUJIWARA Katsunori
cmdutil: introduce 'editform' to distinguish the purpose of commit text editing...
r21999 def commiteditor(repo, ctx, subs, editform=''):
Matt Mackall
commit: move commit editor to cmdutil, pass as function
r8407 if ctx.description():
return ctx.description()
Tony Tung
commit: abort when a committemplate is not changed...
r26742 return commitforceeditor(repo, ctx, subs, editform=editform,
unchangedmessagedetection=True)
Matt Mackall
commit: move commit editor to cmdutil, pass as function
r8407
FUJIWARA Katsunori
cmdutil: introduce 'editform' to distinguish the purpose of commit text editing...
r21999 def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None,
Tony Tung
commit: abort when a committemplate is not changed...
r26742 editform='', unchangedmessagedetection=False):
Matt Mackall
commiteditor: refactor default extramsg
r21923 if not extramsg:
extramsg = _("Leave message empty to abort commit.")
FUJIWARA Katsunori
cmdutil: look commit template definition up by specified 'editform'...
r22012
forms = [e for e in editform.split('.') if e]
forms.insert(0, 'changeset')
Tony Tung
commit: abort when a committemplate is not changed...
r26742 templatetext = None
FUJIWARA Katsunori
cmdutil: look commit template definition up by specified 'editform'...
r22012 while forms:
tmpl = repo.ui.config('committemplate', '.'.join(forms))
if tmpl:
Tony Tung
commit: abort when a committemplate is not changed...
r26742 templatetext = committext = buildcommittemplate(
repo, ctx, subs, extramsg, tmpl)
FUJIWARA Katsunori
cmdutil: look commit template definition up by specified 'editform'...
r22012 break
forms.pop()
FUJIWARA Katsunori
cmdutil: make commit message shown in text editor customizable by template...
r21924 else:
committext = buildcommittext(repo, ctx, subs, extramsg)
FUJIWARA Katsunori
cmdutil: separate building commit text from 'commitforceeditor'...
r21869
# run editor in the repository root
olddir = os.getcwd()
os.chdir(repo.root)
FUJIWARA Katsunori
cmdutil: make in-memory changes visible to external editor (issue4378)...
r26750
# make in-memory changes visible to external process
tr = repo.currenttransaction()
repo.dirstate.write(tr)
pending = tr and tr.writepending() and repo.root
Tony Tung
commit: abort when a committemplate is not changed...
r26742 editortext = repo.ui.edit(committext, ctx.user(), ctx.extra(),
FUJIWARA Katsunori
cmdutil: make in-memory changes visible to external editor (issue4378)...
r26750 editform=editform, pending=pending)
Tony Tung
commit: abort when a committemplate is not changed...
r26742 text = re.sub("(?m)^HG:.*(\n|$)", "", editortext)
FUJIWARA Katsunori
cmdutil: separate building commit text from 'commitforceeditor'...
r21869 os.chdir(olddir)
if finishdesc:
text = finishdesc(text)
if not text.strip():
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("empty commit message"))
Tony Tung
commit: abort when a committemplate is not changed...
r26742 if unchangedmessagedetection and editortext == templatetext:
raise error.Abort(_("commit message unchanged"))
FUJIWARA Katsunori
cmdutil: separate building commit text from 'commitforceeditor'...
r21869
return text
FUJIWARA Katsunori
cmdutil: make commit message shown in text editor customizable by template...
r21924 def buildcommittemplate(repo, ctx, subs, extramsg, tmpl):
ui = repo.ui
tmpl, mapfile = gettemplate(ui, tmpl, None)
Yuya Nishihara
templater: do not abuse SyntaxError to report errors in template map file...
r28628 t = changeset_templater(ui, repo, None, {}, tmpl, mapfile, False)
FUJIWARA Katsunori
cmdutil: make commit message shown in text editor customizable by template...
r21924
FUJIWARA Katsunori
cmdutil: use '[committemplate]' section like as map file for style definition...
r22013 for k, v in repo.ui.configitems('committemplate'):
if k != 'changeset':
t.t.cache[k] = v
FUJIWARA Katsunori
cmdutil: make commit message shown in text editor customizable by template...
r21924 if not extramsg:
extramsg = '' # ensure that extramsg is string
ui.pushbuffer()
t.show(ctx, extramsg=extramsg)
return ui.popbuffer()
timeless@mozdev.org
cmdutil: handle multiline translations of HG: messages safely...
r26426 def hgprefix(msg):
return "\n".join(["HG: %s" % a for a in msg.split("\n") if a])
FUJIWARA Katsunori
cmdutil: separate building commit text from 'commitforceeditor'...
r21869 def buildcommittext(repo, ctx, subs, extramsg):
Matt Mackall
commit: move commit editor to cmdutil, pass as function
r8407 edittext = []
Matt Mackall
commit: editor reads file lists from provided context
r8707 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
Matt Mackall
commit: move commit editor to cmdutil, pass as function
r8407 if ctx.description():
edittext.append(ctx.description())
edittext.append("")
edittext.append("") # Empty line between message and comments.
timeless@mozdev.org
cmdutil: handle multiline translations of HG: messages safely...
r26426 edittext.append(hgprefix(_("Enter commit message."
" Lines beginning with 'HG:' are removed.")))
edittext.append(hgprefix(extramsg))
Matt Mackall
commit: move commit editor to cmdutil, pass as function
r8407 edittext.append("HG: --")
timeless@mozdev.org
cmdutil: handle multiline translations of HG: messages safely...
r26426 edittext.append(hgprefix(_("user: %s") % ctx.user()))
Matt Mackall
commit: move commit editor to cmdutil, pass as function
r8407 if ctx.p2():
timeless@mozdev.org
cmdutil: handle multiline translations of HG: messages safely...
r26426 edittext.append(hgprefix(_("branch merge")))
Matt Mackall
commit: move commit editor to cmdutil, pass as function
r8407 if ctx.branch():
timeless@mozdev.org
cmdutil: handle multiline translations of HG: messages safely...
r26426 edittext.append(hgprefix(_("branch '%s'") % ctx.branch()))
Ryan McElroy
bookmarks: simplify iscurrent to isactivewdirparent (API)...
r24986 if bookmarks.isactivewdirparent(repo):
timeless@mozdev.org
cmdutil: handle multiline translations of HG: messages safely...
r26426 edittext.append(hgprefix(_("bookmark '%s'") % repo._activebookmark))
edittext.extend([hgprefix(_("subrepo %s") % s) for s in subs])
edittext.extend([hgprefix(_("added %s") % f) for f in added])
edittext.extend([hgprefix(_("changed %s") % f) for f in modified])
edittext.extend([hgprefix(_("removed %s") % f) for f in removed])
Matt Mackall
commit: editor reads file lists from provided context
r8707 if not added and not modified and not removed:
timeless@mozdev.org
cmdutil: handle multiline translations of HG: messages safely...
r26426 edittext.append(hgprefix(_("no files changed")))
Matt Mackall
commit: move commit editor to cmdutil, pass as function
r8407 edittext.append("")
FUJIWARA Katsunori
cmdutil: separate building commit text from 'commitforceeditor'...
r21869 return "\n".join(edittext)
Adrian Buehlmann
commands: use a decorator to build table incrementally...
r14297
Pierre-Yves David
addremove: remove a mutable default argument...
r26324 def commitstatus(repo, node, branch, bheads=None, opts=None):
if opts is None:
opts = {}
Kevin Bullock
commit: factor out status printing into a helper function...
r18688 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]):
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:
#
# Par column: for the 2 parents with ...
# N: null or no parent
# B: parent is on another named branch
# C: parent is a regular non head changeset
# H: parent was a branch head of the current branch
# Msg column: whether we print "created new head" message
# In the following, it is assumed that there already exists some
# initial branch heads of the current branch, otherwise nothing is
# printed anyway.
#
# Par Msg Comment
# N N y additional topo root
#
# B N y additional branch root
# C N y additional topo head
# H N n usual case
#
# B B y weird additional branch root
# C B y branch merge
# H B n merge with named branch
#
# C C y additional head from merge
# C H n merge with a head
#
# H H n head merge: head count decreases
if not opts.get('close_branch'):
for r in parents:
if r.closesbranch() and r.branch() == branch:
repo.ui.status(_('reopening closed branch head %d\n') % r)
if repo.ui.debugflag:
repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
elif repo.ui.verbose:
repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
Matt Harbison
commit: factor the post commit status check into a cmdutil method...
r27943 def postcommitstatus(repo, pats, opts):
return repo.status(match=scmutil.match(repo[None], pats, opts))
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 def revert(ui, repo, ctx, parents, *pats, **opts):
parent, p2 = parents
node = ctx.node()
mf = ctx.manifest()
Pierre-Yves David
revert: use p2 as parent when reverting against it...
r21579 if node == p2:
parent = p2
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304
# need all matching names in dirstate and manifest of target rev,
# so have to walk both. do not print errors if files exist in one
Yuya Nishihara
revert: comment that filesets are always evaluated against workingctx
r24451 # but not other. in both cases, filesets should be evaluated against
# workingctx to get consistent result (issue4497). this means 'set:**'
# cannot be used to select missing files from target rev.
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304
Pierre-Yves David
revert: add some inline comments...
r21575 # `names` is a mapping for all elements in working copy and target revision
# The mapping is in the form:
# <asb path in repo> -> (<path from CWD>, <exactly specified by matcher?>)
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 names = {}
Bryan O'Sullivan
with: use context manager for wlock in revert
r27803 with repo.wlock():
Pierre-Yves David
revert: add some inline comments...
r21575 ## filling of the `names` mapping
# walk dirstate to fill `names`
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304
Laurent Charignon
revert: fix --interactive on local modification (issue4576)...
r24475 interactive = opts.get('interactive', False)
Martin von Zweigbergk
revert: define 'wctx' a little earlier and use it more
r24449 wctx = repo[None]
m = scmutil.match(wctx, pats, opts)
Matt Mackall
revert: move calculation of targetsubs earlier
r24479
# we'll need this later
targetsubs = sorted(s for s in wctx.substate if m(s))
Martin von Zweigbergk
revert: take fast path also when not reverting to '.'...
r24450 if not m.always():
Matt Harbison
revert: replace match.bad() monkey patching with match.badmatch()...
r25439 for abs in repo.walk(matchmod.badmatch(m, lambda x, y: False)):
Durham Goode
revert: special case 'hg revert --all'...
r22573 names[abs] = m.rel(abs), m.exact(abs)
# walk target manifest to fill `names`
def badfn(path, msg):
if path in names:
return
if path in ctx.substate:
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 return
Durham Goode
revert: special case 'hg revert --all'...
r22573 path_ = path + '/'
for f in names:
if f.startswith(path_):
return
ui.warn("%s: %s\n" % (m.rel(path), msg))
Matt Harbison
revert: replace match.bad() monkey patching with match.badmatch()...
r25439 for abs in ctx.walk(matchmod.badmatch(m, badfn)):
Durham Goode
revert: special case 'hg revert --all'...
r22573 if abs not in names:
names[abs] = m.rel(abs), m.exact(abs)
# 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)
else:
Martin von Zweigbergk
revert: take fast path also when not reverting to '.'...
r24450 changes = repo.status(node1=node, match=m)
Durham Goode
revert: special case 'hg revert --all'...
r22573 for kind in changes:
for abs in kind:
names[abs] = m.rel(abs), m.exact(abs)
m = scmutil.matchfiles(repo, names)
Martin von Zweigbergk
revert: access status fields by name rather than index...
r23374 modified = set(changes.modified)
added = set(changes.added)
removed = set(changes.removed)
_deleted = set(changes.deleted)
unknown = set(changes.unknown)
unknown.update(changes.ignored)
clean = set(changes.clean)
Pierre-Yves David
revert: track added files with local modifications...
r22610 modadded = set()
Pierre-Yves David
revert: triage "deleted" files into more appropriate categories...
r22185
# split between files known in target manifest and the others
smf = set(mf)
# determine the exact nature of the deleted changesets
Pierre-Yves David
revert: explicitly track added but deleted file...
r22490 deladded = _deleted - smf
deleted = _deleted - deladded
Pierre-Yves David
revert: call status against revert target too...
r22155
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r24180 # We need to account for the state of the file in the dirstate,
# even when we revert against something else than parent. This will
Pierre-Yves David
revert: call status against revert target too...
r22155 # slightly alter the behavior of revert (doing back up or not, delete
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23139 # or just forget etc).
Pierre-Yves David
revert: call status against revert target too...
r22155 if parent == node:
dsmodified = modified
dsadded = added
dsremoved = removed
Pierre-Yves David
revert: look for copy information for all local modifications...
r23403 # store all local modifications, useful later for rename detection
localchanges = dsmodified | dsadded
Pierre-Yves David
revert: call status against revert target too...
r22155 modified, added, removed = set(), set(), set()
else:
changes = repo.status(node1=parent, match=m)
Martin von Zweigbergk
revert: access status fields by name rather than index...
r23374 dsmodified = set(changes.modified)
dsadded = set(changes.added)
dsremoved = set(changes.removed)
Pierre-Yves David
revert: look for copy information for all local modifications...
r23403 # store all local modifications, useful later for rename detection
localchanges = dsmodified | dsadded
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304
Pierre-Yves David
revert: use "remove" information from both statuses...
r22188 # only take into account for removes between wc and target
clean |= dsremoved - removed
dsremoved &= removed
# distinct between dirstate remove and other
removed -= dsremoved
Pierre-Yves David
revert: track added files with local modifications...
r22610 modadded = added & dsmodified
added -= modadded
Pierre-Yves David
revert: use modified information from both statuses...
r22190 # tell newly modified apart.
dsmodified &= modified
Augie Fackler
cmdutil: typo fix in comment
r29103 dsmodified |= modified & dsadded # dirstate added may need backup
Pierre-Yves David
revert: use modified information from both statuses...
r22190 modified -= dsmodified
Pierre-Yves David
revert: split between newly added file and file added in other changeset...
r22488 # We need to wait for some post-processing to update this set
# before making the distinction. The dirstate will be used for
# that purpose.
Pierre-Yves David
revert: simplify handling of `added` files...
r22208 dsadded = added
Pierre-Yves David
revert: detect files added during a merge...
r22209 # in case of merge, files that are actually added can be reported as
# modified, we need to post process the result
if p2 != nullid:
Pierre-Yves David
revert: properly revert to ancestor of p2 during merge (issue5052)...
r28192 mergeadd = dsmodified - smf
Pierre-Yves David
revert: detect files added during a merge...
r22209 dsadded |= mergeadd
dsmodified -= mergeadd
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304
Pierre-Yves David
revert: add some inline comments...
r21575 # if f is a rename, update `names` to also revert the source
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 cwd = repo.getcwd()
Pierre-Yves David
revert: look for copy information for all local modifications...
r23403 for f in localchanges:
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 src = repo.dirstate.copied(f)
Pierre-Yves David
revert: add an XXX about rename tracking...
r22213 # XXX should we check for rename down to target node?
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 if src and src not in names and repo.dirstate[src] == 'r':
Pierre-Yves David
revert: prefix variable names for dirstate status with "ds"...
r22154 dsremoved.add(src)
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 names[src] = (repo.pathto(src, cwd), True)
Pierre-Yves David
revert: split between newly added file and file added in other changeset...
r22488 # distinguish between file to forget and the other
added = set()
for abs in dsadded:
if repo.dirstate[abs] != 'a':
added.add(abs)
dsadded -= added
Pierre-Yves David
revert: explicitly track added but deleted file...
r22490 for abs in deladded:
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 if repo.dirstate[abs] == 'a':
Pierre-Yves David
revert: explicitly track added but deleted file...
r22490 dsadded.add(abs)
deladded -= dsadded
Pierre-Yves David
revert: detect unknown files in the same path as files marked as removed...
r22396 # For files marked as removed, we check if an unknown file is present at
# the same path. If a such file exists it may need to be backed up.
# Making the distinction at this stage helps have simpler backup
# logic.
removunk = set()
for abs in removed:
target = repo.wjoin(abs)
if os.path.lexists(target):
removunk.add(abs)
removed -= removunk
dsremovunk = set()
for abs in dsremoved:
target = repo.wjoin(abs)
if os.path.lexists(target):
dsremovunk.add(abs)
dsremoved -= dsremovunk
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304
Pierre-Yves David
revert: add some inline comments...
r21575 # action to be actually performed by revert
# (<list of file>, message>) tuple
Pierre-Yves David
revert: group action into a single dictionary...
r21576 actions = {'revert': ([], _('reverting %s\n')),
'add': ([], _('adding %s\n')),
Pierre-Yves David
revert: have an explicit action for "forget"...
r22489 'remove': ([], _('removing %s\n')),
Pierre-Yves David
revert: add a `drop` action...
r22491 'drop': ([], _('removing %s\n')),
Pierre-Yves David
revert: have an explicit action for "forget"...
r22489 'forget': ([], _('forgetting %s\n')),
Pierre-Yves David
revert: use actions[...] in all disptable cases...
r22231 'undelete': ([], _('undeleting %s\n')),
Pierre-Yves David
revert: add a message to noop action...
r22234 'noop': (None, _('no changes needed to %s\n')),
Pierre-Yves David
revert: handle unknown files through status...
r22236 'unknown': (None, _('file not managed: %s\n')),
Pierre-Yves David
revert: use actions[...] in all disptable cases...
r22231 }
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304
Pierre-Yves David
revert: small refactoring in the way backup value are handled...
r22608 # "constant" that convey the backup strategy.
# All set to `discard` if `no-backup` is set do avoid checking
# no_backup lower in the code.
Pierre-Yves David
revert: distinguish between "check" and "backup" strategy...
r22609 # These values are ordered for comparison purposes
skarlage
revert: don't backup if no files reverted in interactive mode (issue4793)...
r29498 backupinteractive = 3 # do backup if interactively modified
Pierre-Yves David
revert: small refactoring in the way backup value are handled...
r22608 backup = 2 # unconditionally do backup
Pierre-Yves David
revert: distinguish between "check" and "backup" strategy...
r22609 check = 1 # check if the existing file differs from target
Pierre-Yves David
revert: small refactoring in the way backup value are handled...
r22608 discard = 0 # never do backup
if opts.get('no_backup'):
skarlage
revert: don't backup if no files reverted in interactive mode (issue4793)...
r29498 backupinteractive = backup = check = discard
if interactive:
dsmodifiedbackup = backupinteractive
else:
dsmodifiedbackup = backup
tobackup = set()
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304
Pierre-Yves David
revert: properly back up added files with local modification...
r22611 backupanddel = actions['remove']
if not opts.get('no_backup'):
backupanddel = actions['drop']
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 disptable = (
# dispatch table:
# file state
Pierre-Yves David
revert: move manifest membership condition outside of the loop...
r22153 # action
# make backup
Pierre-Yves David
revert: add documentation in the dispatch table...
r22371
## Sets that results that will change file on disk
# Modified compared to target, no local change
Pierre-Yves David
revert: add more padding in the dispatch list...
r22372 (modified, actions['revert'], discard),
Pierre-Yves David
revert: distinguish between deleted file and locally modified...
r22397 # Modified compared to target, but local file is deleted
(deleted, actions['revert'], discard),
Pierre-Yves David
revert: add documentation in the dispatch table...
r22371 # Modified compared to target, local change
skarlage
revert: don't backup if no files reverted in interactive mode (issue4793)...
r29498 (dsmodified, actions['revert'], dsmodifiedbackup),
Pierre-Yves David
revert: add documentation in the dispatch table...
r22371 # Added since target
Pierre-Yves David
revert: split between newly added file and file added in other changeset...
r22488 (added, actions['remove'], discard),
# Added in working directory
Pierre-Yves David
revert: have an explicit action for "forget"...
r22489 (dsadded, actions['forget'], discard),
Pierre-Yves David
revert: track added files with local modifications...
r22610 # Added since target, have local modification
Pierre-Yves David
revert: properly back up added files with local modification...
r22611 (modadded, backupanddel, backup),
Pierre-Yves David
revert: explicitly track added but deleted file...
r22490 # Added since target but file is missing in working directory
Pierre-Yves David
revert: add a `drop` action...
r22491 (deladded, actions['drop'], discard),
Pierre-Yves David
revert: add documentation in the dispatch table...
r22371 # Removed since target, before working copy parent
Pierre-Yves David
revert: detect unknown files in the same path as files marked as removed...
r22396 (removed, actions['add'], discard),
# Same as `removed` but an unknown file exists at the same path
Pierre-Yves David
revert: distinguish between "check" and "backup" strategy...
r22609 (removunk, actions['add'], check),
Pierre-Yves David
revert: add documentation in the dispatch table...
r22371 # Removed since targe, marked as such in working copy parent
Pierre-Yves David
revert: detect unknown files in the same path as files marked as removed...
r22396 (dsremoved, actions['undelete'], discard),
# Same as `dsremoved` but an unknown file exists at the same path
Pierre-Yves David
revert: distinguish between "check" and "backup" strategy...
r22609 (dsremovunk, actions['undelete'], check),
Pierre-Yves David
revert: add documentation in the dispatch table...
r22371 ## the following sets does not result in any file changes
# File with no modification
Pierre-Yves David
revert: add more padding in the dispatch list...
r22372 (clean, actions['noop'], discard),
Pierre-Yves David
revert: add documentation in the dispatch table...
r22371 # Existing file, not tracked anywhere
Pierre-Yves David
revert: add more padding in the dispatch list...
r22372 (unknown, actions['unknown'], discard),
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 )
for abs, (rel, exact) in sorted(names.items()):
Pierre-Yves David
revert: add some inline comments...
r21575 # target file to be touch on disk (relative to cwd)
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 target = repo.wjoin(abs)
Pierre-Yves David
revert: add some inline comments...
r21575 # search the entry in the dispatch table.
Pierre-Yves David
revert: inline a now useless closure...
r22212 # if the file is in any of these sets, it was touched in the working
Pierre-Yves David
revert: add some inline comments...
r21575 # directory parent and we are sure it needs to be reverted.
Pierre-Yves David
revert: explode the action tuple in the for loop...
r22232 for table, (xlist, msg), dobackup in disptable:
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 if abs not in table:
continue
Pierre-Yves David
revert: simplify loop conditional...
r22233 if xlist is not None:
xlist.append(abs)
skarlage
revert: don't backup if no files reverted in interactive mode (issue4793)...
r29498 if dobackup:
# If in interactive mode, don't automatically create
# .orig files (issue4793)
if dobackup == backupinteractive:
tobackup.add(abs)
elif (backup <= dobackup or wctx[abs].cmp(ctx[abs])):
Siddharth Agarwal
origpath: move from cmdutil to scmutil...
r27651 bakname = scmutil.origpath(ui, repo, rel)
Pierre-Yves David
revert: distinguish between "check" and "backup" strategy...
r22609 ui.note(_('saving current version of %s as %s\n') %
(rel, bakname))
if not opts.get('dry_run'):
Laurent Charignon
revert: fix --interactive on local modification (issue4576)...
r24475 if interactive:
util.copyfile(target, bakname)
else:
util.rename(target, bakname)
Pierre-Yves David
revert: simplify loop conditional...
r22233 if ui.verbose or not exact:
if not isinstance(msg, basestring):
msg = msg(abs)
ui.status(msg % rel)
elif exact:
Pierre-Yves David
revert: add a message to noop action...
r22234 ui.warn(msg % rel)
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 break
Pierre-Yves David
revert: add some inline comments...
r21575
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304 if not opts.get('dry_run'):
Durham Goode
revert: move prefetch to after the actions logic...
r23965 needdata = ('revert', 'add', 'undelete')
_revertprefetch(repo, ctx, *[actions[name][0] for name in needdata])
skarlage
revert: don't backup if no files reverted in interactive mode (issue4793)...
r29498 _performrevert(repo, parents, ctx, actions, interactive, tobackup)
Bryan O'Sullivan
revert: ensure that copies and renames are honored (issue3920)...
r19129
Matt Harbison
revert: display full subrepo output with --dry-run...
r24134 if targetsubs:
# Revert the subrepos on the revert list
for sub in targetsubs:
Matt Harbison
revert: handle subrepos missing in the given --rev...
r24463 try:
Matt Harbison
revert: evaluate subrepos to revert against the working directory...
r24464 wctx.sub(sub).revert(ctx.substate[sub], *pats, **opts)
Matt Harbison
revert: handle subrepos missing in the given --rev...
r24463 except KeyError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort("subrepository '%s' does not exist in %s!"
Matt Harbison
revert: handle subrepos missing in the given --rev...
r24463 % (sub, short(ctx.node())))
Angel Ezquerra
revert: move bulk of revert command from commands to cmdutil...
r16304
Pierre-Yves David
revert: add a way for external extensions to prefetch file data...
r22370 def _revertprefetch(repo, ctx, *files):
"""Let extension changing the storage layer prefetch content"""
pass
skarlage
revert: don't backup if no files reverted in interactive mode (issue4793)...
r29498 def _performrevert(repo, parents, ctx, actions, interactive=False,
tobackup=None):
Pierre-Yves David
revert: group action into a single dictionary...
r21576 """function that actually perform all the actions computed for revert
Pierre-Yves David
revert: extract actual revert in its own function...
r20571
This is an independent function to let extension to plug in and react to
the imminent revert.
Mads Kiilerich
spelling: fixes from spell checker
r21024 Make sure you have the working directory locked when calling this function.
Pierre-Yves David
revert: extract actual revert in its own function...
r20571 """
parent, p2 = parents
node = ctx.node()
liscju
revert: makes interactive mode ask to forget added files (issue4936)...
r27985 excluded_files = []
matcher_opts = {"exclude": excluded_files}
Pierre-Yves David
revert: extract actual revert in its own function...
r20571 def checkout(f):
fc = ctx[f]
FUJIWARA Katsunori
cmdutil: remove useless dirstate.normallookup() invocation in revert()...
r25755 repo.wwrite(f, fc.data(), fc.flags())
Pierre-Yves David
revert: extract actual revert in its own function...
r20571
audit_path = pathutil.pathauditor(repo.root)
Pierre-Yves David
revert: have an explicit action for "forget"...
r22489 for f in actions['forget'][0]:
liscju
revert: makes interactive mode ask to forget added files (issue4936)...
r27985 if interactive:
choice = \
repo.ui.promptchoice(
_("forget added file %s (yn)?$$ &Yes $$ &No")
% f)
if choice == 0:
repo.dirstate.drop(f)
else:
excluded_files.append(repo.wjoin(f))
else:
repo.dirstate.drop(f)
Pierre-Yves David
revert: group action into a single dictionary...
r21576 for f in actions['remove'][0]:
Pierre-Yves David
revert: extract actual revert in its own function...
r20571 audit_path(f)
Matt Harbison
revert: restore the ability to revert across case only renames (issue4481)...
r24857 try:
util.unlinkpath(repo.wjoin(f))
except OSError:
pass
Pierre-Yves David
revert: add a `drop` action...
r22491 repo.dirstate.remove(f)
for f in actions['drop'][0]:
audit_path(f)
Pierre-Yves David
revert: extract actual revert in its own function...
r20571 repo.dirstate.remove(f)
normal = None
if node == parent:
# We're reverting to our parent. If possible, we'd like status
# to report the file as clean. We have to use normallookup for
# merges to avoid losing information about merged/dirty files.
if p2 != nullid:
normal = repo.dirstate.normallookup
else:
normal = repo.dirstate.normal
Laurent Charignon
revert: add flag to make revert interactive
r24359
Laurent Charignon
revert: fix edition of newly added file during --interactive...
r25259 newlyaddedandmodifiedfiles = set()
Laurent Charignon
revert: add flag to make revert interactive
r24359 if interactive:
# Prompt the user for changes to revert
torevert = [repo.wjoin(f) for f in actions['revert'][0]]
liscju
revert: makes interactive mode ask to forget added files (issue4936)...
r27985 m = scmutil.match(ctx, torevert, matcher_opts)
Laurent Charignon
revert: make revert --interactive use git style diff...
r25258 diffopts = patch.difffeatureopts(repo.ui, whitespace=True)
diffopts.nodates = True
diffopts.git = True
timeless
cleanup: remove superfluous space after space after equals (python)
r27637 reversehunks = repo.ui.configbool('experimental',
'revertalternateinteractivemode',
True)
Laurent Charignon
revert: add an experimental config to use inverted selection...
r25424 if reversehunks:
diff = patch.diff(repo, ctx.node(), None, m, opts=diffopts)
else:
diff = patch.diff(repo, None, ctx.node(), m, opts=diffopts)
Laurent Charignon
revert: add flag to make revert interactive
r24359 originalchunks = patch.parsepatch(diff)
Denis Laxalde
patch: define full messages for interactive record/revert...
r29326 operation = 'discard' if node == parent else 'revert'
Laurent Charignon
revert: add an experimental config to use inverted selection...
r25424
Laurent Charignon
revert: add flag to make revert interactive
r24359 try:
Laurent Charignon
revert: add an experimental config to use inverted selection...
r25424
Denis Laxalde
revert: use "discard"/"revert" verb when reverting interactively (issue5143)...
r29283 chunks, opts = recordfilter(repo.ui, originalchunks,
operation=operation)
Laurent Charignon
revert: add an experimental config to use inverted selection...
r25424 if reversehunks:
chunks = patch.reversehunks(chunks)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except patch.PatchError as err:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('error parsing patch: %s') % err)
Laurent Charignon
revert: add flag to make revert interactive
r24359
Laurent Charignon
revert: fix edition of newly added file during --interactive...
r25259 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
skarlage
revert: don't backup if no files reverted in interactive mode (issue4793)...
r29498 if tobackup is None:
tobackup = set()
Laurent Charignon
revert: add flag to make revert interactive
r24359 # Apply changes
timeless
pycompat: switch to util.stringio for py3 compat
r28861 fp = stringio()
Laurent Charignon
revert: add flag to make revert interactive
r24359 for c in chunks:
skarlage
revert: don't backup if no files reverted in interactive mode (issue4793)...
r29498 # Create a backup file only if this hunk should be backed up
if ishunk(c) and c.header.filename() in tobackup:
abs = c.header.filename()
target = repo.wjoin(abs)
bakname = scmutil.origpath(repo.ui, repo, m.rel(abs))
util.copyfile(target, bakname)
tobackup.remove(abs)
Laurent Charignon
revert: add flag to make revert interactive
r24359 c.write(fp)
dopatch = fp.tell()
fp.seek(0)
if dopatch:
try:
patch.internalpatch(repo.ui, repo, fp, 1, eolmode=None)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except patch.PatchError as err:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(str(err))
Laurent Charignon
revert: add flag to make revert interactive
r24359 del fp
else:
for f in actions['revert'][0]:
FUJIWARA Katsunori
cmdutil: remove useless dirstate.normallookup() invocation in revert()...
r25755 checkout(f)
Laurent Charignon
revert: add flag to make revert interactive
r24359 if normal:
normal(f)
Pierre-Yves David
revert: extract actual revert in its own function...
r20571
Pierre-Yves David
revert: group action into a single dictionary...
r21576 for f in actions['add'][0]:
Laurent Charignon
revert: fix edition of newly added file during --interactive...
r25259 # Don't checkout modified files, they are already created by the diff
if f not in newlyaddedandmodifiedfiles:
checkout(f)
repo.dirstate.add(f)
Pierre-Yves David
revert: extract actual revert in its own function...
r20571
normal = repo.dirstate.normallookup
if node == parent and p2 == nullid:
normal = repo.dirstate.normal
Pierre-Yves David
revert: group action into a single dictionary...
r21576 for f in actions['undelete'][0]:
Pierre-Yves David
revert: extract actual revert in its own function...
r20571 checkout(f)
normal(f)
copied = copies.pathcopies(repo[parent], ctx)
Pierre-Yves David
revert: group action into a single dictionary...
r21576 for f in actions['add'][0] + actions['undelete'][0] + actions['revert'][0]:
Pierre-Yves David
revert: extract actual revert in its own function...
r20571 if f in copied:
repo.dirstate.copy(copied[f], f)
Adrian Buehlmann
commands: use a decorator to build table incrementally...
r14297 def command(table):
Gregory Szorc
cmdutil: better document command()
r21766 """Returns a function object to be used as a decorator for making commands.
This function receives a command table as its argument. The table should
be a dict.
The returned function can be used as a decorator for adding commands
to that command table. This function accepts multiple arguments to define
a command.
The first argument is the command name.
The options argument is an iterable of tuples defining command arguments.
See ``mercurial.fancyopts.fancyopts()`` for the format of each tuple.
Adrian Buehlmann
commands: use a decorator to build table incrementally...
r14297
Gregory Szorc
cmdutil: better document command()
r21766 The synopsis argument defines a short, one line summary of how to use the
command. This shows up in the help output.
Gregory Szorc
commands: add norepo argument to command decorator...
r21767
The norepo argument defines whether the command does not require a
local repository. Most commands operate against a repository, thus the
default is False.
Gregory Szorc
cmdutil: add optionalrepo argument to command decorator
r21774
The optionalrepo argument defines whether the command optionally requires
a local repository.
Gregory Szorc
cmdutil: support inferrepo in command decorator
r21777
The inferrepo argument defines whether to try to find a repository from the
command line arguments. If True, arguments will be examined for potential
repository locations. See ``findrepo()``. If a repository is found, it
will be used.
Gregory Szorc
cmdutil: better document command()
r21766 """
Gregory Szorc
cmdutil: support inferrepo in command decorator
r21777 def cmd(name, options=(), synopsis=None, norepo=False, optionalrepo=False,
inferrepo=False):
Adrian Buehlmann
commands: use a decorator to build table incrementally...
r14297 def decorator(func):
Yuya Nishihara
dispatch: store norepo/optionalrepo/inferrepo attributes in function (API)...
r28313 func.norepo = norepo
func.optionalrepo = optionalrepo
func.inferrepo = inferrepo
Adrian Buehlmann
commands: use a decorator to build table incrementally...
r14297 if synopsis:
Pierre-Yves David
cmdutil: make options argument optional...
r18235 table[name] = func, list(options), synopsis
Adrian Buehlmann
commands: use a decorator to build table incrementally...
r14297 else:
Pierre-Yves David
cmdutil: make options argument optional...
r18235 table[name] = func, list(options)
Adrian Buehlmann
commands: use a decorator to build table incrementally...
r14297 return func
return decorator
return cmd
Bryan O'Sullivan
summary: augment output with info from extensions
r19211
Augie Fackler
checkunresolved: move to new package to help avoid import cycles...
r30494 checkunresolved = mergeutil.checkunresolved
timeless
cmdutil: refactor checkunresolved...
r30272
FUJIWARA Katsunori
outgoing: introduce "outgoinghooks" to avoid redundant outgoing check...
r21051 # a list of (ui, repo, otherpeer, opts, missing) functions called by
# commands.outgoing. "missing" is "missing" of the result of
# "findcommonoutgoing()"
outgoinghooks = util.hooks()
Bryan O'Sullivan
summary: augment output with info from extensions
r19211 # a list of (ui, repo) functions called by commands.summary
summaryhooks = util.hooks()
Matt Mackall
cmdutil: core functionality to block during multistep commands (issue3955)...
r19474
FUJIWARA Katsunori
summary: introduce "summaryremotehooks" to avoid redundant incoming/outgoing check...
r21047 # a list of (ui, repo, opts, changes) functions called by commands.summary.
#
# functions should return tuple of booleans below, if 'changes' is None:
# (whether-incomings-are-needed, whether-outgoings-are-needed)
#
# otherwise, 'changes' is a tuple of tuples below:
# - (sourceurl, sourcebranch, sourcepeer, incoming)
# - (desturl, destbranch, destpeer, outgoing)
summaryremotehooks = util.hooks()
Matt Mackall
cmdutil: core functionality to block during multistep commands (issue3955)...
r19474 # A list of state files kept by multistep operations like graft.
# Since graft cannot be aborted, it is considered 'clearable' by update.
# note: bisect is intentionally excluded
Matt Mackall
checkunfinished: accommodate histedit quirk...
r19496 # (state file, clearable, allowcommit, error, hint)
Matt Mackall
cmdutil: core functionality to block during multistep commands (issue3955)...
r19474 unfinishedstates = [
Matt Mackall
checkunfinished: accommodate histedit quirk...
r19496 ('graftstate', True, False, _('graft in progress'),
Matt Mackall
update: add tracking of interrupted updates (issue3113)...
r19482 _("use 'hg graft --continue' or 'hg update' to abort")),
Matt Mackall
checkunfinished: accommodate histedit quirk...
r19496 ('updatestate', True, False, _('last update was interrupted'),
Matt Mackall
update: add tracking of interrupted updates (issue3113)...
r19482 _("use 'hg update' to get a consistent checkout"))
Matt Mackall
cmdutil: core functionality to block during multistep commands (issue3955)...
r19474 ]
Matt Mackall
checkunfinished: accommodate histedit quirk...
r19496 def checkunfinished(repo, commit=False):
Matt Mackall
cmdutil: core functionality to block during multistep commands (issue3955)...
r19474 '''Look for an unfinished multistep operation, like graft, and abort
if found. It's probably good to check this right before
bailifchanged().
'''
Matt Mackall
checkunfinished: accommodate histedit quirk...
r19496 for f, clearable, allowcommit, msg, hint in unfinishedstates:
if commit and allowcommit:
continue
Matt Mackall
cmdutil: core functionality to block during multistep commands (issue3955)...
r19474 if repo.vfs.exists(f):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(msg, hint=hint)
Matt Mackall
cmdutil: core functionality to block during multistep commands (issue3955)...
r19474
def clearunfinished(repo):
'''Check for unfinished operations (as above), and clear the ones
that are clearable.
'''
Matt Mackall
checkunfinished: accommodate histedit quirk...
r19496 for f, clearable, allowcommit, msg, hint in unfinishedstates:
Matt Mackall
cmdutil: core functionality to block during multistep commands (issue3955)...
r19474 if not clearable and repo.vfs.exists(f):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(msg, hint=hint)
Matt Mackall
checkunfinished: accommodate histedit quirk...
r19496 for f, clearable, allowcommit, msg, hint in unfinishedstates:
Matt Mackall
cmdutil: core functionality to block during multistep commands (issue3955)...
r19474 if clearable and repo.vfs.exists(f):
util.unlink(repo.join(f))
FUJIWARA Katsunori
cmdutil: add class to restore dirstate during unexpected failure...
r24991
timeless
resolve: suggest the next action...
r27624 afterresolvedstates = [
timeless
graft: hook afterresolvedstates
r27625 ('graftstate',
_('hg graft --continue')),
timeless
resolve: suggest the next action...
r27624 ]
timeless
cmdutil: provide a way to report how to continue...
r28120 def howtocontinue(repo):
'''Check for an unfinished operation and return the command to finish
it.
Mads Kiilerich
spelling: fixes of non-dictionary words
r30332 afterresolvedstates tuples define a .hg/{file} and the corresponding
timeless
cmdutil: provide a way to report how to continue...
r28120 command needed to finish it.
Returns a (msg, warning) tuple. 'msg' is a string and 'warning' is
a boolean.
'''
contmsg = _("continue: %s")
timeless
resolve: suggest the next action...
r27624 for f, msg in afterresolvedstates:
if repo.vfs.exists(f):
timeless
cmdutil: provide a way to report how to continue...
r28120 return contmsg % msg, True
workingctx = repo[None]
dirty = any(repo.status()) or any(workingctx.sub(s).dirty()
for s in workingctx.substate)
if dirty:
return contmsg % _("hg commit"), False
return None, None
def checkafterresolved(repo):
'''Inform the user about the next action after completing hg resolve
If there's a matching afterresolvedstates, howtocontinue will yield
repo.ui.warn as the reporter.
Otherwise, it will yield repo.ui.note.
'''
msg, warning = howtocontinue(repo)
if msg is not None:
if warning:
repo.ui.warn("%s\n" % msg)
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.
Uses howtocontinue() to find the active task.
If there's no task (repo.ui.note for 'hg commit'), it does not offer
a hint.
'''
after = howtocontinue(repo)
hint = None
if after[1]:
hint = after[0]
raise error.Abort(_('no %s in progress') % task, hint=hint)
timeless
resolve: suggest the next action...
r27624
Augie Fackler
cmdutil: mark dirstateguard as deprecated...
r30493 class dirstateguard(dirstateguardmod.dirstateguard):
def __init__(self, repo, name):
dirstateguardmod.dirstateguard.__init__(self, repo, name)
repo.ui.deprecwarn(
'dirstateguard has moved from cmdutil to dirstateguard',
'4.1')