@@ -23,13 +23,11 @@ pub(crate) type ItemWithParent<O> = TreeType<(O, ParentResult<()>), ParentResult
2323#[ derive( Debug ) ]
2424pub struct Parent {
2525 /// The tree id of the parent tree.
26- tree_id : Option < TreeId > ,
26+ tree_ids : Vec < TreeId > ,
2727 /// The parent tree.
28- tree : Option < Tree > ,
29- /// The current node index.
30- node_idx : usize ,
28+ trees : Vec < ( Tree , usize ) > ,
3129 /// The stack of parent trees.
32- stack : Vec < ( Option < Tree > , usize ) > ,
30+ stack : Vec < Vec < ( Tree , usize ) > > ,
3331 /// Ignore ctime when comparing nodes.
3432 ignore_ctime : bool ,
3533 /// Ignore inode number when comparing nodes.
@@ -90,25 +88,28 @@ impl Parent {
9088 pub ( crate ) fn new (
9189 be : & impl DecryptReadBackend ,
9290 index : & impl ReadGlobalIndex ,
93- tree_id : Option < TreeId > ,
91+ tree_id : impl IntoIterator < Item = TreeId > ,
9492 ignore_ctime : bool ,
9593 ignore_inode : bool ,
9694 ) -> Self {
9795 // if tree_id is given, try to load tree from backend.
98- let tree = tree_id. and_then ( |tree_id| match Tree :: from_backend ( be, index, tree_id) {
99- Ok ( tree) => Some ( tree) ,
100- Err ( err) => {
101- warn ! (
102- "ignoring error when loading parent tree {tree_id}: {}" ,
103- err. display_log( )
104- ) ;
105- None
106- }
107- } ) ;
96+ let ( trees, tree_ids) = tree_id
97+ . into_iter ( )
98+ . filter_map ( |tree_id| match Tree :: from_backend ( be, index, tree_id) {
99+ Ok ( tree) => Some ( ( ( tree, 0 ) , tree_id) ) ,
100+ Err ( err) => {
101+ warn ! (
102+ "ignoring error when loading parent tree {tree_id:?}: {}" ,
103+ err. display_log( )
104+ ) ;
105+ None
106+ }
107+ } )
108+ . unzip ( ) ;
109+
108110 Self {
109- tree_id,
110- tree,
111- node_idx : 0 ,
111+ tree_ids,
112+ trees,
112113 stack : Vec :: new ( ) ,
113114 ignore_ctime,
114115 ignore_inode,
@@ -124,27 +125,24 @@ impl Parent {
124125 /// # Returns
125126 ///
126127 /// The parent node with the given name, or `None` if the parent node is not found.
127- fn p_node ( & mut self , name : & OsStr ) -> Option < & Node > {
128- match & self . tree {
129- None => None ,
130- Some ( tree) => {
131- let p_nodes = & tree. nodes ;
132- loop {
133- match p_nodes. get ( self . node_idx ) {
134- None => break None ,
135- Some ( p_node) => match p_node. name ( ) . as_os_str ( ) . cmp ( name) {
136- Ordering :: Less => self . node_idx += 1 ,
137- Ordering :: Equal => {
138- break Some ( p_node) ;
139- }
140- Ordering :: Greater => {
141- break None ;
142- }
143- } ,
144- }
128+ fn p_node ( & mut self , name : & OsStr ) -> impl Iterator < Item = & Node > {
129+ self . trees . iter_mut ( ) . filter_map ( |( tree, idx) | {
130+ let p_nodes = & tree. nodes ;
131+ loop {
132+ match p_nodes. get ( * idx) {
133+ None => break None ,
134+ Some ( p_node) => match p_node. name ( ) . as_os_str ( ) . cmp ( name) {
135+ Ordering :: Less => * idx += 1 ,
136+ Ordering :: Equal => {
137+ break Some ( p_node) ;
138+ }
139+ Ordering :: Greater => {
140+ break None ;
141+ }
142+ } ,
145143 }
146144 }
147- }
145+ } )
148146 }
149147
150148 /// Returns whether the given node is the parent of the given tree.
@@ -166,18 +164,22 @@ impl Parent {
166164 let ignore_ctime = self . ignore_ctime ;
167165 let ignore_inode = self . ignore_inode ;
168166
169- self . p_node ( name) . map_or ( ParentResult :: NotFound , |p_node| {
170- if p_node. node_type == node. node_type
171- && p_node. meta . size == node. meta . size
172- && p_node. meta . mtime == node. meta . mtime
173- && ( ignore_ctime || p_node. meta . ctime == node. meta . ctime )
174- && ( ignore_inode || p_node. meta . inode == 0 || p_node. meta . inode == node. meta . inode )
175- {
176- ParentResult :: Matched ( p_node)
177- } else {
178- ParentResult :: NotMatched
179- }
180- } )
167+ let mut p_node = self . p_node ( name) . peekable ( ) ;
168+ if p_node. peek ( ) . is_none ( ) {
169+ return ParentResult :: NotFound ;
170+ }
171+
172+ p_node
173+ . find ( |p_node| {
174+ p_node. node_type == node. node_type
175+ && p_node. meta . size == node. meta . size
176+ && p_node. meta . mtime == node. meta . mtime
177+ && ( ignore_ctime || p_node. meta . ctime == node. meta . ctime )
178+ && ( ignore_inode
179+ || p_node. meta . inode == 0
180+ || p_node. meta . inode == node. meta . inode )
181+ } )
182+ . map_or ( ParentResult :: NotMatched , ParentResult :: Matched )
181183 }
182184
183185 // TODO: add documentation!
@@ -196,27 +198,35 @@ impl Parent {
196198 index : & impl ReadGlobalIndex ,
197199 name : & OsStr ,
198200 ) {
199- let tree = self . p_node ( name) . and_then ( |p_node| {
200- p_node. subtree . map_or_else (
201- || {
201+ let mut new_ids: Vec < _ > = self
202+ . p_node ( name)
203+ . filter_map ( |p_node| {
204+ p_node. subtree . or_else ( || {
202205 warn ! ( "ignoring parent node {}: is no tree!" , p_node. name) ;
203206 None
204- } ,
205- |tree_id| match Tree :: from_backend ( be, index, tree_id) {
206- Ok ( tree) => Some ( tree) ,
207- Err ( err) => {
208- warn ! (
209- "ignoring error when loading parent tree {tree_id}: {}" ,
210- err. display_log( )
211- ) ;
212- None
213- }
214- } ,
215- )
216- } ) ;
217- self . stack . push ( ( self . tree . take ( ) , self . node_idx ) ) ;
218- self . tree = tree;
219- self . node_idx = 0 ;
207+ } )
208+ } )
209+ . collect ( ) ;
210+
211+ // remove potentially identical trees
212+ new_ids. sort ( ) ;
213+ new_ids. dedup ( ) ;
214+
215+ let new_tree = new_ids
216+ . into_iter ( )
217+ . filter_map ( |tree_id| match Tree :: from_backend ( be, index, tree_id) {
218+ Ok ( tree) => Some ( ( tree, 0 ) ) ,
219+ Err ( err) => {
220+ warn ! (
221+ "ignoring error when loading parent tree {tree_id}: {}" ,
222+ err. display_log( )
223+ ) ;
224+ None
225+ }
226+ } )
227+ . collect ( ) ;
228+ let old_tree = std:: mem:: replace ( & mut self . trees , new_tree) ;
229+ self . stack . push ( old_tree) ;
220230 }
221231
222232 // TODO: add documentation!
@@ -225,17 +235,15 @@ impl Parent {
225235 ///
226236 /// * If the tree stack is empty.
227237 fn finish_dir ( & mut self ) -> Result < ( ) , TreeStackEmptyError > {
228- let ( tree, node_idx) = self . stack . pop ( ) . ok_or ( TreeStackEmptyError ) ?;
229-
230- self . tree = tree;
231- self . node_idx = node_idx;
238+ let tree = self . stack . pop ( ) . ok_or ( TreeStackEmptyError ) ?;
239+ self . trees = tree;
232240
233241 Ok ( ( ) )
234242 }
235243
236244 // TODO: add documentation!
237245 pub ( crate ) fn tree_id ( & self ) -> Option < TreeId > {
238- self . tree_id
246+ self . tree_ids . first ( ) . copied ( )
239247 }
240248
241249 // TODO: add documentation!
0 commit comments