1 use crate::change::*;
2 use crate::changestore::*;
3 use crate::pristine::*;
4 use crate::small_string::*;
5 
undo_file_addition< T: GraphMutTxnT + TreeMutTxnT<TreeError = <T as GraphTxnT>::GraphError>, >( txn: &mut T, change_id: ChangeId, new_vertex: &NewVertex<Option<Hash>>, ) -> Result<(), TxnErr<T::GraphError>>6 pub fn undo_file_addition<
7     T: GraphMutTxnT + TreeMutTxnT<TreeError = <T as GraphTxnT>::GraphError>,
8 >(
9     txn: &mut T,
10     change_id: ChangeId,
11     new_vertex: &NewVertex<Option<Hash>>,
12 ) -> Result<(), TxnErr<T::GraphError>> {
13     if new_vertex.start == new_vertex.end {
14         let pos = Position {
15             change: change_id,
16             pos: new_vertex.start,
17         };
18         if let Some(&inode) = txn.get_revinodes(&pos, None)? {
19             del_inodes_with_rev(txn, &inode, &pos)?;
20         }
21     }
22     Ok(())
23 }
24 
undo_file_deletion< T: ChannelTxnT + TreeMutTxnT + TreeTxnT<TreeError = <T as GraphTxnT>::GraphError>, P: ChangeStore, >( txn: &mut T, changes: &P, channel: &T::Channel, change_id: ChangeId, newedges: &EdgeMap<Option<Hash>>, salt: u64, ) -> Result<(), super::UnrecordError<P::Error, T::TreeError>>25 pub fn undo_file_deletion<
26     T: ChannelTxnT + TreeMutTxnT + TreeTxnT<TreeError = <T as GraphTxnT>::GraphError>,
27     P: ChangeStore,
28 >(
29     txn: &mut T,
30     changes: &P,
31     channel: &T::Channel,
32     change_id: ChangeId,
33     newedges: &EdgeMap<Option<Hash>>,
34     salt: u64,
35 ) -> Result<(), super::UnrecordError<P::Error, T::TreeError>> {
36     for e in newedges.edges.iter().rev() {
37         assert!(!e.flag.contains(EdgeFlags::PARENT));
38         let source =
39             *txn.find_block_end(txn.graph(channel), internal_pos(txn, &e.from, change_id)?)?;
40         if e.flag.contains(EdgeFlags::FOLDER) && e.to.start_pos() == e.to.end_pos() {
41             let dest = internal_pos(txn, &e.to.start_pos(), change_id)?;
42             restore(txn, changes, channel, source, dest, salt)?
43         }
44     }
45     Ok(())
46 }
47 
restore< T: ChannelTxnT + TreeMutTxnT + TreeTxnT<TreeError = <T as GraphTxnT>::GraphError>, P: ChangeStore, >( txn: &mut T, changes: &P, channel: &T::Channel, source: Vertex<ChangeId>, dest: Position<ChangeId>, salt: u64, ) -> Result<(), super::UnrecordError<P::Error, T::TreeError>>48 fn restore<
49     T: ChannelTxnT + TreeMutTxnT + TreeTxnT<TreeError = <T as GraphTxnT>::GraphError>,
50     P: ChangeStore,
51 >(
52     txn: &mut T,
53     changes: &P,
54     channel: &T::Channel,
55     source: Vertex<ChangeId>,
56     dest: Position<ChangeId>,
57     salt: u64,
58 ) -> Result<(), super::UnrecordError<P::Error, T::TreeError>> {
59     let mut stack = vec![(source, dest)];
60     let mut return_value = Some(Inode::ROOT);
61     while let Some((source, dest)) = stack.pop() {
62         if let Some(parent_inode) = return_value {
63             if parent_inode != Inode::ROOT {
64                 return_value = restore_inode(txn, changes, source, dest, parent_inode, salt)?;
65                 continue;
66             }
67         } else {
68             continue;
69         }
70         let mut source_parent = None;
71         for e in iter_adjacent(
72             txn,
73             txn.graph(channel),
74             source,
75             EdgeFlags::PARENT | EdgeFlags::FOLDER,
76             EdgeFlags::all(),
77         )? {
78             let e = e?;
79             if e.flag().contains(EdgeFlags::PARENT | EdgeFlags::FOLDER) {
80                 source_parent = Some(e.dest());
81                 break;
82             }
83         }
84         let source_parent = source_parent.unwrap();
85 
86         if source_parent.change.is_root() {
87             return_value = restore_inode(txn, changes, source, dest, Inode::ROOT, salt)?;
88         } else if let Some(&inode) = txn.get_revinodes(&source_parent, None)? {
89             return_value = restore_inode(txn, changes, source, dest, inode, salt)?;
90         } else {
91             let grandparent = find_youngest_parent(txn, channel, source_parent.inode_vertex())?;
92             stack.push((source, dest));
93             stack.push((grandparent, source_parent));
94         }
95     }
96     Ok(())
97 }
98 
restore_inode< T: TreeMutTxnT + GraphTxnT + TreeTxnT<TreeError = <T as GraphTxnT>::GraphError>, P: ChangeStore, >( txn: &mut T, changes: &P, source: Vertex<ChangeId>, dest: Position<ChangeId>, parent_inode: Inode, salt: u64, ) -> Result<Option<Inode>, super::UnrecordError<P::Error, T::TreeError>>99 fn restore_inode<
100     T: TreeMutTxnT + GraphTxnT + TreeTxnT<TreeError = <T as GraphTxnT>::GraphError>,
101     P: ChangeStore,
102 >(
103     txn: &mut T,
104     changes: &P,
105     source: Vertex<ChangeId>,
106     dest: Position<ChangeId>,
107     parent_inode: Inode,
108     salt: u64,
109 ) -> Result<Option<Inode>, super::UnrecordError<P::Error, T::TreeError>> {
110     let mut name = Vec::new();
111     let FileMetadata {
112         basename, metadata, ..
113     } = changes
114         .get_file_meta(
115             |h| txn.get_external(&h).unwrap().map(From::from),
116             source,
117             &mut name,
118         )
119         .map_err(super::UnrecordError::Changestore)?;
120     let basename = SmallString::from_str(basename);
121     if let Some(inode) = txn.get_revinodes(&dest, None)? {
122         Ok(Some(*inode))
123     } else {
124         let file_id = OwnedPathId {
125             parent_inode,
126             basename,
127         };
128         if txn.get_tree(&file_id, None)?.is_none() {
129             let inode = crate::fs::create_new_inode(txn, &file_id, salt)?;
130             put_tree_with_rev(txn, &file_id, &inode)?;
131             put_inodes_with_rev(txn, &inode, &dest)?;
132             if metadata.is_dir() {
133                 let id = OwnedPathId {
134                     parent_inode: inode,
135                     basename: SmallString::new(),
136                 };
137                 txn.put_tree(&id, &inode)?;
138             }
139             Ok(Some(inode))
140         } else {
141             Ok(None)
142         }
143     }
144 }
145 
find_youngest_parent<T: ChannelTxnT>( txn: &T, channel: &T::Channel, current: Vertex<ChangeId>, ) -> Result<Vertex<ChangeId>, BlockError<T::GraphError>>146 fn find_youngest_parent<T: ChannelTxnT>(
147     txn: &T,
148     channel: &T::Channel,
149     current: Vertex<ChangeId>,
150 ) -> Result<Vertex<ChangeId>, BlockError<T::GraphError>> {
151     let mut next = None;
152     for e in iter_adjacent(
153         txn,
154         txn.graph(channel),
155         current,
156         EdgeFlags::FOLDER | EdgeFlags::PARENT,
157         EdgeFlags::FOLDER | EdgeFlags::PARENT | EdgeFlags::DELETED | EdgeFlags::BLOCK,
158     )? {
159         let e = e?;
160         if !e.flag().contains(EdgeFlags::FOLDER | EdgeFlags::PARENT) {
161             continue;
162         }
163         if e.flag().contains(EdgeFlags::DELETED) {
164             debug!("deleted: {:?}", e.introduced_by());
165             let age = txn
166                 .get_changeset(txn.changes(channel), &e.introduced_by())?
167                 .unwrap();
168             if let Some((ref mut age0, ref mut v)) = next {
169                 if age > *age0 {
170                     *age0 = age;
171                     *v = e.dest()
172                 }
173             } else {
174                 next = Some((age, e.dest()))
175             }
176         } else {
177             next = Some((&L64(0), e.dest()));
178             break;
179         }
180     }
181     Ok(*txn.find_block_end(txn.graph(channel), next.unwrap().1)?)
182 }
183 
undo_file_reinsertion< P: ChangeStore, T: GraphTxnT + TreeMutTxnT + TreeTxnT<TreeError = <T as GraphTxnT>::GraphError>, >( txn: &mut T, change_id: ChangeId, newedges: &EdgeMap<Option<Hash>>, ) -> Result<(), super::UnrecordError<P::Error, T::TreeError>>184 pub fn undo_file_reinsertion<
185     P: ChangeStore,
186     T: GraphTxnT + TreeMutTxnT + TreeTxnT<TreeError = <T as GraphTxnT>::GraphError>,
187 >(
188     txn: &mut T,
189     change_id: ChangeId,
190     newedges: &EdgeMap<Option<Hash>>,
191 ) -> Result<(), super::UnrecordError<P::Error, T::TreeError>> {
192     for e in newedges.edges.iter() {
193         assert!(!e.flag.contains(EdgeFlags::PARENT));
194         if e.to.start_pos() == e.to.end_pos() {
195             let position = internal_pos(txn, &e.to.start_pos(), change_id)?;
196             if let Some(&inode) = txn.get_revinodes(&position, None)? {
197                 del_inodes_with_rev(txn, &inode, &position)?;
198             }
199         }
200     }
201     Ok(())
202 }
203