gix_config/file/init/
comfort.rs1use crate::{
2 File, Source,
3 file::{Metadata, init},
4 path, source,
5};
6use gix_error::{ExnMessageResult, ExnResult};
7
8impl File {
18 pub fn from_globals() -> ExnMessageResult<File> {
28 let metas = [
29 source::Kind::GitInstallation,
30 source::Kind::System,
31 source::Kind::Global,
32 ]
33 .iter()
34 .flat_map(|kind| kind.sources())
35 .filter_map(|source| {
36 let path = source
37 .storage_location(&mut gix_path::env::var)
38 .and_then(|p| p.is_file().then_some(p));
39
40 Metadata {
41 path,
42 source: *source,
43 level: 0,
44 trust: gix_sec::Trust::Full,
45 }
46 .into()
47 });
48
49 let home = gix_path::env::home_dir();
50 let options = init::Options {
51 includes: init::includes::Options::follow_without_conditional(home.as_deref()),
52 ..Default::default()
53 };
54 File::from_paths_metadata(metas, options).map(Option::unwrap_or_default)
55 }
56
57 pub fn from_environment_overrides() -> ExnResult<File> {
65 let home = gix_path::env::home_dir();
66 let options = init::Options {
67 includes: init::includes::Options::follow_without_conditional(home.as_deref()),
68 ..Default::default()
69 };
70
71 File::from_env(options).map(Option::unwrap_or_default)
72 }
73}
74
75impl File {
77 pub fn from_git_dir(dir: std::path::PathBuf) -> ExnMessageResult<File> {
89 use gix_error::{ResultExt, message};
90
91 let (mut local, git_dir) = {
92 let source = Source::Local;
93 let mut path = dir;
94 path.push(
95 source
96 .storage_location(&mut gix_path::env::var)
97 .expect("location available for local"),
98 );
99 let local = Self::from_path_no_includes(path.clone(), source)
100 .or_raise(|| message("Could not read repository-local configuration"))?;
101 path.pop();
102 (local, path)
103 };
104
105 let worktree = match local.boolean("extensions.worktreeConfig") {
106 Ok(Some(worktree_config)) => worktree_config.then(|| {
107 let source = Source::Worktree;
108 let path = git_dir.join(
109 source
110 .storage_location(&mut gix_path::env::var)
111 .expect("location available for worktree"),
112 );
113 Self::from_path_no_includes(path, source)
114 }),
115 _ => None,
116 }
117 .transpose()
118 .or_raise(|| message("Could not read worktree configuration"))?;
119
120 let home = gix_path::env::home_dir();
121 let options = init::Options {
122 includes: init::includes::Options::follow(
123 path::interpolate::Context {
124 home_dir: home.as_deref(),
125 ..Default::default()
126 },
127 init::includes::conditional::Context {
128 git_dir: Some(git_dir.as_ref()),
129 branch_name: None,
130 },
131 ),
132 ..Default::default()
133 };
134
135 let mut globals = Self::from_globals().or_raise(|| message("Could not read global configuration"))?;
136 globals
137 .resolve_includes(options)
138 .or_raise(|| message("Could not resolve includes in global configuration"))?;
139 local
140 .resolve_includes(options)
141 .or_raise(|| message("Could not resolve includes in repository-local configuration"))?;
142
143 globals
144 .append(local)
145 .or_raise(|| message("Could not append repository-local configuration"))?;
146 if let Some(mut worktree) = worktree {
147 worktree
148 .resolve_includes(options)
149 .or_raise(|| message("Could not resolve includes in worktree configuration"))?;
150 globals
151 .append(worktree)
152 .or_raise(|| message("Could not append worktree configuration"))?;
153 }
154 let environment =
155 Self::from_environment_overrides().or_raise(|| message("Could not read environment configuration"))?;
156 globals
157 .append(environment)
158 .or_raise(|| message("Could not append environment configuration"))?;
159
160 Ok(globals)
161 }
162}