# HG changeset patch # User Pierre-Yves David # Date 1408132561 25200 # Node ID d1baf69b935c66b170ae597c658489c082d53776 # Parent 00bc3152307497337b3bf37a11f105cff8275ed5# Parent 168dfc839eca3523745d7d7593cfc76bbd4bcd2c merge with stable diff -r 168dfc839eca -r d1baf69b935c README --- a/README Thu Aug 14 15:30:04 2014 -0700 +++ b/README Fri Aug 15 12:56:01 2014 -0700 @@ -57,6 +57,10 @@ Changelog ========= +4.2.0 -- + +- uncommit: add a --rev argument + 4.1.1 -- - properly skip marker creating if patch apply cleanly diff -r 168dfc839eca -r d1baf69b935c hgext/evolve.py --- a/hgext/evolve.py Thu Aug 14 15:30:04 2014 -0700 +++ b/hgext/evolve.py Fri Aug 15 12:56:01 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")) diff -r 168dfc839eca -r d1baf69b935c tests/test-tutorial.t --- a/tests/test-tutorial.t Thu Aug 14 15:30:04 2014 -0700 +++ b/tests/test-tutorial.t Fri Aug 15 12:56:01 2014 -0700 @@ -446,11 +446,16 @@ 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. options: -a --all uncommit all changes when no arguments given + -r --rev VALUE revert commit content to REV instead -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns diff -r 168dfc839eca -r d1baf69b935c tests/test-uncommit.t --- a/tests/test-uncommit.t Thu Aug 14 15:30:04 2014 -0700 +++ b/tests/test-uncommit.t Fri Aug 15 12:56:01 2014 -0700 @@ -336,3 +336,25 @@ [8] touncommit $ hg uncommit aa 1 new unstable changesets + +Test uncommiting agains a different base + + $ hg cat b --rev . + b + b + $ hg cat b --rev .^ + b + $ hg cat b --rev 0 + b: no such file in rev 07f494440405 + [1] + $ hg uncommit --rev 0 b + $ hg cat b --rev . + b: no such file in rev 5b27f6b17da2 + [1] + +Test uncommiting precursors + + $ hg uncommit --hidden --rev 'precursors(.)' b + $ hg cat b --rev . + b + b