use std::path::PathBuf;
use crate::{
file::{init, Metadata},
path, source, File, Source,
};
impl File<'static> {
pub fn from_globals() -> Result<File<'static>, init::from_paths::Error> {
let metas = [source::Kind::System, source::Kind::Global]
.iter()
.flat_map(|kind| kind.sources())
.filter_map(|source| {
let path = source
.storage_location(&mut |name| std::env::var_os(name))
.and_then(|p| p.is_file().then_some(p))
.map(|p| p.into_owned());
Metadata {
path,
source: *source,
level: 0,
trust: git_sec::Trust::Full,
}
.into()
});
let home = std::env::var("HOME").ok().map(PathBuf::from);
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() -> Result<File<'static>, init::from_env::Error> {
let home = std::env::var("HOME").ok().map(PathBuf::from);
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<'static> {
pub fn from_git_dir(dir: impl Into<std::path::PathBuf>) -> Result<File<'static>, from_git_dir::Error> {
let (mut local, git_dir) = {
let source = Source::Local;
let mut path = dir.into();
path.push(
source
.storage_location(&mut |n| std::env::var_os(n))
.expect("location available for local"),
);
let local = Self::from_path_no_includes(&path, source)?;
path.pop();
(local, path)
};
let worktree = match local.boolean("extensions", None, "worktreeConfig") {
Some(Ok(worktree_config)) => worktree_config.then(|| {
let source = Source::Worktree;
let path = git_dir.join(
source
.storage_location(&mut |n| std::env::var_os(n))
.expect("location available for worktree"),
);
Self::from_path_no_includes(path, source)
}),
_ => None,
}
.transpose()?;
let home = std::env::var("HOME").ok().map(PathBuf::from);
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,
},
),
lossy: false,
};
let mut globals = Self::from_globals()?;
globals.resolve_includes(options)?;
local.resolve_includes(options)?;
globals.append(local);
if let Some(mut worktree) = worktree {
worktree.resolve_includes(options)?;
globals.append(worktree);
}
globals.append(Self::from_environment_overrides()?);
Ok(globals)
}
}
pub mod from_git_dir {
use crate::file::init;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
FromPaths(#[from] init::from_paths::Error),
#[error(transparent)]
FromEnv(#[from] init::from_env::Error),
#[error(transparent)]
Init(#[from] init::Error),
#[error(transparent)]
Includes(#[from] init::includes::Error),
}
}