]> git.proxmox.com Git - rustc.git/blame - vendor/gix-config/src/file/init/from_paths.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / gix-config / src / file / init / from_paths.rs
CommitLineData
0a29b90c
FG
1use std::collections::BTreeSet;
2
3use crate::{
4 file::{init, init::Options, Metadata},
5 File,
6};
7
8/// The error returned by [`File::from_paths_metadata()`] and [`File::from_path_no_includes()`].
9#[derive(Debug, thiserror::Error)]
10#[allow(missing_docs)]
11pub enum Error {
49aad941
FG
12 #[error("The configuration file at \"{}\" could not be read", path.display())]
13 Io {
14 source: std::io::Error,
15 path: std::path::PathBuf,
16 },
0a29b90c
FG
17 #[error(transparent)]
18 Init(#[from] init::Error),
19}
20
21/// Instantiation from one or more paths
22impl File<'static> {
23 /// Load the single file at `path` with `source` without following include directives.
24 ///
25 /// Note that the path will be checked for ownership to derive trust.
781aab86 26 pub fn from_path_no_includes(path: std::path::PathBuf, source: crate::Source) -> Result<Self, Error> {
49aad941
FG
27 let trust = match gix_sec::Trust::from_path_ownership(&path) {
28 Ok(t) => t,
29 Err(err) => return Err(Error::Io { source: err, path }),
30 };
0a29b90c
FG
31
32 let mut buf = Vec::new();
49aad941
FG
33 match std::io::copy(
34 &mut match std::fs::File::open(&path) {
35 Ok(f) => f,
36 Err(err) => return Err(Error::Io { source: err, path }),
37 },
38 &mut buf,
39 ) {
40 Ok(_) => {}
41 Err(err) => return Err(Error::Io { source: err, path }),
42 }
0a29b90c
FG
43
44 Ok(File::from_bytes_owned(
45 &mut buf,
46 Metadata::from(source).at(path).with(trust),
47 Default::default(),
48 )?)
49 }
50
781aab86 51 /// Constructs a `git-config` file from the provided metadata, which must include a path to read from or be ignored.
0a29b90c
FG
52 /// Returns `Ok(None)` if there was not a single input path provided, which is a possibility due to
53 /// [`Metadata::path`] being an `Option`.
54 /// If an input path doesn't exist, the entire operation will abort. See [`from_paths_metadata_buf()`][Self::from_paths_metadata_buf()]
55 /// for a more powerful version of this method.
56 pub fn from_paths_metadata(
57 path_meta: impl IntoIterator<Item = impl Into<Metadata>>,
58 options: Options<'_>,
59 ) -> Result<Option<Self>, Error> {
60 let mut buf = Vec::with_capacity(512);
61 let err_on_nonexisting_paths = true;
781aab86
FG
62 Self::from_paths_metadata_buf(
63 &mut path_meta.into_iter().map(Into::into),
64 &mut buf,
65 err_on_nonexisting_paths,
66 options,
67 )
0a29b90c
FG
68 }
69
fe692bf9 70 /// Like [`from_paths_metadata()`][Self::from_paths_metadata()], but will use `buf` to temporarily store the config file
0a29b90c
FG
71 /// contents for parsing instead of allocating an own buffer.
72 ///
73 /// If `err_on_nonexisting_paths` is false, instead of aborting with error, we will continue to the next path instead.
74 pub fn from_paths_metadata_buf(
781aab86 75 path_meta: &mut dyn Iterator<Item = Metadata>,
0a29b90c
FG
76 buf: &mut Vec<u8>,
77 err_on_non_existing_paths: bool,
78 options: Options<'_>,
79 ) -> Result<Option<Self>, Error> {
80 let mut target = None;
81 let mut seen = BTreeSet::default();
781aab86 82 for (path, mut meta) in path_meta.filter_map(|mut meta| meta.path.take().map(|p| (p, meta))) {
0a29b90c
FG
83 if !seen.insert(path.clone()) {
84 continue;
85 }
86
87 buf.clear();
49aad941 88 match std::io::copy(
0a29b90c
FG
89 &mut match std::fs::File::open(&path) {
90 Ok(f) => f,
91 Err(err) if !err_on_non_existing_paths && err.kind() == std::io::ErrorKind::NotFound => continue,
49aad941
FG
92 Err(err) => {
93 let err = Error::Io { source: err, path };
94 if options.ignore_io_errors {
781aab86 95 gix_features::trace::warn!("ignoring: {err:#?}");
49aad941
FG
96 continue;
97 } else {
98 return Err(err);
99 }
100 }
0a29b90c
FG
101 },
102 buf,
49aad941
FG
103 ) {
104 Ok(_) => {}
105 Err(err) => {
106 if options.ignore_io_errors {
781aab86 107 gix_features::trace::warn!(
49aad941
FG
108 "ignoring: {:#?}",
109 Error::Io {
110 source: err,
111 path: path.clone()
112 }
113 );
114 buf.clear();
115 } else {
116 return Err(Error::Io { source: err, path });
117 }
118 }
119 };
0a29b90c
FG
120 meta.path = Some(path);
121
122 let config = Self::from_bytes_owned(buf, meta, options)?;
123 match &mut target {
124 None => {
125 target = Some(config);
126 }
127 Some(target) => {
128 target.append(config);
129 }
130 }
131 }
132 Ok(target)
133 }
134}