Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
Signed-off-by: Freyskeyd <[email protected]>
  • Loading branch information
Freyskeyd committed Oct 12, 2017
0 parents commit ef007ee
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/target/
**/*.rs.bk
Cargo.lock
44 changes: 44 additions & 0 deletions .travis.yml
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=""
6 changes: 6 additions & 0 deletions Cargo.toml
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 added README.md
Empty file.
2 changes: 2 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
format_strings = false
reorder_imports = true
237 changes: 237 additions & 0 deletions src/lib.rs
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"));
}
}

0 comments on commit ef007ee

Please sign in to comment.