1use backend::*;
2use std::collections::HashSet;
3
4#[derive(Debug)]
5pub struct FindAlive {
6 stack: Vec<Key<PatchId>>,
7 visited: HashSet<Key<PatchId>>,
8}
9
10impl FindAlive {
11 pub fn new() -> Self {
12 FindAlive {
13 stack: Vec::new(),
14 visited: HashSet::new(),
15 }
16 }
17 pub fn clear(&mut self) {
18 self.stack.clear();
19 self.visited.clear();
20 }
21 pub fn push(&mut self, k: Key<PatchId>) {
22 self.stack.push(k)
23 }
24 pub fn pop(&mut self) -> Option<Key<PatchId>> {
25 while let Some(p) = self.stack.pop() {
26 if !self.visited.contains(&p) {
27 self.visited.insert(p.clone());
28 return Some(p);
29 }
30 }
31 None
32 }
33}
34
35impl<U: Transaction, R> GenericTxn<U, R> {
36 pub fn find_alive_ancestors(
43 &self,
44 find_alive: &mut FindAlive,
45 branch: &Branch,
46 alive: &mut Vec<Key<PatchId>>,
47 file_ancestor: &mut Option<Key<PatchId>>,
48 files: &mut Vec<(Key<PatchId>, Edge)>,
49 ) -> bool {
50 let mut first_is_alive = false;
51 let mut file = None;
52 while let Some(a) = find_alive.pop() {
53 if self.is_alive(branch, a) {
54 alive.push(a);
56 } else {
57 first_is_alive = true;
58 let e = Edge::zero(EdgeFlags::PARENT_EDGE | EdgeFlags::DELETED_EDGE);
59 for (_, v) in self.iter_nodes(&branch, Some((a, Some(&e))))
60 .take_while(|&(k, _)| k == a)
61 {
62 debug!("find_alive_ancestors: {:?}", v);
63 if v.flag.contains(EdgeFlags::FOLDER_EDGE) {
64 file = Some(a);
66 *file_ancestor = Some(a)
67 } else {
68 find_alive.push(v.dest)
69 }
70 }
71 }
72 }
73 debug!("file {:?}", file);
74 if let Some(file) = file {
75 find_alive.clear();
76 find_alive.push(file);
77 while let Some(a) = find_alive.pop() {
78 debug!("file {:?}", a);
79 if !self.is_alive(branch, a) {
80 debug!("not alive");
81 first_is_alive = true;
82 let e = Edge::zero(
83 EdgeFlags::PARENT_EDGE | EdgeFlags::DELETED_EDGE | EdgeFlags::FOLDER_EDGE,
84 );
85 for (_, v) in self.iter_nodes(&branch, Some((a, Some(&e))))
86 .take_while(|&(k, _)| k == a)
87 {
88 debug!("file find_alive_ancestors: {:?}", v);
89 files.push((a, *v));
91 find_alive.push(v.dest)
92 }
93 }
94 }
95 }
96
97 first_is_alive
98 }
99
100 pub fn find_alive_descendants(
108 &self,
109 find_alive: &mut FindAlive,
110 branch: &Branch,
111 alive: &mut Vec<Key<PatchId>>,
112 ) -> bool {
113 let mut first_is_alive = false;
114 debug!("begin find_alive_descendants");
115 while let Some(a) = find_alive.pop() {
116 debug!("find_alive_descendants, a = {:?}", a);
117 if self.is_alive(branch, a) {
118 debug!("alive: {:?}", a);
119 alive.push(a);
120 } else {
121 first_is_alive = true;
123 let e = Edge::zero(EdgeFlags::empty());
124 for (_, v) in self.iter_nodes(&branch, Some((a, Some(&e))))
125 .take_while(|&(k, _)| k == a)
126 .filter(|&(_, v)| !v.flag.contains(EdgeFlags::PARENT_EDGE))
127 {
128 debug!("v = {:?}", v);
129 if v.flag.contains(EdgeFlags::DELETED_EDGE) {
130 debug!("find_alive_descendants: {:?}", v);
131 find_alive.push(v.dest)
132 } else {
133 debug!("alive in for: {:?}", v.dest);
134 alive.push(v.dest)
135 }
136 }
137 }
138 }
139 debug!("end find_alive_descendants");
140 first_is_alive
141 }
142
143 fn find_alive(
144 &self,
145 branch: &Branch,
146 find_alive: &mut FindAlive,
147 alive: &mut HashSet<Key<PatchId>>,
148 file: &mut Option<Key<PatchId>>,
149 current: Key<PatchId>,
150 flag: EdgeFlags,
151 ) {
152 find_alive.clear();
153 debug!("find_alive: {:?}", current);
154 find_alive.push(current);
155 while let Some(current) = find_alive.pop() {
156 debug!("find_alive, current = {:?}", current);
157 if self.is_alive(branch, current) {
158 alive.insert(current.clone());
159 } else {
160 let e = Edge::zero(flag);
161 for (_, e) in self.iter_nodes(branch, Some((current, Some(&e))))
162 .take_while(|&(k, v)| {
163 k == current
164 && v.flag | EdgeFlags::FOLDER_EDGE | EdgeFlags::PSEUDO_EDGE
165 == flag | EdgeFlags::FOLDER_EDGE | EdgeFlags::PSEUDO_EDGE
166 }) {
167 debug!("e = {:?}", e);
168 if e.flag.contains(EdgeFlags::FOLDER_EDGE) && file.is_none() {
170 *file = Some(current.clone())
171 } else {
172 find_alive.push(e.dest.clone())
173 }
174 }
175 }
176 }
177 }
178
179 pub fn find_alive_nonfolder_descendants(
184 &self,
185 branch: &Branch,
186 find_alive: &mut FindAlive,
187 alive: &mut HashSet<Key<PatchId>>,
188 file: &mut Option<Key<PatchId>>,
189 current: Key<PatchId>,
190 ) {
191 self.find_alive(
192 branch,
193 find_alive,
194 alive,
195 file,
196 current,
197 EdgeFlags::DELETED_EDGE,
198 )
199 }
200
201 pub fn find_alive_nonfolder_ancestors(
206 &self,
207 branch: &Branch,
208 find_alive: &mut FindAlive,
209 alive: &mut HashSet<Key<PatchId>>,
210 file: &mut Option<Key<PatchId>>,
211 current: Key<PatchId>,
212 ) {
213 self.find_alive(
214 branch,
215 find_alive,
216 alive,
217 file,
218 current,
219 EdgeFlags::DELETED_EDGE | EdgeFlags::PARENT_EDGE,
220 )
221 }
222}