summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-10-14 14:59:38 +0200
committerGitHub <noreply@github.com>2017-10-14 14:59:38 +0200
commit494327e109fb8f7bda0be793d8a7b1cbf2a5a718 (patch)
treee163697b656751dd7f116207770b425471a9af08
parentbdf1848f3f5f7bf962725f057cd3236b57486544 (diff)
parent38494a31da0525dd679f9742121c2b1bd286e48a (diff)
downloadimag-494327e109fb8f7bda0be793d8a7b1cbf2a5a718.zip
imag-494327e109fb8f7bda0be793d8a7b1cbf2a5a718.tar.gz
Merge pull request #1142 from matthiasbeyer/libimagentryref/abbrev-hash
libimagentryref: abbrev hash
-rw-r--r--bin/core/imag-ref/src/main.rs24
-rw-r--r--lib/entry/libimagentryref/src/refstore.rs49
2 files changed, 53 insertions, 20 deletions
diff --git a/bin/core/imag-ref/src/main.rs b/bin/core/imag-ref/src/main.rs
index 1420f5f..742d11e 100644
--- a/bin/core/imag-ref/src/main.rs
+++ b/bin/core/imag-ref/src/main.rs
@@ -47,10 +47,12 @@ mod ui;
use ui::build_ui;
use std::path::PathBuf;
+use std::process::exit;
use libimagentryref::refstore::RefStore;
use libimagentryref::flags::RefFlags;
use libimagerror::trace::trace_error;
+use libimagerror::trace::MapErrTrace;
use libimagrt::setup::generate_runtime_setup;
use libimagrt::runtime::Runtime;
@@ -101,14 +103,20 @@ fn remove(rt: &Runtime) {
let hash = cmd.value_of("hash").map(String::from).unwrap(); // saved by clap
let yes = cmd.is_present("yes");
- if yes || ask_bool(&format!("Delete Ref with hash '{}'", hash)[..], None) {
- match rt.store().delete_by_hash(hash) {
- Err(e) => trace_error(&e),
- Ok(_) => info!("Ok"),
- }
- } else {
- info!("Aborted");
- }
+ match rt.store().find_storeid_by_partial_hash(&hash).map_err_trace_exit_unwrap(1) {
+ Some(sid) => {
+ if yes || ask_bool(&format!("Delete Ref with hash '{}'", hash)[..], None) {
+ debug!("Found for hash '{}' -> {:?}", hash, sid);
+ rt.store().delete(sid).map_err_trace_exit_unwrap(1)
+ } else {
+ info!("Aborted");
+ }
+ },
+ None => {
+ error!("Not id for hash '{}' found", hash);
+ exit(1)
+ },
+ };
}
diff --git a/lib/entry/libimagentryref/src/refstore.rs b/lib/entry/libimagentryref/src/refstore.rs
index e992a9b..102d3d9 100644
--- a/lib/entry/libimagentryref/src/refstore.rs
+++ b/lib/entry/libimagentryref/src/refstore.rs
@@ -22,8 +22,8 @@ use std::collections::BTreeMap;
use std::fs::File;
use libimagstore::store::FileLockEntry;
-use libimagstore::storeid::StoreId;
use libimagstore::storeid::IntoStoreId;
+use libimagstore::storeid::StoreId;
use libimagstore::storeid::StoreIdIterator;
use libimagstore::store::Store;
@@ -43,14 +43,21 @@ pub trait RefStore {
/// Check whether there is a reference to the file at `pb`
fn exists(&self, pb: PathBuf) -> Result<bool>;
- /// Try to get `si` as Ref object from the store
- fn get<'a>(&'a self, si: StoreId) -> Result<FileLockEntry<'a>>;
-
/// Get a Ref object from the store by hash.
///
/// Returns None if the hash cannot be found.
fn get_by_hash<'a>(&'a self, hash: String) -> Result<Option<FileLockEntry<'a>>>;
+ /// Find a store id by partial ref (also see documentation for
+ /// `RefStore::get_by_partitial_hash()`.
+ fn find_storeid_by_partial_hash(&self, hash: &String) -> Result<Option<StoreId>>;
+
+ /// Get a Ref object from the store by (eventually partial) hash.
+ ///
+ /// If the hash is complete, `RefStore::get_by_hash()` should be used as it is cheaper.
+ /// If the hash comes from user input and thus might be abbreviated, this function can be used.
+ fn get_by_partitial_hash<'a>(&'a self, hash: &String) -> Result<Option<FileLockEntry<'a>>>;
+
/// Delete a ref by hash
///
/// If the returned Result contains an error, the ref might not be deleted.
@@ -111,14 +118,6 @@ impl RefStore for Store {
})
}
- /// Try to get `si` as Ref object from the store
- fn get<'a>(&'a self, si: StoreId) -> Result<FileLockEntry<'a>> {
- match self.get(si)? {
- None => return Err(RE::from_kind(REK::RefNotInStore)),
- Some(fle) => Ok(fle),
- }
- }
-
/// Get a Ref object from the store by hash.
///
/// Returns None if the hash cannot be found.
@@ -129,6 +128,32 @@ impl RefStore for Store {
.map_err(From::from)
}
+ fn find_storeid_by_partial_hash(&self, hash: &String) -> Result<Option<StoreId>> {
+ debug!("Trying to find '{}' in store...", hash);
+ for id in self.retrieve_for_module("ref")? {
+ let components_have_hash = id
+ .components()
+ .any(|c| c.as_os_str().to_str().map(|s| s.contains(hash)).unwrap_or(false));
+
+ if components_have_hash {
+ debug!("Found hash '{}' in {:?}", hash, id);
+ return Ok(Some(id))
+ }
+ }
+ Ok(None)
+ }
+
+ /// Get a Ref object from the store by (eventually partial) hash.
+ ///
+ /// If the hash is complete, `RefStore::get_by_hash()` should be used as it is cheaper.
+ /// If the hash comes from user input and thus might be abbreviated, this function can be used.
+ fn get_by_partitial_hash<'a>(&'a self, hash: &String) -> Result<Option<FileLockEntry<'a>>> {
+ match self.find_storeid_by_partial_hash(hash)? {
+ Some(id) => self.get(id).map_err(From::from),
+ None => Ok(None),
+ }
+ }
+
/// Delete a ref by hash
///
/// If the returned Result contains an error, the ref might not be deleted.