use crate::candidate_error::{CandidateError, CandidateFailure};
use crate::git_metadata::{MetadataOutput, path_from_git_bytes, run_metadata_git, strip_git_line};
use crate::git_system_config::with_real_git;
use crate::repo_read_layout::{git_path, read_layout};
use std::ffi::OsString;
use std::path::{Path, PathBuf};
fn command_failure(purpose: &str, operation: &str, output: &MetadataOutput) -> CandidateError {
return CandidateError::new(
CandidateFailure::GitFailed,
format!(
"monochromatic-git-policy-cli could not {purpose}: git {operation} failed: {}",
String::from_utf8_lossy(output.stderr.as_slice()).trim()
)
.as_str(),
);
}
fn not_started(purpose: &str, operation: &str, error: &std::io::Error) -> CandidateError {
return CandidateError::new(
CandidateFailure::GitNotStarted,
format!("monochromatic-git-policy-cli could not {purpose}: git {operation} could not be started: {error}.")
.as_str(),
);
}
pub fn run_git(
real_git: &Path,
prefix: &[OsString],
command: &[OsString],
overlay: &[(OsString, OsString)],
purpose: &str,
) -> Result<MetadataOutput, CandidateError> {
let mut arguments: Vec<OsString> = prefix.to_vec();
arguments.extend_from_slice(command);
let operation: String = match command.first() {
Some(word) => word.to_string_lossy().into_owned(),
None => String::from("(no command)"),
};
let output: MetadataOutput = match run_metadata_git(real_git, arguments.as_slice(), overlay) {
Ok(captured) => captured,
Err(error) => return Err(not_started(purpose, operation.as_str(), &error)),
};
if !output.success {
return Err(command_failure(purpose, operation.as_str(), &output));
}
return Ok(output);
}
pub fn real_index_path(
real_git: &Path,
prefix: &[OsString],
overlay: &[(OsString, OsString)],
purpose: &str,
) -> Result<PathBuf, CandidateError> {
let layout = read_layout(prefix, with_real_git(overlay, real_git).as_slice());
if let Some(found) = layout.as_ref()
&& let Some(path) = git_path(found, "index")
{
return Ok(path);
}
let output: MetadataOutput = run_git(
real_git,
prefix,
&[
OsString::from("rev-parse"),
OsString::from("--path-format=absolute"),
OsString::from("--git-path"),
OsString::from("index"),
],
overlay,
purpose,
)?;
match path_from_git_bytes(strip_git_line(output.stdout.as_slice())) {
Some(path) => return Ok(path),
None => {
return Err(CandidateError::new(
CandidateFailure::ListingMalformed,
format!(
"monochromatic-git-policy-cli could not {purpose}: git rev-parse --git-path index printed no path."
)
.as_str(),
));
}
}
}