diff --git a/bin/core/imag-ref/src/main.rs b/bin/core/imag-ref/src/main.rs index adb8d1e2..bd9f6ed6 100644 --- a/bin/core/imag-ref/src/main.rs +++ b/bin/core/imag-ref/src/main.rs @@ -74,9 +74,10 @@ fn main() { .map(|name| { debug!("Call: {}", name); match name { - "deref" => deref(&rt), - "create" => create(&rt), - "remove" => remove(&rt), + "deref" => deref(&rt), + "create" => create(&rt), + "remove" => remove(&rt), + "list-dead" => list_dead(&rt), other => { debug!("Unknown command"); let _ = rt.handle_unknown_subcommand("imag-ref", other, rt.cli()) @@ -161,6 +162,48 @@ fn remove(rt: &Runtime) { }); } +fn list_dead(rt: &Runtime) { + let cfg = get_ref_config(&rt, "imag-ref").map_err_trace_exit_unwrap(); + let cmd = rt.cli().subcommand_matches("list-dead").unwrap(); // safe by main() + let list_path = cmd.is_present("list-dead-pathes"); + let list_id = cmd.is_present("list-dead-ids"); + let mut output = rt.stdout(); + + rt.ids::<::ui::PathProvider>() + .map_err_trace_exit_unwrap() + .into_iter() + .for_each(|id| { + match rt.store().get(id.clone()).map_err_trace_exit_unwrap() { + Some(entry) => { + let entry_ref = entry.as_ref_with_hasher::(); + + if entry_ref.is_ref().map_err_trace_exit_unwrap() { // we only care if the entry is a ref + let entry_path = entry_ref.get_path(&cfg).map_err_trace_exit_unwrap(); + + if !entry_path.exists() { + if list_id { + writeln!(output, "{}", entry.get_location().local().display()) + } else if list_path { + writeln!(output, "{}", entry_path.display()) + } else { + unimplemented!() + } + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + + let _ = rt.report_touched(entry.get_location()).unwrap_or_exit(); + } + } + } + + None => { + error!("Does not exist: {}", id.local().display()); + exit(1) + } + } + }); +} + fn create(rt: &Runtime) { unimplemented!() } diff --git a/bin/core/imag-ref/src/ui.rs b/bin/core/imag-ref/src/ui.rs index 1a264ea5..21b5bb13 100644 --- a/bin/core/imag-ref/src/ui.rs +++ b/bin/core/imag-ref/src/ui.rs @@ -100,6 +100,35 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .multiple(false) .help("Use force to override existing references")) ) + + .subcommand(SubCommand::with_name("list-dead") + .about("List all dead references") + .version("0.1") + .arg(Arg::with_name("ID") + .index(1) + .takes_value(true) + .required(false) + .multiple(true) + .help("Filter these IDs for dead ones") + .value_name("ID")) + + .arg(Arg::with_name("list-dead-pathes") + .long("pathes") + .takes_value(false) + .required(false) + .multiple(false) + .conflicts_with("list-dead-ids") + .help("List pathes which do not exist anymore but are referenced from imag entries")) + + .arg(Arg::with_name("list-dead-ids") + .long("ids") + .takes_value(false) + .required(false) + .multiple(false) + .conflicts_with("list-dead-pathes") + .help("List ids of entries which refer to a path that does not exist")) + ) + } pub struct PathProvider; @@ -134,6 +163,20 @@ impl IdPathProvider for PathProvider { .map_err_trace_exit_unwrap() }, + ("list-dead", Some(subm)) => { + subm.values_of("ID") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap() + }, + ("create", _) => { error!("Command does not get IDs as input"); ::std::process::exit(1)