[PATCH 6 of 6 V2] context: override _dirstatestatus in workingcommitctx for correct matching

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Wed Dec 31 02:58:11 CST 2014


# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1420016143 -32400
#      Wed Dec 31 17:55:43 2014 +0900
# Node ID 1d738f28e7b9497e5de73e9c29f9d3b6b7942082
# Parent  10ae70180737bf74303df75359d40ef5066552df
context: override _dirstatestatus in workingcommitctx for correct matching

Before this patch, the result of "status()" on "workingcommitctx" may
incorrectly contain files other than ones to be committed, because
"workingctx._dirstatestatus()" returns the result of
"dirstate.status()" directly.

For correct matching, this patch overrides "_dirstatestatus" in
"workingcommitctx" and makes it return matched files only in
"self._status".

This patch uses empty list for "deleted", "unknown" and "ignored" of
status, because status between "changectx"s also makes them empty.

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -1581,6 +1581,32 @@
                                        listignored, listclean, listunknown)
         return s
 
+    def _dirstatestatus(self, match=None, ignored=False, clean=False,
+                        unknown=False):
+        """Return matched files only in ``self._status``
+
+        Uncommitted files appear "clean" via this context, even if
+        they aren't actually so in the working directory.
+        """
+        match = match or matchmod.always(self._repo.root, self._repo.getcwd())
+        if clean:
+            clean = [f for f in self._manifest if f not in self._changedset]
+        else:
+            clean = []
+        return scmutil.status([f for f in self._status.modified if match(f)],
+                              [f for f in self._status.added if match(f)],
+                              [f for f in self._status.removed if match(f)],
+                              [], [], [], clean)
+
+    @propertycache
+    def _changedset(self):
+        """Return the set of files changed in this context
+        """
+        changed = set(self._status.modified)
+        changed.update(self._status.added)
+        changed.update(self._status.removed)
+        return changed
+
 class memctx(committablectx):
     """Use memctx to perform in-memory commits via localrepo.commitctx().
 
diff --git a/tests/test-commit.t b/tests/test-commit.t
--- a/tests/test-commit.t
+++ b/tests/test-commit.t
@@ -434,7 +434,7 @@
   > changeset = {desc}
   >     HG: files={files}
   >     HG:
-  >     {splitlines(diff()) % ''
+  >     {splitlines(diff()) % 'HG: {line}\n'
   >    }HG:
   >     HG: files={files}\n
   > EOF
@@ -446,6 +446,11 @@
   foo bar
   HG: files=changed
   HG:
+  HG: --- a/changed	Thu Jan 01 00:00:00 1970 +0000
+  HG: +++ b/changed	Thu Jan 01 00:00:00 1970 +0000
+  HG: @@ -1,1 +1,2 @@
+  HG:  changed
+  HG: +changed
   HG:
   HG: files=changed
   $ hg status -amr
@@ -458,6 +463,51 @@
   $ hg rollback -q
 
   $ cat >> .hg/hgrc <<EOF
+  > [committemplate]
+  > changeset = {desc}
+  >     HG: files={files}
+  >     HG:
+  >     {splitlines(diff("changed")) % 'HG: {line}\n'
+  >    }HG:
+  >     HG: files={files}
+  >     HG:
+  >     {splitlines(diff("added")) % 'HG: {line}\n'
+  >    }HG:
+  >     HG: files={files}
+  >     HG:
+  >     {splitlines(diff("removed")) % 'HG: {line}\n'
+  >    }HG:
+  >     HG: files={files}\n
+  > EOF
+  $ HGEDITOR=cat hg commit -q -e -m "foo bar" added removed
+  foo bar
+  HG: files=added removed
+  HG:
+  HG:
+  HG: files=added removed
+  HG:
+  HG: --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  HG: +++ b/added	Thu Jan 01 00:00:00 1970 +0000
+  HG: @@ -0,0 +1,1 @@
+  HG: +added
+  HG:
+  HG: files=added removed
+  HG:
+  HG: --- a/removed	Thu Jan 01 00:00:00 1970 +0000
+  HG: +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  HG: @@ -1,1 +0,0 @@
+  HG: -removed
+  HG:
+  HG: files=added removed
+  $ hg status -amr
+  M changed
+  $ hg parents --template "M {file_mods}\nA {file_adds}\nR {file_dels}\n"
+  M 
+  A added
+  R removed
+  $ hg rollback -q
+
+  $ cat >> .hg/hgrc <<EOF
   > # disable customizing for subsequent tests
   > [committemplate]
   > changeset =
diff --git a/tests/test-context.py b/tests/test-context.py
--- a/tests/test-context.py
+++ b/tests/test-context.py
@@ -108,13 +108,31 @@
 print 'wcctx._status=%s' % (str(wcctx._status))
 
 print '=== with "always match":'
-actx1.status(other=wcctx)
+print actx1.status(other=wcctx)
 print 'wcctx._status=%s' % (str(wcctx._status))
-actx2.status(other=wcctx)
+print actx2.status(other=wcctx)
 print 'wcctx._status=%s' % (str(wcctx._status))
 
 print '=== with "always match" and "listclean=True":'
-actx1.status(other=wcctx, listclean=True)
+print actx1.status(other=wcctx, listclean=True)
 print 'wcctx._status=%s' % (str(wcctx._status))
-actx2.status(other=wcctx, listclean=True)
+print actx2.status(other=wcctx, listclean=True)
 print 'wcctx._status=%s' % (str(wcctx._status))
+
+print '=== with "pattern match":'
+print actx1.status(other=wcctx,
+                   match=scmutil.matchfiles(repo, ['bar-m', 'foo']))
+print 'wcctx._status=%s' % (str(wcctx._status))
+print actx2.status(other=wcctx,
+                   match=scmutil.matchfiles(repo, ['bar-m', 'foo']))
+print 'wcctx._status=%s' % (str(wcctx._status))
+
+print '=== with "pattern match" and "listclean=True":'
+print actx1.status(other=wcctx,
+                   match=scmutil.matchfiles(repo, ['bar-r', 'foo']),
+                   listclean=True)
+print 'wcctx._status=%s' % (str(wcctx._status))
+print actx2.status(other=wcctx,
+                   match=scmutil.matchfiles(repo, ['bar-r', 'foo']),
+                   listclean=True)
+print 'wcctx._status=%s' % (str(wcctx._status))
diff --git a/tests/test-context.py.out b/tests/test-context.py.out
--- a/tests/test-context.py.out
+++ b/tests/test-context.py.out
@@ -27,8 +27,22 @@
 == checking workingcommitctx.status:
 wcctx._status=<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
 === with "always match":
+<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
 wcctx._status=<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
+<status modified=[], added=['bar-a', 'bar-m', 'bar-r'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
 wcctx._status=<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
 === with "always match" and "listclean=True":
+<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=['bar-r', 'foo']>
 wcctx._status=<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
+<status modified=[], added=['bar-a', 'bar-m', 'bar-r'], removed=[], deleted=[], unknown=[], ignored=[], clean=['foo']>
 wcctx._status=<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
+=== with "pattern match":
+<status modified=['bar-m'], added=[], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
+wcctx._status=<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
+<status modified=[], added=['bar-m'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
+wcctx._status=<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
+=== with "pattern match" and "listclean=True":
+<status modified=[], added=[], removed=[], deleted=[], unknown=[], ignored=[], clean=['bar-r', 'foo']>
+wcctx._status=<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
+<status modified=[], added=['bar-r'], removed=[], deleted=[], unknown=[], ignored=[], clean=['foo']>
+wcctx._status=<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>


More information about the Mercurial-devel mailing list