use std::ffi::OsString;
use std::path::PathBuf;
use tracing::{instrument, warn};
use crate::git::{ConfigRead, Repo};
#[instrument]
pub fn get_core_hooks_path(repo: &Repo) -> eyre::Result<PathBuf> {
repo.get_readonly_config()?
.get_or_else("core.hooksPath", || repo.get_path().join("hooks"))
}
#[instrument]
pub fn get_main_branch_name(repo: &Repo) -> eyre::Result<String> {
let config = repo.get_readonly_config()?;
if let Some(branch_name) = config.get("branchless.core.mainBranch")? {
return Ok(branch_name);
}
if let Some(branch_name) = config.get("branchless.mainBranch")? {
return Ok(branch_name);
}
if let Some(branch_name) = get_default_branch_name(repo)? {
return Ok(branch_name);
}
Ok("master".to_string())
}
#[instrument]
pub fn get_comment_char(repo: &Repo) -> eyre::Result<char> {
let from_config: Option<String> = repo.get_readonly_config()?.get("core.commentChar")?;
let comment_char = match from_config {
Some(comment_char) => comment_char.chars().next().unwrap(),
None => char::from(git2::DEFAULT_COMMENT_CHAR.unwrap()),
};
Ok(comment_char)
}
#[instrument]
pub fn get_commit_template(repo: &Repo) -> eyre::Result<Option<String>> {
let commit_template_path: Option<String> =
repo.get_readonly_config()?.get("commit.template")?;
let commit_template_path = match commit_template_path {
Some(commit_template_path) => PathBuf::from(commit_template_path),
None => return Ok(None),
};
let commit_template_path = if commit_template_path.is_relative() {
match repo.get_working_copy_path() {
Some(root) => root.join(commit_template_path),
None => {
warn!(?commit_template_path, "Commit template path was relative, but this repository does not have a working copy");
return Ok(None);
}
}
} else {
commit_template_path
};
match std::fs::read_to_string(&commit_template_path) {
Ok(contents) => Ok(Some(contents)),
Err(e) => {
warn!(?e, ?commit_template_path, "Could not read commit template");
Ok(None)
}
}
}
#[instrument]
pub fn get_default_branch_name(repo: &Repo) -> eyre::Result<Option<String>> {
let config = repo.get_readonly_config()?;
let default_branch_name: Option<String> = config.get("init.defaultBranch")?;
Ok(default_branch_name)
}
#[instrument]
pub fn get_editor(repo: &Repo) -> eyre::Result<Option<OsString>> {
let editor = std::env::var_os("GIT_EDITOR");
if editor != None {
return Ok(editor);
}
let config = repo.get_readonly_config()?;
let editor: Option<String> = config.get("core.editor")?;
match editor {
Some(editor) => Ok(Some(editor.into())),
None => Ok(None),
}
}
#[instrument]
pub fn get_restack_preserve_timestamps(repo: &Repo) -> eyre::Result<bool> {
repo.get_readonly_config()?
.get_or("branchless.restack.preserveTimestamps", false)
}
#[instrument]
pub fn get_next_interactive(repo: &Repo) -> eyre::Result<bool> {
repo.get_readonly_config()?
.get_or("branchless.next.interactive", false)
}
pub const RESTACK_WARN_ABANDONED_CONFIG_KEY: &str = "branchless.restack.warnAbandoned";
#[instrument]
pub fn get_restack_warn_abandoned(repo: &Repo) -> eyre::Result<bool> {
repo.get_readonly_config()?
.get_or(RESTACK_WARN_ABANDONED_CONFIG_KEY, true)
}
#[instrument]
pub fn get_commit_descriptors_branches(repo: &Repo) -> eyre::Result<bool> {
repo.get_readonly_config()?
.get_or("branchless.commitDescriptors.branches", true)
}
#[instrument]
pub fn get_commit_descriptors_differential_revision(repo: &Repo) -> eyre::Result<bool> {
repo.get_readonly_config()?
.get_or("branchless.commitDescriptors.differentialRevision", true)
}
#[instrument]
pub fn get_commit_descriptors_relative_time(repo: &Repo) -> eyre::Result<bool> {
repo.get_readonly_config()?
.get_or("branchless.commitDescriptors.relativeTime", true)
}
pub mod env_vars {
use std::path::PathBuf;
use tracing::instrument;
pub const TEST_GIT: &str = "TEST_GIT";
pub const TEST_GIT_EXEC_PATH: &str = "TEST_GIT_EXEC_PATH";
#[instrument]
pub fn get_path_to_git() -> eyre::Result<PathBuf> {
let path_to_git = std::env::var_os(TEST_GIT).ok_or_else(|| {
eyre::eyre!(
"No path to Git executable was set. \
Try running as: `{0}=$(which git) cargo test ...` \
or set `env.{0}` in your `config.toml` \
(see https://doc.rust-lang.org/cargo/reference/config.html)",
TEST_GIT,
)
})?;
let path_to_git = PathBuf::from(&path_to_git);
Ok(path_to_git)
}
#[instrument]
pub fn get_git_exec_path() -> eyre::Result<PathBuf> {
let git_exec_path = std::env::var_os(TEST_GIT_EXEC_PATH).ok_or_else(|| {
eyre::eyre!(
"No Git exec path was set. \
Try running as: `{0}=$(git --exec-path) cargo test ...` \
or set `env.{0}` in your `config.toml` \
(see https://doc.rust-lang.org/cargo/reference/config.html)",
TEST_GIT_EXEC_PATH,
)
})?;
let git_exec_path = PathBuf::from(&git_exec_path);
Ok(git_exec_path)
}
}