--- a/hgext/evolve.py Thu Aug 14 15:26:55 2014 -0700
+++ b/hgext/evolve.py Fri Aug 15 00:46:23 2014 -0700
@@ -1859,25 +1859,45 @@
_alias, commitcmd = cmdutil.findcmd('commit', commands.table)
return commitcmd[0](ui, repo, *pats, **opts)
-def _commitfiltered(repo, ctx, match):
+
+def _touchedbetween(repo, source, dest, match=None):
+ touched = set()
+ for files in repo.status(source, dest, match=match)[:3]:
+ touched.update(files)
+ return touched
+
+def _commitfiltered(repo, ctx, match, target=None):
"""Recommit ctx with changed files not in match. Return the new
node identifier, or None if nothing changed.
"""
base = ctx.p1()
- m, a, r = repo.status(base, ctx)[:3]
- allfiles = set(m + a + r)
- files = set(f for f in allfiles if not match(f))
- if files == allfiles:
+ if target is None:
+ target = base
+ # ctx
+ initialfiles = _touchedbetween(repo, base, ctx)
+ if base == target:
+ affected = set(f for f in initialfiles if match(f))
+ newcontent = set()
+ else:
+ affected = _touchedbetween(repo, target, ctx, match=match)
+ newcontent = _touchedbetween(repo, target, base, match=match)
+ # The commit touchs all existing files
+ # + all file that needs a new content
+ # - the file affected bny uncommit with the same content than base.
+ files = (initialfiles - affected) | newcontent
+ if not newcontent and files == initialfiles:
return None
# Filter copies
- copied = copies.pathcopies(base, ctx)
+ copied = copies.pathcopies(target, ctx)
copied = dict((src, dst) for src, dst in copied.iteritems()
if dst in files)
- def filectxfn(repo, memctx, path):
- if path not in ctx:
+ def filectxfn(repo, memctx, path, contentctx=ctx, redirect=newcontent):
+ if path in redirect:
+ return filectxfn(repo, memctx, path, contentctx=target, redirect=())
+ if path not in contentctx:
raise IOError()
- fctx = ctx[path]
+ fctx = contentctx[path]
flags = fctx.flags()
mctx = memfilectx(repo, fctx.path(), fctx.data(),
islink='l' in flags,
@@ -1943,6 +1963,7 @@
@command('^uncommit',
[('a', 'all', None, _('uncommit all changes when no arguments given')),
+ ('r', 'rev', '', _('revert commit content to REV instead')),
] + commands.walkopts,
_('[OPTION]... [NAME]'))
def uncommit(ui, repo, *pats, **opts):
@@ -1956,6 +1977,10 @@
The --include option specifies patterns to uncommit.
The --exclude option specifies patterns to keep in the commit.
+ The --rev argument let you change the commit file to a content of another
+ revision. It still does not change the content of your file in the working
+ directory.
+
Return 0 if changed files are uncommitted.
"""
@@ -1976,13 +2001,18 @@
oldphase = old.phase()
updatebookmarks = _bookmarksupdater(repo, old.node())
+
+ rev = None
+ if opts.get('rev'):
+ rev = scmutil.revsingle(repo, opts.get('rev'))
+
# Recommit the filtered changeset
tr = repo.transaction('uncommit')
newid = None
if (pats or opts.get('include') or opts.get('exclude')
or opts.get('all')):
match = scmutil.match(old, pats, opts)
- newid = _commitfiltered(repo, old, match)
+ newid = _commitfiltered(repo, old, match, target=rev)
if newid is None:
raise util.Abort(_('nothing to uncommit'),
hint=_("use --all to uncommit all files"))