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 */ 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/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/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/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"