Refactoring and unwrap cleanup beginnings.

This commit is contained in:
Andrés N. Robalino 2019-08-18 19:12:28 -05:00
parent 81d83d7655
commit 5dd20850b5
7 changed files with 236 additions and 146 deletions

View file

@ -21,7 +21,7 @@ impl PerItemCommand for Cpy {
call_info: &CallInfo, call_info: &CallInfo,
_registry: &CommandRegistry, _registry: &CommandRegistry,
shell_manager: &ShellManager, shell_manager: &ShellManager,
input: Tagged<Value>, _input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError> { ) -> Result<VecDeque<ReturnValue>, ShellError> {
call_info.process(shell_manager, cp)?.run() call_info.process(shell_manager, cp)?.run()
} }
@ -75,7 +75,7 @@ pub fn cp(
let mut sources: FileStructure = FileStructure::new(); let mut sources: FileStructure = FileStructure::new();
sources.walk_decorate(&entry); sources.walk_decorate(&entry)?;
if entry.is_file() { if entry.is_file() {
let strategy = |(source_file, _depth_level)| { let strategy = |(source_file, _depth_level)| {

View file

@ -1,3 +1,4 @@
use crate::commands::command::RunnablePerItemContext;
use crate::errors::ShellError; 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};
@ -9,6 +10,12 @@ use crate::utils::FileStructure;
pub struct Move; pub struct Move;
#[derive(Deserialize)]
pub struct MoveArgs {
source: Tagged<PathBuf>,
destination: Tagged<PathBuf>,
}
impl PerItemCommand for Move { impl PerItemCommand for Move {
fn run( fn run(
&self, &self,
@ -17,7 +24,7 @@ impl PerItemCommand for Move {
shell_manager: &ShellManager, shell_manager: &ShellManager,
_input: Tagged<Value>, _input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError> { ) -> Result<VecDeque<ReturnValue>, ShellError> {
mv(call_info, shell_manager) call_info.process(shell_manager, mv)?.run()
} }
fn name(&self) -> &str { fn name(&self) -> &str {
@ -25,59 +32,77 @@ impl PerItemCommand for Move {
} }
fn signature(&self) -> Signature { fn signature(&self) -> Signature {
Signature::build("mv").named("file", SyntaxType::Any) Signature::build("mv")
.required("source", SyntaxType::Path)
.required("destination", SyntaxType::Path)
.named("file", SyntaxType::Any)
} }
} }
pub fn mv( pub fn mv(
call_info: &CallInfo, args: MoveArgs,
shell_manager: &ShellManager, context: &RunnablePerItemContext,
) -> Result<VecDeque<ReturnValue>, ShellError> { ) -> Result<VecDeque<ReturnValue>, ShellError> {
let mut source = PathBuf::from(shell_manager.path()); let mut source = PathBuf::from(context.shell_manager.path());
let mut destination = PathBuf::from(shell_manager.path()); let mut destination = PathBuf::from(context.shell_manager.path());
let span = call_info.name_span; let name_span = context.name;
match call_info source.push(&args.source.item);
.args
.nth(0) destination.push(&args.destination.item);
.ok_or_else(|| ShellError::string(&format!("No file or directory specified")))?
.as_string()? let sources: Vec<_> = match glob::glob(&source.to_string_lossy()) {
.as_str() Ok(files) => files.collect(),
{ Err(_) => {
file => { return Err(ShellError::labeled_error(
source.push(file); "Invalid pattern.",
"Invalid pattern.",
args.source.tag,
))
} }
} };
match call_info let destination_file_name = {
.args let path = &destination;
.nth(1)
.ok_or_else(|| ShellError::string(&format!("No file or directory specified")))? match path.file_name() {
.as_string()? Some(name) => PathBuf::from(name),
.as_str() None => {
{ return Err(ShellError::labeled_error(
file => { "Rename aborted. Not a valid destination",
destination.push(file); "Rename aborted. Not a valid destination",
name_span,
))
}
} }
} };
let sources = glob::glob(&source.to_string_lossy());
if sources.is_err() {
return Err(ShellError::labeled_error(
"Invalid pattern.",
"Invalid pattern.",
call_info.args.nth(0).unwrap().span(),
));
}
let sources: Vec<_> = sources.unwrap().collect();
if sources.len() == 1 { if sources.len() == 1 {
if let Ok(entry) = &sources[0] { if let Ok(entry) = &sources[0] {
let entry_file_name = match entry.file_name() {
Some(name) => name,
None => {
return Err(ShellError::labeled_error(
"Rename aborted. Not a valid entry name",
"Rename aborted. Not a valid entry name",
name_span,
))
}
};
if destination.exists() && destination.is_dir() { if destination.exists() && destination.is_dir() {
destination = dunce::canonicalize(&destination).unwrap(); destination = match dunce::canonicalize(&destination) {
destination.push(source.file_name().unwrap()); Ok(path) => path,
Err(e) => {
return Err(ShellError::labeled_error(
format!("Rename aborted. {:}", e.to_string()),
format!("Rename aborted. {:}", e.to_string()),
name_span,
))
}
};
destination.push(entry_file_name);
} }
if entry.is_file() { if entry.is_file() {
@ -86,17 +111,17 @@ pub fn mv(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
span, name_span,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -109,17 +134,17 @@ pub fn mv(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
span, name_span,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -131,17 +156,17 @@ pub fn mv(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
span, name_span,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -151,10 +176,11 @@ pub fn mv(
{ {
let mut sources: FileStructure = FileStructure::new(); let mut sources: FileStructure = FileStructure::new();
sources.walk_decorate(&entry); sources.walk_decorate(&entry)?;
let strategy = |(source_file, depth_level)| { let strategy = |(source_file, depth_level)| {
let mut new_dst = destination.clone(); let mut new_dst = destination.clone();
let path = dunce::canonicalize(&source_file).unwrap(); let path = dunce::canonicalize(&source_file).unwrap();
let mut comps: Vec<_> = path let mut comps: Vec<_> = path
@ -181,21 +207,21 @@ pub fn mv(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
span, name_span,
)); ));
} }
Ok(o) => o, Ok(o) => o,
}; }
} }
} }
@ -205,42 +231,78 @@ pub fn mv(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
span, name_span,
)); ));
} }
Ok(o) => o, Ok(o) => o,
}; }
} }
} }
std::fs::remove_dir_all(entry).expect("can not remove directory"); match std::fs::remove_dir_all(entry) {
Err(e) => {
return Err(ShellError::labeled_error(
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
format!(
"Rename {:?} to {:?} aborted. {:}",
entry_file_name,
destination_file_name,
e.to_string(),
),
name_span,
));
}
Ok(o) => o,
};
} }
} }
} }
} else { } else {
if destination.exists() { if destination.exists() {
if !sources.iter().all(|x| (x.as_ref().unwrap()).is_file()) { if !sources.iter().all(|x| {
if let Ok(entry) = x.as_ref() {
entry.is_file()
} else {
false
}
}) {
return Err(ShellError::labeled_error( 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)",
"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)",
call_info.args.nth(0).unwrap().span(), args.source.tag,
)); ));
} }
for entry in sources { for entry in sources {
if let Ok(entry) = entry { if let Ok(entry) = entry {
let entry_file_name = match entry.file_name() {
Some(name) => name,
None => {
return Err(ShellError::labeled_error(
"Rename aborted. Not a valid entry name",
"Rename aborted. Not a valid entry name",
name_span,
))
}
};
let mut to = PathBuf::from(&destination); let mut to = PathBuf::from(&destination);
to.push(&entry.file_name().unwrap()); to.push(entry_file_name);
if entry.is_file() { if entry.is_file() {
match std::fs::rename(&entry, &to) { match std::fs::rename(&entry, &to) {
@ -248,17 +310,17 @@ pub fn mv(
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
format!( format!(
"Rename {:?} to {:?} aborted. {:}", "Rename {:?} to {:?} aborted. {:}",
entry.file_name().unwrap(), entry_file_name,
destination.file_name().unwrap(), destination_file_name,
e.to_string(), e.to_string(),
), ),
span, name_span,
)); ));
} }
Ok(o) => o, Ok(o) => o,
@ -268,15 +330,9 @@ pub fn mv(
} }
} else { } else {
return Err(ShellError::labeled_error( return Err(ShellError::labeled_error(
format!( format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
"Rename aborted. (Does {:?} exist?)", format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
&destination.file_name().unwrap() args.destination.span(),
),
format!(
"Rename aborted. (Does {:?} exist?)",
&destination.file_name().unwrap()
),
call_info.args.nth(1).unwrap().span(),
)); ));
} }
} }

View file

@ -28,7 +28,16 @@ pub trait Plugin {
pub fn serve_plugin(plugin: &mut dyn Plugin) { pub fn serve_plugin(plugin: &mut dyn Plugin) {
let args = std::env::args(); let args = std::env::args();
if args.len() > 1 { if args.len() > 1 {
let input = std::fs::read_to_string(args.skip(1).next().unwrap()); let input = args.skip(1).next();
let input = match input {
Some(arg) => std::fs::read_to_string(arg),
None => {
send_response(ShellError::string(format!("No input given.")));
return;
}
};
if let Ok(input) = input { if let Ok(input) = input {
let command = serde_json::from_str::<NuCommand>(&input); let command = serde_json::from_str::<NuCommand>(&input);
match command { match command {
@ -128,8 +137,12 @@ impl<T> JsonRpc<T> {
fn send_response<T: Serialize>(result: T) { fn send_response<T: Serialize>(result: T) {
let response = JsonRpc::new("response", result); let response = JsonRpc::new("response", result);
let response_raw = serde_json::to_string(&response).unwrap(); let response_raw = serde_json::to_string(&response);
println!("{}", response_raw);
match response_raw {
Ok(response) => println!("{}", response),
Err(err) => println!("{}", err),
}
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "method")] #[serde(tag = "method")]

View file

@ -1,7 +1,7 @@
use indexmap::IndexMap; use indexmap::IndexMap;
use nu::{ use nu::{
serve_plugin, CallInfo, NamedType, Plugin, Primitive, ReturnSuccess, serve_plugin, CallInfo, NamedType, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
ReturnValue, ShellError, Signature, Tagged, TaggedItem, Value, Signature, Tagged, TaggedItem, Value,
}; };
enum Action { enum Action {
@ -30,16 +30,13 @@ impl Inc {
} }
} }
fn apply(&self, input: &str) -> Value { fn apply(&self, input: &str) -> Result<Value, ShellError> {
match &self.action { let applied = match &self.action {
Some(Action::SemVerAction(act_on)) => { Some(Action::SemVerAction(act_on)) => {
let ver = semver::Version::parse(&input); let mut ver = match semver::Version::parse(&input) {
Ok(parsed_ver) => parsed_ver,
if ver.is_err() { Err(_) => return Ok(Value::string(input.to_string())),
return Value::string(input.to_string()); };
}
let mut ver = ver.unwrap();
match act_on { match act_on {
SemVerAction::Major => ver.increment_major(), SemVerAction::Major => ver.increment_major(),
@ -53,7 +50,9 @@ impl Inc {
Ok(v) => Value::string(format!("{}", v + 1)), Ok(v) => Value::string(format!("{}", v + 1)),
Err(_) => Value::string(input), Err(_) => Value::string(input),
}, },
} };
Ok(applied)
} }
fn for_semver(&mut self, part: SemVerAction) { fn for_semver(&mut self, part: SemVerAction) {
@ -83,7 +82,7 @@ impl Inc {
Ok(Value::bytes(b + 1 as u64).tagged(value.tag())) Ok(Value::bytes(b + 1 as u64).tagged(value.tag()))
} }
Value::Primitive(Primitive::String(ref s)) => { Value::Primitive(Primitive::String(ref s)) => {
Ok(Tagged::from_item(self.apply(&s), value.tag())) Ok(Tagged::from_item(self.apply(&s)?, value.tag()))
} }
Value::Object(_) => match self.field { Value::Object(_) => match self.field {
Some(ref f) => { Some(ref f) => {
@ -187,8 +186,8 @@ mod tests {
use super::{Inc, SemVerAction}; use super::{Inc, SemVerAction};
use indexmap::IndexMap; use indexmap::IndexMap;
use nu::{ use nu::{
CallInfo, EvaluatedArgs, Plugin, ReturnSuccess, SourceMap, Span, Tag, Tagged, TaggedDictBuilder, CallInfo, EvaluatedArgs, Plugin, ReturnSuccess, SourceMap, Span, Tag, Tagged,
TaggedItem, Value, TaggedDictBuilder, TaggedItem, Value,
}; };
struct CallStub { struct CallStub {
@ -237,7 +236,7 @@ mod tests {
fn inc_plugin_configuration_flags_wired() { fn inc_plugin_configuration_flags_wired() {
let mut plugin = Inc::new(); let mut plugin = Inc::new();
let configured = plugin.config().unwrap(); let configured = plugin.config().expect("Can not configure plugin");
for action_flag in &["major", "minor", "patch"] { for action_flag in &["major", "minor", "patch"] {
assert!(configured.named.get(*action_flag).is_some()); assert!(configured.named.get(*action_flag).is_some());
@ -304,21 +303,21 @@ mod tests {
fn incs_major() { fn incs_major() {
let mut inc = Inc::new(); let mut inc = Inc::new();
inc.for_semver(SemVerAction::Major); inc.for_semver(SemVerAction::Major);
assert_eq!(inc.apply("0.1.3"), Value::string("1.0.0")); assert_eq!(inc.apply("0.1.3").unwrap(), Value::string("1.0.0"));
} }
#[test] #[test]
fn incs_minor() { fn incs_minor() {
let mut inc = Inc::new(); let mut inc = Inc::new();
inc.for_semver(SemVerAction::Minor); inc.for_semver(SemVerAction::Minor);
assert_eq!(inc.apply("0.1.3"), Value::string("0.2.0")); assert_eq!(inc.apply("0.1.3").unwrap(), Value::string("0.2.0"));
} }
#[test] #[test]
fn incs_patch() { fn incs_patch() {
let mut inc = Inc::new(); let mut inc = Inc::new();
inc.for_semver(SemVerAction::Patch); inc.for_semver(SemVerAction::Patch);
assert_eq!(inc.apply("0.1.3"), Value::string("0.1.4")); assert_eq!(inc.apply("0.1.3").unwrap(), Value::string("0.1.4"));
} }
#[test] #[test]

View file

@ -36,19 +36,15 @@ impl Str {
} }
} }
fn apply(&self, input: &str) -> Value { fn apply(&self, input: &str) -> Result<Value, ShellError> {
if self.action.is_none() { let applied = match self.action.as_ref() {
return Value::string(input.to_string()); Some(Action::Downcase) => Value::string(input.to_ascii_lowercase()),
} Some(Action::Upcase) => Value::string(input.to_ascii_uppercase()),
Some(Action::ToInteger) => match input.trim().parse::<i64>() {
match self.action.as_ref().unwrap() {
Action::Downcase => Value::string(input.to_ascii_lowercase()),
Action::Upcase => Value::string(input.to_ascii_uppercase()),
Action::ToInteger => match input.trim().parse::<i64>() {
Ok(v) => Value::int(v), Ok(v) => Value::int(v),
Err(_) => Value::string(input), Err(_) => Value::string(input),
}, },
Action::Replace(ref mode) => match mode { Some(Action::Replace(ref mode)) => match mode {
ReplaceAction::Direct => Value::string(self.first_param()), ReplaceAction::Direct => Value::string(self.first_param()),
ReplaceAction::FindAndReplace => { ReplaceAction::FindAndReplace => {
let regex = Regex::new(self.first_param()); let regex = Regex::new(self.first_param());
@ -59,7 +55,10 @@ impl Str {
} }
} }
}, },
} None => Value::string(input),
};
Ok(applied)
} }
fn did_supply_field(&self) -> bool { fn did_supply_field(&self) -> bool {
@ -133,7 +132,7 @@ impl Str {
fn strutils(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> { fn strutils(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> {
match value.item { match value.item {
Value::Primitive(Primitive::String(ref s)) => { Value::Primitive(Primitive::String(ref s)) => {
Ok(Tagged::from_item(self.apply(&s), value.tag())) Ok(Tagged::from_item(self.apply(&s)?, value.tag()))
} }
Value::Object(_) => match self.field { Value::Object(_) => match self.field {
Some(ref f) => { Some(ref f) => {
@ -431,21 +430,21 @@ mod tests {
fn str_downcases() { fn str_downcases() {
let mut strutils = Str::new(); let mut strutils = Str::new();
strutils.for_downcase(); strutils.for_downcase();
assert_eq!(strutils.apply("ANDRES"), Value::string("andres")); assert_eq!(strutils.apply("ANDRES").unwrap(), Value::string("andres"));
} }
#[test] #[test]
fn str_upcases() { fn str_upcases() {
let mut strutils = Str::new(); let mut strutils = Str::new();
strutils.for_upcase(); strutils.for_upcase();
assert_eq!(strutils.apply("andres"), Value::string("ANDRES")); assert_eq!(strutils.apply("andres").unwrap(), Value::string("ANDRES"));
} }
#[test] #[test]
fn str_to_int() { fn str_to_int() {
let mut strutils = Str::new(); let mut strutils = Str::new();
strutils.for_to_int(); strutils.for_to_int();
assert_eq!(strutils.apply("9999"), Value::int(9999 as i64)); assert_eq!(strutils.apply("9999").unwrap(), Value::int(9999 as i64));
} }
#[test] #[test]
@ -453,7 +452,7 @@ mod tests {
let mut strutils = Str::new(); let mut strutils = Str::new();
strutils.for_replace(ReplaceAction::Direct); strutils.for_replace(ReplaceAction::Direct);
strutils.replace_with("robalino"); strutils.replace_with("robalino");
assert_eq!(strutils.apply("andres"), Value::string("robalino")); assert_eq!(strutils.apply("andres").unwrap(), Value::string("robalino"));
} }
#[test] #[test]
@ -462,7 +461,10 @@ mod tests {
strutils.for_replace(ReplaceAction::FindAndReplace); strutils.for_replace(ReplaceAction::FindAndReplace);
strutils.find_with(r"kittens"); strutils.find_with(r"kittens");
strutils.replace_with("jotandrehuda"); strutils.replace_with("jotandrehuda");
assert_eq!(strutils.apply("wykittens"), Value::string("wyjotandrehuda")); assert_eq!(
strutils.apply("wykittens").unwrap(),
Value::string("wyjotandrehuda")
);
} }
#[test] #[test]

View file

@ -1,3 +1,4 @@
use crate::errors::ShellError;
use std::ops::Div; use std::ops::Div;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -71,7 +72,6 @@ impl<T: AsRef<str>> Div<T> for &RelativePath {
} }
} }
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] #[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Res { pub struct Res {
pub loc: PathBuf, pub loc: PathBuf,
@ -108,23 +108,25 @@ impl FileStructure {
.collect() .collect()
} }
pub fn walk_decorate(&mut self, start_path: &Path) { pub fn walk_decorate(&mut self, start_path: &Path) -> Result<(), ShellError> {
self.set_root(&dunce::canonicalize(start_path).unwrap()); self.set_root(&dunce::canonicalize(start_path)?);
self.resources = Vec::<Res>::new(); self.resources = Vec::<Res>::new();
self.build(start_path, 0); self.build(start_path, 0)?;
self.resources.sort(); self.resources.sort();
Ok(())
} }
fn build(&mut self, src: &'a Path, lvl: usize) { fn build(&mut self, src: &'a Path, lvl: usize) -> Result<(), ShellError> {
let source = dunce::canonicalize(src).unwrap(); let source = dunce::canonicalize(src)?;
if source.is_dir() { if source.is_dir() {
for entry in std::fs::read_dir(&source).unwrap() { for entry in std::fs::read_dir(&source)? {
let entry = entry.unwrap(); let entry = entry?;
let path = entry.path(); let path = entry.path();
if path.is_dir() { if path.is_dir() {
self.build(&path, lvl + 1); self.build(&path, lvl + 1)?;
} }
self.resources.push(Res { self.resources.push(Res {
@ -138,6 +140,8 @@ impl FileStructure {
at: lvl, at: lvl,
}); });
} }
Ok(())
} }
} }
@ -152,13 +156,18 @@ mod tests {
sdx.push("tests"); sdx.push("tests");
sdx.push("fixtures"); sdx.push("fixtures");
sdx.push("formats"); sdx.push("formats");
dunce::canonicalize(sdx).unwrap()
match dunce::canonicalize(sdx) {
Ok(path) => path,
Err(_) => panic!("Wrong path."),
}
} }
#[test] #[test]
fn prepares_and_decorates_source_files_for_copying() { fn prepares_and_decorates_source_files_for_copying() {
let mut res = FileStructure::new(); let mut res = FileStructure::new();
res.walk_decorate(fixtures().as_path());
res.walk_decorate(fixtures().as_path()).expect("Can not decorate files traversal.");
assert_eq!( assert_eq!(
res.resources, res.resources,
@ -195,4 +204,3 @@ mod tests {
); );
} }
} }

View file

@ -151,7 +151,20 @@ impl Playground {
} }
pub fn glob_vec(pattern: &str) -> Vec<PathBuf> { pub fn glob_vec(pattern: &str) -> Vec<PathBuf> {
glob(pattern).unwrap().map(|r| r.unwrap()).collect() let glob = glob(pattern);
match glob {
Ok(paths) => paths
.map(|path| {
if let Ok(path) = path {
path
} else {
unreachable!()
}
})
.collect(),
Err(_) => panic!("Invalid pattern."),
}
} }
} }
@ -178,11 +191,10 @@ pub fn normalize_string(input: &str) -> String {
pub fn create_file_at(full_path: impl AsRef<Path>) -> Result<(), std::io::Error> { pub fn create_file_at(full_path: impl AsRef<Path>) -> Result<(), std::io::Error> {
let full_path = full_path.as_ref(); let full_path = full_path.as_ref();
assert!( if let Some(parent) = full_path.parent() {
full_path.parent().unwrap().is_dir(), panic!(format!("{:?} exists", parent.display()));
"{:?} exists", }
full_path.parent().unwrap().display(),
);
std::fs::write(full_path, "fake data".as_bytes()) std::fs::write(full_path, "fake data".as_bytes())
} }