annotate rust/hg-core/src/dirstate/dirstate_tree/iter.rs @ 45562:b51167d70f5a

rust: add `dirstate_tree` module Mercurial needs to represent the filesystem hierarchy on which it operates, for example in the dirstate. Its current on-disk representation is an unsorted, flat structure that gets transformed in the current Rust code into a `HashMap`. This loses the hierarchical information of the dirstate, leading to some unfortunate performance and algorithmic compromises. This module adds an implementation of a radix tree that is specialized for representing the dirstate: its unit is the path component. I have made no efforts to optimize either its memory footprint or its insertion speed: they're pretty bad for now. Following will be a few patches that modify the dirstate.status logic to use that new hierarchical information, fixing issue 6335 in the same swing. Differential Revision: https://phab.mercurial-scm.org/D9085
author Raphaël Gomès <rgomes@octobus.net>
date Fri, 25 Sep 2020 17:51:34 +0200
parents
children c35db907363d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
45562
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
1 // iter.rs
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
2 //
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
3 // Copyright 2020, Raphaël Gomès <rgomes@octobus.net>
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
4 //
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
5 // This software may be used and distributed according to the terms of the
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
6 // GNU General Public License version 2 or any later version.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
7
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
8 use super::node::{Node, NodeKind};
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
9 use super::tree::Tree;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
10 use crate::dirstate::dirstate_tree::node::Directory;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
11 use crate::dirstate::status::Dispatch;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
12 use crate::utils::hg_path::{hg_path_to_path_buf, HgPath, HgPathBuf};
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
13 use crate::DirstateEntry;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
14 use std::borrow::Cow;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
15 use std::collections::VecDeque;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
16 use std::iter::{FromIterator, FusedIterator};
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
17 use std::path::PathBuf;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
18
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
19 impl FromIterator<(HgPathBuf, DirstateEntry)> for Tree {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
20 fn from_iter<T: IntoIterator<Item = (HgPathBuf, DirstateEntry)>>(iter: T) -> Self {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
21 let mut tree = Self::new();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
22 for (path, entry) in iter {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
23 tree.insert(path, entry);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
24 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
25 tree
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
26 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
27 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
28
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
29 /// Iterator of all entries in the dirstate tree.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
30 ///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
31 /// It has no particular ordering.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
32 pub struct Iter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
33 to_visit: VecDeque<(Cow<'a, [u8]>, &'a Node)>,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
34 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
35
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
36 impl<'a> Iter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
37 pub fn new(node: &'a Node) -> Iter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
38 let mut to_visit = VecDeque::new();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
39 to_visit.push_back((Cow::Borrowed(&b""[..]), node));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
40 Self { to_visit }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
41 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
42 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
43
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
44 impl<'a> Iterator for Iter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
45 type Item = (HgPathBuf, DirstateEntry);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
46
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
47 fn next(&mut self) -> Option<Self::Item> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
48 while let Some((base_path, node)) = self.to_visit.pop_front() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
49 match &node.kind {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
50 NodeKind::Directory(dir) => {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
51 add_children_to_visit(&mut self.to_visit, &base_path, &dir);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
52 if let Some(file) = &dir.was_file {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
53 return Some((HgPathBuf::from_bytes(&base_path), file.entry));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
54 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
55 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
56 NodeKind::File(file) => {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
57 if let Some(dir) = &file.was_directory {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
58 add_children_to_visit(&mut self.to_visit, &base_path, &dir);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
59 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
60 return Some((HgPathBuf::from_bytes(&base_path), file.entry));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
61 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
62 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
63 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
64 None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
65 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
66 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
67
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
68 impl<'a> FusedIterator for Iter<'a> {}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
69
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
70 /// Iterator of all entries in the dirstate tree, with a special filesystem
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
71 /// handling for the directories containing said entries.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
72 ///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
73 /// It checks every directory on-disk to see if it has become a symlink, to
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
74 /// prevent a potential security issue.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
75 /// Using this information, it may dispatch `status` information early: it
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
76 /// returns canonical paths along with `Shortcut`s, which are either a
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
77 /// `DirstateEntry` or a `Dispatch`, if the fate of said path has already been
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
78 /// determined.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
79 ///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
80 /// Like `Iter`, it has no particular ordering.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
81 pub struct FsIter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
82 root_dir: PathBuf,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
83 to_visit: VecDeque<(Cow<'a, [u8]>, &'a Node)>,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
84 shortcuts: VecDeque<(HgPathBuf, StatusShortcut)>,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
85 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
86
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
87 impl<'a> FsIter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
88 pub fn new(node: &'a Node, root_dir: PathBuf) -> FsIter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
89 let mut to_visit = VecDeque::new();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
90 to_visit.push_back((Cow::Borrowed(&b""[..]), node));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
91 Self {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
92 root_dir,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
93 to_visit,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
94 shortcuts: Default::default(),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
95 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
96 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
97
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
98 /// Mercurial tracks symlinks but *not* what they point to.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
99 /// If a directory is moved and symlinked:
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
100 ///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
101 /// ```bash
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
102 /// $ mkdir foo
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
103 /// $ touch foo/a
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
104 /// $ # commit...
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
105 /// $ mv foo bar
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
106 /// $ ln -s bar foo
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
107 /// ```
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
108 /// We need to dispatch the new symlink as `Unknown` and all the
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
109 /// descendents of the directory it replace as `Deleted`.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
110 fn dispatch_symlinked_directory(&mut self, path: impl AsRef<HgPath>, node: &Node) {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
111 let path = path.as_ref();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
112 self.shortcuts
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
113 .push_back((path.to_owned(), StatusShortcut::Dispatch(Dispatch::Unknown)));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
114 for (file, _) in node.iter() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
115 self.shortcuts.push_back((
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
116 path.join(&file),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
117 StatusShortcut::Dispatch(Dispatch::Deleted),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
118 ));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
119 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
120 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
121
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
122 /// Returns `true` if the canonical `path` of a directory corresponds to a
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
123 /// symlink on disk. It means it was moved and symlinked after the last
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
124 /// dirstate update.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
125 ///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
126 /// # Special cases
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
127 ///
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
128 /// Returns `false` for the repository root.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
129 /// Returns `false` on io error, error handling is outside of the iterator.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
130 fn directory_became_symlink(&mut self, path: &HgPath) -> bool {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
131 if path.is_empty() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
132 return false;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
133 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
134 let filename_as_path = match hg_path_to_path_buf(&path) {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
135 Ok(p) => p,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
136 _ => return false,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
137 };
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
138 let meta = self.root_dir.join(filename_as_path).symlink_metadata();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
139 match meta {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
140 Ok(ref m) if m.file_type().is_symlink() => true,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
141 _ => return false,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
142 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
143 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
144 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
145
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
146 /// Returned by `FsIter`, since the `Dispatch` of any given entry may already
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
147 /// be determined during the iteration. This is necessary for performance
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
148 /// reasons, since hierarchical information is needed to `Dispatch` an entire
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
149 /// subtree efficiently.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
150 #[derive(Debug, Copy, Clone)]
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
151 pub enum StatusShortcut {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
152 /// A entry in the dirstate for further inspection
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
153 Entry(DirstateEntry),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
154 /// The result of the status of the corresponding file
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
155 Dispatch(Dispatch),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
156 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
157
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
158 impl<'a> Iterator for FsIter<'a> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
159 type Item = (HgPathBuf, StatusShortcut);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
160
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
161 fn next(&mut self) -> Option<Self::Item> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
162 // If any paths have already been `Dispatch`-ed, return them
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
163 while let Some(res) = self.shortcuts.pop_front() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
164 return Some(res);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
165 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
166
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
167 while let Some((base_path, node)) = self.to_visit.pop_front() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
168 match &node.kind {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
169 NodeKind::Directory(dir) => {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
170 let canonical_path = HgPath::new(&base_path);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
171 if self.directory_became_symlink(canonical_path) {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
172 // Potential security issue, don't do a normal
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
173 // traversal, force the results.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
174 self.dispatch_symlinked_directory(canonical_path, &node);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
175 continue;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
176 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
177 add_children_to_visit(&mut self.to_visit, &base_path, &dir);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
178 if let Some(file) = &dir.was_file {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
179 return Some((
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
180 HgPathBuf::from_bytes(&base_path),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
181 StatusShortcut::Entry(file.entry),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
182 ));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
183 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
184 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
185 NodeKind::File(file) => {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
186 if let Some(dir) = &file.was_directory {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
187 add_children_to_visit(&mut self.to_visit, &base_path, &dir);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
188 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
189 return Some((
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
190 HgPathBuf::from_bytes(&base_path),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
191 StatusShortcut::Entry(file.entry),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
192 ));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
193 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
194 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
195 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
196
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
197 None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
198 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
199 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
200
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
201 impl<'a> FusedIterator for FsIter<'a> {}
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
202
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
203 fn join_path<'a, 'b>(path: &'a [u8], other: &'b [u8]) -> Cow<'b, [u8]> {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
204 if path.is_empty() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
205 other.into()
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
206 } else {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
207 [path, &b"/"[..], other].concat().into()
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
208 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
209 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
210
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
211 /// Adds all children of a given directory `dir` to the visit queue `to_visit`
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
212 /// prefixed by a `base_path`.
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
213 fn add_children_to_visit<'a>(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
214 to_visit: &mut VecDeque<(Cow<'a, [u8]>, &'a Node)>,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
215 base_path: &[u8],
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
216 dir: &'a Directory,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
217 ) {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
218 to_visit.extend(dir.children.iter().map(|(path, child)| {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
219 let full_path = join_path(&base_path, &path);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
220 (Cow::from(full_path), child)
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
221 }));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
222 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
223
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
224 #[cfg(test)]
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
225 mod tests {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
226 use super::*;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
227 use crate::utils::hg_path::HgPath;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
228 use crate::{EntryState, FastHashMap};
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
229 use std::collections::HashSet;
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
230
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
231 #[test]
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
232 fn test_iteration() {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
233 let mut tree = Tree::new();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
234
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
235 assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
236 tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
237 HgPathBuf::from_bytes(b"foo/bar"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
238 DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
239 state: EntryState::Merged,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
240 mode: 41,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
241 mtime: 42,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
242 size: 43,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
243 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
244 ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
245 None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
246 );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
247
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
248 assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
249 tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
250 HgPathBuf::from_bytes(b"foo2"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
251 DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
252 state: EntryState::Merged,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
253 mode: 40,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
254 mtime: 41,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
255 size: 42,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
256 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
257 ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
258 None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
259 );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
260
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
261 assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
262 tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
263 HgPathBuf::from_bytes(b"foo/baz"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
264 DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
265 state: EntryState::Normal,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
266 mode: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
267 mtime: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
268 size: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
269 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
270 ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
271 None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
272 );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
273
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
274 assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
275 tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
276 HgPathBuf::from_bytes(b"foo/bap/nested"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
277 DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
278 state: EntryState::Normal,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
279 mode: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
280 mtime: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
281 size: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
282 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
283 ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
284 None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
285 );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
286
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
287 assert_eq!(tree.len(), 4);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
288
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
289 let results: HashSet<_> = tree.iter().map(|(c, _)| c.to_owned()).collect();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
290 dbg!(&results);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
291 assert!(results.contains(HgPath::new(b"foo2")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
292 assert!(results.contains(HgPath::new(b"foo/bar")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
293 assert!(results.contains(HgPath::new(b"foo/baz")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
294 assert!(results.contains(HgPath::new(b"foo/bap/nested")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
295
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
296 let mut iter = tree.iter();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
297 assert!(iter.next().is_some());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
298 assert!(iter.next().is_some());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
299 assert!(iter.next().is_some());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
300 assert!(iter.next().is_some());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
301 assert_eq!(None, iter.next());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
302 assert_eq!(None, iter.next());
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
303 drop(iter);
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
304
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
305 assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
306 tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
307 HgPathBuf::from_bytes(b"foo/bap/nested/a"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
308 DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
309 state: EntryState::Normal,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
310 mode: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
311 mtime: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
312 size: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
313 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
314 ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
315 None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
316 );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
317
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
318 let results: FastHashMap<_, _> = tree.iter().collect();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
319 assert!(results.contains_key(HgPath::new(b"foo2")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
320 assert!(results.contains_key(HgPath::new(b"foo/bar")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
321 assert!(results.contains_key(HgPath::new(b"foo/baz")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
322 // Is a dir but `was_file`, so it's listed as a removed file
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
323 assert!(results.contains_key(HgPath::new(b"foo/bap/nested")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
324 assert!(results.contains_key(HgPath::new(b"foo/bap/nested/a")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
325
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
326 // insert removed file (now directory) after nested file
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
327 assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
328 tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
329 HgPathBuf::from_bytes(b"a/a"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
330 DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
331 state: EntryState::Normal,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
332 mode: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
333 mtime: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
334 size: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
335 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
336 ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
337 None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
338 );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
339
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
340 // `insert` returns `None` for a directory
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
341 assert_eq!(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
342 tree.insert(
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
343 HgPathBuf::from_bytes(b"a"),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
344 DirstateEntry {
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
345 state: EntryState::Removed,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
346 mode: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
347 mtime: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
348 size: 0,
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
349 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
350 ),
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
351 None
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
352 );
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
353
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
354 let results: FastHashMap<_, _> = tree.iter().collect();
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
355 assert!(results.contains_key(HgPath::new(b"a")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
356 assert!(results.contains_key(HgPath::new(b"a/a")));
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
357 }
b51167d70f5a rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
358 }