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