smaug_lib/sources/
git_source.rs

1use crate::dependency::Dependency;
2use crate::source::Source;
3use crate::sources::dir_source::DirSource;
4use git2::build::CheckoutBuilder;
5use git2::build::RepoBuilder;
6use git2::FetchOptions;
7use git2::Oid;
8use log::*;
9use std::path::Path;
10
11#[derive(Clone, Debug)]
12pub struct GitSource {
13    pub repo: String,
14    pub branch: Option<String>,
15    pub rev: Option<String>,
16    pub tag: Option<String>,
17}
18
19impl Source for GitSource {
20    fn install(&self, dependency: &Dependency, path: &Path) -> std::io::Result<()> {
21        let destination = crate::smaug::cache_dir().join(dependency.clone().name);
22        trace!(
23            "Installing git repository {} to {}",
24            self.repo,
25            destination.display()
26        );
27
28        if destination.exists() {
29            trace!("Removing directory {}", destination.to_str().unwrap());
30            rm_rf::ensure_removed(destination.clone()).unwrap();
31        }
32
33        let fetch = FetchOptions::new();
34        let checkout = CheckoutBuilder::new();
35
36        let mut builder = RepoBuilder::new();
37        builder.fetch_options(fetch);
38        builder.with_checkout(checkout);
39
40        debug!("Repository: {}", self.repo);
41        if self.branch.is_some() {
42            debug!("Branch: {}", self.branch.as_ref().unwrap());
43            builder.branch(self.branch.as_ref().unwrap().as_str());
44        }
45
46        trace!(
47            "Cloning git repository to {}",
48            destination.to_str().unwrap()
49        );
50        let repository = builder.clone(&self.repo, destination.as_path()).unwrap();
51
52        if self.rev.is_some() {
53            let revision = self.rev.clone().unwrap();
54            debug!("Revision: {}", revision);
55            let mut checkout = CheckoutBuilder::new();
56            let object = repository
57                .find_object(
58                    Oid::from_str(revision.as_str()).expect("Could not find the revision"),
59                    None,
60                )
61                .unwrap();
62            repository
63                .reset(&object, git2::ResetType::Hard, Some(&mut checkout))
64                .unwrap();
65        }
66
67        if self.tag.is_some() {
68            let tag = self.tag.clone().unwrap();
69            let mut checkout = CheckoutBuilder::new();
70
71            let rev = repository
72                .revparse_single(&tag)
73                .expect("Couldn't parse tag");
74
75            repository
76                .reset(&rev, git2::ResetType::Hard, Some(&mut checkout))
77                .unwrap();
78        }
79
80        let cached = repository.path().parent().expect("No parent dir");
81
82        DirSource {
83            path: cached.to_path_buf(),
84        }
85        .install(dependency, path)
86    }
87}