D11430: dirstate: introduce a set_tracked method on "map" and "item"

marmoute (Pierre-Yves David) phabricator at mercurial-scm.org
Thu Sep 16 14:44:29 UTC 2021


marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  This move more implementation details withing the DirstateItem itself, which is
  what we have been doing for a while.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11430

AFFECTED FILES
  mercurial/cext/parsers.c
  mercurial/dirstate.py
  mercurial/dirstatemap.py
  mercurial/pure/parsers.py

CHANGE DETAILS

diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py
--- a/mercurial/pure/parsers.py
+++ b/mercurial/pure/parsers.py
@@ -240,6 +240,18 @@
         self._size = size
         self._mtime = mtime
 
+    def set_tracked(self):
+        """mark a file as tracked in the working copy
+
+        This will ultimately be called by command like `hg add`.
+        """
+        self._wc_tracked = True
+        # `set_tracked` is replacing various `normallookup` call. So we set
+        # "possibly dirty" to stay on the safe side.
+        #
+        # Consider dropping this in the future in favor of something less broad.
+        self._possibly_dirty = True
+
     def set_untracked(self):
         """mark a file as untracked in the working copy
 
diff --git a/mercurial/dirstatemap.py b/mercurial/dirstatemap.py
--- a/mercurial/dirstatemap.py
+++ b/mercurial/dirstatemap.py
@@ -307,6 +307,36 @@
             self.otherparentset.discard(filename)
         self._map[filename] = entry
 
+    def set_tracked(self, filename):
+        new = False
+        entry = self.get(filename)
+        if entry is None:
+            self._dirs_incr(filename)
+            entry = DirstateItem(
+                p1_tracked=False,
+                p2_tracked=False,
+                wc_tracked=True,
+                merged=False,
+                clean_p1=False,
+                clean_p2=False,
+                possibly_dirty=False,
+                parentfiledata=None,
+            )
+            self._map[filename] = entry
+            if entry.dm_nonnormal:
+                self.nonnormalset.add(filename)
+            new = True
+        elif not entry.tracked:
+            self._dirs_incr(filename, entry)
+            entry.set_tracked()
+            new = True
+        else:
+            # XXX This is probably overkill for more case, but we need this to
+            # fully replace the `normallookup` call with `set_tracked` one.
+            # Consider smoothing this in the future.
+            self.set_possibly_dirty(filename)
+        return new
+
     def set_untracked(self, f):
         """Mark a file as no longer tracked in the dirstate map"""
         entry = self.get(f)
@@ -663,6 +693,23 @@
             else:
                 assert False, 'unreachable'
 
+        def set_tracked(self, filename):
+            new = False
+            entry = self.get(filename)
+            if entry is None:
+                self.addfile(filename, added=True)
+                new = True
+            elif not entry.tracked:
+                entry.set_tracked()
+                self._rustmap.set_v1(filename, entry)
+                new = True
+            else:
+                # XXX This is probably overkill for more case, but we need this to
+                # fully replace the `normallookup` call with `set_tracked` one.
+                # Consider smoothing this in the future.
+                self.set_possibly_dirty(filename)
+            return new
+
         def set_untracked(self, f):
             """Mark a file as no longer tracked in the dirstate map"""
             # in merge is only trigger more logic, so it "fine" to pass it.
diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -478,18 +478,9 @@
         self._dirty = True
         self._updatedfiles.add(filename)
         entry = self._map.get(filename)
-        if entry is None:
+        if entry is None or not entry.tracked:
             self._check_new_tracked_filename(filename)
-            self._map.addfile(filename, added=True)
-            return True
-        elif not entry.tracked:
-            self._normallookup(filename)
-            return True
-        # XXX This is probably overkill for more case, but we need this to
-        # fully replace the `normallookup` call with `set_tracked` one.
-        # Consider smoothing this in the future.
-        self.set_possibly_dirty(filename)
-        return False
+        return self._map.set_tracked(filename)
 
     @requires_no_parents_change
     def set_untracked(self, filename):
diff --git a/mercurial/cext/parsers.c b/mercurial/cext/parsers.c
--- a/mercurial/cext/parsers.c
+++ b/mercurial/cext/parsers.c
@@ -507,6 +507,17 @@
 	Py_RETURN_NONE;
 }
 
+static PyObject *dirstate_item_set_tracked(dirstateItemObject *self)
+{
+	self->flags |= dirstate_flag_wc_tracked;
+	self->flags |= dirstate_flag_possibly_dirty;
+	/* size = None on the python size turn into size = NON_NORMAL when
+	 * accessed. So the next line is currently required, but a some future
+	 * clean up would be welcome. */
+	self->size = dirstate_v1_nonnormal;
+	Py_RETURN_NONE;
+}
+
 static PyObject *dirstate_item_set_untracked(dirstateItemObject *self)
 {
 	self->flags &= ~dirstate_flag_wc_tracked;
@@ -548,6 +559,8 @@
      METH_NOARGS, "mark a file as \"possibly dirty\""},
     {"set_clean", (PyCFunction)dirstate_item_set_clean, METH_VARARGS,
      "mark a file as \"clean\""},
+    {"set_tracked", (PyCFunction)dirstate_item_set_tracked, METH_NOARGS,
+     "mark a file as \"tracked\""},
     {"set_untracked", (PyCFunction)dirstate_item_set_untracked, METH_NOARGS,
      "mark a file as \"untracked\""},
     {NULL} /* Sentinel */



To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel


More information about the Mercurial-devel mailing list