git_rs/stores/
mod.rs

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}