# HG changeset patch # User Arseniy Alekseyev # Date 2022-09-20 22:16:50 # Node ID 6939d5ed20e0ce76dcc84344c0baa0054ca78ed9 # Parent 117dcc4a0e671f4979c67ab0dc104805b4844ab6 rhg: central treatment of PLAIN and PLAINEXCEPT diff --git a/rust/hg-core/src/config.rs b/rust/hg-core/src/config.rs --- a/rust/hg-core/src/config.rs +++ b/rust/hg-core/src/config.rs @@ -12,5 +12,5 @@ mod config; mod layer; mod values; -pub use config::{Config, ConfigSource, ConfigValueParseError}; +pub use config::{Config, ConfigSource, ConfigValueParseError, PlainInfo}; pub use layer::{ConfigError, ConfigOrigin, ConfigParseError}; diff --git a/rust/hg-core/src/config/config.rs b/rust/hg-core/src/config/config.rs --- a/rust/hg-core/src/config/config.rs +++ b/rust/hg-core/src/config/config.rs @@ -22,11 +22,20 @@ use std::str; use crate::errors::{HgResultExt, IoResultExt}; +#[derive(Clone)] +pub struct PlainInfo { + pub plain: bool, + pub plainalias: bool, + pub plainrevsetalias: bool, + pub plaintemplatealias: bool, +} + /// Holds the config values for the current repository /// TODO update this docstring once we support more sources #[derive(Clone)] pub struct Config { layers: Vec, + plain: PlainInfo, } impl DisplayBytes for Config { @@ -83,17 +92,65 @@ impl fmt::Display for ConfigValueParseEr } } +fn should_ignore(plain: &PlainInfo, section: &[u8], item: &[u8]) -> bool { + // duplication with [_applyconfig] in [ui.py], + if !plain.plain { + return false; + } + if section == b"alias" { + return plain.plainalias; + } + if section == b"revsetalias" { + return plain.plainrevsetalias; + } + if section == b"templatealias" { + return plain.plaintemplatealias; + } + + if section == b"ui" { + let to_delete: &[&[u8]] = &[ + b"debug", + b"fallbackencoding", + b"quiet", + b"slash", + b"logtemplate", + b"message-output", + b"statuscopies", + b"style", + b"traceback", + b"verbose", + ]; + return to_delete.contains(&item); + } + let sections_to_delete: &[&[u8]] = + &[b"defaults", b"commands", b"command-templates"]; + return sections_to_delete.contains(§ion); +} + +impl PlainInfo { + pub fn empty() -> Self { + Self { + plain: false, + plainalias: false, + plainrevsetalias: false, + plaintemplatealias: false, + } + } +} impl Config { /// The configuration to use when printing configuration-loading errors pub fn empty() -> Self { - Self { layers: Vec::new() } + Self { + layers: Vec::new(), + plain: PlainInfo::empty(), + } } /// Load system and user configuration from various files. /// /// This is also affected by some environment variables. pub fn load_non_repo() -> Result { - let mut config = Self { layers: Vec::new() }; + let mut config = Self::empty(); let opt_rc_path = env::var_os("HGRCPATH"); // HGRCPATH replaces system config if opt_rc_path.is_none() { @@ -266,7 +323,10 @@ impl Config { } } - Ok(Config { layers }) + Ok(Config { + layers, + plain: PlainInfo::empty(), + }) } /// Loads the per-repository config into a new `Config` which is combined @@ -283,6 +343,7 @@ impl Config { let mut repo_config = Self { layers: other_layers, + plain: PlainInfo::empty(), }; for path in repo_config_files { // TODO: check if this file should be trusted: @@ -293,6 +354,10 @@ impl Config { Ok(repo_config) } + pub fn apply_plain(&mut self, plain: PlainInfo) { + self.plain = plain; + } + fn get_parse<'config, T: 'config>( &'config self, section: &[u8], @@ -413,6 +478,9 @@ impl Config { section: &[u8], item: &[u8], ) -> Option<(&ConfigLayer, &ConfigValue)> { + if should_ignore(&self.plain, §ion, &item) { + return None; + } for layer in self.layers.iter().rev() { if !layer.trusted { continue; diff --git a/rust/rhg/src/commands/status.rs b/rust/rhg/src/commands/status.rs --- a/rust/rhg/src/commands/status.rs +++ b/rust/rhg/src/commands/status.rs @@ -209,8 +209,7 @@ pub fn run(invocation: &crate::CliInvoca let config = invocation.config; let args = invocation.subcommand_args; - let verbose = !ui.plain(None) - && !args.is_present("print0") + let verbose = !args.is_present("print0") && (args.is_present("verbose") || config.get_bool(b"ui", b"verbose")? || config.get_bool(b"commands", b"status.verbose")?); @@ -315,10 +314,9 @@ pub fn run(invocation: &crate::CliInvoca } } } - let relative_paths = (!ui.plain(None)) - && config - .get_option(b"commands", b"status.relative")? - .unwrap_or(config.get_bool(b"ui", b"relative-paths")?); + let relative_paths = config + .get_option(b"commands", b"status.relative")? + .unwrap_or(config.get_bool(b"ui", b"relative-paths")?); let output = DisplayStatusPaths { ui, no_status, diff --git a/rust/rhg/src/main.rs b/rust/rhg/src/main.rs --- a/rust/rhg/src/main.rs +++ b/rust/rhg/src/main.rs @@ -6,11 +6,12 @@ use clap::AppSettings; use clap::Arg; use clap::ArgMatches; use format_bytes::{format_bytes, join}; -use hg::config::{Config, ConfigSource}; +use hg::config::{Config, ConfigSource, PlainInfo}; use hg::repo::{Repo, RepoError}; use hg::utils::files::{get_bytes_from_os_str, get_path_from_bytes}; use hg::utils::SliceExt; use hg::{exit_codes, requirements}; +use std::borrow::Cow; use std::collections::HashSet; use std::ffi::OsString; use std::os::unix::prelude::CommandExt; @@ -326,6 +327,18 @@ fn rhg_main(argv: Vec) -> ! { } else { &non_repo_config }; + + let mut config_cow = Cow::Borrowed(config); + if ui::plain(None) { + config_cow.to_mut().apply_plain(PlainInfo { + plain: true, + plainalias: ui::plain(Some("alias")), + plainrevsetalias: ui::plain(Some("revsetalias")), + plaintemplatealias: ui::plain(Some("templatealias")), + }) + }; + let config = config_cow.as_ref(); + let ui = Ui::new(&config).unwrap_or_else(|error| { exit( &argv, diff --git a/rust/rhg/src/ui.rs b/rust/rhg/src/ui.rs --- a/rust/rhg/src/ui.rs +++ b/rust/rhg/src/ui.rs @@ -127,26 +127,22 @@ impl Ui { } stdout.flush() } - - /// Return whether plain mode is active. - /// - /// Plain mode means that all configuration variables which affect - /// the behavior and output of Mercurial should be - /// ignored. Additionally, the output should be stable, - /// reproducible and suitable for use in scripts or applications. - /// - /// The only way to trigger plain mode is by setting either the - /// `HGPLAIN' or `HGPLAINEXCEPT' environment variables. - /// - /// The return value can either be - /// - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT - /// - False if feature is disabled by default and not included in HGPLAIN - /// - True otherwise - pub fn plain(&self, feature: Option<&str>) -> bool { - plain(feature) - } } +/// Return whether plain mode is active. +/// +/// Plain mode means that all configuration variables which affect +/// the behavior and output of Mercurial should be +/// ignored. Additionally, the output should be stable, +/// reproducible and suitable for use in scripts or applications. +/// +/// The only way to trigger plain mode is by setting either the +/// `HGPLAIN' or `HGPLAINEXCEPT' environment variables. +/// +/// The return value can either be +/// - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT +/// - False if feature is disabled by default and not included in HGPLAIN +/// - True otherwise pub fn plain(opt_feature: Option<&str>) -> bool { if let Some(except) = env::var_os("HGPLAINEXCEPT") { opt_feature.map_or(true, |feature| {