comtrya_lib/atoms/git/
clone.rs

1use super::super::Atom;
2use crate::atoms::Outcome;
3use gix::interrupt;
4use gix::{progress::Discard, Url};
5use std::path::PathBuf;
6use tracing::instrument;
7
8#[derive(Default)]
9pub struct Clone {
10    pub repository: Url,
11    pub directory: PathBuf,
12}
13
14impl std::fmt::Display for Clone {
15    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16        write!(
17            f,
18            "GitClone {} to {}",
19            self.repository,
20            self.directory.display()
21        )
22    }
23}
24
25impl Atom for Clone {
26    #[instrument(name = "git.clone.plan", level = "info", skip(self))]
27    fn plan(&self) -> anyhow::Result<Outcome> {
28        Ok(Outcome {
29            side_effects: vec![],
30            should_run: !self.directory.exists(),
31        })
32    }
33
34    #[instrument(name = "git.clone.execute", level = "info", skip(self))]
35    fn execute(&mut self) -> anyhow::Result<()> {
36        unsafe {
37            interrupt::init_handler(1, || {})?;
38        };
39
40        std::fs::create_dir_all(&self.directory)?;
41
42        let mut prepare_clone = gix::prepare_clone(self.repository.clone(), &self.directory)?;
43        let (mut prepare_checkout, _) = prepare_clone
44            .fetch_then_checkout(gix::progress::Discard, &interrupt::IS_INTERRUPTED)?;
45
46        let (repo, _) = prepare_checkout.main_worktree(Discard, &interrupt::IS_INTERRUPTED)?;
47
48        let _ = repo
49            .find_default_remote(gix::remote::Direction::Fetch)
50            .expect("always present after clone")?;
51
52        Ok(())
53    }
54}