changeset 47990:0d2a404f1932

dirstate: introduce a set_tracked method on "map" and "item" This move more implementation details withing the DirstateItem itself, which is what we have been doing for a while. Differential Revision: https://phab.mercurial-scm.org/D11430
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 15 Sep 2021 18:05:39 +0200
parents 87b3010c08e0
children 625b84c1abdd
files mercurial/cext/parsers.c mercurial/dirstate.py mercurial/dirstatemap.py mercurial/pure/parsers.py
diffstat 4 files changed, 74 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/cext/parsers.c	Wed Sep 15 11:13:46 2021 +0200
+++ b/mercurial/cext/parsers.c	Wed Sep 15 18:05:39 2021 +0200
@@ -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 */
--- a/mercurial/dirstate.py	Wed Sep 15 11:13:46 2021 +0200
+++ b/mercurial/dirstate.py	Wed Sep 15 18:05:39 2021 +0200
@@ -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):
--- a/mercurial/dirstatemap.py	Wed Sep 15 11:13:46 2021 +0200
+++ b/mercurial/dirstatemap.py	Wed Sep 15 18:05:39 2021 +0200
@@ -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.
--- a/mercurial/pure/parsers.py	Wed Sep 15 11:13:46 2021 +0200
+++ b/mercurial/pure/parsers.py	Wed Sep 15 18:05:39 2021 +0200
@@ -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