libpijul_compat/backend/
mod.rs

1use hex;
2use rand;
3use sanakirja;
4use sanakirja::Representable;
5pub use sanakirja::Transaction;
6use std;
7use std::path::Path;
8use {ErrorKind, Result};
9
10pub use self::patch_id::*;
11
12fn from_hex(hex: &str, s: &mut [u8]) -> bool {
13    let hex = hex.as_bytes();
14    if hex.len() <= 2 * s.len() {
15        let mut i = 0;
16        while i < hex.len() {
17            let h = hex[i].to_ascii_lowercase();
18            if h >= b'0' && h <= b'9' {
19                s[i / 2] = s[i / 2] << 4 | (h - b'0')
20            } else if h >= b'a' && h <= b'f' {
21                s[i / 2] = s[i / 2] << 4 | (h - b'a' + 10)
22            } else {
23                return false;
24            }
25            i += 1
26        }
27        if i & 1 == 1 {
28            s[i / 2] = s[i / 2] << 4
29        }
30        true
31    } else {
32        false
33    }
34}
35mod edge;
36mod file_header;
37mod file_id;
38mod hash;
39mod inode;
40mod key;
41mod patch_id;
42mod small_string;
43
44pub use self::edge::*;
45pub use self::file_header::*;
46pub use self::file_id::*;
47pub use self::hash::*;
48pub use self::inode::*;
49pub use self::key::*;
50pub use self::small_string::*;
51
52pub type NodesDb = sanakirja::Db<self::key::Key<PatchId>, self::edge::UnsafeEdge>;
53
54/// The type of patch application numbers.
55pub type ApplyTimestamp = u64;
56
57/// The u64 is the epoch time in seconds when this patch was applied
58/// to the repository.
59type PatchSet = sanakirja::Db<self::patch_id::PatchId, ApplyTimestamp>;
60
61type RevPatchSet = sanakirja::Db<ApplyTimestamp, self::patch_id::PatchId>;
62
63pub struct Dbs {
64    /// A map of the files in the working copy.
65    tree: sanakirja::Db<self::file_id::UnsafeFileId, self::inode::Inode>,
66    /// The reverse of tree.
67    revtree: sanakirja::Db<self::inode::Inode, self::file_id::UnsafeFileId>,
68    /// A map from inodes (in tree) to keys in branches.
69    inodes: sanakirja::Db<self::inode::Inode, self::file_header::FileHeader>,
70    /// The reverse of inodes, minus the header.
71    revinodes: sanakirja::Db<self::key::Key<PatchId>, self::inode::Inode>,
72    /// Text contents of keys.
73    contents: sanakirja::Db<self::key::Key<PatchId>, sanakirja::value::UnsafeValue>,
74    /// A map from external patch hashes to internal ids.
75    internal: sanakirja::Db<self::hash::UnsafeHash, self::patch_id::PatchId>,
76    /// The reverse of internal.
77    external: sanakirja::Db<self::patch_id::PatchId, self::hash::UnsafeHash>,
78    /// A reverse map of patch dependencies, i.e. (k,v) is in this map
79    /// means that v depends on k.
80    revdep: sanakirja::Db<self::patch_id::PatchId, self::patch_id::PatchId>,
81    /// A map from branch names to graphs.
82    branches:
83        sanakirja::Db<self::small_string::UnsafeSmallStr, (NodesDb, PatchSet, RevPatchSet, u64)>,
84    /// A map of edges to patches that remove them.
85    cemetery:
86        sanakirja::Db<(self::key::Key<PatchId>, self::edge::UnsafeEdge), self::patch_id::PatchId>,
87    /// Dependencies
88    dep: sanakirja::Db<self::patch_id::PatchId, self::patch_id::PatchId>,
89    /// Files touched by patches.
90    touched_files: sanakirja::Db<self::key::Key<PatchId>, self::patch_id::PatchId>,
91    /// Partial checkouts: branch -> partial
92    partials: sanakirja::Db<self::small_string::UnsafeSmallStr, self::key::Key<PatchId>>,
93}
94
95/// Common type for both mutable transactions (`MutTxn`) and immutable
96/// transaction (`Txn`). All of `Txn`'s methods are also `MutTxn`'s
97/// methods.
98pub struct GenericTxn<T, R> {
99    #[doc(hidden)]
100    pub txn: T,
101    #[doc(hidden)]
102    pub rng: R,
103    #[doc(hidden)]
104    pub dbs: Dbs,
105}
106
107/// A mutable transaction on a repository.
108pub type MutTxn<'env, R> = GenericTxn<sanakirja::MutTxn<'env, ()>, R>;
109/// An immutable transaction on a repository.
110pub type Txn<'env> = GenericTxn<sanakirja::Txn<'env>, ()>;
111
112/// The default name of a branch, for users who start working before
113/// choosing branch names (or like the default name, "master").
114pub const DEFAULT_BRANCH: &'static str = "master";
115
116/// A repository. All operations on repositories must be done via transactions.
117pub struct Repository {
118    env: sanakirja::Env,
119}
120
121#[derive(Debug, PartialEq, Clone, Copy)]
122pub enum Root {
123    Tree,
124    RevTree,
125    Inodes,
126    RevInodes,
127    Contents,
128    Internal,
129    External,
130    RevDep,
131    Branches,
132    Cemetery,
133    TouchedFiles,
134    Dep,
135    RevTouchedFiles,
136    Partials,
137}
138
139trait OpenDb: Transaction {
140    fn open_db<K: Representable, V: Representable>(
141        &mut self,
142        num: Root,
143    ) -> Result<sanakirja::Db<K, V>> {
144        if let Some(db) = self.root(num as usize) {
145            Ok(db)
146        } else {
147            Err(ErrorKind::NoDb(num).into())
148        }
149    }
150}
151
152impl<'a, T> OpenDb for sanakirja::MutTxn<'a, T> {
153    fn open_db<K: Representable, V: Representable>(
154        &mut self,
155        num: Root,
156    ) -> Result<sanakirja::Db<K, V>> {
157        if let Some(db) = self.root(num as usize) {
158            Ok(db)
159        } else {
160            Ok(self.create_db()?)
161        }
162    }
163}
164impl<'a> OpenDb for sanakirja::Txn<'a> {}
165
166// Repositories need at least 2^5 = 32 pages, each of size 2^12.
167const MIN_REPO_SIZE: u64 = 1 << 17;
168
169impl Repository {
170    #[doc(hidden)]
171    pub fn size(&self) -> u64 {
172        self.env.size()
173    }
174
175    #[doc(hidden)]
176    pub fn repository_size<P: AsRef<Path>>(path: P) -> Result<u64> {
177        let size = sanakirja::Env::file_size(path.as_ref())?;
178        debug!("repository_size = {:?}", size);
179        Ok(size)
180    }
181
182    /// Open a repository, possibly increasing the size of the
183    /// underlying file if `size_increase` is `Some(…)`.
184    pub fn open<P: AsRef<Path>>(path: P, size_increase: Option<u64>) -> Result<Self> {
185        let size = if let Some(size) = size_increase {
186            Repository::repository_size(path.as_ref()).unwrap_or(MIN_REPO_SIZE)
187                + std::cmp::max(size, MIN_REPO_SIZE)
188        } else {
189            if let Ok(len) = Repository::repository_size(path.as_ref()) {
190                std::cmp::max(len, MIN_REPO_SIZE)
191            } else {
192                MIN_REPO_SIZE
193            }
194        };
195        Ok(Repository {
196            env: sanakirja::Env::new(path, size)?,
197        })
198    }
199
200    /// Open a repository, possibly increasing the size of the
201    /// underlying file if `size_increase` is `Some(…)`.
202    pub unsafe fn open_nolock<P: AsRef<Path>>(path: P, size_increase: Option<u64>) -> Result<Self> {
203        let size = if let Some(size) = size_increase {
204            Repository::repository_size(path.as_ref()).unwrap_or(MIN_REPO_SIZE)
205                + std::cmp::max(size, MIN_REPO_SIZE)
206        } else {
207            if let Ok(len) = Repository::repository_size(path.as_ref()) {
208                std::cmp::max(len, MIN_REPO_SIZE)
209            } else {
210                MIN_REPO_SIZE
211            }
212        };
213        debug!("sanakirja::Env::new_nolock");
214        Ok(Repository {
215            env: sanakirja::Env::new_nolock(path, size)?,
216        })
217    }
218
219    /// Close a repository. It is undefined behaviour to use it afterwards.
220    pub unsafe fn close(&mut self) {
221        self.env.close()
222    }
223
224    /// Start an immutable transaction. Immutable transactions can run
225    /// concurrently.
226    pub fn txn_begin(&self) -> Result<Txn> {
227        let mut txn = self.env.txn_begin()?;
228        let dbs = Dbs::new(&mut txn)?;
229        let repo = GenericTxn {
230            txn: txn,
231            rng: (),
232            dbs: dbs,
233        };
234        Ok(repo)
235    }
236
237    /// Start a mutable transaction. Mutable transactions exclude each
238    /// other, but can in principle be run concurrently with immutable
239    /// transactions. In that case, the immutable transaction only
240    /// have access to the state of the repository immediately before
241    /// the mutable transaction started.
242    pub fn mut_txn_begin<R: rand::Rng>(&self, r: R) -> Result<MutTxn<R>> {
243        let mut txn = self.env.mut_txn_begin()?;
244        let dbs = Dbs::new(&mut txn)?;
245        let repo = GenericTxn {
246            txn: txn,
247            rng: r,
248            dbs: dbs,
249        };
250        Ok(repo)
251    }
252}
253
254impl Dbs {
255    fn new<T: OpenDb>(txn: &mut T) -> Result<Self> {
256        let external = txn.open_db(Root::External)?;
257        let branches = txn.open_db(Root::Branches)?;
258        let tree = txn.open_db(Root::Tree)?;
259        let revtree = txn.open_db(Root::RevTree)?;
260        let inodes = txn.open_db(Root::Inodes)?;
261        let revinodes = txn.open_db(Root::RevInodes)?;
262        let internal = txn.open_db(Root::Internal)?;
263        let contents = txn.open_db(Root::Contents)?;
264        let revdep = txn.open_db(Root::RevDep)?;
265        let cemetery = txn.open_db(Root::Cemetery)?;
266        let dep = txn.open_db(Root::Dep)?;
267        let touched_files = txn.open_db(Root::TouchedFiles)?;
268        let partials = txn.open_db(Root::Partials)?;
269
270        Ok(Dbs {
271            external,
272            branches,
273            inodes,
274            tree,
275            revtree,
276            revinodes,
277            internal,
278            revdep,
279            contents,
280            cemetery,
281            dep,
282            touched_files,
283            partials,
284        })
285    }
286}
287
288/// The representation of a branch. The "application number" of a
289/// patch on a branch is the state of the application counter at the
290/// time the patch has been applied to that branch.
291#[derive(Debug)]
292pub struct Branch {
293    /// The table containing the branch graph.
294    pub db: NodesDb,
295    /// The map of all patches applied to that branch, ordered by patch hash.
296    pub patches: PatchSet,
297    /// The map of all patches applied to that branch, ordered by application number.
298    pub revpatches: RevPatchSet,
299    /// The number of patches that have been applied on that branch,
300    /// including patches that are no longer on the branch (i.e. that
301    /// have been unrecorded).
302    pub apply_counter: u64,
303    /// Branch name.
304    pub name: small_string::SmallString,
305}
306
307use sanakirja::Commit;
308/// Branches and commits.
309impl<'env, R: rand::Rng> MutTxn<'env, R> {
310    /// Open a branch by name, creating an empty branch with that name
311    /// if the name doesn't exist.
312    pub fn open_branch<'name>(&mut self, name: &str) -> Result<Branch> {
313        let name = small_string::SmallString::from_str(name);
314        let (branch, patches, revpatches, counter) = if let Some(x) =
315            self.txn
316                .get(&self.dbs.branches, name.as_small_str().to_unsafe(), None)
317        {
318            x
319        } else {
320            (
321                self.txn.create_db()?,
322                self.txn.create_db()?,
323                self.txn.create_db()?,
324                0,
325            )
326        };
327        Ok(Branch {
328            db: branch,
329            patches: patches,
330            revpatches: revpatches,
331            name: name,
332            apply_counter: counter,
333        })
334    }
335
336    /// Commit a branch. This is a extremely important thing to do on
337    /// branches, and it is not done automatically when committing
338    /// transactions.
339    ///
340    /// **I repeat: not calling this method before committing a
341    /// transaction might cause database corruption.**
342    pub fn commit_branch(&mut self, branch: Branch) -> Result<()> {
343        debug!("Commit_branch. This is not too safe.");
344        // Since we are replacing the value, we don't want to
345        // decrement its reference counter (which del would do), hence
346        // the transmute.
347        //
348        // This would normally be wrong. The only reason it works is
349        // because we know that dbs_branches has never been forked
350        // from another database, hence all the reference counts to
351        // its elements are 1 (and therefore represented as "not
352        // referenced" in Sanakirja.
353        let mut dbs_branches: sanakirja::Db<UnsafeSmallStr, (u64, u64, u64, u64)> =
354            unsafe { std::mem::transmute(self.dbs.branches) };
355
356        debug!("Commit_branch, dbs_branches = {:?}", dbs_branches);
357        self.txn.del(
358            &mut self.rng,
359            &mut dbs_branches,
360            branch.name.as_small_str().to_unsafe(),
361            None,
362        )?;
363        debug!("Commit_branch, dbs_branches = {:?}", dbs_branches);
364        self.dbs.branches = unsafe { std::mem::transmute(dbs_branches) };
365        self.txn.put(
366            &mut self.rng,
367            &mut self.dbs.branches,
368            branch.name.as_small_str().to_unsafe(),
369            (
370                branch.db,
371                branch.patches,
372                branch.revpatches,
373                branch.apply_counter,
374            ),
375        )?;
376        debug!("Commit_branch, self.dbs.branches = {:?}", self.dbs.branches);
377        Ok(())
378    }
379
380    /// Rename a branch. The branch still needs to be committed after
381    /// this operation.
382    pub fn rename_branch(&mut self, branch: &mut Branch, new_name: &str) -> Result<()> {
383        debug!("Commit_branch. This is not too safe.");
384        // Since we are replacing the value, we don't want to
385        // decrement its reference counter (which del would do), hence
386        // the transmute.
387        //
388        // Read the note in `commit_branch` to understand why this
389        // works.
390        let name_exists = self.get_branch(new_name).is_some();
391        if name_exists {
392            Err(ErrorKind::BranchNameAlreadyExists(new_name.to_string()).into())
393        } else {
394            let mut dbs_branches: sanakirja::Db<UnsafeSmallStr, (u64, u64, u64, u64)> =
395                unsafe { std::mem::transmute(self.dbs.branches) };
396            self.txn.del(
397                &mut self.rng,
398                &mut dbs_branches,
399                branch.name.as_small_str().to_unsafe(),
400                None,
401            )?;
402            self.dbs.branches = unsafe { std::mem::transmute(dbs_branches) };
403            branch.name.clone_from_str(new_name);
404            Ok(())
405        }
406    }
407
408    /// Commit a transaction. **Be careful to commit all open branches
409    /// before**.
410    pub fn commit(mut self) -> Result<()> {
411        self.txn.set_root(Root::Tree as usize, self.dbs.tree);
412        self.txn.set_root(Root::RevTree as usize, self.dbs.revtree);
413        self.txn.set_root(Root::Inodes as usize, self.dbs.inodes);
414        self.txn
415            .set_root(Root::RevInodes as usize, self.dbs.revinodes);
416        self.txn
417            .set_root(Root::Contents as usize, self.dbs.contents);
418        self.txn
419            .set_root(Root::Internal as usize, self.dbs.internal);
420        self.txn
421            .set_root(Root::External as usize, self.dbs.external);
422        self.txn
423            .set_root(Root::Branches as usize, self.dbs.branches);
424        self.txn.set_root(Root::RevDep as usize, self.dbs.revdep);
425        self.txn
426            .set_root(Root::Cemetery as usize, self.dbs.cemetery);
427        self.txn.set_root(Root::Dep as usize, self.dbs.dep);
428        self.txn
429            .set_root(Root::TouchedFiles as usize, self.dbs.touched_files);
430        self.txn
431            .set_root(Root::Partials as usize, self.dbs.partials);
432
433        self.txn.commit()?;
434        Ok(())
435    }
436}
437
438use sanakirja::value::*;
439use sanakirja::{Cursor, RevCursor};
440pub struct TreeIterator<'a, T: Transaction + 'a>(Cursor<'a, T, UnsafeFileId, Inode>);
441
442impl<'a, T: Transaction + 'a> Iterator for TreeIterator<'a, T> {
443    type Item = (FileId<'a>, Inode);
444    fn next(&mut self) -> Option<Self::Item> {
445        debug!("tree iter");
446        if let Some((k, v)) = self.0.next() {
447            debug!("tree iter: {:?} {:?}", k, v);
448            unsafe { Some((FileId::from_unsafe(k), v)) }
449        } else {
450            None
451        }
452    }
453}
454
455pub struct RevtreeIterator<'a, T: Transaction + 'a>(Cursor<'a, T, Inode, UnsafeFileId>);
456
457impl<'a, T: Transaction + 'a> Iterator for RevtreeIterator<'a, T> {
458    type Item = (Inode, FileId<'a>);
459    fn next(&mut self) -> Option<Self::Item> {
460        if let Some((k, v)) = self.0.next() {
461            unsafe { Some((k, FileId::from_unsafe(v))) }
462        } else {
463            None
464        }
465    }
466}
467
468pub struct NodesIterator<'a, T: Transaction + 'a>(Cursor<'a, T, Key<PatchId>, UnsafeEdge>);
469
470impl<'a, T: Transaction + 'a> Iterator for NodesIterator<'a, T> {
471    type Item = (Key<PatchId>, &'a Edge);
472    fn next(&mut self) -> Option<Self::Item> {
473        if let Some((k, v)) = self.0.next() {
474            unsafe { Some((k, Edge::from_unsafe(v))) }
475        } else {
476            None
477        }
478    }
479}
480pub struct BranchIterator<'a, T: Transaction + 'a>(
481    Cursor<'a, T, UnsafeSmallStr, (NodesDb, PatchSet, RevPatchSet, u64)>,
482);
483
484impl<'a, T: Transaction + 'a> Iterator for BranchIterator<'a, T> {
485    type Item = Branch;
486    fn next(&mut self) -> Option<Self::Item> {
487        if let Some((k, v)) = self.0.next() {
488            unsafe {
489                Some(Branch {
490                    name: SmallStr::from_unsafe(k).to_owned(),
491                    db: v.0,
492                    patches: v.1,
493                    revpatches: v.2,
494                    apply_counter: v.3,
495                })
496            }
497        } else {
498            None
499        }
500    }
501}
502
503pub struct PatchesIterator<'a, T: Transaction + 'a>(Cursor<'a, T, PatchId, ApplyTimestamp>);
504
505impl<'a, T: Transaction + 'a> Iterator for PatchesIterator<'a, T> {
506    type Item = (PatchId, ApplyTimestamp);
507    fn next(&mut self) -> Option<Self::Item> {
508        self.0.next()
509    }
510}
511
512pub struct RevAppliedIterator<'a, T: Transaction + 'a>(RevCursor<'a, T, ApplyTimestamp, PatchId>);
513
514impl<'a, T: Transaction + 'a> Iterator for RevAppliedIterator<'a, T> {
515    type Item = (ApplyTimestamp, PatchId);
516    fn next(&mut self) -> Option<Self::Item> {
517        self.0.next()
518    }
519}
520
521pub struct AppliedIterator<'a, T: Transaction + 'a>(Cursor<'a, T, ApplyTimestamp, PatchId>);
522
523impl<'a, T: Transaction + 'a> Iterator for AppliedIterator<'a, T> {
524    type Item = (ApplyTimestamp, PatchId);
525    fn next(&mut self) -> Option<Self::Item> {
526        self.0.next()
527    }
528}
529
530pub struct InodesIterator<'a, T: Transaction + 'a>(Cursor<'a, T, Inode, FileHeader>);
531
532impl<'a, T: Transaction + 'a> Iterator for InodesIterator<'a, T> {
533    type Item = (Inode, FileHeader);
534    fn next(&mut self) -> Option<Self::Item> {
535        self.0.next()
536    }
537}
538
539pub struct InternalIterator<'a, T: Transaction + 'a>(Cursor<'a, T, UnsafeHash, PatchId>);
540
541impl<'a, T: Transaction + 'a> Iterator for InternalIterator<'a, T> {
542    type Item = (HashRef<'a>, PatchId);
543    fn next(&mut self) -> Option<Self::Item> {
544        if let Some((k, v)) = self.0.next() {
545            unsafe { Some((HashRef::from_unsafe(k), v)) }
546        } else {
547            None
548        }
549    }
550}
551pub struct ExternalIterator<'a, T: Transaction + 'a>(Cursor<'a, T, PatchId, UnsafeHash>);
552
553impl<'a, T: Transaction + 'a> Iterator for ExternalIterator<'a, T> {
554    type Item = (PatchId, HashRef<'a>);
555    fn next(&mut self) -> Option<Self::Item> {
556        if let Some((k, v)) = self.0.next() {
557            unsafe { Some((k, HashRef::from_unsafe(v))) }
558        } else {
559            None
560        }
561    }
562}
563
564pub struct RevdepIterator<'a, T: Transaction + 'a>(Cursor<'a, T, PatchId, PatchId>);
565
566impl<'a, T: Transaction + 'a> Iterator for RevdepIterator<'a, T> {
567    type Item = (PatchId, PatchId);
568    fn next(&mut self) -> Option<Self::Item> {
569        self.0.next()
570    }
571}
572
573pub struct DepIterator<'a, T: Transaction + 'a>(Cursor<'a, T, PatchId, PatchId>);
574
575impl<'a, T: Transaction + 'a> Iterator for DepIterator<'a, T> {
576    type Item = (PatchId, PatchId);
577    fn next(&mut self) -> Option<Self::Item> {
578        self.0.next()
579    }
580}
581
582pub struct ContentsIterator<'a, T: Transaction + 'a>(
583    &'a T,
584    Cursor<'a, T, Key<PatchId>, UnsafeValue>,
585);
586
587impl<'a, T: Transaction + 'a> Iterator for ContentsIterator<'a, T> {
588    type Item = (Key<PatchId>, Value<'a, T>);
589    fn next(&mut self) -> Option<Self::Item> {
590        if let Some((k, v)) = self.1.next() {
591            unsafe { Some((k, Value::from_unsafe(&v, self.0))) }
592        } else {
593            None
594        }
595    }
596}
597
598pub struct CemeteryIterator<'a, T: Transaction + 'a>(
599    Cursor<'a, T, (Key<PatchId>, UnsafeEdge), PatchId>,
600);
601
602impl<'a, T: Transaction + 'a> Iterator for CemeteryIterator<'a, T> {
603    type Item = ((Key<PatchId>, &'a Edge), PatchId);
604    fn next(&mut self) -> Option<Self::Item> {
605        if let Some(((k, v), w)) = self.0.next() {
606            unsafe { Some(((k, Edge::from_unsafe(v)), w)) }
607        } else {
608            None
609        }
610    }
611}
612
613pub struct TouchedIterator<'a, T: Transaction + 'a>(Cursor<'a, T, Key<PatchId>, PatchId>);
614
615impl<'a, T: Transaction + 'a> Iterator for TouchedIterator<'a, T> {
616    type Item = (Key<PatchId>, PatchId);
617    fn next(&mut self) -> Option<Self::Item> {
618        if let Some((k, v)) = self.0.next() {
619            Some((k, v))
620        } else {
621            None
622        }
623    }
624}
625
626pub struct PartialsIterator<'a, T: Transaction + 'a>(Cursor<'a, T, UnsafeSmallStr, Key<PatchId>>);
627
628impl<'a, T: Transaction + 'a> Iterator for PartialsIterator<'a, T> {
629    type Item = (SmallStr<'a>, Key<PatchId>);
630    fn next(&mut self) -> Option<Self::Item> {
631        if let Some((k, v)) = self.0.next() {
632            unsafe { Some((SmallStr::from_unsafe(k), v)) }
633        } else {
634            None
635        }
636    }
637}
638
639mod dump {
640    use super::*;
641    use sanakirja;
642
643    impl<U: Transaction, R> GenericTxn<U, R> {
644        pub fn dump(&self) {
645            debug!("============= dumping Tree");
646            for (k, v) in self.iter_tree(None) {
647                debug!("> {:?} {:?}", k, v)
648            }
649            debug!("============= dumping Inodes");
650            for (k, v) in self.iter_inodes(None) {
651                debug!("> {:?} {:?}", k, v)
652            }
653            debug!("============= dumping RevDep");
654            for (k, v) in self.iter_revdep(None) {
655                debug!("> {:?} {:?}", k, v)
656            }
657            debug!("============= dumping Internal");
658            for (k, v) in self.iter_internal(None) {
659                debug!("> {:?} {:?}", k, v)
660            }
661            debug!("============= dumping External");
662            for (k, v) in self.iter_external(None) {
663                debug!("> {:?} {:?} {:?}", k, v, v.to_base58());
664            }
665            debug!("============= dumping Contents");
666            {
667                sanakirja::debug(&self.txn, &[&self.dbs.contents], "dump_contents");
668            }
669            debug!("============= dumping Partials");
670            for (k, v) in self.iter_partials("") {
671                debug!("> {:?} {:?}", k, v);
672            }
673            debug!("============= dumping Branches");
674            for (br, (db, patches, revpatches, counter)) in self.txn.iter(&self.dbs.branches, None)
675            {
676                debug!("patches: {:?} {:?}", patches, revpatches);
677                debug!(
678                    "============= dumping Patches in branch {:?}, counter = {:?}",
679                    br, counter
680                );
681                for (k, v) in self.txn.iter(&patches, None) {
682                    debug!("> {:?} {:?}", k, v)
683                }
684                debug!("============= dumping RevPatches in branch {:?}", br);
685                for (k, v) in self.txn.iter(&revpatches, None) {
686                    debug!("> {:?} {:?}", k, v)
687                }
688                debug!("============= dumping Nodes in branch {:?}", br);
689                unsafe {
690                    // sanakirja::debug(&self.txn, &[&db], path);
691                    debug!("> {:?}", SmallStr::from_unsafe(br));
692                    for (k, v) in self.txn.iter(&db, None) {
693                        debug!(">> {:?} {:?}", k, Edge::from_unsafe(v))
694                    }
695                }
696            }
697        }
698    }
699}
700
701pub struct ParentsIterator<'a, U: Transaction + 'a> {
702    it: NodesIterator<'a, U>,
703    key: Key<PatchId>,
704    flag: EdgeFlags,
705}
706
707impl<'a, U: Transaction + 'a> Iterator for ParentsIterator<'a, U> {
708    type Item = &'a Edge;
709    fn next(&mut self) -> Option<Self::Item> {
710        if let Some((v, e)) = self.it.next() {
711            if v == self.key && e.flag <= self.flag {
712                Some(e)
713            } else {
714                None
715            }
716        } else {
717            None
718        }
719    }
720}
721/*
722macro_rules! iterate_parents {
723    ($txn:expr, $branch:expr, $key:expr, $flag: expr) => { {
724        let edge = Edge::zero($flag|PARENT_EDGE);
725        $txn.iter_nodes(& $branch, Some(($key, Some(&edge))))
726            .take_while(|&(k, parent)| {
727                *k == *$key && parent.flag <= $flag|PARENT_EDGE|PSEUDO_EDGE
728            })
729            .map(|(_,b)| b)
730    } }
731}
732*/
733
734impl<U: Transaction, R> GenericTxn<U, R> {
735    /// Does this repository has a branch called `name`?
736    pub fn has_branch(&self, name: &str) -> bool {
737        let name = small_string::SmallString::from_str(name);
738        self.txn
739            .get(&self.dbs.branches, name.as_small_str().to_unsafe(), None)
740            .is_some()
741    }
742
743    /// Get the branch with the given name, if it exists.
744    pub fn get_branch<'name>(&self, name: &str) -> Option<Branch> {
745        let name = small_string::SmallString::from_str(name);
746        if let Some((branch, patches, revpatches, counter)) =
747            self.txn
748                .get(&self.dbs.branches, name.as_small_str().to_unsafe(), None)
749        {
750            Some(Branch {
751                db: branch,
752                patches: patches,
753                revpatches: revpatches,
754                apply_counter: counter,
755                name: name,
756            })
757        } else {
758            None
759        }
760    }
761
762    /// Return the first edge of this `key` if `edge` is `None`, and
763    /// a pointer to the edge in the database if `edge` is `Some`.
764    pub fn get_nodes<'a>(
765        &'a self,
766        branch: &Branch,
767        key: Key<PatchId>,
768        edge: Option<&Edge>,
769    ) -> Option<&'a Edge> {
770        self.txn
771            .get(&branch.db, key, edge.map(|e| e.to_unsafe()))
772            .map(|e| unsafe { Edge::from_unsafe(e) })
773    }
774
775    /// An iterator over keys and edges, in branch `branch`, starting
776    /// from key and edge specified by `key`. If `key` is `None`, the
777    /// iterations start from the first key and first edge. If `key`
778    /// is of the form `Some(a, None)`, they start from the first edge
779    /// of key `a`. If `key` is of the from `Some(a, Some(b))`, they
780    /// start from the first key and edge that is at least `(a, b)`.
781    pub fn iter_nodes<'a>(
782        &'a self,
783        branch: &'a Branch,
784        key: Option<(Key<PatchId>, Option<&Edge>)>,
785    ) -> NodesIterator<'a, U> {
786        NodesIterator(
787            self.txn
788                .iter(&branch.db, key.map(|(k, v)| (k, v.map(|v| v.to_unsafe())))),
789        )
790    }
791
792    pub fn iter_parents<'a>(
793        &'a self,
794        branch: &'a Branch,
795        key: Key<PatchId>,
796        flag: EdgeFlags,
797    ) -> ParentsIterator<'a, U> {
798        let edge = Edge::zero(flag | EdgeFlags::PARENT_EDGE);
799        ParentsIterator {
800            it: self.iter_nodes(branch, Some((key, Some(&edge)))),
801            key,
802            flag: flag | EdgeFlags::PARENT_EDGE | EdgeFlags::PSEUDO_EDGE,
803        }
804    }
805
806    /// An iterator over branches in the database, starting from the
807    /// given branch name.
808    pub fn iter_branches<'a>(&'a self, key: Option<&SmallStr>) -> BranchIterator<'a, U> {
809        BranchIterator(
810            self.txn
811                .iter(&self.dbs.branches, key.map(|k| (k.to_unsafe(), None))),
812        )
813    }
814
815    /// An iterator over branches in the database, starting from the
816    /// given branch name.
817    pub fn iter_partials<'a>(&'a self, branch: &str) -> PartialsIterator<'a, U> {
818        let key = SmallString::from_str(branch);
819        PartialsIterator(self.txn.iter(
820            &self.dbs.partials,
821            Some((key.as_small_str().to_unsafe(), None)),
822        ))
823    }
824
825    /// An iterator over patches in a branch, in the alphabetical
826    /// order of their hash.
827    pub fn iter_patches<'a>(
828        &'a self,
829        branch: &'a Branch,
830        key: Option<PatchId>,
831    ) -> PatchesIterator<'a, U> {
832        PatchesIterator(self.txn.iter(&branch.patches, key.map(|k| (k, None))))
833    }
834
835    /// An iterator over patches in a branch, in the reverse order in
836    /// which they were applied.
837    pub fn rev_iter_applied<'a>(
838        &'a self,
839        branch: &'a Branch,
840        key: Option<ApplyTimestamp>,
841    ) -> RevAppliedIterator<'a, U> {
842        RevAppliedIterator(
843            self.txn
844                .rev_iter(&branch.revpatches, key.map(|k| (k, None))),
845        )
846    }
847
848    /// An iterator over patches in a branch in the order in which
849    /// they were applied.
850    pub fn iter_applied<'a>(
851        &'a self,
852        branch: &'a Branch,
853        key: Option<ApplyTimestamp>,
854    ) -> AppliedIterator<'a, U> {
855        AppliedIterator(self.txn.iter(&branch.revpatches, key.map(|k| (k, None))))
856    }
857
858    /// An iterator over files and directories currently tracked by
859    /// Pijul, starting from the given `FileId`. The `Inode`s returned
860    /// by the iterator can be used to form new `FileId`s and traverse
861    /// the tree from top to bottom.
862    ///
863    /// The set of tracked files is changed by the following
864    /// operations: outputting the repository, adding, deleting and
865    /// moving files. It is not related to branches, but only to the
866    /// files actually present on the file system.
867    pub fn iter_tree<'a>(&'a self, key: Option<(&FileId, Option<Inode>)>) -> TreeIterator<'a, U> {
868        debug!("iter_tree: {:?}", key);
869        TreeIterator(
870            self.txn
871                .iter(&self.dbs.tree, key.map(|(k, v)| (k.to_unsafe(), v))),
872        )
873    }
874
875    /// An iterator over files and directories, following directories
876    /// in the opposite direction.
877    pub fn iter_revtree<'a>(
878        &'a self,
879        key: Option<(Inode, Option<&FileId>)>,
880    ) -> RevtreeIterator<'a, U> {
881        RevtreeIterator(self.txn.iter(
882            &self.dbs.revtree,
883            key.map(|(k, v)| (k, v.map(|v| v.to_unsafe()))),
884        ))
885    }
886
887    /// An iterator over the "inodes" database, which contains
888    /// correspondences between files on the filesystem and the files
889    /// in the graph.
890    pub fn iter_inodes<'a>(
891        &'a self,
892        key: Option<(Inode, Option<FileHeader>)>,
893    ) -> InodesIterator<'a, U> {
894        InodesIterator(self.txn.iter(&self.dbs.inodes, key))
895    }
896
897    /// Iterator over the `PatchId` to `Hash` correspondence.
898    pub fn iter_external<'a>(
899        &'a self,
900        key: Option<(PatchId, Option<HashRef>)>,
901    ) -> ExternalIterator<'a, U> {
902        ExternalIterator(self.txn.iter(
903            &self.dbs.external,
904            key.map(|(k, v)| (k, v.map(|v| v.to_unsafe()))),
905        ))
906    }
907
908    /// Iterator over the `Hash` to `PatchId` correspondence.
909    pub fn iter_internal<'a>(
910        &'a self,
911        key: Option<(HashRef, Option<PatchId>)>,
912    ) -> InternalIterator<'a, U> {
913        InternalIterator(
914            self.txn
915                .iter(&self.dbs.internal, key.map(|(k, v)| (k.to_unsafe(), v))),
916        )
917    }
918
919    /// Iterator over reverse dependencies (`(k, v)` is in the reverse
920    /// dependency table if `v` depends on `k`, and both are in at
921    /// least one branch).
922    pub fn iter_revdep<'a>(
923        &'a self,
924        key: Option<(PatchId, Option<PatchId>)>,
925    ) -> RevdepIterator<'a, U> {
926        RevdepIterator(self.txn.iter(&self.dbs.revdep, key))
927    }
928
929    /// Iterator over dependencies.
930    pub fn iter_dep<'a>(&'a self, key: Option<(PatchId, Option<PatchId>)>) -> DepIterator<'a, U> {
931        DepIterator(self.txn.iter(&self.dbs.dep, key))
932    }
933
934    /// An iterator over line contents (common to all branches).
935    pub fn iter_contents<'a>(&'a self, key: Option<Key<PatchId>>) -> ContentsIterator<'a, U> {
936        ContentsIterator(
937            &self.txn,
938            self.txn.iter(&self.dbs.contents, key.map(|k| (k, None))),
939        )
940    }
941
942    /// An iterator over edges in the cemetery.
943    pub fn iter_cemetery<'a>(&'a self, key: Key<PatchId>, edge: Edge) -> CemeteryIterator<'a, U> {
944        CemeteryIterator(
945            self.txn
946                .iter(&self.dbs.cemetery, Some(((key, edge.to_unsafe()), None))),
947        )
948    }
949
950    /// An iterator over patches that touch a certain file.
951    pub fn iter_touched<'a>(&'a self, key: Key<PatchId>) -> TouchedIterator<'a, U> {
952        TouchedIterator(self.txn.iter(&self.dbs.touched_files, Some((key, None))))
953    }
954
955    /// Tell whether a patch touches a file
956    pub fn get_touched<'a>(&'a self, key: Key<PatchId>, patch: PatchId) -> bool {
957        self.txn
958            .get(&self.dbs.touched_files, key, Some(patch))
959            .is_some()
960    }
961
962    /// Get the `Inode` of a give `FileId`. A `FileId` is itself
963    /// composed of an inode and a name, hence this can be used to
964    /// traverse the tree of tracked files from top to bottom.
965    pub fn get_tree<'a>(&'a self, key: &FileId) -> Option<Inode> {
966        self.txn.get(&self.dbs.tree, key.to_unsafe(), None)
967    }
968
969    /// Get the parent `FileId` of a given `Inode`. A `FileId` is
970    /// itself composed of an `Inode` and a name, so this can be used
971    /// to traverse the tree of tracked files from bottom to top
972    /// (starting from a leaf).
973    pub fn get_revtree<'a>(&'a self, key: Inode) -> Option<FileId<'a>> {
974        self.txn
975            .get(&self.dbs.revtree, key, None)
976            .map(|e| unsafe { FileId::from_unsafe(e) })
977    }
978
979    /// Get the key in branches for the given `Inode`, as well as
980    /// meta-information on the file (permissions, and whether it has
981    /// been moved or deleted compared to the branch).
982    ///
983    /// This table is updated every time the repository is output, and
984    /// when files are moved or deleted. It is meant to be
985    /// synchronised with the current branch (if any).
986    pub fn get_inodes<'a>(&'a self, key: Inode) -> Option<FileHeader> {
987        self.txn.get(&self.dbs.inodes, key, None)
988    }
989
990    /// Get the `Inode` corresponding to `key` in branches (see the
991    /// documentation for `get_inodes`).
992    pub fn get_revinodes(&self, key: Key<PatchId>) -> Option<Inode> {
993        self.txn.get(&self.dbs.revinodes, key, None)
994    }
995
996    /// Get the contents of a line.
997    pub fn get_contents<'a>(&'a self, key: Key<PatchId>) -> Option<Value<'a, U>> {
998        if let Some(e) = self.txn.get(&self.dbs.contents, key, None) {
999            unsafe { Some(Value::from_unsafe(&e, &self.txn)) }
1000        } else {
1001            None
1002        }
1003    }
1004
1005    /// Get the `PatchId` (or internal patch identifier) of the
1006    /// provided patch hash.
1007    pub fn get_internal(&self, key: HashRef) -> Option<PatchId> {
1008        match key {
1009            HashRef::None => Some(ROOT_PATCH_ID),
1010            h => self.txn.get(&self.dbs.internal, h.to_unsafe(), None),
1011        }
1012    }
1013
1014    /// Get the `HashRef` (external patch identifier) of the provided
1015    /// internal patch identifier.
1016    pub fn get_external<'a>(&'a self, key: PatchId) -> Option<HashRef<'a>> {
1017        self.txn
1018            .get(&self.dbs.external, key, None)
1019            .map(|e| unsafe { HashRef::from_unsafe(e) })
1020    }
1021
1022    /// Get the patch number in the branch. Patch numbers are
1023    /// guaranteed to always increase when a new patch is applied, but
1024    /// are not necessarily consecutive.
1025    pub fn get_patch(&self, patch_set: &PatchSet, patchid: PatchId) -> Option<ApplyTimestamp> {
1026        self.txn.get(patch_set, patchid, None)
1027    }
1028
1029    /// Get the smallest patch id that depends on `patch` (and is at
1030    /// least `dep` in alphabetical order if `dep`, is `Some`).
1031    pub fn get_revdep(&self, patch: PatchId, dep: Option<PatchId>) -> Option<PatchId> {
1032        self.txn.get(&self.dbs.revdep, patch, dep)
1033    }
1034
1035    /// Get the smallest patch id that `patch` depends on (and is at
1036    /// least `dep` in alphabetical order if `dep`, is `Some`).
1037    pub fn get_dep(&self, patch: PatchId, dep: Option<PatchId>) -> Option<PatchId> {
1038        self.txn.get(&self.dbs.dep, patch, dep)
1039    }
1040
1041    /// Dump the graph of a branch into a writer, in dot format.
1042    pub fn debug<W>(&self, branch_name: &str, w: &mut W, exclude_parents: bool)
1043    where
1044        W: std::io::Write,
1045    {
1046        debug!("debugging branch {:?}", branch_name);
1047        let mut styles = Vec::with_capacity(16);
1048        for i in 0..32 {
1049            let flag = EdgeFlags::from_bits(i as u8).unwrap();
1050            styles.push(
1051                ("color=").to_string() + ["red", "blue", "orange", "green", "black"][(i >> 1) & 3]
1052                    + if flag.contains(EdgeFlags::DELETED_EDGE) {
1053                        ", style=dashed"
1054                    } else {
1055                        ""
1056                    } + if flag.contains(EdgeFlags::PSEUDO_EDGE) {
1057                    ", style=dotted"
1058                } else {
1059                    ""
1060                },
1061            )
1062        }
1063        w.write(b"digraph{\n").unwrap();
1064        let branch = self.get_branch(branch_name).unwrap();
1065
1066        let mut cur: Key<PatchId> = ROOT_KEY.clone();
1067        for (k, v) in self.iter_nodes(&branch, None) {
1068            if k != cur {
1069                let cont = if let Some(cont) = self.get_contents(k) {
1070                    let cont = cont.into_cow();
1071                    let cont = &cont[..std::cmp::min(50, cont.len())];
1072                    format!(
1073                        "{:?}",
1074                        match std::str::from_utf8(cont) {
1075                            Ok(x) => x.to_string(),
1076                            Err(_) => hex::encode(cont),
1077                        }
1078                    )
1079                } else {
1080                    "\"\"".to_string()
1081                };
1082                // remove the leading and trailing '"'.
1083                let cont = &cont[1..(cont.len() - 1)];
1084                write!(
1085                    w,
1086                    "n_{}[label=\"{}.{}: {}\"];\n",
1087                    k.to_hex(),
1088                    k.patch.to_base58(),
1089                    k.line.to_hex(),
1090                    cont.replace("\n", "")
1091                ).unwrap();
1092                cur = k.clone();
1093            }
1094            debug!("debug: {:?}", v);
1095            let flag = v.flag.bits();
1096            if !(exclude_parents && v.flag.contains(EdgeFlags::PARENT_EDGE)) {
1097                write!(
1098                    w,
1099                    "n_{}->n_{}[{},label=\"{} {}\"];\n",
1100                    k.to_hex(),
1101                    &v.dest.to_hex(),
1102                    styles[(flag & 0xff) as usize],
1103                    flag,
1104                    v.introduced_by.to_base58()
1105                ).unwrap();
1106            }
1107        }
1108        w.write(b"}\n").unwrap();
1109    }
1110
1111    /// Dump the graph of a branch into a writer, in dot format.
1112    pub fn debug_folders<W>(&self, branch_name: &str, w: &mut W)
1113    where
1114        W: std::io::Write,
1115    {
1116        debug!("debugging branch {:?}", branch_name);
1117        let mut styles = Vec::with_capacity(16);
1118        for i in 0..32 {
1119            let flag = EdgeFlags::from_bits(i as u8).unwrap();
1120            styles.push(
1121                ("color=").to_string() + ["red", "blue", "orange", "green", "black"][(i >> 1) & 3]
1122                    + if flag.contains(EdgeFlags::DELETED_EDGE) {
1123                        ", style=dashed"
1124                    } else {
1125                        ""
1126                    } + if flag.contains(EdgeFlags::PSEUDO_EDGE) {
1127                    ", style=dotted"
1128                } else {
1129                    ""
1130                },
1131            )
1132        }
1133        w.write(b"digraph{\n").unwrap();
1134        let branch = self.get_branch(branch_name).unwrap();
1135
1136        let mut nodes = vec![ROOT_KEY];
1137        while let Some(k) = nodes.pop() {
1138            let cont = if let Some(cont) = self.get_contents(k) {
1139                let cont = cont.into_cow();
1140                let cont = &cont[..std::cmp::min(50, cont.len())];
1141                if cont.len() > 2 {
1142                    let (a, b) = cont.split_at(2);
1143                    let cont = format!("{:?}", std::str::from_utf8(b).unwrap());
1144                    let cont = &cont[1..(cont.len() - 1)];
1145                    format!("{} {}", hex::encode(a), cont)
1146                } else {
1147                    format!("{}", hex::encode(cont))
1148                }
1149            } else {
1150                "".to_string()
1151            };
1152            // remove the leading and trailing '"'.
1153            write!(
1154                w,
1155                "n_{}[label=\"{}.{}: {}\"];\n",
1156                k.to_hex(),
1157                k.patch.to_base58(),
1158                k.line.to_hex(),
1159                cont.replace("\n", "")
1160            ).unwrap();
1161
1162            for (_, child) in self.iter_nodes(&branch, Some((k, None)))
1163                .take_while(|&(k_, v_)| {
1164                    debug!(target:"debug", "{:?} {:?}", k_, v_);
1165                    k_ == k
1166                }) {
1167                let flag = child.flag.bits();
1168                write!(
1169                    w,
1170                    "n_{}->n_{}[{},label=\"{} {}\"];\n",
1171                    k.to_hex(),
1172                    &child.dest.to_hex(),
1173                    styles[(flag & 0xff) as usize],
1174                    flag,
1175                    child.introduced_by.to_base58()
1176                ).unwrap();
1177                if child.flag.contains(EdgeFlags::FOLDER_EDGE)
1178                    && !child.flag.contains(EdgeFlags::PARENT_EDGE)
1179                {
1180                    nodes.push(child.dest)
1181                }
1182            }
1183        }
1184        w.write(b"}\n").unwrap();
1185    }
1186
1187    /// Is there an alive/pseudo edge from `a` to `b`.
1188    pub fn is_connected(&self, branch: &Branch, a: Key<PatchId>, b: Key<PatchId>) -> bool {
1189        self.test_edge(
1190            branch,
1191            a,
1192            b,
1193            EdgeFlags::empty(),
1194            EdgeFlags::PSEUDO_EDGE | EdgeFlags::FOLDER_EDGE,
1195        )
1196    }
1197
1198    /// Is there an alive/pseudo edge from `a` to `b`.
1199    pub fn test_edge(
1200        &self,
1201        branch: &Branch,
1202        a: Key<PatchId>,
1203        b: Key<PatchId>,
1204        min: EdgeFlags,
1205        max: EdgeFlags,
1206    ) -> bool {
1207        debug!("is_connected {:?} {:?}", a, b);
1208        let mut edge = Edge::zero(min);
1209        edge.dest = b;
1210        self.iter_nodes(&branch, Some((a, Some(&edge))))
1211            .take_while(|&(k, v)| k == a && v.dest == b && v.flag <= max)
1212            .next()
1213            .is_some()
1214    }
1215}
1216
1217/// Low-level operations on mutable transactions.
1218impl<'env, R: rand::Rng> MutTxn<'env, R> {
1219    /// Delete a branch, destroying its associated graph and patch set.
1220    pub fn drop_branch(&mut self, branch: &str) -> Result<bool> {
1221        let name = SmallString::from_str(branch);
1222        Ok(self.txn.del(
1223            &mut self.rng,
1224            &mut self.dbs.branches,
1225            name.as_small_str().to_unsafe(),
1226            None,
1227        )?)
1228    }
1229
1230    /// Add a binding to the graph of a branch. All edges must be
1231    /// inserted twice, once in each direction, and this method only
1232    /// inserts one direction.
1233    pub fn put_nodes(
1234        &mut self,
1235        branch: &mut Branch,
1236        key: Key<PatchId>,
1237        edge: &Edge,
1238    ) -> Result<bool> {
1239        debug!("put_nodes: {:?} {:?}", key, edge);
1240        Ok(self.txn
1241            .put(&mut self.rng, &mut branch.db, key, edge.to_unsafe())?)
1242    }
1243
1244    /// Same as `put_nodes`, but also adds the reverse edge.
1245    pub fn put_nodes_with_rev(
1246        &mut self,
1247        branch: &mut Branch,
1248        mut key: Key<PatchId>,
1249        mut edge: Edge,
1250    ) -> Result<bool> {
1251        self.put_nodes(branch, key, &edge)?;
1252        std::mem::swap(&mut key, &mut edge.dest);
1253        edge.flag.toggle(EdgeFlags::PARENT_EDGE);
1254        self.put_nodes(branch, key, &edge)
1255    }
1256
1257    /// Delete a binding from a graph. If `edge` is `None`, delete the
1258    /// smallest binding with key at least `key`.
1259    pub fn del_nodes(
1260        &mut self,
1261        branch: &mut Branch,
1262        key: Key<PatchId>,
1263        edge: Option<&Edge>,
1264    ) -> Result<bool> {
1265        Ok(self.txn.del(
1266            &mut self.rng,
1267            &mut branch.db,
1268            key,
1269            edge.map(|e| e.to_unsafe()),
1270        )?)
1271    }
1272
1273    /// Same as `del_nodes`, but also deletes the reverse edge.
1274    pub fn del_nodes_with_rev(
1275        &mut self,
1276        branch: &mut Branch,
1277        mut key: Key<PatchId>,
1278        mut edge: Edge,
1279    ) -> Result<bool> {
1280        self.del_nodes(branch, key, Some(&edge))?;
1281        std::mem::swap(&mut key, &mut edge.dest);
1282        edge.flag.toggle(EdgeFlags::PARENT_EDGE);
1283        self.del_nodes(branch, key, Some(&edge))
1284    }
1285
1286    /// Add a file or directory into the tree database, with parent
1287    /// `key.parent_inode`, name `key.basename` and inode `Inode`
1288    /// (usually randomly generated, as `Inode`s have no relation
1289    /// with patches or branches).
1290    ///
1291    /// All bindings inserted here must have the reverse inserted into
1292    /// the revtree database. If `(key, edge)` is inserted here, then
1293    /// `(edge, key)` must be inserted into revtree.
1294    pub fn put_tree(&mut self, key: &FileId, edge: Inode) -> Result<bool> {
1295        Ok(self.txn
1296            .put(&mut self.rng, &mut self.dbs.tree, key.to_unsafe(), edge)?)
1297    }
1298
1299    /// Delete a file or directory from the tree database. Similarly
1300    /// to the comments in the documentation of the `put_tree` method,
1301    /// the reverse binding must be delete from the revtree database.
1302    pub fn del_tree(&mut self, key: &FileId, edge: Option<Inode>) -> Result<bool> {
1303        Ok(self.txn
1304            .del(&mut self.rng, &mut self.dbs.tree, key.to_unsafe(), edge)?)
1305    }
1306
1307    /// Add a file into the revtree database (see the documentation of
1308    /// the `put_tree` method).
1309    pub fn put_revtree(&mut self, key: Inode, value: &FileId) -> Result<bool> {
1310        Ok(self.txn
1311            .put(&mut self.rng, &mut self.dbs.revtree, key, value.to_unsafe())?)
1312    }
1313
1314    /// Delete a file from the revtree database (see the documentation
1315    /// of the `put_tree` method).
1316    pub fn del_revtree(&mut self, key: Inode, value: Option<&FileId>) -> Result<bool> {
1317        Ok(self.txn.del(
1318            &mut self.rng,
1319            &mut self.dbs.revtree,
1320            key,
1321            value.map(|e| e.to_unsafe()),
1322        )?)
1323    }
1324
1325    /// Delete a binding from the `inodes` database, i.e. the
1326    /// correspondence between branch graphs and the file tree.
1327    ///
1328    /// All bindings in inodes must have their reverse in revinodes
1329    /// (without the `FileMetadata`). `del_revinodes` must be called
1330    /// immediately before or immediately after calling this method.
1331    pub fn del_inodes(&mut self, key: Inode, value: Option<FileHeader>) -> Result<bool> {
1332        Ok(self.txn
1333            .del(&mut self.rng, &mut self.dbs.inodes, key, value)?)
1334    }
1335
1336    /// Replace a binding in the inodes database, or insert a new
1337    /// one if `key` doesn't exist yet in that database.
1338    ///
1339    /// All bindings in inodes must have their reverse inserted in
1340    /// revinodes (without the `FileMetadata`).
1341    pub fn replace_inodes(&mut self, key: Inode, value: FileHeader) -> Result<bool> {
1342        self.txn
1343            .del(&mut self.rng, &mut self.dbs.inodes, key, None)?;
1344        Ok(self.txn
1345            .put(&mut self.rng, &mut self.dbs.inodes, key, value)?)
1346    }
1347
1348    /// Replace a binding in the revinodes database, or insert a new
1349    /// one if `key` doesnt exist yet in that database.
1350    ///
1351    /// All bindings in revinodes must have their reverse inserted
1352    /// inodes (with an extra `FileMetadata`).
1353    pub fn replace_revinodes(&mut self, key: Key<PatchId>, value: Inode) -> Result<bool> {
1354        self.txn
1355            .del(&mut self.rng, &mut self.dbs.revinodes, key, None)?;
1356        Ok(self.txn
1357            .put(&mut self.rng, &mut self.dbs.revinodes, key, value)?)
1358    }
1359
1360    /// Delete a binding from the `revinodes` database, i.e. the
1361    /// correspondence between the file tree and branch graphs.
1362    ///
1363    /// All bindings in revinodes must have their reverse in inodes
1364    /// (with an extra `FileMetadata`). `del_inodes` must be called
1365    /// immediately before or immediately after calling this method.
1366    pub fn del_revinodes(&mut self, key: Key<PatchId>, value: Option<Inode>) -> Result<bool> {
1367        Ok(self.txn
1368            .del(&mut self.rng, &mut self.dbs.revinodes, key, value)?)
1369    }
1370
1371    /// Add the contents of a line. Note that this table is common to
1372    /// all branches.
1373    pub fn put_contents(&mut self, key: Key<PatchId>, value: UnsafeValue) -> Result<bool> {
1374        Ok(self.txn
1375            .put(&mut self.rng, &mut self.dbs.contents, key, value)?)
1376    }
1377
1378    /// Remove the contents of a line.
1379    pub fn del_contents(&mut self, key: Key<PatchId>, value: Option<UnsafeValue>) -> Result<bool> {
1380        Ok(self.txn
1381            .del(&mut self.rng, &mut self.dbs.contents, key, value)?)
1382    }
1383
1384    /// Register the internal identifier of a patch. The
1385    /// `put_external` method must be called immediately after, or
1386    /// immediately before this method.
1387    pub fn put_internal(&mut self, key: HashRef, value: PatchId) -> Result<bool> {
1388        Ok(self.txn.put(
1389            &mut self.rng,
1390            &mut self.dbs.internal,
1391            key.to_unsafe(),
1392            value,
1393        )?)
1394    }
1395
1396    /// Unregister the internal identifier of a patch. Remember to
1397    /// also unregister its external id.
1398    pub fn del_internal(&mut self, key: HashRef) -> Result<bool> {
1399        Ok(self.txn
1400            .del(&mut self.rng, &mut self.dbs.internal, key.to_unsafe(), None)?)
1401    }
1402
1403    /// Register the extern identifier of a patch. The `put_internal`
1404    /// method must be called immediately after, or immediately before
1405    /// this method.
1406    pub fn put_external(&mut self, key: PatchId, value: HashRef) -> Result<bool> {
1407        Ok(self.txn.put(
1408            &mut self.rng,
1409            &mut self.dbs.external,
1410            key,
1411            value.to_unsafe(),
1412        )?)
1413    }
1414
1415    /// Unregister the extern identifier of a patch. Remember to also
1416    /// unregister its internal id.
1417    pub fn del_external(&mut self, key: PatchId) -> Result<bool> {
1418        Ok(self.txn
1419            .del(&mut self.rng, &mut self.dbs.external, key, None)?)
1420    }
1421
1422    /// Add a patch id to a branch. This doesn't apply the patch, it
1423    /// only registers it as applied. The `put_revpatches` method must be
1424    /// called on the same branch immediately before, or immediately
1425    /// after.
1426    pub fn put_patches(
1427        &mut self,
1428        branch: &mut PatchSet,
1429        value: PatchId,
1430        time: ApplyTimestamp,
1431    ) -> Result<bool> {
1432        Ok(self.txn.put(&mut self.rng, branch, value, time)?)
1433    }
1434
1435    /// Delete a patch id from a branch. This doesn't unrecord the
1436    /// patch, it only removes it from the patch set. The
1437    /// `del_revpatches` method must be called on the same branch
1438    /// immediately before, or immediately after.
1439    pub fn del_patches(&mut self, branch: &mut PatchSet, value: PatchId) -> Result<bool> {
1440        Ok(self.txn.del(&mut self.rng, branch, value, None)?)
1441    }
1442
1443    /// Add a patch id to a branch. This doesn't apply the patch, it
1444    /// only registers it as applied. The `put_patches` method must be
1445    /// called on the same branch immediately before, or immediately
1446    /// after.
1447    pub fn put_revpatches(
1448        &mut self,
1449        branch: &mut RevPatchSet,
1450        time: ApplyTimestamp,
1451        value: PatchId,
1452    ) -> Result<bool> {
1453        Ok(self.txn.put(&mut self.rng, branch, time, value)?)
1454    }
1455
1456    /// Delete a patch id from a branch. This doesn't unrecord the
1457    /// patch, it only removes it from the patch set. The
1458    /// `del_patches` method must be called on the same branch
1459    /// immediately before, or immediately after.
1460    pub fn del_revpatches(
1461        &mut self,
1462        revbranch: &mut RevPatchSet,
1463        timestamp: ApplyTimestamp,
1464        value: PatchId,
1465    ) -> Result<bool> {
1466        Ok(self.txn
1467            .del(&mut self.rng, revbranch, timestamp, Some(value))?)
1468    }
1469
1470    /// Register a reverse dependency. All dependencies of all patches
1471    /// applied on at least one branch must be registered in this
1472    /// database, i.e. if a depends on b, then `(b, a)` must be
1473    /// inserted here.
1474    pub fn put_revdep(&mut self, patch: PatchId, revdep: PatchId) -> Result<bool> {
1475        Ok(self.txn
1476            .put(&mut self.rng, &mut self.dbs.revdep, patch, revdep)?)
1477    }
1478
1479    /// Register a dependency. All dependencies of all patches applied
1480    /// on at least one branch must be registered in this database,
1481    /// i.e. if a depends on b, then `(b, a)` must be inserted here.
1482    pub fn put_dep(&mut self, patch: PatchId, dep: PatchId) -> Result<bool> {
1483        Ok(self.txn.put(&mut self.rng, &mut self.dbs.dep, patch, dep)?)
1484    }
1485
1486    /// Remove a reverse dependency. Only call this method when the
1487    /// patch with identifier `patch` is not applied to any branch.
1488    pub fn del_revdep(&mut self, patch: PatchId, revdep: Option<PatchId>) -> Result<bool> {
1489        Ok(self.txn
1490            .del(&mut self.rng, &mut self.dbs.revdep, patch, revdep)?)
1491    }
1492
1493    /// Remove a dependency. Only call this method when the patch with
1494    /// identifier `patch` is not applied to any branch.
1495    pub fn del_dep(&mut self, patch: PatchId, dep: Option<PatchId>) -> Result<bool> {
1496        Ok(self.txn.del(&mut self.rng, &mut self.dbs.dep, patch, dep)?)
1497    }
1498
1499    /// Add an edge to the cemetery.
1500    pub fn put_cemetery(&mut self, key: Key<PatchId>, edge: &Edge, patch: PatchId) -> Result<bool> {
1501        let unsafe_edge = edge.to_unsafe();
1502        Ok(self.txn.put(
1503            &mut self.rng,
1504            &mut self.dbs.cemetery,
1505            (key, unsafe_edge),
1506            patch,
1507        )?)
1508    }
1509
1510    /// Delete an edge from the cemetery.
1511    pub fn del_cemetery(&mut self, key: Key<PatchId>, edge: &Edge, patch: PatchId) -> Result<bool> {
1512        let unsafe_edge = edge.to_unsafe();
1513        Ok(self.txn.del(
1514            &mut self.rng,
1515            &mut self.dbs.cemetery,
1516            (key, unsafe_edge),
1517            Some(patch),
1518        )?)
1519    }
1520
1521    /// Add the relation "patch `patch` touches file `file`".
1522    pub fn put_touched_file(&mut self, file: Key<PatchId>, patch: PatchId) -> Result<bool> {
1523        Ok(self.txn
1524            .put(&mut self.rng, &mut self.dbs.touched_files, file, patch)?)
1525    }
1526
1527    /// Delete all mentions of `patch` in the table of touched files.
1528    pub fn del_touched_file(&mut self, file: Key<PatchId>, patch: PatchId) -> Result<bool> {
1529        Ok(self.txn.del(
1530            &mut self.rng,
1531            &mut self.dbs.touched_files,
1532            file,
1533            Some(patch),
1534        )?)
1535    }
1536
1537    /// Add a partial path to a branch.
1538    pub fn put_partials(&mut self, name: &str, path: Key<PatchId>) -> Result<bool> {
1539        let name = small_string::SmallString::from_str(name);
1540        Ok(self.txn.put(
1541            &mut self.rng,
1542            &mut self.dbs.partials,
1543            name.as_small_str().to_unsafe(),
1544            path,
1545        )?)
1546    }
1547
1548    /// Remove a partial path from a branch.
1549    pub fn del_partials(&mut self, name: &str) -> Result<bool> {
1550        let name = small_string::SmallString::from_str(name);
1551        let mut deleted = false;
1552        while self.txn.del(
1553            &mut self.rng,
1554            &mut self.dbs.partials,
1555            name.as_small_str().to_unsafe(),
1556            None,
1557        )? {
1558            deleted = true
1559        }
1560        Ok(deleted)
1561    }
1562
1563    /// Allocate a string (to be inserted in the contents database).
1564    pub fn alloc_value(&mut self, slice: &[u8]) -> Result<UnsafeValue> {
1565        Ok(UnsafeValue::alloc_if_needed(&mut self.txn, slice)?)
1566    }
1567}