Skip to content

Commit

Permalink
feature[env]: Add support for --chdir=DIR in env (fixes #1568) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
FelipeLema authored and rivy committed Aug 9, 2020
1 parent d9be24e commit ba6b55f
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/uu/env/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ A mere - implies -i. If no COMMAND, print the resulting environment.
struct Options<'a> {
ignore_env: bool,
null: bool,
running_directory: Option<&'a str>,
files: Vec<&'a str>,
unsets: Vec<&'a str>,
sets: Vec<(&'a str, &'a str)>,
Expand Down Expand Up @@ -128,6 +129,13 @@ fn create_app() -> App<'static, 'static> {
.short("i")
.long("ignore-environment")
.help("start with an empty environment"))
.arg(Arg::with_name("chdir")
.short("c")
.long("chdir")
.takes_value(true)
.number_of_values(1)
.value_name("DIR")
.help("change working directory to DIR"))
.arg(Arg::with_name("null")
.short("0")
.long("null")
Expand Down Expand Up @@ -158,6 +166,7 @@ fn run_env(args: impl uucore::Args) -> Result<(), i32> {

let ignore_env = matches.is_present("ignore-environment");
let null = matches.is_present("null");
let running_directory = matches.value_of("chdir");
let files = matches
.values_of("file")
.map(Iterator::collect)
Expand All @@ -170,12 +179,24 @@ fn run_env(args: impl uucore::Args) -> Result<(), i32> {
let mut opts = Options {
ignore_env,
null,
running_directory,
files,
unsets,
sets: vec![],
program: vec![],
};

// change directory
if let Some(d) = opts.running_directory {
match env::set_current_dir(d) {
Ok(()) => d,
Err(error) => {
eprintln!("env: cannot change directory to \"{}\": {}", d, error);
return Err(125);
}
};
}

// we handle the name, value pairs and the program to be executed by treating them as external
// subcommands in clap
if let (external, Some(matches)) = matches.subcommand() {
Expand Down
68 changes: 68 additions & 0 deletions tests/by-util/test_env.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
#[cfg(not(windows))]
use std::fs;

use std::path::Path;
extern crate tempfile;
use self::tempfile::tempdir;
use crate::common::util::*;
use std::env;

#[test]
fn test_env_help() {
Expand Down Expand Up @@ -150,3 +157,64 @@ fn test_fail_null_with_program() {
let out = new_ucmd!().arg("--null").arg("cd").fails().stderr;
assert!(out.contains("cannot specify --null (-0) with command"));
}

#[cfg(not(windows))]
#[test]
fn test_change_directory() {
let scene = TestScenario::new(util_name!());
let temporary_directory = tempdir().unwrap();
let temporary_path = fs::canonicalize(temporary_directory.path()).unwrap();
assert_ne!(env::current_dir().unwrap(), temporary_path);

// command to print out current working directory
let pwd = "pwd";

let out = scene
.ucmd()
.arg("--chdir")
.arg(&temporary_path)
.arg(pwd)
.run()
.stdout;
assert_eq!(out.trim(), temporary_path.as_os_str())
}

// no way to consistently get "current working directory", `cd` doesn't work @ CI
// instead, we test that the unique temporary directory appears somewhere in the printed variables
#[cfg(windows)]
#[test]
fn test_change_directory() {
let scene = TestScenario::new(util_name!());
let temporary_directory = tempdir().unwrap();
let temporary_path = temporary_directory.path();

assert_ne!(env::current_dir().unwrap(), temporary_path);

let out = scene
.ucmd()
.arg("--chdir")
.arg(&temporary_path)
.run()
.stdout;
assert_eq!(
out.lines()
.any(|line| line.ends_with(temporary_path.file_name().unwrap().to_str().unwrap())),
false
);
}

#[test]
fn test_fail_change_directory() {
let scene = TestScenario::new(util_name!());
let some_non_existing_path = "some_nonexistent_path";
assert_eq!(Path::new(some_non_existing_path).is_dir(), false);

let out = scene
.ucmd()
.arg("--chdir")
.arg(some_non_existing_path)
.arg("pwd")
.fails()
.stderr;
assert!(out.contains("env: cannot change directory to "));
}

0 comments on commit ba6b55f

Please sign in to comment.