diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2022-02-26 11:21:41 +0000 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2022-02-26 11:21:41 +0000 |
commit | 7e258b3f195f7a2112c351a6d9289374715c6b46 (patch) | |
tree | c160a8be861f9bc4315158d64de1ce8c8f7649f7 /subplotlib | |
parent | 2a4417efc4d0d578efc16a7e442278747cdb7a2c (diff) | |
download | subplot-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.rs | 98 |
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()) |