Patchwork D11506: dirstate: use a new `drop_merge_data` in `setparent`

login
register
mail settings
Submitter phabricator
Date Sept. 28, 2021, 7:55 p.m.
Message ID <differential-rev-PHID-DREV-7l7up53x2uctvfoyucn6-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/49829/
State Superseded
Headers show

Comments

phabricator - Sept. 28, 2021, 7:55 p.m.
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  What is happening this `setparent` loop is that we remove all `merge` related
  information when the dirstate is moved out of a `merge` situation.
  
  So instead of suffling state to get them where we want, we simply add a method
  on the DirstateItem to do exactly that.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

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

CHANGE DETAILS




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

Patch

diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py
--- a/mercurial/pure/parsers.py
+++ b/mercurial/pure/parsers.py
@@ -263,6 +263,24 @@ 
         self._size = None
         self._mtime = None
 
+    def drop_merge_data(self):
+        """remove all "merge-only" from a DirstateItem
+
+        This is to be call by the dirstatemap code when the second parent is dropped
+        """
+        if not (self.merged or self.from_p2):
+            return
+        self._p1_tracked = self.merged  # why is this not already properly set ?
+
+        self._merged = False
+        self._clean_p1 = False
+        self._clean_p2 = False
+        self._p2_tracked = False
+        self._possibly_dirty = True
+        self._mode = None
+        self._size = None
+        self._mtime = None
+
     @property
     def mode(self):
         return self.v1_mode()
diff --git a/mercurial/dirstatemap.py b/mercurial/dirstatemap.py
--- a/mercurial/dirstatemap.py
+++ b/mercurial/dirstatemap.py
@@ -441,26 +441,11 @@ 
                     continue
 
                 # Discard "merged" markers when moving away from a merge state
-                if s.merged:
-                    source = self.copymap.get(f)
+                if s.merged or s.from_p2:
+                    source = self.copymap.pop(f, None)
                     if source:
                         copies[f] = source
-                    self.reset_state(
-                        f,
-                        wc_tracked=True,
-                        p1_tracked=True,
-                        possibly_dirty=True,
-                    )
-                # Also fix up otherparent markers
-                elif s.from_p2:
-                    source = self.copymap.get(f)
-                    if source:
-                        copies[f] = source
-                    self.reset_state(
-                        f,
-                        p1_tracked=False,
-                        wc_tracked=True,
-                    )
+                    s.drop_merge_data()
         return copies
 
     def read(self):
diff --git a/mercurial/cext/parsers.c b/mercurial/cext/parsers.c
--- a/mercurial/cext/parsers.c
+++ b/mercurial/cext/parsers.c
@@ -515,6 +515,27 @@ 
 	Py_RETURN_NONE;
 }
 
+static PyObject *dirstate_item_drop_merge_data(dirstateItemObject *self)
+{
+	if (dirstate_item_c_merged(self) || dirstate_item_c_from_p2(self)) {
+		if (dirstate_item_c_merged(self)) {
+			self->flags |= dirstate_flag_p1_tracked;
+		} else {
+			self->flags &= ~dirstate_flag_p1_tracked;
+		}
+		self->flags &=
+		    ~(dirstate_flag_merged | dirstate_flag_clean_p1 |
+		      dirstate_flag_clean_p2 | dirstate_flag_p2_tracked);
+		self->flags |= dirstate_flag_possibly_dirty;
+		self->mode = 0;
+		self->mtime = 0;
+		/* 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 PyMethodDef dirstate_item_methods[] = {
     {"v1_state", (PyCFunction)dirstate_item_v1_state, METH_NOARGS,
      "return a \"state\" suitable for v1 serialization"},
@@ -551,6 +572,8 @@ 
      "mark a file as \"tracked\""},
     {"set_untracked", (PyCFunction)dirstate_item_set_untracked, METH_NOARGS,
      "mark a file as \"untracked\""},
+    {"drop_merge_data", (PyCFunction)dirstate_item_drop_merge_data, METH_NOARGS,
+     "remove all \"merge-only\" from a DirstateItem"},
     {NULL} /* Sentinel */
 };