Skip to content

Commit

Permalink
Merge branch 'fix-790'
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Mar 26, 2023
2 parents a69f873 + 603776e commit ee36e5b
Show file tree
Hide file tree
Showing 17 changed files with 268 additions and 203 deletions.
346 changes: 167 additions & 179 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions gix-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ gix-sec = { version = "^0.6.2", path = "../gix-sec" }
gix-ref = { version = "^0.27.0", path = "../gix-ref" }
gix-glob = { version = "^0.5.5", path = "../gix-glob" }

log = "0.4.17"
nom = { version = "7", default_features = false, features = [ "std" ] }
memchr = "2"
thiserror = "1.0.26"
Expand Down
2 changes: 1 addition & 1 deletion gix-config/src/file/init/comfort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl File<'static> {
branch_name: None,
},
),
lossy: false,
..Default::default()
};

let mut globals = Self::from_globals()?;
Expand Down
52 changes: 45 additions & 7 deletions gix-config/src/file/init/from_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ use crate::{
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
Io(#[from] std::io::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),
}
Expand All @@ -22,10 +25,22 @@ impl File<'static> {
/// Note that the path will be checked for ownership to derive trust.
pub fn from_path_no_includes(path: impl Into<std::path::PathBuf>, source: crate::Source) -> Result<Self, Error> {
let path = path.into();
let trust = gix_sec::Trust::from_path_ownership(&path)?;
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();
std::io::copy(&mut std::fs::File::open(&path)?, &mut buf)?;
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,
Expand Down Expand Up @@ -69,14 +84,37 @@ impl File<'static> {
}

buf.clear();
std::io::copy(
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) => return Err(err.into()),
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)?;
Expand Down
4 changes: 4 additions & 0 deletions gix-config/src/file/init/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ pub struct Options<'a> {
/// Note that doing so will degenerate [`write_to()`][crate::File::write_to()] and strip it off its comments
/// and additional whitespace entirely, but will otherwise be a valid configuration file.
pub lossy: bool,
/// If true, any IO error happening when reading a configuration file will be ignored.
///
/// That way it's possible to pass multiple files and read as many as possible, to have 'something' instead of nothing.
pub ignore_io_errors: bool,
}

impl Options<'_> {
Expand Down
4 changes: 3 additions & 1 deletion gix-config/src/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ mod git {
fn first_file_from_config_with_origin(source: &BStr) -> Option<&BStr> {
let file = source.strip_prefix(b"file:")?;
let end_pos = file.find_byte(b'\t')?;
file[..end_pos].as_bstr().into()
file[..end_pos].trim_with(|c| c == '"').as_bstr().into()
}

#[cfg(test)]
Expand All @@ -138,6 +138,7 @@ mod git {
let win_msys =
"file:C:/git-sdk-64/etc/gitconfig core.symlinks=false\r\nfile:C:/git-sdk-64/etc/gitconfig core.autocrlf=true";
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";
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";
let linux = "file:/home/parallels/.gitconfig core.excludesfile=~/.gitignore\n";
let bogus = "something unexpected";
let empty = "";
Expand All @@ -148,6 +149,7 @@ mod git {
Some("/Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig"),
),
(win_msys, Some("C:/git-sdk-64/etc/gitconfig")),
(win_msys_old, Some("C:\\ProgramData/Git/config")),
(win_cmd, Some("C:/Program Files/Git/etc/gitconfig")),
(linux, Some("/home/parallels/.gitconfig")),
(bogus, None),
Expand Down
2 changes: 1 addition & 1 deletion gix-config/tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ gix = { path = "../../gix" }
gix-ref = { path = "../../gix-ref" }
gix-path = { path = "../../gix-path" }
gix-sec = { path = "../../gix-sec" }
serial_test = "1.0.0"
serial_test = { version = "1.0.0", default-features = false }
serde_derive = "1.0"
criterion = "0.4.0"
tempfile = "3.2.0"
Expand Down
2 changes: 1 addition & 1 deletion gix-config/tests/file/init/from_paths/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ mod from_path_no_includes {

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

Expand Down
2 changes: 1 addition & 1 deletion gix-discover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dunce = "1.0.3"

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

[target.'cfg(target_os = "macos")'.dev-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion gix-prompt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ nix = { version = "0.26.1", default-features = false, features = ["term"] }

[dev-dependencies]
gix-testtools = { path = "../tests/tools"}
serial_test = "1.0.0"
serial_test = { version = "1.0.0", default-features = false }
expectrl = "0.6.0"
2 changes: 1 addition & 1 deletion gix/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ gix-testtools = { path = "../tests/tools" }
is_ci = "1.1.1"
anyhow = "1"
walkdir = "2.3.2"
serial_test = "1.0.0"
serial_test = { version = "1.0.0", default-features = false }
async-std = { version = "1.12.0", features = ["attributes"] }

[package.metadata.docs.rs]
Expand Down
33 changes: 29 additions & 4 deletions gix/src/config/cache/incubate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ impl StageOne {
gix_config::Source::Local,
git_dir_trust,
lossy,
lenient,
)?;

// Note that we assume the repo is bare by default unless we are told otherwise. This is relevant if
Expand Down Expand Up @@ -64,6 +65,7 @@ impl StageOne {
gix_config::Source::Worktree,
git_dir_trust,
lossy,
lenient,
)?;
config.append(worktree_config);
};
Expand All @@ -86,24 +88,47 @@ fn load_config(
source: gix_config::Source,
git_dir_trust: gix_sec::Trust,
lossy: Option<bool>,
lenient: bool,
) -> Result<gix_config::File<'static>, Error> {
buf.clear();
let metadata = gix_config::file::Metadata::from(source)
.at(&config_path)
.with(git_dir_trust);
let mut file = match std::fs::File::open(&config_path) {
Ok(f) => f,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(gix_config::File::new(metadata)),
Err(err) => return Err(err.into()),
Err(err) => {
let err = Error::Io {
source: err,
path: config_path,
};
if lenient {
log::warn!("ignoring: {err:#?}");
return Ok(gix_config::File::new(metadata));
} else {
return Err(err);
}
}
};

buf.clear();
if let Err(err) = std::io::copy(&mut file, buf) {
let err = Error::Io {
source: err,
path: config_path,
};
if lenient {
log::warn!("ignoring: {err:#?}");
} else {
return Err(err);
}
};
std::io::copy(&mut file, buf)?;

let config = gix_config::File::from_bytes_owned(
buf,
metadata,
gix_config::file::init::Options {
includes: gix_config::file::includes::Options::no_follow(),
..util::base_options(lossy)
..util::base_options(lossy, lenient)
},
)?;

Expand Down
4 changes: 2 additions & 2 deletions gix/src/config/cache/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl Cache {
} else {
gix_config::file::includes::Options::no_follow()
},
..util::base_options(lossy)
..util::base_options(lossy, lenient_config)
};

let config = {
Expand Down Expand Up @@ -118,7 +118,7 @@ impl Cache {
)
.map_err(|err| match err {
gix_config::file::init::from_paths::Error::Init(err) => Error::from(err),
gix_config::file::init::from_paths::Error::Io(err) => err.into(),
gix_config::file::init::from_paths::Error::Io { source, path } => Error::Io { source, path },
})?
.unwrap_or_default();

Expand Down
3 changes: 2 additions & 1 deletion gix/src/config/cache/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ pub(crate) fn interpolate_context<'a>(
}
}

pub(crate) fn base_options(lossy: Option<bool>) -> gix_config::file::init::Options<'static> {
pub(crate) fn base_options(lossy: Option<bool>, lenient: bool) -> gix_config::file::init::Options<'static> {
gix_config::file::init::Options {
lossy: lossy.unwrap_or(!cfg!(debug_assertions)),
ignore_io_errors: lenient,
..Default::default()
}
}
Expand Down
7 changes: 5 additions & 2 deletions gix/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ pub enum Error {
UnsupportedObjectFormat { name: BString },
#[error(transparent)]
CoreAbbrev(#[from] abbrev::Error),
#[error("Could not read configuration file")]
Io(#[from] std::io::Error),
#[error("Could not read configuration file at \"{}\"", path.display())]
Io {
source: std::io::Error,
path: std::path::PathBuf,
},
#[error(transparent)]
Init(#[from] gix_config::file::init::Error),
#[error(transparent)]
Expand Down
3 changes: 3 additions & 0 deletions gix/src/open/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ impl Options {
///
/// This is recommended for all applications that prefer correctness over usability.
/// `git` itself defaults to strict configuration mode, flagging incorrect configuration immediately.
///
/// Failure to read configuration files due to IO errors will also be a hard error if this mode is enabled, otherwise
/// these errors will merely be logged.
pub fn strict_config(mut self, toggle: bool) -> Self {
self.lenient_config = !toggle;
self
Expand Down
2 changes: 1 addition & 1 deletion src/plumbing/options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub struct Args {
#[clap(long, conflicts_with("verbose"))]
pub progress: bool,

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

0 comments on commit ee36e5b

Please sign in to comment.