comtrya_lib/atoms/git/
clone.rs1use 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}