-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
6 changed files
with
292 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/target/ | ||
**/*.rs.bk | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
sudo: false | ||
language: rust | ||
cache: cargo | ||
rust: | ||
- beta | ||
- stable | ||
- nightly | ||
matrix: | ||
include: | ||
- rust: nightly-2017-10-09 | ||
env: CLIPPY_VERS="0.0.165" | ||
before_script: | | ||
[[ "$(cargo +nightly-2017-10-09 clippy --version)" != "$CLIPPY_VERS" ]] && \ | ||
cargo +nightly-2017-10-09 install clippy --vers "$CLIPPY_VERS" --force || true | ||
script: | | ||
cargo +nightly-2017-10-09 clippy -- -D warnings | ||
- rust: nightly-2017-10-09 | ||
env: RUSTFMT_VERS="0.2.8" | ||
before_script: | | ||
[[ "$(cargo +nightly-2017-10-09 fmt -- --version)" != "$RUSTFMT_VERS"* ]] && \ | ||
cargo +nightly-2017-10-09 install rustfmt-nightly --vers "$RUSTFMT_VERS" --force || true | ||
script: | | ||
cargo +nightly-2017-10-09 fmt --all -- --write-mode=diff | ||
before_script: | ||
- | | ||
pip install 'travis-cargo<0.2' --user && | ||
export PATH=$HOME/.local/bin:$PATH | ||
script: | ||
- | | ||
travis-cargo build && | ||
travis-cargo clean && | ||
travis-cargo test && | ||
travis-cargo bench | ||
notifications: | ||
email: | ||
on_success: never | ||
branches: | ||
only: | ||
- master | ||
- staging | ||
- trying | ||
env: | ||
global: | ||
- TRAVIS_CARGO_NIGHTLY_FEATURE="" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[package] | ||
name = "environment" | ||
version = "0.1.0" | ||
authors = ["Freyskeyd <[email protected]>"] | ||
|
||
[dependencies] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
format_strings = false | ||
reorder_imports = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
use std::ffi::OsString; | ||
|
||
/// Structure to deal with environment variables | ||
#[derive(Clone, Debug, PartialEq, Eq)] | ||
pub struct Environment { | ||
/// Customized environment variables | ||
vars: Vec<(OsString, OsString)>, | ||
/// Define if the structure must inherit | ||
inherit: bool, | ||
} | ||
|
||
impl Default for Environment { | ||
fn default() -> Self { | ||
Self { | ||
vars: vec![], | ||
inherit: false, | ||
} | ||
} | ||
} | ||
|
||
impl Environment { | ||
/// Create a new Environment that inherits this process' environment. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ```rust | ||
/// extern crate environment; | ||
/// use std::ffi::OsString; | ||
/// | ||
/// let e = environment::Environment::inherit().compile(); | ||
/// let e_: Vec<(OsString, OsString)> = ::std::env::vars_os().collect(); | ||
/// | ||
/// assert_eq!(e, e_); | ||
/// ``` | ||
pub fn inherit() -> Self { | ||
Self { | ||
vars: vec![], | ||
inherit: true, | ||
} | ||
} | ||
|
||
/// Create a new Environment independent of the current process's Environment | ||
/// | ||
/// # Examples | ||
/// | ||
/// ```rust | ||
/// extern crate environment; | ||
/// | ||
/// let e = environment::Environment::empty().compile(); | ||
/// assert_eq!(e, Vec::new()); | ||
/// ``` | ||
pub fn empty() -> Self { | ||
Self::default() | ||
} | ||
|
||
/// Insert a new entry into the custom variables for this environment object | ||
/// | ||
/// # Examples | ||
/// | ||
/// ```rust | ||
/// extern crate environment; | ||
/// | ||
/// use std::ffi::OsString; | ||
/// | ||
/// let e = environment::Environment::empty().insert("foo", "bar").compile(); | ||
/// assert_eq!(e, vec![(OsString::from("foo"), OsString::from("bar"))]); | ||
/// ``` | ||
pub fn insert<S1: Into<OsString>, S2: Into<OsString>>(mut self, key: S1, val: S2) -> Self { | ||
self.vars.push((key.into(), val.into())); | ||
self | ||
} | ||
|
||
/// Compile Environment object | ||
pub fn compile(self) -> Vec<(OsString, OsString)> { | ||
if self.inherit { | ||
::std::env::vars_os().chain(self.vars).collect() | ||
} else { | ||
self.vars | ||
} | ||
} | ||
} | ||
|
||
/// Implicit clone for ergonomics | ||
impl<'a> From<&'a Environment> for Environment { | ||
fn from(v: &'a Environment) -> Self { | ||
v.clone() | ||
} | ||
} | ||
|
||
pub trait EnvironmentItem { | ||
fn to_environment_tuple(&self) -> (OsString, OsString); | ||
} | ||
|
||
impl<T: ToString, Z: ToString> EnvironmentItem for (T, Z) { | ||
fn to_environment_tuple(&self) -> (OsString, OsString) { | ||
( | ||
OsString::from(self.0.to_string()), | ||
OsString::from(self.1.to_string()), | ||
) | ||
} | ||
} | ||
|
||
impl<'s, T: ToString, Z: ToString> EnvironmentItem for &'s (T, Z) { | ||
fn to_environment_tuple(&self) -> (OsString, OsString) { | ||
( | ||
OsString::from(self.0.to_string()), | ||
OsString::from(self.1.to_string()), | ||
) | ||
} | ||
} | ||
|
||
impl<'s, T> From<T> for Environment | ||
where | ||
T: IntoIterator, | ||
T::Item: EnvironmentItem, | ||
{ | ||
fn from(v: T) -> Self { | ||
Self { | ||
vars: v.into_iter().map(|k| k.to_environment_tuple()).collect(), | ||
inherit: false, | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
use std::borrow::Cow; | ||
use std::process::Command; | ||
|
||
#[test] | ||
fn take_ownership() { | ||
let x = Environment::inherit(); | ||
|
||
let mut c = Command::new("printenv"); | ||
c.env_clear().envs(x.clone().compile()).envs(x.compile()); | ||
} | ||
|
||
#[test] | ||
fn in_place_mod() { | ||
let y = Environment::empty(); | ||
|
||
let y = y.insert("key", "value"); | ||
|
||
assert_eq!( | ||
y.compile(), | ||
vec![(OsString::from("key"), OsString::from("value"))] | ||
); | ||
} | ||
|
||
#[test] | ||
fn in_place_mod2() { | ||
let x = Environment::inherit(); | ||
|
||
let mut c = Command::new("printenv"); | ||
|
||
let output = c.env_clear() | ||
.envs(x.insert("key", "value").insert("key", "vv").compile()) | ||
.output() | ||
.expect("failed to execute command"); | ||
|
||
let output = String::from_utf8_lossy(&output.stdout); | ||
|
||
assert!(output.contains("key=vv")); | ||
// Granted, `insert` moved `x`, so we can no longer reference it, even | ||
// though only a reference was passed to `envs` | ||
} | ||
|
||
#[test] | ||
fn in_place_mod3() { | ||
// In-place modification while allowing later accesses to the `Environment` | ||
let y = Environment::empty(); | ||
|
||
assert_eq!( | ||
y.clone().insert("key", "value").compile(), | ||
vec![(OsString::from("key"), OsString::from("value"))] | ||
); | ||
|
||
let mut c = Command::new("printenv"); | ||
|
||
let output = c.env_clear() | ||
.envs(y.compile()) | ||
.output() | ||
.expect("failed to execute command"); | ||
|
||
let output = String::from_utf8_lossy(&output.stdout); | ||
|
||
assert_eq!(output, ""); | ||
} | ||
|
||
#[test] | ||
fn empty_env() { | ||
// In-place modification while allowing later accesses to the `Environment` | ||
let y = Environment::empty(); | ||
|
||
let mut c = Command::new("printenv"); | ||
|
||
let output = c.env_clear() | ||
.envs(y.compile()) | ||
.output() | ||
.expect("failed to execute command"); | ||
|
||
let output = String::from_utf8_lossy(&output.stdout); | ||
|
||
assert!(output.is_empty()); | ||
} | ||
|
||
#[test] | ||
fn take_vec() { | ||
let v = vec![("bar", "baz")]; | ||
|
||
let e: Environment = v.into(); | ||
|
||
let mut c = Command::new("printenv"); | ||
|
||
let output = c.env_clear() | ||
.envs(e.clone().compile()) | ||
.output() | ||
.expect("failed to execute command"); | ||
|
||
let output = String::from_utf8_lossy(&output.stdout); | ||
|
||
assert!(output.contains("bar=baz")); | ||
|
||
let mut c = Command::new("printenv"); | ||
|
||
let output = c.env_clear() | ||
.envs(e.clone().insert("bar", "vv").compile()) | ||
.output() | ||
.expect("failed to execute command"); | ||
|
||
let output = String::from_utf8_lossy(&output.stdout); | ||
|
||
assert!(output.contains("bar=vv")); | ||
assert!(!output.contains("bar=baz")); | ||
} | ||
} |