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