use git2::build::CheckoutBuilder;
use git2::{Branch, Commit, Cred, Error, PushOptions, Remote, Repository};
use std::path::Path;
use std::process::{Command, Output};
use std::result::Result;
use settings::Git;
pub static GIT_REF_BASE: &'static str = "refs/heads";
pub fn get_latest_commit(repo: &Repository) -> Commit {
let head = repo.head().unwrap();
let oid = head.target().unwrap();
repo.find_commit(oid).unwrap()
}
pub fn push_to_remote(
remote: &mut Remote,
branch: &Branch,
delete: bool,
mut opts: &mut PushOptions,
) -> Result<(), Error> {
let action = if delete { ":" } else { "+" };
let refspecs: &[&str] = &[&format!(
"{}{}/{}",
action,
GIT_REF_BASE,
branch.name().unwrap().unwrap()
)];
remote.push(refspecs, Some(&mut opts))
}
pub fn pull(repo: &Repository) -> Result<Output, &'static str> {
let workdir = repo.workdir().unwrap();
let output = Command::new("git")
.arg("pull") .current_dir(&workdir) .output() .unwrap();
if output.status.success() {
debug!(
"Pull: {}",
String::from_utf8(output.clone().stdout).unwrap()
);
Ok(output)
} else {
Err("Error: couldn't pull changes")
}
}
pub fn checkout_branch(repo: &Repository, branch: &str) -> () {
let workdir = repo.workdir().unwrap();
Command::new("git")
.arg("reset")
.arg("--hard")
.current_dir(&workdir)
.output()
.unwrap();
Command::new("git")
.arg("clean")
.arg("-f") .arg("-d") .current_dir(&workdir)
.output()
.unwrap();
repo.set_head(&format!("{}/{}", GIT_REF_BASE, &branch))
.unwrap_or_else(|err| panic!("Couldn't set HEAD: {}", err));
repo.checkout_head(Some(&mut CheckoutBuilder::new().force()))
.unwrap_or_else(|err| panic!("Couldn't checkout HEAD: {}", err));
Command::new("git")
.arg("reset")
.arg("--hard")
.current_dir(&workdir)
.output()
.unwrap();
Command::new("git")
.arg("clean")
.arg("-f") .arg("-d") .current_dir(&workdir)
.output()
.unwrap();
()
}
pub fn apply_patch(repo: &Repository, path: &Path) -> Result<Output, &'static str> {
let workdir = repo.workdir().unwrap();
let output = Command::new("git")
.arg("am") .arg("-3") .arg(&path) .current_dir(&workdir) .output() .unwrap();
if output.status.success() {
debug!(
"Patch applied with text {}",
String::from_utf8(output.clone().stdout).unwrap()
);
Ok(output)
} else {
info!(
"Patch failed to apply with text {} {}",
String::from_utf8(output.clone().stdout).unwrap(),
String::from_utf8(output.clone().stderr).unwrap()
);
Command::new("git")
.arg("am")
.arg("--abort")
.current_dir(&workdir)
.output()
.unwrap();
Err("Patch did not apply successfully")
}
}
pub fn cred_from_settings(settings: &Git) -> Result<Cred, Error> {
let public_key = settings.public_key.as_ref().map(String::as_ref);
let passphrase = settings.passphrase.as_ref().map(String::as_ref);
Cred::ssh_key(
&settings.user,
public_key,
Path::new(&settings.private_key),
passphrase,
)
}