Skip to content

Commit ee36e5b

Browse files
committed
Merge branch 'fix-790'
2 parents a69f873 + 603776e commit ee36e5b

File tree

17 files changed

+268
-203
lines changed

17 files changed

+268
-203
lines changed

Diff for: Cargo.lock

+167-179
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: gix-config/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ gix-sec = { version = "^0.6.2", path = "../gix-sec" }
2424
gix-ref = { version = "^0.27.0", path = "../gix-ref" }
2525
gix-glob = { version = "^0.5.5", path = "../gix-glob" }
2626

27+
log = "0.4.17"
2728
nom = { version = "7", default_features = false, features = [ "std" ] }
2829
memchr = "2"
2930
thiserror = "1.0.26"

Diff for: gix-config/src/file/init/comfort.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl File<'static> {
122122
branch_name: None,
123123
},
124124
),
125-
lossy: false,
125+
..Default::default()
126126
};
127127

128128
let mut globals = Self::from_globals()?;

Diff for: gix-config/src/file/init/from_paths.rs

+45-7
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ use crate::{
99
#[derive(Debug, thiserror::Error)]
1010
#[allow(missing_docs)]
1111
pub enum Error {
12-
#[error(transparent)]
13-
Io(#[from] std::io::Error),
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+
},
1417
#[error(transparent)]
1518
Init(#[from] init::Error),
1619
}
@@ -22,10 +25,22 @@ impl File<'static> {
2225
/// Note that the path will be checked for ownership to derive trust.
2326
pub fn from_path_no_includes(path: impl Into<std::path::PathBuf>, source: crate::Source) -> Result<Self, Error> {
2427
let path = path.into();
25-
let trust = gix_sec::Trust::from_path_ownership(&path)?;
28+
let trust = match gix_sec::Trust::from_path_ownership(&path) {
29+
Ok(t) => t,
30+
Err(err) => return Err(Error::Io { source: err, path }),
31+
};
2632

2733
let mut buf = Vec::new();
28-
std::io::copy(&mut std::fs::File::open(&path)?, &mut buf)?;
34+
match std::io::copy(
35+
&mut match std::fs::File::open(&path) {
36+
Ok(f) => f,
37+
Err(err) => return Err(Error::Io { source: err, path }),
38+
},
39+
&mut buf,
40+
) {
41+
Ok(_) => {}
42+
Err(err) => return Err(Error::Io { source: err, path }),
43+
}
2944

3045
Ok(File::from_bytes_owned(
3146
&mut buf,
@@ -69,14 +84,37 @@ impl File<'static> {
6984
}
7085

7186
buf.clear();
72-
std::io::copy(
87+
match std::io::copy(
7388
&mut match std::fs::File::open(&path) {
7489
Ok(f) => f,
7590
Err(err) if !err_on_non_existing_paths && err.kind() == std::io::ErrorKind::NotFound => continue,
76-
Err(err) => return Err(err.into()),
91+
Err(err) => {
92+
let err = Error::Io { source: err, path };
93+
if options.ignore_io_errors {
94+
log::warn!("ignoring: {err:#?}");
95+
continue;
96+
} else {
97+
return Err(err);
98+
}
99+
}
77100
},
78101
buf,
79-
)?;
102+
) {
103+
Ok(_) => {}
104+
Err(err) => {
105+
if options.ignore_io_errors {
106+
log::warn!(
107+
"ignoring: {:#?}",
108+
Error::Io {
109+
source: err,
110+
path: path.clone()
111+
}
112+
);
113+
} else {
114+
return Err(Error::Io { source: err, path });
115+
}
116+
}
117+
};
80118
meta.path = Some(path);
81119

82120
let config = Self::from_bytes_owned(buf, meta, options)?;

Diff for: gix-config/src/file/init/types.rs

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ pub struct Options<'a> {
2222
/// Note that doing so will degenerate [`write_to()`][crate::File::write_to()] and strip it off its comments
2323
/// and additional whitespace entirely, but will otherwise be a valid configuration file.
2424
pub lossy: bool,
25+
/// If true, any IO error happening when reading a configuration file will be ignored.
26+
///
27+
/// That way it's possible to pass multiple files and read as many as possible, to have 'something' instead of nothing.
28+
pub ignore_io_errors: bool,
2529
}
2630

2731
impl Options<'_> {

Diff for: gix-config/src/source.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ mod git {
127127
fn first_file_from_config_with_origin(source: &BStr) -> Option<&BStr> {
128128
let file = source.strip_prefix(b"file:")?;
129129
let end_pos = file.find_byte(b'\t')?;
130-
file[..end_pos].as_bstr().into()
130+
file[..end_pos].trim_with(|c| c == '"').as_bstr().into()
131131
}
132132

133133
#[cfg(test)]
@@ -138,6 +138,7 @@ mod git {
138138
let win_msys =
139139
"file:C:/git-sdk-64/etc/gitconfig core.symlinks=false\r\nfile:C:/git-sdk-64/etc/gitconfig core.autocrlf=true";
140140
let win_cmd = "file:C:/Program Files/Git/etc/gitconfig diff.astextplain.textconv=astextplain\r\nfile:C:/Program Files/Git/etc/gitconfig filter.lfs.clean=gix-lfs clean -- %f\r\n";
141+
let win_msys_old = "file:\"C:\\ProgramData/Git/config\" diff.astextplain.textconv=astextplain\r\nfile:\"C:\\ProgramData/Git/config\" filter.lfs.clean=git-lfs clean -- %f\r\n";
141142
let linux = "file:/home/parallels/.gitconfig core.excludesfile=~/.gitignore\n";
142143
let bogus = "something unexpected";
143144
let empty = "";
@@ -148,6 +149,7 @@ mod git {
148149
Some("/Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig"),
149150
),
150151
(win_msys, Some("C:/git-sdk-64/etc/gitconfig")),
152+
(win_msys_old, Some("C:\\ProgramData/Git/config")),
151153
(win_cmd, Some("C:/Program Files/Git/etc/gitconfig")),
152154
(linux, Some("/home/parallels/.gitconfig")),
153155
(bogus, None),

Diff for: gix-config/tests/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ gix = { path = "../../gix" }
2828
gix-ref = { path = "../../gix-ref" }
2929
gix-path = { path = "../../gix-path" }
3030
gix-sec = { path = "../../gix-sec" }
31-
serial_test = "1.0.0"
31+
serial_test = { version = "1.0.0", default-features = false }
3232
serde_derive = "1.0"
3333
criterion = "0.4.0"
3434
tempfile = "3.2.0"

Diff for: gix-config/tests/file/init/from_paths/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ mod from_path_no_includes {
1818

1919
let err = gix_config::File::from_path_no_includes(config_path, gix_config::Source::Local).unwrap_err();
2020
assert!(
21-
matches!(err, gix_config::file::init::from_paths::Error::Io(io_error) if io_error.kind() == std::io::ErrorKind::NotFound)
21+
matches!(err, gix_config::file::init::from_paths::Error::Io{source: io_error, ..} if io_error.kind() == std::io::ErrorKind::NotFound)
2222
);
2323
}
2424

Diff for: gix-discover/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ dunce = "1.0.3"
2626

2727
[dev-dependencies]
2828
gix-testtools = { path = "../tests/tools" }
29-
serial_test = "1.0.0"
29+
serial_test = { version = "1.0.0", default-features = false }
3030
is_ci = "1.1.1"
3131

3232
[target.'cfg(target_os = "macos")'.dev-dependencies]

Diff for: gix-prompt/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ nix = { version = "0.26.1", default-features = false, features = ["term"] }
2424

2525
[dev-dependencies]
2626
gix-testtools = { path = "../tests/tools"}
27-
serial_test = "1.0.0"
27+
serial_test = { version = "1.0.0", default-features = false }
2828
expectrl = "0.6.0"

Diff for: gix/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ gix-testtools = { path = "../tests/tools" }
172172
is_ci = "1.1.1"
173173
anyhow = "1"
174174
walkdir = "2.3.2"
175-
serial_test = "1.0.0"
175+
serial_test = { version = "1.0.0", default-features = false }
176176
async-std = { version = "1.12.0", features = ["attributes"] }
177177

178178
[package.metadata.docs.rs]

Diff for: gix/src/config/cache/incubate.rs

+29-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ impl StageOne {
3030
gix_config::Source::Local,
3131
git_dir_trust,
3232
lossy,
33+
lenient,
3334
)?;
3435

3536
// Note that we assume the repo is bare by default unless we are told otherwise. This is relevant if
@@ -64,6 +65,7 @@ impl StageOne {
6465
gix_config::Source::Worktree,
6566
git_dir_trust,
6667
lossy,
68+
lenient,
6769
)?;
6870
config.append(worktree_config);
6971
};
@@ -86,24 +88,47 @@ fn load_config(
8688
source: gix_config::Source,
8789
git_dir_trust: gix_sec::Trust,
8890
lossy: Option<bool>,
91+
lenient: bool,
8992
) -> Result<gix_config::File<'static>, Error> {
90-
buf.clear();
9193
let metadata = gix_config::file::Metadata::from(source)
9294
.at(&config_path)
9395
.with(git_dir_trust);
9496
let mut file = match std::fs::File::open(&config_path) {
9597
Ok(f) => f,
9698
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(gix_config::File::new(metadata)),
97-
Err(err) => return Err(err.into()),
99+
Err(err) => {
100+
let err = Error::Io {
101+
source: err,
102+
path: config_path,
103+
};
104+
if lenient {
105+
log::warn!("ignoring: {err:#?}");
106+
return Ok(gix_config::File::new(metadata));
107+
} else {
108+
return Err(err);
109+
}
110+
}
111+
};
112+
113+
buf.clear();
114+
if let Err(err) = std::io::copy(&mut file, buf) {
115+
let err = Error::Io {
116+
source: err,
117+
path: config_path,
118+
};
119+
if lenient {
120+
log::warn!("ignoring: {err:#?}");
121+
} else {
122+
return Err(err);
123+
}
98124
};
99-
std::io::copy(&mut file, buf)?;
100125

101126
let config = gix_config::File::from_bytes_owned(
102127
buf,
103128
metadata,
104129
gix_config::file::init::Options {
105130
includes: gix_config::file::includes::Options::no_follow(),
106-
..util::base_options(lossy)
131+
..util::base_options(lossy, lenient)
107132
},
108133
)?;
109134

Diff for: gix/src/config/cache/init.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl Cache {
6565
} else {
6666
gix_config::file::includes::Options::no_follow()
6767
},
68-
..util::base_options(lossy)
68+
..util::base_options(lossy, lenient_config)
6969
};
7070

7171
let config = {
@@ -118,7 +118,7 @@ impl Cache {
118118
)
119119
.map_err(|err| match err {
120120
gix_config::file::init::from_paths::Error::Init(err) => Error::from(err),
121-
gix_config::file::init::from_paths::Error::Io(err) => err.into(),
121+
gix_config::file::init::from_paths::Error::Io { source, path } => Error::Io { source, path },
122122
})?
123123
.unwrap_or_default();
124124

Diff for: gix/src/config/cache/util.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ pub(crate) fn interpolate_context<'a>(
1717
}
1818
}
1919

20-
pub(crate) fn base_options(lossy: Option<bool>) -> gix_config::file::init::Options<'static> {
20+
pub(crate) fn base_options(lossy: Option<bool>, lenient: bool) -> gix_config::file::init::Options<'static> {
2121
gix_config::file::init::Options {
2222
lossy: lossy.unwrap_or(!cfg!(debug_assertions)),
23+
ignore_io_errors: lenient,
2324
..Default::default()
2425
}
2526
}

Diff for: gix/src/config/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,11 @@ pub enum Error {
6262
UnsupportedObjectFormat { name: BString },
6363
#[error(transparent)]
6464
CoreAbbrev(#[from] abbrev::Error),
65-
#[error("Could not read configuration file")]
66-
Io(#[from] std::io::Error),
65+
#[error("Could not read configuration file at \"{}\"", path.display())]
66+
Io {
67+
source: std::io::Error,
68+
path: std::path::PathBuf,
69+
},
6770
#[error(transparent)]
6871
Init(#[from] gix_config::file::init::Error),
6972
#[error(transparent)]

Diff for: gix/src/open/options.rs

+3
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ impl Options {
134134
///
135135
/// This is recommended for all applications that prefer correctness over usability.
136136
/// `git` itself defaults to strict configuration mode, flagging incorrect configuration immediately.
137+
///
138+
/// Failure to read configuration files due to IO errors will also be a hard error if this mode is enabled, otherwise
139+
/// these errors will merely be logged.
137140
pub fn strict_config(mut self, toggle: bool) -> Self {
138141
self.lenient_config = !toggle;
139142
self

Diff for: src/plumbing/options/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub struct Args {
3838
#[clap(long, conflicts_with("verbose"))]
3939
pub progress: bool,
4040

41-
/// Don't default malformed configuration flags, but show an error instead.
41+
/// Don't default malformed configuration flags, but show an error instead. Ignore IO errors as well.
4242
///
4343
/// Note that some subcommands use strict mode by default.
4444
// TODO: needs a 'lenient' mutually exclusive counterpart. Opens the gate to auto-verbose some commands, and add --no-verbose

0 commit comments

Comments
 (0)