#![allow(unused_labels)]
use std::env::current_dir;
use std::fs;
use std::path::{Path, PathBuf};
use log::*;
use crate::core::filter::filter_paths;
use crate::core::history::write_history;
use crate::core::trash::Trash;
use crate::core::utils::{check_root, trash_dir};
use crate::{prompt_yes, show_error, verbose};
#[allow(unused_imports)]
use super::args::{Cli, InteractiveMode};
pub fn handle_interactive_once(args: &Cli) -> bool {
let items = args.file.as_ref().unwrap();
if args.interactive == Some(InteractiveMode::Once) && (items.len() > 3 || args.recursive) {
let msg: String = format!(
"remove {} {}{}",
items.len(),
if items.len() > 1 {
"arguments"
} else {
"argument"
},
if args.recursive { " recursively?" } else { "?" }
);
if prompt_yes!("{}", msg) {
return true;
}
}
false
}
fn core_remove(args: &Cli, item: &Path) {
let trash = Trash { file: item };
let id = trash.get_log_id();
trace!("id: {:?}", id);
let item_path = current_dir().unwrap().join(item);
trace!("item path recursive true: {:?}", item_path);
let trash_path = trash_dir().join(trash.trash_name(id.1));
trace!("trash path recursive true: {:?}", trash_path);
if check_root() {
trace!("is root user");
} else {
trace!("is normal user");
let rename_result = fs::rename(
&item_path,
trash_dir().join(trash.trash_name(trash.get_log_id().1)),
);
if let Err(e) = rename_result {
show_error!("Error moving {}: {:?}", item.display(), e);
if prompt_yes!(
"can't remove {} to trash dir. Do you wanna remove it?",
item.display()
) {
if item.is_dir() {
fs::remove_dir_all(item).unwrap();
} else {
fs::remove_file(item).unwrap();
}
}
}
if args.pattern.is_none() {
verbose!(
args.verbose,
"Trashed {} to {}",
item.display(),
trash_dir()
.join(trash.trash_name(trash.get_log_id().1))
.display()
);
write_history(
id.0,
item_path.to_str().unwrap().to_string(),
trash_path.to_str().unwrap().to_string(),
)
.unwrap();
}
}
}
pub fn init_remove(items: Vec<PathBuf>, args: &Cli) -> anyhow::Result<(), anyhow::Error> {
let enties = filter_paths(items, args).unwrap_or_else(|e| {
show_error!("{}", e);
Vec::new()
});
handle_interactive_once(args);
for item in &enties {
if args.list {
println!("{}", item.display());
} else {
let is_root = item.parent().is_none() && item.has_root();
if is_root {
show_error!("{} is root!", item.display());
continue;
} else {
handle_interactive(args, item)
}
}
}
trace!("{:#?}", enties);
Ok(())
}
fn handle_interactive(args: &Cli, item: &Path) {
match args.interactive {
Some(InteractiveMode::Always) => {
if prompt_yes!("do you wanna remove: `{}`?", &item.display()) {
core_remove(args, item)
}
}
#[cfg(feature = "extra_commands")]
Some(InteractiveMode::PromptProtected) => {
if prompt_yes!("msg") {
} else {
}
}
Some(_) => core_remove(args, item),
None => core_remove(args, item),
}
}
#[cfg(test)]
mod test {
use std::path::Path;
use std::{fs, path};
use crate::core::args::Cli;
use crate::core::rm::check_root;
use super::init_remove;
#[test]
fn test_check_root() {
let is_root = check_root();
assert!(!is_root);
}
#[test]
fn revome_files_in_some_dir_from_root() {
let base_dir = std::env::current_dir()
.unwrap()
.join("trash/tests/revome_files_in_some_dir_from_root");
fs::create_dir_all(&base_dir).unwrap();
let files = vec![
base_dir.join("file1.txt"),
base_dir.join("file2.pdf"),
base_dir.join("file3"),
];
for filename in &files {
fs::write(filename, "some contents").unwrap();
}
let args = Cli {
file: Some(files.clone()),
interactive: None,
recursive: false,
#[cfg(feature = "extra_commands")]
check: false,
#[cfg(feature = "extra_commands")]
dev: false,
force: None,
list: false,
verbose: false,
pattern: None,
command: None,
};
init_remove(files.clone(), &args).unwrap();
for filename in &files {
assert!(!path::Path::new(&filename).exists())
}
}
#[test]
fn revome_dirs_in_some_dir_from_root() {
let base_dir = std::env::current_dir()
.unwrap()
.join("trash/tests/revome_dirs_in_some_dir_from_root");
fs::create_dir_all(&base_dir).unwrap();
let dirs = vec![
base_dir.join("dir1"),
base_dir.join("dir2"),
base_dir.join("dir3"),
];
for dirnames in &dirs {
fs::create_dir(dirnames).unwrap();
}
let args = Cli {
file: Some(dirs.clone()),
interactive: None,
recursive: true,
#[cfg(feature = "extra_commands")]
check: false,
#[cfg(feature = "extra_commands")]
dev: false,
force: None,
list: false,
verbose: false,
pattern: None,
command: None,
};
init_remove(dirs.clone(), &args).unwrap();
for filename in &dirs {
assert!(!path::Path::new(&filename).exists())
}
}
#[test]
fn force_revome_dirs_in_some_dir_from_root() {
let base_dir = std::env::current_dir()
.unwrap()
.join("trash/tests/force_revome_dirs_in_some_dir_from_root");
if !base_dir.exists() {
fs::create_dir_all(&base_dir).unwrap();
}
let dirs = vec![
base_dir.join("dir1"),
base_dir.join("dir2"),
base_dir.join("dir3"),
];
for dirnames in &dirs {
if !dirnames.exists() {
fs::create_dir(dirnames).unwrap();
}
}
let args = Cli {
file: None,
interactive: None,
recursive: false,
#[cfg(feature = "extra_commands")]
check: false,
#[cfg(feature = "extra_commands")]
dev: false,
force: Some(dirs.clone()),
list: false,
verbose: false,
pattern: None,
command: None,
};
if let Some(forece_file) = args.force {
for item in forece_file {
if Path::new(&item).exists() {
if item.is_dir() {
fs::remove_dir_all(item).expect("Error while removing dirs");
} else {
fs::remove_file(item).expect("Error while removing files");
}
} else {
println!("Path didnt exists");
}
}
}
for filename in &dirs {
assert!(!path::Path::new(&filename).exists())
}
}
#[test]
fn list_files_in_some_dir_from_root() {
let base_dir = std::env::current_dir()
.unwrap()
.join("trash/tests/list_files_in_some_dir_from_root");
fs::create_dir_all(&base_dir).unwrap();
let files = vec![
base_dir.join("file1.txt"),
base_dir.join("file2.pdf"),
base_dir.join("file3"),
];
for filename in &files {
fs::write(filename, "some contents").unwrap();
}
let args = Cli {
file: Some(files.clone()),
interactive: None,
recursive: true,
#[cfg(feature = "extra_commands")]
check: false,
#[cfg(feature = "extra_commands")]
dev: false,
force: None,
list: true,
verbose: false,
pattern: None,
command: None,
};
init_remove(files.clone(), &args).unwrap();
for filename in &files {
assert!(path::Path::new(&filename).exists())
}
}
#[test]
fn pattern_files_in_some_dir_from_root() {
let base_dir = std::env::current_dir()
.unwrap()
.join("trash/tests/pattern_files_in_some_dir_from_root");
fs::create_dir_all(&base_dir).unwrap();
let files = vec![
base_dir.join("file1.txt"),
base_dir.join("file2.pdf"),
base_dir.join("file3"),
];
for filename in &files {
if !filename.exists() {
fs::write(filename, "some contents").unwrap();
}
}
let args = Cli {
file: Some(files.clone()),
interactive: None,
recursive: false,
#[cfg(feature = "extra_commands")]
check: false,
#[cfg(feature = "extra_commands")]
dev: false,
force: None,
list: false,
verbose: false,
pattern: Some("txt".to_string()),
command: None,
};
init_remove(files.clone(), &args).unwrap();
assert!(!path::Path::new(&base_dir.join("file1.txt")).exists());
assert!(path::Path::new(&base_dir.join("file2.pdf")).exists());
assert!(path::Path::new(&base_dir.join("file3")).exists());
}
}