Use fsio crate for file system apis

This commit is contained in:
sagie gur ari 2020-02-17 21:59:57 +00:00
parent e8f5d12a29
commit a3d4b7c747
24 changed files with 82 additions and 274 deletions

View file

@ -1,5 +1,10 @@
## CHANGELOG
### v0.2.1
* SDK - Use fsio crate for file system apis.
* Runtime - Use fsio crate for file system apis.
### v0.2.0 (2020-02-06)
* The if/else and not commands now support complex conditions #81

View file

@ -22,6 +22,9 @@ include = [
"/README.md"
]
[dependencies]
fsio = "^0.1"
[badges.travis-ci]
branch = "master"
repository = "sagiegurari/duckscript"

View file

@ -1,29 +0,0 @@
//! # io
//!
//! IO helper functions
//!
#[cfg(test)]
#[path = "./io_test.rs"]
mod io_test;
use crate::types::error::{ErrorInfo, ScriptError};
use std::fs::File;
use std::io::Read;
use std::path::Path;
pub(crate) fn read_text_file(file: &str) -> Result<String, ScriptError> {
let file_path = Path::new(file);
match File::open(&file_path) {
Ok(mut fd) => {
let mut content = String::new();
fd.read_to_string(&mut content).unwrap();
Ok(content)
}
Err(error) => Err(ScriptError {
info: ErrorInfo::ErrorReadingFile(file.to_string(), Some(error)),
}),
}
}

View file

@ -1,15 +0,0 @@
use super::*;
#[test]
fn read_text_file_found() {
let text = read_text_file("./Cargo.toml");
assert!(text.unwrap().contains("duckscript"));
}
#[test]
fn read_text_file_not_found() {
let text = read_text_file("./Cargo.toml2");
assert!(text.is_err());
}

View file

@ -124,7 +124,6 @@
//!
mod expansion;
mod io;
pub mod parser;
mod preprocessor;
pub mod runner;

View file

@ -7,12 +7,12 @@
#[path = "./parser_test.rs"]
mod parser_test;
use crate::io;
use crate::preprocessor;
use crate::types::error::{ErrorInfo, ScriptError};
use crate::types::instruction::{
Instruction, InstructionMetaInfo, InstructionType, PreProcessInstruction, ScriptInstruction,
};
use fsio::file::read_text_file;
static COMMENT_PREFIX_STR: &str = "#";
static PRE_PROCESS_PREFIX: char = '!';
@ -23,9 +23,11 @@ pub fn parse_file(file: &str) -> Result<Vec<Instruction>, ScriptError> {
let mut meta_info = InstructionMetaInfo::new();
meta_info.source = Some(file.to_string());
match io::read_text_file(file) {
match read_text_file(file) {
Ok(text) => parse_lines(&text, meta_info),
Err(error) => Err(error),
Err(error) => Err(ScriptError {
info: ErrorInfo::ErrorReadingFile(file.to_string(), Some(error)),
}),
}
}

View file

@ -4,9 +4,9 @@
//!
use crate::types::instruction::InstructionMetaInfo;
use fsio::error::FsIOError;
use std::fmt;
use std::fmt::Display;
use std::io;
#[cfg(test)]
#[path = "./error_test.rs"]
@ -33,7 +33,7 @@ fn format_error_message(
/// Holds the error information
pub enum ErrorInfo {
/// Error Info Type
ErrorReadingFile(String, Option<io::Error>),
ErrorReadingFile(String, Option<FsIOError>),
/// Error Info Type
Initialization(String),
/// Error Info Type

View file

@ -27,6 +27,7 @@ attohttpc = "^0.11"
base64 = "^0.11"
duckscript = { version = "^0.2.0", path = "../duckscript" }
fs_extra = "^1"
fsio = "^0.1"
home = "^0.5"
java-properties = "^1"
meval = "^0.2"

View file

@ -1,5 +1,6 @@
use crate::utils::{io, pckg};
use crate::utils::pckg;
use duckscript::types::command::{Command, CommandResult};
use fsio::path::get_basename;
#[cfg(test)]
#[path = "./mod_test.rs"]
@ -31,7 +32,7 @@ impl Command for CommandImpl {
if arguments.is_empty() {
CommandResult::Error("Path not provided.".to_string())
} else {
let basename = io::get_base_name(&arguments[0]);
let basename = get_basename(&arguments[0]);
CommandResult::Continue(basename)
}
}

View file

@ -1,5 +1,6 @@
use crate::utils::{io, pckg};
use crate::utils::pckg;
use duckscript::types::command::{Command, CommandResult};
use fsio::path::canonicalize_or;
#[cfg(test)]
#[path = "./mod_test.rs"]
@ -31,7 +32,7 @@ impl Command for CommandImpl {
if arguments.is_empty() {
CommandResult::Error("Path not provided.".to_string())
} else {
let path = io::get_canonical_path(&arguments[0]);
let path = canonicalize_or(&arguments[0], &arguments[0]);
CommandResult::Continue(Some(path.to_string()))
}

View file

@ -1,6 +1,7 @@
use crate::utils::{io, pckg};
use crate::utils::pckg;
use duckscript::types::command::{Command, CommandResult};
use fs_extra::dir;
use fsio::directory::create_parent;
use std::fs;
use std::path::Path;
@ -44,7 +45,7 @@ impl Command for CommandImpl {
let target_path_str = &arguments[1];
if source_file {
match io::create_parent_directory(target_path_str) {
match create_parent(target_path_str) {
Ok(_) => match fs::copy(source_path_str, target_path_str) {
Ok(_) => CommandResult::Continue(Some("true".to_string())),
Err(error) => CommandResult::Error(error.to_string()),
@ -52,7 +53,7 @@ impl Command for CommandImpl {
Err(error) => CommandResult::Error(error.to_string()),
}
} else {
match io::create_directory(target_path_str) {
match fsio::directory::create(target_path_str) {
Ok(_) => {
let options = dir::CopyOptions::new();

View file

@ -1,5 +1,6 @@
use crate::utils::{io, pckg};
use crate::utils::pckg;
use duckscript::types::command::{Command, CommandResult};
use fsio::path::get_parent_directory;
#[cfg(test)]
#[path = "./mod_test.rs"]
@ -31,7 +32,7 @@ impl Command for CommandImpl {
if arguments.is_empty() {
CommandResult::Error("Path not provided.".to_string())
} else {
let parent_path = io::get_parent_directory_name(&arguments[0]);
let parent_path = get_parent_directory(&arguments[0]);
CommandResult::Continue(parent_path)
}
}

View file

@ -1,6 +1,7 @@
use crate::utils::{flags, io, pckg};
use crate::utils::{flags, pckg};
use duckscript::types::command::{Command, CommandResult};
use fs_extra::dir::{ls, DirEntryAttr, DirEntryValue};
use fsio::path::{get_basename, get_parent_directory};
use std::collections::{HashMap, HashSet};
use std::path::Path;
@ -113,7 +114,7 @@ impl Command for CommandImpl {
}
let (is_file, query_path) = if path.is_file() {
match io::get_parent_directory_name(path_str) {
match get_parent_directory(path_str) {
Some(value) => (true, value),
None => return CommandResult::Continue(Some("false".to_string())),
}
@ -128,7 +129,7 @@ impl Command for CommandImpl {
let items = ls_result.items;
if is_file {
let file_name = match io::get_base_name(path_str) {
let file_name = match get_basename(path_str) {
Some(value) => value,
None => path_str.to_string(),
};

View file

@ -1,5 +1,6 @@
use crate::utils::{io, pckg};
use crate::utils::pckg;
use duckscript::types::command::{Command, CommandResult};
use fsio;
#[cfg(test)]
#[path = "./mod_test.rs"]
@ -31,7 +32,7 @@ impl Command for CommandImpl {
if arguments.is_empty() {
CommandResult::Error("Directory name not provided.".to_string())
} else {
match io::create_directory(&arguments[0]) {
match fsio::directory::create(&arguments[0]) {
Ok(_) => CommandResult::Continue(Some("true".to_string())),
Err(error) => CommandResult::Error(error.to_string()),
}

View file

@ -1,6 +1,7 @@
use super::*;
use crate::test;
use crate::test::CommandValidation;
use fsio::file::write_text_file;
#[test]
fn common_functions() {
@ -35,7 +36,7 @@ fn run_directory_already_exists() {
#[test]
fn run_directory_exists_as_file() {
let result = io::write_text_file(
let result = write_text_file(
"./target/_duckscript/mkdir/run_directory_exists_as_file/test.txt",
"test file",
);

View file

@ -1,6 +1,7 @@
use crate::utils::{io, pckg};
use crate::utils::pckg;
use duckscript::types::command::{Command, CommandResult};
use fs_extra::{dir, move_items};
use fsio;
use std::fs;
use std::path::Path;
@ -49,7 +50,7 @@ impl Command for CommandImpl {
Err(error) => CommandResult::Error(error.to_string()),
}
} else {
match io::create_directory(&arguments[1]) {
match fsio::directory::create(&arguments[1]) {
Ok(_) => {
let options = dir::CopyOptions::new();
let from_paths = vec![&arguments[0]];

View file

@ -1,6 +1,7 @@
use super::*;
use crate::test;
use crate::test::CommandValidation;
use fsio::file::ensure_exists;
#[test]
fn common_functions() {
@ -29,7 +30,7 @@ fn run_input_path_not_exists() {
#[test]
fn run_file_to_file() {
let mut path = Path::new("./target/_duckscript/mv/run_file_to_file/1/file1.txt");
let result = io::create_empty_file("./target/_duckscript/mv/run_file_to_file/1/file1.txt");
let result = ensure_exists("./target/_duckscript/mv/run_file_to_file/1/file1.txt");
assert!(result.is_ok());
assert!(path.exists());
@ -46,7 +47,7 @@ fn run_file_to_file() {
#[test]
fn run_file_to_directory() {
let mut path = Path::new("./target/_duckscript/mv/run_file_to_directory/1/file1.txt");
let result = io::create_empty_file("./target/_duckscript/mv/run_file_to_directory/1/file1.txt");
let result = ensure_exists("./target/_duckscript/mv/run_file_to_directory/1/file1.txt");
assert!(result.is_ok());
assert!(path.exists());
@ -63,8 +64,7 @@ fn run_file_to_directory() {
#[test]
fn run_directory_to_directory() {
let mut path = Path::new("./target/_duckscript/mv/run_directory_to_directory/1/1/file1.txt");
let result =
io::create_empty_file("./target/_duckscript/mv/run_directory_to_directory/1/1/file1.txt");
let result = ensure_exists("./target/_duckscript/mv/run_directory_to_directory/1/1/file1.txt");
assert!(result.is_ok());
assert!(path.exists());

View file

@ -1,7 +1,8 @@
use super::*;
use crate::test;
use crate::test::CommandValidation;
use crate::utils::io;
use fsio;
use fsio::file::ensure_exists;
#[test]
fn common_functions() {
@ -29,7 +30,7 @@ fn run_path_not_exists() {
#[test]
fn run_path_not_empty_not_recursive() {
let result = io::create_directory("./target/_duckscript/rm/not_empty/dir1");
let result = fsio::directory::create("./target/_duckscript/rm/not_empty/dir1");
assert!(result.is_ok());
test::run_script_and_error(
@ -42,7 +43,7 @@ fn run_path_not_empty_not_recursive() {
#[test]
fn run_path_is_file() {
let path = Path::new("./target/_duckscript/rm/file.txt");
let result = io::create_empty_file("./target/_duckscript/rm/file.txt");
let result = ensure_exists("./target/_duckscript/rm/file.txt");
assert!(result.is_ok());
assert!(path.exists());
@ -58,7 +59,7 @@ fn run_path_is_file() {
#[test]
fn run_path_recursive() {
let path = Path::new("./target/_duckscript/rm/recursive/file.txt");
let result = io::create_empty_file("./target/_duckscript/rm/recursive/file.txt");
let result = ensure_exists("./target/_duckscript/rm/recursive/file.txt");
assert!(result.is_ok());
assert!(path.exists());

View file

@ -1,7 +1,8 @@
use super::*;
use crate::test;
use crate::test::CommandValidation;
use crate::utils::io;
use fsio;
use fsio::file::ensure_exists;
#[test]
fn common_functions() {
@ -24,7 +25,7 @@ fn run_path_not_exists() {
#[test]
fn run_path_not_empty() {
let result = io::create_directory("./target/_duckscript/rmdir/not_empty/dir1");
let result = fsio::directory::create("./target/_duckscript/rmdir/not_empty/dir1");
assert!(result.is_ok());
test::run_script_and_validate(
@ -36,7 +37,7 @@ fn run_path_not_empty() {
#[test]
fn run_path_is_file() {
let result = io::create_empty_file("./target/_duckscript/rmdir/file.txt");
let result = ensure_exists("./target/_duckscript/rmdir/file.txt");
assert!(result.is_ok());
test::run_script_and_validate(
@ -48,7 +49,7 @@ fn run_path_is_file() {
#[test]
fn run_valid() {
let result = io::create_directory("./target/_duckscript/rmdir/existing_dir");
let result = fsio::directory::create("./target/_duckscript/rmdir/existing_dir");
assert!(result.is_ok());
test::run_script_and_validate(

View file

@ -1,6 +1,7 @@
use super::*;
use crate::test;
use crate::test::CommandValidation;
use fsio;
#[test]
fn common_functions() {
@ -23,7 +24,7 @@ fn run_provided() {
#[test]
fn run_path_to_existing_directory() {
let result = io::create_directory("./target/_duckscript/touch/existing_dir");
let result = fsio::directory::create("./target/_duckscript/touch/existing_dir");
assert!(result.is_ok());
test::run_script_and_validate(

View file

@ -1,6 +1,8 @@
use crate::utils::{io, pckg};
use crate::utils::pckg;
use attohttpc;
use duckscript::types::command::{Command, CommandResult};
use fsio::directory::create_parent;
use fsio::file::delete;
use std::fs::File;
#[cfg(test)]
@ -96,8 +98,8 @@ fn do_request(url: String, options: Options) -> CommandResult {
Ok(response) => {
if response.is_success() {
match options.output_file {
Some(file) => match io::create_parent_directory(&file) {
Ok(_) => match io::delete_file(&file) {
Some(file) => match create_parent(&file) {
Ok(_) => match delete(&file) {
Ok(_) => match File::create(file) {
Ok(file_struct) => match response.write_to(file_struct) {
Ok(size) => CommandResult::Continue(Some(size.to_string())),
@ -105,7 +107,7 @@ fn do_request(url: String, options: Options) -> CommandResult {
},
Err(error) => CommandResult::Error(error.to_string()),
},
Err(error) => CommandResult::Error(error),
Err(error) => CommandResult::Error(error.to_string()),
},
Err(error) => CommandResult::Error(error.to_string()),
},

View file

@ -1,6 +1,7 @@
use super::*;
use crate::test;
use crate::test::{CommandValidation, SetCommand};
use fsio::file::{delete_ignore_error, read_text_file};
#[test]
fn common_functions() {
@ -24,8 +25,8 @@ fn run_get() {
#[test]
fn run_get_to_file() {
let file = "./target/_duckscript/http_client/page.html";
let result = io::delete_file(file);
assert!(result.is_ok());
let result = delete_ignore_error(file);
assert!(result);
test::run_script_and_validate(
vec![create("")],
@ -33,7 +34,7 @@ fn run_get_to_file() {
CommandValidation::PositiveNumber("out".to_string())
);
let read_result = io::read_text_file(file);
let read_result = read_text_file(file);
assert!(read_result.is_ok());
let text = read_result.unwrap();

View file

@ -1,86 +1,13 @@
use duckscript::types::error::{ErrorInfo, ScriptError};
use std::fs::{create_dir_all, remove_file, File, OpenOptions};
use std::io::{Read, Write};
use std::path::Path;
use fsio::file::{append_file, ensure_exists, read_file, write_file};
#[cfg(test)]
#[path = "./io_test.rs"]
mod io_test;
pub(crate) fn get_canonical_path(path: &str) -> String {
let path_obj = Path::new(path);
match path_obj.canonicalize() {
Ok(path_buf) => path_buf.to_string_lossy().into_owned(),
_ => path.to_string(),
}
}
pub(crate) fn get_base_name(path: &str) -> Option<String> {
let canonical_path = get_canonical_path(path);
let path = Path::new(&canonical_path);
match path.file_name() {
Some(name) => Some(name.to_string_lossy().into_owned()),
None => None,
}
}
pub(crate) fn get_parent_directory_name(path: &str) -> Option<String> {
let file_path = Path::new(path);
let directory = file_path.parent();
match directory {
Some(directory_path) => {
let directory = directory_path.to_string_lossy().into_owned();
if directory.is_empty() {
None
} else {
Some(directory)
}
}
None => None,
}
}
pub(crate) fn create_directory(directory: &str) -> Result<(), String> {
let directory_path = Path::new(directory);
create_directory_for_path(&directory_path)
}
pub(crate) fn create_parent_directory(file: &str) -> Result<(), String> {
match get_parent_directory_name(file) {
Some(parent) => create_directory(&parent),
None => Ok(()),
}
}
fn create_directory_for_path(directory_path: &Path) -> Result<(), String> {
if directory_path.is_dir() && directory_path.exists() {
return Ok(());
}
match create_dir_all(&directory_path) {
Ok(_) => Ok(()),
Err(error) => Err(error.to_string()),
}
}
pub(crate) fn read_text_file(file: &str) -> Result<String, ScriptError> {
let file_path = Path::new(file);
match File::open(&file_path) {
Ok(mut fd) => {
let mut content = String::new();
match fd.read_to_string(&mut content) {
Ok(_) => Ok(content),
Err(error) => Err(ScriptError {
info: ErrorInfo::ErrorReadingFile(file.to_string(), Some(error)),
}),
}
}
match fsio::file::read_text_file(file) {
Ok(content) => Ok(content),
Err(error) => Err(ScriptError {
info: ErrorInfo::ErrorReadingFile(file.to_string(), Some(error)),
}),
@ -88,18 +15,8 @@ pub(crate) fn read_text_file(file: &str) -> Result<String, ScriptError> {
}
pub(crate) fn read_raw_file(file: &str) -> Result<Vec<u8>, ScriptError> {
let file_path = Path::new(file);
match File::open(&file_path) {
Ok(mut fd) => {
let mut content = vec![];
match fd.read_to_end(&mut content) {
Ok(_) => Ok(content),
Err(error) => Err(ScriptError {
info: ErrorInfo::ErrorReadingFile(file.to_string(), Some(error)),
}),
}
}
match read_file(file) {
Ok(content) => Ok(content),
Err(error) => Err(ScriptError {
info: ErrorInfo::ErrorReadingFile(file.to_string(), Some(error)),
}),
@ -115,92 +32,23 @@ pub(crate) fn write_to_text_file(file: &str, text: &str, append: bool) -> Result
}
pub(crate) fn write_to_file(file: &str, data: &[u8], append: bool) -> Result<(), ScriptError> {
let file_path = Path::new(file);
// create parent directory
match create_parent_directory(file) {
Ok(_) => (),
Err(_) => {
return Err(ScriptError {
info: ErrorInfo::Runtime(
format!("Error creating parent directory for file: {}", file).to_string(),
None,
),
});
}
}
let result = if append && file_path.exists() {
OpenOptions::new().append(true).open(file)
let result = if append {
append_file(file, data)
} else {
File::create(&file_path)
write_file(file, data)
};
match result {
Ok(mut fd) => match fd.write_all(data) {
Err(_) => Err(ScriptError {
info: ErrorInfo::Runtime(
format!("Error writing to file: {}", file).to_string(),
None,
),
}),
Ok(_) => match fd.sync_all() {
_ => Ok(()),
},
},
Err(_) => Err(ScriptError {
info: ErrorInfo::Runtime(
format!("Error opening file: {} for writing.", file).to_string(),
None,
),
Ok(content) => Ok(content),
Err(error) => Err(ScriptError {
info: ErrorInfo::Runtime(error.to_string(), None),
}),
}
}
pub(crate) fn create_empty_file(file: &str) -> Result<(), String> {
let file_path = Path::new(file);
if file_path.exists() {
if file_path.is_file() {
Ok(())
} else {
Err(format!(
"Unable to create file: {} directory with that path exists.",
file
)
.to_string())
}
} else {
// create parent directory
let directory = file_path.parent();
match directory {
Some(directory_path) => match create_directory_for_path(&directory_path) {
_ => (),
},
None => (),
};
match File::create(&file_path) {
Ok(_) => Ok(()),
_ => Err(format!("Unable to create file: {}", file).to_string()),
}
}
}
pub(crate) fn delete_file(file: &str) -> Result<(), String> {
let file_path = Path::new(file);
if file_path.exists() {
match remove_file(file) {
Ok(_) => Ok(()),
Err(error) => Err(format!(
"Unable to delete file: {} error: {}",
file,
error.to_string()
)
.to_string()),
}
} else {
Ok(())
match ensure_exists(file) {
Ok(_) => Ok(()),
Err(error) => Err(error.to_string()),
}
}

View file

@ -1,25 +1,5 @@
use super::*;
#[test]
fn get_parent_directory_name_with_dir() {
let directory = get_parent_directory_name("./dir/file.txt");
assert_eq!(directory.unwrap(), "./dir");
}
#[test]
fn get_parent_directory_name_found() {
let directory = get_parent_directory_name("./file.txt");
assert_eq!(directory.unwrap(), ".");
}
#[test]
fn get_parent_directory_name_file_only() {
let directory = get_parent_directory_name("file.txt");
assert!(directory.is_none());
}
use std::path::Path;
#[test]
fn read_text_file_found() {