changeset 47512:769037a279ec

dirstate-entry: add a `state` property (and use it) This replace the [0] access. Ultimately is we should probably get ride of this in its current form. However this is a good transitional solution to move away for tuple indexing for now. Differential Revision: https://phab.mercurial-scm.org/D10954
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Sun, 04 Jul 2021 03:29:20 +0200
parents eaae39894312
children 10e740292dff
files mercurial/cext/parsers.c mercurial/dirstate.py mercurial/pure/parsers.py
diffstat 3 files changed, 45 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/cext/parsers.c	Sat Jul 03 19:52:00 2021 +0200
+++ b/mercurial/cext/parsers.c	Sun Jul 04 03:29:20 2021 +0200
@@ -150,6 +150,16 @@
     {NULL} /* Sentinel */
 };
 
+static PyObject *dirstatetuple_get_state(dirstateTupleObject *self)
+{
+	return PyBytes_FromStringAndSize(&self->state, 1);
+};
+
+static PyGetSetDef dirstatetuple_getset[] = {
+    {"state", (getter)dirstatetuple_get_state, NULL, "state", NULL},
+    {NULL} /* Sentinel */
+};
+
 PyTypeObject dirstateTupleType = {
     PyVarObject_HEAD_INIT(NULL, 0)      /* header */
     "dirstate_tuple",                   /* tp_name */
@@ -180,7 +190,7 @@
     0,                                  /* tp_iternext */
     dirstatetuple_methods,              /* tp_methods */
     0,                                  /* tp_members */
-    0,                                  /* tp_getset */
+    dirstatetuple_getset,               /* tp_getset */
     0,                                  /* tp_base */
     0,                                  /* tp_dict */
     0,                                  /* tp_descr_get */
--- a/mercurial/dirstate.py	Sat Jul 03 19:52:00 2021 +0200
+++ b/mercurial/dirstate.py	Sun Jul 04 03:29:20 2021 +0200
@@ -311,8 +311,15 @@
           r  marked for removal
           a  marked for addition
           ?  not tracked
+
+        XXX The "state" is a bit obscure to be in the "public" API. we should
+        consider migrating all user of this to going through the dirstate entry
+        instead.
         """
-        return self._map.get(key, (b"?",))[0]
+        entry = self._map.get(key)
+        if entry is not None:
+            return entry.state
+        return b'?'
 
     def __contains__(self, key):
         return key in self._map
@@ -380,13 +387,13 @@
                     continue
 
                 # Discard 'm' markers when moving away from a merge state
-                if s[0] == b'm':
+                if s.state == b'm':
                     source = self._map.copymap.get(f)
                     if source:
                         copies[f] = source
                     self.normallookup(f)
                 # Also fix up otherparent markers
-                elif s[0] == b'n' and s[2] == FROM_P2:
+                elif s.state == b'n' and s[2] == FROM_P2:
                     source = self._map.copymap.get(f)
                     if source:
                         copies[f] = source
@@ -465,7 +472,7 @@
                 if self._map.hastrackeddir(d):
                     break
                 entry = self._map.get(d)
-                if entry is not None and entry[0] != b'r':
+                if entry is not None and entry.state != b'r':
                     msg = _(b'file %r in dirstate clashes with %r')
                     msg %= (pycompat.bytestr(d), pycompat.bytestr(f))
                     raise error.Abort(msg)
@@ -524,7 +531,7 @@
             # being removed, restore that state.
             entry = self._map.get(f)
             if entry is not None:
-                if entry[0] == b'r' and entry[2] in (NONNORMAL, FROM_P2):
+                if entry.state == b'r' and entry[2] in (NONNORMAL, FROM_P2):
                     source = self._map.copymap.get(f)
                     if entry[2] == NONNORMAL:
                         self.merge(f)
@@ -533,7 +540,11 @@
                     if source:
                         self.copy(source, f)
                     return
-                if entry[0] == b'm' or entry[0] == b'n' and entry[2] == FROM_P2:
+                if (
+                    entry.state == b'm'
+                    or entry.state == b'n'
+                    and entry[2] == FROM_P2
+                ):
                     return
         self._addpath(f, b'n', 0, possibly_dirty=True)
         self._map.copymap.pop(f, None)
@@ -761,7 +772,7 @@
         if delaywrite > 0:
             # do we have any files to delay for?
             for f, e in pycompat.iteritems(self._map):
-                if e[0] == b'n' and e[3] == now:
+                if e.state == b'n' and e[3] == now:
                     import time  # to avoid useless import
 
                     # rather than sleep n seconds, sleep until the next
@@ -1315,7 +1326,7 @@
             # general. That is much slower than simply accessing and storing the
             # tuple members one by one.
             t = dget(fn)
-            state = t[0]
+            state = t.state
             mode = t[1]
             size = t[2]
             time = t[3]
--- a/mercurial/pure/parsers.py	Sat Jul 03 19:52:00 2021 +0200
+++ b/mercurial/pure/parsers.py	Sun Jul 04 03:29:20 2021 +0200
@@ -64,6 +64,21 @@
         else:
             raise IndexError(idx)
 
+    @property
+    def state(self):
+        """
+        States are:
+          n  normal
+          m  needs merging
+          r  marked for removal
+          a  marked for addition
+
+        XXX This "state" is a bit obscure and mostly a direct expression of the
+        dirstatev1 format. It would make sense to ultimately deprecate it in
+        favor of the more "semantic" attributes.
+        """
+        return self._state
+
     def v1_state(self):
         """return a "state" suitable for v1 serialization"""
         return self._state