1use backend::*;
2use patch::*;
3use rand;
4use record::{InodeUpdate, RecordState};
5use std::collections::HashSet;
6use std::path::Path;
7use Result;
8mod apply;
9pub mod find_alive;
10mod repair_deleted_context;
11use output;
12
13impl<U: Transaction, R> GenericTxn<U, R> {
14 pub fn internal_hash(&self, e: &Option<Hash>, internal: PatchId) -> PatchId {
16 match *e {
17 Some(Hash::None) => ROOT_PATCH_ID.clone(),
18 Some(ref h) => self.get_internal(h.as_ref()).unwrap().to_owned(),
19 None => internal.clone(),
20 }
21 }
22
23 pub fn internal_key(&self, key: &Key<Option<Hash>>, internal: PatchId) -> Key<PatchId> {
26 Key {
28 patch: self.internal_hash(&key.patch, internal),
29 line: key.line.clone(),
30 }
31 }
32
33 pub fn internal_key_unwrap(&self, key: &Key<Option<Hash>>) -> Key<PatchId> {
34 Key {
35 patch: self.get_internal(key.patch.as_ref().unwrap().as_ref())
36 .unwrap()
37 .to_owned(),
38 line: key.line.clone(),
39 }
40 }
41}
42
43impl<'env, T: rand::Rng> MutTxn<'env, T> {
44 pub fn apply_patches<F, P: output::ToPrefixes>(
49 &mut self,
50 branch: &mut Branch,
51 r: &Path,
52 remote_patches: &[(Hash, Patch)],
53 partial_paths: P,
54 mut f: F,
55 ) -> Result<()>
56 where
57 F: FnMut(usize, &Hash),
58 {
59 let (pending, local_pending) = {
60 let mut record = RecordState::new();
61 self.record(&mut record, branch, &r, None)?;
62 let (changes, local) = record.finish();
63 let mut p = UnsignedPatch::empty();
64 p.changes = changes
65 .into_iter()
66 .flat_map(|x| x.into_iter())
67 .map(|x| self.globalize_change(x))
68 .collect();
69 p.dependencies = self.dependencies(&branch, p.changes.iter());
70 (p.leave_unsigned(), local)
71 };
72
73 let mut new_patches_count = 0;
74 for &(ref p, ref patch) in remote_patches.iter() {
75 debug!("apply_patches: {:?}", p);
76 self.apply_patches_rec(branch, remote_patches, p, patch, &mut new_patches_count)?;
77 f(new_patches_count, p);
78 }
79 debug!("{} patches applied", new_patches_count);
80
81 if new_patches_count > 0 {
82 let partial_paths = partial_paths.to_prefixes(self, &branch);
83 self.output_changes_file(&branch, r)?;
84 debug!("output_repository");
85 self.output_partials(branch.name.as_str(), &partial_paths)?;
86 self.output_repository(branch, &r, &partial_paths, &pending, &local_pending)?;
87 debug!("done outputting_repository");
88 }
89 debug!("finished apply_patches");
90 Ok(())
91 }
92
93 pub fn apply_patches_rec(
98 &mut self,
99 branch: &mut Branch,
100 patches: &[(Hash, Patch)],
101 patch_hash: &Hash,
102 patch: &Patch,
103 new_patches_count: &mut usize,
104 ) -> Result<()> {
105 let internal = {
106 if let Some(internal) = self.get_internal(patch_hash.as_ref()) {
107 if self.get_patch(&branch.patches, internal).is_some() {
108 debug!(
109 "get_patch returned {:?}",
110 self.get_patch(&branch.patches, internal)
111 );
112 None
113 } else {
114 Some(internal.to_owned())
117 }
118 } else {
119 let internal = self.new_internal(patch_hash.as_ref());
121 Some(internal)
122 }
123 };
124 if let Some(internal) = internal {
125 info!(
126 "Now applying patch {:?} {:?} to branch {:?}",
127 patch.name, patch_hash, branch
128 );
129 if patch.dependencies().is_empty() {
130 info!("Patch {:?} has no dependencies", patch_hash);
131 }
132 for dep in patch.dependencies().iter() {
133 info!("Applying dependency {:?}", dep);
134 info!("dep hash {:?}", dep.to_base58());
135 let is_applied = {
136 if let Some(dep_internal) = self.get_internal(dep.as_ref()) {
137 self.get_patch(&branch.patches, dep_internal).is_some()
138 } else {
139 false
140 }
141 };
142 if !is_applied {
143 info!("Not applied");
144 if let Some(&(_, ref patch)) = patches.iter().find(|&&(ref a, _)| a == dep) {
148 self.apply_patches_rec(branch, patches, &dep, patch, new_patches_count)?;
149 } else {
150 error!("Dependency not found");
151 }
152 } else {
153 info!("Already applied");
154 }
155 let dep_internal = self.get_internal(dep.as_ref()).unwrap().to_owned();
156 self.put_revdep(dep_internal, internal)?;
157 self.put_dep(internal, dep_internal)?;
158 }
159
160 self.register_patch(internal, patch_hash, patch)?;
162
163 let now = branch.apply_counter;
164 branch.apply_counter += 1;
165 self.apply(branch, &patch, internal, now)?;
166
167 *new_patches_count += 1;
168
169 Ok(())
170 } else {
171 info!("Patch {:?} has already been applied", patch_hash);
172 Ok(())
173 }
174 }
175
176 pub fn apply_local_patch(
178 &mut self,
179 branch: &mut Branch,
180 working_copy: &Path,
181 hash: &Hash,
182 patch: &Patch,
183 inode_updates: &HashSet<InodeUpdate>,
184 is_pending: bool,
185 ) -> Result<PatchId> {
186 info!("registering a patch with {} changes", patch.changes().len());
187 info!("dependencies: {:?}", patch.dependencies());
188
189 let internal: PatchId = self.new_internal(hash.as_ref());
192
193 for dep in patch.dependencies().iter() {
194 let dep_internal = self.get_internal(dep.as_ref()).unwrap().to_owned();
195 self.put_revdep(dep_internal, internal)?;
196 self.put_dep(internal, dep_internal)?;
197 }
198 self.register_patch(internal, hash, patch)?;
199
200 info!("Applying local patch");
201 let now = branch.apply_counter;
202 self.apply(branch, &patch, internal, now)?;
203 debug!("synchronizing tree: {:?}", inode_updates);
204 for update in inode_updates.iter() {
205 self.update_inode(&branch, internal, update)?;
206 }
207 debug!("committing branch");
208 if !is_pending {
209 debug!("not pending, adding to changes");
210 branch.apply_counter += 1;
211 self.output_changes_file(&branch, working_copy)?;
212 }
213 trace!("done apply_local_patch");
214 Ok(internal)
215 }
216
217 fn register_patch(&mut self, internal: PatchId, hash: &Hash, patch: &Patch) -> Result<()> {
218 self.put_external(internal, hash.as_ref())?;
219 self.put_internal(hash.as_ref(), internal)?;
220 for hunk in patch.changes() {
221 let inode = match *hunk {
222 Change::NewNodes { ref inode, .. } => inode,
223 Change::NewEdges { ref inode, .. } => inode,
224 };
225 let inode = self.internal_key(inode, internal);
226 self.put_touched_file(inode, internal)?;
227 }
228 Ok(())
229 }
230
231 fn update_inode(
237 &mut self,
238 branch: &Branch,
239 internal: PatchId,
240 update: &InodeUpdate,
241 ) -> Result<()> {
242 match *update {
243 InodeUpdate::Add {
244 ref line,
245 ref meta,
246 inode,
247 } => {
248 let key = FileHeader {
249 metadata: *meta,
250 status: FileStatus::Ok,
251 key: Key {
252 patch: internal.clone(),
253 line: line.clone(),
254 },
255 };
256 if self.get_nodes(&branch, key.key, None).is_some() {
258 debug!("it's in here!: {:?} {:?}", key, inode);
259 self.replace_inodes(inode, key)?;
260 self.replace_revinodes(key.key, inode)?;
261 }
262 }
263 InodeUpdate::Deleted { inode } => {
264 debug!("deleted: {:?}", inode);
266 let header = self.get_inodes(inode).unwrap().clone();
267 debug!("deleted header: {:?}", header);
268 let edge = Edge::zero(
269 EdgeFlags::PARENT_EDGE | EdgeFlags::FOLDER_EDGE | EdgeFlags::DELETED_EDGE,
270 );
271 if self.iter_nodes(&branch, Some((header.key, Some(&edge))))
272 .take_while(|&(k, v)| k == header.key && edge.flag == v.flag)
273 .any(|(_, v)| v.introduced_by == internal)
274 {
275 self.del_inodes(inode, Some(header))?;
276 self.del_revinodes(header.key, Some(inode))?;
277
278 if let Some(parent) = self.get_revtree(inode).map(|x| x.to_owned()) {
281 let parent = parent.as_file_id();
282 self.del_tree(&parent, None)?;
283 self.del_revtree(inode, None)?;
284 }
285 }
286 }
287 InodeUpdate::Moved { inode } => {
288 debug!("moved: {:?}", inode);
290 let mut header = self.get_inodes(inode).unwrap().clone();
291 debug!("moved header: {:?}", header);
292 let edge = Edge::zero(EdgeFlags::PARENT_EDGE | EdgeFlags::FOLDER_EDGE);
293 if self.iter_nodes(&branch, Some((header.key, Some(&edge))))
294 .take_while(|&(k, v)| k == header.key && edge.flag == v.flag)
295 .any(|(_, v)| v.introduced_by == internal)
296 {
297 header.status = FileStatus::Ok;
298 self.replace_inodes(inode, header)?;
299 self.replace_revinodes(header.key, inode)?;
300 }
301 }
302 }
303 Ok(())
304 }
305}