Skip to content

Commit

Permalink
Merge pull request #18 from AmineZouitine/error_handling
Browse files Browse the repository at this point in the history
Error handling
  • Loading branch information
AmineZouitine authored Oct 13, 2022
2 parents 97050bf + 6a35c61 commit 964d5aa
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 58 deletions.
59 changes: 59 additions & 0 deletions src/argument_errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use core::fmt;
use std::error::Error;

use colored::Colorize;

#[derive(Debug)]
pub enum RmtArgumentErrors {
InvalidNumberOfArguments(usize),
InvalidDirFlags {
folder_name: String,
element_in_folder: usize,
},
InvalidFillFolderFlags {
folder_name: String,
},
InvalidEmptyFolderFlags {
folder_name: String,
},
InvalidElementName {
element_name: String,
},
}

impl RmtArgumentErrors {
fn error_message(&self) -> String {
match self {
RmtArgumentErrors::InvalidNumberOfArguments(args_number) => format!(
"The number of arguments ({}) is not valid.",
args_number.to_string().red().bold(),
),
RmtArgumentErrors::InvalidDirFlags { folder_name, element_in_folder } => format!("You cannot delete {} folder with the {} flags because there is {} elements inside, you should use {} flags instead.", folder_name.red().bold(), "-d".red().bold().green(), element_in_folder.to_string().red().bold(), "-r".green().bold()),
RmtArgumentErrors::InvalidEmptyFolderFlags { folder_name } => format!("You cannot delete {} folder without using {} or {} flags.", folder_name.red().bold(), "-r".green().bold(), "-d".green().bold()),
RmtArgumentErrors::InvalidFillFolderFlags { folder_name } => format!("You cannot delete {} folder without using {} flags (do no use {} flags because your directory isn't empty).", folder_name.red().bold(), "-r".green().bold(), "-d".green().bold()),
RmtArgumentErrors::InvalidElementName { element_name} => format!("you cannot destroy your {} because it doesn't exist (use the {} option to stop getting this warning).", element_name.red().bold(), "-f".green().bold())
}
}

fn default_help_message() -> String {
format!(
"Use the {} option to get more details on how to use {}.",
"rmt --help".bold().green(),
"rmt".bold()
)
}
}

impl fmt::Display for RmtArgumentErrors {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}: {}\n{}",
"Error".red().bold(),
self.error_message(),
RmtArgumentErrors::default_help_message().italic()
)
}
}

impl Error for RmtArgumentErrors {}
85 changes: 51 additions & 34 deletions src/data_manager.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use crate::structure_manager;
use std::process::exit;

use crate::trash_item::TrashItem;
use crate::{database_errors::RmtDataBaseErrors, structure_manager};
use rusqlite::{params, types::FromSql, Connection, Row};

// Create the database and the table to save information about deleted elements.
pub fn setup_data_base(is_test: bool) -> Connection {
let connection = structure_manager::create_data_base_file(is_test);
let table_name = structure_manager::get_data_base_table_name(is_test);

connection
.execute(
&format!(
"CREATE TABLE IF NOT EXISTS {} (
let stmt_result = connection.execute(
&format!(
"CREATE TABLE IF NOT EXISTS {} (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
hash NOT NULL UNIQUE,
Expand All @@ -20,29 +21,41 @@ pub fn setup_data_base(is_test: bool) -> Connection {
compression_size INTEGER,
is_folder INTEGER NOT NULL
)",
table_name
),
[],
)
.unwrap_or_else(|_| panic!("Unable to execute creation of {} table", table_name));

connection
table_name
),
[],
);

match stmt_result {
Ok(_) => connection,
Err(_) => {
println!("{}", RmtDataBaseErrors::DataBaseCreation);
exit(1);
}
}
}

fn get<T: FromSql>(row: &Row, index: usize) -> T {
let element: T = row
.get(index)
.unwrap_or_else(|_| panic!("Get a {} not valid", index));
element
match row.get(index) {
Ok(element) => element,
Err(_) => {
println!("{}", RmtDataBaseErrors::GetCellElement(index));
exit(1);
}
}
}

// Find all elements on the table and convert them to TrashItems
pub fn find_all_trash_items(connection: &Connection, is_test: bool) -> Vec<TrashItem> {
let table_name = structure_manager::get_data_base_table_name(is_test);

let mut stmt = connection
.prepare(&format!("SELECT * FROM {}", table_name))
.expect("Cannot select every element in database");
let mut stmt = match connection.prepare(&format!("SELECT * FROM {}", table_name)) {
Ok(stmt) => stmt,
Err(_) => {
println!("{}", RmtDataBaseErrors::SelectAllElements);
exit(1);
}
};

let mut trash_items = Vec::<TrashItem>::new();

Expand Down Expand Up @@ -88,7 +101,7 @@ pub fn delete_trash_item_by_id(connection: &Connection, is_test: bool, id: i32)
pub fn insert_trash_item(connection: &Connection, trash_item: &TrashItem, is_test: bool) {
let table_name = structure_manager::get_data_base_table_name(is_test);

connection
let stmt_result = connection
.execute(
&format!("INSERT INTO {} (name, hash, path, date, real_size, compression_size, is_folder) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)", table_name),
params![
Expand All @@ -100,25 +113,29 @@ pub fn insert_trash_item(connection: &Connection, trash_item: &TrashItem, is_tes
trash_item.compression_size,
trash_item.is_folder
],
)
.unwrap_or_else(|_| panic!("Unable to do insert element request with this values : {:?}",
trash_item));
);

match stmt_result {
Ok(_) => (),
Err(_) => println!("{}", RmtDataBaseErrors::InsertTrashItem),
};
}

pub fn delete_trash_item(connection: &Connection, trash_item_id: i32, is_test: bool) {
let table_name = structure_manager::get_data_base_table_name(is_test);

connection
.execute(
&format!("DELETE FROM {} WHERE id = (?1)", table_name),
params![trash_item_id],
)
.unwrap_or_else(|_| {
panic!(
"Unable to do delete element request with this id : {}",
trash_item_id
)
});
let stmt_result = connection.execute(
&format!("DELETE FROM {} WHERE id = (?1)", table_name),
params![trash_item_id],
);

match stmt_result {
Ok(_) => (),
Err(_) => {
println!("{}", RmtDataBaseErrors::DeleteElementById(trash_item_id));
exit(1);
}
}
}

pub fn delete_all_trash_item(connection: &Connection, is_test: bool) {
Expand Down
59 changes: 59 additions & 0 deletions src/database_errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use core::fmt;
use std::error::Error;

use colored::Colorize;

use crate::trash_item::TrashItem;

#[derive(Debug)]
pub enum RmtDataBaseErrors {
DataBaseCreation,
SelectAllElements,
GetCellElement(usize),
DeleteElementById(i32),
InsertTrashItem,
DeleteAllElement,
}

impl RmtDataBaseErrors {
fn error_message(&self) -> String {
match self {
RmtDataBaseErrors::DataBaseCreation => "Impossible to create the database.".to_string(),
RmtDataBaseErrors::SelectAllElements => {
"Impossible to select all the elements.".to_string()
}
RmtDataBaseErrors::GetCellElement(index) => format!(
"Impossible to retrieve the cell with index {}.",
index.to_string().red().bold()
),
RmtDataBaseErrors::DeleteElementById(id) => format!(
"Impossible to delete the element at index {}.",
id.to_string().red().bold()
),
RmtDataBaseErrors::InsertTrashItem => format!("Impossible to insert the trashItem.",),
RmtDataBaseErrors::DeleteAllElement => "Impossible to delete all elements.".to_string(),
}
}

fn default_help_message() -> String {
format!(
"If you haven't touched the {} file yourself, please open an issue on: {} with as many details as possible.",
".trash_rmt".red().bold(),
"https://github.com/AmineZouitine/rmt.rs".bold().green()
)
}
}

impl fmt::Display for RmtDataBaseErrors {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}: {}\n{}",
"Error".red().bold(),
self.error_message(),
RmtDataBaseErrors::default_help_message().italic()
)
}
}

impl Error for RmtDataBaseErrors {}
10 changes: 5 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
pub mod argument_errors;
pub mod arguments_manager;
pub mod config;
pub mod config_manager;
pub mod data_manager;
pub mod database_errors;
pub mod display_manager;
pub mod input_manager;
pub mod structure_manager;
Expand All @@ -11,6 +13,8 @@ use arguments_manager::ArgumentsManager;
use clap::Parser;
use colored::Colorize;

use crate::argument_errors::RmtArgumentErrors;

fn main() {
let is_test = false;
let arguments_manager = ArgumentsManager::parse();
Expand All @@ -21,11 +25,7 @@ fn main() {
&& !arguments_manager.is_trash_display
&& !arguments_manager.is_trash_info
{
println!(
"{}\nYou should use {}",
"The arguments are not valid.".red().bold(),
"rmt --help".green().bold()
);
println!("{}", RmtArgumentErrors::InvalidNumberOfArguments(0));
return;
}

Expand Down
45 changes: 26 additions & 19 deletions src/trash_manager.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::argument_errors::RmtArgumentErrors;
use crate::arguments_manager::ArgumentsManager;
use crate::display_manager;
use crate::structure_manager::{self, get_element_name, get_element_path, get_home_directory_path};
Expand Down Expand Up @@ -28,37 +29,38 @@ pub fn add_element_to_trash(
element_name: &str,
is_test: bool,
arguments_manager: &ArgumentsManager,
) {
) -> Result<(), RmtArgumentErrors> {
let mut element_path = match abspath(element_name) {
Some(path) => {
if Path::new(&path).is_dir() {
let element_in_dir = fs::read_dir(&path).unwrap().count();
if (element_in_dir == 0
if element_in_dir == 0
&& !arguments_manager.is_empty_dir
&& !arguments_manager.is_recursive)
|| (element_in_dir > 0 && !arguments_manager.is_recursive)
&& !arguments_manager.is_recursive
{
println!(
"Cannot delete the folder {} without the {} option or {} (for an empty folder)",
element_name.green().bold(),
"-r".bold().green(),
"-d".bold().green()
);
return;
return Err(RmtArgumentErrors::InvalidEmptyFolderFlags {
folder_name: element_name.to_string(),
});
} else if element_in_dir > 0 && arguments_manager.is_empty_dir {
return Err(RmtArgumentErrors::InvalidDirFlags {
folder_name: element_name.to_string(),
element_in_folder: element_in_dir,
});
} else if element_in_dir > 0 && !arguments_manager.is_recursive {
return Err(RmtArgumentErrors::InvalidFillFolderFlags {
folder_name: element_name.to_string(),
});
}
}
path
}
None => {
if arguments_manager.is_force {
return;
return Ok(());
}
println!(
"Unable to delete {}: No such file or folder (use {} to remove warnings)",
element_name.green().bold(),
"-f".green().bold()
);
return;
return Err(RmtArgumentErrors::InvalidElementName {
element_name: element_name.to_string(),
});
}
};

Expand Down Expand Up @@ -119,6 +121,7 @@ pub fn add_element_to_trash(
element_name.green().bold()
);
}
Ok(())
}

pub fn add_all_elements_to_trash(
Expand All @@ -141,7 +144,11 @@ pub fn add_all_elements_to_trash(
let message = format!("Are you sure to delete {} ?", path.bold().green());
if !arguments_manager.confirmation_always || display_manager::get_user_validation(&message)
{
add_element_to_trash(connection, config, path, is_test, arguments_manager);
if let Err(rmt_error) =
add_element_to_trash(connection, config, path, is_test, arguments_manager)
{
println!("{}", rmt_error);
}
}
}
}
Expand Down

0 comments on commit 964d5aa

Please sign in to comment.