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