Merge pull request #286 from androbtech/mv-and-bitsmoar

Moving file/dir in place and some refactored a little.
This commit is contained in:
Jonathan Turner 2019-08-15 13:37:10 +12:00 committed by GitHub
commit d11d840f0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 697 additions and 188 deletions

View File

@ -130,6 +130,7 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat
| cp source path | Copy files | | cp source path | Copy files |
| ls (path) | View the contents of the current or given path | | ls (path) | View the contents of the current or given path |
| mkdir path | Make directories, creates intermediary directories as required. | | mkdir path | Make directories, creates intermediary directories as required. |
| mv source target | Move files or directories. |
| date (--utc) | Get the current datetime | | date (--utc) | Get the current datetime |
| ps | View current processes | | ps | View current processes |
| sys | View information about the current system | | sys | View information about the current system |

View File

@ -189,9 +189,10 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
static_command(Exit), static_command(Exit),
static_command(Clip), static_command(Clip),
static_command(Autoview), static_command(Autoview),
static_command(Copycp), static_command(Cpy),
static_command(Date), static_command(Date),
static_command(Mkdir), static_command(Mkdir),
static_command(Move),
static_command(Save), static_command(Save),
static_command(Table), static_command(Table),
static_command(VTable), static_command(VTable),

View File

@ -25,6 +25,7 @@ crate mod get;
crate mod lines; crate mod lines;
crate mod ls; crate mod ls;
crate mod mkdir; crate mod mkdir;
crate mod mv;
crate mod next; crate mod next;
crate mod nth; crate mod nth;
crate mod open; crate mod open;
@ -61,12 +62,13 @@ crate use command::{
RawCommandArgs, StaticCommand, UnevaluatedCallInfo, RawCommandArgs, StaticCommand, UnevaluatedCallInfo,
}; };
crate use config::Config; crate use config::Config;
crate use cp::Copycp; crate use cp::Cpy;
crate use date::Date; crate use date::Date;
crate use enter::Enter; crate use enter::Enter;
crate use exit::Exit; crate use exit::Exit;
crate use get::Get; crate use get::Get;
crate use mkdir::Mkdir; crate use mkdir::Mkdir;
crate use mv::Move;
crate use open::Open; crate use open::Open;
crate use rm::Remove; crate use rm::Remove;
crate use save::Save; crate use save::Save;

View File

@ -2,11 +2,12 @@ use crate::errors::ShellError;
use crate::parser::hir::SyntaxType; use crate::parser::hir::SyntaxType;
use crate::parser::registry::{CommandRegistry, Signature}; use crate::parser::registry::{CommandRegistry, Signature};
use crate::prelude::*; use crate::prelude::*;
use std::path::{Path, PathBuf}; use crate::utils::FileStructure;
use std::path::PathBuf;
pub struct Copycp; pub struct Cpy;
impl StaticCommand for Copycp { impl StaticCommand for Cpy {
fn run( fn run(
&self, &self,
args: CommandArgs, args: CommandArgs,
@ -26,75 +27,6 @@ impl StaticCommand for Copycp {
} }
} }
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Res {
pub loc: PathBuf,
pub at: usize,
}
impl Res {}
pub struct FileStructure {
root: PathBuf,
resources: Vec<Res>,
}
impl FileStructure {
pub fn new() -> FileStructure {
FileStructure {
root: PathBuf::new(),
resources: Vec::<Res>::new(),
}
}
pub fn set_root(&mut self, path: &Path) {
self.root = path.to_path_buf();
}
pub fn paths_applying_with<F>(&mut self, to: F) -> Vec<(PathBuf, PathBuf)>
where
F: Fn((PathBuf, usize)) -> (PathBuf, PathBuf),
{
self.resources
.iter()
.map(|f| (PathBuf::from(&f.loc), f.at))
.map(|f| to(f))
.collect()
}
pub fn walk_decorate(&mut self, start_path: &Path) {
self.set_root(&dunce::canonicalize(start_path).unwrap());
self.resources = Vec::<Res>::new();
self.build(start_path, 0);
self.resources.sort();
}
fn build(&mut self, src: &'a Path, lvl: usize) {
let source = dunce::canonicalize(src).unwrap();
if source.is_dir() {
for entry in std::fs::read_dir(&source).unwrap() {
let entry = entry.unwrap();
let path = entry.path();
if path.is_dir() {
self.build(&path, lvl + 1);
}
self.resources.push(Res {
loc: path.to_path_buf(),
at: lvl,
});
}
} else {
self.resources.push(Res {
loc: source,
at: lvl,
});
}
}
}
pub fn cp(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> { pub fn cp(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let mut source = PathBuf::from(args.shell_manager.path()); let mut source = PathBuf::from(args.shell_manager.path());
let mut destination = PathBuf::from(args.shell_manager.path()); let mut destination = PathBuf::from(args.shell_manager.path());
@ -306,10 +238,10 @@ pub fn cp(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
} }
} else { } else {
if destination.exists() { if destination.exists() {
if !sources.iter().all(|x| (x.as_ref().unwrap()).is_file()) && !args.has("recursive") { if !sources.iter().all(|x| (x.as_ref().unwrap()).is_file()) {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
"Copy aborted (directories found). Try using \"--recursive\".", "Copy aborted (directories found). Recursive copying in patterns not supported yet (try copying the directory directly)",
"Copy aborted (directories found). Try using \"--recursive\".", "Copy aborted (directories found). Recursive copying in patterns not supported yet (try copying the directory directly)",
args.nth(0).unwrap().span(), args.nth(0).unwrap().span(),
)); ));
} }
@ -319,18 +251,20 @@ pub fn cp(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
let mut to = PathBuf::from(&destination); let mut to = PathBuf::from(&destination);
to.push(&entry.file_name().unwrap()); to.push(&entry.file_name().unwrap());
if entry.is_file() {
match std::fs::copy(&entry, &to) { match std::fs::copy(&entry, &to) {
Err(e) => { Err(e) => {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
name_span, args.nth(0).unwrap().span(),
)); ));
} }
Ok(o) => o, Ok(o) => o,
}; };
} }
} }
}
} else { } else {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!( format!(
@ -348,58 +282,3 @@ pub fn cp(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
Ok(OutputStream::empty()) Ok(OutputStream::empty())
} }
#[cfg(test)]
mod tests {
use super::{FileStructure, Res};
use std::path::PathBuf;
fn fixtures() -> PathBuf {
let mut sdx = PathBuf::new();
sdx.push("tests");
sdx.push("fixtures");
sdx.push("formats");
dunce::canonicalize(sdx).unwrap()
}
#[test]
fn prepares_and_decorates_source_files_for_copying() {
let mut res = FileStructure::new();
res.walk_decorate(fixtures().as_path());
assert_eq!(
res.resources,
vec![
Res {
loc: fixtures().join("appveyor.yml"),
at: 0
},
Res {
loc: fixtures().join("caco3_plastics.csv"),
at: 0
},
Res {
loc: fixtures().join("cargo_sample.toml"),
at: 0
},
Res {
loc: fixtures().join("jonathan.xml"),
at: 0
},
Res {
loc: fixtures().join("sample.ini"),
at: 0
},
Res {
loc: fixtures().join("sgml_description.json"),
at: 0
},
Res {
loc: fixtures().join("utf16.ini"),
at: 0
}
]
);
}
}

279
src/commands/mv.rs Normal file
View File

@ -0,0 +1,279 @@
use crate::errors::ShellError;
use crate::parser::hir::SyntaxType;
use crate::parser::registry::{CommandRegistry, Signature};
use crate::prelude::*;
use std::path::PathBuf;
#[cfg(windows)]
use crate::utils::FileStructure;
pub struct Move;
impl StaticCommand for Move {
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
mv(args, registry)
}
fn name(&self) -> &str {
"mv"
}
fn signature(&self) -> Signature {
Signature::build("mv").named("file", SyntaxType::Any)
}
}
pub fn mv(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let mut source = PathBuf::from(args.shell_manager.path());
let mut destination = PathBuf::from(args.shell_manager.path());
let span = args.name_span();
let args = args.evaluate_once(registry)?;
match args
.nth(0)
.ok_or_else(|| ShellError::string(&format!("No file or directory specified")))?
.as_string()?
.as_str()
{
file => {
source.push(file);
}
}
match args
.nth(1)
.ok_or_else(|| ShellError::string(&format!("No file or directory specified")))?
.as_string()?
.as_str()
{
file => {
destination.push(file);
}
}
let sources = glob::glob(&source.to_string_lossy());
if sources.is_err() {
return Err(ShellError::labeled_error(
"Invalid pattern.",
"Invalid pattern.",
args.nth(0).unwrap().span(),
));
}
let sources: Vec<_> = sources.unwrap().collect();
if sources.len() == 1 {
if let Ok(entry) = &sources[0] {
if destination.exists() && destination.is_dir() {
destination = dunce::canonicalize(&destination).unwrap();
destination.push(source.file_name().unwrap());
}
if entry.is_file() {
match std::fs::rename(&entry, &destination) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
span,
));
}
Ok(o) => o,
};
}
if entry.is_dir() {
match std::fs::create_dir_all(&destination) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
span,
));
}
Ok(o) => o,
};
#[cfg(not(windows))]
{
match std::fs::rename(&entry, &destination) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
span,
));
}
Ok(o) => o,
};
}
#[cfg(windows)]
{
let mut sources: FileStructure = FileStructure::new();
sources.walk_decorate(&entry);
let strategy = |(source_file, depth_level)| {
let mut new_dst = destination.clone();
let path = dunce::canonicalize(&source_file).unwrap();
let mut comps: Vec<_> = path
.components()
.map(|fragment| fragment.as_os_str())
.rev()
.take(1 + depth_level)
.collect();
comps.reverse();
for fragment in comps.iter() {
new_dst.push(fragment);
}
(PathBuf::from(&source_file), PathBuf::from(new_dst))
};
for (ref src, ref dst) in sources.paths_applying_with(strategy) {
if src.is_dir() {
if !dst.exists() {
match std::fs::create_dir_all(dst) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
span,
));
}
Ok(o) => o,
};
}
}
if src.is_file() {
match std::fs::rename(src, dst) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
span,
));
}
Ok(o) => o,
};
}
}
std::fs::remove_dir_all(entry).expect("can not remove directory");
}
}
}
} else {
if destination.exists() {
if !sources.iter().all(|x| (x.as_ref().unwrap()).is_file()) {
return Err(ShellError::labeled_error(
"Rename aborted (directories found). Renaming in patterns not supported yet (try moving the directory directly)",
"Rename aborted (directories found). Renaming in patterns not supported yet (try moving the directory directly)",
args.nth(0).unwrap().span(),
));
}
for entry in sources {
if let Ok(entry) = entry {
let mut to = PathBuf::from(&destination);
to.push(&entry.file_name().unwrap());
if entry.is_file() {
match std::fs::rename(&entry, &to) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(),
destination.file_name().unwrap(),
e.to_string(),
),
span,
));
}
Ok(o) => o,
};
}
}
}
} else {
return Err(ShellError::labeled_error(
format!(
"Rename aborted. (Does {:?} exist?)",
&destination.file_name().unwrap()
),
format!(
"Rename aborted. (Does {:?} exist?)",
&destination.file_name().unwrap()
),
args.nth(1).unwrap().span(),
));
}
}
Ok(OutputStream::empty())
}

View File

@ -70,3 +70,129 @@ impl<T: AsRef<str>> Div<T> for &RelativePath {
RelativePath::new(result) RelativePath::new(result)
} }
} }
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Res {
pub loc: PathBuf,
pub at: usize,
}
impl Res {}
pub struct FileStructure {
root: PathBuf,
pub resources: Vec<Res>,
}
impl FileStructure {
pub fn new() -> FileStructure {
FileStructure {
root: PathBuf::new(),
resources: Vec::<Res>::new(),
}
}
pub fn set_root(&mut self, path: &Path) {
self.root = path.to_path_buf();
}
pub fn paths_applying_with<F>(&mut self, to: F) -> Vec<(PathBuf, PathBuf)>
where
F: Fn((PathBuf, usize)) -> (PathBuf, PathBuf),
{
self.resources
.iter()
.map(|f| (PathBuf::from(&f.loc), f.at))
.map(|f| to(f))
.collect()
}
pub fn walk_decorate(&mut self, start_path: &Path) {
self.set_root(&dunce::canonicalize(start_path).unwrap());
self.resources = Vec::<Res>::new();
self.build(start_path, 0);
self.resources.sort();
}
fn build(&mut self, src: &'a Path, lvl: usize) {
let source = dunce::canonicalize(src).unwrap();
if source.is_dir() {
for entry in std::fs::read_dir(&source).unwrap() {
let entry = entry.unwrap();
let path = entry.path();
if path.is_dir() {
self.build(&path, lvl + 1);
}
self.resources.push(Res {
loc: path.to_path_buf(),
at: lvl,
});
}
} else {
self.resources.push(Res {
loc: source,
at: lvl,
});
}
}
}
#[cfg(test)]
mod tests {
use super::{FileStructure, Res};
use std::path::PathBuf;
fn fixtures() -> PathBuf {
let mut sdx = PathBuf::new();
sdx.push("tests");
sdx.push("fixtures");
sdx.push("formats");
dunce::canonicalize(sdx).unwrap()
}
#[test]
fn prepares_and_decorates_source_files_for_copying() {
let mut res = FileStructure::new();
res.walk_decorate(fixtures().as_path());
assert_eq!(
res.resources,
vec![
Res {
loc: fixtures().join("appveyor.yml"),
at: 0
},
Res {
loc: fixtures().join("caco3_plastics.csv"),
at: 0
},
Res {
loc: fixtures().join("cargo_sample.toml"),
at: 0
},
Res {
loc: fixtures().join("jonathan.xml"),
at: 0
},
Res {
loc: fixtures().join("sample.ini"),
at: 0
},
Res {
loc: fixtures().join("sgml_description.json"),
at: 0
},
Res {
loc: fixtures().join("utf16.ini"),
at: 0
}
]
);
}
}

View File

@ -1,15 +1,10 @@
mod helpers; mod helpers;
use helpers::in_directory as cwd; use helpers::in_directory as cwd;
use helpers::Playground;
#[test] #[test]
fn cd_directory_not_found() { fn cd_directory_not_found() {
let sandbox = Playground::setup_for("cd_directory_not_found_test").test_dir_name(); nu_error!(output, cwd("tests/fixtures"), "cd dir_that_does_not_exist");
let full_path = format!("{}/{}", Playground::root(), sandbox);
nu_error!(output, cwd(&full_path), "cd dir_that_does_not_exist");
assert!(output.contains("dir_that_does_not_exist")); assert!(output.contains("dir_that_does_not_exist"));
assert!(output.contains("directory not found")); assert!(output.contains("directory not found"));

View File

@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
#[test] #[test]
fn copies_a_file() { fn copies_a_file() {
let sandbox = Playground::setup_for("cp_test").test_dir_name(); let sandbox = Playground::setup_for("cp_test_1").test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox); let full_path = format!("{}/{}", Playground::root(), sandbox);
let expected_file = format!("{}/{}", full_path, "sample.ini"); let expected_file = format!("{}/{}", full_path, "sample.ini");
@ -15,7 +15,7 @@ fn copies_a_file() {
nu!( nu!(
_output, _output,
cwd(&Playground::root()), cwd(&Playground::root()),
"cp ../formats/sample.ini cp_test/sample.ini" "cp ../formats/sample.ini cp_test_1/sample.ini"
); );
assert!(h::file_exists_at(PathBuf::from(expected_file))); assert!(h::file_exists_at(PathBuf::from(expected_file)));
@ -56,16 +56,16 @@ fn copies_the_directory_inside_directory_if_path_to_copy_is_directory_and_with_r
EmptyFile("jonathan.txt"), EmptyFile("jonathan.txt"),
EmptyFile("andres.txt"), EmptyFile("andres.txt"),
]) ])
.within("copies_expected") .mkdir("expected")
.test_dir_name(); .test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox); let full_path = format!("{}/{}", Playground::root(), sandbox);
let expected_dir = format!("{}/{}", full_path, "copies_expected/originals"); let expected_dir = format!("{}/{}", full_path, "expected/originals");
nu!( nu!(
_output, _output,
cwd(&full_path), cwd(&full_path),
"cp originals copies_expected --recursive" "cp originals expected --recursive"
); );
assert!(h::dir_exists_at(PathBuf::from(&expected_dir))); assert!(h::dir_exists_at(PathBuf::from(&expected_dir)));
@ -114,11 +114,11 @@ fn deep_copies_with_recursive_flag() {
.with_files(vec![EmptyFile("coverage.txt"), EmptyFile("commands.txt")]) .with_files(vec![EmptyFile("coverage.txt"), EmptyFile("commands.txt")])
.within("originals/contributors/yehuda") .within("originals/contributors/yehuda")
.with_files(vec![EmptyFile("defer-evaluation.txt")]) .with_files(vec![EmptyFile("defer-evaluation.txt")])
.within("copies_expected") .mkdir("expected")
.test_dir_name(); .test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox); let full_path = format!("{}/{}", Playground::root(), sandbox);
let expected_dir = format!("{}/{}", full_path, "copies_expected/originals"); let expected_dir = format!("{}/{}", full_path, "expected/originals");
let jonathans_expected_copied_dir = format!("{}/contributors/jonathan", expected_dir); let jonathans_expected_copied_dir = format!("{}/contributors/jonathan", expected_dir);
let andres_expected_copied_dir = format!("{}/contributors/andres", expected_dir); let andres_expected_copied_dir = format!("{}/contributors/andres", expected_dir);
@ -127,7 +127,7 @@ fn deep_copies_with_recursive_flag() {
nu!( nu!(
_output, _output,
cwd(&full_path), cwd(&full_path),
"cp originals copies_expected --recursive" "cp originals expected --recursive"
); );
assert!(h::dir_exists_at(PathBuf::from(&expected_dir))); assert!(h::dir_exists_at(PathBuf::from(&expected_dir)));
@ -162,7 +162,8 @@ fn copies_using_path_with_wildcard() {
Path::new("cargo_sample.toml"), Path::new("cargo_sample.toml"),
Path::new("jonathan.xml"), Path::new("jonathan.xml"),
Path::new("sample.ini"), Path::new("sample.ini"),
Path::new("sgml_description.json") Path::new("sgml_description.json"),
Path::new("utf16.ini"),
], ],
PathBuf::from(&expected_copies_path) PathBuf::from(&expected_copies_path)
)); ));
@ -185,7 +186,8 @@ fn copies_using_a_glob() {
Path::new("cargo_sample.toml"), Path::new("cargo_sample.toml"),
Path::new("jonathan.xml"), Path::new("jonathan.xml"),
Path::new("sample.ini"), Path::new("sample.ini"),
Path::new("sgml_description.json") Path::new("sgml_description.json"),
Path::new("utf16.ini"),
], ],
PathBuf::from(&expected_copies_path) PathBuf::from(&expected_copies_path)
)); ));

View File

@ -6,7 +6,7 @@ use std::path::PathBuf;
#[test] #[test]
fn creates_directory() { fn creates_directory() {
let sandbox = Playground::setup_for("mkdir_test").test_dir_name(); let sandbox = Playground::setup_for("mkdir_test_1").test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox); let full_path = format!("{}/{}", Playground::root(), sandbox);

222
tests/command_mv_tests.rs Normal file
View File

@ -0,0 +1,222 @@
mod helpers;
use h::{in_directory as cwd, Playground, Stub::*};
use helpers as h;
use std::path::{Path, PathBuf};
#[test]
fn moves_a_file() {
let sandbox = Playground::setup_for("mv_test_1")
.with_files(vec![
EmptyFile("andres.txt"),
])
.mkdir("expected")
.test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox);
let original = format!("{}/{}", full_path, "andres.txt");
let expected = format!("{}/{}", full_path, "expected/yehuda.txt");
nu!(
_output,
cwd(&full_path),
"mv andres.txt expected/yehuda.txt"
);
assert!(!h::file_exists_at(PathBuf::from(original)));
assert!(h::file_exists_at(PathBuf::from(expected)));
}
#[test]
fn overwrites_if_moving_to_existing_file() {
let sandbox = Playground::setup_for("mv_test_2")
.with_files(vec![
EmptyFile("andres.txt"),
EmptyFile("jonathan.txt"),
])
.test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox);
let original = format!("{}/{}", full_path, "andres.txt");
let expected = format!("{}/{}", full_path, "jonathan.txt");
nu!(
_output,
cwd(&full_path),
"mv andres.txt jonathan.txt"
);
assert!(!h::file_exists_at(PathBuf::from(original)));
assert!(h::file_exists_at(PathBuf::from(expected)));
}
#[test]
fn moves_a_directory() {
let sandbox = Playground::setup_for("mv_test_3")
.mkdir("empty_dir")
.test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox);
let original_dir = format!("{}/{}", full_path, "empty_dir");
let expected = format!("{}/{}", full_path, "renamed_dir");
nu!(
_output,
cwd(&full_path),
"mv empty_dir renamed_dir"
);
assert!(!h::dir_exists_at(PathBuf::from(original_dir)));
assert!(h::dir_exists_at(PathBuf::from(expected)));
}
#[test]
fn moves_the_file_inside_directory_if_path_to_move_is_existing_directory() {
let sandbox = Playground::setup_for("mv_test_4")
.with_files(vec![
EmptyFile("jonathan.txt"),
])
.mkdir("expected")
.test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox);
let original_dir = format!("{}/{}", full_path, "jonathan.txt");
let expected = format!("{}/{}", full_path, "expected/jonathan.txt");
nu!(
_output,
cwd(&full_path),
"mv jonathan.txt expected"
);
assert!(!h::file_exists_at(PathBuf::from(original_dir)));
assert!(h::file_exists_at(PathBuf::from(expected)));
}
#[test]
fn moves_the_directory_inside_directory_if_path_to_move_is_existing_directory() {
let sandbox = Playground::setup_for("mv_test_5")
.within("contributors")
.with_files(vec![
EmptyFile("jonathan.txt"),
])
.mkdir("expected")
.test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox);
let original_dir = format!("{}/{}", full_path, "contributors");
let expected = format!("{}/{}", full_path, "expected/contributors");
nu!(
_output,
cwd(&full_path),
"mv contributors expected"
);
assert!(!h::dir_exists_at(PathBuf::from(original_dir)));
assert!(h::file_exists_at(PathBuf::from(expected)));
}
#[test]
fn moves_the_directory_inside_directory_if_path_to_move_is_nonexistent_directory() {
let sandbox = Playground::setup_for("mv_test_6")
.within("contributors")
.with_files(vec![
EmptyFile("jonathan.txt"),
])
.mkdir("expected")
.test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox);
let original_dir = format!("{}/{}", full_path, "contributors");
nu!(
_output,
cwd(&full_path),
"mv contributors expected/this_dir_exists_now/los_tres_amigos"
);
let expected = format!("{}/{}", full_path, "expected/this_dir_exists_now/los_tres_amigos");
assert!(!h::dir_exists_at(PathBuf::from(original_dir)));
assert!(h::file_exists_at(PathBuf::from(expected)));
}
#[test]
fn moves_using_path_with_wildcard() {
let sandbox = Playground::setup_for("mv_test_7")
.within("originals")
.with_files(vec![
EmptyFile("andres.ini"),
EmptyFile("caco3_plastics.csv"),
EmptyFile("cargo_sample.toml"),
EmptyFile("jonathan.ini"),
EmptyFile("jonathan.xml"),
EmptyFile("sgml_description.json"),
EmptyFile("sample.ini"),
EmptyFile("utf16.ini"),
EmptyFile("yehuda.ini"),
])
.mkdir("work_dir")
.mkdir("expected")
.test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox);
let work_dir = format!("{}/{}", full_path, "work_dir");
let expected_copies_path = format!("{}/{}", full_path, "expected");
nu!(
_output,
cwd(&work_dir),
"mv ../originals/*.ini ../expected"
);
assert!(h::files_exist_at(
vec![
Path::new("yehuda.ini"),
Path::new("jonathan.ini"),
Path::new("sample.ini"),
Path::new("andres.ini"),
],
PathBuf::from(&expected_copies_path)
));
}
#[test]
fn moves_using_a_glob() {
let sandbox = Playground::setup_for("mv_test_8")
.within("meals")
.with_files(vec![
EmptyFile("arepa.txt"),
EmptyFile("empanada.txt"),
EmptyFile("taquiza.txt"),
])
.mkdir("work_dir")
.mkdir("expected")
.test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox);
let meal_dir = format!("{}/{}", full_path, "meals");
let work_dir = format!("{}/{}", full_path, "work_dir");
let expected_copies_path = format!("{}/{}", full_path, "expected");
nu!(
_output,
cwd(&work_dir),
"mv ../meals/* ../expected"
);
assert!(h::dir_exists_at(PathBuf::from(meal_dir)));
assert!(h::files_exist_at(
vec![
Path::new("arepa.txt"),
Path::new("empanada.txt"),
Path::new("taquiza.txt"),
],
PathBuf::from(&expected_copies_path)
));
}

View File

@ -125,7 +125,7 @@ fn save_figures_out_intelligently_where_to_write_out_with_metadata() {
#[test] #[test]
fn save_can_write_out_csv() { fn save_can_write_out_csv() {
let sandbox = Playground::setup_for("save_test").test_dir_name(); let sandbox = Playground::setup_for("save_writes_out_csv_test").test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox); let full_path = format!("{}/{}", Playground::root(), sandbox);
let expected_file = format!("{}/{}", full_path, "cargo_sample.csv"); let expected_file = format!("{}/{}", full_path, "cargo_sample.csv");
@ -133,7 +133,7 @@ fn save_can_write_out_csv() {
nu!( nu!(
_output, _output,
cwd(&Playground::root()), cwd(&Playground::root()),
"open ../formats/cargo_sample.toml | inc package.version --minor | get package | save save_test/cargo_sample.csv" "open ../formats/cargo_sample.toml | inc package.version --minor | get package | save save_writes_out_csv_test/cargo_sample.csv"
); );
let actual = h::file_contents(&expected_file); let actual = h::file_contents(&expected_file);
@ -142,14 +142,14 @@ fn save_can_write_out_csv() {
#[test] #[test]
fn rm_removes_a_file() { fn rm_removes_a_file() {
let sandbox = Playground::setup_for("rm_test") let sandbox = Playground::setup_for("rm_regular_file_test")
.with_files(vec![EmptyFile("i_will_be_deleted.txt")]) .with_files(vec![EmptyFile("i_will_be_deleted.txt")])
.test_dir_name(); .test_dir_name();
nu!( nu!(
_output, _output,
cwd(&Playground::root()), cwd(&Playground::root()),
"rm rm_test/i_will_be_deleted.txt" "rm rm_regular_file_test/i_will_be_deleted.txt"
); );
let path = &format!( let path = &format!(
@ -180,7 +180,7 @@ fn rm_removes_files_with_wildcard() {
src/parser/hir/baseline_parse_tokens.rs src/parser/hir/baseline_parse_tokens.rs
"#; "#;
let sandbox = Playground::setup_for("rm_test_wildcard") let sandbox = Playground::setup_for("rm_wildcard_test")
.within("src") .within("src")
.with_files(vec![ .with_files(vec![
EmptyFile("cli.rs"), EmptyFile("cli.rs"),
@ -210,7 +210,7 @@ fn rm_removes_files_with_wildcard() {
nu!( nu!(
_output, _output,
cwd("tests/fixtures/nuplayground/rm_test_wildcard"), cwd("tests/fixtures/nuplayground/rm_wildcard_test"),
"rm \"src/*/*/*.rs\"" "rm \"src/*/*/*.rs\""
); );
@ -231,7 +231,7 @@ fn rm_removes_files_with_wildcard() {
#[test] #[test]
fn rm_removes_directory_contents_with_recursive_flag() { fn rm_removes_directory_contents_with_recursive_flag() {
let sandbox = Playground::setup_for("rm_test_recursive") let sandbox = Playground::setup_for("rm_directory_removal_recursively_test")
.with_files(vec![ .with_files(vec![
EmptyFile("yehuda.txt"), EmptyFile("yehuda.txt"),
EmptyFile("jonathan.txt"), EmptyFile("jonathan.txt"),
@ -242,7 +242,7 @@ fn rm_removes_directory_contents_with_recursive_flag() {
nu!( nu!(
_output, _output,
cwd("tests/fixtures/nuplayground"), cwd("tests/fixtures/nuplayground"),
"rm rm_test_recursive --recursive" "rm rm_directory_removal_recursively_test --recursive"
); );
let expected = format!("{}/{}", Playground::root(), sandbox); let expected = format!("{}/{}", Playground::root(), sandbox);
@ -252,10 +252,10 @@ fn rm_removes_directory_contents_with_recursive_flag() {
#[test] #[test]
fn rm_errors_if_attempting_to_delete_a_directory_without_recursive_flag() { fn rm_errors_if_attempting_to_delete_a_directory_without_recursive_flag() {
let sandbox = Playground::setup_for("rm_test_2").test_dir_name(); let sandbox = Playground::setup_for("rm_prevent_directory_removal_without_flag_test").test_dir_name();
let full_path = format!("{}/{}", Playground::root(), sandbox); let full_path = format!("{}/{}", Playground::root(), sandbox);
nu_error!(output, cwd(&Playground::root()), "rm rm_test_2"); nu_error!(output, cwd(&Playground::root()), "rm rm_prevent_directory_removal_without_flag_test");
assert!(h::file_exists_at(PathBuf::from(full_path))); assert!(h::file_exists_at(PathBuf::from(full_path)));
assert!(output.contains("is a directory")); assert!(output.contains("is a directory"));

View File

@ -15,8 +15,8 @@ fn can_only_apply_one() {
} }
#[test] #[test]
fn regular_field_by_one() { fn by_one_with_field_passed() {
Playground::setup_for("plugin_inc_test_1") Playground::setup_for("plugin_inc_by_one_with_field_passed_test")
.with_files(vec![FileWithContent( .with_files(vec![FileWithContent(
"sample.toml", "sample.toml",
r#" r#"
@ -27,17 +27,16 @@ fn regular_field_by_one() {
nu!( nu!(
output, output,
cwd("tests/fixtures/nuplayground/plugin_inc_test_1"), cwd("tests/fixtures/nuplayground/plugin_inc_by_one_with_field_passed_test"),
"open sample.toml | inc package.edition | get package.edition | echo $it" "open sample.toml | inc package.edition | get package.edition | echo $it"
); );
assert_eq!(output, "2019"); assert_eq!(output, "2019");
} }
#[test] #[test]
fn by_one_without_passing_field() { fn by_one_with_no_field_passed() {
Playground::setup_for("plugin_inc_test_2") Playground::setup_for("plugin_inc_by_one_with_no_field_passed_test")
.with_files(vec![FileWithContent( .with_files(vec![FileWithContent(
"sample.toml", "sample.toml",
r#" r#"
@ -48,16 +47,17 @@ fn by_one_without_passing_field() {
nu!( nu!(
output, output,
cwd("tests/fixtures/nuplayground/plugin_inc_test_2"), cwd("tests/fixtures/nuplayground/plugin_inc_by_one_with_no_field_passed_test"),
"open sample.toml | get package.contributors | inc | echo $it" "open sample.toml | get package.contributors | inc | echo $it"
); );
assert_eq!(output, "3"); assert_eq!(output, "3");
} }
#[test] #[test]
fn semversion_major_inc() { fn semversion_major_inc() {
Playground::setup_for("plugin_inc_test_3") Playground::setup_for("plugin_inc_major_semversion_test")
.with_files(vec![FileWithContent( .with_files(vec![FileWithContent(
"sample.toml", "sample.toml",
r#" r#"
@ -68,7 +68,7 @@ fn semversion_major_inc() {
nu!( nu!(
output, output,
cwd("tests/fixtures/nuplayground/plugin_inc_test_3"), cwd("tests/fixtures/nuplayground/plugin_inc_major_semversion_test"),
"open sample.toml | inc package.version --major | get package.version | echo $it" "open sample.toml | inc package.version --major | get package.version | echo $it"
); );
@ -77,7 +77,7 @@ fn semversion_major_inc() {
#[test] #[test]
fn semversion_minor_inc() { fn semversion_minor_inc() {
Playground::setup_for("plugin_inc_test_4") Playground::setup_for("plugin_inc_minor_semversion_test")
.with_files(vec![FileWithContent( .with_files(vec![FileWithContent(
"sample.toml", "sample.toml",
r#" r#"
@ -88,7 +88,7 @@ fn semversion_minor_inc() {
nu!( nu!(
output, output,
cwd("tests/fixtures/nuplayground/plugin_inc_test_4"), cwd("tests/fixtures/nuplayground/plugin_inc_minor_semversion_test"),
"open sample.toml | inc package.version --minor | get package.version | echo $it" "open sample.toml | inc package.version --minor | get package.version | echo $it"
); );
@ -97,7 +97,7 @@ fn semversion_minor_inc() {
#[test] #[test]
fn semversion_patch_inc() { fn semversion_patch_inc() {
Playground::setup_for("plugin_inc_test_5") Playground::setup_for("plugin_inc_patch_semversion_test")
.with_files(vec![FileWithContent( .with_files(vec![FileWithContent(
"sample.toml", "sample.toml",
r#" r#"
@ -108,7 +108,7 @@ fn semversion_patch_inc() {
nu!( nu!(
output, output,
cwd("tests/fixtures/nuplayground/plugin_inc_test_5"), cwd("tests/fixtures/nuplayground/plugin_inc_patch_semversion_test"),
"open sample.toml | inc package.version --patch | get package.version | echo $it" "open sample.toml | inc package.version --patch | get package.version | echo $it"
); );
@ -117,7 +117,7 @@ fn semversion_patch_inc() {
#[test] #[test]
fn semversion_without_passing_field() { fn semversion_without_passing_field() {
Playground::setup_for("plugin_inc_test_6") Playground::setup_for("plugin_inc_semversion_without_passing_field_test")
.with_files(vec![FileWithContent( .with_files(vec![FileWithContent(
"sample.toml", "sample.toml",
r#" r#"
@ -128,7 +128,7 @@ fn semversion_without_passing_field() {
nu!( nu!(
output, output,
cwd("tests/fixtures/nuplayground/plugin_inc_test_6"), cwd("tests/fixtures/nuplayground/plugin_inc_semversion_without_passing_field_test"),
"open sample.toml | get package.version | inc --patch | echo $it" "open sample.toml | get package.version | inc --patch | echo $it"
); );

View File

@ -116,8 +116,10 @@ impl Playground {
} }
} }
pub fn cd(&mut self, path: &str) -> &mut Self { pub fn mkdir(&mut self, directory: &str) -> &mut Self {
self.cwd.push(path); self.cwd.push(directory);
std::fs::create_dir_all(&self.cwd).expect("can not create directory");
self.back_to_playground();
self self
} }