Merge pull request #667 from matthiasbeyer/rewrite-storeid-type
Rewrite storeid type
This commit is contained in:
commit
737aab80dc
48 changed files with 482 additions and 470 deletions
|
@ -1,4 +1,3 @@
|
|||
use std::path::PathBuf;
|
||||
use std::process::exit;
|
||||
|
||||
use libimagdiary::diary::Diary;
|
||||
|
@ -8,7 +7,6 @@ use libimagentrylist::listers::core::CoreLister;
|
|||
use libimagentrylist::lister::Lister;
|
||||
use libimagrt::runtime::Runtime;
|
||||
use libimagstore::store::Entry;
|
||||
use libimagstore::storeid::StoreId;
|
||||
use libimagerror::trace::trace_error;
|
||||
|
||||
use util::get_diary_name;
|
||||
|
@ -21,11 +19,11 @@ pub fn list(rt: &Runtime) {
|
|||
}
|
||||
let diaryname = diaryname.unwrap();
|
||||
|
||||
fn location_to_listing_string(id: &StoreId, base: &PathBuf) -> String {
|
||||
id.strip_prefix(base)
|
||||
fn entry_to_location_listing_string(e: &Entry) -> String {
|
||||
e.get_location().clone()
|
||||
.without_base()
|
||||
.to_str()
|
||||
.map_err(|e| trace_error(&e))
|
||||
.ok()
|
||||
.and_then(|p| p.to_str().map(String::from))
|
||||
.unwrap_or(String::from("<<Path Parsing Error>>"))
|
||||
}
|
||||
|
||||
|
@ -40,9 +38,7 @@ pub fn list(rt: &Runtime) {
|
|||
a.ok()
|
||||
}).map(|e| e.into());
|
||||
|
||||
let base = rt.store().path();
|
||||
|
||||
CoreLister::new(&move |e: &Entry| location_to_listing_string(e.get_location(), base))
|
||||
CoreLister::new(&entry_to_location_listing_string)
|
||||
.list(es) // TODO: Do not ignore non-ok()s
|
||||
.map_err(|e| DE::new(DEK::IOError, Some(Box::new(e))))
|
||||
})
|
||||
|
|
|
@ -23,3 +23,6 @@ path = "../libimagentrylink"
|
|||
[dependencies.libimagerror]
|
||||
path = "../libimagerror"
|
||||
|
||||
[dependencies.libimagutil]
|
||||
path = "../libimagutil"
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ extern crate libimagentrylink;
|
|||
extern crate libimagrt;
|
||||
extern crate libimagstore;
|
||||
extern crate libimagerror;
|
||||
extern crate libimagutil;
|
||||
|
||||
use std::process::exit;
|
||||
use std::ops::Deref;
|
||||
|
@ -36,6 +37,7 @@ use libimagstore::store::FileLockEntry;
|
|||
use libimagstore::store::Store;
|
||||
use libimagerror::trace::{trace_error, trace_error_exit};
|
||||
use libimagentrylink::external::ExternalLinker;
|
||||
use libimagutil::warn_result::*;
|
||||
use clap::ArgMatches;
|
||||
use url::Url;
|
||||
|
||||
|
@ -74,10 +76,19 @@ fn handle_internal_linking(rt: &Runtime) {
|
|||
for entry in cmd.value_of("list").unwrap().split(',') {
|
||||
debug!("Listing for '{}'", entry);
|
||||
match get_entry_by_name(rt, entry) {
|
||||
Ok(e) => {
|
||||
Ok(Some(e)) => {
|
||||
e.get_internal_links()
|
||||
.map(|links| {
|
||||
for (i, link) in links.iter().map(|l| l.to_str()).filter_map(|x| x).enumerate() {
|
||||
let i = links
|
||||
.iter()
|
||||
.filter_map(|l| {
|
||||
l.to_str()
|
||||
.map_warn_err(|e| format!("Failed to convert StoreId to string: {:?}", e))
|
||||
.ok()
|
||||
})
|
||||
.enumerate();
|
||||
|
||||
for (i, link) in i {
|
||||
println!("{: <3}: {}", i, link);
|
||||
}
|
||||
})
|
||||
|
@ -85,6 +96,11 @@ fn handle_internal_linking(rt: &Runtime) {
|
|||
.ok();
|
||||
},
|
||||
|
||||
Ok(None) => {
|
||||
warn!("Entry not found: {:?}", entry);
|
||||
break;
|
||||
}
|
||||
|
||||
Err(e) => {
|
||||
trace_error(&e);
|
||||
break;
|
||||
|
@ -148,7 +164,8 @@ fn get_from_entry<'a>(rt: &'a Runtime) -> Option<FileLockEntry<'a>> {
|
|||
debug!("We couldn't get the entry from name: '{:?}'", from_name);
|
||||
trace_error(&e); None
|
||||
},
|
||||
Ok(e) => Some(e),
|
||||
Ok(Some(e)) => Some(e),
|
||||
Ok(None) => None,
|
||||
}
|
||||
|
||||
})
|
||||
|
@ -166,17 +183,20 @@ fn get_to_entries<'a>(rt: &'a Runtime) -> Option<Vec<FileLockEntry<'a>>> {
|
|||
for entry in values.map(|v| get_entry_by_name(rt, v)) {
|
||||
match entry {
|
||||
Err(e) => trace_error(&e),
|
||||
Ok(e) => v.push(e),
|
||||
Ok(Some(e)) => v.push(e),
|
||||
Ok(None) => warn!("Entry not found: {:?}", v),
|
||||
}
|
||||
}
|
||||
v
|
||||
})
|
||||
}
|
||||
|
||||
fn get_entry_by_name<'a>(rt: &'a Runtime, name: &str) -> Result<FileLockEntry<'a>, StoreError> {
|
||||
use libimagstore::storeid::build_entry_path;
|
||||
build_entry_path(rt.store(), name)
|
||||
.and_then(|path| rt.store().retrieve(path))
|
||||
fn get_entry_by_name<'a>(rt: &'a Runtime, name: &str) -> Result<Option<FileLockEntry<'a>>, StoreError> {
|
||||
use std::path::PathBuf;
|
||||
use libimagstore::storeid::StoreId;
|
||||
|
||||
StoreId::new(Some(rt.store().path().clone()), PathBuf::from(name))
|
||||
.and_then(|id| rt.store().get(id))
|
||||
}
|
||||
|
||||
fn handle_external_linking(rt: &Runtime) {
|
||||
|
@ -186,6 +206,11 @@ fn handle_external_linking(rt: &Runtime) {
|
|||
if entry.is_err() {
|
||||
trace_error_exit(&entry.unwrap_err(), 1);
|
||||
}
|
||||
let entry = entry.unwrap();
|
||||
if entry.is_none() {
|
||||
warn!("Entry not found: {:?}", entry_name);
|
||||
return;
|
||||
}
|
||||
let mut entry = entry.unwrap();
|
||||
|
||||
if scmd.is_present("add") {
|
||||
|
|
|
@ -13,8 +13,9 @@ use clap::ArgMatches;
|
|||
use libimagrt::runtime::Runtime;
|
||||
use libimagstore::store::Entry;
|
||||
use libimagstore::store::EntryHeader;
|
||||
use libimagstore::storeid::build_entry_path;
|
||||
use libimagstore::storeid::StoreId;
|
||||
use libimagerror::trace::trace_error_exit;
|
||||
use libimagutil::debug_result::*;
|
||||
|
||||
use error::StoreError;
|
||||
use error::StoreErrorKind;
|
||||
|
@ -36,13 +37,15 @@ pub fn create(rt: &Runtime) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
let path = match build_entry_path(rt.store(), path.unwrap()) {
|
||||
let store_path = rt.store().path().clone();
|
||||
let path = match StoreId::new(Some(store_path), PathBuf::from(path.unwrap())) {
|
||||
Err(e) => trace_error_exit(&e, 1),
|
||||
Ok(p) => p,
|
||||
Ok(o) => o,
|
||||
};
|
||||
debug!("path = {:?}", path);
|
||||
|
||||
if scmd.subcommand_matches("entry").is_some() {
|
||||
debug!("Creating entry from CLI specification");
|
||||
create_from_cli_spec(rt, scmd, &path)
|
||||
.or_else(|_| create_from_source(rt, scmd, &path))
|
||||
.or_else(|_| create_with_content_and_header(rt,
|
||||
|
@ -50,13 +53,17 @@ pub fn create(rt: &Runtime) {
|
|||
String::new(),
|
||||
EntryHeader::new()))
|
||||
} else {
|
||||
debug!("Creating entry");
|
||||
create_with_content_and_header(rt, &path, String::new(), EntryHeader::new())
|
||||
}
|
||||
.unwrap_or_else(|e| debug!("Error building Entry: {:?}", e))
|
||||
.unwrap_or_else(|e| {
|
||||
error!("Error building Entry");
|
||||
trace_error_exit(&e, 1);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn create_from_cli_spec(rt: &Runtime, matches: &ArgMatches, path: &PathBuf) -> Result<()> {
|
||||
fn create_from_cli_spec(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> Result<()> {
|
||||
let content = matches.subcommand_matches("entry")
|
||||
.map_or_else(|| {
|
||||
debug!("Didn't find entry subcommand, getting raw content");
|
||||
|
@ -80,7 +87,7 @@ fn create_from_cli_spec(rt: &Runtime, matches: &ArgMatches, path: &PathBuf) -> R
|
|||
create_with_content_and_header(rt, path, content, header)
|
||||
}
|
||||
|
||||
fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &PathBuf) -> Result<()> {
|
||||
fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> Result<()> {
|
||||
let content = matches
|
||||
.value_of("from-raw")
|
||||
.ok_or(StoreError::new(StoreErrorKind::NoCommandlineCall, None))
|
||||
|
@ -93,9 +100,11 @@ fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &PathBuf) -> Res
|
|||
debug!("Content with len = {}", content.len());
|
||||
|
||||
Entry::from_str(path.clone(), &content[..])
|
||||
.map_dbg_err(|e| format!("Error building entry: {:?}", e))
|
||||
.and_then(|new_e| {
|
||||
let r = rt.store()
|
||||
.create(path.clone())
|
||||
.map_dbg_err(|e| format!("Error in Store::create(): {:?}", e))
|
||||
.map(|mut old_e| {
|
||||
*old_e.deref_mut() = new_e;
|
||||
});
|
||||
|
@ -103,17 +112,19 @@ fn create_from_source(rt: &Runtime, matches: &ArgMatches, path: &PathBuf) -> Res
|
|||
debug!("Entry build");
|
||||
r
|
||||
})
|
||||
.map_dbg_err(|e| format!("Error storing entry: {:?}", e))
|
||||
.map_err(|serr| StoreError::new(StoreErrorKind::BackendError, Some(Box::new(serr))))
|
||||
}
|
||||
|
||||
fn create_with_content_and_header(rt: &Runtime,
|
||||
path: &PathBuf,
|
||||
path: &StoreId,
|
||||
content: String,
|
||||
header: EntryHeader) -> Result<()>
|
||||
{
|
||||
debug!("Creating entry with content");
|
||||
debug!("Creating entry with content at {:?}", path);
|
||||
rt.store()
|
||||
.create(PathBuf::from(path))
|
||||
.create(path.clone())
|
||||
.map_dbg_err(|e| format!("Error in Store::create(): {:?}", e))
|
||||
.map(|mut element| {
|
||||
{
|
||||
let mut e_content = element.get_content_mut();
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use libimagstore::storeid::build_entry_path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use libimagrt::runtime::Runtime;
|
||||
use libimagerror::trace::trace_error_exit;
|
||||
use libimagstore::storeid::StoreId;
|
||||
|
||||
pub fn delete(rt: &Runtime) {
|
||||
use std::process::exit;
|
||||
|
@ -10,7 +12,8 @@ pub fn delete(rt: &Runtime) {
|
|||
.map(|sub| {
|
||||
sub.value_of("id")
|
||||
.map(|id| {
|
||||
let path = try!(build_entry_path(rt.store(), id)
|
||||
let path = PathBuf::from(id);
|
||||
let path = try!(StoreId::new(Some(rt.store().path().clone()), path)
|
||||
.map_err(|e| trace_error_exit(&e, 1)));
|
||||
debug!("Deleting file at {:?}", id);
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use libimagstore::storeid::build_entry_path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use libimagrt::runtime::Runtime;
|
||||
use libimagerror::trace::{trace_error, trace_error_exit};
|
||||
use libimagstore::storeid::StoreId;
|
||||
|
||||
use retrieve::print_entry;
|
||||
|
||||
|
@ -10,7 +12,8 @@ pub fn get(rt: &Runtime) {
|
|||
.map(|scmd| {
|
||||
scmd.value_of("id")
|
||||
.map(|id| {
|
||||
let path = match build_entry_path(rt.store(), id) {
|
||||
let path = PathBuf::from(id);
|
||||
let path = match StoreId::new(Some(rt.store().path().clone()), path) {
|
||||
Err(e) => trace_error_exit(&e, 1),
|
||||
Ok(p) => p,
|
||||
};
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use toml::Value;
|
||||
|
||||
use libimagstore::store::FileLockEntry;
|
||||
use libimagstore::storeid::build_entry_path;
|
||||
use libimagstore::storeid::StoreId;
|
||||
use libimagrt::runtime::Runtime;
|
||||
use libimagerror::trace::{trace_error, trace_error_exit};
|
||||
|
||||
|
@ -12,7 +14,8 @@ pub fn retrieve(rt: &Runtime) {
|
|||
.map(|scmd| {
|
||||
scmd.value_of("id")
|
||||
.map(|id| {
|
||||
let path = try!(build_entry_path(rt.store(), id)
|
||||
let path = PathBuf::from(id);
|
||||
let path = try!(StoreId::new(Some(rt.store().path().clone()), path)
|
||||
.map_err(|e| trace_error_exit(&e, 1)));
|
||||
debug!("path = {:?}", path);
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use std::ops::DerefMut;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use libimagrt::runtime::Runtime;
|
||||
use libimagstore::storeid::build_entry_path;
|
||||
use libimagerror::trace::trace_error_exit;
|
||||
use libimagstore::storeid::StoreId;
|
||||
|
||||
use util::build_toml_header;
|
||||
|
||||
|
@ -12,7 +13,8 @@ pub fn update(rt: &Runtime) {
|
|||
.map(|scmd| {
|
||||
scmd.value_of("id")
|
||||
.map(|id| {
|
||||
let path = match build_entry_path(rt.store(), id) {
|
||||
let path = PathBuf::from(id);
|
||||
let path = match StoreId::new(Some(rt.store().path().clone()), path) {
|
||||
Err(e) => trace_error_exit(&e, 1),
|
||||
Ok(p) => p,
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ source $(dirname ${BASH_SOURCE[0]})/../../tests/utils.sh
|
|||
source $(dirname ${BASH_SOURCE[0]})/utils.sh
|
||||
|
||||
test_call() {
|
||||
imag-store create -p /test-call~0.2.0
|
||||
imag-store create -p test-call
|
||||
if [[ ! $? -eq 0 ]]; then
|
||||
err "Return value should be zero, was non-zero"
|
||||
return 1;
|
||||
|
@ -12,7 +12,7 @@ test_call() {
|
|||
}
|
||||
|
||||
test_call_id() {
|
||||
imag-store create -i /test-call~0.2.0
|
||||
imag-store create -i test-call
|
||||
if [[ ! $? -eq 0 ]]; then
|
||||
err "Return value should be zero, was non-zero"
|
||||
return 1;
|
||||
|
@ -28,7 +28,7 @@ test_call_no_id() {
|
|||
}
|
||||
|
||||
test_mkstore() {
|
||||
imag-store create -p /test-mkstore~0.2.0 || { err "Calling imag failed"; return 1; }
|
||||
imag-store create -p test-mkstore || { err "Calling imag failed"; return 1; }
|
||||
if [[ -d ${STORE} ]]; then
|
||||
out "Store exists."
|
||||
else
|
||||
|
@ -48,12 +48,12 @@ version = "0.2.0"
|
|||
EOS
|
||||
)
|
||||
|
||||
imag-store create -p /test-std-header~0.2.0
|
||||
local result=$(cat ${STORE}/test-std-header~0.2.0)
|
||||
imag-store create -p test-std-header
|
||||
local result=$(cat ${STORE}/test-std-header)
|
||||
if [[ "$expected" == "$result" ]]; then
|
||||
out "Expected store entry == result"
|
||||
else
|
||||
err "${STORE}/test-std-header~0.2.0 differs from expected"
|
||||
err "${STORE}/test-std-header differs from expected"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
@ -72,8 +72,8 @@ zzz = "z"
|
|||
EOS
|
||||
)
|
||||
|
||||
imag-store create -p /test-std-header-plus-custom~0.2.0 entry -h zzz.zzz=z
|
||||
local result=$(cat ${STORE}/test-std-header-plus-custom~0.2.0)
|
||||
imag-store create -p test-std-header-plus-custom entry -h zzz.zzz=z
|
||||
local result=$(cat ${STORE}/test-std-header-plus-custom)
|
||||
if [[ "$expected" == "$result" ]]; then
|
||||
out "Expected store entry == result"
|
||||
else
|
||||
|
@ -99,8 +99,8 @@ zzz = "z"
|
|||
EOS
|
||||
)
|
||||
|
||||
local filename="test-std-header-plus-custom-multiheader~0.2.0"
|
||||
imag-store create -p /$filename entry -h zzz.zzz=z foo.bar=baz
|
||||
local filename="test-std-header-plus-custom-multiheader"
|
||||
imag-store create -p $filename entry -h zzz.zzz=z foo.bar=baz
|
||||
local result=$(cat ${STORE}/$filename)
|
||||
if [[ "$expected" == "$result" ]]; then
|
||||
out "Expected store entry == result"
|
||||
|
@ -126,8 +126,8 @@ zzz = "z"
|
|||
EOS
|
||||
)
|
||||
|
||||
local filename="test-std-header-plus-custom-mutliheader-same-section~0.2.0"
|
||||
imag-store create -p /$filename entry -h zzz.zzz=z zzz.bar=baz
|
||||
local filename="test-std-header-plus-custom-mutliheader-same-section"
|
||||
imag-store create -p $filename entry -h zzz.zzz=z zzz.bar=baz
|
||||
local result=$(cat ${STORE}/$filename)
|
||||
if [[ "$expected" == "$result" ]]; then
|
||||
out "Expected store entry == result"
|
||||
|
@ -151,8 +151,8 @@ content
|
|||
EOS
|
||||
)
|
||||
|
||||
local name="test-std-header-plus-custom-and-content~0.2.0"
|
||||
imag-store create -p /$name entry -h zzz.zzz=z -c content
|
||||
local name="test-std-header-plus-custom-and-content"
|
||||
imag-store create -p $name entry -h zzz.zzz=z -c content
|
||||
local result=$(cat ${STORE}/$name)
|
||||
if [[ "$expected" == "$result" ]]; then
|
||||
out "Expected store entry == result"
|
||||
|
|
|
@ -18,9 +18,9 @@ retrieve() {
|
|||
}
|
||||
|
||||
test_retrieve_nothing() {
|
||||
local id="test-retrieve_nothing~0.2.0"
|
||||
local id="test-retrieve_nothing"
|
||||
|
||||
imag-store create -p /${id} || { err "create failed"; return 1; }
|
||||
imag-store create -p ${id} || { err "create failed"; return 1; }
|
||||
|
||||
out "Going to test the retrieve functionality now"
|
||||
local zero_out="$(retrieve --id /${id})"
|
||||
|
@ -33,9 +33,9 @@ test_retrieve_nothing() {
|
|||
}
|
||||
|
||||
test_retrieve_content() {
|
||||
local id="test-retrieve_simple~0.2.0"
|
||||
local id="test-retrieve_simple"
|
||||
|
||||
imag-store create -p /${id} || { err "create failed"; return 1; }
|
||||
imag-store create -p ${id} || { err "create failed"; return 1; }
|
||||
|
||||
out "Going to test the retrieve functionality now"
|
||||
|
||||
|
@ -49,12 +49,12 @@ test_retrieve_content() {
|
|||
}
|
||||
|
||||
test_retrieve_header() {
|
||||
local id="test-retrieve_simple~0.2.0"
|
||||
local id="test-retrieve_simple"
|
||||
|
||||
imag-store create -p /${id} || { err "create failed"; return 1; }
|
||||
imag-store create -p ${id} || { err "create failed"; return 1; }
|
||||
|
||||
out "Going to test the retrieve functionality now"
|
||||
local header_out="$(retrieve --id /${id} --header)"
|
||||
local header_out="$(retrieve --id ${id} --header)"
|
||||
out "Retrieving for header_out finished"
|
||||
|
||||
if [[ ! "$header_out" != "$(std_header)" ]]; then
|
||||
|
@ -64,12 +64,12 @@ test_retrieve_header() {
|
|||
}
|
||||
|
||||
test_retrieve_raw() {
|
||||
local id="test-retrieve_simple~0.2.0"
|
||||
local id="test-retrieve_simple"
|
||||
|
||||
imag-store create -p /${id} || { err "create failed"; return 1; }
|
||||
imag-store create -p ${id} || { err "create failed"; return 1; }
|
||||
|
||||
out "Going to test the retrieve functionality now"
|
||||
local both_out="$(retrieve --id /${id} --raw)"
|
||||
local both_out="$(retrieve --id ${id} --raw)"
|
||||
out "Retrieving for both_out finished"
|
||||
|
||||
if [[ "$both_out" != "$(std_header)" ]]; then
|
||||
|
|
|
@ -12,10 +12,10 @@ delete() {
|
|||
}
|
||||
|
||||
test_delete_simple() {
|
||||
local name="test~0.2.0"
|
||||
local name="test"
|
||||
|
||||
create -p /$name
|
||||
delete --id /$name
|
||||
create -p $name
|
||||
delete --id $name
|
||||
|
||||
local n=$($(find ${STORE}/ -type f | wc -l))
|
||||
if [[ $n -eq 0 ]]; then
|
||||
|
|
|
@ -10,14 +10,15 @@ extern crate libimagentrytag;
|
|||
extern crate libimagerror;
|
||||
|
||||
use std::process::exit;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use libimagrt::runtime::Runtime;
|
||||
use libimagrt::setup::generate_runtime_setup;
|
||||
use libimagentrytag::tagable::Tagable;
|
||||
use libimagentrytag::tag::Tag;
|
||||
use libimagstore::storeid::build_entry_path;
|
||||
use libimagerror::trace::{trace_error, trace_error_exit};
|
||||
use libimagentrytag::ui::{get_add_tags, get_remove_tags};
|
||||
use libimagstore::storeid::StoreId;
|
||||
|
||||
mod ui;
|
||||
|
||||
|
@ -34,11 +35,13 @@ fn main() {
|
|||
.subcommand_name()
|
||||
.map_or_else(
|
||||
|| {
|
||||
let id = PathBuf::from(id);
|
||||
let add = get_add_tags(rt.cli());
|
||||
let rem = get_remove_tags(rt.cli());
|
||||
alter(&rt, id, add, rem);
|
||||
},
|
||||
|name| {
|
||||
let id = PathBuf::from(id);
|
||||
debug!("Call: {}", name);
|
||||
match name {
|
||||
"list" => list(id, &rt),
|
||||
|
@ -50,9 +53,9 @@ fn main() {
|
|||
});
|
||||
}
|
||||
|
||||
fn alter(rt: &Runtime, id: &str, add: Option<Vec<Tag>>, rem: Option<Vec<Tag>>) {
|
||||
fn alter(rt: &Runtime, id: PathBuf, add: Option<Vec<Tag>>, rem: Option<Vec<Tag>>) {
|
||||
let path = {
|
||||
match build_entry_path(rt.store(), id) {
|
||||
match StoreId::new(Some(rt.store().path().clone()), id) {
|
||||
Err(e) => trace_error_exit(&e, 1),
|
||||
Ok(s) => s,
|
||||
}
|
||||
|
@ -91,12 +94,10 @@ fn alter(rt: &Runtime, id: &str, add: Option<Vec<Tag>>, rem: Option<Vec<Tag>>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn list(id: &str, rt: &Runtime) {
|
||||
let path = {
|
||||
match build_entry_path(rt.store(), id) {
|
||||
fn list(id: PathBuf, rt: &Runtime) {
|
||||
let path = match StoreId::new(Some(rt.store().path().clone()), id) {
|
||||
Err(e) => trace_error_exit(&e, 1),
|
||||
Ok(s) => s,
|
||||
}
|
||||
};
|
||||
debug!("path = {:?}", path);
|
||||
|
||||
|
@ -108,8 +109,7 @@ fn list(id: &str, rt: &Runtime) {
|
|||
},
|
||||
|
||||
Err(e) => {
|
||||
debug!("Could not get '{:?}' => {:?}", id, path);
|
||||
warn!("Could not get entry '{}'", id);
|
||||
warn!("Could not get entry '{:?}'", path);
|
||||
trace_error_exit(&e, 1);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -30,7 +30,6 @@ use std::path::PathBuf;
|
|||
use libimagrt::setup::generate_runtime_setup;
|
||||
use libimagerror::trace::trace_error_exit;
|
||||
use libimagentryview::builtin::stdout::StdoutViewer;
|
||||
use libimagentryview::builtin::versions::VersionsViewer;
|
||||
use libimagentryview::viewer::Viewer;
|
||||
|
||||
mod ui;
|
||||
|
@ -68,9 +67,7 @@ fn main() {
|
|||
}
|
||||
};
|
||||
|
||||
let res = if rt.cli().is_present("versions") {
|
||||
VersionsViewer::new(rt.store()).view_entry(&entry)
|
||||
} else {
|
||||
let res = {
|
||||
if scmd.is_present("view-in-stdout") {
|
||||
} else if scmd.is_present("view-in-ui") {
|
||||
warn!("Viewing in UI is currently not supported, switch to stdout");
|
||||
|
|
|
@ -10,12 +10,6 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
|
|||
.help("View this entry at this store path")
|
||||
.value_name("ID"))
|
||||
|
||||
.arg(Arg::with_name("versions")
|
||||
.long("versions")
|
||||
.takes_value(false)
|
||||
.required(false)
|
||||
.help("Only print available versions for this file"))
|
||||
|
||||
.arg(Arg::with_name("view-header")
|
||||
.long("header")
|
||||
.short("h")
|
||||
|
|
|
@ -51,8 +51,9 @@ impl<'a> DerefMut for BookmarkCollection<'a> {
|
|||
impl<'a> BookmarkCollection<'a> {
|
||||
|
||||
pub fn new(store: &'a Store, name: &str) -> Result<BookmarkCollection<'a>> {
|
||||
let id = ModuleEntryPath::new(name).into_storeid();
|
||||
store.create(id)
|
||||
ModuleEntryPath::new(name)
|
||||
.into_storeid()
|
||||
.and_then(|id| store.create(id))
|
||||
.map(|fle| {
|
||||
BookmarkCollection {
|
||||
fle: fle,
|
||||
|
@ -63,8 +64,9 @@ impl<'a> BookmarkCollection<'a> {
|
|||
}
|
||||
|
||||
pub fn get(store: &'a Store, name: &str) -> Result<BookmarkCollection<'a>> {
|
||||
let id = ModuleEntryPath::new(name).into_storeid();
|
||||
store.get(id)
|
||||
ModuleEntryPath::new(name)
|
||||
.into_storeid()
|
||||
.and_then(|id| store.get(id))
|
||||
.map_err_into(BEK::StoreReadError)
|
||||
.and_then(|fle| {
|
||||
match fle {
|
||||
|
@ -78,7 +80,10 @@ impl<'a> BookmarkCollection<'a> {
|
|||
}
|
||||
|
||||
pub fn delete(store: &Store, name: &str) -> Result<()> {
|
||||
store.delete(ModuleEntryPath::new(name).into_storeid()).map_err_into(BEK::StoreReadError)
|
||||
ModuleEntryPath::new(name)
|
||||
.into_storeid()
|
||||
.and_then(|id| store.delete(id))
|
||||
.map_err_into(BEK::StoreReadError)
|
||||
}
|
||||
|
||||
pub fn links(&self) -> Result<Vec<Url>> {
|
||||
|
|
|
@ -21,7 +21,7 @@ extern crate regex;
|
|||
#[macro_use] extern crate libimagerror;
|
||||
extern crate libimagentrylink;
|
||||
|
||||
module_entry_path_mod!("bookmark", "0.1.0");
|
||||
module_entry_path_mod!("bookmark");
|
||||
|
||||
pub mod collection;
|
||||
pub mod error;
|
||||
|
|
|
@ -48,8 +48,10 @@ impl<'a> Counter<'a> {
|
|||
|
||||
debug!("Creating new counter: '{}' with value: {}", name, init);
|
||||
let fle = {
|
||||
let mut lockentry = try!(store.create(ModuleEntryPath::new(name.clone()).into_storeid())
|
||||
let id = try!(ModuleEntryPath::new(name.clone())
|
||||
.into_storeid()
|
||||
.map_err_into(CEK::StoreWriteError));
|
||||
let mut lockentry = try!(store.create(id).map_err_into(CEK::StoreWriteError));
|
||||
|
||||
{
|
||||
let mut entry = lockentry.deref_mut();
|
||||
|
@ -161,14 +163,18 @@ impl<'a> Counter<'a> {
|
|||
|
||||
pub fn load(name: CounterName, store: &Store) -> Result<Counter> {
|
||||
debug!("Loading counter: '{}'", name);
|
||||
let id = ModuleEntryPath::new(name).into_storeid();
|
||||
let id = try!(ModuleEntryPath::new(name)
|
||||
.into_storeid()
|
||||
.map_err_into(CEK::StoreWriteError));
|
||||
Counter::from_storeid(store, id)
|
||||
}
|
||||
|
||||
pub fn delete(name: CounterName, store: &Store) -> Result<()> {
|
||||
debug!("Deleting counter: '{}'", name);
|
||||
store.delete(ModuleEntryPath::new(name).into_storeid())
|
||||
.map_err_into(CEK::StoreWriteError)
|
||||
let id = try!(ModuleEntryPath::new(name)
|
||||
.into_storeid()
|
||||
.map_err_into(CEK::StoreWriteError));
|
||||
store.delete(id).map_err_into(CEK::StoreWriteError)
|
||||
}
|
||||
|
||||
pub fn all_counters(store: &Store) -> Result<CounterIterator> {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
generate_error_module!(
|
||||
generate_error_types!(CounterError, CounterErrorKind,
|
||||
StoreIdError => "StoreId error",
|
||||
StoreReadError => "Store read error",
|
||||
StoreWriteError => "Store write error",
|
||||
HeaderTypeError => "Header type error",
|
||||
|
|
|
@ -19,7 +19,7 @@ extern crate toml;
|
|||
#[macro_use] extern crate libimagstore;
|
||||
#[macro_use] extern crate libimagerror;
|
||||
|
||||
module_entry_path_mod!("counter", "0.2.0");
|
||||
module_entry_path_mod!("counter");
|
||||
|
||||
pub mod counter;
|
||||
pub mod error;
|
||||
|
|
|
@ -45,8 +45,8 @@ impl<'a> Diary<'a> {
|
|||
}
|
||||
|
||||
pub fn retrieve(&self, id: DiaryId) -> Result<Entry> {
|
||||
self.store
|
||||
.retrieve(id.into_storeid())
|
||||
id.into_storeid()
|
||||
.and_then(|id| self.store.retrieve(id))
|
||||
.map(|fle| Entry::new(fle))
|
||||
.map_err(|e| DE::new(DEK::StoreWriteError, Some(Box::new(e))))
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use chrono::Timelike;
|
|||
|
||||
use libimagstore::storeid::StoreId;
|
||||
use libimagstore::storeid::IntoStoreId;
|
||||
use libimagstore::store::Result as StoreResult;
|
||||
|
||||
use module_path::ModuleEntryPath;
|
||||
|
||||
|
@ -118,7 +119,7 @@ impl Default for DiaryId {
|
|||
|
||||
impl IntoStoreId for DiaryId {
|
||||
|
||||
fn into_storeid(self) -> StoreId {
|
||||
fn into_storeid(self) -> StoreResult<StoreId> {
|
||||
let s : String = self.into();
|
||||
ModuleEntryPath::new(s).into_storeid()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use libimagstore::store::Entry;
|
||||
use libimagstore::storeid::StoreId;
|
||||
|
||||
pub trait IsInDiary {
|
||||
|
||||
|
@ -11,15 +10,15 @@ pub trait IsInDiary {
|
|||
impl IsInDiary for Entry {
|
||||
|
||||
fn is_in_diary(&self, name: &str) -> bool {
|
||||
self.get_location().is_in_diary(name)
|
||||
self.get_location().clone().is_in_diary(name)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl IsInDiary for PathBuf {
|
||||
impl IsInDiary for StoreId {
|
||||
|
||||
fn is_in_diary(&self, name: &str) -> bool {
|
||||
self.to_str().map(|s| s.contains(name)).unwrap_or(false)
|
||||
self.local().starts_with(format!("diary/{}", name))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ extern crate itertools;
|
|||
extern crate libimagentryedit;
|
||||
extern crate libimagrt;
|
||||
|
||||
module_entry_path_mod!("diary", "0.2.0");
|
||||
module_entry_path_mod!("diary");
|
||||
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
|
|
|
@ -7,7 +7,8 @@ generate_error_module!(
|
|||
InternalConversionError => "Error while converting values internally",
|
||||
InvalidUri => "URI is not valid",
|
||||
StoreReadError => "Store read error",
|
||||
StoreWriteError => "Store write error"
|
||||
StoreWriteError => "Store write error",
|
||||
StoreIdError => "StoreId handling error"
|
||||
);
|
||||
);
|
||||
|
||||
|
|
|
@ -91,8 +91,8 @@ pub trait ExternalLinker : InternalLinker {
|
|||
|
||||
/// Check whether the StoreId starts with `/link/external/`
|
||||
pub fn is_external_link_storeid(id: &StoreId) -> bool {
|
||||
debug!("Checking whether this is a /link/external/*: '{:?}'", id);
|
||||
id.parent().map(|par| par.ends_with("/link/external")).unwrap_or(false)
|
||||
debug!("Checking whether this is a link/external/*: '{:?}'", id);
|
||||
id.local().starts_with("link/external")
|
||||
}
|
||||
|
||||
fn get_external_link_from_file(entry: &FileLockEntry) -> Result<Url> {
|
||||
|
@ -144,7 +144,13 @@ impl ExternalLinker for Entry {
|
|||
s.input_str(&link.as_str()[..]);
|
||||
s.result_str()
|
||||
};
|
||||
let file_id = ModuleEntryPath::new(format!("external/{}", hash)).into_storeid();
|
||||
let file_id = try!(
|
||||
ModuleEntryPath::new(format!("external/{}", hash)).into_storeid()
|
||||
.map_err_into(LEK::StoreWriteError)
|
||||
.map_dbg_err(|_| {
|
||||
format!("Failed to build StoreId for this hash '{:?}'", hash)
|
||||
})
|
||||
);
|
||||
|
||||
debug!("Link = '{:?}'", link);
|
||||
debug!("Hash = '{:?}'", hash);
|
||||
|
|
|
@ -7,6 +7,7 @@ use libimagstore::store::Result as StoreResult;
|
|||
use libimagerror::into::IntoError;
|
||||
|
||||
use error::LinkErrorKind as LEK;
|
||||
use error::MapErrInto;
|
||||
use result::Result;
|
||||
|
||||
use toml::Value;
|
||||
|
@ -53,13 +54,11 @@ impl InternalLinker for Entry {
|
|||
.into_iter()
|
||||
.fold(Ok(vec![]), |acc, elem| {
|
||||
acc.and_then(move |mut v| {
|
||||
match elem {
|
||||
None => Err(LEK::InternalConversionError.into()),
|
||||
Some(e) => {
|
||||
elem.map_err_into(LEK::InternalConversionError)
|
||||
.map(|e| {
|
||||
v.push(e);
|
||||
Ok(v)
|
||||
},
|
||||
}
|
||||
v
|
||||
})
|
||||
})
|
||||
}));
|
||||
process_rw_result(self.get_header_mut().set("imag.links", Value::Array(new_links)))
|
||||
|
@ -98,16 +97,16 @@ impl InternalLinker for Entry {
|
|||
|
||||
}
|
||||
|
||||
fn links_into_values(links: Vec<StoreId>) -> Vec<Option<Value>> {
|
||||
fn links_into_values(links: Vec<StoreId>) -> Vec<Result<Value>> {
|
||||
links
|
||||
.into_iter()
|
||||
.map(|s| s.to_str().map(String::from))
|
||||
.unique()
|
||||
.map(|s| s.without_base().to_str().map_err_into(LEK::InternalConversionError))
|
||||
.map(|elem| elem.map(Value::String))
|
||||
.sorted_by(|a, b| {
|
||||
match (a, b) {
|
||||
(&Some(Value::String(ref a)), &Some(Value::String(ref b))) => Ord::cmp(a, b),
|
||||
(&None, _) | (_, &None) => Ordering::Equal,
|
||||
(&Ok(Value::String(ref a)), &Ok(Value::String(ref b))) => Ord::cmp(a, b),
|
||||
(&Err(_), _) | (_, &Err(_)) => Ordering::Equal,
|
||||
_ => unreachable!()
|
||||
}
|
||||
})
|
||||
|
@ -118,13 +117,11 @@ fn rewrite_links(header: &mut EntryHeader, links: Vec<StoreId>) -> Result<()> {
|
|||
.into_iter()
|
||||
.fold(Ok(vec![]), |acc, elem| {
|
||||
acc.and_then(move |mut v| {
|
||||
match elem {
|
||||
None => Err(LEK::InternalConversionError.into()),
|
||||
Some(e) => {
|
||||
elem.map_err_into(LEK::InternalConversionError)
|
||||
.map(|e| {
|
||||
v.push(e);
|
||||
Ok(v)
|
||||
},
|
||||
}
|
||||
v
|
||||
})
|
||||
})
|
||||
}));
|
||||
|
||||
|
@ -142,13 +139,11 @@ fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> {
|
|||
.into_iter()
|
||||
.fold(Ok(vec![]), |acc, elem| {
|
||||
acc.and_then(move |mut v| {
|
||||
match elem {
|
||||
None => Err(LEK::InternalConversionError.into()),
|
||||
Some(e) => {
|
||||
elem.map_err_into(LEK::InternalConversionError)
|
||||
.map(|e| {
|
||||
v.push(e);
|
||||
Ok(v)
|
||||
},
|
||||
}
|
||||
v
|
||||
})
|
||||
})
|
||||
}));
|
||||
process_rw_result(target.get_header_mut().set("imag.links", Value::Array(links)))
|
||||
|
@ -157,6 +152,8 @@ fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> {
|
|||
}
|
||||
|
||||
fn process_rw_result(links: StoreResult<Option<Value>>) -> Result<Vec<Link>> {
|
||||
use std::path::PathBuf;
|
||||
|
||||
let links = match links {
|
||||
Err(e) => {
|
||||
debug!("RW action on store failed. Generating LinkError");
|
||||
|
@ -179,14 +176,15 @@ fn process_rw_result(links: StoreResult<Option<Value>>) -> Result<Vec<Link>> {
|
|||
return Err(LEK::ExistingLinkTypeWrong.into());
|
||||
}
|
||||
|
||||
let links : Vec<Link> = links.into_iter()
|
||||
let links : Vec<Link> = try!(links.into_iter()
|
||||
.map(|link| {
|
||||
match link {
|
||||
Value::String(s) => StoreId::from(s),
|
||||
Value::String(s) => StoreId::new_baseless(PathBuf::from(s))
|
||||
.map_err_into(LEK::StoreIdError),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
.collect());
|
||||
|
||||
debug!("Ok, the RW action was successful, returning link vector now!");
|
||||
Ok(links)
|
||||
|
|
|
@ -23,7 +23,7 @@ extern crate crypto;
|
|||
#[macro_use] extern crate libimagerror;
|
||||
#[macro_use] extern crate libimagutil;
|
||||
|
||||
module_entry_path_mod!("links", "0.2.0");
|
||||
module_entry_path_mod!("links");
|
||||
|
||||
pub mod error;
|
||||
pub mod external;
|
||||
|
|
|
@ -28,8 +28,8 @@ impl<'a> Lister for LineLister<'a> {
|
|||
use error::ListErrorKind as LEK;
|
||||
|
||||
entries.fold_defresult(|entry| {
|
||||
write!(stdout(), "{:?}\n", entry.get_location().to_str().unwrap_or(self.unknown_output))
|
||||
.map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e))))
|
||||
let s = entry.get_location().to_str().unwrap_or(String::from(self.unknown_output));
|
||||
write!(stdout(), "{:?}\n", s).map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e))))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -26,10 +26,12 @@ impl Lister for PathLister {
|
|||
fn list<'a, I: Iterator<Item = FileLockEntry<'a>>>(&self, entries: I) -> Result<()> {
|
||||
use error::ListError as LE;
|
||||
use error::ListErrorKind as LEK;
|
||||
use std::path::PathBuf;
|
||||
|
||||
entries.fold_defresult(|entry| {
|
||||
Ok(entry.get_location().clone())
|
||||
.and_then(|pb| {
|
||||
let pb : PathBuf = pb.into();
|
||||
if self.absolute {
|
||||
pb.canonicalize().map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e))))
|
||||
} else {
|
||||
|
|
13
libimagentryselect/src/error.rs
Normal file
13
libimagentryselect/src/error.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
generate_error_module!(
|
||||
generate_error_types!(EntrySelectError, EntrySelectErrorKind,
|
||||
CLIError => "Error on commandline",
|
||||
IdMissingError => "Commandline: ID missing",
|
||||
StoreIdParsingError => "Error while parsing StoreId",
|
||||
IdSelectingError => "Error while selecting id"
|
||||
);
|
||||
);
|
||||
|
||||
pub use self::error::EntrySelectError;
|
||||
pub use self::error::EntrySelectErrorKind;
|
||||
pub use self::error::MapErrInto;
|
||||
|
|
@ -17,7 +17,10 @@ extern crate log;
|
|||
extern crate interactor;
|
||||
|
||||
extern crate libimagstore;
|
||||
#[macro_use]
|
||||
extern crate libimagerror;
|
||||
|
||||
pub mod error;
|
||||
pub mod result;
|
||||
pub mod ui;
|
||||
|
||||
|
|
6
libimagentryselect/src/result.rs
Normal file
6
libimagentryselect/src/result.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
use std::result::Result as RResult;
|
||||
|
||||
use error::EntrySelectError;
|
||||
|
||||
pub type Result<T> = RResult<T, EntrySelectError>;
|
||||
|
|
@ -3,7 +3,11 @@ use std::path::PathBuf;
|
|||
use clap::{Arg, ArgMatches};
|
||||
|
||||
use libimagstore::storeid::StoreId;
|
||||
use libimagerror::trace::trace_error;
|
||||
use libimagerror::into::IntoError;
|
||||
|
||||
use result::Result;
|
||||
use error::MapErrInto;
|
||||
use error::EntrySelectErrorKind as ESEK;
|
||||
|
||||
pub fn id_argument<'a, 'b>() -> Arg<'a, 'b> {
|
||||
Arg::with_name(id_argument_name())
|
||||
|
@ -26,28 +30,35 @@ pub fn id_argument_long() -> &'static str {
|
|||
"id"
|
||||
}
|
||||
|
||||
pub fn get_id(matches: &ArgMatches) -> Option<Vec<StoreId>> {
|
||||
matches.values_of(id_argument_name())
|
||||
.map(|vals| {
|
||||
pub fn get_id(matches: &ArgMatches) -> Result<Vec<StoreId>> {
|
||||
matches
|
||||
.values_of(id_argument_name())
|
||||
.ok_or(ESEK::IdMissingError.into_error())
|
||||
.map_err_into(ESEK::CLIError)
|
||||
.and_then(|vals| {
|
||||
vals.into_iter()
|
||||
.map(String::from)
|
||||
.map(StoreId::from)
|
||||
.collect()
|
||||
.fold(Ok(vec![]), |acc, elem| {
|
||||
acc.and_then(|mut v| {
|
||||
let elem = StoreId::new_baseless(PathBuf::from(String::from(elem)));
|
||||
let elem = try!(elem.map_err_into(ESEK::StoreIdParsingError));
|
||||
v.push(elem);
|
||||
Ok(v)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_or_select_id(matches: &ArgMatches, store_path: &PathBuf) -> Option<Vec<StoreId>> {
|
||||
pub fn get_or_select_id(matches: &ArgMatches, store_path: &PathBuf) -> Result<Vec<StoreId>> {
|
||||
use interactor::{pick_file, default_menu_cmd};
|
||||
|
||||
get_id(matches).or_else(|| {
|
||||
match pick_file(default_menu_cmd, store_path.clone()) {
|
||||
Err(e) => {
|
||||
trace_error(&e);
|
||||
None
|
||||
match get_id(matches).map_err_into(ESEK::IdSelectingError) {
|
||||
Ok(v) => Ok(v),
|
||||
Err(_) => {
|
||||
let path = store_path.clone();
|
||||
let p = try!(pick_file(default_menu_cmd, path).map_err_into(ESEK::IdSelectingError));
|
||||
let id = try!(StoreId::new_baseless(p).map_err_into(ESEK::StoreIdParsingError));
|
||||
Ok(vec![id])
|
||||
},
|
||||
|
||||
Ok(p) => Some(vec![StoreId::from(p)]),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
pub mod editor;
|
||||
pub mod plain;
|
||||
pub mod stdout;
|
||||
pub mod versions;
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
use libimagstore::store::Entry;
|
||||
use libimagstore::store::Store;
|
||||
use libimagerror::into::IntoError;
|
||||
|
||||
use viewer::Viewer;
|
||||
use result::Result;
|
||||
use error::ViewErrorKind as VEK;
|
||||
|
||||
pub struct VersionsViewer<'a> {
|
||||
store: &'a Store,
|
||||
}
|
||||
|
||||
impl<'a> VersionsViewer<'a> {
|
||||
|
||||
pub fn new(store: &'a Store) -> VersionsViewer<'a> {
|
||||
VersionsViewer {
|
||||
store: store,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<'a> Viewer for VersionsViewer<'a> {
|
||||
|
||||
fn view_entry(&self, entr: &Entry) -> Result<()> {
|
||||
use glob::glob;
|
||||
|
||||
entr.get_location()
|
||||
.clone()
|
||||
.storified(self.store)
|
||||
.to_str()
|
||||
.and_then(|s| s.split("~").next())
|
||||
.map(|component| {
|
||||
glob(&format!("{}~*", component)[..])
|
||||
.map_err(|_| VEK::PatternError.into_error())
|
||||
.and_then(|paths| {
|
||||
for entry in paths {
|
||||
let p = match entry {
|
||||
Err(_) => return Err(VEK::GlobError.into_error()),
|
||||
Ok(p) => p,
|
||||
};
|
||||
let p = p.file_name()
|
||||
.and_then(|s| s.to_str())
|
||||
.unwrap(); // TODO
|
||||
println!("{}", p);
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
.unwrap_or(Err(VEK::PatternBuildingError.into_error()))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -9,4 +9,5 @@ generate_error_module!(
|
|||
|
||||
pub use self::error::NoteError;
|
||||
pub use self::error::NoteErrorKind;
|
||||
pub use self::error::MapErrInto;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ extern crate libimagrt;
|
|||
extern crate libimagentryedit;
|
||||
extern crate libimagentrytag;
|
||||
|
||||
module_entry_path_mod!("notes", "0.2.0");
|
||||
module_entry_path_mod!("notes");
|
||||
|
||||
pub mod error;
|
||||
pub mod note;
|
||||
|
|
|
@ -19,6 +19,7 @@ use module_path::ModuleEntryPath;
|
|||
use result::Result;
|
||||
use error::NoteError as NE;
|
||||
use error::NoteErrorKind as NEK;
|
||||
use error::MapErrInto;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Note<'a> {
|
||||
|
@ -32,11 +33,10 @@ impl<'a> Note<'a> {
|
|||
|
||||
debug!("Creating new Note: '{}'", name);
|
||||
let fle = {
|
||||
let lockentry = store.create(ModuleEntryPath::new(name.clone()).into_storeid());
|
||||
if lockentry.is_err() {
|
||||
return Err(NE::new(NEK::StoreWriteError, Some(Box::new(lockentry.unwrap_err()))));
|
||||
}
|
||||
let mut lockentry = lockentry.unwrap();
|
||||
let mut lockentry = try!(ModuleEntryPath::new(name.clone())
|
||||
.into_storeid()
|
||||
.and_then(|id| store.create(id))
|
||||
.map_err_into(NEK::StoreWriteError));
|
||||
|
||||
{
|
||||
let mut entry = lockentry.deref_mut();
|
||||
|
@ -93,24 +93,26 @@ impl<'a> Note<'a> {
|
|||
}
|
||||
|
||||
pub fn delete(store: &Store, name: String) -> Result<()> {
|
||||
store.delete(ModuleEntryPath::new(name).into_storeid())
|
||||
.map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
|
||||
ModuleEntryPath::new(name)
|
||||
.into_storeid()
|
||||
.and_then(|id| store.delete(id))
|
||||
.map_err_into(NEK::StoreWriteError)
|
||||
}
|
||||
|
||||
pub fn retrieve(store: &Store, name: String) -> Result<Note> {
|
||||
store.retrieve(ModuleEntryPath::new(name).into_storeid())
|
||||
.map_err(|e| NE::new(NEK::StoreWriteError, Some(Box::new(e))))
|
||||
ModuleEntryPath::new(name)
|
||||
.into_storeid()
|
||||
.and_then(|id| store.retrieve(id))
|
||||
.map_err_into(NEK::StoreWriteError)
|
||||
.map(|entry| Note { entry: entry })
|
||||
}
|
||||
|
||||
pub fn get(store: &Store, name: String) -> Result<Option<Note>> {
|
||||
use libimagerror::into::IntoError;
|
||||
|
||||
match store.get(ModuleEntryPath::new(name).into_storeid()) {
|
||||
Ok(Some(entry)) => Ok(Some(Note { entry: entry })),
|
||||
Ok(None) => Ok(None),
|
||||
Err(e) => Err(NEK::StoreWriteError.into_error_with_cause(Box::new(e))),
|
||||
}
|
||||
ModuleEntryPath::new(name)
|
||||
.into_storeid()
|
||||
.and_then(|id| store.get(id))
|
||||
.map_err_into(NEK::StoreWriteError)
|
||||
.map(|o| o.map(|entry| Note { entry: entry }))
|
||||
}
|
||||
|
||||
pub fn all_notes(store: &Store) -> Result<NoteIterator> {
|
||||
|
|
|
@ -25,7 +25,7 @@ extern crate walkdir;
|
|||
#[macro_use] extern crate libimagutil;
|
||||
extern crate libimagentrylist;
|
||||
|
||||
module_entry_path_mod!("ref", "0.2.0");
|
||||
module_entry_path_mod!("ref");
|
||||
|
||||
pub mod error;
|
||||
pub mod flags;
|
||||
|
|
|
@ -19,6 +19,7 @@ use libimagerror::into::IntoError;
|
|||
use toml::Value;
|
||||
|
||||
use error::RefErrorKind as REK;
|
||||
use error::MapErrInto;
|
||||
use flags::RefFlags;
|
||||
use result::Result;
|
||||
use hasher::*;
|
||||
|
@ -47,8 +48,9 @@ impl<'a> Ref<'a> {
|
|||
///
|
||||
/// Returns None if the hash cannot be found.
|
||||
pub fn get_by_hash(store: &'a Store, hash: String) -> Result<Option<Ref<'a>>> {
|
||||
store
|
||||
.get(ModuleEntryPath::new(hash).into_storeid())
|
||||
ModuleEntryPath::new(hash)
|
||||
.into_storeid()
|
||||
.and_then(|id| store.get(id))
|
||||
.map(|opt_fle| opt_fle.map(|fle| Ref(fle)))
|
||||
.map_err(Box::new)
|
||||
.map_err(|e| REK::StoreReadError.into_error_with_cause(e))
|
||||
|
@ -58,8 +60,9 @@ impl<'a> Ref<'a> {
|
|||
///
|
||||
/// If the returned Result contains an error, the ref might not be deleted.
|
||||
pub fn delete_by_hash(store: &'a Store, hash: String) -> Result<()> {
|
||||
store
|
||||
.delete(ModuleEntryPath::new(hash).into_storeid())
|
||||
ModuleEntryPath::new(hash)
|
||||
.into_storeid()
|
||||
.and_then(|id| store.delete(id))
|
||||
.map_err(Box::new)
|
||||
.map_err(|e| REK::StoreWriteError.into_error_with_cause(e))
|
||||
}
|
||||
|
@ -223,10 +226,8 @@ impl<'a> Ref<'a> {
|
|||
|
||||
/// Get the hash from the path of the ref
|
||||
pub fn get_path_hash(&self) -> Option<String> {
|
||||
self.0
|
||||
.get_location()
|
||||
.as_path()
|
||||
.file_name()
|
||||
let pb : PathBuf = self.0.get_location().clone().into();
|
||||
pb.file_name()
|
||||
.and_then(|osstr| osstr.to_str())
|
||||
.and_then(|s| s.split("~").next())
|
||||
.map(String::from)
|
||||
|
@ -398,13 +399,9 @@ impl<'a> Ref<'a> {
|
|||
// manually here. If you can come up with a better version of this, feel free to
|
||||
// take this note as a todo.
|
||||
for r in possible_refs {
|
||||
let contains_hash = match r.to_str() {
|
||||
None => { // couldn't parse StoreId -> PathBuf -> &str
|
||||
// TODO: How to report this?
|
||||
return Err(REK::TypeConversionError.into_error());
|
||||
},
|
||||
Some(s) => s.contains(&hash[..]),
|
||||
};
|
||||
let contains_hash = try!(r.to_str()
|
||||
.map_err_into(REK::TypeConversionError)
|
||||
.map(|s| s.contains(&hash[..])));
|
||||
|
||||
if !contains_hash {
|
||||
continue;
|
||||
|
|
|
@ -42,6 +42,7 @@ generate_custom_error_types!(StoreError, StoreErrorKind, CustomErrorData,
|
|||
StorePathError => "Store Path error",
|
||||
EntryRenameError => "Entry rename error",
|
||||
StoreIdHandlingError => "StoreId handling error",
|
||||
StoreIdLocalPartAbsoluteError => "StoreId 'id' part is absolute (starts with '/') which is not allowed",
|
||||
|
||||
CreateCallError => "Error when calling create()",
|
||||
RetrieveCallError => "Error when calling retrieve()",
|
||||
|
|
|
@ -36,6 +36,7 @@ use hook::position::HookPosition;
|
|||
use hook::Hook;
|
||||
|
||||
use libimagerror::into::IntoError;
|
||||
use libimagerror::trace::trace_error;
|
||||
use libimagutil::iter::FoldResult;
|
||||
|
||||
use self::glob_store_iter::*;
|
||||
|
@ -65,14 +66,17 @@ pub enum StoreObject {
|
|||
}
|
||||
|
||||
pub struct Walk {
|
||||
store_path: PathBuf,
|
||||
dirwalker: WalkDirIter,
|
||||
}
|
||||
|
||||
impl Walk {
|
||||
|
||||
fn new(mut store_path: PathBuf, mod_name: &str) -> Walk {
|
||||
let pb = store_path.clone();
|
||||
store_path.push(mod_name);
|
||||
Walk {
|
||||
store_path: pb,
|
||||
dirwalker: WalkDir::new(store_path).into_iter(),
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +99,15 @@ impl Iterator for Walk {
|
|||
Ok(next) => if next.file_type().is_dir() {
|
||||
return Some(StoreObject::Collection(next.path().to_path_buf()))
|
||||
} else if next.file_type().is_file() {
|
||||
return Some(StoreObject::Id(next.path().to_path_buf().into()))
|
||||
let n = next.path().to_path_buf();
|
||||
let sid = match StoreId::new(Some(self.store_path.clone()), n) {
|
||||
Err(e) => {
|
||||
trace_error(&e);
|
||||
continue;
|
||||
},
|
||||
Ok(o) => o,
|
||||
};
|
||||
return Some(StoreObject::Id(sid))
|
||||
},
|
||||
Err(e) => {
|
||||
warn!("Error in Walker");
|
||||
|
@ -376,7 +388,7 @@ impl Store {
|
|||
|
||||
/// Creates the Entry at the given location (inside the entry)
|
||||
pub fn create<'a, S: IntoStoreId>(&'a self, id: S) -> Result<FileLockEntry<'a>> {
|
||||
let id = id.into_storeid().storified(self);
|
||||
let id = try!(id.into_storeid()).with_base(self.path().clone());
|
||||
if let Err(e) = self.execute_hooks_for_id(self.pre_create_aspects.clone(), &id) {
|
||||
return Err(e)
|
||||
.map_err_into(SEK::PreHookExecuteError)
|
||||
|
@ -414,7 +426,7 @@ impl Store {
|
|||
/// Implicitely creates a entry in the store if there is no entry with the id `id`. For a
|
||||
/// non-implicitely-create look at `Store::get`.
|
||||
pub fn retrieve<'a, S: IntoStoreId>(&'a self, id: S) -> Result<FileLockEntry<'a>> {
|
||||
let id = id.into_storeid().storified(self);
|
||||
let id = try!(id.into_storeid()).with_base(self.path().clone());
|
||||
if let Err(e) = self.execute_hooks_for_id(self.pre_retrieve_aspects.clone(), &id) {
|
||||
return Err(e)
|
||||
.map_err_into(SEK::PreHookExecuteError)
|
||||
|
@ -447,57 +459,14 @@ impl Store {
|
|||
///
|
||||
/// This executes the {pre,post}_retrieve_aspects hooks.
|
||||
pub fn get<'a, S: IntoStoreId + Clone>(&'a self, id: S) -> Result<Option<FileLockEntry<'a>>> {
|
||||
if !id.clone().into_storeid().storified(self).exists() {
|
||||
debug!("Does not exist: {:?}", id.clone().into_storeid());
|
||||
let id_copy = try!(id.clone().into_storeid()).with_base(self.path().clone());
|
||||
if !id_copy.exists() {
|
||||
debug!("Does not exist: {:?}", id_copy);
|
||||
return Ok(None);
|
||||
}
|
||||
self.retrieve(id).map(Some).map_err_into(SEK::GetCallError)
|
||||
}
|
||||
|
||||
/// Same as `Store::get()` but also tries older versions of the entry, returning an iterator
|
||||
/// over all versions of the entry.
|
||||
pub fn get_all_versions<'a, S: IntoStoreId>(&'a self, id: S) -> Result<StoreIdIterator>
|
||||
{
|
||||
// get PathBuf component from storeid, but not version component
|
||||
fn path_component<S: IntoStoreId>(id: S) -> Result<PathBuf> {
|
||||
let p : PathBuf = id.into_storeid().into();
|
||||
match p.to_str() {
|
||||
Some(s) => {
|
||||
let mut split = s.split("~");
|
||||
let path_element = match split.next() {
|
||||
Some(s) => s,
|
||||
None => return Err(SE::new(SEK::StorePathError, None))
|
||||
.map_err_into(SEK::GetAllVersionsCallError),
|
||||
};
|
||||
|
||||
Ok(PathBuf::from(path_element))
|
||||
},
|
||||
|
||||
None => Err(SE::new(SEK::StorePathError, None))
|
||||
.map_err_into(SEK::GetAllVersionsCallError),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_glob_pattern(mut pb: PathBuf) -> Option<String> {
|
||||
pb.push("~*.*.*");
|
||||
pb.to_str().map(String::from)
|
||||
}
|
||||
|
||||
match path_component(id).map(build_glob_pattern) {
|
||||
Err(e) => Err(SEK::StorePathError.into_error_with_cause(Box::new(e)))
|
||||
.map_err_into(SEK::GetAllVersionsCallError),
|
||||
Ok(None) => Err(SE::new(SEK::StorePathError, None))
|
||||
.map_err_into(SEK::GetAllVersionsCallError),
|
||||
Ok(Some(pattern)) => {
|
||||
glob(&pattern[..])
|
||||
.map(|paths| GlobStoreIdIterator::new(paths).into())
|
||||
.map_err_into(SEK::GlobError)
|
||||
.map_err_into(SEK::GetAllVersionsCallError)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Iterate over all StoreIds for one module name
|
||||
pub fn retrieve_for_module(&self, mod_name: &str) -> Result<StoreIdIterator> {
|
||||
let mut path = self.path().clone();
|
||||
|
@ -510,7 +479,7 @@ impl Store {
|
|||
debug!("glob()ing with '{}'", path);
|
||||
glob(&path[..]).map_err_into(SEK::GlobError)
|
||||
})
|
||||
.map(|paths| GlobStoreIdIterator::new(paths).into())
|
||||
.map(|paths| GlobStoreIdIterator::new(paths, self.path().clone()).into())
|
||||
.map_err_into(SEK::GlobError)
|
||||
.map_err_into(SEK::RetrieveForModuleCallError)
|
||||
}
|
||||
|
@ -567,7 +536,7 @@ impl Store {
|
|||
/// Retrieve a copy of a given entry, this cannot be used to mutate
|
||||
/// the one on disk
|
||||
pub fn retrieve_copy<S: IntoStoreId>(&self, id: S) -> Result<Entry> {
|
||||
let id = id.into_storeid().storified(self);
|
||||
let id = try!(id.into_storeid()).with_base(self.path().clone());
|
||||
let entries = match self.entries.write() {
|
||||
Err(_) => {
|
||||
return Err(SE::new(SEK::LockPoisoned, None))
|
||||
|
@ -586,7 +555,7 @@ impl Store {
|
|||
|
||||
/// Delete an entry
|
||||
pub fn delete<S: IntoStoreId>(&self, id: S) -> Result<()> {
|
||||
let id = id.into_storeid().storified(self);
|
||||
let id = try!(id.into_storeid()).with_base(self.path().clone());
|
||||
if let Err(e) = self.execute_hooks_for_id(self.pre_delete_aspects.clone(), &id) {
|
||||
return Err(e)
|
||||
.map_err_into(SEK::PreHookExecuteError)
|
||||
|
@ -609,7 +578,7 @@ impl Store {
|
|||
|
||||
// remove the entry first, then the file
|
||||
entries.remove(&id);
|
||||
if let Err(e) = FileAbstraction::remove_file(&id) {
|
||||
if let Err(e) = FileAbstraction::remove_file(&id.clone().into()) {
|
||||
return Err(SEK::FileError.into_error_with_cause(Box::new(e)))
|
||||
.map_err_into(SEK::DeleteCallError);
|
||||
}
|
||||
|
@ -637,7 +606,7 @@ impl Store {
|
|||
fn save_to_other_location(&self, entry: &FileLockEntry, new_id: StoreId, remove_old: bool)
|
||||
-> Result<()>
|
||||
{
|
||||
let new_id = new_id.storified(self);
|
||||
let new_id = new_id.with_base(self.path().clone());
|
||||
let hsmap = self.entries.write();
|
||||
if hsmap.is_err() {
|
||||
return Err(SE::new(SEK::LockPoisoned, None)).map_err_into(SEK::MoveCallError)
|
||||
|
@ -666,8 +635,8 @@ impl Store {
|
|||
/// Move an entry without loading
|
||||
pub fn move_by_id(&self, old_id: StoreId, new_id: StoreId) -> Result<()> {
|
||||
|
||||
let new_id = new_id.storified(self);
|
||||
let old_id = old_id.storified(self);
|
||||
let new_id = new_id.with_base(self.path().clone());
|
||||
let old_id = old_id.with_base(self.path().clone());
|
||||
|
||||
if let Err(e) = self.execute_hooks_for_id(self.pre_move_aspects.clone(), &old_id) {
|
||||
return Err(e)
|
||||
|
@ -677,15 +646,17 @@ impl Store {
|
|||
}
|
||||
|
||||
{
|
||||
let hsmap = self.entries.write();
|
||||
if hsmap.is_err() {
|
||||
return Err(SE::new(SEK::LockPoisoned, None))
|
||||
}
|
||||
let hsmap = hsmap.unwrap();
|
||||
let hsmap = match self.entries.write() {
|
||||
Err(_) => return Err(SE::new(SEK::LockPoisoned, None)),
|
||||
Ok(m) => m,
|
||||
};
|
||||
|
||||
if hsmap.contains_key(&old_id) {
|
||||
return Err(SE::new(SEK::EntryAlreadyBorrowed, None));
|
||||
} else {
|
||||
match FileAbstraction::rename(&old_id.clone(), &new_id) {
|
||||
let old_id_pb = old_id.clone().into();
|
||||
let new_id_pb = new_id.clone().into();
|
||||
match FileAbstraction::rename(&old_id_pb, &new_id_pb) {
|
||||
Err(e) => return Err(SEK::EntryRenameError.into_error_with_cause(Box::new(e))),
|
||||
Ok(_) => {
|
||||
debug!("Rename worked");
|
||||
|
@ -831,11 +802,19 @@ impl Drop for Store {
|
|||
* TODO: Unlock them
|
||||
*/
|
||||
fn drop(&mut self) {
|
||||
let store_id = StoreId::from(self.location.clone());
|
||||
match StoreId::new(Some(self.location.clone()), PathBuf::from(".")) {
|
||||
Err(e) => {
|
||||
trace_error(&e);
|
||||
warn!("Cannot construct StoreId for Store to execute hooks!");
|
||||
warn!("Will close Store without executing hooks!");
|
||||
},
|
||||
Ok(store_id) => {
|
||||
if let Err(e) = self.execute_hooks_for_id(self.store_unload_aspects.clone(), &store_id) {
|
||||
debug!("Store-load hooks execution failed. Cannot create store object.");
|
||||
warn!("Store Unload Hook error: {:?}", e);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
debug!("Dropping store");
|
||||
}
|
||||
|
@ -1449,7 +1428,7 @@ impl Entry {
|
|||
|
||||
debug!("Header and content found. Yay! Building Entry object now");
|
||||
Ok(Entry {
|
||||
location: loc.into_storeid(),
|
||||
location: try!(loc.into_storeid()),
|
||||
header: try!(EntryHeader::parse(header)),
|
||||
content: content.into(),
|
||||
})
|
||||
|
@ -1490,11 +1469,18 @@ impl Entry {
|
|||
mod glob_store_iter {
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::fmt::Error as FmtError;
|
||||
use std::path::PathBuf;
|
||||
use glob::Paths;
|
||||
use storeid::StoreId;
|
||||
use storeid::StoreIdIterator;
|
||||
|
||||
use error::StoreErrorKind as SEK;
|
||||
use error::MapErrInto;
|
||||
|
||||
use libimagerror::trace::trace_error;
|
||||
|
||||
pub struct GlobStoreIdIterator {
|
||||
store_path: PathBuf,
|
||||
paths: Paths,
|
||||
}
|
||||
|
||||
|
@ -1516,8 +1502,9 @@ mod glob_store_iter {
|
|||
|
||||
impl GlobStoreIdIterator {
|
||||
|
||||
pub fn new(paths: Paths) -> GlobStoreIdIterator {
|
||||
pub fn new(paths: Paths, store_path: PathBuf) -> GlobStoreIdIterator {
|
||||
GlobStoreIdIterator {
|
||||
store_path: store_path,
|
||||
paths: paths,
|
||||
}
|
||||
}
|
||||
|
@ -1528,15 +1515,16 @@ mod glob_store_iter {
|
|||
type Item = StoreId;
|
||||
|
||||
fn next(&mut self) -> Option<StoreId> {
|
||||
self.paths.next().and_then(|o| {
|
||||
match o {
|
||||
Ok(o) => Some(o),
|
||||
Err(e) => {
|
||||
self.paths
|
||||
.next()
|
||||
.and_then(|o| {
|
||||
o.map_err_into(SEK::StoreIdHandlingError)
|
||||
.and_then(|p| StoreId::new(Some(self.store_path.clone()), p))
|
||||
.map_err(|e| {
|
||||
debug!("GlobStoreIdIterator error: {:?}", e);
|
||||
None
|
||||
},
|
||||
}
|
||||
}).map(|p| StoreId::from(p))
|
||||
trace_error(&e);
|
||||
}).ok()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1551,6 +1539,7 @@ mod test {
|
|||
use std::collections::BTreeMap;
|
||||
use super::EntryHeader;
|
||||
use super::Token;
|
||||
use storeid::StoreId;
|
||||
|
||||
use toml::Value;
|
||||
|
||||
|
@ -1681,7 +1670,7 @@ Hai";
|
|||
use super::Entry;
|
||||
use std::path::PathBuf;
|
||||
println!("{}", TEST_ENTRY);
|
||||
let entry = Entry::from_str(PathBuf::from("/test/foo~1.3"),
|
||||
let entry = Entry::from_str(StoreId::new_baseless(PathBuf::from("test/foo~1.3")).unwrap(),
|
||||
TEST_ENTRY).unwrap();
|
||||
|
||||
assert_eq!(entry.content, "Hai");
|
||||
|
@ -1692,7 +1681,7 @@ Hai";
|
|||
use super::Entry;
|
||||
use std::path::PathBuf;
|
||||
println!("{}", TEST_ENTRY);
|
||||
let entry = Entry::from_str(PathBuf::from("/test/foo~1.3"),
|
||||
let entry = Entry::from_str(StoreId::new_baseless(PathBuf::from("test/foo~1.3")).unwrap(),
|
||||
TEST_ENTRY).unwrap();
|
||||
let string = entry.to_str();
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use std::path::PathBuf;
|
||||
use std::path::Path;
|
||||
use std::borrow::Borrow;
|
||||
use std::ops::Deref;
|
||||
|
||||
use semver::Version;
|
||||
use std::fmt::{Display, Debug, Formatter};
|
||||
use std::fmt::Error as FmtError;
|
||||
use std::result::Result as RResult;
|
||||
use std::path::Components;
|
||||
|
||||
use libimagerror::into::IntoError;
|
||||
|
||||
use error::StoreErrorKind as SEK;
|
||||
use store::Result;
|
||||
|
@ -14,21 +13,82 @@ use store::Store;
|
|||
|
||||
/// The Index into the Store
|
||||
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
|
||||
pub struct StoreId(PathBuf);
|
||||
pub struct StoreId {
|
||||
base: Option<PathBuf>,
|
||||
id: PathBuf,
|
||||
}
|
||||
|
||||
impl StoreId {
|
||||
|
||||
pub fn storified(self, store: &Store) -> StoreId {
|
||||
if self.starts_with(store.path()) {
|
||||
debug!("Not storifying {:?}, because it is already.", self);
|
||||
self
|
||||
} else {
|
||||
debug!("Create new store id out of: {:?} and {:?}", store.path(), self);
|
||||
let mut new_id = store.path().clone();
|
||||
new_id.push(self);
|
||||
debug!("Created: '{:?}'", new_id);
|
||||
StoreId::from(new_id)
|
||||
pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
|
||||
StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
|
||||
}
|
||||
|
||||
pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
|
||||
if id.is_absolute() {
|
||||
Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
|
||||
} else {
|
||||
Ok(StoreId {
|
||||
base: None,
|
||||
id: id
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn without_base(mut self) -> StoreId {
|
||||
self.base = None;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_base(mut self, base: PathBuf) -> Self {
|
||||
self.base = Some(base);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn storified(self, store: &Store) -> StoreId {
|
||||
StoreId {
|
||||
base: Some(store.path().clone()),
|
||||
id: self.id
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exists(&self) -> bool {
|
||||
let pb : PathBuf = self.clone().into();
|
||||
pb.exists()
|
||||
}
|
||||
|
||||
pub fn is_file(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn is_dir(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn to_str(&self) -> Result<String> {
|
||||
if self.base.is_some() {
|
||||
let mut base = self.base.as_ref().cloned().unwrap();
|
||||
base.push(self.id.clone());
|
||||
base
|
||||
} else {
|
||||
self.id.clone()
|
||||
}
|
||||
.to_str()
|
||||
.map(String::from)
|
||||
.ok_or(SEK::StoreIdHandlingError.into_error())
|
||||
}
|
||||
|
||||
/// Returns the components of the `id` part of the StoreId object.
|
||||
///
|
||||
/// Can be used to check whether a StoreId points to an entry in a specific collection of
|
||||
/// StoreIds.
|
||||
pub fn components(&self) -> Components {
|
||||
self.id.components()
|
||||
}
|
||||
|
||||
/// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
|
||||
pub fn local(&self) -> &PathBuf {
|
||||
&self.id
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,7 +96,9 @@ impl StoreId {
|
|||
impl Into<PathBuf> for StoreId {
|
||||
|
||||
fn into(self) -> PathBuf {
|
||||
self.0
|
||||
let mut base = self.base.unwrap_or(PathBuf::from("/"));
|
||||
base.push(self.id);
|
||||
base
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -44,97 +106,35 @@ impl Into<PathBuf> for StoreId {
|
|||
impl Display for StoreId {
|
||||
|
||||
fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
|
||||
match self.0.to_str() {
|
||||
match self.id.to_str() {
|
||||
Some(s) => write!(fmt, "{}", s),
|
||||
None => write!(fmt, "{}", self.0.to_string_lossy()),
|
||||
None => write!(fmt, "{}", self.id.to_string_lossy()),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Deref for StoreId {
|
||||
type Target = PathBuf;
|
||||
|
||||
fn deref(&self) -> &PathBuf {
|
||||
&self.0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl From<PathBuf> for StoreId {
|
||||
|
||||
fn from(pb: PathBuf) -> StoreId {
|
||||
StoreId(pb)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl From<String> for StoreId {
|
||||
|
||||
fn from(string: String) -> StoreId {
|
||||
StoreId(string.into())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl AsRef<Path> for StoreId {
|
||||
|
||||
fn as_ref(&self) -> &Path {
|
||||
self.0.as_ref()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Borrow<Path> for StoreId {
|
||||
|
||||
fn borrow(&self) -> &Path {
|
||||
self.0.borrow()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// This Trait allows you to convert various representations to a single one
|
||||
/// suitable for usage in the Store
|
||||
pub trait IntoStoreId {
|
||||
fn into_storeid(self) -> StoreId;
|
||||
}
|
||||
|
||||
impl IntoStoreId for PathBuf {
|
||||
fn into_storeid(self) -> StoreId {
|
||||
StoreId(self)
|
||||
}
|
||||
fn into_storeid(self) -> Result<StoreId>;
|
||||
}
|
||||
|
||||
impl IntoStoreId for StoreId {
|
||||
fn into_storeid(self) -> StoreId {
|
||||
self
|
||||
fn into_storeid(self) -> Result<StoreId> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
|
||||
debug!("Checking path element for version");
|
||||
if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) {
|
||||
debug!("Version cannot be parsed from {:?}", path_elem);
|
||||
debug!("Path does not contain version!");
|
||||
return Err(SEK::StorePathLacksVersion.into());
|
||||
impl IntoStoreId for PathBuf {
|
||||
fn into_storeid(self) -> Result<StoreId> {
|
||||
StoreId::new_baseless(self)
|
||||
}
|
||||
debug!("Version checking succeeded");
|
||||
|
||||
debug!("Building path from {:?}", path_elem);
|
||||
let mut path = store.path().clone();
|
||||
|
||||
if path_elem.starts_with('/') {
|
||||
path.push(&path_elem[1..]);
|
||||
} else {
|
||||
path.push(path_elem);
|
||||
}
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! module_entry_path_mod {
|
||||
($name:expr, $version:expr) => (
|
||||
($name:expr) => (
|
||||
#[deny(missing_docs,
|
||||
missing_copy_implementations,
|
||||
trivial_casts, trivial_numeric_casts,
|
||||
|
@ -144,12 +144,12 @@ macro_rules! module_entry_path_mod {
|
|||
unused_imports)]
|
||||
/// A helper module to create valid module entry paths
|
||||
pub mod module_path {
|
||||
use semver::Version;
|
||||
use std::convert::AsRef;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use $crate::storeid::StoreId;
|
||||
use $crate::store::Result;
|
||||
|
||||
/// A Struct giving you the ability to choose store entries assigned
|
||||
/// to it.
|
||||
|
@ -163,19 +163,16 @@ macro_rules! module_entry_path_mod {
|
|||
let mut path = PathBuf::new();
|
||||
path.push(format!("{}", $name));
|
||||
path.push(pa.as_ref().clone());
|
||||
let version = Version::parse($version).unwrap();
|
||||
let name = pa.as_ref().file_name().unwrap()
|
||||
.to_str().unwrap();
|
||||
path.set_file_name(format!("{}~{}",
|
||||
name,
|
||||
version));
|
||||
path.set_file_name(name);
|
||||
ModuleEntryPath(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::storeid::IntoStoreId for ModuleEntryPath {
|
||||
fn into_storeid(self) -> $crate::storeid::StoreId {
|
||||
StoreId::from(self.0)
|
||||
fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
|
||||
StoreId::new(None, self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,13 +215,13 @@ mod test {
|
|||
|
||||
use storeid::IntoStoreId;
|
||||
|
||||
module_entry_path_mod!("test", "0.2.0-alpha+leet1337");
|
||||
module_entry_path_mod!("test");
|
||||
|
||||
#[test]
|
||||
fn correct_path() {
|
||||
let p = module_path::ModuleEntryPath::new("test");
|
||||
|
||||
assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
|
||||
assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,27 +18,23 @@ use libimagstore::store::FileLockEntry;
|
|||
use libimagstore::store::Entry;
|
||||
|
||||
trait EntryFlock {
|
||||
fn lock(&self, store_location: &PathBuf) -> IoResult<()>;
|
||||
fn unlock(&self, store_location: &PathBuf) -> IoResult<()>;
|
||||
fn lock(&self) -> IoResult<()>;
|
||||
fn unlock(&self) -> IoResult<()>;
|
||||
}
|
||||
|
||||
impl EntryFlock for Entry {
|
||||
|
||||
fn lock(&self, store_location: &PathBuf) -> IoResult<()> {
|
||||
fn lock(&self) -> IoResult<()> {
|
||||
use std::fs::File;
|
||||
|
||||
let mut location = store_location.clone();
|
||||
location.push(self.get_location());
|
||||
|
||||
let location : PathBuf = self.get_location().clone().into();
|
||||
File::open(location).and_then(|file| file.lock_exclusive())
|
||||
}
|
||||
|
||||
fn unlock(&self, store_location: &PathBuf) -> IoResult<()> {
|
||||
fn unlock(&self) -> IoResult<()> {
|
||||
use std::fs::File;
|
||||
|
||||
let mut location = store_location.clone();
|
||||
location.push(self.get_location());
|
||||
|
||||
let location : PathBuf = self.get_location().clone().into();
|
||||
File::open(location).and_then(|file| file.unlock())
|
||||
}
|
||||
|
||||
|
@ -60,15 +56,13 @@ fn action_to_str(a: &Action) -> &'static str {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct FlockUpdateHook {
|
||||
action: Action,
|
||||
store_location: PathBuf,
|
||||
}
|
||||
|
||||
impl FlockUpdateHook {
|
||||
|
||||
pub fn new(action: Action, store_location: PathBuf) -> FlockUpdateHook {
|
||||
pub fn new(action: Action) -> FlockUpdateHook {
|
||||
FlockUpdateHook {
|
||||
action: action,
|
||||
store_location: store_location,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +101,7 @@ impl MutableHookDataAccessor for FlockUpdateHook {
|
|||
|
||||
fn access_mut(&self, fle: &mut FileLockEntry) -> HookResult<()> {
|
||||
debug!("[FLOCK HOOK][{}] {:?}", action_to_str(&self.action), fle.get_location());
|
||||
fle.lock(&self.store_location)
|
||||
fle.lock()
|
||||
.map_err(|e| HookError::new(HookErrorKind::HookExecutionError, Some(Box::new(e))))
|
||||
.map(|_| ())
|
||||
}
|
||||
|
@ -118,7 +112,7 @@ impl NonMutableHookDataAccessor for FlockUpdateHook {
|
|||
|
||||
fn access(&self, fle: &FileLockEntry) -> HookResult<()> {
|
||||
debug!("[FLOCK HOOK][{}] {:?}", action_to_str(&self.action), fle.get_location());
|
||||
fle.unlock(&self.store_location)
|
||||
fle.unlock()
|
||||
.map_err(|e| HookError::new(HookErrorKind::HookExecutionError, Some(Box::new(e))))
|
||||
.map(|_| ())
|
||||
}
|
||||
|
|
|
@ -53,12 +53,10 @@ impl NonMutableHookDataAccessor for LinkedEntriesExistHook {
|
|||
let _ = fle.get_internal_links()
|
||||
.map(|links| {
|
||||
for link in links {
|
||||
let mut path = self.store_location.clone();
|
||||
path.push(link);
|
||||
if !path.exists() {
|
||||
warn!("File link does not exist: {:?} -> {:?}", fle.get_location(), path);
|
||||
} else if !path.is_file() {
|
||||
warn!("File link is not a file: {:?} -> {:?}", fle.get_location(), path);
|
||||
if !link.exists() {
|
||||
warn!("File link does not exist: {:?} -> {:?}", fle.get_location(), link);
|
||||
} else if !link.is_file() {
|
||||
warn!("File link is not a file: {:?} -> {:?}", fle.get_location(), link);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -2,6 +2,7 @@ generate_error_module!(
|
|||
generate_error_types!(TodoError, TodoErrorKind,
|
||||
ConversionError => "Conversion Error",
|
||||
StoreError => "Store Error",
|
||||
StoreIdError => "Store Id handling error",
|
||||
ImportError => "Error importing"
|
||||
);
|
||||
);
|
||||
|
|
|
@ -22,7 +22,7 @@ extern crate serde_json;
|
|||
#[macro_use] extern crate libimagerror;
|
||||
extern crate task_hookrs;
|
||||
|
||||
module_entry_path_mod!("todo", "0.1.0");
|
||||
module_entry_path_mod!("todo");
|
||||
|
||||
pub mod error;
|
||||
pub mod result;
|
||||
|
|
|
@ -73,9 +73,9 @@ impl<'a> Task<'a> {
|
|||
///
|
||||
/// If there is no task with this UUID, this returns `Ok(None)`.
|
||||
pub fn get_from_uuid(store: &'a Store, uuid: Uuid) -> Result<Option<Task<'a>>> {
|
||||
let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid();
|
||||
|
||||
store.get(store_id)
|
||||
ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
|
||||
.into_storeid()
|
||||
.and_then(|store_id| store.get(store_id))
|
||||
.map(|o| o.map(Task::new))
|
||||
.map_err_into(TodoErrorKind::StoreError)
|
||||
}
|
||||
|
@ -138,7 +138,9 @@ impl<'a> Task<'a> {
|
|||
}
|
||||
|
||||
pub fn delete_by_uuid(store: &Store, uuid: Uuid) -> Result<()> {
|
||||
store.delete(ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid())
|
||||
ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
|
||||
.into_storeid()
|
||||
.and_then(|id| store.delete(id))
|
||||
.map_err(|e| TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
|
||||
}
|
||||
|
||||
|
@ -196,34 +198,30 @@ impl<'a> IntoTask<'a> for TTask {
|
|||
|
||||
fn into_task(self, store : &'a Store) -> Result<Task<'a>> {
|
||||
let uuid = self.uuid();
|
||||
let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid();
|
||||
|
||||
match store.retrieve(store_id) {
|
||||
Err(e) => return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))),
|
||||
Ok(mut fle) => {
|
||||
ModuleEntryPath::new(format!("taskwarrior/{}", uuid))
|
||||
.into_storeid()
|
||||
.map_err_into(TodoErrorKind::StoreIdError)
|
||||
.and_then(|id| {
|
||||
store.retrieve(id)
|
||||
.map_err_into(TodoErrorKind::StoreError)
|
||||
.and_then(|mut fle| {
|
||||
{
|
||||
let mut header = fle.get_header_mut();
|
||||
match header.read("todo") {
|
||||
Ok(None) => {
|
||||
if let Err(e) = header.set("todo", Value::Table(BTreeMap::new())) {
|
||||
return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
|
||||
}
|
||||
}
|
||||
Ok(Some(_)) => { }
|
||||
Err(e) => {
|
||||
return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
|
||||
}
|
||||
let mut hdr = fle.get_header_mut();
|
||||
let read = hdr.read("todo").map_err_into(TodoErrorKind::StoreError);
|
||||
if try!(read).is_none() {
|
||||
try!(hdr
|
||||
.set("todo", Value::Table(BTreeMap::new()))
|
||||
.map_err_into(TodoErrorKind::StoreError));
|
||||
}
|
||||
|
||||
if let Err(e) = header.set("todo.uuid", Value::String(format!("{}",uuid))) {
|
||||
return Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
|
||||
}
|
||||
try!(hdr.set("todo.uuid", Value::String(format!("{}",uuid)))
|
||||
.map_err_into(TodoErrorKind::StoreError));
|
||||
}
|
||||
|
||||
// If none of the errors above have returned the function, everything is fine
|
||||
Ok(Task::new(fle))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue