annotate rust/hg-core/src/operations/dirstate_status.rs @ 47347:73ddcedeaadf

dirstate-tree: Change status() results to not borrow DirstateMap 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. Differential Revision: https://phab.mercurial-scm.org/D10824
author Simon Sapin <simon.sapin@octobus.net>
date Fri, 28 May 2021 20:07:27 +0200
parents 9c6b458a08e1
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 }