Mercurial > evolve
diff hgext/evolve.py @ 1058:00bc31523074
uncommit: add a --rev argument
The uncommit command now taks a --rev argument. This lets restore the file
content in the current commit to another revision (instead of just is parent
content). This still does not touch the working directory content.\
This allow the longly awaited:
hg uncommit --hidden --rev 'precursors(.)'
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Fri, 15 Aug 2014 00:46:23 -0700 |
parents | cfe1b9d3e5d9 |
children | 742c1ce79a96 |
line wrap: on
line diff
--- 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"))