gix_config/file/init/
from_paths.rs1use std::collections::BTreeSet;
2
3use gix_error::ExnMessageResult;
4
5use crate::{
6 File,
7 file::{Metadata, init::Options},
8};
9
10impl File {
12 pub fn from_path_no_includes(path: std::path::PathBuf, source: crate::Source) -> ExnMessageResult<Self> {
16 use gix_error::{ResultExt, message};
17 let trust = gix_sec::Trust::from_path_ownership(&path).or_raise(|| {
18 message!(
19 "The configuration file at \"{}\" could not be inspected",
20 path.display()
21 )
22 })?;
23
24 let mut buf = Vec::new();
25 let mut file = std::fs::File::open(&path)
26 .or_raise(|| message!("The configuration file at \"{}\" could not be read", path.display()))?;
27 std::io::copy(&mut file, &mut buf)
28 .or_raise(|| message!("The configuration file at \"{}\" could not be read", path.display()))?;
29
30 File::from_bytes_owned(
31 &mut buf,
32 Metadata::from(source).at(path).with(trust),
33 Default::default(),
34 )
35 .or_raise(|| message("Could not initialize configuration from a path"))
36 }
37
38 pub fn from_paths_metadata(
44 path_meta: impl IntoIterator<Item = impl Into<Metadata>>,
45 options: Options<'_>,
46 ) -> ExnMessageResult<Option<Self>> {
47 let mut buf = Vec::with_capacity(512);
48 let err_on_nonexisting_paths = true;
49 Self::from_paths_metadata_buf(
50 &mut path_meta.into_iter().map(Into::into),
51 &mut buf,
52 err_on_nonexisting_paths,
53 options,
54 )
55 }
56
57 pub fn from_paths_metadata_buf(
62 path_meta: &mut dyn Iterator<Item = Metadata>,
63 buf: &mut Vec<u8>,
64 err_on_non_existing_paths: bool,
65 options: Options<'_>,
66 ) -> ExnMessageResult<Option<Self>> {
67 use gix_error::{ErrorExt, ResultExt, message};
68 let mut target = None;
69 let mut seen = BTreeSet::default();
70 for (path, mut meta) in path_meta.filter_map(|mut meta| meta.path.take().map(|p| (p, meta))) {
71 if !seen.insert(path.clone()) {
72 continue;
73 }
74
75 buf.clear();
76 match std::io::copy(
77 &mut match std::fs::File::open(&path) {
78 Ok(f) => f,
79 Err(err) if !err_on_non_existing_paths && err.kind() == std::io::ErrorKind::NotFound => continue,
80 Err(err) => {
81 let err = err.and_raise(message!(
82 "The configuration file at \"{}\" could not be read",
83 path.display()
84 ));
85 if options.ignore_io_errors {
86 gix_features::trace::warn!("ignoring: {err:#?}");
87 continue;
88 } else {
89 return Err(err);
90 }
91 }
92 },
93 buf,
94 ) {
95 Ok(_) => {}
96 Err(err) => {
97 let err = err.and_raise(message!(
98 "The configuration file at \"{}\" could not be read",
99 path.display()
100 ));
101 if options.ignore_io_errors {
102 gix_features::trace::warn!("ignoring: {err:#?}");
103 buf.clear();
104 } else {
105 return Err(err);
106 }
107 }
108 }
109 meta.path = Some(path);
110
111 let config = Self::from_bytes_owned(buf, meta, options)
112 .or_raise(|| message("Could not initialize configuration from a path"))?;
113 match &mut target {
114 None => {
115 target = Some(config);
116 }
117 Some(target) => {
118 target
119 .append(config)
120 .or_raise(|| message("Could not append configuration from a path"))?;
121 }
122 }
123 }
124 Ok(target)
125 }
126}