D7582: rust-configparser: run rustfmt
indygreg (Gregory Szorc)
phabricator at mercurial-scm.org
Sat Dec 7 22:58:15 UTC 2019
indygreg created this revision.
Herald added subscribers: mercurial-devel, mjpieters, kevincox, durin42.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
The vendored code doesn't follow rustfmt's conventions.
This commit runs rustfmt so it does.
1. skip-blame rustfmt
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D7582
AFFECTED FILES
rust/hg-core/src/configparser/c_api.rs
rust/hg-core/src/configparser/config.rs
rust/hg-core/src/configparser/hg.rs
rust/hg-core/src/configparser/mod.rs
rust/hg-core/src/configparser/parser.rs
CHANGE DETAILS
diff --git a/rust/hg-core/src/configparser/parser.rs b/rust/hg-core/src/configparser/parser.rs
--- a/rust/hg-core/src/configparser/parser.rs
+++ b/rust/hg-core/src/configparser/parser.rs
@@ -1,4 +1,3 @@
-
// Generated by generate_parser.py. Do not edit manually. Instead, edit
// spec.pest, then run generate_parser.py (require cargo-expand).
//
@@ -13,7 +12,6 @@
// Therefore this file is @generated. @no-lint.
// pest-checksum: af79d1287503f19c331643cd2e28d30f6312592f.
-
#[allow(dead_code, non_camel_case_types)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Rule {
diff --git a/rust/hg-core/src/configparser/mod.rs b/rust/hg-core/src/configparser/mod.rs
--- a/rust/hg-core/src/configparser/mod.rs
+++ b/rust/hg-core/src/configparser/mod.rs
@@ -12,8 +12,8 @@
//! ## Features
//!
//! - Parse valid hgrc-like config files efficiently.
-//! - Track source locations of config values. Keep multiple locations of
-//! a same config if it is overridden.
+//! - Track source locations of config values. Keep multiple locations of a
+//! same config if it is overridden.
//!
//! ## Config Format
//!
diff --git a/rust/hg-core/src/configparser/hg.rs b/rust/hg-core/src/configparser/hg.rs
--- a/rust/hg-core/src/configparser/hg.rs
+++ b/rust/hg-core/src/configparser/hg.rs
@@ -16,9 +16,9 @@
use anyhow::Result;
use bytes::Bytes;
-use crate::utils::path::expand_path;
use super::config::{ConfigSet, Options};
use super::error::Error;
+use crate::utils::path::expand_path;
pub const HGPLAIN: &str = "HGPLAIN";
pub const HGPLAINEXCEPT: &str = "HGPLAINEXCEPT";
@@ -28,13 +28,17 @@
/// Drop configs according to `$HGPLAIN` and `$HGPLAINEXCEPT`.
fn process_hgplain(self) -> Self;
- /// Set read-only config items. `items` contains a list of tuple `(section, name)`.
- /// Setting those items to new value will be ignored.
- fn readonly_items<S: Into<Bytes>, N: Into<Bytes>>(self, items: Vec<(S, N)>) -> Self;
+ /// Set read-only config items. `items` contains a list of tuple `(section,
+ /// name)`. Setting those items to new value will be ignored.
+ fn readonly_items<S: Into<Bytes>, N: Into<Bytes>>(
+ self,
+ items: Vec<(S, N)>,
+ ) -> Self;
- /// Set section remap. If a section name matches an entry key, it will be treated as if the
- /// name is the entry value. The remap wouldn't happen recursively. For example, with a
- /// `{"A": "B", "B": "C"}` map, section name "A" will be treated as "B", not "C".
+ /// Set section remap. If a section name matches an entry key, it will be
+ /// treated as if the name is the entry value. The remap wouldn't
+ /// happen recursively. For example, with a `{"A": "B", "B": "C"}` map,
+ /// section name "A" will be treated as "B", not "C".
/// This is implemented via `append_filter`.
fn remap_sections<K: Eq + Hash + Into<Bytes>, V: Into<Bytes>>(
self,
@@ -43,7 +47,10 @@
/// Set section whitelist. Sections outside the whitelist won't be loaded.
/// This is implemented via `append_filter`.
- fn whitelist_sections<B: Clone + Into<Bytes>>(self, sections: Vec<B>) -> Self;
+ fn whitelist_sections<B: Clone + Into<Bytes>>(
+ self,
+ sections: Vec<B>,
+ ) -> Self;
}
pub trait ConfigSetHgExt {
@@ -58,10 +65,18 @@
/// Load a specified config file. Respect HGPLAIN environment variables.
/// Return errors parsing files.
- fn load_hgrc(&mut self, path: impl AsRef<Path>, source: &'static str) -> Vec<Error>;
+ fn load_hgrc(
+ &mut self,
+ path: impl AsRef<Path>,
+ source: &'static str,
+ ) -> Vec<Error>;
/// Get a config item. Convert to type `T`.
- fn get_opt<T: FromConfigValue>(&self, section: &str, name: &str) -> Result<Option<T>>;
+ fn get_opt<T: FromConfigValue>(
+ &self,
+ section: &str,
+ name: &str,
+ ) -> Result<Option<T>>;
/// Get a config item. Convert to type `T`.
///
@@ -78,7 +93,11 @@
/// Get a config item. Convert to type `T`.
///
/// If the config item is not set, return `T::default()`.
- fn get_or_default<T: Default + FromConfigValue>(&self, section: &str, name: &str) -> Result<T> {
+ fn get_or_default<T: Default + FromConfigValue>(
+ &self,
+ section: &str,
+ name: &str,
+ ) -> Result<T> {
self.get_or(section, name, Default::default)
}
}
@@ -113,10 +132,13 @@
// [defaults] and [commands] are always blacklisted.
let mut section_blacklist: HashSet<Bytes> =
- ["defaults", "commands"].iter().map(|&s| s.into()).collect();
+ ["defaults", "commands"]
+ .iter()
+ .map(|&s| s.into())
+ .collect();
- // [alias], [revsetalias], [templatealias] are blacklisted if they are outside
- // HGPLAINEXCEPT.
+ // [alias], [revsetalias], [templatealias] are blacklisted if
+ // they are outside HGPLAINEXCEPT.
for &name in ["alias", "revsetalias", "templatealias"].iter() {
if !plain_exceptions.contains(name) {
section_blacklist.insert(Bytes::from(name));
@@ -138,7 +160,8 @@
.iter()
.map(|&s| s.into())
.collect();
- // exitcodemask is blacklisted if exitcode is outside HGPLAINEXCEPT.
+ // exitcodemask is blacklisted if exitcode is outside
+ // HGPLAINEXCEPT.
if !plain_exceptions.contains("exitcode") {
ui_blacklist.insert("exitcodemask".into());
}
@@ -146,15 +169,17 @@
(section_blacklist, ui_blacklist)
};
- let filter = move |section: Bytes, name: Bytes, value: Option<Bytes>| {
- if section_blacklist.contains(§ion)
- || (section.as_ref() == b"ui" && ui_blacklist.contains(&name))
- {
- None
- } else {
- Some((section, name, value))
- }
- };
+ let filter =
+ move |section: Bytes, name: Bytes, value: Option<Bytes>| {
+ if section_blacklist.contains(§ion)
+ || (section.as_ref() == b"ui"
+ && ui_blacklist.contains(&name))
+ {
+ None
+ } else {
+ Some((section, name, value))
+ }
+ };
self.append_filter(Box::new(filter))
} else {
@@ -164,27 +189,32 @@
/// Set section whitelist. Sections outside the whitelist won't be loaded.
/// This is implemented via `append_filter`.
- fn whitelist_sections<B: Clone + Into<Bytes>>(self, sections: Vec<B>) -> Self {
+ fn whitelist_sections<B: Clone + Into<Bytes>>(
+ self,
+ sections: Vec<B>,
+ ) -> Self {
let whitelist: HashSet<Bytes> = sections
.iter()
.cloned()
.map(|section| section.into())
.collect();
- let filter = move |section: Bytes, name: Bytes, value: Option<Bytes>| {
- if whitelist.contains(§ion) {
- Some((section, name, value))
- } else {
- None
- }
- };
+ let filter =
+ move |section: Bytes, name: Bytes, value: Option<Bytes>| {
+ if whitelist.contains(§ion) {
+ Some((section, name, value))
+ } else {
+ None
+ }
+ };
self.append_filter(Box::new(filter))
}
- /// Set section remap. If a section name matches an entry key, it will be treated as if the
- /// name is the entry value. The remap wouldn't happen recursively. For example, with a
- /// `{"A": "B", "B": "C"}` map, section name "A" will be treated as "B", not "C".
+ /// Set section remap. If a section name matches an entry key, it will be
+ /// treated as if the name is the entry value. The remap wouldn't
+ /// happen recursively. For example, with a `{"A": "B", "B": "C"}` map,
+ /// section name "A" will be treated as "B", not "C".
/// This is implemented via `append_filter`.
fn remap_sections<K, V>(self, remap: HashMap<K, V>) -> Self
where
@@ -196,27 +226,32 @@
.map(|(k, v)| (k.into(), v.into()))
.collect();
- let filter = move |section: Bytes, name: Bytes, value: Option<Bytes>| {
- let section = remap.get(§ion).cloned().unwrap_or(section);
- Some((section, name, value))
- };
+ let filter =
+ move |section: Bytes, name: Bytes, value: Option<Bytes>| {
+ let section = remap.get(§ion).cloned().unwrap_or(section);
+ Some((section, name, value))
+ };
self.append_filter(Box::new(filter))
}
- fn readonly_items<S: Into<Bytes>, N: Into<Bytes>>(self, items: Vec<(S, N)>) -> Self {
+ fn readonly_items<S: Into<Bytes>, N: Into<Bytes>>(
+ self,
+ items: Vec<(S, N)>,
+ ) -> Self {
let readonly_items: HashSet<(Bytes, Bytes)> = items
.into_iter()
.map(|(section, name)| (section.into(), name.into()))
.collect();
- let filter = move |section: Bytes, name: Bytes, value: Option<Bytes>| {
- if readonly_items.contains(&(section.clone(), name.clone())) {
- None
- } else {
- Some((section, name, value))
- }
- };
+ let filter =
+ move |section: Bytes, name: Bytes, value: Option<Bytes>| {
+ if readonly_items.contains(&(section.clone(), name.clone())) {
+ None
+ } else {
+ Some((section, name, value))
+ }
+ };
self.append_filter(Box::new(filter))
}
@@ -230,23 +265,37 @@
if env::var(HGRCPATH).is_err() {
#[cfg(unix)]
{
- errors.append(&mut self.load_path("/etc/mercurial/system.rc", &opts));
- // TODO(T40519286): Remove this after the tupperware overrides move out of hgrc.d
errors.append(
- &mut self.load_path("/etc/mercurial/hgrc.d/tupperware_overrides.rc", &opts),
+ &mut self.load_path("/etc/mercurial/system.rc", &opts),
);
- // TODO(quark): Remove this after packages using system.rc are rolled out
- errors.append(&mut self.load_path("/etc/mercurial/hgrc.d/include.rc", &opts));
+ // TODO(T40519286): Remove this after the tupperware overrides
+ // move out of hgrc.d
+ errors.append(&mut self.load_path(
+ "/etc/mercurial/hgrc.d/tupperware_overrides.rc",
+ &opts,
+ ));
+ // TODO(quark): Remove this after packages using system.rc are
+ // rolled out
+ errors.append(
+ &mut self
+ .load_path("/etc/mercurial/hgrc.d/include.rc", &opts),
+ );
}
#[cfg(windows)]
{
if let Ok(program_data_path) = env::var("PROGRAMDATA") {
use std::path::Path;
- let hgrc_dir = Path::new(&program_data_path).join("Facebook\\Mercurial");
- errors.append(&mut self.load_path(hgrc_dir.join("system.rc"), &opts));
- // TODO(quark): Remove this after packages using system.rc are rolled out
- errors.append(&mut self.load_path(hgrc_dir.join("hgrc"), &opts));
+ let hgrc_dir = Path::new(&program_data_path)
+ .join("Facebook\\Mercurial");
+ errors.append(
+ &mut self.load_path(hgrc_dir.join("system.rc"), &opts),
+ );
+ // TODO(quark): Remove this after packages using system.rc
+ // are rolled out
+ errors.append(
+ &mut self.load_path(hgrc_dir.join("hgrc"), &opts),
+ );
}
}
}
@@ -302,27 +351,42 @@
}
} else {
if let Some(home_dir) = dirs::home_dir() {
- errors.append(&mut self.load_path(home_dir.join(".hgrc"), &opts));
+ errors.append(
+ &mut self.load_path(home_dir.join(".hgrc"), &opts),
+ );
#[cfg(windows)]
{
- errors.append(&mut self.load_path(home_dir.join("mercurial.ini"), &opts));
+ errors.append(
+ &mut self
+ .load_path(home_dir.join("mercurial.ini"), &opts),
+ );
}
}
if let Some(config_dir) = dirs::config_dir() {
- errors.append(&mut self.load_path(config_dir.join("hg/hgrc"), &opts));
+ errors.append(
+ &mut self.load_path(config_dir.join("hg/hgrc"), &opts),
+ );
}
}
errors
}
- fn load_hgrc(&mut self, path: impl AsRef<Path>, source: &'static str) -> Vec<Error> {
+ fn load_hgrc(
+ &mut self,
+ path: impl AsRef<Path>,
+ source: &'static str,
+ ) -> Vec<Error> {
let opts = Options::new().source(source).process_hgplain();
self.load_path(path, &opts)
}
- fn get_opt<T: FromConfigValue>(&self, section: &str, name: &str) -> Result<Option<T>> {
+ fn get_opt<T: FromConfigValue>(
+ &self,
+ section: &str,
+ name: &str,
+ ) -> Result<Option<T>> {
ConfigSet::get(self, section, name)
.map(|bytes| T::try_from_bytes(&bytes))
.transpose()
@@ -335,7 +399,9 @@
match value.as_ref() {
"1" | "yes" | "true" | "on" | "always" => Ok(true),
"0" | "no" | "false" | "off" | "never" => Ok(false),
- _ => Err(Error::Convert(format!("invalid bool: {}", value)).into()),
+ _ => {
+ Err(Error::Convert(format!("invalid bool: {}", value)).into())
+ }
}
}
}
@@ -412,8 +478,9 @@
impl FromConfigValue for String {
fn try_from_bytes(bytes: &[u8]) -> Result<Self> {
- String::from_utf8(bytes.to_vec())
- .map_err(|_| Error::Convert(format!("{:?} is not utf8 encoded", bytes)).into())
+ String::from_utf8(bytes.to_vec()).map_err(|_| {
+ Error::Convert(format!("{:?} is not utf8 encoded", bytes)).into()
+ })
}
}
@@ -453,7 +520,8 @@
let value = std::str::from_utf8(bytes)?.to_lowercase();
for (suffix, unit) in sizeunits.iter() {
if value.ends_with(suffix) {
- let number_str: &str = value[..value.len() - suffix.len()].trim();
+ let number_str: &str =
+ value[..value.len() - suffix.len()].trim();
let number: f64 = number_str.parse()?;
if number < 0.0 {
return Err(Error::Convert(format!(
@@ -467,7 +535,11 @@
}
}
- Err(Error::Convert(format!("'{:?}' cannot be parsed as a byte size", value)).into())
+ Err(Error::Convert(format!(
+ "'{:?}' cannot be parsed as a byte size",
+ value
+ ))
+ .into())
}
}
@@ -580,7 +652,9 @@
// ```
State::Plain => {
let mut whitespace = false;
- while offset < value.len() && b" \n\r\t,".contains(&value[offset]) {
+ while offset < value.len()
+ && b" \n\r\t,".contains(&value[offset])
+ {
whitespace = true;
offset += 1;
}
@@ -667,7 +741,9 @@
if offset < value.len() && value[offset] == b'"' {
parts.push(Vec::new());
offset += 1;
- while offset < value.len() && b" \n\r\t,".contains(&value[offset]) {
+ while offset < value.len()
+ && b" \n\r\t,".contains(&value[offset])
+ {
offset += 1;
}
state = State::Plain;
@@ -686,10 +762,11 @@
offset += 1;
}
if offset >= value.len() {
- let mut real_parts: Vec<Vec<u8>> = parse_list_internal(parts.last().unwrap())
- .iter()
- .map(|b| b.to_vec())
- .collect();
+ let mut real_parts: Vec<Vec<u8>> =
+ parse_list_internal(parts.last().unwrap())
+ .iter()
+ .map(|b| b.to_vec())
+ .collect();
if real_parts.is_empty() {
parts.pop();
parts.push(vec![b'"']);
@@ -928,7 +1005,10 @@
parse_list(b"Do\"Not\"Separate"),
vec![b("Do\"Not\"Separate")]
);
- assert_eq!(parse_list(b"\"Do\"Separate"), vec![b("Do"), b("Separate")]);
+ assert_eq!(
+ parse_list(b"\"Do\"Separate"),
+ vec![b("Do"), b("Separate")]
+ );
assert_eq!(
parse_list(b"\"Do\\\"NotSeparate\""),
vec![b("Do\"NotSeparate")]
@@ -954,7 +1034,9 @@
vec![b("\""), b("just"), b("with"), b("starting"), b("quotation")]
);
assert_eq!(
- parse_list(&b"\"longer quotation\" with \"no ending quotation"[..]),
+ parse_list(
+ &b"\"longer quotation\" with \"no ending quotation"[..]
+ ),
vec![
b("longer quotation"),
b("with"),
@@ -967,7 +1049,10 @@
parse_list(&b"this is \\\" \"not a quotation mark\""[..]),
vec![b("this"), b("is"), b("\""), b("not a quotation mark")]
);
- assert_eq!(parse_list(b"\n \n\nding\ndong"), vec![b("ding"), b("dong")]);
+ assert_eq!(
+ parse_list(b"\n \n\nding\ndong"),
+ vec![b("ding"), b("dong")]
+ );
// Other manually written cases
assert_eq!(parse_list("a,b,,c"), vec![b("a"), b("b"), b("c")]);
diff --git a/rust/hg-core/src/configparser/config.rs b/rust/hg-core/src/configparser/config.rs
--- a/rust/hg-core/src/configparser/config.rs
+++ b/rust/hg-core/src/configparser/config.rs
@@ -40,7 +40,8 @@
#[derive(Clone, Debug)]
pub struct ValueSource {
value: Option<Bytes>,
- source: Bytes, // global, user, repo, "--config", or an extension name, etc.
+ source: Bytes, /* global, user, repo, "--config", or an extension name,
+ * etc. */
location: Option<ValueLocation>,
}
@@ -58,7 +59,15 @@
#[derive(Default)]
pub struct Options {
source: Bytes,
- filters: Vec<Box<dyn Fn(Bytes, Bytes, Option<Bytes>) -> Option<(Bytes, Bytes, Option<Bytes>)>>>,
+ filters: Vec<
+ Box<
+ dyn Fn(
+ Bytes,
+ Bytes,
+ Option<Bytes>,
+ ) -> Option<(Bytes, Bytes, Option<Bytes>)>,
+ >,
+ >,
}
impl ConfigSet {
@@ -72,9 +81,10 @@
/// If `path` is a directory, it is ignored.
/// If `path` is a file, it will be loaded directly.
///
- /// A config file can use `%include` to load other paths (directories or files). They will
- /// be loaded recursively. Includes take effect in place, instead of deferred. For example,
- /// with the following two files:
+ /// A config file can use `%include` to load other paths (directories or
+ /// files). They will be loaded recursively. Includes take effect in
+ /// place, instead of deferred. For example, with the following two
+ /// files:
///
/// ```plain,ignore
/// # This is 1.rc
@@ -91,28 +101,43 @@
///
/// After loading `1.rc`. `x` is set to 3 and `y` is set to 2.
///
- /// Loading a file that is already parsed or being parsed by this `load_path` call is ignored,
- /// to avoid infinite loop. A separate `load_path` call would not ignore files loaded by
- /// other `load_path` calls.
+ /// Loading a file that is already parsed or being parsed by this
+ /// `load_path` call is ignored, to avoid infinite loop. A separate
+ /// `load_path` call would not ignore files loaded by other `load_path`
+ /// calls.
///
- /// Return a list of errors. An error pasing a file will stop that file from loading, without
- /// affecting other files.
- pub fn load_path<P: AsRef<Path>>(&mut self, path: P, opts: &Options) -> Vec<Error> {
+ /// Return a list of errors. An error pasing a file will stop that file
+ /// from loading, without affecting other files.
+ pub fn load_path<P: AsRef<Path>>(
+ &mut self,
+ path: P,
+ opts: &Options,
+ ) -> Vec<Error> {
let mut visited = HashSet::new();
let mut errors = Vec::new();
self.load_file(path.as_ref(), opts, &mut visited, &mut errors);
errors
}
- /// Load content of an unnamed config file. The `ValueLocation`s of loaded config items will
- /// have an empty `path`.
+ /// Load content of an unnamed config file. The `ValueLocation`s of loaded
+ /// config items will have an empty `path`.
///
/// Return a list of errors.
- pub fn parse<B: Into<Bytes>>(&mut self, content: B, opts: &Options) -> Vec<Error> {
+ pub fn parse<B: Into<Bytes>>(
+ &mut self,
+ content: B,
+ opts: &Options,
+ ) -> Vec<Error> {
let mut visited = HashSet::new();
let mut errors = Vec::new();
let buf = content.into();
- self.load_file_content(Path::new(""), buf, opts, &mut visited, &mut errors);
+ self.load_file_content(
+ Path::new(""),
+ buf,
+ opts,
+ &mut visited,
+ &mut errors,
+ );
errors
}
@@ -131,17 +156,21 @@
/// Get config value for a given config.
/// Return `None` if the config item does not exist or is unset.
- pub fn get<S: Into<Bytes>, N: Into<Bytes>>(&self, section: S, name: N) -> Option<Bytes> {
+ pub fn get<S: Into<Bytes>, N: Into<Bytes>>(
+ &self,
+ section: S,
+ name: N,
+ ) -> Option<Bytes> {
self.sections.get(§ion.into()).and_then(|section| {
- section
- .items
- .get(&name.into())
- .and_then(|values| values.last().and_then(|value| value.value.clone()))
+ section.items.get(&name.into()).and_then(|values| {
+ values.last().and_then(|value| value.value.clone())
+ })
})
}
- /// Get detailed sources of a given config, including overrides, and source information.
- /// The last item in the returned vector is the latest value that is considered effective.
+ /// Get detailed sources of a given config, including overrides, and source
+ /// information. The last item in the returned vector is the latest
+ /// value that is considered effective.
///
/// Return an emtpy vector if the config does not exist.
pub fn get_sources<S: Into<Bytes>, N: Into<Bytes>>(
@@ -151,12 +180,15 @@
) -> Vec<ValueSource> {
self.sections
.get(§ion.into())
- .and_then(|section| section.items.get(&name.into()).map(|values| values.clone()))
+ .and_then(|section| {
+ section.items.get(&name.into()).map(|values| values.clone())
+ })
.unwrap_or(Vec::new())
}
- /// Set a config item directly. `section`, `name` locates the config. `value` is the new value.
- /// `source` is some annotation about who set it, ex. "reporc", "userrc", "--config", etc.
+ /// Set a config item directly. `section`, `name` locates the config.
+ /// `value` is the new value. `source` is some annotation about who set
+ /// it, ex. "reporc", "userrc", "--config", etc.
pub fn set<T: Into<Bytes>, N: Into<Bytes>>(
&mut self,
section: T,
@@ -178,12 +210,14 @@
location: Option<ValueLocation>,
opts: &Options,
) {
- let filtered = opts
- .filters
- .iter()
- .fold(Some((section, name, value)), move |acc, func| {
- acc.and_then(|(section, name, value)| func(section, name, value))
- });
+ let filtered = opts.filters.iter().fold(
+ Some((section, name, value)),
+ move |acc, func| {
+ acc.and_then(|(section, name, value)| {
+ func(section, name, value)
+ })
+ },
+ );
if let Some((section, name, value)) = filtered {
self.sections
.entry(section)
@@ -227,15 +261,18 @@
self.load_file_content(path, buf, opts, visited, errors);
}
- Err(error) => errors.push(Error::Io(path.to_path_buf(), error)),
+ Err(error) => {
+ errors.push(Error::Io(path.to_path_buf(), error))
+ }
}
} else {
- // On Windows, a UNC path `\\?\C:\foo\.\x` will fail to canonicalize
- // because it contains `.`. That path can be constructed by using
- // `PathBuf::join` to concatenate a UNC path `\\?\C:\foo` with
- // a "normal" path `.\x`.
- // Try to fix it automatically by stripping the UNC prefix and retry
- // `canonicalize`. `C:\foo\.\x` would be canonicalized without errors.
+ // On Windows, a UNC path `\\?\C:\foo\.\x` will fail to
+ // canonicalize because it contains `.`. That path can
+ // be constructed by using `PathBuf::join` to
+ // concatenate a UNC path `\\?\C:\foo` with a "normal"
+ // path `.\x`. Try to fix it automatically by stripping
+ // the UNC prefix and retry `canonicalize`.
+ // `C:\foo\.\x` would be canonicalized without errors.
#[cfg(windows)]
{
if let Some(path_str) = path.to_str() {
@@ -247,9 +284,9 @@
}
}
- // If `path.canonicalize` reports an error. It's usually the path cannot
- // be resolved (ex. does not exist). It is considered normal and is not
- // reported in `errors`.
+ // If `path.canonicalize` reports an error. It's usually the path
+ // cannot be resolved (ex. does not exist). It is considered
+ // normal and is not reported in `errors`.
}
fn load_file_content(
@@ -265,50 +302,62 @@
let skip_include = path.parent().is_none(); // skip handling %include if path is empty
// Utilities to avoid too much indentation.
- let handle_value = |this: &mut ConfigSet,
- pair: Pair,
- section: Bytes,
- name: Bytes,
- location: ValueLocation| {
- let pairs = pair.into_inner();
- let mut lines = Vec::with_capacity(1);
- for pair in pairs {
- if Rule::line == pair.as_rule() {
- lines.push(extract(&buf, pair.as_span()));
+ let handle_value =
+ |this: &mut ConfigSet,
+ pair: Pair,
+ section: Bytes,
+ name: Bytes,
+ location: ValueLocation| {
+ let pairs = pair.into_inner();
+ let mut lines = Vec::with_capacity(1);
+ for pair in pairs {
+ if Rule::line == pair.as_rule() {
+ lines.push(extract(&buf, pair.as_span()));
+ }
}
- }
+
+ let value = match lines.len() {
+ 1 => lines[0].clone(),
+ _ => Bytes::from(lines.join(&b'\n')),
+ };
- let value = match lines.len() {
- 1 => lines[0].clone(),
- _ => Bytes::from(lines.join(&b'\n')),
+ let (start, end) = strip_offsets(&value, 0, value.len());
+ let value = value.slice(start, end);
+
+ this.set_internal(
+ section,
+ name,
+ value.into(),
+ location.into(),
+ opts,
+ )
};
- let (start, end) = strip_offsets(&value, 0, value.len());
- let value = value.slice(start, end);
-
- this.set_internal(section, name, value.into(), location.into(), opts)
- };
-
- let handle_config_item = |this: &mut ConfigSet, pair: Pair, section: Bytes| {
- let pairs = pair.into_inner();
- let mut name = Bytes::new();
- for pair in pairs {
- match pair.as_rule() {
- Rule::config_name => name = extract(&buf, pair.as_span()),
- Rule::value => {
- let span = pair.as_span();
- let location = ValueLocation {
- path: shared_path.clone(),
- content: buf.clone(),
- location: span.start()..span.end(),
- };
- return handle_value(this, pair, section, name, location);
+ let handle_config_item =
+ |this: &mut ConfigSet, pair: Pair, section: Bytes| {
+ let pairs = pair.into_inner();
+ let mut name = Bytes::new();
+ for pair in pairs {
+ match pair.as_rule() {
+ Rule::config_name => {
+ name = extract(&buf, pair.as_span())
+ }
+ Rule::value => {
+ let span = pair.as_span();
+ let location = ValueLocation {
+ path: shared_path.clone(),
+ content: buf.clone(),
+ location: span.start()..span.end(),
+ };
+ return handle_value(
+ this, pair, section, name, location,
+ );
+ }
+ _ => (),
}
- _ => (),
}
- }
- unreachable!();
- };
+ unreachable!();
+ };
let handle_section = |pair: Pair, section: &mut Bytes| {
let pairs = pair.into_inner();
@@ -324,51 +373,63 @@
unreachable!();
};
- let mut handle_include = |this: &mut ConfigSet, pair: Pair, errors: &mut Vec<Error>| {
- let pairs = pair.into_inner();
- for pair in pairs {
- match pair.as_rule() {
- Rule::line => {
- if !skip_include {
- let include_path = pair.as_str();
- let full_include_path =
- path.parent().unwrap().join(expand_path(include_path));
- this.load_file(&full_include_path, opts, visited, errors);
+ let mut handle_include =
+ |this: &mut ConfigSet, pair: Pair, errors: &mut Vec<Error>| {
+ let pairs = pair.into_inner();
+ for pair in pairs {
+ match pair.as_rule() {
+ Rule::line => {
+ if !skip_include {
+ let include_path = pair.as_str();
+ let full_include_path = path
+ .parent()
+ .unwrap()
+ .join(expand_path(include_path));
+ this.load_file(
+ &full_include_path,
+ opts,
+ visited,
+ errors,
+ );
+ }
}
+ _ => (),
}
- _ => (),
}
- }
- };
+ };
- let handle_unset = |this: &mut ConfigSet, pair: Pair, section: &Bytes| {
- let unset_span = pair.as_span();
- let pairs = pair.into_inner();
- for pair in pairs {
- match pair.as_rule() {
- Rule::config_name => {
- let name = extract(&buf, pair.as_span());
- let location = ValueLocation {
- path: shared_path.clone(),
- content: buf.clone(),
- location: unset_span.start()..unset_span.end(),
- };
- return this.set_internal(
- section.clone(),
- name,
- None,
- location.into(),
- opts,
- );
+ let handle_unset =
+ |this: &mut ConfigSet, pair: Pair, section: &Bytes| {
+ let unset_span = pair.as_span();
+ let pairs = pair.into_inner();
+ for pair in pairs {
+ match pair.as_rule() {
+ Rule::config_name => {
+ let name = extract(&buf, pair.as_span());
+ let location = ValueLocation {
+ path: shared_path.clone(),
+ content: buf.clone(),
+ location: unset_span.start()..unset_span.end(),
+ };
+ return this.set_internal(
+ section.clone(),
+ name,
+ None,
+ location.into(),
+ opts,
+ );
+ }
+ _ => (),
}
- _ => (),
}
- }
- unreachable!();
- };
+ unreachable!();
+ };
let mut handle_directive =
- |this: &mut ConfigSet, pair: Pair, section: &Bytes, errors: &mut Vec<Error>| {
+ |this: &mut ConfigSet,
+ pair: Pair,
+ section: &Bytes,
+ errors: &mut Vec<Error>| {
let pairs = pair.into_inner();
for pair in pairs {
match pair.as_rule() {
@@ -381,22 +442,34 @@
let text = match str::from_utf8(&buf) {
Ok(text) => text,
- Err(error) => return errors.push(Error::Utf8(path.to_path_buf(), error)),
+ Err(error) => {
+ return errors.push(Error::Utf8(path.to_path_buf(), error))
+ }
};
let pairs = match ConfigParser::parse(Rule::file, &text) {
Ok(pairs) => pairs,
Err(error) => {
- return errors.push(Error::Parse(path.to_path_buf(), format!("{}", error)));
+ return errors.push(Error::Parse(
+ path.to_path_buf(),
+ format!("{}", error),
+ ));
}
};
for pair in pairs {
match pair.as_rule() {
- Rule::config_item => handle_config_item(self, pair, section.clone()),
+ Rule::config_item => {
+ handle_config_item(self, pair, section.clone())
+ }
Rule::section => handle_section(pair, &mut section),
- Rule::directive => handle_directive(self, pair, §ion, errors),
- Rule::blank_line | Rule::comment_line | Rule::new_line | Rule::EOI => (),
+ Rule::directive => {
+ handle_directive(self, pair, §ion, errors)
+ }
+ Rule::blank_line
+ | Rule::comment_line
+ | Rule::new_line
+ | Rule::EOI => (),
Rule::comment_start
| Rule::compound
@@ -422,8 +495,8 @@
&self.value
}
- /// Return the "source" information for the config value. It's usually who sets the config,
- /// like "--config", "user_hgrc", "system_hgrc", etc.
+ /// Return the "source" information for the config value. It's usually who
+ /// sets the config, like "--config", "user_hgrc", "system_hgrc", etc.
pub fn source(&self) -> &Bytes {
&self.source
}
@@ -434,7 +507,9 @@
/// If the value is `None`, the byte range is for the "%unset" statement.
pub fn location(&self) -> Option<(PathBuf, Range<usize>)> {
match self.location {
- Some(ref src) => Some((src.path.as_ref().to_path_buf(), src.location.clone())),
+ Some(ref src) => {
+ Some((src.path.as_ref().to_path_buf(), src.location.clone()))
+ }
None => None,
}
}
@@ -454,23 +529,31 @@
Self::default()
}
- /// Append a filter. A filter can decide to ignore a config item, or change its section,
- /// config name, or even value. The filter function takes a tuple of `(section, name, value)`
- /// and outputs `None` to prevent inserting that value, or `Some((section, name, value))` to
+ /// Append a filter. A filter can decide to ignore a config item, or change
+ /// its section, config name, or even value. The filter function takes
+ /// a tuple of `(section, name, value)` and outputs `None` to prevent
+ /// inserting that value, or `Some((section, name, value))` to
/// insert it with optionally different name or values.
///
/// Filters inserted first will be executed first.
pub fn append_filter(
mut self,
- filter: Box<dyn Fn(Bytes, Bytes, Option<Bytes>) -> Option<(Bytes, Bytes, Option<Bytes>)>>,
+ filter: Box<
+ dyn Fn(
+ Bytes,
+ Bytes,
+ Option<Bytes>,
+ ) -> Option<(Bytes, Bytes, Option<Bytes>)>,
+ >,
) -> Self {
self.filters.push(filter);
self
}
- /// Set `source` information. It is about who initialized the config loading. For example,
- /// "user_hgrc" indicates it is from the user config file, "--config" indicates it is from the
- /// global "--config" command line flag, "env" indicates it is translated from an environment
+ /// Set `source` information. It is about who initialized the config
+ /// loading. For example, "user_hgrc" indicates it is from the user
+ /// config file, "--config" indicates it is from the global "--config"
+ /// command line flag, "env" indicates it is translated from an environment
/// variable (ex. "PAGER"), etc.
pub fn source<B: Into<Bytes>>(mut self, source: B) -> Self {
self.source = source.into();
@@ -485,8 +568,8 @@
}
}
-/// Remove space characters from both ends. Remove newline characters from the end.
-/// `start` position is inclusive, `end` is exclusive.
+/// Remove space characters from both ends. Remove newline characters from the
+/// end. `start` position is inclusive, `end` is exclusive.
/// Return the stripped `start` and `end` offsets.
#[inline]
fn strip_offsets(buf: &Bytes, start: usize, end: usize) -> (usize, usize) {
@@ -899,7 +982,10 @@
);
let mut cfg = ConfigSet::new();
- let errors = cfg.load_path(dir.path().join("rootrc"), &"test_parse_include".into());
+ let errors = cfg.load_path(
+ dir.path().join("rootrc"),
+ &"test_parse_include".into(),
+ );
assert!(errors.is_empty());
assert_eq!(cfg.sections(), vec![Bytes::from("x"), Bytes::from("y")]);
@@ -935,7 +1021,8 @@
write_file(dir.path().join("f2/f/4.rc"), "[y]\nb=2\n");
let mut cfg = ConfigSet::new();
- let errors = cfg.load_path(dir.path().join("rootrc"), &"include_expand".into());
+ let errors =
+ cfg.load_path(dir.path().join("rootrc"), &"include_expand".into());
assert!(errors.is_empty());
assert_eq!(cfg.get("x", "a"), Some(Bytes::from("1")));
diff --git a/rust/hg-core/src/configparser/c_api.rs b/rust/hg-core/src/configparser/c_api.rs
--- a/rust/hg-core/src/configparser/c_api.rs
+++ b/rust/hg-core/src/configparser/c_api.rs
@@ -5,7 +5,8 @@
* GNU General Public License version 2.
*/
-//! This module exports some symbols to allow calling the config parser from C/C++
+//! This module exports some symbols to allow calling the config parser from
+//! C/C++
use std::ffi::{CStr, OsStr};
use std::os::raw::c_char;
use std::path::Path;
@@ -64,7 +65,10 @@
/// error object is UTF-8 encoded text, and errors can span multiple lines.
#[cfg(unix)]
#[no_mangle]
-pub extern "C" fn hgrc_configset_load_path(cfg: *mut ConfigSet, path: *const c_char) -> *mut Bytes {
+pub extern "C" fn hgrc_configset_load_path(
+ cfg: *mut ConfigSet,
+ path: *const c_char,
+) -> *mut Bytes {
debug_assert!(!path.is_null());
debug_assert!(!cfg.is_null());
@@ -81,7 +85,9 @@
/// Load system config files
#[no_mangle]
-pub extern "C" fn hgrc_configset_load_system(cfg: *mut ConfigSet) -> *mut Bytes {
+pub extern "C" fn hgrc_configset_load_system(
+ cfg: *mut ConfigSet,
+) -> *mut Bytes {
debug_assert!(!cfg.is_null());
let cfg = unsafe { &mut *cfg };
@@ -100,8 +106,9 @@
errors_to_bytes(cfg.load_user())
}
-/// Returns a Bytes object holding the configuration value for the corresponding
-/// section name and key. If there is no matching section/key pair, returns nullptr.
+/// Returns a Bytes object holding the configuration value for the
+/// corresponding section name and key. If there is no matching section/key
+/// pair, returns nullptr.
#[no_mangle]
pub extern "C" fn hgrc_configset_get(
cfg: *const ConfigSet,
@@ -130,8 +137,8 @@
len: usize,
}
-/// Returns the data pointer and length for a Bytes object, suitable for constructing
-/// a folly::ByteRange.
+/// Returns the data pointer and length for a Bytes object, suitable for
+/// constructing a folly::ByteRange.
#[no_mangle]
pub extern "C" fn hgrc_bytes_data(bytes: *const Bytes) -> ByteData {
debug_assert!(!bytes.is_null());
To: indygreg, #hg-reviewers
Cc: durin42, kevincox, mjpieters, mercurial-devel
More information about the Mercurial-devel
mailing list