summaryrefslogtreecommitdiff
path: root/subplotlib
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2022-02-26 11:21:41 +0000
committerDaniel Silverstone <dsilvers@digital-scurf.org>2022-02-26 11:21:41 +0000
commit7e258b3f195f7a2112c351a6d9289374715c6b46 (patch)
treec160a8be861f9bc4315158d64de1ce8c8f7649f7 /subplotlib
parent2a4417efc4d0d578efc16a7e442278747cdb7a2c (diff)
downloadsubplot-7e258b3f195f7a2112c351a6d9289374715c6b46.tar.gz
(subplotlib): Add a test for PATH prepending in Runcmd
Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
Diffstat (limited to 'subplotlib')
-rw-r--r--subplotlib/src/steplibrary/runcmd.rs98
1 files changed, 75 insertions, 23 deletions
diff --git a/subplotlib/src/steplibrary/runcmd.rs b/subplotlib/src/steplibrary/runcmd.rs
index aee675e..8ed4f4f 100644
--- a/subplotlib/src/steplibrary/runcmd.rs
+++ b/subplotlib/src/steplibrary/runcmd.rs
@@ -6,10 +6,10 @@ pub use super::datadir::Datadir;
pub use crate::prelude::*;
use std::collections::HashMap;
-use std::env;
+use std::env::{self, JoinPathsError};
use std::ffi::{OsStr, OsString};
use std::io::Write;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
/// The Runcmd context gives a step function access to the ability to run
@@ -89,6 +89,76 @@ impl Runcmd {
pub fn stderr_as_string(&self) -> String {
String::from_utf8_lossy(&self.stderr).into_owned()
}
+
+ /// Set an env var in the Runcmd context
+ ///
+ /// This sets an environment variable into the Runcmd context for use
+ /// during execution
+ pub fn setenv<K: Into<OsString>, V: Into<OsString>>(&mut self, key: K, value: V) {
+ self.env.insert(key.into(), value.into());
+ }
+
+ /// Get an env var from the Runcmd context
+ ///
+ /// This retrieves a set environment variable from the Runcmd context
+ pub fn getenv<K: AsRef<OsStr>>(&self, key: K) -> Option<&OsStr> {
+ self.env.get(key.as_ref()).map(OsString::as_os_str)
+ }
+
+ /// Unset an env var in the Runcmd context
+ ///
+ /// This removes an environment variable (if set) from the Runcmd context
+ /// and returns whether or not it was removed.
+ pub fn unsetenv<K: AsRef<OsStr>>(&mut self, key: K) -> bool {
+ self.env.remove(key.as_ref()).is_some()
+ }
+
+ /// Join the `PATH` environment variable and the `paths` attribute
+ /// together properly.
+ ///
+ /// This prepends the paths (in reverse order) to the `PATH` environment
+ /// variable and then returns it.
+ ///
+ /// If there is no `PATH` in the stored environment then the resultant
+ /// path will be entirely made up of the pushed path elements
+ ///
+ /// ```
+ /// # use subplotlib::steplibrary::runcmd::Runcmd;
+ ///
+ /// let mut rc = Runcmd::default();
+ ///
+ /// assert_eq!(rc.join_paths().unwrap(), "");
+ ///
+ /// rc.setenv("PATH", "one");
+ /// assert_eq!(rc.join_paths().unwrap(), "one");
+ ///
+ /// rc.prepend_to_path("two");
+ /// assert_eq!(rc.join_paths().unwrap(), "two:one");
+ ///
+ /// rc.unsetenv("PATH");
+ /// assert_eq!(rc.join_paths().unwrap(), "two");
+ ///
+ /// rc.prepend_to_path("three");
+ /// assert_eq!(rc.join_paths().unwrap(), "three:two");
+ ///
+ /// rc.setenv("PATH", "one");
+ /// assert_eq!(rc.join_paths().unwrap(), "three:two:one");
+ /// ```
+ ///
+ pub fn join_paths(&self) -> Result<OsString, JoinPathsError> {
+ let curpath = self
+ .env
+ .get(OsStr::new("PATH"))
+ .map(|s| s.as_os_str())
+ .unwrap_or_else(|| OsStr::new(""));
+ env::join_paths(
+ self.paths
+ .iter()
+ .rev()
+ .map(PathBuf::from)
+ .chain(env::split_paths(curpath).filter(|p| p != Path::new(""))),
+ )
+ }
}
/// Ensure the given data file is available as a script in the data dir
@@ -196,35 +266,17 @@ pub fn try_to_run_in(context: &ScenarioContext, dirname: &str, argv0: &str, args
proc.env("HOME", &datadir);
proc.env("TMPDIR", &datadir);
- let mut curpath = context.with(
+ context.with(
|runcmd: &Runcmd| {
- let mut curpath = None;
for (k, v) in runcmd.env.iter() {
proc.env(k, v);
- if k == "PATH" {
- curpath = Some(v.to_owned());
- }
}
- Ok(curpath)
+ Ok(())
},
false,
)?;
- let path = context.with(
- |runcmd: &Runcmd| {
- Ok(env::join_paths(
- runcmd
- .paths
- .iter()
- .rev()
- .map(PathBuf::from)
- .chain(env::split_paths(
- curpath.as_deref().unwrap_or_else(|| OsStr::new("")),
- )),
- )?)
- },
- false,
- )?;
+ let path = context.with(|runcmd: &Runcmd| Ok(runcmd.join_paths()?), false)?;
proc.env("PATH", path);
proc.stdin(Stdio::null())
.stdout(Stdio::piped())