1use std::collections::HashSet;
2use std::io::Cursor;
3use std::io::Write;
4
5use crate::walk::commits::CommitIterator;
6use crate::walk::tree::TreeIterator;
7use crate::objects::{Type, Object};
8use crate::errors::Result;
9use crate::id::Id;
10
11pub mod loose;
12pub mod pack;
13pub mod fs;
14
15pub trait Queryable {
16 fn get<W: Write, S: Queryable>(&self, id: &Id, output: &mut W, backends: &StorageSet<S>) -> Result<Option<Type>>;
17}
18
19impl Queryable for () {
20 fn get<W: Write, S: Queryable>(&self, id: &Id, _output: &mut W, _backends: &StorageSet<S>) -> Result<Option<Type>> {
21 Ok(None)
22 }
23}
24
25impl<Q: Queryable> Queryable for (Q,) {
26 fn get<W: Write, S: Queryable>(&self, id: &Id, output: &mut W, backends: &StorageSet<S>) -> Result<Option<Type>> {
27 self.0.get(id, output, backends)
28 }
29}
30
31impl<H: Queryable, T: Queryable> Queryable for (H, T) {
32 fn get<W: Write, S: Queryable>(&self, id: &Id, output: &mut W, backends: &StorageSet<S>) -> Result<Option<Type>> {
33 let opt = self.0.get(id, output, backends)?;
34 if opt.is_some() {
35 return Ok(opt)
36 }
37
38 self.1.get(id, output, backends)
39 }
40}
41
42impl<Q: Queryable> Queryable for Vec<Q> {
43 fn get<W: Write, S: Queryable>(&self, id: &Id, output: &mut W, backends: &StorageSet<S>) -> Result<Option<Type>> {
44 for queryable in self {
45 let opt = queryable.get(id, output, backends)?;
46 if opt.is_some() {
47 return Ok(opt)
48 }
49 }
50
51 Ok(None)
52 }
53}
54
55pub struct StorageSet<Q: Queryable> {
56 backend: Q
57}
58
59impl<Q: Queryable> StorageSet<Q> {
60 pub fn new(backend: Q) -> StorageSet<Q> {
61 StorageSet {
62 backend
63 }
64 }
65
66 pub fn get<W: Write>(&self, id: &Id, output: &mut W) -> Result<Option<Type>> {
67 self.backend.get(id, output, &self)
68 }
69
70 pub fn commits(&self, id: &Id, seen: Option<HashSet<Id>>) -> CommitIterator<Q> {
71 CommitIterator::new(&self, id, seen)
72 }
73
74 pub fn tree(&self, id: &Id) -> TreeIterator<Q> {
75 let result = match self.get_and_load(id) {
76 Ok(xs) => xs,
77 Err(_) => return TreeIterator::new(&self, vec![])
78 };
79
80 if result.is_none() {
81 return TreeIterator::new(&self, vec![])
82 }
83
84 match result.unwrap() {
85 Object::Commit(commit) => {
86 match commit.tree() {
87 Some(tree) => self.tree(&tree),
88 None => TreeIterator::new(&self, vec![])
89 }
90 },
91 Object::Tree(tree) => {
92 TreeIterator::new(&self, vec![tree.into_iter()])
93 },
94 _ => {
95 TreeIterator::new(&self, vec![])
96 }
97 }
98 }
99
100 pub fn get_and_load(&self, id: &Id) -> Result<Option<Object>> {
101 let mut data = Vec::new();
102 match self.get(id, &mut data)? {
103 Some(typ) => Ok(Some(typ.load(&mut Cursor::new(&data))?)),
104 None => Ok(None)
105 }
106 }
107}