Skip to content

Commit

Permalink
Using clap for parsing arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
obvMellow committed Jul 31, 2024
1 parent 51899c0 commit 96f8182
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 149 deletions.
53 changes: 53 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ indicatif-log-bridge = "0.2.2"
colog = "1.3.0"
log = "0.4.22"
rand = "0.9.0-alpha.1"
clap = { version = "4.5.11", features = ["derive"] }
74 changes: 22 additions & 52 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,35 @@ use ini::Ini;
use std::fs;
use std::path::PathBuf;

pub fn revert(config_dir: PathBuf, mut config: Ini, args: &Vec<String>) {
let i = args
.iter()
.position(|v| v == &"revert".to_string())
.unwrap();
let hash = match args.get(i + 1) {
Some(v) => v,
None => {
eprintln!("Please enter a valid ID.");
return;
}
};

pub fn revert(config_dir: PathBuf, mut config: Ini, id: String, multithread: bool) {
let mut setter = config.with_section(Some("Backups"));
let mut vec = match setter.get(hash) {
let mut vec = match setter.get(&id) {
Some(v) => v.split(SEPARATOR),
None => {
eprintln!("Couldn't find \"{}\".", hash);
eprintln!("Couldn't find \"{}\".", id);
return;
}
};
let mut dest_str = PathBuf::from(vec.nth(0).unwrap().to_string());
dest_str.pop();
let dest_str = dest_str.to_str().unwrap().to_string();
let mut source_str = vec.nth(0).unwrap().to_string(); // Getting the first element again because .nth() consumes all preceding and the returned element
let source_str = vec.nth(0).unwrap().to_string(); // Getting the first element again because .nth() consumes all preceding and the returned element

_copy(config_dir, &mut config, args, &mut source_str, dest_str);
_copy(
config_dir,
&mut config,
multithread,
source_str.into(),
dest_str.into(),
);
}

pub fn delete(mut config_dir: PathBuf, mut config: Ini, args: &Vec<String>) {
let i = args
.iter()
.position(|v| v == &"delete".to_string())
.unwrap();
let hash = match args.get(i + 1) {
Some(v) => v,
None => {
eprintln!("Please enter a valid ID.");
return;
}
};

pub fn delete(mut config_dir: PathBuf, mut config: Ini, id: String) {
let mut setter = config.with_section(Some("Backups"));
let dest = match setter.get(hash) {
let dest = match setter.get(&id) {
Some(v) => v.split(SEPARATOR).collect::<Vec<&str>>()[1],
None => {
eprintln!("Couldn't find \"{}\".", hash);
eprintln!("Couldn't find \"{}\".", id);
return;
}
};
Expand All @@ -62,27 +44,15 @@ pub fn delete(mut config_dir: PathBuf, mut config: Ini, args: &Vec<String>) {
}
};
println!("Deleted {}", dest);
_delete_entry(&mut config_dir, &mut config, hash);
_delete_entry(&mut config_dir, &mut config, &id);
}

pub fn soft_delete(mut config_dir: PathBuf, mut config: Ini, args: &Vec<String>) {
let i = args
.iter()
.position(|v| v == &"soft-delete".to_string())
.unwrap();
let hash = match args.get(i + 1) {
Some(v) => v,
None => {
eprintln!("Please enter a valid ID.");
return;
}
};

if _delete_entry(&mut config_dir, &mut config, hash) {
println!("Deleted {}", hash);
pub fn soft_delete(mut config_dir: PathBuf, mut config: Ini, id: String) {
if _delete_entry(&mut config_dir, &mut config, &id) {
println!("Deleted {}", id);
return;
}
eprintln!("Couldn't find \"{}\".", hash);
eprintln!("Couldn't find \"{}\".", id);
}

pub fn list(config: Ini) {
Expand All @@ -103,9 +73,9 @@ pub fn list(config: Ini) {
}
}

fn _delete_entry(config_dir: &mut PathBuf, config: &mut Ini, hash: &String) -> bool {
if config.with_section(Some("Backups")).get(hash).is_some() {
config.with_section(Some("Backups")).delete(hash);
fn _delete_entry(config_dir: &mut PathBuf, config: &mut Ini, id: &String) -> bool {
if config.with_section(Some("Backups")).get(id).is_some() {
config.with_section(Some("Backups")).delete(id);
} else {
return false;
}
Expand Down
120 changes: 57 additions & 63 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#![feature(test)]

mod commands;
mod test;

#[cfg(not(test))]
use indicatif_log_bridge::LogWrapper;

use crate::commands::*;
use clap::{Parser, Subcommand};
use colored::Colorize;
use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle};
use ini::Ini;
Expand Down Expand Up @@ -89,17 +88,39 @@ impl From<u64> for FileSize {
}
}

const HELP_STR: &str = "\
Usage: hardcpy [SOURCE] [DESTINATION] [OPTIONS]
hardcpy [COMMAND]
Commands:
help: Prints this message.
list: Lists all the backups you have created so far.
soft-delete: Deletes the entry for a backup. This does not delete any of the files.
delete: Deletes a backup.
revert: Copies a backup to it's original source. Note that this creates a new backup entry.
Options:
--multi-thread: Utilize multi-threading. Can be faster on very large folders.";
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
#[command(subcommand)]
command: Commands,
}

#[derive(Subcommand, Debug)]
enum Commands {
List,
SoftDelete {
#[arg(short, long)]
id: String,
},
Delete {
#[arg(short, long)]
id: String,
},
Revert {
#[arg(short, long)]
id: String,

#[arg(short, long)]
multithread: bool
},
Create {
source: PathBuf,
dest: PathBuf,

#[arg(short, long)]
multithread: bool
},
}

const SEPARATOR: char = '┇';

Expand All @@ -116,89 +137,62 @@ fn main() {

let mut config = Ini::load_from_file(config_dir.join("config.ini")).unwrap_or(Ini::new());

let args: Vec<String> = std::env::args().collect();

if args.len() < 2 {
println!("{}", HELP_STR);
return;
}

let cmd = &args[1];

match cmd.as_str() {
"help" => println!("{}", HELP_STR),
"list" => list(config),
"soft-delete" => soft_delete(config_dir, config, &args),
"delete" => delete(config_dir, config, &args),
"revert" => revert(config_dir, config, &args),
_ => {
let mut source_str = "".to_string();
let mut dest_str = "".to_string();
for arg in args.clone() {
if arg.starts_with("--")
|| std::env::current_exe()
.unwrap()
.to_str()
.unwrap()
.contains(&arg)
{
continue;
}

if source_str.is_empty() {
source_str = arg;
} else {
dest_str = arg;
}
}

if source_str.is_empty() || dest_str.is_empty() {
println!("{}", HELP_STR);
return;
}
let args = Args::parse();

_copy(config_dir, &mut config, &args, &mut source_str, dest_str);
match args.command {
Commands::List => list(config),
Commands::SoftDelete { id } => soft_delete(config_dir, config, id),
Commands::Delete { id } => delete(config_dir, config, id),
Commands::Revert { id, multithread } => revert(config_dir, config, id, multithread),
Commands::Create { source, dest, multithread } => {
_copy(config_dir, &mut config, multithread, source, dest);
}
}
}

fn _copy(
config_dir: PathBuf,
config: &mut Ini,
args: &Vec<String>,
source_str: &mut String,
dest_str: String,
is_multithread: bool,
source_str: PathBuf,
dest_str: PathBuf,
) -> bool {
let source_name = PathBuf::from(&source_str).iter().last().unwrap().to_owned();
let source_name = source_str.iter().last().unwrap().to_owned();

let source = match fs::read_dir(&source_str) {
Ok(d) => d,
Err(e) => {
eprintln!("Error: {} (\"{}\")", e, source_str);
eprintln!("Error: {} (\"{}\")", e, source_str.display());
return true;
}
};

match fs::create_dir_all(&dest_str) {
Ok(_) => {}
Err(e) => {
eprintln!("{} {} (\"{}\")", "Error:".red().bold(), e, dest_str);
eprintln!(
"{} {} (\"{}\")",
"Error:".red().bold(),
e,
dest_str.display()
);
return true;
}
}

let timer = Instant::now();
let conclusion;

if args.contains(&"--multi-thread".to_string()) {
if is_multithread {
conclusion = multithread(source, PathBuf::from(&dest_str), source_name.clone());
} else {
conclusion = singlethread(source, PathBuf::from(&dest_str), source_name.clone());
}

let v = format!(
"{source_str}{SEPARATOR}{}",
PathBuf::from(&dest_str).join(source_name).to_str().unwrap()
"{}{SEPARATOR}{}",
source_str.display(),
dest_str.join(source_name).to_str().unwrap()
);
let mut hasher = fnv::FnvHasher::default();
v.hash(&mut hasher);
Expand Down
Loading

0 comments on commit 96f8182

Please sign in to comment.