Patchwork [1,of,4,status-via-diff] context: use manifest.diff() to compute most of status

login
register
mail settings
Submitter Augie Fackler
Date Jan. 7, 2015, 9:10 p.m.
Message ID <0c9ac5831b88025a0047.1420665023@arthedain.pit.corp.google.com>
Download mbox | patch
Permalink /patch/7354/
State Accepted
Commit d43948a910a516e9e1be38b69d773816cb879d8a
Headers show

Comments

Augie Fackler - Jan. 7, 2015, 9:10 p.m.
# HG changeset patch
# User Augie Fackler <augie@google.com>
# Date 1418675635 18000
#      Mon Dec 15 15:33:55 2014 -0500
# Node ID 0c9ac5831b88025a0047bed1529a94f3000c5820
# Parent  b9d06fa10ef29c012d48bd4f3c93fd7bf1347d40
context: use manifest.diff() to compute most of status

We can do a little tiny bit better by enhancing manifest.diff to
optionally include files that are in both sides. This will be done in
a followup patch.

Patch

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -135,24 +135,35 @@  class basectx(object):
         mf1 = other._manifestmatches(match, s)
         mf2 = self._manifestmatches(match, s)
 
-        modified, added, clean = [], [], []
+        modified, added = [], []
+        removed = []
+        clean = set()
         deleted, unknown, ignored = s.deleted, s.unknown, s.ignored
         deletedset = set(deleted)
-        withflags = mf1.withflags() | mf2.withflags()
-        for fn, mf2node in mf2.iteritems():
+        d = mf1.diff(mf2)
+        for fn, ((node1, flag1), (node2, flag2)) in d.iteritems():
             if fn in deletedset:
                 continue
-            if fn in mf1:
-                if ((fn in withflags and mf1.flags(fn) != mf2.flags(fn)) or
-                     (mf1[fn] != mf2node and
-                      (mf2node != _newnode or self[fn].cmp(other[fn])))):
-                    modified.append(fn)
-                elif listclean:
-                    clean.append(fn)
-                del mf1[fn]
+            if node1 is None:
+                added.append(fn)
+            elif node2 is None:
+                removed.append(fn)
+            elif node2 != _newnode:
+                # The file was not a new file in mf2, so an entry
+                # from diff is really a difference.
+                modified.append(fn)
+            elif self[fn].cmp(other[fn]):
+                # node2 was newnode, but the working file doesn't
+                # match the one in mf1.
+                modified.append(fn)
             else:
-                added.append(fn)
-        removed = mf1.keys()
+                clean.add(fn)
+        if listclean:
+            nondiff = (set(mf1) | set(mf2)) - set(d)
+            clean = list((clean | nondiff) - deletedset)
+        else:
+            clean = []
+
         if removed:
             # need to filter files if they are already reported as removed
             unknown = [fn for fn in unknown if fn not in mf1]