Mercurial > hg
annotate rust/hg-core/src/dirstate/dirstate_tree/node.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 |
rev | line source |
---|---|
45562
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
1 // node.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::iter::Iter; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
9 use crate::utils::hg_path::HgPathBuf; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
10 use crate::{DirstateEntry, EntryState, FastHashMap}; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
11 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
12 /// Represents a filesystem directory in the dirstate tree |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
13 #[derive(Debug, Default, Clone, PartialEq)] |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
14 pub struct Directory { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
15 /// Contains the old file information if it existed between changesets. |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
16 /// Happens if a file `foo` is marked as removed, removed from the |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
17 /// filesystem then a directory `foo` is created and at least one of its |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
18 /// descendents is added to Mercurial. |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
19 pub(super) was_file: Option<Box<File>>, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
20 pub(super) children: FastHashMap<Vec<u8>, Node>, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
21 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
22 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
23 /// Represents a filesystem file (or symlink) in the dirstate tree |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
24 #[derive(Debug, Clone, PartialEq)] |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
25 pub struct File { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
26 /// Contains the old structure if it existed between changesets. |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
27 /// Happens all descendents of `foo` marked as removed and removed from |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
28 /// the filesystem, then a file `foo` is created and added to Mercurial. |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
29 pub(super) was_directory: Option<Box<Directory>>, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
30 pub(super) entry: DirstateEntry, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
31 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
32 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
33 #[derive(Debug, Clone, PartialEq)] |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
34 pub enum NodeKind { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
35 Directory(Directory), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
36 File(File), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
37 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
38 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
39 #[derive(Debug, Default, Clone, PartialEq)] |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
40 pub struct Node { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
41 pub kind: NodeKind, |
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 Default for NodeKind { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
45 fn default() -> Self { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
46 NodeKind::Directory(Default::default()) |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
47 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
48 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
49 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
50 impl Node { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
51 pub fn insert(&mut self, path: &[u8], new_entry: DirstateEntry) -> InsertResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
52 let mut split = path.splitn(2, |&c| c == b'/'); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
53 let head = split.next().unwrap_or(b""); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
54 let tail = split.next().unwrap_or(b""); |
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 if let NodeKind::File(file) = &mut self.kind { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
57 if tail.is_empty() && head.is_empty() { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
58 // We're modifying the current file |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
59 let new = Self { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
60 kind: NodeKind::File(File { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
61 entry: new_entry, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
62 ..file.clone() |
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 }; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
65 return InsertResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
66 did_insert: false, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
67 old_entry: Some(std::mem::replace(self, new)), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
68 }; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
69 } else { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
70 match file.entry.state { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
71 // Only replace the current file with a directory if it's |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
72 // marked as `Removed` |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
73 EntryState::Removed => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
74 self.kind = NodeKind::Directory(Directory { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
75 was_file: Some(Box::from(file.clone())), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
76 children: Default::default(), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
77 }) |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
78 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
79 _ => return Node::insert_in_file(file, new_entry, head, tail), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
80 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
81 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
82 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
83 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
84 match &mut self.kind { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
85 NodeKind::Directory(directory) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
86 return Node::insert_in_directory(directory, new_entry, head, tail); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
87 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
88 NodeKind::File(_) => unreachable!("The file case has already been handled"), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
89 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
90 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
91 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
92 /// The current file still exists and is not marked as `Removed`. |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
93 /// Insert the entry in its `was_directory`. |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
94 fn insert_in_file( |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
95 file: &mut File, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
96 new_entry: DirstateEntry, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
97 head: &[u8], |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
98 tail: &[u8], |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
99 ) -> InsertResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
100 if let Some(d) = &mut file.was_directory { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
101 Node::insert_in_directory(d, new_entry, head, tail) |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
102 } else { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
103 let mut dir = Directory { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
104 was_file: None, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
105 children: FastHashMap::default(), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
106 }; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
107 let res = Node::insert_in_directory(&mut dir, new_entry, head, tail); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
108 file.was_directory = Some(Box::new(dir)); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
109 res |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
110 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
111 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
112 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
113 /// Insert an entry in the subtree of `directory` |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
114 fn insert_in_directory( |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
115 directory: &mut Directory, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
116 new_entry: DirstateEntry, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
117 head: &[u8], |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
118 tail: &[u8], |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
119 ) -> InsertResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
120 let mut res = InsertResult::default(); |
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 if let Some(node) = directory.children.get_mut(head) { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
123 // Node exists |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
124 match &mut node.kind { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
125 NodeKind::Directory(subdir) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
126 if tail.is_empty() { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
127 let becomes_file = Self { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
128 kind: NodeKind::File(File { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
129 was_directory: Some(Box::from(subdir.clone())), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
130 entry: new_entry, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
131 }), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
132 }; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
133 let old_entry = directory.children.insert(head.to_owned(), becomes_file); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
134 return InsertResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
135 did_insert: true, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
136 old_entry, |
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 } else { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
139 res = node.insert(tail, new_entry); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
140 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
141 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
142 NodeKind::File(_) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
143 res = node.insert(tail, new_entry); |
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 } else if tail.is_empty() { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
147 // File does not already exist |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
148 directory.children.insert( |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
149 head.to_owned(), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
150 Self { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
151 kind: NodeKind::File(File { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
152 was_directory: None, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
153 entry: new_entry, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
154 }), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
155 }, |
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 res.did_insert = true; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
158 } else { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
159 // Directory does not already exist |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
160 let mut nested = Self { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
161 kind: NodeKind::Directory(Directory { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
162 was_file: None, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
163 children: Default::default(), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
164 }), |
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 res = nested.insert(tail, new_entry); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
167 directory.children.insert(head.to_owned(), nested); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
168 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
169 res |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
170 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
171 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
172 /// Removes an entry from the tree, returns a `RemoveResult`. |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
173 pub fn remove(&mut self, path: &[u8]) -> RemoveResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
174 let empty_result = RemoveResult::default(); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
175 if path.is_empty() { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
176 return empty_result; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
177 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
178 let mut split = path.splitn(2, |&c| c == b'/'); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
179 let head = split.next(); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
180 let tail = split.next().unwrap_or(b""); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
181 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
182 let head = match head { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
183 None => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
184 return empty_result; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
185 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
186 Some(h) => h, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
187 }; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
188 if head == path { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
189 match &mut self.kind { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
190 NodeKind::Directory(d) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
191 return Node::remove_from_directory(head, d); |
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 NodeKind::File(f) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
194 if let Some(d) = &mut f.was_directory { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
195 let RemoveResult { old_entry, .. } = Node::remove_from_directory(head, d); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
196 return RemoveResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
197 cleanup: false, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
198 old_entry, |
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 } |
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 empty_result |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
204 } else { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
205 // Look into the dirs |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
206 match &mut self.kind { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
207 NodeKind::Directory(d) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
208 if let Some(child) = d.children.get_mut(head) { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
209 let mut res = child.remove(tail); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
210 if res.cleanup { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
211 d.children.remove(head); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
212 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
213 res.cleanup = d.children.len() == 0 && d.was_file.is_none(); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
214 res |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
215 } else { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
216 empty_result |
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 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
219 NodeKind::File(f) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
220 if let Some(d) = &mut f.was_directory { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
221 if let Some(child) = d.children.get_mut(head) { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
222 let RemoveResult { cleanup, old_entry } = child.remove(tail); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
223 if cleanup { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
224 d.children.remove(head); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
225 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
226 if d.children.len() == 0 && d.was_file.is_none() { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
227 f.was_directory = None; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
228 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
229 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
230 return RemoveResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
231 cleanup: false, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
232 old_entry, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
233 }; |
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 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
236 empty_result |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
237 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
238 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
239 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
240 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
241 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
242 fn remove_from_directory(head: &[u8], d: &mut Directory) -> RemoveResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
243 if let Some(node) = d.children.get_mut(head) { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
244 return match &mut node.kind { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
245 NodeKind::Directory(d) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
246 if let Some(f) = &mut d.was_file { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
247 let entry = f.entry; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
248 d.was_file = None; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
249 RemoveResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
250 cleanup: false, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
251 old_entry: Some(entry), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
252 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
253 } else { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
254 RemoveResult::default() |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
255 } |
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 NodeKind::File(f) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
258 let entry = f.entry; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
259 let mut cleanup = false; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
260 match &f.was_directory { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
261 None => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
262 if d.children.len() == 1 { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
263 cleanup = true; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
264 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
265 d.children.remove(head); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
266 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
267 Some(dir) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
268 node.kind = NodeKind::Directory(*dir.clone()); |
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 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
272 RemoveResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
273 cleanup: cleanup, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
274 old_entry: Some(entry), |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
275 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
276 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
277 }; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
278 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
279 RemoveResult::default() |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
280 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
281 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
282 pub fn get(&self, path: &[u8]) -> Option<&Node> { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
283 if path.is_empty() { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
284 return Some(&self); |
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 let mut split = path.splitn(2, |&c| c == b'/'); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
287 let head = split.next(); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
288 let tail = split.next().unwrap_or(b""); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
289 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
290 let head = match head { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
291 None => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
292 return Some(&self); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
293 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
294 Some(h) => h, |
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 match &self.kind { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
297 NodeKind::Directory(d) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
298 if let Some(child) = d.children.get(head) { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
299 return child.get(tail); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
300 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
301 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
302 NodeKind::File(f) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
303 if let Some(d) = &f.was_directory { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
304 if let Some(child) = d.children.get(head) { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
305 return child.get(tail); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
306 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
307 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
308 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
309 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
310 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
311 None |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
312 } |
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 pub fn get_mut(&mut self, path: &[u8]) -> Option<&mut NodeKind> { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
315 if path.is_empty() { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
316 return Some(&mut self.kind); |
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 mut split = path.splitn(2, |&c| c == b'/'); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
319 let head = split.next(); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
320 let tail = split.next().unwrap_or(b""); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
321 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
322 let head = match head { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
323 None => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
324 return Some(&mut self.kind); |
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 Some(h) => h, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
327 }; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
328 match &mut self.kind { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
329 NodeKind::Directory(d) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
330 if let Some(child) = d.children.get_mut(head) { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
331 return child.get_mut(tail); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
332 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
333 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
334 NodeKind::File(f) => { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
335 if let Some(d) = &mut f.was_directory { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
336 if let Some(child) = d.children.get_mut(head) { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
337 return child.get_mut(tail); |
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 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
341 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
342 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
343 None |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
344 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
345 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
346 pub fn iter(&self) -> Iter { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
347 Iter::new(self) |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
348 } |
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 /// Information returned to the caller of an `insert` operation for integrity. |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
352 #[derive(Debug, Default)] |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
353 pub struct InsertResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
354 /// Whether the insertion resulted in an actual insertion and not an |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
355 /// update |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
356 pub(super) did_insert: bool, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
357 /// The entry that was replaced, if it exists |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
358 pub(super) old_entry: Option<Node>, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
359 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
360 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
361 /// Information returned to the caller of a `remove` operation integrity. |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
362 #[derive(Debug, Default)] |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
363 pub struct RemoveResult { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
364 /// If the caller needs to remove the current node |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
365 pub(super) cleanup: bool, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
366 /// The entry that was replaced, if it exists |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
367 pub(super) old_entry: Option<DirstateEntry>, |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
368 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
369 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
370 impl<'a> IntoIterator for &'a Node { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
371 type Item = (HgPathBuf, DirstateEntry); |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
372 type IntoIter = Iter<'a>; |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
373 |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
374 fn into_iter(self) -> Self::IntoIter { |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
375 self.iter() |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
376 } |
b51167d70f5a
rust: add `dirstate_tree` module
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
377 } |