radicle_node/worker/
garbage.rs

1use std::process::{Command, ExitStatus, Stdio};
2use std::{fmt, io};
3
4use radicle::prelude::RepoId;
5use radicle::storage::ReadStorage;
6
7/// Default expiry time for objects.
8pub const EXPIRY_DEFAULT: Expiry = Expiry::Hours(1);
9
10/// Expiry of objects for garbage collector.
11#[derive(Copy, Clone, Debug, PartialEq, Eq)]
12pub enum Expiry {
13    Now,
14    Seconds(usize),
15    Hours(usize),
16    Days(usize),
17    Weeks(usize),
18}
19
20impl Default for Expiry {
21    fn default() -> Self {
22        EXPIRY_DEFAULT
23    }
24}
25
26impl fmt::Display for Expiry {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        match self {
29            Self::Now => f.write_str("now"),
30            Self::Seconds(s) => write!(f, "{s}.seconds.ago"),
31            Self::Hours(s) => write!(f, "{s}.hours.ago"),
32            Self::Days(s) => write!(f, "{s}.days.ago"),
33            Self::Weeks(s) => write!(f, "{s}.weeks.ago"),
34        }
35    }
36}
37
38/// Run Git garbage collector.
39pub fn collect(storage: &impl ReadStorage, rid: RepoId, expiry: Expiry) -> io::Result<ExitStatus> {
40    let git_dir = storage.path_of(&rid);
41    let mut gc = Command::new("git");
42    gc.current_dir(git_dir)
43        .env_clear()
44        .envs(std::env::vars().filter(|(key, _)| key == "PATH" || key.starts_with("GIT_TRACE")))
45        .args(["gc", &format!("--prune={expiry}"), "--auto"])
46        .stdout(Stdio::piped())
47        .stdin(Stdio::piped())
48        .stderr(Stdio::inherit());
49    let mut child = gc.spawn()?;
50    let status = child.wait()?;
51
52    Ok(status)
53}