summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Thiel <sthiel@thoughtworks.com>2019-06-15 16:21:08 +0800
committerSebastian Thiel <sthiel@thoughtworks.com>2019-06-15 16:25:29 +0800
commit08dfbb633fe25cc922b898aaf367f26a08730d91 (patch)
treec9653c772f145b46aef9df68a166456f5e801e29
parent48813ae0a1c9316b4a7ad1669de2c44389026769 (diff)
This might be the first working version of deletion
-rw-r--r--src/interactive/app/handlers.rs62
-rw-r--r--src/interactive/app_test/journeys_with_writes.rs12
-rw-r--r--src/interactive/app_test/utils.rs4
3 files changed, 68 insertions, 10 deletions
diff --git a/src/interactive/app/handlers.rs b/src/interactive/app/handlers.rs
index 261866c..7733075 100644
--- a/src/interactive/app/handlers.rs
+++ b/src/interactive/app/handlers.rs
@@ -6,8 +6,8 @@ use crate::interactive::{
};
use dua::traverse::TreeIndex;
use itertools::Itertools;
-use petgraph::visit::Bfs;
-use petgraph::Direction;
+use petgraph::{visit::Bfs, Direction};
+use std::{fs, io, path::PathBuf};
use termion::event::Key;
use tui::backend::Backend;
use tui_react::Terminal;
@@ -156,6 +156,8 @@ impl TerminalApp {
pub fn delete_entry(&mut self, index: TreeIndex) -> Result<(), usize> {
if let Some(_entry) = self.traversal.tree.node_weight(index) {
+ let path_to_delete = path_of(&self.traversal.tree, index);
+ delete_directory_recursively(path_to_delete)?;
let parent_idx = self
.traversal
.tree
@@ -233,3 +235,59 @@ impl TerminalApp {
}
}
}
+
+fn into_error_count(res: Result<(), io::Error>) -> usize {
+ match res.map_err(io_err_to_usize) {
+ Ok(_) => 0,
+ Err(c) => c,
+ }
+}
+
+fn io_err_to_usize(err: io::Error) -> usize {
+ if err.kind() == io::ErrorKind::NotFound {
+ 0
+ } else {
+ 1
+ }
+}
+
+fn delete_directory_recursively(path: PathBuf) -> Result<(), usize> {
+ let mut files_or_dirs = vec![path];
+ let mut dirs = Vec::new();
+ let mut num_errors = 0;
+ while let Some(path) = files_or_dirs.pop() {
+ match fs::read_dir(&path) {
+ Ok(iterator) => {
+ dirs.push(path);
+ for entry in iterator {
+ match entry.map_err(io_err_to_usize) {
+ Ok(entry) => files_or_dirs.push(entry.path()),
+ Err(c) => num_errors += c,
+ }
+ }
+ }
+ Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
+ continue;
+ }
+ Err(ref e) if e.kind() == io::ErrorKind::Other => {
+ // assume file, save IOps
+ num_errors += into_error_count(fs::remove_file(path));
+ continue;
+ }
+ Err(_) => {
+ num_errors += 1;
+ continue;
+ }
+ };
+ }
+
+ for dir in dirs.into_iter().rev() {
+ num_errors += into_error_count(fs::remove_dir(dir));
+ }
+
+ if num_errors == 0 {
+ Ok(())
+ } else {
+ Err(num_errors)
+ }
+}
diff --git a/src/interactive/app_test/journeys_with_writes.rs b/src/interactive/app_test/journeys_with_writes.rs
index e8cd6b5..cbd51cd 100644
--- a/src/interactive/app_test/journeys_with_writes.rs
+++ b/src/interactive/app_test/journeys_with_writes.rs
@@ -29,14 +29,9 @@ fn basic_user_journey_with_deletion() -> Result<(), Error> {
// When selecting the marker window and pressing the combination to delete entries
app.process_events(
&mut terminal,
- vec![Ok(Key::Char('\t')), Ok(Key::Ctrl('R'))].into_iter(),
+ vec![Ok(Key::Char('\t')), Ok(Key::Ctrl('r'))].into_iter(),
)?;
assert_eq!(
- fixture.as_ref().is_dir(),
- false,
- "the directory should have been deleted"
- );
- assert_eq!(
app.window.mark_pane.is_none(),
true,
"the marker pane is gone as all entries have been removed"
@@ -46,5 +41,10 @@ fn basic_user_journey_with_deletion() -> Result<(), Error> {
app.state.root, app.traversal.root_index,
"the only root left is the top-level"
);
+ assert_eq!(
+ fixture.as_ref().is_dir(),
+ false,
+ "the directory should have been deleted",
+ );
Ok(())
}
diff --git a/src/interactive/app_test/utils.rs b/src/interactive/app_test/utils.rs
index 144a4cc..7488143 100644
--- a/src/interactive/app_test/utils.rs
+++ b/src/interactive/app_test/utils.rs
@@ -65,7 +65,7 @@ pub struct WritableFixture {
impl Drop for WritableFixture {
fn drop(&mut self) {
- delete_recursive(&self.root).unwrap();
+ delete_recursive(&self.root).ok();
}
}
@@ -74,7 +74,7 @@ fn delete_recursive(path: impl AsRef<Path>) -> Result<(), Error> {
let mut dirs: Vec<_> = Vec::new();
for entry in WalkDir::new(&path).num_threads(1).into_iter() {
- let entry: DirEntry = entry.unwrap();
+ let entry: DirEntry = entry?;
let p = entry.path();
match p.is_dir() {
true => dirs.push(p),