gitscope
← rgit / 0.1.0 / src/database/schema/tag.rs
https://dev.kronoz.win/r/rgit.git
src/database/schema/tag.rs · Rust
Blame Raw
 1use std::{collections::HashSet, ops::Deref};
 2
 3use git2::Signature;
 4use serde::{Deserialize, Serialize};
 5use sled::IVec;
 6use yoke::{Yoke, Yokeable};
 7
 8use crate::database::schema::{commit::Author, Yoked};
 9
10#[derive(Serialize, Deserialize, Debug, Yokeable)]
11pub struct Tag<'a> {
12    #[serde(borrow)]
13    pub tagger: Option<Author<'a>>,
14}
15
16impl<'a> Tag<'a> {
17    pub fn new(tagger: Option<&'a Signature<'_>>) -> Self {
18        Self {
19            tagger: tagger.map(Into::into),
20        }
21    }
22
23    pub fn insert(&self, batch: &TagTree, name: &str) {
24        batch
25            .insert(name.as_bytes(), bincode::serialize(self).unwrap())
26            .unwrap();
27    }
28}
29
30pub struct TagTree(sled::Tree);
31
32impl Deref for TagTree {
33    type Target = sled::Tree;
34
35    fn deref(&self) -> &Self::Target {
36        &self.0
37    }
38}
39
40pub type YokedTag = Yoked<Tag<'static>>;
41
42impl TagTree {
43    pub(super) fn new(tree: sled::Tree) -> Self {
44        Self(tree)
45    }
46
47    pub fn remove(&self, name: &str) -> bool {
48        self.0.remove(name).unwrap().is_some()
49    }
50
51    pub fn list(&self) -> HashSet<String> {
52        self.iter()
53            .keys()
54            .filter_map(Result::ok)
55            .map(|v| String::from_utf8_lossy(&v).into_owned())
56            .collect()
57    }
58
59    pub fn fetch_all(&self) -> Vec<(String, YokedTag)> {
60        let mut res = self
61            .iter()
62            .map(|res| {
63                let (name, value) = res?;
64
65                let name = String::from_utf8_lossy(&name)
66                    .strip_prefix("refs/tags/")
67                    .unwrap()
68                    .to_string();
69
70                // internally value is an Arc so it should already be stablederef but because
71                // of reasons unbeknownst to me, sled has its own Arc implementation so we need
72                // to box the value as well to get a stablederef...
73                let value = Box::new(value);
74
75                Ok((
76                    name,
77                    Yoke::try_attach_to_cart(value, |data: &IVec| bincode::deserialize(data))
78                        .unwrap(),
79                ))
80            })
81            .collect::<Result<Vec<(String, YokedTag)>, sled::Error>>()
82            .unwrap();
83
84        res.sort_unstable_by(|a, b| {
85            let a_tagger = a.1.get().tagger.as_ref().map(|v| v.time);
86            let b_tagger = b.1.get().tagger.as_ref().map(|v| v.time);
87            b_tagger.cmp(&a_tagger)
88        });
89
90        res
91    }
92}