use crate::{
File, Source,
file::{Metadata, init},
path, source,
};
use gix_error::{ExnMessageResult, ExnResult};
impl File {
pub fn from_globals() -> ExnMessageResult<File> {
let metas = [
source::Kind::GitInstallation,
source::Kind::System,
source::Kind::Global,
]
.iter()
.flat_map(|kind| kind.sources())
.filter_map(|source| {
let path = source
.storage_location(&mut gix_path::env::var)
.and_then(|p| p.is_file().then_some(p));
Metadata {
path,
source: *source,
level: 0,
trust: gix_sec::Trust::Full,
}
.into()
});
let home = gix_path::env::home_dir();
let options = init::Options {
includes: init::includes::Options::follow_without_conditional(home.as_deref()),
..Default::default()
};
File::from_paths_metadata(metas, options).map(Option::unwrap_or_default)
}
pub fn from_environment_overrides() -> ExnResult<File> {
let home = gix_path::env::home_dir();
let options = init::Options {
includes: init::includes::Options::follow_without_conditional(home.as_deref()),
..Default::default()
};
File::from_env(options).map(Option::unwrap_or_default)
}
}
impl File {
pub fn from_git_dir(dir: std::path::PathBuf) -> ExnMessageResult<File> {
use gix_error::{ResultExt, message};
let (mut local, git_dir) = {
let source = Source::Local;
let mut path = dir;
path.push(
source
.storage_location(&mut gix_path::env::var)
.expect("location available for local"),
);
let local = Self::from_path_no_includes(path.clone(), source)
.or_raise(|| message("Could not read repository-local configuration"))?;
path.pop();
(local, path)
};
let worktree = match local.boolean("extensions.worktreeConfig") {
Ok(Some(worktree_config)) => worktree_config.then(|| {
let source = Source::Worktree;
let path = git_dir.join(
source
.storage_location(&mut gix_path::env::var)
.expect("location available for worktree"),
);
Self::from_path_no_includes(path, source)
}),
_ => None,
}
.transpose()
.or_raise(|| message("Could not read worktree configuration"))?;
let home = gix_path::env::home_dir();
let options = init::Options {
includes: init::includes::Options::follow(
path::interpolate::Context {
home_dir: home.as_deref(),
..Default::default()
},
init::includes::conditional::Context {
git_dir: Some(git_dir.as_ref()),
branch_name: None,
},
),
..Default::default()
};
let mut globals = Self::from_globals().or_raise(|| message("Could not read global configuration"))?;
globals
.resolve_includes(options)
.or_raise(|| message("Could not resolve includes in global configuration"))?;
local
.resolve_includes(options)
.or_raise(|| message("Could not resolve includes in repository-local configuration"))?;
globals
.append(local)
.or_raise(|| message("Could not append repository-local configuration"))?;
if let Some(mut worktree) = worktree {
worktree
.resolve_includes(options)
.or_raise(|| message("Could not resolve includes in worktree configuration"))?;
globals
.append(worktree)
.or_raise(|| message("Could not append worktree configuration"))?;
}
let environment =
Self::from_environment_overrides().or_raise(|| message("Could not read environment configuration"))?;
globals
.append(environment)
.or_raise(|| message("Could not append environment configuration"))?;
Ok(globals)
}
}