changeset 1059:d1baf69b935c

merge with stable
author Pierre-Yves David <pierre-yves.david@fb.com>
date Fri, 15 Aug 2014 12:56:01 -0700
parents 00bc31523074 (diff) 168dfc839eca (current diff)
children 742c1ce79a96
files README
diffstat 4 files changed, 71 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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"))
--- 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
   
--- 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