dirstate: use a new `drop_merge_data` in `setparent`
What is happening in this `setparent` loop is that we remove all `merge`
related information when the dirstate is moved out of a `merge` situation.
So instead of shuffling state to get them where we want, we simply add a method
on the DirstateItem to do drop the information we want dropped.
Differential Revision: https://phab.mercurial-scm.org/D11506
--- a/mercurial/cext/parsers.c Wed Sep 22 15:17:12 2021 +0200
+++ b/mercurial/cext/parsers.c Wed Sep 22 17:46:29 2021 +0200
@@ -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 */
};
--- a/mercurial/dirstatemap.py Wed Sep 22 15:17:12 2021 +0200
+++ b/mercurial/dirstatemap.py Wed Sep 22 17:46:29 2021 +0200
@@ -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):
--- a/mercurial/pure/parsers.py Wed Sep 22 15:17:12 2021 +0200
+++ b/mercurial/pure/parsers.py Wed Sep 22 17:46:29 2021 +0200
@@ -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()