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
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 // 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 }