changeset 51623:59f846fbc11d

branching: merge stable into default
author Raphaël Gomès <rgomes@octobus.net>
date Mon, 06 May 2024 18:50:21 +0200
parents a4b3b8dee0a8 (current diff) 99072b02138f (diff)
children e32f23f15623
files mercurial/util.py rust/hg-core/src/revlog/mod.rs
diffstat 11 files changed, 116 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/.hgsigs	Tue Mar 26 01:27:27 2024 -0400
+++ b/.hgsigs	Mon May 06 18:50:21 2024 +0200
@@ -260,3 +260,4 @@
 c9ceb4f6025690167bdb245e530de6bac8baae95 0 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
+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
--- a/.hgtags	Tue Mar 26 01:27:27 2024 -0400
+++ b/.hgtags	Mon May 06 18:50:21 2024 +0200
@@ -276,3 +276,4 @@
 c9ceb4f6025690167bdb245e530de6bac8baae95 6.7
 2e6fde2ed01e63f0de6a5966994fbb60b1f87057 6.7.1
 803e61387e86f103483120df35619bdb175e3482 6.7.2
+028dc3f92dbd0f93bb78f9848c94ba5eecd72e71 6.7.3
--- a/mercurial/admin/verify.py	Tue Mar 26 01:27:27 2024 -0400
+++ b/mercurial/admin/verify.py	Mon May 06 18:50:21 2024 +0200
@@ -37,9 +37,8 @@
 
     is_narrow = requirements.NARROW_REQUIREMENT in repo.requirements
     narrow_matcher = repo.narrowmatch() if is_narrow else None
-
-    for err in repo.dirstate.verify(m1, m2, narrow_matcher):
-        ui.warn(err[0] % err[1:])
+    for err in repo.dirstate.verify(m1, m2, parent1, narrow_matcher):
+        ui.warn(err)
         errors += 1
 
     return errors
--- a/mercurial/admin_commands.py	Tue Mar 26 01:27:27 2024 -0400
+++ b/mercurial/admin_commands.py	Mon May 06 18:50:21 2024 +0200
@@ -47,4 +47,4 @@
         ui.status(_(b"running %s\n") % name)
         errors = func()
         if errors:
-            ui.warn(_(b"found %d errors\n") % len(errors))
+            ui.warn(_(b"found %d errors\n") % errors)
--- a/mercurial/util.py	Tue Mar 26 01:27:27 2024 -0400
+++ b/mercurial/util.py	Mon May 06 18:50:21 2024 +0200
@@ -2209,6 +2209,8 @@
 
 
 _re2_input = lambda x: x
+# google-re2 will need to be tell to not output error on its own
+_re2_options = None
 try:
     import re2  # pytype: disable=import-error
 
@@ -2229,6 +2231,7 @@
     def _checkre2():
         global _re2
         global _re2_input
+        global _re2_options
         if _re2 is not None:
             # we already have the answer
             return
@@ -2247,6 +2250,12 @@
             check_input = pycompat.sysstr(check_input)
             _re2 = bool(re2.match(check_pattern, check_input))
             _re2_input = pycompat.sysstr
+        try:
+            quiet = re2.Options()
+            quiet.log_errors = False
+            _re2_options = quiet
+        except AttributeError:
+            pass
 
     def compile(self, pat, flags=0):
         """Compile a regular expression, using re2 if possible
@@ -2262,7 +2271,12 @@
             if flags & remod.MULTILINE:
                 pat = b'(?m)' + pat
             try:
-                return re2.compile(_re2_input(pat))
+                input_regex = _re2_input(pat)
+                if _re2_options is not None:
+                    compiled = re2.compile(input_regex, options=_re2_options)
+                else:
+                    compiled = re2.compile(input_regex)
+                return compiled
             except re2.error:
                 pass
         return remod.compile(pat, flags)
--- a/relnotes/6.7	Tue Mar 26 01:27:27 2024 -0400
+++ b/relnotes/6.7	Mon May 06 18:50:21 2024 +0200
@@ -1,3 +1,20 @@
+= Mercurial 6.7.3 =
+
+ * setup: display return code information about failed `hg` call
+ * bundle-spec: properly identify changegroup-less bundle
+ * bundle-spec: properly parse boolean configuration as boolean
+ * matchers: fix the bug in rust PatternMatcher that made it cut off early
+ * match: fix the "visitdir" method on "rootfilesin" matchers
+ * match: fix the rust-side bug in visit_children_set for rootfilesin matchers
+ * match: strengthen visit_children_set invariant, Recursive means "all files"
+ * wireprotoserver: ensure that output stream gets flushed on exception
+ * re2: make errors quiet
+ * dirstate-v2: add check of parent/child nodes being related when writing
+ * dirstate-v2: check that root nodes are at the root before writing
+ * rust-cpython: don't swallow the dirstate error message
+ * rust: blanket implementation of Graph for Graph references
+ * Various fixes to `admin::verify`
+
 = Mercurial 6.7.2 =
 
 Exceptional release following a large performance regression when cloning.
--- a/rust/hg-core/src/ancestors.rs	Tue Mar 26 01:27:27 2024 -0400
+++ b/rust/hg-core/src/ancestors.rs	Mon May 06 18:50:21 2024 +0200
@@ -423,6 +423,18 @@
             ),
             vec![8, 7, 4, 3, 2, 1, 0]
         );
+        // it works as well on references, because &Graph implements Graph
+        // this is needed as of this writing by RHGitaly
+        assert_eq!(
+            list_ancestors(
+                &SampleGraph,
+                vec![11.into(), 13.into()],
+                0.into(),
+                false
+            ),
+            vec![8, 7, 4, 3, 2, 1, 0]
+        );
+
         assert_eq!(
             list_ancestors(
                 SampleGraph,
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs	Tue Mar 26 01:27:27 2024 -0400
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs	Mon May 06 18:50:21 2024 +0200
@@ -640,7 +640,20 @@
         out: Vec::with_capacity(size_guess),
     };
 
-    let root_nodes = writer.write_nodes(dirstate_map.root.as_ref())?;
+    let root_nodes = dirstate_map.root.as_ref();
+    for node in root_nodes.iter() {
+        // Catch some corruptions before we write to disk
+        let full_path = node.full_path(dirstate_map.on_disk)?;
+        let base_name = node.base_name(dirstate_map.on_disk)?;
+        if full_path != base_name {
+            let explanation = format!(
+                "Dirstate root node '{}' is not at the root",
+                full_path
+            );
+            return Err(HgError::corrupted(explanation).into());
+        }
+    }
+    let root_nodes = writer.write_nodes(root_nodes)?;
 
     let unreachable_bytes = if append {
         dirstate_map.unreachable_bytes
@@ -691,9 +704,11 @@
         // First accumulate serialized nodes in a `Vec`
         let mut on_disk_nodes = Vec::with_capacity(nodes_len);
         for node in nodes {
-            let children =
-                self.write_nodes(node.children(self.dirstate_map.on_disk)?)?;
+            let children = node.children(self.dirstate_map.on_disk)?;
             let full_path = node.full_path(self.dirstate_map.on_disk)?;
+            self.check_children(&children, full_path)?;
+
+            let children = self.write_nodes(children)?;
             let full_path = self.write_path(full_path.as_bytes());
             let copy_source = if let Some(source) =
                 node.copy_source(self.dirstate_map.on_disk)?
@@ -771,6 +786,37 @@
         Ok(ChildNodes { start, len })
     }
 
+    /// Catch some dirstate corruptions before writing them to disk
+    fn check_children(
+        &mut self,
+        children: &dirstate_map::ChildNodesRef,
+        full_path: &HgPath,
+    ) -> Result<(), DirstateError> {
+        for child in children.iter() {
+            let child_full_path =
+                child.full_path(self.dirstate_map.on_disk)?;
+
+            let prefix_length = child_full_path.len()
+                // remove the filename
+                - child.base_name(self.dirstate_map.on_disk)?.len()
+                // remove the slash
+                - 1;
+
+            let child_prefix = &child_full_path.as_bytes()[..prefix_length];
+
+            if child_prefix != full_path.as_bytes() {
+                let explanation = format!(
+                    "dirstate child node's path '{}' \
+                        does not start with its parent's path '{}'",
+                    child_full_path, full_path,
+                );
+
+                return Err(HgError::corrupted(explanation).into());
+            }
+        }
+        Ok(())
+    }
+
     /// If the given slice of items is within `on_disk`, returns its offset
     /// from the start of `on_disk`.
     fn on_disk_offset_of<T>(&self, slice: &[T]) -> Option<Offset>
--- a/rust/hg-core/src/revlog/mod.rs	Tue Mar 26 01:27:27 2024 -0400
+++ b/rust/hg-core/src/revlog/mod.rs	Mon May 06 18:50:21 2024 +0200
@@ -133,6 +133,12 @@
     ParentOutOfRange(Revision),
 }
 
+impl<T: Graph> Graph for &T {
+    fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> {
+        (*self).parents(rev)
+    }
+}
+
 /// The Mercurial Revlog Index
 ///
 /// This is currently limited to the minimal interface that is needed for
--- a/rust/hg-cpython/src/dirstate/dirstate_map.rs	Tue Mar 26 01:27:27 2024 -0400
+++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs	Mon May 06 18:50:21 2024 +0200
@@ -270,9 +270,9 @@
                 let tuple = (packed, tree_metadata, append);
                 Ok(tuple.to_py_object(py).into_object())
             },
-            Err(_) => Err(PyErr::new::<exc::OSError, _>(
+            Err(e) => Err(PyErr::new::<exc::OSError, _>(
                 py,
-                "Dirstate error".to_string(),
+                e.to_string(),
             )),
         }
     }
--- a/tests/test-verify.t	Tue Mar 26 01:27:27 2024 -0400
+++ b/tests/test-verify.t	Mon May 06 18:50:21 2024 +0200
@@ -132,6 +132,16 @@
   dirstate inconsistent with current parent's manifest
   1 dirstate errors
   [1]
+
+We can check the dirstate in isolation
+  $ hg admin::verify -c dirstate
+  running 1 checks
+  running working-copy.dirstate
+  checking dirstate
+  warning: ignoring unknown working parent c5ddb05ab828!
+  file marked as tracked in p1 (000000000000) but not in manifest1
+  found 1 errors
+
   $ cp -R .hg/store-full/. .hg/store
 
 Entire changelog and filelog missing