identity: support SAPLING_SCRIPT in addition to HGPLAIN

Summary:
By adjusting the identities list we can now adjust which plain
environment variables are supported.

Reviewed By: bolinfest

Differential Revision: D39738363

fbshipit-source-id: 46ae208bc3a86c9bad4c726530db27557e6be413
This commit is contained in:
Durham Goode 2022-09-28 13:41:46 -07:00 committed by Facebook GitHub Bot
parent 50bf4b4d98
commit 9e0d3cb248
10 changed files with 66 additions and 29 deletions

View File

@ -671,7 +671,7 @@ def statuscmd(orig, ui, repo, *pats, **opts):
message = _("--root-relative not supported with patterns")
hint = _("run from the repo root instead")
raise error.Abort(message, hint=hint)
elif encoding.environ.get("HGPLAIN"): # don't break automation
elif ui.plain():
pass
# Here's an ugly hack! If users are passing "re:" to make status relative,
# hgwatchman will never refresh the full state and status will become and

View File

@ -17,6 +17,8 @@ import locale
import os
import sys
import bindings
from . import encoding, identity, pycompat
@ -146,9 +148,12 @@ _plain = True
def _getplain():
if "HGPLAIN" not in encoding.environ and "HGPLAINEXCEPT" not in encoding.environ:
plain = bindings.identity.envvar("PLAIN")
plainexcept = bindings.identity.envvar("PLAINEXCEPT")
if plain is None and plainexcept is None:
return False
exceptions = encoding.environ.get("HGPLAINEXCEPT", "").strip().split(",")
exceptions = (plainexcept or "").strip().split(",")
return "i18n" not in exceptions

View File

@ -558,11 +558,13 @@ class ui(object):
- False if feature is disabled by default and not included in HGPLAIN
- True otherwise
"""
if "HGPLAIN" not in os.environ and "HGPLAINEXCEPT" not in os.environ:
plain = bindings.identity.envvar("PLAIN")
plainexcept = bindings.identity.envvar("PLAINEXCEPT")
if plain is None and plainexcept is None:
return False
exceptions = encoding.environ.get("HGPLAINEXCEPT", "").strip().split(",")
exceptions = (plainexcept or "").strip().split(",")
# TODO: add support for HGPLAIN=+feature,-feature syntax
if "+strictflags" not in encoding.environ.get("HGPLAIN", "").split(","):
if "+strictflags" not in (plain or "").split(","):
exceptions.append("strictflags")
if feature and exceptions:
return feature not in exceptions

View File

@ -21,6 +21,7 @@ pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
m.add(py, "sniffenv", py_fn!(py, sniff_env()))?;
m.add(py, "sniffroot", py_fn!(py, sniff_root(path: PyPathBuf)))?;
m.add(py, "sniffdir", py_fn!(py, sniff_dir(path: PyPathBuf)))?;
m.add(py, "envvar", py_fn!(py, try_env_var(suffix: PyString)))?;
Ok(m)
}
@ -53,3 +54,9 @@ fn sniff_dir(py: Python, path: PyPathBuf) -> PyResult<Option<identity>> {
Some(ident) => Some(identity::create_instance(py, ident)?),
})
}
fn try_env_var(py: Python, suffix: PyString) -> PyResult<Option<String>> {
rsident::env_var(suffix.to_string(py)?.as_ref())
.transpose()
.map_pyerr(py)
}

View File

@ -22,6 +22,7 @@ anyhow = "1.0.65"
eventsource = "0.5"
filetime = "0.2.9"
hostcaps = { version = "0.1.0", git = "https://github.com/facebookexperimental/rust-shed.git", branch = "main" }
identity = { version = "0.1.0", path = "../identity" }
lazy_static = "1.4"
log = { version = "0.4.14", features = ["kv_unstable", "kv_unstable_std"] }
regex = "1.5.4"

View File

@ -38,7 +38,7 @@ impl CloudSyncTrigger {
let now = Instant::now();
let child = Command::new("hg")
.current_dir(&path)
.env("HGPLAIN", "hint")
.env(identity::try_env_var("PLAIN")?, "hint")
.args(vec!["cloud", "sync"])
.arg("--check-autosync-enabled")
.arg("--use-bgssh")

View File

@ -23,8 +23,7 @@ use std::path::PathBuf;
use anyhow::Result;
use configmodel::Config;
use configmodel::ConfigExt;
use hgplain::HGPLAIN;
use hgplain::HGPLAINEXCEPT;
use hgplain;
use minibytes::Text;
use url::Url;
use util::path::expand_path;
@ -134,15 +133,9 @@ pub fn load(
impl OptionsHgExt for Options {
fn process_hgplain(self) -> Self {
let plain_set = env::var(HGPLAIN).is_ok();
let plain_except = env::var(HGPLAINEXCEPT);
if plain_set || plain_except.is_ok() {
if hgplain::is_plain(None) {
let (section_exclude_list, ui_exclude_list) = {
let plain_exceptions: HashSet<String> = plain_except
.unwrap_or_else(|_| "".to_string())
.split(',')
.map(|s| s.to_string())
.collect();
let plain_exceptions = hgplain::exceptions();
// [defaults] and [commands] are always excluded.
let mut section_exclude_list: HashSet<Text> =
@ -874,6 +867,9 @@ mod tests {
use crate::config::tests::write_file;
use crate::lock_env;
const HGPLAIN: &str = "HGPLAIN";
const HGPLAINEXCEPT: &str = "HGPLAINEXCEPT";
#[test]
fn test_basic_hgplain() {
let mut env = lock_env();

View File

@ -24,6 +24,8 @@ pub struct Identity {
dot_dir: &'static str,
env_prefix: &'static str,
config_name: &'static str,
scripting_env_var: &'static str,
scripting_except_env_var: &'static str,
}
impl Identity {
@ -47,8 +49,12 @@ impl Identity {
self.env_prefix
}
fn env_var(&self, suffix: &str) -> Option<Result<String, VarError>> {
let var_name = format!("{}{}", self.env_prefix, suffix);
pub fn env_var(&self, suffix: &str) -> Option<Result<String, VarError>> {
let var_name = match suffix {
"PLAIN" => self.scripting_env_var.to_string(),
"PLAINEXCEPT" => self.scripting_except_env_var.to_string(),
_ => format!("{}{}", self.env_prefix, suffix),
};
match std::env::var(var_name) {
Err(err) if err == VarError::NotPresent => None,
Err(err) => Some(Err(err)),
@ -69,6 +75,8 @@ const HG: Identity = Identity {
dot_dir: ".hg",
env_prefix: "HG",
config_name: "hgrc",
scripting_env_var: "HGPLAIN",
scripting_except_env_var: "HGPLAINEXCEPT",
};
const SL: Identity = Identity {
@ -77,6 +85,8 @@ const SL: Identity = Identity {
dot_dir: ".sl",
env_prefix: "SL",
config_name: "slconfig",
scripting_env_var: "SL_AUTOMATION",
scripting_except_env_var: "SL_AUTOMATION_EXCEPT",
};
#[cfg(test)]
@ -86,6 +96,8 @@ const TEST: Identity = Identity {
dot_dir: ".test",
env_prefix: "TEST",
config_name: "testrc",
scripting_env_var: "TEST_SCRIPT",
scripting_except_env_var: "TEST_SCRIPT_EXCEPT",
};
#[cfg(all(not(feature = "sl_only"), not(test)))]
@ -169,12 +181,12 @@ pub fn sniff_root(path: &Path) -> Result<Option<(PathBuf, Identity)>> {
Ok(None)
}
fn try_env_var(var_suffix: &str) -> Result<String, VarError> {
pub fn env_var(var_suffix: &str) -> Option<Result<String, VarError>> {
let current_id = IDENTITY.read();
// Always prefer current identity.
if let Some(res) = current_id.env_var(var_suffix) {
return res;
return Some(res);
}
// Backwards compat for old env vars.
@ -184,11 +196,18 @@ fn try_env_var(var_suffix: &str) -> Result<String, VarError> {
}
if let Some(res) = id.env_var(var_suffix) {
return res;
return Some(res);
}
}
Err(VarError::NotPresent)
None
}
pub fn try_env_var(var_suffix: &str) -> Result<String, VarError> {
match env_var(var_suffix) {
Some(result) => result,
None => Err(VarError::NotPresent),
}
}
pub fn sniff_env() -> Identity {

View File

@ -5,3 +5,6 @@ name = "hgplain"
version = "0.1.0"
authors = ["Facebook Source Control Team <sourcecontrol-dev@fb.com>"]
edition = "2021"
[dependencies]
identity = { version = "0.1.0", path = "../../identity" }

View File

@ -5,15 +5,12 @@
* GNU General Public License version 2.
*/
use std::env;
pub const HGPLAIN: &str = "HGPLAIN";
pub const HGPLAINEXCEPT: &str = "HGPLAINEXCEPT";
use std::collections::HashSet;
/// Return whether plain mode is active, similar to python ui.plain().
pub fn is_plain(feature: Option<&str>) -> bool {
let plain = env::var(HGPLAIN);
let plain_except = env::var(HGPLAINEXCEPT);
let plain = identity::try_env_var("PLAIN");
let plain_except = identity::try_env_var("PLAINEXCEPT");
if plain.is_err() && plain_except.is_err() {
return false;
@ -28,3 +25,10 @@ pub fn is_plain(feature: Option<&str>) -> bool {
true
}
}
pub fn exceptions() -> HashSet<String> {
match identity::try_env_var("PLAINEXCEPT") {
Ok(value) => value.split(',').map(|s| s.to_string()).collect(),
Err(_) => HashSet::new(),
}
}