diff --git a/bin/core/imag-ref/src/main.rs b/bin/core/imag-ref/src/main.rs index a9500beb..adb8d1e2 100644 --- a/bin/core/imag-ref/src/main.rs +++ b/bin/core/imag-ref/src/main.rs @@ -36,6 +36,7 @@ #[macro_use] extern crate log; extern crate clap; +extern crate failure; extern crate libimagstore; #[macro_use] extern crate libimagrt; @@ -50,6 +51,8 @@ use ui::build_ui; use std::process::exit; use std::io::Write; +use failure::Error; + use libimagerror::trace::MapErrTrace; use libimagerror::exit::ExitUnwrap; use libimagrt::setup::generate_runtime_setup; @@ -86,27 +89,30 @@ fn main() { } fn deref(rt: &Runtime) { - let cmd = rt.cli().subcommand_matches("deref").unwrap(); - let ids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(); - let cfg = get_ref_config(&rt, "imag-ref").map_err_trace_exit_unwrap(); - let out = rt.stdout(); + let cmd = rt.cli().subcommand_matches("deref").unwrap(); + let basepath = cmd.value_of("override-basepath"); + let ids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(); + let cfg = get_ref_config(&rt, "imag-ref").map_err_trace_exit_unwrap(); + let out = rt.stdout(); let mut outlock = out.lock(); ids.into_iter() .for_each(|id| { match rt.store().get(id.clone()).map_err_trace_exit_unwrap() { Some(entry) => { - entry - .as_ref_with_hasher::() - .get_path(&cfg) - .map_err_trace_exit_unwrap() - .to_str() - .ok_or_else(|| { - error!("Could not transform path into string!"); - exit(1) - }) - .map(|s| writeln!(outlock, "{}", s)) - .ok(); // safe here because we exited already in the error case + let r_entry = entry.as_ref_with_hasher::(); + + if let Some(alternative_basepath) = basepath { + r_entry.get_path_with_basepath_setting(&cfg, alternative_basepath) + } else { + r_entry.get_path(&cfg) + } + .map_err_trace_exit_unwrap() + .to_str() + .ok_or_else(|| ::libimagerror::errors::ErrorMsg::UTF8Error) + .map_err(Error::from) + .and_then(|s| writeln!(outlock, "{}", s).map_err(Error::from)) + .map_err_trace_exit_unwrap(); let _ = rt.report_touched(&id).unwrap_or_exit(); }, diff --git a/bin/core/imag-ref/src/ui.rs b/bin/core/imag-ref/src/ui.rs index c14eafe2..1a264ea5 100644 --- a/bin/core/imag-ref/src/ui.rs +++ b/bin/core/imag-ref/src/ui.rs @@ -45,6 +45,14 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .required(false) .multiple(false) .help("Ignore store entries which are not refs and do not print error message")) + + .arg(Arg::with_name("override-basepath") + .long("basepath-setting") + .short("B") + .takes_value(true) + .required(false) + .multiple(false) + .help("Override the basepath key to look up in the configuration")) ) .subcommand(SubCommand::with_name("remove") diff --git a/lib/entry/libimagentryref/src/reference.rs b/lib/entry/libimagentryref/src/reference.rs index fe9014d8..da1ce325 100644 --- a/lib/entry/libimagentryref/src/reference.rs +++ b/lib/entry/libimagentryref/src/reference.rs @@ -28,6 +28,7 @@ use libimagerror::errors::ErrorMsg as EM; use toml::Value; use toml_query::read::TomlValueReadExt; +use toml_query::read::TomlValueReadTypeExt; use toml_query::read::Partial; use toml_query::delete::TomlValueDeleteExt; use toml_query::insert::TomlValueInsertExt; @@ -146,6 +147,9 @@ pub trait Ref { fn get_path(&self, config: &Config) -> Result; + fn get_path_with_basepath_setting(&self, config: &Config, base: B) -> Result + where B: AsRef; + fn get_relative_path(&self) -> Result; /// Get the stored hash. @@ -180,20 +184,25 @@ impl<'a, H: Hasher> Ref for RefWithHasher<'a, H> { /// Get the path of the actual file fn get_path(&self, config: &Config) -> Result { - use toml_query::read::TomlValueReadTypeExt; + let basepath_name = self.0 + .get_header() + .read_string("ref.basepath")? + .ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.basepath")))?; + self.get_path_with_basepath_setting(config, basepath_name) + } + + fn get_path_with_basepath_setting(&self, config: &Config, base: B) + -> Result + where B: AsRef + { let relpath = self.0 .get_header() .read_string("ref.relpath")? .map(PathBuf::from) .ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.relpath")))?; - let basepath_name = self.0 - .get_header() - .read_string("ref.basepath")? - .ok_or_else(|| Error::from(EM::EntryHeaderFieldMissing("ref.basepath")))?; - - get_file_path(config, &basepath_name, relpath) + get_file_path(config, base.as_ref(), relpath) } /// Get the relative path, relative to the configured basepath