io::process::Command: add fine-grained env builder

This commit changes the `io::process::Command` API to provide
fine-grained control over the environment:

* The `env` method now inserts/updates a key/value pair.
* The `env_remove` method removes a key from the environment.
* The old `env` method, which sets the entire environment in one shot,
  is renamed to `env_set_all`. It can be used in conjunction with the
  finer-grained methods. This renaming is a breaking change.

To support these new methods, the internal `env` representation for
`Command` has been changed to an optional `HashMap` holding owned
`CString`s (to support non-utf8 data). The `HashMap` is only
materialized if the environment is updated. The implementation does not
try hard to avoid allocation, since the cost of launching a process will
dwarf any allocation cost.

This patch also adds `PartialOrd`, `Eq`, and `Hash` implementations for
`CString`.

[breaking-change]
This commit is contained in:
Aaron Turon 2014-07-02 13:50:45 -07:00
parent f9fe251777
commit bfa853f8ed
11 changed files with 137 additions and 72 deletions

View file

@ -176,26 +176,15 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
// environment to ensure that the target loads the right libraries at
// runtime. It would be a sad day if the *host* libraries were loaded as a
// mistake.
let exe = outdir.path().join("rust_out");
let env = {
let mut cmd = Command::new(outdir.path().join("rust_out"));
let newpath = {
let mut path = DynamicLibrary::search_path();
path.insert(0, libdir.clone());
// Remove the previous dylib search path var
let var = DynamicLibrary::envvar();
let mut env: Vec<(String,String)> = os::env().move_iter().collect();
match env.iter().position(|&(ref k, _)| k.as_slice() == var) {
Some(i) => { env.remove(i); }
None => {}
};
// Add the new dylib search path var
let newpath = DynamicLibrary::create_path(path.as_slice());
env.push((var.to_string(),
str::from_utf8(newpath.as_slice()).unwrap().to_string()));
env
DynamicLibrary::create_path(path.as_slice())
};
match Command::new(exe).env(env.as_slice()).output() {
cmd.env(DynamicLibrary::envvar(), newpath.as_slice());
match cmd.output() {
Err(e) => fail!("couldn't run the test: {}{}", e,
if e.kind == io::PermissionDenied {
" - maybe your tempdir is mounted with noexec?"