1 #[macro_use]
2 extern crate log;
3 #[macro_use]
4 extern crate serde_derive;
5 #[macro_use]
6 extern crate bitflags;
7 #[macro_use]
8 extern crate pijul_macros;
9 #[macro_use]
10 extern crate thiserror;
11 #[macro_use]
12 extern crate lazy_static;
13 
14 pub mod alive;
15 mod apply;
16 pub mod change;
17 pub mod changestore;
18 mod diff;
19 pub mod find_alive;
20 pub mod fs;
21 mod missing_context;
22 pub mod output;
23 pub mod path;
24 pub mod pristine;
25 pub mod record;
26 pub mod small_string;
27 mod text_encoding;
28 mod unrecord;
29 mod vector2;
30 pub mod vertex_buffer;
31 pub mod working_copy;
32 
33 pub mod key;
34 pub mod tag;
35 
36 mod chardetng;
37 
38 #[cfg(test)]
39 mod tests;
40 
41 pub const DOT_DIR: &str = ".pijul";
42 
43 #[derive(Debug, Error)]
44 #[error("Parse error: {:?}", s)]
45 pub struct ParseError {
46     s: String,
47 }
48 
49 #[derive(Debug, Error, Serialize, Deserialize)]
50 pub enum RemoteError {
51     #[error("Repository not found: {}", url)]
52     RepositoryNotFound { url: String },
53     #[error("Channel {} not found for repository {}", channel, url)]
54     ChannelNotFound { channel: String, url: String },
55     #[error("Ambiguous path: {}", path)]
56     AmbiguousPath { path: String },
57     #[error("Path not found: {}", path)]
58     PathNotFound { path: String },
59     #[error("Change not found: {}", change)]
60     ChangeNotFound { change: String },
61 }
62 
63 pub use crate::apply::Workspace as ApplyWorkspace;
64 pub use crate::apply::{apply_change_arc, ApplyError, LocalApplyError};
65 pub use crate::diff::DEFAULT_SEPARATOR;
66 pub use crate::fs::{FsError, WorkingCopyIterator};
67 pub use crate::output::{Archive, Conflict};
68 pub use crate::pristine::{
69     ArcTxn, Base32, ChangeId, ChannelMutTxnT, ChannelRef, ChannelTxnT, DepsTxnT, EdgeFlags,
70     GraphTxnT, Hash, Inode, Merkle, MutTxnT, OwnedPathId, RemoteRef, TreeTxnT, TxnT, Vertex,
71 };
72 pub use crate::record::Builder as RecordBuilder;
73 pub use crate::record::{Algorithm, InodeUpdate};
74 pub use crate::unrecord::UnrecordError;
75 
76 // Making hashmaps deterministic (for testing)
77 #[cfg(feature = "deterministic_hash")]
78 pub type Hasher = std::hash::BuildHasherDefault<twox_hash::XxHash64>;
79 #[cfg(not(feature = "deterministic_hash"))]
80 pub type Hasher = std::collections::hash_map::RandomState;
81 
82 pub type HashMap<K, V> = std::collections::HashMap<K, V, Hasher>;
83 pub type HashSet<K> = std::collections::HashSet<K, Hasher>;
84 
85 impl MutTxnTExt for pristine::sanakirja::MutTxn<()> {}
86 impl TxnTExt for pristine::sanakirja::MutTxn<()> {}
87 impl TxnTExt for pristine::sanakirja::Txn {}
88 
commit<T: pristine::MutTxnT>( txn: std::sync::Arc<std::sync::RwLock<T>>, ) -> Result<(), T::GraphError>89 pub fn commit<T: pristine::MutTxnT>(
90     txn: std::sync::Arc<std::sync::RwLock<T>>,
91 ) -> Result<(), T::GraphError> {
92     let txn = if let Ok(txn) = std::sync::Arc::try_unwrap(txn) {
93         txn.into_inner().unwrap()
94     } else {
95         unreachable!()
96     };
97     txn.commit()
98 }
99 
100 pub trait MutTxnTExt: pristine::MutTxnT {
apply_change_ws<C: changestore::ChangeStore>( &mut self, changes: &C, channel: &mut Self::Channel, hash: &crate::pristine::Hash, workspace: &mut ApplyWorkspace, ) -> Result<(u64, pristine::Merkle), crate::apply::ApplyError<C::Error, Self::GraphError>>101     fn apply_change_ws<C: changestore::ChangeStore>(
102         &mut self,
103         changes: &C,
104         channel: &mut Self::Channel,
105         hash: &crate::pristine::Hash,
106         workspace: &mut ApplyWorkspace,
107     ) -> Result<(u64, pristine::Merkle), crate::apply::ApplyError<C::Error, Self::GraphError>> {
108         crate::apply::apply_change_ws(changes, self, channel, hash, workspace)
109     }
110 
apply_change_rec_ws<C: changestore::ChangeStore>( &mut self, changes: &C, channel: &mut Self::Channel, hash: &crate::pristine::Hash, workspace: &mut ApplyWorkspace, ) -> Result<(), crate::apply::ApplyError<C::Error, Self::GraphError>>111     fn apply_change_rec_ws<C: changestore::ChangeStore>(
112         &mut self,
113         changes: &C,
114         channel: &mut Self::Channel,
115         hash: &crate::pristine::Hash,
116         workspace: &mut ApplyWorkspace,
117     ) -> Result<(), crate::apply::ApplyError<C::Error, Self::GraphError>> {
118         crate::apply::apply_change_rec_ws(changes, self, channel, hash, workspace, false)
119     }
120 
apply_change<C: changestore::ChangeStore>( &mut self, changes: &C, channel: &mut Self::Channel, hash: &pristine::Hash, ) -> Result<(u64, pristine::Merkle), crate::apply::ApplyError<C::Error, Self::GraphError>>121     fn apply_change<C: changestore::ChangeStore>(
122         &mut self,
123         changes: &C,
124         channel: &mut Self::Channel,
125         hash: &pristine::Hash,
126     ) -> Result<(u64, pristine::Merkle), crate::apply::ApplyError<C::Error, Self::GraphError>> {
127         crate::apply::apply_change(changes, self, channel, hash)
128     }
129 
apply_change_rec<C: changestore::ChangeStore>( &mut self, changes: &C, channel: &mut Self::Channel, hash: &pristine::Hash, ) -> Result<(), crate::apply::ApplyError<C::Error, Self::GraphError>>130     fn apply_change_rec<C: changestore::ChangeStore>(
131         &mut self,
132         changes: &C,
133         channel: &mut Self::Channel,
134         hash: &pristine::Hash,
135     ) -> Result<(), crate::apply::ApplyError<C::Error, Self::GraphError>> {
136         crate::apply::apply_change_rec(changes, self, channel, hash, false)
137     }
138 
apply_deps_rec<C: changestore::ChangeStore>( &mut self, changes: &C, channel: &mut Self::Channel, hash: &pristine::Hash, ) -> Result<(), crate::apply::ApplyError<C::Error, Self::GraphError>>139     fn apply_deps_rec<C: changestore::ChangeStore>(
140         &mut self,
141         changes: &C,
142         channel: &mut Self::Channel,
143         hash: &pristine::Hash,
144     ) -> Result<(), crate::apply::ApplyError<C::Error, Self::GraphError>> {
145         crate::apply::apply_change_rec(changes, self, channel, hash, true)
146     }
147 
apply_local_change_ws( &mut self, channel: &pristine::ChannelRef<Self>, change: &change::Change, hash: &pristine::Hash, inode_updates: &HashMap<usize, InodeUpdate>, workspace: &mut ApplyWorkspace, ) -> Result<(u64, pristine::Merkle), crate::apply::LocalApplyError<Self::GraphError>>148     fn apply_local_change_ws(
149         &mut self,
150         channel: &pristine::ChannelRef<Self>,
151         change: &change::Change,
152         hash: &pristine::Hash,
153         inode_updates: &HashMap<usize, InodeUpdate>,
154         workspace: &mut ApplyWorkspace,
155     ) -> Result<(u64, pristine::Merkle), crate::apply::LocalApplyError<Self::GraphError>> {
156         crate::apply::apply_local_change_ws(self, channel, change, hash, inode_updates, workspace)
157     }
158 
apply_local_change( &mut self, channel: &crate::pristine::ChannelRef<Self>, change: &crate::change::Change, hash: &pristine::Hash, inode_updates: &HashMap<usize, InodeUpdate>, ) -> Result<(u64, pristine::Merkle), crate::apply::LocalApplyError<Self::GraphError>>159     fn apply_local_change(
160         &mut self,
161         channel: &crate::pristine::ChannelRef<Self>,
162         change: &crate::change::Change,
163         hash: &pristine::Hash,
164         inode_updates: &HashMap<usize, InodeUpdate>,
165     ) -> Result<(u64, pristine::Merkle), crate::apply::LocalApplyError<Self::GraphError>> {
166         crate::apply::apply_local_change(self, channel, change, hash, inode_updates)
167     }
168 
apply_recorded<C: changestore::ChangeStore>( &mut self, channel: &mut pristine::ChannelRef<Self>, recorded: record::Recorded, changestore: &C, ) -> Result<pristine::Hash, crate::apply::ApplyError<C::Error, Self::GraphError>>169     fn apply_recorded<C: changestore::ChangeStore>(
170         &mut self,
171         channel: &mut pristine::ChannelRef<Self>,
172         recorded: record::Recorded,
173         changestore: &C,
174     ) -> Result<pristine::Hash, crate::apply::ApplyError<C::Error, Self::GraphError>> {
175         let contents_hash = {
176             let mut hasher = pristine::Hasher::default();
177             hasher.update(&recorded.contents.lock()[..]);
178             hasher.finish()
179         };
180         let mut change = change::LocalChange {
181             offsets: change::Offsets::default(),
182             hashed: change::Hashed {
183                 version: change::VERSION,
184                 contents_hash,
185                 changes: recorded
186                     .actions
187                     .into_iter()
188                     .map(|rec| rec.globalize(self).unwrap())
189                     .collect(),
190                 metadata: Vec::new(),
191                 dependencies: Vec::new(),
192                 extra_known: Vec::new(),
193                 header: change::ChangeHeader::default(),
194             },
195             unhashed: None,
196             contents: std::sync::Arc::try_unwrap(recorded.contents)
197                 .unwrap()
198                 .into_inner(),
199         };
200         let hash = changestore
201             .save_change(&mut change, |_, _| Ok(()))
202             .map_err(apply::ApplyError::Changestore)?;
203         apply::apply_local_change(self, channel, &change, &hash, &recorded.updatables)?;
204         Ok(hash)
205     }
206 
unrecord<C: changestore::ChangeStore>( &mut self, changes: &C, channel: &pristine::ChannelRef<Self>, hash: &pristine::Hash, salt: u64, ) -> Result<bool, unrecord::UnrecordError<C::Error, Self::GraphError>>207     fn unrecord<C: changestore::ChangeStore>(
208         &mut self,
209         changes: &C,
210         channel: &pristine::ChannelRef<Self>,
211         hash: &pristine::Hash,
212         salt: u64,
213     ) -> Result<bool, unrecord::UnrecordError<C::Error, Self::GraphError>> {
214         unrecord::unrecord(self, channel, changes, hash, salt)
215     }
216 
217     /// Register a file in the working copy, where the file is given by
218     /// its path from the root of the repository, where the components of
219     /// the path are separated by `/` (example path: `a/b/c`).
add_file(&mut self, path: &str, salt: u64) -> Result<Inode, fs::FsError<Self::GraphError>>220     fn add_file(&mut self, path: &str, salt: u64) -> Result<Inode, fs::FsError<Self::GraphError>> {
221         fs::add_inode(self, None, path, false, salt)
222     }
223 
224     /// Register a directory in the working copy, where the directory is
225     /// given by its path from the root of the repository, where the
226     /// components of the path are separated by `/` (example path:
227     /// `a/b/c`).
add_dir(&mut self, path: &str, salt: u64) -> Result<Inode, fs::FsError<Self::GraphError>>228     fn add_dir(&mut self, path: &str, salt: u64) -> Result<Inode, fs::FsError<Self::GraphError>> {
229         fs::add_inode(self, None, path, true, salt)
230     }
231 
232     /// Register a file or directory in the working copy, given by its
233     /// path from the root of the repository, where the components of the
234     /// path are separated by `/` (example path: `a/b/c`).
add( &mut self, path: &str, is_dir: bool, salt: u64, ) -> Result<Inode, fs::FsError<Self::GraphError>>235     fn add(
236         &mut self,
237         path: &str,
238         is_dir: bool,
239         salt: u64,
240     ) -> Result<Inode, fs::FsError<Self::GraphError>> {
241         fs::add_inode(self, None, path, is_dir, salt)
242     }
243 
move_file( &mut self, a: &str, b: &str, salt: u64, ) -> Result<(), fs::FsError<Self::GraphError>>244     fn move_file(
245         &mut self,
246         a: &str,
247         b: &str,
248         salt: u64,
249     ) -> Result<(), fs::FsError<Self::GraphError>> {
250         fs::move_file(self, a, b, salt)
251     }
252 
remove_file(&mut self, a: &str) -> Result<(), fs::FsError<Self::GraphError>>253     fn remove_file(&mut self, a: &str) -> Result<(), fs::FsError<Self::GraphError>> {
254         fs::remove_file(self, a)
255     }
256 
archive_with_state<P: changestore::ChangeStore, A: Archive>( &mut self, changes: &P, channel: &mut pristine::ChannelRef<Self>, state: &pristine::Merkle, extra: &[pristine::Hash], arch: &mut A, salt: u64, ) -> Result<Vec<output::Conflict>, output::ArchiveError<P::Error, Self::GraphError, A::Error>>257     fn archive_with_state<P: changestore::ChangeStore, A: Archive>(
258         &mut self,
259         changes: &P,
260         channel: &mut pristine::ChannelRef<Self>,
261         state: &pristine::Merkle,
262         extra: &[pristine::Hash],
263         arch: &mut A,
264         salt: u64,
265     ) -> Result<Vec<output::Conflict>, output::ArchiveError<P::Error, Self::GraphError, A::Error>>
266     {
267         self.archive_prefix_with_state(
268             changes,
269             channel,
270             state,
271             extra,
272             &mut std::iter::empty(),
273             arch,
274             salt,
275         )
276     }
277 
278     /// Warning: this method unrecords changes until finding the
279     /// state. If this is not wanted, please fork the channel before
280     /// calling.
archive_prefix_with_state< 'a, P: changestore::ChangeStore, A: Archive, I: Iterator<Item = &'a str>, >( &mut self, changes: &P, channel: &mut pristine::ChannelRef<Self>, state: &pristine::Merkle, extra: &[pristine::Hash], prefix: &mut I, arch: &mut A, salt: u64, ) -> Result<Vec<output::Conflict>, output::ArchiveError<P::Error, Self::GraphError, A::Error>>281     fn archive_prefix_with_state<
282         'a,
283         P: changestore::ChangeStore,
284         A: Archive,
285         I: Iterator<Item = &'a str>,
286     >(
287         &mut self,
288         changes: &P,
289         channel: &mut pristine::ChannelRef<Self>,
290         state: &pristine::Merkle,
291         extra: &[pristine::Hash],
292         prefix: &mut I,
293         arch: &mut A,
294         salt: u64,
295     ) -> Result<Vec<output::Conflict>, output::ArchiveError<P::Error, Self::GraphError, A::Error>>
296     {
297         let mut unrecord = Vec::new();
298         let mut found = false;
299         for x in pristine::changeid_rev_log(self, &channel.read(), None)? {
300             let (_, p) = x?;
301             let m: Merkle = (&p.b).into();
302             if &m == state {
303                 found = true;
304                 break;
305             } else {
306                 unrecord.push(p.a.into())
307             }
308         }
309         debug!("unrecord = {:?}", unrecord);
310         if found {
311             for h in unrecord.iter() {
312                 let h = self.get_external(h)?.unwrap().into();
313                 self.unrecord(changes, channel, &h, salt)?;
314             }
315             {
316                 let mut channel_ = channel.write();
317                 for app in extra.iter() {
318                     self.apply_change_rec(changes, &mut channel_, app)?
319                 }
320             }
321             output::archive(changes, self, channel, prefix, arch)
322         } else {
323             Err(output::ArchiveError::StateNotFound { state: *state })
324         }
325     }
326 }
327 
328 pub trait TxnTExt: pristine::TxnT {
is_directory(&self, inode: pristine::Inode) -> Result<bool, Self::TreeError>329     fn is_directory(&self, inode: pristine::Inode) -> Result<bool, Self::TreeError> {
330         fs::is_directory(self, inode).map_err(|e| e.0)
331     }
332 
is_tracked(&self, path: &str) -> Result<bool, Self::TreeError>333     fn is_tracked(&self, path: &str) -> Result<bool, Self::TreeError> {
334         fs::is_tracked(self, path).map_err(|e| e.0)
335     }
336 
iter_working_copy(&self) -> WorkingCopyIterator<Self>337     fn iter_working_copy(&self) -> WorkingCopyIterator<Self> {
338         fs::iter_working_copy(self, pristine::Inode::ROOT)
339     }
340 
iter_graph_children<'txn, 'changes, P>( &'txn self, changes: &'changes P, channel: &'txn Self::Channel, key: pristine::Position<ChangeId>, ) -> Result<fs::GraphChildren<'txn, 'changes, Self, P>, Self::GraphError> where P: changestore::ChangeStore,341     fn iter_graph_children<'txn, 'changes, P>(
342         &'txn self,
343         changes: &'changes P,
344         channel: &'txn Self::Channel,
345         key: pristine::Position<ChangeId>,
346     ) -> Result<fs::GraphChildren<'txn, 'changes, Self, P>, Self::GraphError>
347     where
348         P: changestore::ChangeStore,
349     {
350         fs::iter_graph_children(self, changes, &self.graph(channel), key)
351     }
352 
has_change( &self, channel: &pristine::ChannelRef<Self>, hash: &pristine::Hash, ) -> Result<Option<u64>, Self::GraphError>353     fn has_change(
354         &self,
355         channel: &pristine::ChannelRef<Self>,
356         hash: &pristine::Hash,
357     ) -> Result<Option<u64>, Self::GraphError> {
358         if let Some(cid) = pristine::GraphTxnT::get_internal(self, &hash.into()).map_err(|e| e.0)? {
359             self.get_changeset(self.changes(&channel.read()), cid)
360                 .map_err(|e| e.0)
361                 .map(|x| x.map(|x| u64::from_le(x.0)))
362         } else {
363             Ok(None)
364         }
365     }
366 
is_alive( &self, channel: &Self::Channel, a: &pristine::Vertex<pristine::ChangeId>, ) -> Result<bool, Self::GraphError>367     fn is_alive(
368         &self,
369         channel: &Self::Channel,
370         a: &pristine::Vertex<pristine::ChangeId>,
371     ) -> Result<bool, Self::GraphError> {
372         pristine::is_alive(self, self.graph(channel), a).map_err(|e| e.0)
373     }
374 
current_state(&self, channel: &Self::Channel) -> Result<pristine::Merkle, Self::GraphError>375     fn current_state(&self, channel: &Self::Channel) -> Result<pristine::Merkle, Self::GraphError> {
376         pristine::current_state(self, channel).map_err(|e| e.0)
377     }
378 
log<'channel, 'txn>( &'txn self, channel: &'channel Self::Channel, from: u64, ) -> Result<Log<'txn, Self>, Self::GraphError>379     fn log<'channel, 'txn>(
380         &'txn self,
381         channel: &'channel Self::Channel,
382         from: u64,
383     ) -> Result<Log<'txn, Self>, Self::GraphError> {
384         Ok(Log {
385             txn: self,
386             iter: pristine::changeid_log(self, channel, pristine::L64(from.to_le()))
387                 .map_err(|e| e.0)?,
388         })
389     }
390 
log_for_path<'channel, 'txn>( &'txn self, channel: &'channel Self::Channel, pos: pristine::Position<pristine::ChangeId>, from: u64, ) -> Result<pristine::PathChangeset<'channel, 'txn, Self>, Self::GraphError>391     fn log_for_path<'channel, 'txn>(
392         &'txn self,
393         channel: &'channel Self::Channel,
394         pos: pristine::Position<pristine::ChangeId>,
395         from: u64,
396     ) -> Result<pristine::PathChangeset<'channel, 'txn, Self>, Self::GraphError> {
397         pristine::log_for_path(self, channel, pos, from).map_err(|e| e.0)
398     }
399 
rev_log_for_path<'channel, 'txn>( &'txn self, channel: &'channel Self::Channel, pos: pristine::Position<pristine::ChangeId>, from: u64, ) -> Result<pristine::RevPathChangeset<'channel, 'txn, Self>, Self::DepsError>400     fn rev_log_for_path<'channel, 'txn>(
401         &'txn self,
402         channel: &'channel Self::Channel,
403         pos: pristine::Position<pristine::ChangeId>,
404         from: u64,
405     ) -> Result<pristine::RevPathChangeset<'channel, 'txn, Self>, Self::DepsError> {
406         pristine::rev_log_for_path(self, channel, pos, from).map_err(|e| e.0)
407     }
408 
reverse_log<'channel, 'txn>( &'txn self, channel: &'channel Self::Channel, from: Option<u64>, ) -> Result<RevLog<'txn, Self>, Self::GraphError>409     fn reverse_log<'channel, 'txn>(
410         &'txn self,
411         channel: &'channel Self::Channel,
412         from: Option<u64>,
413     ) -> Result<RevLog<'txn, Self>, Self::GraphError> {
414         Ok(RevLog {
415             txn: self,
416             iter: pristine::changeid_rev_log(self, channel, from.map(|x| pristine::L64(x.to_le())))
417                 .map_err(|e| e.0)?,
418         })
419     }
420 
changeid_reverse_log<'txn>( &'txn self, channel: &Self::Channel, from: Option<pristine::L64>, ) -> Result< pristine::RevCursor< Self, &'txn Self, Self::RevchangesetCursor, pristine::L64, pristine::Pair<pristine::ChangeId, pristine::SerializedMerkle>, >, Self::GraphError, >421     fn changeid_reverse_log<'txn>(
422         &'txn self,
423         channel: &Self::Channel,
424         from: Option<pristine::L64>,
425     ) -> Result<
426         pristine::RevCursor<
427             Self,
428             &'txn Self,
429             Self::RevchangesetCursor,
430             pristine::L64,
431             pristine::Pair<pristine::ChangeId, pristine::SerializedMerkle>,
432         >,
433         Self::GraphError,
434     > {
435         pristine::changeid_rev_log(self, channel, from).map_err(|e| e.0)
436     }
437 
get_changes( &self, channel: &pristine::ChannelRef<Self>, n: u64, ) -> Result<Option<(pristine::Hash, pristine::Merkle)>, Self::GraphError>438     fn get_changes(
439         &self,
440         channel: &pristine::ChannelRef<Self>,
441         n: u64,
442     ) -> Result<Option<(pristine::Hash, pristine::Merkle)>, Self::GraphError> {
443         if let Some(p) = self
444             .get_revchangeset(self.rev_changes(&channel.read()), &pristine::L64(n.to_le()))
445             .map_err(|e| e.0)?
446         {
447             Ok(Some((
448                 self.get_external(&p.a.into())
449                     .map_err(|e| e.0)?
450                     .unwrap()
451                     .into(),
452                 (&p.b).into(),
453             )))
454         } else {
455             Ok(None)
456         }
457     }
458 
get_revchanges( &self, channel: &pristine::ChannelRef<Self>, h: &pristine::Hash, ) -> Result<Option<u64>, Self::GraphError>459     fn get_revchanges(
460         &self,
461         channel: &pristine::ChannelRef<Self>,
462         h: &pristine::Hash,
463     ) -> Result<Option<u64>, Self::GraphError> {
464         if let Some(h) = pristine::GraphTxnT::get_internal(self, &h.into()).map_err(|e| e.0)? {
465             self.get_changeset(self.changes(&channel.read()), h)
466                 .map_err(|e| e.0)
467                 .map(|x| x.map(|x| u64::from_le(x.0)))
468         } else {
469             Ok(None)
470         }
471     }
472 
touched_files(&self, h: &pristine::Hash) -> Result<Option<Touched<Self>>, Self::DepsError>473     fn touched_files(&self, h: &pristine::Hash) -> Result<Option<Touched<Self>>, Self::DepsError> {
474         if let Some(id) = pristine::GraphTxnT::get_internal(self, &h.into()).map_err(|e| e.0)? {
475             Ok(Some(Touched {
476                 txn: self,
477                 iter: self.iter_rev_touched_files(id, None).map_err(|e| e.0)?,
478                 id: *id,
479             }))
480         } else {
481             Ok(None)
482         }
483     }
484 
find_oldest_path<C: changestore::ChangeStore>( &self, changes: &C, channel: &pristine::ChannelRef<Self>, position: &pristine::Position<pristine::Hash>, ) -> Result<Option<(String, bool)>, output::FileError<C::Error, Self::GraphError>>485     fn find_oldest_path<C: changestore::ChangeStore>(
486         &self,
487         changes: &C,
488         channel: &pristine::ChannelRef<Self>,
489         position: &pristine::Position<pristine::Hash>,
490     ) -> Result<Option<(String, bool)>, output::FileError<C::Error, Self::GraphError>> {
491         let position = pristine::Position {
492             change: *pristine::GraphTxnT::get_internal(self, &position.change.into())?.unwrap(),
493             pos: position.pos,
494         };
495         fs::find_path(changes, self, &channel.read(), false, position)
496     }
497 
find_youngest_path<C: changestore::ChangeStore>( &self, changes: &C, channel: &pristine::ChannelRef<Self>, position: pristine::Position<pristine::Hash>, ) -> Result<Option<(String, bool)>, output::FileError<C::Error, Self::GraphError>>498     fn find_youngest_path<C: changestore::ChangeStore>(
499         &self,
500         changes: &C,
501         channel: &pristine::ChannelRef<Self>,
502         position: pristine::Position<pristine::Hash>,
503     ) -> Result<Option<(String, bool)>, output::FileError<C::Error, Self::GraphError>> {
504         let position = pristine::Position {
505             change: *pristine::GraphTxnT::get_internal(self, &position.change.into())?.unwrap(),
506             pos: position.pos,
507         };
508         fs::find_path(changes, self, &channel.read(), true, position)
509     }
510 
follow_oldest_path<C: changestore::ChangeStore>( &self, changes: &C, channel: &pristine::ChannelRef<Self>, path: &str, ) -> Result< (pristine::Position<pristine::ChangeId>, bool), fs::FsErrorC<C::Error, Self::GraphError>, >511     fn follow_oldest_path<C: changestore::ChangeStore>(
512         &self,
513         changes: &C,
514         channel: &pristine::ChannelRef<Self>,
515         path: &str,
516     ) -> Result<
517         (pristine::Position<pristine::ChangeId>, bool),
518         fs::FsErrorC<C::Error, Self::GraphError>,
519     > {
520         fs::follow_oldest_path(changes, self, &channel.read(), path)
521     }
522 
archive<C: changestore::ChangeStore, A: Archive>( &self, changes: &C, channel: &pristine::ChannelRef<Self>, arch: &mut A, ) -> Result<Vec<output::Conflict>, output::ArchiveError<C::Error, Self::GraphError, A::Error>>523     fn archive<C: changestore::ChangeStore, A: Archive>(
524         &self,
525         changes: &C,
526         channel: &pristine::ChannelRef<Self>,
527         arch: &mut A,
528     ) -> Result<Vec<output::Conflict>, output::ArchiveError<C::Error, Self::GraphError, A::Error>>
529     {
530         output::archive(changes, self, channel, &mut std::iter::empty(), arch)
531     }
532 
archive_prefix<'a, C: changestore::ChangeStore, I: Iterator<Item = &'a str>, A: Archive>( &self, changes: &C, channel: &pristine::ChannelRef<Self>, prefix: &mut I, arch: &mut A, ) -> Result<Vec<output::Conflict>, output::ArchiveError<C::Error, Self::GraphError, A::Error>>533     fn archive_prefix<'a, C: changestore::ChangeStore, I: Iterator<Item = &'a str>, A: Archive>(
534         &self,
535         changes: &C,
536         channel: &pristine::ChannelRef<Self>,
537         prefix: &mut I,
538         arch: &mut A,
539     ) -> Result<Vec<output::Conflict>, output::ArchiveError<C::Error, Self::GraphError, A::Error>>
540     {
541         output::archive(changes, self, channel, prefix, arch)
542     }
543 
iter_adjacent<'txn>( &'txn self, graph: &'txn Self::Channel, key: Vertex<pristine::ChangeId>, min_flag: pristine::EdgeFlags, max_flag: pristine::EdgeFlags, ) -> Result<pristine::AdjacentIterator<'txn, Self>, pristine::TxnErr<Self::GraphError>>544     fn iter_adjacent<'txn>(
545         &'txn self,
546         graph: &'txn Self::Channel,
547         key: Vertex<pristine::ChangeId>,
548         min_flag: pristine::EdgeFlags,
549         max_flag: pristine::EdgeFlags,
550     ) -> Result<pristine::AdjacentIterator<'txn, Self>, pristine::TxnErr<Self::GraphError>> {
551         pristine::iter_adjacent(self, self.graph(graph), key, min_flag, max_flag)
552     }
553 }
554 
555 pub struct Log<'txn, T: pristine::ChannelTxnT> {
556     txn: &'txn T,
557     iter: pristine::Cursor<
558         T,
559         &'txn T,
560         T::RevchangesetCursor,
561         pristine::L64,
562         pristine::Pair<pristine::ChangeId, pristine::SerializedMerkle>,
563     >,
564 }
565 
566 impl<'txn, T: pristine::ChannelTxnT> Iterator for Log<'txn, T> {
567     type Item = Result<
568         (
569             u64,
570             (
571                 &'txn pristine::SerializedHash,
572                 &'txn pristine::SerializedMerkle,
573             ),
574         ),
575         T::GraphError,
576     >;
next(&mut self) -> Option<Self::Item>577     fn next(&mut self) -> Option<Self::Item> {
578         match self.iter.next() {
579             Some(Ok((n, p))) => {
580                 let ext = match self.txn.get_external(&p.a) {
581                     Err(pristine::TxnErr(e)) => return Some(Err(e)),
582                     Ok(Some(ext)) => ext,
583                     Ok(None) => panic!("Unknown change {:?}", p),
584                 };
585                 Some(Ok((u64::from_le(n.0), (ext, &p.b))))
586             }
587             None => None,
588             Some(Err(e)) => Some(Err(e.0)),
589         }
590     }
591 }
592 
593 pub struct RevLog<'txn, T: pristine::ChannelTxnT> {
594     txn: &'txn T,
595     iter: pristine::RevCursor<
596         T,
597         &'txn T,
598         T::RevchangesetCursor,
599         pristine::L64,
600         pristine::Pair<pristine::ChangeId, pristine::SerializedMerkle>,
601     >,
602 }
603 
604 impl<'txn, T: pristine::ChannelTxnT> Iterator for RevLog<'txn, T> {
605     type Item = Result<
606         (
607             u64,
608             (
609                 &'txn pristine::SerializedHash,
610                 &'txn pristine::SerializedMerkle,
611             ),
612         ),
613         T::GraphError,
614     >;
next(&mut self) -> Option<Self::Item>615     fn next(&mut self) -> Option<Self::Item> {
616         match self.iter.next() {
617             Some(Ok((n, p))) => match self.txn.get_external(&p.a.into()) {
618                 Ok(Some(ext)) => Some(Ok((u64::from_le(n.0), (ext, &p.b)))),
619                 Err(e) => Some(Err(e.0)),
620                 Ok(None) => panic!("Unknown change {:?}", p),
621             },
622             None => None,
623             Some(Err(e)) => Some(Err(e.0)),
624         }
625     }
626 }
627 
628 pub struct Touched<'txn, T: pristine::DepsTxnT> {
629     txn: &'txn T,
630     iter: pristine::Cursor<
631         T,
632         &'txn T,
633         T::Rev_touched_filesCursor,
634         pristine::ChangeId,
635         pristine::Position<pristine::ChangeId>,
636     >,
637     id: pristine::ChangeId,
638 }
639 
640 impl<
641         'txn,
642         T: pristine::DepsTxnT + pristine::GraphTxnT<GraphError = <T as pristine::DepsTxnT>::DepsError>,
643     > Iterator for Touched<'txn, T>
644 {
645     type Item = Result<pristine::Position<pristine::Hash>, T::DepsError>;
next(&mut self) -> Option<Self::Item>646     fn next(&mut self) -> Option<Self::Item> {
647         while let Some(x) = self.iter.next() {
648             let (cid, file) = match x {
649                 Ok(x) => x,
650                 Err(e) => return Some(Err(e.0)),
651             };
652             if *cid > self.id {
653                 return None;
654             } else if *cid == self.id {
655                 let change = match self.txn.get_external(&file.change) {
656                     Ok(ext) => ext.unwrap(),
657                     Err(e) => return Some(Err(e.0)),
658                 };
659                 return Some(Ok(pristine::Position {
660                     change: change.into(),
661                     pos: file.pos,
662                 }));
663             }
664         }
665         None
666     }
667 }
668 
669 #[doc(hidden)]
670 #[derive(Debug, Default, Clone)]
671 pub struct Timers {
672     pub alive_output: std::time::Duration,
673     pub alive_graph: std::time::Duration,
674     pub alive_retrieve: std::time::Duration,
675     pub alive_contents: std::time::Duration,
676     pub alive_write: std::time::Duration,
677     pub record: std::time::Duration,
678     pub apply: std::time::Duration,
679     pub repair_context: std::time::Duration,
680     pub check_cyclic_paths: std::time::Duration,
681     pub find_alive: std::time::Duration,
682 }
683 use std::sync::Mutex;
684 lazy_static! {
685     pub static ref TIMERS: Mutex<Timers> = Mutex::new(Timers {
686         alive_output: std::time::Duration::from_secs(0),
687         alive_graph: std::time::Duration::from_secs(0),
688         alive_retrieve: std::time::Duration::from_secs(0),
689         alive_contents: std::time::Duration::from_secs(0),
690         alive_write: std::time::Duration::from_secs(0),
691         record: std::time::Duration::from_secs(0),
692         apply: std::time::Duration::from_secs(0),
693         repair_context: std::time::Duration::from_secs(0),
694         check_cyclic_paths: std::time::Duration::from_secs(0),
695         find_alive: std::time::Duration::from_secs(0),
696     });
697 }
698 #[doc(hidden)]
reset_timers()699 pub fn reset_timers() {
700     *TIMERS.lock().unwrap() = Timers::default();
701 }
702 #[doc(hidden)]
get_timers() -> Timers703 pub fn get_timers() -> Timers {
704     TIMERS.lock().unwrap().clone()
705 }
706