context: run commands in the C locale by default
Subprocesses inherit the session environment, so a translated host locale leaked into builds: perl-based packaging tools (dpkg-architecture, dpkg-parsechangelog, quilt, ...) warned about missing locale settings, change their output with the environment, and dpkg-buildpackage treats some of that output as data. Default every command to LANG=C and LC_ALL=C; a caller can still override explicitly through envs().
This commit is contained in:
+38
-1
@@ -243,12 +243,22 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Make a command inside context
|
/// Make a command inside context
|
||||||
|
///
|
||||||
|
/// Build tooling must not inherit the session's locale: dpkg-family
|
||||||
|
/// tools and perl-based packaging scripts change their output (and
|
||||||
|
/// dpkg-buildpackage treats some of it as data) with the environment,
|
||||||
|
/// and a translated or mixed locale leaks host state into builds. The
|
||||||
|
/// C locale is the default; a caller can still override it by setting
|
||||||
|
/// LANG/LC_ALL through [`ContextCommand::envs`] afterwards.
|
||||||
pub fn command<S: AsRef<OsStr>>(&self, program: S) -> ContextCommand<'_> {
|
pub fn command<S: AsRef<OsStr>>(&self, program: S) -> ContextCommand<'_> {
|
||||||
ContextCommand {
|
ContextCommand {
|
||||||
context: self,
|
context: self,
|
||||||
program: program.as_ref().to_string_lossy().to_string(),
|
program: program.as_ref().to_string_lossy().to_string(),
|
||||||
args: Vec::new(),
|
args: Vec::new(),
|
||||||
env: Vec::new(),
|
env: vec![
|
||||||
|
("LANG".to_string(), "C".to_string()),
|
||||||
|
("LC_ALL".to_string(), "C".to_string()),
|
||||||
|
],
|
||||||
cwd: None,
|
cwd: None,
|
||||||
sink: None,
|
sink: None,
|
||||||
}
|
}
|
||||||
@@ -530,4 +540,31 @@ mod endpoint_tests {
|
|||||||
let err = ContextConfig::from_endpoint("host:99999").unwrap_err();
|
let err = ContextConfig::from_endpoint("host:99999").unwrap_err();
|
||||||
assert_eq!(err, "Invalid port number");
|
assert_eq!(err, "Invalid port number");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Commands run in the C locale whatever the session environment
|
||||||
|
/// carries: host locale variables must not leak into builds. An
|
||||||
|
/// explicit caller override still wins.
|
||||||
|
#[test]
|
||||||
|
fn commands_default_to_the_c_locale() {
|
||||||
|
let ctx = Context::new(ContextConfig::Local).unwrap();
|
||||||
|
|
||||||
|
let locale = ctx
|
||||||
|
.command("sh")
|
||||||
|
.arg("-c")
|
||||||
|
.arg("printf '%s' \"${LC_ALL:-unset}:${LANG:-unset}\"")
|
||||||
|
.output()
|
||||||
|
.unwrap()
|
||||||
|
.stdout;
|
||||||
|
assert_eq!(String::from_utf8_lossy(&locale), "C:C");
|
||||||
|
|
||||||
|
let locale = ctx
|
||||||
|
.command("sh")
|
||||||
|
.arg("-c")
|
||||||
|
.arg("printf '%s' \"$LC_ALL\"")
|
||||||
|
.env("LC_ALL", "C.UTF-8")
|
||||||
|
.output()
|
||||||
|
.unwrap()
|
||||||
|
.stdout;
|
||||||
|
assert_eq!(String::from_utf8_lossy(&locale), "C.UTF-8");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user