use crate::git_system_config::with_real_git;
use crate::repo_read_layout::read_layout_after_success_for;
use std::ffi::OsString;
use std::path::{Path, PathBuf};
fn directory_options(global_arguments: &[OsString]) -> Option<Vec<OsString>> {
let mut kept: Vec<OsString> = Vec::new();
let mut options = global_arguments.iter();
while let Some(option) = options.next() {
let value: &OsString = options.next()?;
if option == "-C" {
kept.push(option.clone());
kept.push(value.clone());
} else if option != "-c" {
return None;
}
}
return Some(kept);
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum Selection {
Found(PathBuf),
Outside,
Unresolved(String),
}
pub(crate) fn status_git_dir(global_arguments: &[OsString], environment: &[(OsString, OsString)], real_git: Option<&Path>) -> Selection {
let named: Vec<(OsString, OsString)> = match real_git {
Some(found) => with_real_git(environment, found),
None => environment.to_vec(),
};
if let Some(prefix) = directory_options(global_arguments)
&& let Some(layout) = read_layout_after_success_for(prefix.as_slice(), named.as_slice())
{
return Selection::Found(layout.git_dir);
}
let Some(real) = real_git else {
return Selection::Unresolved(String::from("no real Git was found to ask"));
};
let mut asking = std::process::Command::new(real);
asking.args(global_arguments).args(["rev-parse", "--path-format=absolute", "--absolute-git-dir"]);
for (name, value) in environment {
asking.env(name, value);
}
asking.env("LC_ALL", "C").stdin(std::process::Stdio::null());
crate::started_as_git::mark_real_git_start(&mut asking, crate::started_as_git::StartMode::Child);
let asked = asking.output();
let output = match asked {
Ok(found) => found,
Err(error) => return Selection::Unresolved(format!("Git could not be started: {error}")),
};
let said: String = String::from_utf8_lossy(output.stdout.as_slice()).trim().to_owned();
if output.status.success() && !said.is_empty() {
return Selection::Found(PathBuf::from(said));
}
let complaint: String = String::from_utf8_lossy(output.stderr.as_slice()).trim().to_owned();
if output.status.code() == Some(NOT_A_REPOSITORY_EXIT_CODE) && complaint.contains("not a git repository") {
return Selection::Outside;
}
return Selection::Unresolved(format!("Git said: {complaint}"));
}
const NOT_A_REPOSITORY_EXIT_CODE: i32 = 128;