1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use crate::errors::*;
use crate::Guidon;
use crate::TryNew;
use derive_builder::Builder;
use git2::build::RepoBuilder;
use git2::{AutotagOption, Cred, FetchOptions, ProxyOptions};
use std::env;
use std::fs::create_dir_all;
use std::fs::remove_dir_all;
#[derive(Debug, Clone, Builder, Default)]
#[builder(default)]
#[builder(field(private))]
#[builder(setter(into, strip_option))]
pub struct GitOptions {
repo: String,
rev: Option<String>,
credentials: Option<(String, String)>,
unsecure: bool,
auto_proxy: bool,
}
impl GitOptions {
pub fn builder() -> GitOptionsBuilder {
GitOptionsBuilder::default()
}
}
impl<'a> TryNew<GitOptions> for Guidon<'a> {
fn try_new(git: GitOptions) -> Result<Self> {
let mut cb = git2::RemoteCallbacks::new();
if let Some(creds) = git.credentials {
cb.credentials(move |_, _, _| {
let credentials = Cred::userpass_plaintext(&creds.0, &creds.1)?;
Ok(credentials)
});
}
if git.unsecure {
cb.certificate_check(|_, _| true);
}
let mut fo = FetchOptions::new();
fo.remote_callbacks(cb)
.download_tags(AutotagOption::All)
.update_fetchhead(true);
if git.auto_proxy {
let mut po = ProxyOptions::new();
po.auto();
fo.proxy_options(po);
}
let dest = env::temp_dir().join("guidon");
let _ = remove_dir_all(&dest);
create_dir_all(&dest)?;
let repo = RepoBuilder::new()
.fetch_options(fo)
.clone(&git.repo, dest.as_path())?;
let local =
repo.revparse_single(&git.rev.unwrap_or_else(|| "refs/heads/master".to_owned()))?;
let mut opts = git2::build::CheckoutBuilder::new();
opts.force();
opts.use_theirs(true);
repo.checkout_tree(&local, Some(&mut opts))?;
Guidon::try_new(dest)
}
}
impl From<git2::Error> for GuidonError {
fn from(error: git2::Error) -> Self {
GuidonError {
kind: ErrorKind::GitError,
message: error.to_string(),
}
}
}