consolidate common remotecallbacks code to a single fn

This commit is contained in:
Bryson Steck 2025-03-23 17:56:58 -06:00
parent 81f825b9d3
commit 445ba1fe1f
Signed by: bryson
SSH key fingerprint: SHA256:XpKABw/nP4z8UVaH+weLaBnEOD86+cVwif+QjuYLGT4

View file

@ -50,6 +50,33 @@ impl Refractr {
Ok(work_dir.to_string_lossy().to_string())
}
fn set_up_ssh(&self, key_path: String, strict: bool) -> Result<RemoteCallbacks, String> {
let mut cb = RemoteCallbacks::new();
cb.credentials(move |_, _, _| Cred::ssh_key("git", None, Path::new(&key_path), None));
cb.certificate_check(move |cert, url| {
let sha256 = hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec());
if strict {
common::error(
format!(
"unknown host {} with sha256 host key {}, exiting",
url, sha256
),
ExitCode::RemoteError,
);
} else {
common::warning(format!(
"unknown host {} with sha256 host key {}, implicitly trusting",
url, sha256
));
common::warning(format!(
"to suppress this warning in the future, add this host to your known_hosts file"
));
}
Ok(CertificateCheckStatus::CertificateOk)
});
Ok(cb)
}
fn get_refs(&self, branches: &Vec<String>, tags: Option<StringArray>) -> Vec<String> {
let mut refs_branches = Vec::new();
for branch in branches {
@ -84,30 +111,22 @@ impl Refractr {
branches: &Vec<String>,
ssh: bool,
ssh_key: &String,
strict: bool,
) -> Result<(), Error> {
let mut cb = RemoteCallbacks::new();
let mut fo = FetchOptions::new();
if ssh {
let key_string: String = ssh_key.clone();
cb.credentials(move |_, _, _| Cred::ssh_key("git", None, Path::new(&key_string), None));
cb.certificate_check(|cert, url| {
let mut sha256 = String::new();
for i in cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec() {
sha256.push_str(&hex::encode(i.to_string()));
}
common::warning(format!(
"implicitly trusting unknown host {} with sha256 host key {}",
url,
hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec())
));
common::warning(format!(
"to ignore this error in the future, add this host to your known_hosts file"
));
Ok(CertificateCheckStatus::CertificateOk)
});
match self.set_up_ssh(ssh_key.clone(), strict.clone()) {
Ok(cb) => {
fo.remote_callbacks(cb);
()
},
Err(e) => common::error(
format!("error setting up ssh: {}", e),
ExitCode::ConfigError,
),
};
}
fo.download_tags(git2::AutotagOption::All);
fo.remote_callbacks(cb);
repo
.find_remote("origin")?
.fetch(&branches, Some(&mut fo), None)?;
@ -170,41 +189,34 @@ impl Refractr {
1,
format!("Pushing to remote: {}", remote.url().unwrap()),
);
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(|_, _, _| {
Cred::ssh_key("git", None, &Path::new(&cfg.git.ssh_identity_file), None)
});
callbacks.certificate_check(|cert, url| {
let mut sha256 = String::new();
for i in cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec() {
sha256.push_str(&hex::encode(i.to_string()));
}
common::warning(format!(
"implicitly trusting unknown host {} with sha256 host key {}",
url,
hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec())
));
common::warning(format!(
"to ignore this error in the future, add this host to your known_hosts file"
));
Ok(CertificateCheckStatus::CertificateOk)
});
let mut push_options = PushOptions::new();
push_options.remote_callbacks(callbacks);
let mut po = PushOptions::new();
match self.set_up_ssh(cfg.git.ssh_identity_file.clone(), self.strict.clone()) {
Ok(cb) => {
po.remote_callbacks(cb);
()
},
Err(e) => common::error(
format!("error setting up ssh: {}", e),
ExitCode::ConfigError,
),
};
let mut refs = Vec::new();
let mut refs_str = String::new();
let strings = self.get_refs(&cfg.branches, match cfg.push_tags {
true => Some(repo.tag_names(None).unwrap()),
false => None
});
let strings = self.get_refs(
&cfg.branches,
match cfg.push_tags {
true => Some(repo.tag_names(None).unwrap()),
false => None,
},
);
for branch in &strings {
refs.push(branch.as_str());
refs_str.push_str(format!("{} ", branch).as_str());
}
common::verbose(self.verbose, 4, format!("ref list: {}", refs_str));
match remote.push::<&str>(&refs, Some(&mut push_options)) {
match remote.push::<&str>(&refs, Some(&mut po)) {
Ok(_) => (),
Err(e) => {
if self.strict {
@ -330,31 +342,25 @@ impl Refractr {
let ssh = cfg.config.from.starts_with("ssh://");
let mut builder = RepoBuilder::new();
let mut cb = RemoteCallbacks::new();
let mut fo = FetchOptions::new();
// make initial clone
if ssh {
let key_string = cfg.config.git.ssh_identity_file.clone();
cb.credentials(move |_, _, _| Cred::ssh_key("git", None, Path::new(&key_string), None));
cb.certificate_check(|cert, url| {
let mut sha256 = String::new();
for i in cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec() {
sha256.push_str(&hex::encode(i.to_string()));
}
common::warning(format!(
"implicitly trusting unknown host {} with sha256 host key {}",
url,
hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec())
));
common::warning(format!(
"to ignore this error in the future, add this host to your known_hosts file"
));
Ok(CertificateCheckStatus::CertificateOk)
});
match self.set_up_ssh(
cfg.config.git.ssh_identity_file.clone(),
self.strict.clone(),
) {
Ok(cb) => {
fo.remote_callbacks(cb);
()
},
Err(e) => common::error(
format!("error setting up ssh: {}", e),
ExitCode::ConfigError,
),
};
}
fo.download_tags(git2::AutotagOption::All);
fo.remote_callbacks(cb);
builder.fetch_options(fo);
let repo_dir = format!("{}{}{}", &path_str, MAIN_SEPARATOR_STR, repo_name);
@ -403,6 +409,7 @@ impl Refractr {
&cfg.config.branches,
ssh,
&cfg.config.git.ssh_identity_file,
self.strict.clone(),
) {
common::error(
format!("failed to fetch repo {}: {}", cfg.config.from, e),