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