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
54pub type ApplyTimestamp = u64;
56
57type PatchSet = sanakirja::Db<self::patch_id::PatchId, ApplyTimestamp>;
60
61type RevPatchSet = sanakirja::Db<ApplyTimestamp, self::patch_id::PatchId>;
62
63pub struct Dbs {
64 tree: sanakirja::Db<self::file_id::UnsafeFileId, self::inode::Inode>,
66 revtree: sanakirja::Db<self::inode::Inode, self::file_id::UnsafeFileId>,
68 inodes: sanakirja::Db<self::inode::Inode, self::file_header::FileHeader>,
70 revinodes: sanakirja::Db<self::key::Key<PatchId>, self::inode::Inode>,
72 contents: sanakirja::Db<self::key::Key<PatchId>, sanakirja::value::UnsafeValue>,
74 internal: sanakirja::Db<self::hash::UnsafeHash, self::patch_id::PatchId>,
76 external: sanakirja::Db<self::patch_id::PatchId, self::hash::UnsafeHash>,
78 revdep: sanakirja::Db<self::patch_id::PatchId, self::patch_id::PatchId>,
81 branches:
83 sanakirja::Db<self::small_string::UnsafeSmallStr, (NodesDb, PatchSet, RevPatchSet, u64)>,
84 cemetery:
86 sanakirja::Db<(self::key::Key<PatchId>, self::edge::UnsafeEdge), self::patch_id::PatchId>,
87 dep: sanakirja::Db<self::patch_id::PatchId, self::patch_id::PatchId>,
89 touched_files: sanakirja::Db<self::key::Key<PatchId>, self::patch_id::PatchId>,
91 partials: sanakirja::Db<self::small_string::UnsafeSmallStr, self::key::Key<PatchId>>,
93}
94
95pub 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
107pub type MutTxn<'env, R> = GenericTxn<sanakirja::MutTxn<'env, ()>, R>;
109pub type Txn<'env> = GenericTxn<sanakirja::Txn<'env>, ()>;
111
112pub const DEFAULT_BRANCH: &'static str = "master";
115
116pub 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
166const 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 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 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 pub unsafe fn close(&mut self) {
221 self.env.close()
222 }
223
224 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 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#[derive(Debug)]
292pub struct Branch {
293 pub db: NodesDb,
295 pub patches: PatchSet,
297 pub revpatches: RevPatchSet,
299 pub apply_counter: u64,
303 pub name: small_string::SmallString,
305}
306
307use sanakirja::Commit;
308impl<'env, R: rand::Rng> MutTxn<'env, R> {
310 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 pub fn commit_branch(&mut self, branch: Branch) -> Result<()> {
343 debug!("Commit_branch. This is not too safe.");
344 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 pub fn rename_branch(&mut self, branch: &mut Branch, new_name: &str) -> Result<()> {
383 debug!("Commit_branch. This is not too safe.");
384 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 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 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}
721impl<U: Transaction, R> GenericTxn<U, R> {
735 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 pub fn get_inodes<'a>(&'a self, key: Inode) -> Option<FileHeader> {
987 self.txn.get(&self.dbs.inodes, key, None)
988 }
989
990 pub fn get_revinodes(&self, key: Key<PatchId>) -> Option<Inode> {
993 self.txn.get(&self.dbs.revinodes, key, None)
994 }
995
996 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 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 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 pub fn get_patch(&self, patch_set: &PatchSet, patchid: PatchId) -> Option<ApplyTimestamp> {
1026 self.txn.get(patch_set, patchid, None)
1027 }
1028
1029 pub fn get_revdep(&self, patch: PatchId, dep: Option<PatchId>) -> Option<PatchId> {
1032 self.txn.get(&self.dbs.revdep, patch, dep)
1033 }
1034
1035 pub fn get_dep(&self, patch: PatchId, dep: Option<PatchId>) -> Option<PatchId> {
1038 self.txn.get(&self.dbs.dep, patch, dep)
1039 }
1040
1041 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 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 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 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 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 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
1217impl<'env, R: rand::Rng> MutTxn<'env, R> {
1219 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 pub fn alloc_value(&mut self, slice: &[u8]) -> Result<UnsafeValue> {
1565 Ok(UnsafeValue::alloc_if_needed(&mut self.txn, slice)?)
1566 }
1567}