D10830: merge: make applyupdates() not mutate mresult argument
martinvonz created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY We have an extension at work that overrides `merge.applyupdates()` to make it skip some writes and instead instruct the virtual filesystem we use to get a different version. That override doesn't work correctly when doing `hg co -m` and there's a modified file in the dirstate that's deleted in the destination. That's because `applyupdates()` mutates its `mresult` argument and our extension had passed in a modified copied of `mresult` to the overridden function, which resulted in the mutation not having any effect. This patch fixes that by letting the caller (i.e. `merge._update()`) update `mresult` with the extra actions instead. Besides fixing our internal extension, that seems cleaner to me anyway (better to not mutate `mresult` only in some cases and we can skip some of the logic if we're not going to update the dirstate anyway). REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10830 AFFECTED FILES mercurial/merge.py CHANGE DETAILS diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -1724,20 +1724,13 @@ removed += msremoved extraactions = ms.actions() -if extraactions: -for k, acts in pycompat.iteritems(extraactions): -for a in acts: -mresult.addfile(a[0], k, *a[1:]) -if k == mergestatemod.ACTION_GET and wantfiledata: -# no filedata until mergestate is updated to provide it -for a in acts: -getfiledata[a[0]] = None progress.complete() -assert len(getfiledata) == ( -mresult.len((mergestatemod.ACTION_GET,)) if wantfiledata else 0 +return ( +updateresult(updated, merged, removed, unresolved), +getfiledata, +extraactions, ) -return updateresult(updated, merged, removed, unresolved), getfiledata def _advertisefsmonitor(repo, num_gets, p1node): @@ -2122,7 +2115,7 @@ ) wantfiledata = updatedirstate and not branchmerge -stats, getfiledata = applyupdates( +stats, getfiledata, extraactions = applyupdates( repo, mresult, wc, @@ -2133,6 +2126,18 @@ ) if updatedirstate: +if extraactions: +for k, acts in pycompat.iteritems(extraactions): +for a in acts: +mresult.addfile(a[0], k, *a[1:]) +if k == mergestatemod.ACTION_GET and wantfiledata: +# no filedata until mergestate is updated to provide it +for a in acts: +getfiledata[a[0]] = None + +assert len(getfiledata) == ( +mresult.len((mergestatemod.ACTION_GET,)) if wantfiledata else 0 +) with repo.dirstate.parentchange(): repo.setparents(fp1, fp2) mergestatemod.recordupdates( To: martinvonz, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
mercurial@47342: 27 new changesets (3 on stable)
27 new changesets (3 on stable) in mercurial: https://www.mercurial-scm.org/repo/hg/rev/c365850b6114 changeset: 47316:c365850b6114 branch: stable parent: 47183:8be95673eb8a user:Raphaël Gomès date:Tue May 04 10:33:36 2021 +0200 summary: rust-status: highlight a bug in Rust-augmented status https://www.mercurial-scm.org/repo/hg/rev/c8f62920f07a changeset: 47317:c8f62920f07a branch: stable user:Raphaël Gomès date:Tue May 04 10:46:50 2021 +0200 summary: rust-status: fix ignore and include not composing (issue6514) https://www.mercurial-scm.org/repo/hg/rev/5ac0f2a8ba72 changeset: 47318:5ac0f2a8ba72 branch: stable user:Matt Harbison date:Thu May 20 14:20:39 2021 -0400 summary: tests: monkeypatch `util.get_password()` to avoid deadlocks on Windows https://www.mercurial-scm.org/repo/hg/rev/e985a36c2aa3 changeset: 47319:e985a36c2aa3 parent: 47315:825d5a5907b4 user:Simon Sapin date:Fri May 21 17:12:47 2021 +0200 summary: upgrade: Use `improvement` subclasses everywhere, not instances https://www.mercurial-scm.org/repo/hg/rev/a43d256c041a changeset: 47320:a43d256c041a user:Simon Sapin date:Wed May 19 18:35:43 2021 +0200 summary: dirstate-v2: Add `hg debugupgraderepo` command support https://www.mercurial-scm.org/repo/hg/rev/62225f9da938 changeset: 47321:62225f9da938 user:Simon Sapin date:Sat May 22 17:32:09 2021 +0200 summary: rhg: Sort `rhg status` output correctly https://www.mercurial-scm.org/repo/hg/rev/1760de72a992 changeset: 47322:1760de72a992 user:Simon Sapin date:Sat May 22 17:35:54 2021 +0200 summary: rhg: A missing .hg/dirstate file is not an error https://www.mercurial-scm.org/repo/hg/rev/f612db768c7a changeset: 47323:f612db768c7a user:Pierre-Yves David date:Tue May 18 15:07:17 2021 +0200 summary: revlogv2: use a unique filename for index https://www.mercurial-scm.org/repo/hg/rev/0a3fa41fa719 changeset: 47324:0a3fa41fa719 user:Pierre-Yves David date:Wed May 19 16:55:36 2021 +0200 summary: revlogv2: use a unique filename for data https://www.mercurial-scm.org/repo/hg/rev/f286d715f9ab changeset: 47325:f286d715f9ab user:Pierre-Yves David date:Thu May 20 21:48:53 2021 +0200 summary: revlogv2: simplify and clarify the processing of each entry https://www.mercurial-scm.org/repo/hg/rev/53ab13d6a5db changeset: 47326:53ab13d6a5db user:Pierre-Yves David date:Thu May 20 21:54:21 2021 +0200 summary: revlogv2: add a `get_data` helper to grab the next piece of docket https://www.mercurial-scm.org/repo/hg/rev/1844a2e3401c changeset: 47327:1844a2e3401c user:Pierre-Yves David date:Wed May 26 21:35:51 2021 +0200 summary: revlog: simplify the try nesting in the `_writing` context https://www.mercurial-scm.org/repo/hg/rev/27e9ed1217c5 changeset: 47328:27e9ed1217c5 user:Pierre-Yves David date:Wed May 26 21:46:45 2021 +0200 summary: revlog: close the index file handle after the data one https://www.mercurial-scm.org/repo/hg/rev/717a94b423b9 changeset: 47329:717a94b423b9 parent: 47328:27e9ed1217c5 parent: 47318:5ac0f2a8ba72 user:Matt Harbison date:Fri May 28 17:33:20 2021 -0400 summary: merge with stable https://www.mercurial-scm.org/repo/hg/rev/73f23e7610f8 changeset: 47330:73f23e7610f8 user:Simon Sapin date:Wed May 19 13:15:00 2021 +0200 summary: dirstate-tree: Remove DirstateMap::iter_node_data_mut https://www.mercurial-scm.org/repo/hg/rev/0252600fd1cf changeset: 47331:0252600fd1cf user:Simon Sapin date:Wed May 19 13:15:00 2021 +0200 summary: dirstate-tree: Downgrade ` Node` to `` in status and serialization https://www.mercurial-scm.org/repo/hg/rev/4ee9f419c52e changeset: 47332:4ee9f419c52e user:Simon Sapin date:Wed May 19 13:15:00 2021 +0200 summary: rust: Return owned instead of borrowed DirstateEntry in DirstateMap APIs https://www.mercurial-scm.org/repo/hg/rev/69530e5d4fe5 changeset: 47333:69530e5d4fe5 user:Simon Sapin date:Wed May 19 13:15:00 2021 +0200 summary: dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums https://www.mercurial-scm.org/repo/hg/rev/18b3060fe598 changeset: 47334:18b3060fe598 user:Simon Sapin date:Wed May 19 13:15:00 2021 +0200 summary: dirstate-v2: Add a zero-size error type for dirstate v2 parse errors https://www.mercurial-scm.org/repo/hg/rev/ed1583a845d2 changeset: 47335:ed1583a845d2 user:Simon Sapin date:Wed May 19 13:15:00 2021 +0200 summary: dirstate-v2: Make more APIs fallible, returning Result https://www.mercurial-scm.org/repo/hg/rev/8d0260d0dbc9 changeset: 47336:8d0260d0dbc9 user:Simon Sapin date:Wed May 19 13:15:00 2021 +0200 summary: dirstate-v2:
D10828: dirstate-v2: Add --dirs to debugdirstate command
SimonSapin created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY `hg debugdirstate --dirs` also shows information stored in the dirstate (for `read_dir` caching) about directories. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10828 AFFECTED FILES mercurial/debugcommands.py mercurial/dirstate.py rust/hg-core/src/dirstate/parsers.rs rust/hg-core/src/dirstate_tree/dirstate_map.rs rust/hg-core/src/dirstate_tree/dispatch.rs rust/hg-core/src/dirstate_tree/on_disk.rs rust/hg-cpython/src/dirstate/dirstate_map.rs rust/hg-cpython/src/dirstate/dispatch.rs rust/hg-cpython/src/parsers.rs tests/test-completion.t tests/test-status.t CHANGE DETAILS diff --git a/tests/test-status.t b/tests/test-status.t --- a/tests/test-status.t +++ b/tests/test-status.t @@ -915,3 +915,46 @@ I A.hs I B.hs I ignored-folder/ctest.hs + +#if dirstate-v2 + +Check read_dir caching + + $ cd .. + $ hg init repo8 + $ cd repo8 + $ mkdir subdir + $ touch subdir/a subdir/b + $ hg ci -Aqm '#0' + +The cached mtime is initially unset + + $ hg debugdirstate --dirs --no-dates | grep '^d' + d 0 0 unset subdir + +It is still not set when there are unknown files + + $ touch subdir/unknown + $ hg status + ? subdir/unknown + $ hg debugdirstate --dirs --no-dates | grep '^d' + d 0 0 unset subdir + +Now the directory is eligible for caching, so its mtime is save in the dirstate + + $ rm subdir/unknown + $ hg status + $ hg debugdirstate --dirs --no-dates | grep '^d' + d 0 0 set subdir + +This time the command should be ever so slightly faster since it does not need `read_dir("subdir")` + + $ hg status + +Creating a new file changes the directory’s mtime, invalidating the cache + + $ touch subdir/unknown + $ hg status + ? subdir/unknown + +#endif diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -282,7 +282,7 @@ debugdata: changelog, manifest, dir debugdate: extended debugdeltachain: changelog, manifest, dir, template - debugdirstate: nodates, dates, datesort + debugdirstate: nodates, dates, datesort, dirs debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure, template debugdownload: output debugextensions: template diff --git a/rust/hg-cpython/src/parsers.rs b/rust/hg-cpython/src/parsers.rs --- a/rust/hg-cpython/src/parsers.rs +++ b/rust/hg-cpython/src/parsers.rs @@ -98,7 +98,7 @@ p1: p1.try_into().unwrap(), p2: p2.try_into().unwrap(), }, -Timestamp(now.as_object().extract::(py)?), +Timestamp(now.as_object().extract::(py)?), ) { Ok(packed) => { for (filename, entry) in dirstate_map.iter() { diff --git a/rust/hg-cpython/src/dirstate/dispatch.rs b/rust/hg-cpython/src/dirstate/dispatch.rs --- a/rust/hg-cpython/src/dirstate/dispatch.rs +++ b/rust/hg-cpython/src/dirstate/dispatch.rs @@ -206,4 +206,18 @@ fn iter() -> StateMapIter<'_> { self.get().iter() } + +fn iter_directories( +, +) -> Box< +dyn Iterator< +Item = Result< +(, Option), +DirstateV2ParseError, +>, +> + Send ++ '_, +> { +self.get().iter_directories() +} } diff --git a/rust/hg-cpython/src/dirstate/dirstate_map.rs b/rust/hg-cpython/src/dirstate/dirstate_map.rs --- a/rust/hg-cpython/src/dirstate/dirstate_map.rs +++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs @@ -535,6 +535,18 @@ ) } +def directories() -> PyResult { +let dirs = PyList::new(py, &[]); +for item in self.inner(py).borrow().iter_directories() { +let (path, mtime) = item.map_err(|e| v2_error(py, e))?; +let path = PyBytes::new(py, path.as_bytes()); +let mtime = mtime.map(|t| t.0).unwrap_or(-1); +let tuple = (path, (b'd', 0, 0, mtime)); +dirs.append(py, tuple.to_py_object(py).into_object()) +} +Ok(dirs) +} + }); impl DirstateMap { diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs b/rust/hg-core/src/dirstate_tree/on_disk.rs --- a/rust/hg-core/src/dirstate_tree/on_disk.rs +++ b/rust/hg-core/src/dirstate_tree/on_disk.rs @@ -352,6 +352,12 @@ } } +impl Timestamp { +pub fn seconds() -> i64 { +self.seconds.get() +} +} + impl From for Timestamp { fn from(system_time: SystemTime) -> Self { let (secs, nanos) = match system_time.duration_since(UNIX_EPOCH) { diff --git a/rust/hg-core/src/dirstate_tree/dispatch.rs b/rust/hg-core/src/dirstate_tree/dispatch.rs --- a/rust/hg-core/src/dirstate_tree/dispatch.rs +++ b/rust/hg-core/src/dirstate_tree/dispatch.rs @@ -143,6 +143,18
D10827: dirstate-v2: Write .hg/dirstate back to disk on directory cache changes
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 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 _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>, + +/// 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() To: SimonSapin, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10829: dirstate-v2: Drop parent directory cache when removing a dirstate node
SimonSapin created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The premise of the directory cache is that the dirstate contains child nodes for every entry that `read_dir` would return. When removing nodes, that may not be the case anymore so the cache should be invalidated. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10829 AFFECTED FILES rust/hg-core/src/dirstate_tree/dirstate_map.rs tests/test-status.t CHANGE DETAILS diff --git a/tests/test-status.t b/tests/test-status.t --- a/tests/test-status.t +++ b/tests/test-status.t @@ -957,4 +957,18 @@ $ hg status ? subdir/unknown + $ rm subdir/unknown + $ hg status + +Removing a node from the dirstate resets the cache for its parent directory + + $ hg forget subdir/a + $ hg debugdirstate --dirs --no-dates | grep '^d' + d 0 0 set subdir + $ hg ci -qm '#1' + $ hg debugdirstate --dirs --no-dates | grep '^d' + d 0 0 unset subdir + $ hg status + ? subdir/a + #endif diff --git a/rust/hg-core/src/dirstate_tree/dirstate_map.rs b/rust/hg-core/src/dirstate_tree/dirstate_map.rs --- a/rust/hg-core/src/dirstate_tree/dirstate_map.rs +++ b/rust/hg-core/src/dirstate_tree/dirstate_map.rs @@ -712,11 +712,17 @@ had_entry: bool, had_copy_source: bool, } + +/// If this returns `Ok(Some((dropped, removed)))`, then +/// +/// * `dropped` is about the leaf node that was at `filename` +/// * `removed` is whether this particular level of recursion just +/// removed a node in `nodes`. fn recur<'on_disk>( on_disk: &'on_disk [u8], nodes: ChildNodes<'on_disk>, path: , -) -> Result, DirstateV2ParseError> { +) -> Result, DirstateV2ParseError> { let (first_path_component, rest_of_path) = path.split_first_component(); let node = if let Some(node) = @@ -728,11 +734,21 @@ }; let dropped; if let Some(rest) = rest_of_path { -if let Some(d) = recur(on_disk, node.children, rest)? { +if let Some((d, removed)) = +recur(on_disk, node.children, rest)? +{ dropped = d; if dropped.was_tracked { node.tracked_descendants_count -= 1; } + +// Directory caches must be invalidated when removing a +// child node +if removed { +if let NodeData::CachedDirectory { .. } = { +node.data = NodeData::None +} +} } else { return Ok(None); } @@ -752,16 +768,18 @@ } // After recursion, for both leaf (rest_of_path is None) nodes and // parent nodes, remove a node if it just became empty. -if !node.data.has_entry() +let remove = !node.data.has_entry() && node.copy_source.is_none() -&& node.children.is_empty() -{ +&& node.children.is_empty(); +if remove { nodes.make_mut(on_disk)?.remove(first_path_component); } -Ok(Some(dropped)) +Ok(Some((dropped, remove))) } -if let Some(dropped) = recur(self.on_disk, self.root, filename)? { +if let Some((dropped, _removed)) = +recur(self.on_disk, self.root, filename)? +{ if dropped.had_entry { self.nodes_with_entry_count -= 1 } To: SimonSapin, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10826: dirstate-v2: Skip readdir in status based on directory mtime
SimonSapin created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY When calling `read_dir` during `status` and the directory is found to be eligible for caching (see code comments), write the directory’s mtime to the dirstate. The presence of a directory mtime in the dirstate is meaningful and indicates eligibility. When an eligible directory mtime is found in the dirstate and `stat()` shows that the mtime has not changed, `status` can skip calling `read_dir` again and instead rely on the names of child nodes in the dirstate tree. The `tempfile` crate is used to create a temporary file in order to use its modification time as "current time" with the same truncation as other files and directories would have in their own modification time. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10826 AFFECTED FILES rust/hg-core/Cargo.toml rust/hg-core/src/dirstate_tree/dirstate_map.rs rust/hg-core/src/dirstate_tree/on_disk.rs rust/hg-core/src/dirstate_tree/status.rs CHANGE DETAILS 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 @@ -2,8 +2,11 @@ use crate::dirstate_tree::dirstate_map::BorrowedPath; use crate::dirstate_tree::dirstate_map::ChildNodesRef; use crate::dirstate_tree::dirstate_map::DirstateMap; +use crate::dirstate_tree::dirstate_map::NodeData; use crate::dirstate_tree::dirstate_map::NodeRef; use crate::dirstate_tree::on_disk::DirstateV2ParseError; +use crate::dirstate_tree::on_disk::Timestamp; +use crate::dirstate_tree::path_with_basename::WithBasename; use crate::matchers::get_ignore_function; use crate::matchers::Matcher; use crate::utils::files::get_bytes_from_os_string; @@ -18,10 +21,12 @@ use crate::StatusOptions; use micro_timer::timed; use rayon::prelude::*; +use std::borrow::Cow; use std::io; use std::path::Path; use std::path::PathBuf; use std::sync::Mutex; +use std::time::SystemTime; /// Returns the status of the working directory compared to its parent /// changeset. @@ -52,19 +57,45 @@ options, matcher, ignore_fn, -outcome: Mutex::new(DirstateStatus::default()), +outcome: Default::default(), +cached_directory_mtimes_to_add: Default::default(), +filesystem_time_at_status_start: filesystem_now(_dir).ok(), }; let is_at_repo_root = true; let hg_path = ::OnDisk(HgPath::new("")); let has_ignored_ancestor = false; +let root_cached_mtime = None; +let root_dir_metadata = None; +// If the path we have for the repository root is a symlink, do follow it. +// (As opposed to symlinks within the working directory which are not +// followed, using `std::fs::symlink_metadata`.) common.traverse_fs_directory_and_dirstate( has_ignored_ancestor, dmap.root.as_ref(), hg_path, _dir, +root_dir_metadata, +root_cached_mtime, is_at_repo_root, )?; -Ok((common.outcome.into_inner().unwrap(), warnings)) +let outcome = common.outcome.into_inner().unwrap(); +let to_add = common.cached_directory_mtimes_to_add.into_inner().unwrap(); +for (path, mtime) in _add { +let node = DirstateMap::get_or_insert_node( +dmap.on_disk, + dmap.root, +path, +WithBasename::to_cow_owned, +|_| {}, +)?; +match { +NodeData::Entry(_) => {} // Don’t overwrite an entry +NodeData::CachedDirectory { .. } | NodeData::None => { +node.data = NodeData::CachedDirectory { mtime: *mtime } +} +} +} +Ok((outcome, warnings)) } /// Bag of random things needed by various parts of the algorithm. Reduces the @@ -75,6 +106,12 @@ matcher: &'a (dyn Matcher + Sync), ignore_fn: IgnoreFnType<'a>, outcome: Mutex>, +cached_directory_mtimes_to_add: +Mutex, Timestamp)>>, + +/// The current time at the start of the `status()` algorithm, as measured +/// and possibly truncated by the filesystem. +filesystem_time_at_status_start: Option, } impl<'a, 'tree, 'on_disk> StatusCommon<'a, 'tree, 'on_disk> { @@ -97,18 +134,54 @@ .push((hg_path.to_owned().into(), BadMatch::OsError(errno))) } +/// If this returns true, we can get accurate results by only using +/// `symlink_metadata` for child nodes that exist in the dirstate and don’t +/// need to call `read_dir`. +fn can_skip_fs_readdir( +, +directory_metadata: Option<::fs::Metadata>, +cached_directory_mtime: Option<>, +) -> bool { +if !self.options.list_unknown && !self.options.list_ignored { +// All states that we care about listing have corresponding +
D10824: dirstate-tree: Change status() results to not borrow DirstateMap
SimonSapin created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The `status` function takes a `&'tree mut DirstateMap<'on_disk>` parameter. `'on_disk` borrows a read-only byte buffer with the contents of the `.hg/dirstate` file. `DirstateMap` internally uses represents file paths as `std::borrow::Cow<'on_disk, HgPath>`, which borrows the byte buffer when possible and allocates an owned string if not, such as for files added to the dirstate after it was loaded from disk. Previously the return type of of `status` has a `'tree` lifetime, meaning it could borrow all paths from the `DirstateMap`. With this changeset, that lifetime is changed to `'on_disk` meaning that only paths from the byte buffer can be borrowed, and paths allocated by `DirstateMap` must be copied. Usually most paths are in the byte buffer, and most paths are not part of the return value of `status`, so the number of extra copies should be small. This change will enable `status` to mutate the `DirstateMap` after it has finished constructing its return value. Previously such mutation would be prevented by possible on-going borrows. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10824 AFFECTED FILES rust/hg-core/src/dirstate/status.rs rust/hg-core/src/dirstate_tree/dirstate_map.rs rust/hg-core/src/dirstate_tree/status.rs rust/hg-core/src/operations/dirstate_status.rs CHANGE DETAILS diff --git a/rust/hg-core/src/operations/dirstate_status.rs b/rust/hg-core/src/operations/dirstate_status.rs --- a/rust/hg-core/src/operations/dirstate_status.rs +++ b/rust/hg-core/src/operations/dirstate_status.rs @@ -61,7 +61,10 @@ } drop(traversed_sender); -let traversed = traversed_receiver.into_iter().collect(); +let traversed = traversed_receiver +.into_iter() +.map(std::borrow::Cow::Owned) +.collect(); Ok(build_response(results, traversed)) } 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 @@ -1,4 +1,5 @@ use crate::dirstate::status::IgnoreFnType; +use crate::dirstate_tree::dirstate_map::BorrowedPath; use crate::dirstate_tree::dirstate_map::ChildNodesRef; use crate::dirstate_tree::dirstate_map::DirstateMap; use crate::dirstate_tree::dirstate_map::NodeRef; @@ -17,7 +18,6 @@ use crate::StatusOptions; use micro_timer::timed; use rayon::prelude::*; -use std::borrow::Cow; use std::io; use std::path::Path; use std::path::PathBuf; @@ -39,7 +39,7 @@ root_dir: PathBuf, ignore_files: Vec, options: StatusOptions, -) -> Result<(DirstateStatus<'tree>, Vec), StatusError> { +) -> Result<(DirstateStatus<'on_disk>, Vec), StatusError> { let (ignore_fn, warnings): (IgnoreFnType, _) = if options.list_ignored || options.list_unknown { get_ignore_function(ignore_files, _dir)? @@ -55,7 +55,7 @@ outcome: Mutex::new(DirstateStatus::default()), }; let is_at_repo_root = true; -let hg_path = HgPath::new(""); +let hg_path = ::OnDisk(HgPath::new("")); let has_ignored_ancestor = false; common.traverse_fs_directory_and_dirstate( has_ignored_ancestor, @@ -69,15 +69,15 @@ /// Bag of random things needed by various parts of the algorithm. Reduces the /// number of parameters passed to functions. -struct StatusCommon<'tree, 'a, 'on_disk: 'tree> { +struct StatusCommon<'a, 'tree, 'on_disk: 'tree> { dmap: &'tree DirstateMap<'on_disk>, options: StatusOptions, matcher: &'a (dyn Matcher + Sync), ignore_fn: IgnoreFnType<'a>, -outcome: Mutex>, +outcome: Mutex>, } -impl<'tree, 'a> StatusCommon<'tree, 'a, '_> { +impl<'a, 'tree, 'on_disk> StatusCommon<'a, 'tree, 'on_disk> { fn read_dir( , hg_path: , @@ -100,8 +100,8 @@ fn traverse_fs_directory_and_dirstate( , has_ignored_ancestor: bool, -dirstate_nodes: ChildNodesRef<'tree, '_>, -directory_hg_path: &'tree HgPath, +dirstate_nodes: ChildNodesRef<'tree, 'on_disk>, +directory_hg_path: <'tree, 'on_disk>, directory_fs_path: , is_at_repo_root: bool, ) -> Result<(), DirstateV2ParseError> { @@ -199,10 +199,10 @@ , fs_path: , fs_metadata: ::fs::Metadata, -dirstate_node: NodeRef<'tree, '_>, +dirstate_node: NodeRef<'tree, 'on_disk>, has_ignored_ancestor: bool, ) -> Result<(), DirstateV2ParseError> { -let hg_path = dirstate_node.full_path(self.dmap.on_disk)?; +let hg_path = _node.full_path_borrowed(self.dmap.on_disk)?; let file_type = fs_metadata.file_type(); let file_or_symlink = file_type.is_file() || file_type.is_symlink(); if
D10825: dirstate-v2: Allow tree nodes without an entry to store a timestamp
SimonSapin created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY Timestamps are stored on 96 bits: - 64 bits for the signed number of seconds since the Unix epoch - 32 bits for the nanoseconds in the `0 <= ns < 1_000_000_000` range For now timestamps are not used or set yet. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10825 AFFECTED FILES rust/hg-core/src/dirstate_tree/dirstate_map.rs rust/hg-core/src/dirstate_tree/on_disk.rs CHANGE DETAILS diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs b/rust/hg-core/src/dirstate_tree/on_disk.rs --- a/rust/hg-core/src/dirstate_tree/on_disk.rs +++ b/rust/hg-core/src/dirstate_tree/on_disk.rs @@ -17,10 +17,11 @@ use crate::DirstateError; use crate::DirstateParents; use crate::EntryState; -use bytes_cast::unaligned::{I32Be, U32Be, U64Be}; +use bytes_cast::unaligned::{I32Be, I64Be, U32Be, U64Be}; use bytes_cast::BytesCast; use std::borrow::Cow; -use std::convert::{TryFrom, TryInto}; +use std::convert::TryFrom; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; /// Added at the start of `.hg/dirstate` when the "v2" format is used. /// This a redundant sanity check more than an actual "magic number" since @@ -50,22 +51,43 @@ base_name_start: Size, copy_source: OptPathSlice, -entry: OptEntry, children: ChildNodes, pub(super) tracked_descendants_count: Size, + +/// Dependending on the value of `state`: +/// +/// * A null byte: `data` represents nothing +/// * A `n`, `a`, `r`, or `m` ASCII byte: `state` and `data` together +/// represents a dirstate entry like in the v1 format. +/// * A `d` ASCII byte: the bytes of `data` should instead be interpreted +/// as the `Timestamp` for the mtime of a cached directory. +/// +/// TODO: document directory caching +state: u8, +data: Entry, } -/// Either nothing if `state == b'\0'`, or a dirstate entry like in the v1 -/// format #[derive(BytesCast, Copy, Clone)] #[repr(C)] -struct OptEntry { -state: u8, +struct Entry { mode: I32Be, mtime: I32Be, size: I32Be, } +/// Duration since the Unix epoch +#[derive(BytesCast, Copy, Clone)] +#[repr(C)] +pub(super) struct Timestamp { +seconds: I64Be, + +/// In `0 .. 1_000_000_000`. +/// +/// This timestamp is later or earlier than `(seconds, 0)` by this many +/// nanoseconds, if `seconds` is non-negative or negative, respectively. +nanoseconds: U32Be, +} + /// Counted in bytes from the start of the file /// /// NOTE: If we decide to never support `.hg/dirstate` files larger than 4 GiB @@ -216,34 +238,54 @@ }) } -pub(super) fn has_entry() -> bool { -self.entry.state != b'\0' +pub(super) fn node_data( +, +) -> Result { +let entry = |state| { +dirstate_map::NodeData::Entry(self.entry_with_given_state(state)) +}; + +match self.state { +b'\0' => Ok(dirstate_map::NodeData::None), +b'd' => Ok(dirstate_map::NodeData::CachedDirectory { +mtime: *self.data.as_timestamp(), +}), +b'n' => Ok(entry(EntryState::Normal)), +b'a' => Ok(entry(EntryState::Added)), +b'r' => Ok(entry(EntryState::Removed)), +b'm' => Ok(entry(EntryState::Merged)), +_ => Err(DirstateV2ParseError), +} } pub(super) fn state( , ) -> Result, DirstateV2ParseError> { -Ok(if self.has_entry() { -Some( -self.entry -.state -.try_into() -.map_err(|_| DirstateV2ParseError)?, -) -} else { -None -}) +match self.state { +b'\0' | b'd' => Ok(None), +b'n' => Ok(Some(EntryState::Normal)), +b'a' => Ok(Some(EntryState::Added)), +b'r' => Ok(Some(EntryState::Removed)), +b'm' => Ok(Some(EntryState::Merged)), +_ => Err(DirstateV2ParseError), +} +} + +fn entry_with_given_state(, state: EntryState) -> DirstateEntry { +DirstateEntry { +state, +mode: self.data.mode.get(), +mtime: self.data.mtime.get(), +size: self.data.size.get(), +} } pub(super) fn entry( , ) -> Result, DirstateV2ParseError> { -Ok(self.state()?.map(|state| DirstateEntry { -state, -mode: self.entry.mode.get(), -mtime: self.entry.mtime.get(), -size: self.entry.size.get(), -})) +Ok(self +.state()? +.map(|state| self.entry_with_given_state(state))) } pub(super) fn children<'on_disk>( @@ -262,12 +304,58 @@ self.children(on_disk)?, ),
D10823: dirstate-tree: Fix status algorithm with unreadable directory
SimonSapin created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY When reading a directory fails such as because of insufficient permissions, it should be treated as empty by status instead of skipped entirely. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10823 AFFECTED FILES rust/hg-core/src/dirstate_tree/status.rs tests/test-status.t CHANGE DETAILS diff --git a/tests/test-status.t b/tests/test-status.t --- a/tests/test-status.t +++ b/tests/test-status.t @@ -837,6 +837,23 @@ yet by the Rust implementation of status, but includematcher is supported. --include is used below for that reason +#if unix-permissions + +Not having permission to read a directory that contains tracked files makes +status emit a warning then behave as if the directory was empty or removed +entirely: + + $ chmod 0 subdir + $ hg status --include subdir + subdir: Permission denied + R subdir/removed + ! subdir/clean + ! subdir/deleted + ! subdir/modified + $ chmod 755 subdir + +#endif + Remove a directory that contains tracked files $ rm -r subdir 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 @@ -141,7 +141,10 @@ ) { entries } else { -return Ok(()); +// Treat an unreadable directory (typically because of insufficient +// permissions) like an empty directory. `self.read_dir` has +// already called `self.io_error` so a warning will be emitted. +Vec::new() }; // `merge_join_by` requires both its input iterators to be sorted: To: SimonSapin, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Failed pipeline for branch/default | mercurial-devel | 0028ee17
Pipeline #22659 has failed! Project: mercurial-devel ( https://foss.heptapod.net/octobus/mercurial-devel ) Branch: branch/default ( https://foss.heptapod.net/octobus/mercurial-devel/-/commits/branch/default ) Commit: 0028ee17 ( https://foss.heptapod.net/octobus/mercurial-devel/-/commit/0028ee17628564ceb954e766449cc4e2111762ec ) Commit Message: docket: make compatible with py3.6, where Struc... Commit Author: Martin von Zweigbergk ( https://foss.heptapod.net/martinvonz ) Pipeline #22659 ( https://foss.heptapod.net/octobus/mercurial-devel/-/pipelines/22659 ) triggered by Administrator ( https://foss.heptapod.net/root ) had 1 failed build. Job #203301 ( https://foss.heptapod.net/octobus/mercurial-devel/-/jobs/203301/raw ) Stage: tests Name: test-py2-chg -- You're receiving this email because of your account on foss.heptapod.net. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Octobus monthly mini-sprints
Hi everybody, In order to keep on improving our coordination with the community, Octobus will organize periodic mini-sprints, starting next month. We'll dedicate one day per month to work with whomever is interested on one of the three areas we're active in: Mercurial core, Evolve and Heptapod. Of course, in the current context, these will be held entirely in virtual. The sprints will happen every first Friday of the month. The whole thing will start next month. Here's our schedule for the next three mini-sprints: - 2021-07-02: Heptapod [1] - 2021-08-06: Mercurial core (early in development cycle after 5.9) - 2021-09-03: Evolve Since we're trying to start a routine, we'll try and keep the same rotation for a while after that. The backbone of communication should be provided by the chat systems [2], and of course we can add videoconferencing on the fly when needed, but we can work out the details until then. Hope to "see" you there, we're looking forward for your feedback, ideas of things to discuss etc. Best, [1] I'll be organizing that one, more about it soon to come. [2] should be https://mattermost.heptapod.net/heptapod/channels/development for Heptapod and IRC channels in other cases. -- Georges Racinet https://octobus.net, https://about.heptapod.host, https://heptapod.net GPG: BF5456F4DC625443849B6E58EE20CA44EF691D39, sur serveurs publics ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10822: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10822 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -575,12 +575,8 @@ if f in filenodes: fns = [(v, k) for k, v in pycompat.iteritems(filenodes[f])] for lr, node in sorted(fns): -self._err( -lr, -_(b"manifest refers to unknown revision %s") -% short(node), -f, -) +msg = _(b"manifest refers to unknown revision %s") +self._err(lr, msg % short(node), f) progress.complete() if self.warnorphanstorefiles: To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10821: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. We extract the long message in a module level constant for clarity. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10821 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -50,6 +50,10 @@ b"warning: copy source of '%s' not in parents of %s" ) +WARN_NULLID_COPY_SOURCE = _( +b"warning: %s@%s: copy source revision is nullid %s:%s\n" +) + class verifier(object): def __init__(self, repo, level=None): @@ -557,13 +561,9 @@ m = _(b"empty or missing copy source revlog %s:%s") self._err(lr, m % (rp[0], short(rp[1])), f) elif rp[1] == self.repo.nullid: -ui.note( -_( -b"warning: %s@%s: copy source" -b" revision is nullid %s:%s\n" -) -% (f, lr, rp[0], short(rp[1])) -) +msg = WARN_NULLID_COPY_SOURCE +msg %= (f, lr, rp[0], short(rp[1])) +ui.note(msg) else: fl2.rev(rp[1]) except Exception as inst: To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10820: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10820 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -554,15 +554,8 @@ self._warn(WARN_UNKNOWN_COPY_SOURCE % (f, ctx)) fl2 = repo.file(rp[0]) if not len(fl2): -self._err( -lr, -_( -b"empty or missing copy source revlog " -b"%s:%s" -) -% (rp[0], short(rp[1])), -f, -) +m = _(b"empty or missing copy source revlog %s:%s") +self._err(lr, m % (rp[0], short(rp[1])), f) elif rp[1] == self.repo.nullid: ui.note( _( To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10819: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. We extract the long message in a module level constant for clarity. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10819 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -46,6 +46,10 @@ b"parent-directory manifest refers to unknown revision %s" ) +WARN_UNKNOWN_COPY_SOURCE = _( +b"warning: copy source of '%s' not in parents of %s" +) + class verifier(object): def __init__(self, repo, level=None): @@ -547,13 +551,7 @@ if lr is not None and ui.verbose: ctx = lrugetctx(lr) if not any(rp[0] in pctx for pctx in ctx.parents()): -self._warn( -_( -b"warning: copy source of '%s' not" -b" in parents of %s" -) -% (f, ctx) -) +self._warn(WARN_UNKNOWN_COPY_SOURCE % (f, ctx)) fl2 = repo.file(rp[0]) if not len(fl2): self._err( To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10818: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10818 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -514,11 +514,8 @@ if problem.warning: self._warn(problem.warning) elif problem.error: -self._err( -linkrev if linkrev is not None else lr, -problem.error, -f, -) +linkrev_msg = linkrev if linkrev is not None else lr +self._err(linkrev_msg, problem.error, f) else: raise error.ProgrammingError( b'problem instance does not set warning or error ' To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10817: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10817 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -494,9 +494,8 @@ storefiles.remove(ff) except KeyError: if self.warnorphanstorefiles: -self._warn( -_(b" warning: revlog '%s' not in fncache!") % ff -) +msg = _(b" warning: revlog '%s' not in fncache!") +self._warn(msg % ff) self.fncachewarned = True if not len(fl) and (self.havecl or self.havemf): To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10816: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10816 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -378,12 +378,9 @@ if dir: self._err(c, WARN_PARENT_DIR_UNKNOWN_REV % short(m), label) else: -self._err( -c, -_(b"changeset refers to unknown revision %s") -% short(m), -label, -) +msg = _(b"changeset refers to unknown revision %s") +msg %= short(m) +self._err(c, msg, label) if not dir and subdirnodes: self.ui.status(_(b"checking directory manifests\n")) To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10815: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. We extract the long message in a module level constant for clarity. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10815 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -42,6 +42,10 @@ b'hint: run "hg debugrebuildfncache" to recover from corrupt fncache\n' ) +WARN_PARENT_DIR_UNKNOWN_REV = _( +b"parent-directory manifest refers to unknown revision %s" +) + class verifier(object): def __init__(self, repo, level=None): @@ -372,15 +376,7 @@ changesetpairs = [(c, m) for m in mflinkrevs for c in mflinkrevs[m]] for c, m in sorted(changesetpairs): if dir: -self._err( -c, -_( -b"parent-directory manifest refers to unknown" -b" revision %s" -) -% short(m), -label, -) +self._err(c, WARN_PARENT_DIR_UNKNOWN_REV % short(m), label) else: self._err( c, To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10814: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10814 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -345,9 +345,8 @@ if fl == b't': if not match.visitdir(fullpath): continue -subdirnodes.setdefault(fullpath + b'/', {}).setdefault( -fn, [] -).append(lr) +sdn = subdirnodes.setdefault(fullpath + b'/', {}) +sdn.setdefault(fn, []).append(lr) else: if not match(fullpath): continue To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10813: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10813 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -361,12 +361,8 @@ # code (eg: hash verification, filename are ordered, etc.) mfdelta = mfl.get(dir, n).read() except Exception as inst: -self._exc( -lr, -_(b"reading full manifest %s") % short(n), -inst, -label, -) +msg = _(b"reading full manifest %s") % short(n) +self._exc(lr, msg, inst, label) if not dir: progress.complete() To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10812: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10812 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -329,11 +329,8 @@ if n in mflinkrevs: del mflinkrevs[n] elif dir: -self._err( -lr, -_(b"%s not in parent-directory manifest") % short(n), -label, -) +msg = _(b"%s not in parent-directory manifest") % short(n) +self._err(lr, msg, label) else: self._err(lr, _(b"%s not in changesets") % short(n), label) To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10811: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10811 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -211,10 +211,9 @@ if self.errors: ui.warn(_(b"%d integrity errors encountered!\n") % self.errors) if self.badrevs: -ui.warn( -_(b"(first damaged changeset appears to be %d)\n") -% min(self.badrevs) -) +msg = _(b"(first damaged changeset appears to be %d)\n") +msg %= min(self.badrevs) +ui.warn(msg) return 1 return 0 To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10810: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. We extract the long message in a module level constant for clarity. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10810 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -38,6 +38,11 @@ return f +HINT_FNCACHE = _( +b'hint: run "hg debugrebuildfncache" to recover from corrupt fncache\n' +) + + class verifier(object): def __init__(self, repo, level=None): self.repo = repo.unfiltered() @@ -202,12 +207,7 @@ if self.warnings: ui.warn(_(b"%d warnings encountered!\n") % self.warnings) if self.fncachewarned: -ui.warn( -_( -b'hint: run "hg debugrebuildfncache" to recover from ' -b'corrupt fncache\n' -) -) +ui.warn(HINT_FNCACHE) if self.errors: ui.warn(_(b"%d integrity errors encountered!\n") % self.errors) if self.badrevs: To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10809: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10809 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -156,11 +156,8 @@ msg = _(b"unknown parent 1 %s of %s") % (short(p1), short(node)) self._err(lr, msg, f) if p2 not in seen and p2 != self.repo.nullid: -self._err( -lr, -_(b"unknown parent 2 %s of %s") % (short(p2), short(node)), -f, -) +msg = _(b"unknown parent 2 %s of %s") % (short(p2), short(node)) +self._err(lr, msg, f) except Exception as inst: self._exc(lr, _(b"checking parents of %s") % short(node), inst, f) To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10808: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10808 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -153,11 +153,8 @@ try: p1, p2 = obj.parents(node) if p1 not in seen and p1 != self.repo.nullid: -self._err( -lr, -_(b"unknown parent 1 %s of %s") % (short(p1), short(node)), -f, -) +msg = _(b"unknown parent 1 %s of %s") % (short(p1), short(node)) +self._err(lr, msg, f) if p2 not in seen and p2 != self.repo.nullid: self._err( lr, To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10807: verify: use some intermediate variables instead of a multi-liner
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is shorter and easier to read as the indentation remains the same. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10807 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -145,10 +145,9 @@ linkrevs.append(lr) except Exception: pass -self._warn( -_(b" (expected %s)") -% b" ".join(map(pycompat.bytestr, linkrevs)) -) +msg = _(b" (expected %s)") +msg %= b" ".join(map(pycompat.bytestr, linkrevs)) +self._warn(msg) lr = None # can't be trusted try: To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10806: verify: expand a one liner into explicit commands
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The result is not longer, but it is more edible. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10806 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -139,11 +139,10 @@ if f and len(linkrevs) > 1: try: # attempt to filter down to real linkrevs -linkrevs = [ -l -for l in linkrevs -if self.lrugetctx(l)[f].filenode() == node -] +linkrevs = [] +for lr in linkrevs: +if self.lrugetctx(lr)[f].filenode() == node: +linkrevs.append(lr) except Exception: pass self._warn( To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10805: verify: align a comment line
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This argument description is back with it comrade. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10805 AFFECTED FILES mercurial/verify.py CHANGE DETAILS diff --git a/mercurial/verify.py b/mercurial/verify.py --- a/mercurial/verify.py +++ b/mercurial/verify.py @@ -114,7 +114,7 @@ arguments are: - obj: the source revlog - i:the revision number -- node:the revision node id +- node: the revision node id - seen: nodes previously seen for this revlog - linkrevs: [changelog-revisions] introducing "node" - f:string label ("changelog", "manifest", or filename) To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel