Add resurrect option

This commit is contained in:
Kevin Liu 2016-09-16 21:35:54 -07:00
parent 03530ae8b9
commit 2b0694f480
2 changed files with 44 additions and 21 deletions

View file

@ -1,6 +1,6 @@
[project] [project]
name = "rip" # rm improved name = "rip" # rm improved
version = "0.3.0" version = "0.4.0"
authors = ["mail@nivekuil.com"] authors = ["mail@nivekuil.com"]
[dependencies] [dependencies]

View file

@ -1,14 +1,17 @@
// -*- compile-command: "cargo build" -*- // -*- compile-command: "cargo build" -*-
#![feature(core_str_ext)]
#[macro_use] #[macro_use]
extern crate clap; extern crate clap;
extern crate core;
extern crate walkdir; extern crate walkdir;
use clap::{Arg, App}; use clap::{Arg, App};
use core::str::StrExt;
use walkdir::WalkDir; use walkdir::WalkDir;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::fs; use std::fs;
use std::io::Write;
use std::env; use std::env;
use std::io::{Read, Write};
static GRAVEYARD: &'static str = "/tmp/.graveyard"; static GRAVEYARD: &'static str = "/tmp/.graveyard";
static HISTFILE: &'static str = ".rip_history"; static HISTFILE: &'static str = ".rip_history";
@ -20,24 +23,29 @@ fn main() {
.about("Rm ImProved .about("Rm ImProved
Send files to the graveyard (/tmp/.graveyard) instead of unlinking them.") Send files to the graveyard (/tmp/.graveyard) instead of unlinking them.")
.arg(Arg::with_name("SOURCE") .arg(Arg::with_name("SOURCE")
.help("File or directory to remove") .help("File or directory to remove")
.required(true) .required(true)
.multiple(true) .multiple(true)
.index(1) .index(1)
.conflicts_with("decompose") .conflicts_with("decompose")
.conflicts_with("seance")) .conflicts_with("seance")
.conflicts_with("resurrect"))
.arg(Arg::with_name("graveyard") .arg(Arg::with_name("graveyard")
.help("Directory where deleted files go to rest") .help("Directory where deleted files go to rest")
.long("graveyard") .long("graveyard")
.takes_value(true)) .takes_value(true))
.arg(Arg::with_name("decompose") .arg(Arg::with_name("decompose")
.help("Permanently delete (unlink) the entire graveyard") .help("Permanently delete (unlink) the entire graveyard")
.long("decompose")) .long("decompose"))
.arg(Arg::with_name("seance") .arg(Arg::with_name("seance")
.help("List all objects in the graveyard that were sent from the \ .help("List all objects in the graveyard that were sent from the \
current directory") current directory")
.short("s") .short("s")
.long("seance")) .long("seance"))
.arg(Arg::with_name("resurrect")
.help("Undo the last deletion")
.short("r")
.long("resurrect"))
.get_matches(); .get_matches();
let graveyard: &Path = Path::new(matches.value_of("graveyard") let graveyard: &Path = Path::new(matches.value_of("graveyard")
@ -48,7 +56,23 @@ Send files to the graveyard (/tmp/.graveyard) instead of unlinking them.")
return; return;
} }
if matches.is_present("resurrect") {
let histfile = graveyard.join(HISTFILE);
let mut f = fs::File::open(histfile).expect("No histfile found.");
let mut s = String::new();
f.read_to_string(&mut s).unwrap();
let mut tokens = StrExt::split(s.as_str(), "\t");
let dest = tokens.next().expect("Bad histfile format for dest");
let source = tokens.next().expect("Bad histfile format for source");
if let Err(e) = bury(Path::new(source), Path::new(dest)) {
println!("ERROR: {}: {}", e, source);
}
println!("Returned {} to {}", source, dest);
return;
}
let cwd: PathBuf = env::current_dir().expect("Failed to get current dir"); let cwd: PathBuf = env::current_dir().expect("Failed to get current dir");
if matches.is_present("seance") { if matches.is_present("seance") {
let path = cwd.strip_prefix("/").unwrap(); let path = cwd.strip_prefix("/").unwrap();
for entry in WalkDir::new(graveyard.join(path)).into_iter().skip(1) { for entry in WalkDir::new(graveyard.join(path)).into_iter().skip(1) {
@ -63,11 +87,10 @@ Send files to the graveyard (/tmp/.graveyard) instead of unlinking them.")
return; return;
} }
let sources: clap::Values = matches.values_of("SOURCE").unwrap(); for source in matches.values_of("SOURCE").unwrap() {
for source in sources {
let path: PathBuf = cwd.join(Path::new(source)); let path: PathBuf = cwd.join(Path::new(source));
// Can't join absolute paths, so we need to strip the leading "/"
let dest: PathBuf = { let dest: PathBuf = {
// Can't join absolute paths, so we need to strip the leading "/"
let grave = graveyard.join(path.strip_prefix("/").unwrap()); let grave = graveyard.join(path.strip_prefix("/").unwrap());
if grave.exists() { rename_grave(grave) } else { grave } if grave.exists() { rename_grave(grave) } else { grave }
}; };
@ -80,7 +103,7 @@ Send files to the graveyard (/tmp/.graveyard) instead of unlinking them.")
} }
} }
/// Write deletion history to HISTFILE in the format "SOURCE\tDEST". /// Write deletion history to HISTFILE in the format "SOURCEPATH\tGRAVEPATH".
fn write_log(source: PathBuf, dest: PathBuf, graveyard: &Path) fn write_log(source: PathBuf, dest: PathBuf, graveyard: &Path)
-> std::io::Result<()> { -> std::io::Result<()> {
let histfile = graveyard.join(HISTFILE); let histfile = graveyard.join(HISTFILE);