summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Barrett <spalf0@gmail.com>2019-08-15 10:19:59 -0500
committerTom Barrett <spalf0@gmail.com>2019-08-15 10:19:59 -0500
commit46b6a160c71473177bcd607103fae35e3468d463 (patch)
tree3f991595182c21db14fc36cd3e7891672c9fd83d
parent81bbfcb77ef9fe029897878ebd733017066c80e1 (diff)
wrote basic test, now passing io errors via ?
-rw-r--r--src/lib.rs1
-rw-r--r--src/main.rs193
-rw-r--r--tests/tests.rs49
3 files changed, 162 insertions, 81 deletions
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..2a04341
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1 @@
+pub mod main;
diff --git a/src/main.rs b/src/main.rs
index cd10462..bb1701a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,6 +4,7 @@ extern crate dirs;
use clap::{App, AppSettings::ArgRequiredElseHelp, Arg};
use csv::{ReaderBuilder, Writer};
use std::fs;
+use std::io;
use std::path::{Component, PathBuf};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
@@ -37,102 +38,116 @@ fn main() {
fs::create_dir(&rsyclebin).unwrap();
}
- if matches.is_present("restore") {
- if let Some(filename) = matches.value_of("INPUT") {
- let filename = filename.to_owned() + ".";
- restore(rsyclebin, &filename);
+ if let Some(filename) = matches.value_of("INPUT") {
+ let path = build_path(filename).unwrap();
+ if matches.is_present("restore") {
+ restore(rsyclebin, path).unwrap();
} else {
- restore_cli(rsyclebin);
+ rsycle(rsyclebin, path).unwrap();
}
} else if matches.is_present("empty") {
- empty(rsyclebin);
+ empty(rsyclebin).unwrap();
} else if matches.is_present("list") {
- list(rsyclebin);
- } else if let Some(filename) = matches.value_of("INPUT") {
- rsycle(rsyclebin, filename);
+ list(rsyclebin).unwrap();
+ } else if matches.is_present("restore") {
+ restore_cli(rsyclebin);
}
}
-fn log(rsyclebin: PathBuf, old_path: PathBuf, new_path: PathBuf) {
+pub fn build_path(filename: &str) -> Result<PathBuf, io::Error> {
+ let relative: PathBuf = [Component::CurDir, Component::Normal(filename.as_ref())]
+ .iter()
+ .collect();
+
+ fs::canonicalize(&relative)
+}
+
+pub fn rsycle(rsyclebin: PathBuf, old_path: PathBuf) -> Result<(), io::Error> {
+ if !old_path.exists() {
+ Err(io::Error::new(io::ErrorKind::NotFound, "File not found!"))
+ } else {
+ let new_filename = old_path.file_name().unwrap().to_str().unwrap().to_owned()
+ + "."
+ + &SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .unwrap()
+ .as_secs()
+ .to_string();
+
+ let mut new_path = rsyclebin.clone();
+ new_path.push(new_filename);
+
+ log(rsyclebin, old_path.clone(), new_path.clone())?;
+ fs::rename(old_path, new_path)
+ }
+}
+
+fn log(rsyclebin: PathBuf, old_path: PathBuf, new_path: PathBuf) -> Result<(), io::Error> {
let mut rsyclebin_log = rsyclebin.clone();
rsyclebin_log.push(".log");
let file = fs::OpenOptions::new()
.append(true)
.create(true)
- .open(rsyclebin_log)
- .unwrap();
+ .open(rsyclebin_log)?;
let mut writer = Writer::from_writer(file);
- writer
- .write_record(&[
- fs::canonicalize(old_path).unwrap().to_str().unwrap(),
- new_path.to_str().unwrap(),
- ])
- .unwrap();
- writer.flush().unwrap();
+ writer.write_record(&[
+ fs::canonicalize(old_path)?.to_str().unwrap(),
+ new_path.to_str().unwrap(),
+ ])?;
+ writer.flush()
}
-fn rsycle(rsyclebin: PathBuf, filename: &str) {
- let old_path: PathBuf = [Component::CurDir, Component::Normal(filename.as_ref())]
- .iter()
- .collect();
+pub fn restore(rsyclebin: PathBuf, original_path: PathBuf) -> Result<(), io::Error> {
+ let current_path = most_recent_current_path(rsyclebin, original_path.clone())?;
- if !old_path.exists() {
- println!("File not found!");
- return;
+ if !original_path.exists() {
+ fs::rename(current_path, original_path)
+ } else {
+ Err(io::Error::new(
+ io::ErrorKind::NotFound,
+ "There is a file in the way!",
+ ))
}
+}
- let new_filename = filename.to_owned()
- + "."
- + &SystemTime::now()
- .duration_since(UNIX_EPOCH)
- .unwrap()
- .as_secs()
- .to_string();
+pub fn most_recent_current_path(rsyclebin: PathBuf, path: PathBuf) -> Result<PathBuf, io::Error> {
+ let mut rsyclebin_log = rsyclebin.clone();
+ rsyclebin_log.push(".log");
- let mut new_path = rsyclebin.clone();
- new_path.push(new_filename);
+ let file = fs::OpenOptions::new().read(true).open(rsyclebin_log)?;
- log(rsyclebin, old_path.clone(), new_path.clone());
- fs::rename(old_path, new_path).unwrap();
-}
+ let mut reader = ReaderBuilder::new().has_headers(false).from_reader(file);
-fn restore(rsyclebin: PathBuf, filename: &str) {
- let paths: Vec<PathBuf> = fs::read_dir(rsyclebin.clone())
- .unwrap()
+ let path_str = path.to_str().unwrap();
+
+ let original_paths: Vec<PathBuf> = reader
+ .records()
.map(Result::unwrap)
- .map(|dir| dir.path())
- .filter(|path| {
+ .filter(|line| line.get(0).unwrap() == path_str)
+ .map(|line| PathBuf::from(line.get(1).unwrap()))
+ .collect();
+
+ Ok(original_paths
+ .iter()
+ .max_by_key(|path| {
path.file_name()
.unwrap()
.to_str()
.unwrap()
- .starts_with(filename)
+ .split('.')
+ .collect::<Vec<&str>>()
+ .pop()
+ .unwrap()
+ .parse::<u64>()
+ .unwrap()
})
- .collect();
-
- match paths.iter().max_by_key(|path| {
- path.file_name()
- .unwrap()
- .to_str()
- .unwrap()
- .split('.')
- .collect::<Vec<&str>>()
- .pop()
- .unwrap()
- .parse::<u64>()
- .unwrap()
- }) {
- Some(latest_path) => {
- let original_path = find_original_path(rsyclebin, latest_path.to_path_buf());
- fs::rename(latest_path, original_path).unwrap();
- }
- None => println!("No file found !"),
- }
+ .unwrap()
+ .to_path_buf())
}
-fn list(rsyclebin: PathBuf) {
+pub fn list(rsyclebin: PathBuf) -> Result<(), io::Error> {
let mut paths: Vec<PathBuf> = fs::read_dir(rsyclebin.clone())
.unwrap()
.map(Result::unwrap)
@@ -150,37 +165,53 @@ fn list(rsyclebin: PathBuf) {
if let Some(last_point) = filename.pop() {
if let Ok(date) = last_point.parse::<u64>() {
- let original_path = find_original_path(rsyclebin.clone(), current_path.clone());
+ let original_path = find_original_path(rsyclebin.clone(), current_path.clone())?;
let date = UNIX_EPOCH + Duration::from_secs(date);
- println!("{:?}, {:?}, {:?}", original_path, current_path, date);
+ println!(
+ "original: {:?}, current: {:?}, date: {:?}",
+ original_path, current_path, date
+ );
}
}
}
+
+ Ok(())
}
-fn find_original_path(rsyclebin: PathBuf, path: PathBuf) -> String {
+fn find_original_path(rsyclebin: PathBuf, current_path: PathBuf) -> Result<PathBuf, io::Error> {
let mut rsyclebin_log = rsyclebin.clone();
rsyclebin_log.push(".log");
- let file = fs::OpenOptions::new()
- .read(true)
- .open(rsyclebin_log)
- .unwrap();
+ let file = fs::OpenOptions::new().read(true).open(rsyclebin_log)?;
let mut reader = ReaderBuilder::new().has_headers(false).from_reader(file);
- let path_str = path.to_str().unwrap();
+ let path_str = current_path.to_str().unwrap();
- reader
- .records()
- .map(Result::unwrap)
- .find(|line| line.get(1).unwrap() == path_str)
- .map(|line| line.get(0).unwrap().to_string())
- .unwrap()
+ Ok(PathBuf::from(
+ reader
+ .records()
+ .map(Result::unwrap)
+ .find(|line| line.get(1).unwrap() == path_str)
+ .map(|line| line.get(0).unwrap().to_string())
+ .unwrap(),
+ ))
}
-fn empty(rsyclebin: PathBuf) {
- fs::remove_dir_all(rsyclebin).unwrap()
+pub fn empty(rsyclebin: PathBuf) -> Result<(), io::Error> {
+ let paths: Vec<PathBuf> = fs::read_dir(rsyclebin.clone())
+ .unwrap()
+ .map(Result::unwrap)
+ .map(|dir| dir.path())
+ .collect();
+
+ for path in paths {
+ if fs::remove_file(path.clone()).is_err() {
+ fs::remove_dir_all(path)?
+ }
+ }
+
+ Ok(())
}
fn restore_cli(_rsyclebin: PathBuf) {
diff --git a/tests/tests.rs b/tests/tests.rs
new file mode 100644
index 0000000..efdb909
--- /dev/null
+++ b/tests/tests.rs
@@ -0,0 +1,49 @@
+extern crate rsycle;
+
+#[cfg(test)]
+mod tests {
+ use rsycle::main::{build_path, empty, list, restore, rsycle};
+ use std::fs;
+ use std::path::{Component, PathBuf};
+
+ fn get_rsyclebin() -> PathBuf {
+ let mut rsyclebin = dirs::home_dir().unwrap();
+ rsyclebin.push(".test_rsyclebin");
+ if !rsyclebin.exists() {
+ fs::create_dir(&rsyclebin).unwrap();
+ }
+ rsyclebin
+ }
+
+ #[test]
+ fn test_rsycle() {
+ let rsyclebin = get_rsyclebin();
+
+ let filename = "test_file".as_ref();
+
+ let mut test_path: PathBuf = [Component::CurDir, Component::Normal(filename)]
+ .iter()
+ .collect();
+
+ assert!(!test_path.exists());
+
+ fs::File::create(test_path.clone()).unwrap();
+
+ test_path = build_path(filename.to_str().unwrap()).unwrap();
+
+ assert!(rsycle(rsyclebin.clone(), test_path.clone()).is_ok());
+
+ assert!(!test_path.exists());
+
+ assert!(list(rsyclebin.clone()).is_ok());
+
+ assert!(restore(rsyclebin.clone(), test_path.clone()).is_ok());
+
+ assert!(test_path.exists());
+
+ assert!(empty(rsyclebin.clone()).is_ok());
+
+ fs::remove_file(test_path).unwrap();
+ fs::remove_dir_all(rsyclebin).unwrap();
+ }
+}