Patchwork D11421: dirstate: introduce a `set_clean` method on dirstate's map and items

login
register
mail settings
Submitter phabricator
Date Sept. 14, 2021, 9:21 p.m.
Message ID <differential-rev-PHID-DREV-uayf3wlpmhhooelpqwv2-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/49734/
State Superseded
Headers show

Comments

phabricator - Sept. 14, 2021, 9:21 p.m.
marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  This method is the "reverse" of "set possibly dirty", and can be used to more
  accurately other call that the dirstate was making. It is currently heavily
  influenced by its origin.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

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

CHANGE DETAILS




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

Patch

diff --git a/rust/Cargo.lock b/rust/Cargo.lock
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -1,7 +1,5 @@ 
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
-
 [[package]]
 name = "adler"
 version = "0.2.3"
diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py
--- a/mercurial/pure/parsers.py
+++ b/mercurial/pure/parsers.py
@@ -222,6 +222,24 @@ 
         """
         self._possibly_dirty = True
 
+    def set_clean(self, mode, size, mtime):
+        """mark a file as "clean" cancelling potential "possibly dirty call"
+
+        Note: this function is a descendant of `dirstate.normal` and is
+        currently expected to be call on "normal" entry only. There are not
+        reason for this to not change in the future as long as the ccode is
+        updated to preserve the proper state of the non-normal files.
+        """
+        self._wc_tracked = True
+        self._p1_tracked = True
+        self._p2_tracked = False  # this might be wrong
+        self._merged = False
+        self._clean_p2 = False
+        self._possibly_dirty = False
+        self._mode = mode
+        self._size = size
+        self._mtime = mtime
+
     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
@@ -162,6 +162,15 @@ 
         """record that the current state of the file on disk is unknown"""
         self[filename].set_possibly_dirty()
 
+    def set_clean(self, filename, mode, size, mtime):
+        """mark a file as back to a clean state"""
+        entry = self[filename]
+        mtime = mtime & rangemask
+        size = size & rangemask
+        entry.set_clean(mode, size, mtime)
+        self.copymap.pop(filename, None)
+        self.nonnormalset.discard(filename)
+
     def addfile(
         self,
         f,
@@ -924,6 +933,15 @@ 
             entry.set_possibly_dirty()
             self._rustmap.set_v1(filename, entry)
 
+        def set_clean(self, filename, mode, size, mtime):
+            """mark a file as back to a clean state"""
+            entry = self[filename]
+            mtime = mtime & rangemask
+            size = size & rangemask
+            entry.set_clean(mode, size, mtime)
+            self._rustmap.set_v1(filename, entry)
+            self._rustmap.copymap().pop(filename, None)
+
         def __setitem__(self, key, value):
             assert isinstance(value, DirstateItem)
             self._rustmap.set_v1(key, value)
diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -508,10 +508,9 @@ 
             (mode, size, mtime) = parentfiledata
         else:
             (mode, size, mtime) = self._get_filedata(filename)
-        self._addpath(filename, mode=mode, size=size, mtime=mtime)
-        self._map.copymap.pop(filename, None)
-        if filename in self._map.nonnormalset:
-            self._map.nonnormalset.remove(filename)
+        if not self._map[filename].tracked:
+            self._check_new_tracked_filename(filename)
+        self._map.set_clean(filename, mode, size, mtime)
         if mtime > self._lastnormaltime:
             # Remember the most recent modification timeslot for status(),
             # to make sure we won't miss future size-preserving file content
diff --git a/mercurial/cext/parsers.c b/mercurial/cext/parsers.c
--- a/mercurial/cext/parsers.c
+++ b/mercurial/cext/parsers.c
@@ -492,6 +492,21 @@ 
 	}
 }
 
+/* See docstring of the python implementation for details */
+static PyObject *dirstate_item_set_clean(dirstateItemObject *self,
+                                         PyObject *args)
+{
+	int size, mode, mtime;
+	if (!PyArg_ParseTuple(args, "iii", &mode, &size, &mtime)) {
+		return NULL;
+	}
+	self->flags = dirstate_flag_wc_tracked | dirstate_flag_p1_tracked;
+	self->mode = mode;
+	self->size = size;
+	self->mtime = mtime;
+	Py_RETURN_NONE;
+}
+
 static PyObject *dirstate_item_set_untracked(dirstateItemObject *self)
 {
 	self->flags &= ~dirstate_flag_wc_tracked;
@@ -531,6 +546,8 @@ 
      "constructor to help legacy API to build a new \"normal\" item"},
     {"set_possibly_dirty", (PyCFunction)dirstate_item_set_possibly_dirty,
      METH_NOARGS, "mark a file as \"possibly dirty\""},
+    {"set_clean", (PyCFunction)dirstate_item_set_clean, METH_VARARGS,
+     "mark a file as \"clean\""},
     {"set_untracked", (PyCFunction)dirstate_item_set_untracked, METH_NOARGS,
      "mark a file as \"untracked\""},
     {NULL} /* Sentinel */