annotate rust/hg-core/src/operations/dirstate_status.rs @ 47379:f6bb181c75f8

rust: Parse "subinclude"d files along the way, not later When parsing a `.hgignore` file and encountering an `include:` line, the included file is parsed recursively right then in a depth-first fashion. With `subinclude:` however included files were parsed (recursively) much later. This changes it to be expanded during parsing, like `.hgignore`. The motivation for this is an upcoming changeset that needs to detect changes in which files are ignored or not. The plan is to hash all ignore files while they are being read, and store that hash in the dirstate (in v2 format). In order to allow a potential alternative implementations to read that format, the algorithm to compute that hash must be documented. Having a well-defined depth-first ordering for the tree of (sub-)included files makes that easier. Differential Revision: https://phab.mercurial-scm.org/D10834
author Simon Sapin <simon.sapin@octobus.net>
date Wed, 02 Jun 2021 18:03:43 +0200
parents 73ddcedeaadf
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
1 // dirstate_status.rs
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
2 //
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
3 // Copyright 2019, Raphaël Gomès <rgomes@octobus.net>
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
4 //
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
5 // This software may be used and distributed according to the terms of the
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
6 // GNU General Public License version 2 or any later version.
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
7
47110
9c6b458a08e1 rust: Move "lookup" a.k.a. "unsure" paths into `DirstateStatus` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47093
diff changeset
8 use crate::dirstate::status::{build_response, Dispatch, Status};
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
9 use crate::matchers::Matcher;
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
10 use crate::{DirstateStatus, StatusError};
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
11
47093
787ff5d21bcd dirstate-tree: Make Rust DirstateMap bindings go through a trait object
Simon Sapin <simon.sapin@octobus.net>
parents: 46890
diff changeset
12 impl<'a, M: ?Sized + Matcher + Sync> Status<'a, M> {
47110
9c6b458a08e1 rust: Move "lookup" a.k.a. "unsure" paths into `DirstateStatus` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47093
diff changeset
13 pub(crate) fn run(&self) -> Result<DirstateStatus<'a>, StatusError> {
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
14 let (traversed_sender, traversed_receiver) =
46054
fd47483f1645 rust: use crossbeam-channel crate directly
Simon Sapin <simon-commits@exyr.org>
parents: 45862
diff changeset
15 crossbeam_channel::unbounded();
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
16
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
17 // Step 1: check the files explicitly mentioned by the user
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
18 let (work, mut results) = self.walk_explicit(traversed_sender.clone());
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
19
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
20 if !work.is_empty() {
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
21 // Hashmaps are quite a bit slower to build than vecs, so only
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
22 // build it if needed.
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
23 let old_results = results.iter().cloned().collect();
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
24
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
25 // Step 2: recursively check the working directory for changes if
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
26 // needed
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
27 for (dir, dispatch) in work {
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
28 match dispatch {
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
29 Dispatch::Directory { was_file } => {
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
30 if was_file {
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
31 results.push((dir.to_owned(), Dispatch::Removed));
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
32 }
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
33 if self.options.list_ignored
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
34 || self.options.list_unknown
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
35 && !self.dir_ignore(&dir)
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
36 {
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
37 self.traverse(
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
38 &dir,
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
39 &old_results,
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
40 &mut results,
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
41 traversed_sender.clone(),
45862
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Rapha?l Gom?s <rgomes@octobus.net>
parents: 45610
diff changeset
42 );
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
43 }
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
44 }
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
45 _ => {
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
46 unreachable!("There can only be directories in `work`")
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
47 }
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
48 }
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
49 }
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
50 }
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
51
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
52 if !self.matcher.is_exact() {
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
53 if self.options.list_unknown {
45862
5c736ba5dc27 rust-status: don't bubble up os errors, translate them to bad matches
Rapha?l Gom?s <rgomes@octobus.net>
parents: 45610
diff changeset
54 self.handle_unknowns(&mut results);
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
55 } else {
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
56 // TODO this is incorrect, see issue6335
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
57 // This requires a fix in both Python and Rust that can happen
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
58 // with other pending changes to `status`.
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
59 self.extend_from_dmap(&mut results);
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
60 }
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
61 }
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
62
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
63 drop(traversed_sender);
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47110
diff changeset
64 let traversed = traversed_receiver
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47110
diff changeset
65 .into_iter()
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47110
diff changeset
66 .map(std::borrow::Cow::Owned)
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47110
diff changeset
67 .collect();
45113
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
68
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
69 Ok(build_response(results, traversed))
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
70 }
98817e5daca7 hg-core: define a `dirstate_status` `Operation`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
71 }