Patchwork [3,of,4] revert: call status against revert target too

login
register
mail settings
Submitter Pierre-Yves David
Date Aug. 13, 2014, 8:13 p.m.
Message ID <404ea53d797b8de16c6c.1407960833@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/5373/
State Accepted
Headers show

Comments

Pierre-Yves David - Aug. 13, 2014, 8:13 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1403621232 -3600
#      Tue Jun 24 15:47:12 2014 +0100
# Node ID 404ea53d797b8de16c6ce15da42663b08cf9bcf7
# Parent  f92a82e1addd276b8a05488410c506e41c88bc4e
revert: call status against revert target too

We now call status against the target (and possibly against the working
directory parent is different). We do not use the information from the two
sources yet, but this is coming soon.

We need the status information aganst the dirstate in all case because we need
to be able to backup local modification.

Patch

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2364,14 +2364,34 @@  def revert(ui, repo, ctx, parents, *pats
                 names[abs] = m.rel(abs), m.exact(abs)
 
         # get the list of subrepos that must be reverted
         targetsubs = sorted(s for s in ctx.substate if m(s))
 
-        # Find status of all file in `names`. (Against working directory parent)
+        # Find status of all file in `names`.
         m = scmutil.matchfiles(repo, names)
-        changes = repo.status(node1=parent, match=m)[:4]
-        dsmodified, dsadded, dsremoved, dsdeleted = map(set, changes)
+
+        changes = repo.status(node1=node, match=m, clean=True)
+        modified = set(changes[0])
+        added    = set(changes[1])
+        removed  = set(changes[2])
+        deleted  = set(changes[3])
+
+        # We need to account for the state of file in the dirstate
+        #
+        # Even, when we revert agains something else than parent. this will
+        # slightly alter the behavior of revert (doing back up or not, delete
+        # or just forget etc)
+        if parent == node:
+            dsmodified = modified
+            dsadded = added
+            dsremoved = removed
+            modified, added, removed = set(), set(), set()
+        else:
+            changes = repo.status(node1=parent, match=m)
+            dsmodified = set(changes[0])
+            dsadded    = set(changes[1])
+            dsremoved  = set(changes[2])
 
         # if f is a rename, update `names` to also revert the source
         cwd = repo.getcwd()
         for f in dsadded:
             src = repo.dirstate.copied(f)
@@ -2393,12 +2413,12 @@  def revert(ui, repo, ctx, parents, *pats
         dsmodified -= missingmodified
         missingadded = dsadded - smf
         dsadded -= missingadded
         missingremoved = dsremoved - smf
         dsremoved -= missingremoved
-        missingdeleted = dsdeleted - smf
-        dsdeleted -= missingdeleted
+        missingdeleted = deleted - smf
+        deleted -= missingdeleted
 
         # action to be actually performed by revert
         # (<list of file>, message>) tuple
         actions = {'revert': ([], _('reverting %s\n')),
                    'add': ([], _('adding %s\n')),
@@ -2414,11 +2434,11 @@  def revert(ui, repo, ctx, parents, *pats
             (missingmodified,  (actions['remove'],   True)),
             (dsadded,          (actions['revert'],   True)),
             (missingadded,     (actions['remove'],   False)),
             (dsremoved,        (actions['undelete'], True)),
             (missingremoved,   (None,                False)),
-            (dsdeleted,        (actions['revert'],   False)),
+            (deleted,          (actions['revert'],   False)),
             (missingdeleted,   (actions['remove'],   False)),
             )
 
         for abs, (rel, exact) in sorted(names.items()):
             # hash on file in target manifest (or None if missing from target)