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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use crate::{GitCredentials, GitRepo};
use std::path::Path;
use std::process::{Command, Stdio};
use color_eyre::eyre::Result;
use log::{debug, info};
impl GitRepo {
pub fn git_clone<P: AsRef<Path>>(&self, target: P) -> Result<GitRepo> {
let cb = self.build_git2_remotecallback();
let mut builder = git2::build::RepoBuilder::new();
let mut fetch_options = git2::FetchOptions::new();
fetch_options.remote_callbacks(cb);
builder.fetch_options(fetch_options);
if let Some(b) = &self.branch {
builder.branch(b);
}
let repo = match builder.clone(&self.url.to_string(), target.as_ref()) {
Ok(repo) => repo,
Err(e) => panic!("failed to clone: {}", e),
};
let mut git_repo: GitRepo = repo.into();
git_repo = git_repo.with_credentials(self.credentials.clone());
Ok(git_repo)
}
pub fn git_clone_shallow<P: AsRef<Path>>(&self, target: P) -> Result<GitRepo> {
let repo = if let Some(cred) = self.credentials.clone() {
match cred {
crate::GitCredentials::SshKey {
username,
public_key,
private_key,
passphrase,
} => {
let mut parsed_uri = self.url.trim_auth();
parsed_uri.user = Some(username.to_string());
let shell_clone_command = Command::new("git")
.arg("clone")
.arg(format!("{}", parsed_uri))
.arg(format!("{}", target.as_ref().display()))
.arg("--no-single-branch")
.arg("--depth=1")
.arg("--config")
.arg(format!(
"core.sshcommand=ssh -i {privkey_path}",
privkey_path = private_key
.clone()
.into_os_string()
.into_string()
.expect("Couldn't convert path to string")
))
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.expect("failed to run git clone");
let clone_out = shell_clone_command
.wait_with_output()
.expect("failed to open stdout");
debug!("Clone output: {:?}", clone_out);
let creds = GitCredentials::SshKey {
username,
public_key,
private_key,
passphrase,
};
GitRepo::open(target.as_ref().to_path_buf(), None, None)
.expect(
format!("Failed to open shallow clone dir: {:?}", clone_out).as_str(),
)
.with_credentials(Some(creds))
}
crate::GitCredentials::UserPassPlaintext { username, password } => {
let mut cli_remote_url = self.url.clone();
cli_remote_url.user = Some(username.to_string());
cli_remote_url.token = Some(password.to_string());
let shell_clone_command = Command::new("git")
.arg("clone")
.arg(format!("{}", cli_remote_url))
.arg(format!("{}", target.as_ref().display()))
.arg("--no-single-branch")
.arg("--depth=1")
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.expect("Failed to run git clone");
let clone_out = shell_clone_command.stdout.expect("Failed to open stdout");
let creds = GitCredentials::UserPassPlaintext { username, password };
GitRepo::open(target.as_ref().to_path_buf(), None, None)
.expect(
format!("Failed to open shallow clone dir: {:?}", clone_out).as_str(),
)
.with_credentials(Some(creds))
}
}
} else {
let parsed_uri = self.url.trim_auth();
info!("Url: {}", format!("{}", parsed_uri));
info!("Directory: {}", format!("{}", target.as_ref().display()));
let shell_clone_command = Command::new("git")
.arg("clone")
.arg(format!("{}", parsed_uri))
.arg(format!("{}", target.as_ref().display()))
.arg("--no-single-branch")
.arg("--depth=1")
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.expect("Failed to run git clone");
let clone_out = shell_clone_command
.wait_with_output()
.expect("Failed to wait for output")
.stdout;
GitRepo::open(target.as_ref().to_path_buf(), None, None)
.expect(format!("Failed to open shallow clone dir: {:?}", clone_out).as_str())
};
Ok(repo)
}
}