Patchwork D10827: dirstate-v2: Write .hg/dirstate back to disk on directory cache changes

login
register
mail settings
Submitter phabricator
Date June 1, 2021, 4:53 p.m.
Message ID <differential-rev-PHID-DREV-katwrd75lndbppow2otf-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/49148/
State Superseded
Headers show

Comments

phabricator - June 1, 2021, 4:53 p.m.
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

AFFECTED FILES
  mercurial/context.py
  mercurial/dirstate.py
  rust/hg-core/src/dirstate/status.rs
  rust/hg-core/src/dirstate_tree/status.rs
  rust/hg-cpython/src/dirstate/status.rs

CHANGE DETAILS




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

Patch

diff --git a/rust/hg-cpython/src/dirstate/status.rs b/rust/hg-cpython/src/dirstate/status.rs
--- a/rust/hg-cpython/src/dirstate/status.rs
+++ b/rust/hg-cpython/src/dirstate/status.rs
@@ -260,6 +260,7 @@ 
     let unsure = collect_pybytes_list(py, status_res.unsure.as_ref());
     let bad = collect_bad_matches(py, status_res.bad.as_ref())?;
     let traversed = collect_pybytes_list(py, status_res.traversed.as_ref());
+    let dirty = status_res.dirty.to_py_object(py);
     let py_warnings = PyList::new(py, &[]);
     for warning in warnings.iter() {
         // We use duck-typing on the Python side for dispatch, good enough for
@@ -297,6 +298,7 @@ 
             py_warnings.into_object(),
             bad.into_object(),
             traversed.into_object(),
+            dirty.into_object(),
         ][..],
     ))
 }
diff --git a/rust/hg-core/src/dirstate_tree/status.rs b/rust/hg-core/src/dirstate_tree/status.rs
--- a/rust/hg-core/src/dirstate_tree/status.rs
+++ b/rust/hg-core/src/dirstate_tree/status.rs
@@ -78,8 +78,9 @@ 
         root_cached_mtime,
         is_at_repo_root,
     )?;
-    let outcome = common.outcome.into_inner().unwrap();
+    let mut outcome = common.outcome.into_inner().unwrap();
     let to_add = common.cached_directory_mtimes_to_add.into_inner().unwrap();
+    outcome.dirty = !to_add.is_empty();
     for (path, mtime) in &to_add {
         let node = DirstateMap::get_or_insert_node(
             dmap.on_disk,
diff --git a/rust/hg-core/src/dirstate/status.rs b/rust/hg-core/src/dirstate/status.rs
--- a/rust/hg-core/src/dirstate/status.rs
+++ b/rust/hg-core/src/dirstate/status.rs
@@ -293,6 +293,10 @@ 
 
     /// Only filled if `collect_traversed_dirs` is `true`
     pub traversed: Vec<HgPathCow<'a>>,
+
+    /// Whether `status()` made changed to the `DirstateMap` that should be
+    /// written back to disk
+    pub dirty: bool,
 }
 
 #[derive(Debug, derive_more::From)]
@@ -919,6 +923,7 @@ 
         bad,
         unsure,
         traversed,
+        dirty: false,
     }
 }
 
diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -1137,6 +1137,7 @@ 
             warnings,
             bad,
             traversed,
+            dirty,
         ) = rustmod.status(
             self._map._rustmap,
             matcher,
@@ -1150,6 +1151,8 @@ 
             bool(matcher.traversedir),
         )
 
+        self._dirty |= dirty
+
         if matcher.traversedir:
             for dir in traversed:
                 matcher.traversedir(dir)
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -1840,7 +1840,7 @@ 
     def _poststatusfixup(self, status, fixup):
         """update dirstate for files that are actually clean"""
         poststatus = self._repo.postdsstatus()
-        if fixup or poststatus:
+        if fixup or poststatus or self._repo.dirstate._dirty:
             try:
                 oldid = self._repo.dirstate.identity()