mirror of
https://github.com/nushell/nushell.git
synced 2024-11-27 02:44:01 +01:00
Merge pull request #286 from androbtech/mv-and-bitsmoar
Moving file/dir in place and some refactored a little.
This commit is contained in:
commit
d11d840f0f
@ -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 |
|
||||
| ls (path) | View the contents of the current or given path |
|
||||
| mkdir path | Make directories, creates intermediary directories as required. |
|
||||
| mv source target | Move files or directories. |
|
||||
| date (--utc) | Get the current datetime |
|
||||
| ps | View current processes |
|
||||
| sys | View information about the current system |
|
||||
|
@ -189,9 +189,10 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||
static_command(Exit),
|
||||
static_command(Clip),
|
||||
static_command(Autoview),
|
||||
static_command(Copycp),
|
||||
static_command(Cpy),
|
||||
static_command(Date),
|
||||
static_command(Mkdir),
|
||||
static_command(Move),
|
||||
static_command(Save),
|
||||
static_command(Table),
|
||||
static_command(VTable),
|
||||
|
@ -25,6 +25,7 @@ crate mod get;
|
||||
crate mod lines;
|
||||
crate mod ls;
|
||||
crate mod mkdir;
|
||||
crate mod mv;
|
||||
crate mod next;
|
||||
crate mod nth;
|
||||
crate mod open;
|
||||
@ -61,12 +62,13 @@ crate use command::{
|
||||
RawCommandArgs, StaticCommand, UnevaluatedCallInfo,
|
||||
};
|
||||
crate use config::Config;
|
||||
crate use cp::Copycp;
|
||||
crate use cp::Cpy;
|
||||
crate use date::Date;
|
||||
crate use enter::Enter;
|
||||
crate use exit::Exit;
|
||||
crate use get::Get;
|
||||
crate use mkdir::Mkdir;
|
||||
crate use mv::Move;
|
||||
crate use open::Open;
|
||||
crate use rm::Remove;
|
||||
crate use save::Save;
|
||||
|
@ -2,11 +2,12 @@ use crate::errors::ShellError;
|
||||
use crate::parser::hir::SyntaxType;
|
||||
use crate::parser::registry::{CommandRegistry, Signature};
|
||||
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(
|
||||
&self,
|
||||
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> {
|
||||
let mut source = 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 {
|
||||
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(
|
||||
"Copy aborted (directories found). Try using \"--recursive\".",
|
||||
"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). Recursive copying in patterns not supported yet (try copying the directory directly)",
|
||||
args.nth(0).unwrap().span(),
|
||||
));
|
||||
}
|
||||
@ -319,16 +251,18 @@ pub fn cp(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
|
||||
let mut to = PathBuf::from(&destination);
|
||||
to.push(&entry.file_name().unwrap());
|
||||
|
||||
match std::fs::copy(&entry, &to) {
|
||||
Err(e) => {
|
||||
return Err(ShellError::labeled_error(
|
||||
e.to_string(),
|
||||
e.to_string(),
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
Ok(o) => o,
|
||||
};
|
||||
if entry.is_file() {
|
||||
match std::fs::copy(&entry, &to) {
|
||||
Err(e) => {
|
||||
return Err(ShellError::labeled_error(
|
||||
e.to_string(),
|
||||
e.to_string(),
|
||||
args.nth(0).unwrap().span(),
|
||||
));
|
||||
}
|
||||
Ok(o) => o,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -348,58 +282,3 @@ pub fn cp(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
|
||||
|
||||
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
279
src/commands/mv.rs
Normal 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())
|
||||
}
|
126
src/utils.rs
126
src/utils.rs
@ -70,3 +70,129 @@ impl<T: AsRef<str>> Div<T> for &RelativePath {
|
||||
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
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,10 @@
|
||||
mod helpers;
|
||||
|
||||
use helpers::in_directory as cwd;
|
||||
use helpers::Playground;
|
||||
|
||||
#[test]
|
||||
fn cd_directory_not_found() {
|
||||
let sandbox = Playground::setup_for("cd_directory_not_found_test").test_dir_name();
|
||||
|
||||
let full_path = format!("{}/{}", Playground::root(), sandbox);
|
||||
|
||||
nu_error!(output, cwd(&full_path), "cd dir_that_does_not_exist");
|
||||
nu_error!(output, cwd("tests/fixtures"), "cd dir_that_does_not_exist");
|
||||
|
||||
assert!(output.contains("dir_that_does_not_exist"));
|
||||
assert!(output.contains("directory not found"));
|
||||
|
@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
#[test]
|
||||
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 expected_file = format!("{}/{}", full_path, "sample.ini");
|
||||
@ -15,7 +15,7 @@ fn copies_a_file() {
|
||||
nu!(
|
||||
_output,
|
||||
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)));
|
||||
@ -56,16 +56,16 @@ fn copies_the_directory_inside_directory_if_path_to_copy_is_directory_and_with_r
|
||||
EmptyFile("jonathan.txt"),
|
||||
EmptyFile("andres.txt"),
|
||||
])
|
||||
.within("copies_expected")
|
||||
.mkdir("expected")
|
||||
.test_dir_name();
|
||||
|
||||
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!(
|
||||
_output,
|
||||
cwd(&full_path),
|
||||
"cp originals copies_expected --recursive"
|
||||
"cp originals expected --recursive"
|
||||
);
|
||||
|
||||
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")])
|
||||
.within("originals/contributors/yehuda")
|
||||
.with_files(vec![EmptyFile("defer-evaluation.txt")])
|
||||
.within("copies_expected")
|
||||
.mkdir("expected")
|
||||
.test_dir_name();
|
||||
|
||||
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 andres_expected_copied_dir = format!("{}/contributors/andres", expected_dir);
|
||||
@ -127,7 +127,7 @@ fn deep_copies_with_recursive_flag() {
|
||||
nu!(
|
||||
_output,
|
||||
cwd(&full_path),
|
||||
"cp originals copies_expected --recursive"
|
||||
"cp originals expected --recursive"
|
||||
);
|
||||
|
||||
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("jonathan.xml"),
|
||||
Path::new("sample.ini"),
|
||||
Path::new("sgml_description.json")
|
||||
Path::new("sgml_description.json"),
|
||||
Path::new("utf16.ini"),
|
||||
],
|
||||
PathBuf::from(&expected_copies_path)
|
||||
));
|
||||
@ -185,7 +186,8 @@ fn copies_using_a_glob() {
|
||||
Path::new("cargo_sample.toml"),
|
||||
Path::new("jonathan.xml"),
|
||||
Path::new("sample.ini"),
|
||||
Path::new("sgml_description.json")
|
||||
Path::new("sgml_description.json"),
|
||||
Path::new("utf16.ini"),
|
||||
],
|
||||
PathBuf::from(&expected_copies_path)
|
||||
));
|
||||
|
@ -6,7 +6,7 @@ use std::path::PathBuf;
|
||||
|
||||
#[test]
|
||||
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);
|
||||
|
||||
|
222
tests/command_mv_tests.rs
Normal file
222
tests/command_mv_tests.rs
Normal 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)
|
||||
));
|
||||
}
|
@ -125,7 +125,7 @@ fn save_figures_out_intelligently_where_to_write_out_with_metadata() {
|
||||
|
||||
#[test]
|
||||
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 expected_file = format!("{}/{}", full_path, "cargo_sample.csv");
|
||||
@ -133,7 +133,7 @@ fn save_can_write_out_csv() {
|
||||
nu!(
|
||||
_output,
|
||||
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);
|
||||
@ -142,14 +142,14 @@ fn save_can_write_out_csv() {
|
||||
|
||||
#[test]
|
||||
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")])
|
||||
.test_dir_name();
|
||||
|
||||
nu!(
|
||||
_output,
|
||||
cwd(&Playground::root()),
|
||||
"rm rm_test/i_will_be_deleted.txt"
|
||||
"rm rm_regular_file_test/i_will_be_deleted.txt"
|
||||
);
|
||||
|
||||
let path = &format!(
|
||||
@ -180,7 +180,7 @@ fn rm_removes_files_with_wildcard() {
|
||||
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")
|
||||
.with_files(vec![
|
||||
EmptyFile("cli.rs"),
|
||||
@ -210,7 +210,7 @@ fn rm_removes_files_with_wildcard() {
|
||||
|
||||
nu!(
|
||||
_output,
|
||||
cwd("tests/fixtures/nuplayground/rm_test_wildcard"),
|
||||
cwd("tests/fixtures/nuplayground/rm_wildcard_test"),
|
||||
"rm \"src/*/*/*.rs\""
|
||||
);
|
||||
|
||||
@ -231,7 +231,7 @@ fn rm_removes_files_with_wildcard() {
|
||||
|
||||
#[test]
|
||||
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![
|
||||
EmptyFile("yehuda.txt"),
|
||||
EmptyFile("jonathan.txt"),
|
||||
@ -242,7 +242,7 @@ fn rm_removes_directory_contents_with_recursive_flag() {
|
||||
nu!(
|
||||
_output,
|
||||
cwd("tests/fixtures/nuplayground"),
|
||||
"rm rm_test_recursive --recursive"
|
||||
"rm rm_directory_removal_recursively_test --recursive"
|
||||
);
|
||||
|
||||
let expected = format!("{}/{}", Playground::root(), sandbox);
|
||||
@ -252,10 +252,10 @@ fn rm_removes_directory_contents_with_recursive_flag() {
|
||||
|
||||
#[test]
|
||||
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);
|
||||
|
||||
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!(output.contains("is a directory"));
|
||||
|
@ -15,8 +15,8 @@ fn can_only_apply_one() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regular_field_by_one() {
|
||||
Playground::setup_for("plugin_inc_test_1")
|
||||
fn by_one_with_field_passed() {
|
||||
Playground::setup_for("plugin_inc_by_one_with_field_passed_test")
|
||||
.with_files(vec![FileWithContent(
|
||||
"sample.toml",
|
||||
r#"
|
||||
@ -27,17 +27,16 @@ fn regular_field_by_one() {
|
||||
|
||||
nu!(
|
||||
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"
|
||||
);
|
||||
|
||||
assert_eq!(output, "2019");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn by_one_without_passing_field() {
|
||||
Playground::setup_for("plugin_inc_test_2")
|
||||
fn by_one_with_no_field_passed() {
|
||||
Playground::setup_for("plugin_inc_by_one_with_no_field_passed_test")
|
||||
.with_files(vec![FileWithContent(
|
||||
"sample.toml",
|
||||
r#"
|
||||
@ -45,19 +44,20 @@ fn by_one_without_passing_field() {
|
||||
contributors = "2"
|
||||
"#,
|
||||
)]);
|
||||
|
||||
|
||||
nu!(
|
||||
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"
|
||||
);
|
||||
|
||||
|
||||
assert_eq!(output, "3");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn semversion_major_inc() {
|
||||
Playground::setup_for("plugin_inc_test_3")
|
||||
Playground::setup_for("plugin_inc_major_semversion_test")
|
||||
.with_files(vec![FileWithContent(
|
||||
"sample.toml",
|
||||
r#"
|
||||
@ -68,7 +68,7 @@ fn semversion_major_inc() {
|
||||
|
||||
nu!(
|
||||
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"
|
||||
);
|
||||
|
||||
@ -77,7 +77,7 @@ fn semversion_major_inc() {
|
||||
|
||||
#[test]
|
||||
fn semversion_minor_inc() {
|
||||
Playground::setup_for("plugin_inc_test_4")
|
||||
Playground::setup_for("plugin_inc_minor_semversion_test")
|
||||
.with_files(vec![FileWithContent(
|
||||
"sample.toml",
|
||||
r#"
|
||||
@ -88,7 +88,7 @@ fn semversion_minor_inc() {
|
||||
|
||||
nu!(
|
||||
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"
|
||||
);
|
||||
|
||||
@ -97,7 +97,7 @@ fn semversion_minor_inc() {
|
||||
|
||||
#[test]
|
||||
fn semversion_patch_inc() {
|
||||
Playground::setup_for("plugin_inc_test_5")
|
||||
Playground::setup_for("plugin_inc_patch_semversion_test")
|
||||
.with_files(vec![FileWithContent(
|
||||
"sample.toml",
|
||||
r#"
|
||||
@ -108,7 +108,7 @@ fn semversion_patch_inc() {
|
||||
|
||||
nu!(
|
||||
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"
|
||||
);
|
||||
|
||||
@ -117,7 +117,7 @@ fn semversion_patch_inc() {
|
||||
|
||||
#[test]
|
||||
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(
|
||||
"sample.toml",
|
||||
r#"
|
||||
@ -128,7 +128,7 @@ fn semversion_without_passing_field() {
|
||||
|
||||
nu!(
|
||||
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"
|
||||
);
|
||||
|
||||
|
@ -116,8 +116,10 @@ impl Playground {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cd(&mut self, path: &str) -> &mut Self {
|
||||
self.cwd.push(path);
|
||||
pub fn mkdir(&mut self, directory: &str) -> &mut Self {
|
||||
self.cwd.push(directory);
|
||||
std::fs::create_dir_all(&self.cwd).expect("can not create directory");
|
||||
self.back_to_playground();
|
||||
self
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user