mirror of
https://github.com/uutils/coreutils
synced 2024-12-15 07:42:48 +00:00
Fix env and add tests.
I updated env to use the nightly build. I also added several tests.
This commit is contained in:
parent
1f2b68251f
commit
500bbbfa83
2 changed files with 88 additions and 34 deletions
56
src/env/env.rs
vendored
56
src/env/env.rs
vendored
|
@ -1,5 +1,4 @@
|
|||
#![crate_name = "env"]
|
||||
#![feature(core, old_io, os)]
|
||||
|
||||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
|
@ -13,7 +12,9 @@
|
|||
/* last synced with: env (GNU coreutils) 8.13 */
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
|
||||
struct options {
|
||||
ignore_env: bool,
|
||||
|
@ -42,28 +43,22 @@ fn version() {
|
|||
// print name=value env pairs on screen
|
||||
// if null is true, separate pairs with a \0, \n otherwise
|
||||
fn print_env(null: bool) {
|
||||
let env = std::os::env();
|
||||
|
||||
for &(ref n, ref v) in env.iter() {
|
||||
print!("{}={}{}",
|
||||
n.as_slice(),
|
||||
v.as_slice(),
|
||||
if null { '\0' } else { '\n' }
|
||||
);
|
||||
for (n, v) in env::vars() {
|
||||
print!("{}={}{}", n, v, if null { '\0' } else { '\n' });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let prog = args[0].as_slice();
|
||||
let prog = &args[0];
|
||||
|
||||
// to handle arguments the same way than GNU env, we can't use getopts
|
||||
let mut opts = box options {
|
||||
let mut opts = Box::new(options {
|
||||
ignore_env: false,
|
||||
null: false,
|
||||
unsets: vec!(),
|
||||
sets: vec!(),
|
||||
program: vec!()
|
||||
};
|
||||
});
|
||||
|
||||
let mut wait_cmd = false;
|
||||
let mut iter = args.iter();
|
||||
|
@ -78,7 +73,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
|
||||
if wait_cmd {
|
||||
// we still accept NAME=VAL here but not other options
|
||||
let mut sp = opt.as_slice().splitn(1, '=');
|
||||
let mut sp = opt.splitn(2, '=');
|
||||
let name = sp.next();
|
||||
let value = sp.next();
|
||||
|
||||
|
@ -92,8 +87,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else if opt.as_slice().starts_with("--") {
|
||||
match opt.as_slice() {
|
||||
} else if opt.starts_with("--") {
|
||||
match opt.as_ref() {
|
||||
"--help" => { usage(prog); return 0; }
|
||||
"--version" => { version(); return 0; }
|
||||
|
||||
|
@ -103,7 +98,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
let var = iter.next();
|
||||
|
||||
match var {
|
||||
None => println!("{}: this option requires an argument: {}", prog, opt.as_slice()),
|
||||
None => println!("{}: this option requires an argument: {}", prog, opt),
|
||||
Some(s) => opts.unsets.push(s.to_string())
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +109,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
} else if opt.as_slice().starts_with("-") {
|
||||
} else if opt.starts_with("-") {
|
||||
if opt.len() == 0 {
|
||||
// implies -i and stop parsing opts
|
||||
wait_cmd = true;
|
||||
|
@ -122,7 +117,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut chars = opt.as_slice().chars();
|
||||
let mut chars = opt.chars();
|
||||
chars.next();
|
||||
|
||||
for c in chars {
|
||||
|
@ -136,7 +131,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
let var = iter.next();
|
||||
|
||||
match var {
|
||||
None => println!("{}: this option requires an argument: {}", prog, opt.as_slice()),
|
||||
None => println!("{}: this option requires an argument: {}", prog, opt),
|
||||
Some(s) => opts.unsets.push(s.to_string())
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +144,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
}
|
||||
} else {
|
||||
// is it a NAME=VALUE like opt ?
|
||||
let mut sp = opt.as_slice().splitn(1, '=');
|
||||
let mut sp = opt.splitn(2, "=");
|
||||
let name = sp.next();
|
||||
let value = sp.next();
|
||||
|
||||
|
@ -175,32 +170,25 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
opts.program.push(opt.to_string());
|
||||
}
|
||||
|
||||
let env = std::os::env();
|
||||
|
||||
if opts.ignore_env {
|
||||
for &(ref name, _) in env.iter() {
|
||||
std::os::unsetenv(name.as_slice())
|
||||
for (ref name, _) in env::vars() {
|
||||
env::remove_var(name);
|
||||
}
|
||||
}
|
||||
|
||||
for name in opts.unsets.iter() {
|
||||
std::os::unsetenv((name).as_slice())
|
||||
env::remove_var(name);
|
||||
}
|
||||
|
||||
for &(ref name, ref val) in opts.sets.iter() {
|
||||
std::os::setenv(name.as_slice(), val.as_slice())
|
||||
env::set_var(name, val);
|
||||
}
|
||||
|
||||
if opts.program.len() >= 1 {
|
||||
use std::old_io::process::{Command, InheritFd};
|
||||
let prog = opts.program[0].clone();
|
||||
let args = &opts.program[1..];
|
||||
match Command::new(prog).args(args).stdin(InheritFd(0)).stdout(InheritFd(1)).stderr(InheritFd(2)).status() {
|
||||
Ok(exit) =>
|
||||
return match exit {
|
||||
std::old_io::process::ExitStatus(s) => s as i32,
|
||||
_ => 1
|
||||
},
|
||||
match Command::new(prog).args(args).status() {
|
||||
Ok(exit) => return if exit.success() { 0 } else { exit.code().unwrap() },
|
||||
Err(_) => return 1
|
||||
}
|
||||
} else {
|
||||
|
|
66
test/env.rs
Normal file
66
test/env.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use std::process::Command;
|
||||
use std::str;
|
||||
|
||||
static PROGNAME: &'static str = "./env";
|
||||
|
||||
#[test]
|
||||
fn test_single_name_value_pair() {
|
||||
let po = Command::new(PROGNAME)
|
||||
.arg("FOO=bar")
|
||||
.output()
|
||||
.unwrap_or_else(|err| panic!("{}", err));
|
||||
|
||||
let out = str::from_utf8(&po.stdout[..]).unwrap();
|
||||
assert!(out.lines_any().any(|line| line == "FOO=bar"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_name_value_pairs() {
|
||||
let po = Command::new(PROGNAME)
|
||||
.arg("FOO=bar")
|
||||
.arg("ABC=xyz")
|
||||
.output()
|
||||
.unwrap_or_else(|err| panic!("{}", err));
|
||||
|
||||
let out = str::from_utf8(&po.stdout[..]).unwrap();
|
||||
assert_eq!(out.lines_any().filter(|&line| line == "FOO=bar" || line == "ABC=xyz").count(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ignore_environment() {
|
||||
let po = Command::new(PROGNAME)
|
||||
.arg("-i")
|
||||
.output()
|
||||
.unwrap_or_else(|err| panic!("{}", err));
|
||||
|
||||
let out = str::from_utf8(&po.stdout[..]).unwrap();
|
||||
assert_eq!(out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_null_delimiter() {
|
||||
let po = Command::new(PROGNAME)
|
||||
.arg("-i")
|
||||
.arg("--null")
|
||||
.arg("FOO=bar")
|
||||
.arg("ABC=xyz")
|
||||
.output()
|
||||
.unwrap_or_else(|err| panic!("{}", err));
|
||||
|
||||
let out = str::from_utf8(&po.stdout[..]).unwrap();
|
||||
assert_eq!(out, "FOO=bar\0ABC=xyz\0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unset_variable() {
|
||||
// This test depends on the HOME variable being pre-defined by the
|
||||
// default shell
|
||||
let po = Command::new(PROGNAME)
|
||||
.arg("-u")
|
||||
.arg("HOME")
|
||||
.output()
|
||||
.unwrap_or_else(|err| panic!("{}", err));
|
||||
|
||||
let out = str::from_utf8(&po.stdout[..]).unwrap();
|
||||
assert_eq!(out.lines_any().any(|line| line.starts_with("HOME=")), false);
|
||||
}
|
Loading…
Reference in a new issue