rhg: central treatment of PLAIN and PLAINEXCEPT
authorArseniy Alekseyev <aalekseyev@janestreet.com>
Tue, 20 Sep 2022 18:16:50 -0400
changeset 49512 6939d5ed20e0
parent 49511 117dcc4a0e67
child 49513 467d9df98c68
rhg: central treatment of PLAIN and PLAINEXCEPT
rust/hg-core/src/config.rs
rust/hg-core/src/config/config.rs
rust/rhg/src/commands/status.rs
rust/rhg/src/main.rs
rust/rhg/src/ui.rs
--- a/rust/hg-core/src/config.rs	Tue Oct 04 12:34:50 2022 -0400
+++ b/rust/hg-core/src/config.rs	Tue Sep 20 18:16:50 2022 -0400
@@ -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};
--- a/rust/hg-core/src/config/config.rs	Tue Oct 04 12:34:50 2022 -0400
+++ b/rust/hg-core/src/config/config.rs	Tue Sep 20 18:16:50 2022 -0400
@@ -22,11 +22,20 @@
 
 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<layer::ConfigLayer>,
+    plain: PlainInfo,
 }
 
 impl DisplayBytes for Config {
@@ -83,17 +92,65 @@
     }
 }
 
+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(&section);
+}
+
+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<Self, ConfigError> {
-        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 @@
             }
         }
 
-        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 @@
 
         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 @@
         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 @@
         section: &[u8],
         item: &[u8],
     ) -> Option<(&ConfigLayer, &ConfigValue)> {
+        if should_ignore(&self.plain, &section, &item) {
+            return None;
+        }
         for layer in self.layers.iter().rev() {
             if !layer.trusted {
                 continue;
--- a/rust/rhg/src/commands/status.rs	Tue Oct 04 12:34:50 2022 -0400
+++ b/rust/rhg/src/commands/status.rs	Tue Sep 20 18:16:50 2022 -0400
@@ -209,8 +209,7 @@
     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 @@
                 }
             }
         }
-        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,
--- a/rust/rhg/src/main.rs	Tue Oct 04 12:34:50 2022 -0400
+++ b/rust/rhg/src/main.rs	Tue Sep 20 18:16:50 2022 -0400
@@ -6,11 +6,12 @@
 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 @@
     } 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,
--- a/rust/rhg/src/ui.rs	Tue Oct 04 12:34:50 2022 -0400
+++ b/rust/rhg/src/ui.rs	Tue Sep 20 18:16:50 2022 -0400
@@ -127,26 +127,22 @@
         }
         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| {