mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-07-26 01:31:57 -07:00
ignore: respect XDG_CONFIG_DIR/git/config
This commit updates the logic for finding the value of git's `core.excludesFile` configuration parameter. Namely, we now check `$XDG_CONFIG_DIR/git/config` in addition to `$HOME/.gitconfig` (where the latter overrules the former on a knob-by-knob basis). Fixes #995
This commit is contained in:
@@ -109,6 +109,8 @@ Bug fixes:
|
|||||||
* [BUG #988](https://github.com/BurntSushi/ripgrep/issues/988):
|
* [BUG #988](https://github.com/BurntSushi/ripgrep/issues/988):
|
||||||
Fix a bug in the `ignore` crate that prevented the use of explicit ignore
|
Fix a bug in the `ignore` crate that prevented the use of explicit ignore
|
||||||
files after disabling all other ignore rules.
|
files after disabling all other ignore rules.
|
||||||
|
* [BUG #995](https://github.com/BurntSushi/ripgrep/issues/995):
|
||||||
|
Respect `$XDG_CONFIG_DIR/git/config` for detecting `core.excludesFile`.
|
||||||
|
|
||||||
|
|
||||||
0.8.1 (2018-02-20)
|
0.8.1 (2018-02-20)
|
||||||
|
@@ -515,16 +515,27 @@ impl GitignoreBuilder {
|
|||||||
///
|
///
|
||||||
/// Note that the file path returned may not exist.
|
/// Note that the file path returned may not exist.
|
||||||
fn gitconfig_excludes_path() -> Option<PathBuf> {
|
fn gitconfig_excludes_path() -> Option<PathBuf> {
|
||||||
gitconfig_contents()
|
// git supports $HOME/.gitconfig and $XDG_CONFIG_DIR/git/config. Notably,
|
||||||
.and_then(|data| parse_excludes_file(&data))
|
// both can be active at the same time, where $HOME/.gitconfig takes
|
||||||
.or_else(excludes_file_default)
|
// precedent. So if $HOME/.gitconfig defines a `core.excludesFile`, then
|
||||||
|
// we're done.
|
||||||
|
match gitconfig_home_contents().and_then(|x| parse_excludes_file(&x)) {
|
||||||
|
Some(path) => return Some(path),
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
match gitconfig_xdg_contents().and_then(|x| parse_excludes_file(&x)) {
|
||||||
|
Some(path) => return Some(path),
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
excludes_file_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the file contents of git's global config file, if one exists.
|
/// Returns the file contents of git's global config file, if one exists, in
|
||||||
fn gitconfig_contents() -> Option<Vec<u8>> {
|
/// the user's home directory.
|
||||||
let home = match env::var_os("HOME") {
|
fn gitconfig_home_contents() -> Option<Vec<u8>> {
|
||||||
|
let home = match home_dir() {
|
||||||
None => return None,
|
None => return None,
|
||||||
Some(home) => PathBuf::from(home),
|
Some(home) => home,
|
||||||
};
|
};
|
||||||
let mut file = match File::open(home.join(".gitconfig")) {
|
let mut file = match File::open(home.join(".gitconfig")) {
|
||||||
Err(_) => return None,
|
Err(_) => return None,
|
||||||
@@ -534,17 +545,28 @@ fn gitconfig_contents() -> Option<Vec<u8>> {
|
|||||||
file.read_to_end(&mut contents).ok().map(|_| contents)
|
file.read_to_end(&mut contents).ok().map(|_| contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the file contents of git's global config file, if one exists, in
|
||||||
|
/// the user's XDG_CONFIG_DIR directory.
|
||||||
|
fn gitconfig_xdg_contents() -> Option<Vec<u8>> {
|
||||||
|
let path = env::var_os("XDG_CONFIG_HOME")
|
||||||
|
.and_then(|x| if x.is_empty() { None } else { Some(PathBuf::from(x)) })
|
||||||
|
.or_else(|| home_dir().map(|p| p.join(".config")))
|
||||||
|
.map(|x| x.join("git/config"));
|
||||||
|
let mut file = match path.and_then(|p| File::open(p).ok()) {
|
||||||
|
None => return None,
|
||||||
|
Some(file) => io::BufReader::new(file),
|
||||||
|
};
|
||||||
|
let mut contents = vec![];
|
||||||
|
file.read_to_end(&mut contents).ok().map(|_| contents)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the default file path for a global .gitignore file.
|
/// Returns the default file path for a global .gitignore file.
|
||||||
///
|
///
|
||||||
/// Specifically, this respects XDG_CONFIG_HOME.
|
/// Specifically, this respects XDG_CONFIG_HOME.
|
||||||
fn excludes_file_default() -> Option<PathBuf> {
|
fn excludes_file_default() -> Option<PathBuf> {
|
||||||
// We're fine with using env::home_dir for now. Its bugs are, IMO, pretty
|
|
||||||
// minor corner cases. We should still probably eventually migrate to
|
|
||||||
// the `dirs` crate to get a proper implementation.
|
|
||||||
#![allow(deprecated)]
|
|
||||||
env::var_os("XDG_CONFIG_HOME")
|
env::var_os("XDG_CONFIG_HOME")
|
||||||
.and_then(|x| if x.is_empty() { None } else { Some(PathBuf::from(x)) })
|
.and_then(|x| if x.is_empty() { None } else { Some(PathBuf::from(x)) })
|
||||||
.or_else(|| env::home_dir().map(|p| p.join(".config")))
|
.or_else(|| home_dir().map(|p| p.join(".config")))
|
||||||
.map(|x| x.join("git/ignore"))
|
.map(|x| x.join("git/ignore"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,7 +578,8 @@ fn parse_excludes_file(data: &[u8]) -> Option<PathBuf> {
|
|||||||
// a full INI parser. Yuck.
|
// a full INI parser. Yuck.
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref RE: Regex = Regex::new(
|
static ref RE: Regex = Regex::new(
|
||||||
r"(?ium)^\s*excludesfile\s*=\s*(.+)\s*$").unwrap();
|
r"(?im)^\s*excludesfile\s*=\s*(.+)\s*$"
|
||||||
|
).unwrap();
|
||||||
};
|
};
|
||||||
let caps = match RE.captures(data) {
|
let caps = match RE.captures(data) {
|
||||||
None => return None,
|
None => return None,
|
||||||
@@ -567,13 +590,22 @@ fn parse_excludes_file(data: &[u8]) -> Option<PathBuf> {
|
|||||||
|
|
||||||
/// Expands ~ in file paths to the value of $HOME.
|
/// Expands ~ in file paths to the value of $HOME.
|
||||||
fn expand_tilde(path: &str) -> String {
|
fn expand_tilde(path: &str) -> String {
|
||||||
let home = match env::var("HOME") {
|
let home = match home_dir() {
|
||||||
Err(_) => return path.to_string(),
|
None => return path.to_string(),
|
||||||
Ok(home) => home,
|
Some(home) => home.to_string_lossy().into_owned(),
|
||||||
};
|
};
|
||||||
path.replace("~", &home)
|
path.replace("~", &home)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the location of the user's home directory.
|
||||||
|
fn home_dir() -> Option<PathBuf> {
|
||||||
|
// We're fine with using env::home_dir for now. Its bugs are, IMO, pretty
|
||||||
|
// minor corner cases. We should still probably eventually migrate to
|
||||||
|
// the `dirs` crate to get a proper implementation.
|
||||||
|
#![allow(deprecated)]
|
||||||
|
env::home_dir()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
Reference in New Issue
Block a user