Merge branch 'minor'
This merges some important fixes: * libimagstore: Remove calls to filesystem-accessing functions but use abstractions instead. * Make Debug for FileLockEntry more verbose * Fix In-Memory test backend bug where the backend did not remove the old entry on "move" as well as some nice formatting stuff and refactorings to simplify code and similar improvements. Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
commit
7fd3350146
13 changed files with 166 additions and 198 deletions
|
@ -119,14 +119,11 @@ fn list(rt: &Runtime) {
|
||||||
.all_contacts()
|
.all_contacts()
|
||||||
.map_err_trace_exit_unwrap(1)
|
.map_err_trace_exit_unwrap(1)
|
||||||
.into_get_iter(rt.store())
|
.into_get_iter(rt.store())
|
||||||
.map(|fle| {
|
.trace_unwrap_exit(1)
|
||||||
let fle = fle
|
.map(|fle| fle.ok_or_else(|| Error::from(err_msg("StoreId not found".to_owned()))))
|
||||||
.map_err_trace_exit_unwrap(1)
|
.trace_unwrap_exit(1)
|
||||||
.ok_or_else(|| Error::from(err_msg("StoreId not found".to_owned())))
|
.map(|e| e.deser())
|
||||||
.map_err_trace_exit_unwrap(1);
|
.trace_unwrap_exit(1)
|
||||||
|
|
||||||
fle.deser().map_err_trace_exit_unwrap(1)
|
|
||||||
})
|
|
||||||
.enumerate();
|
.enumerate();
|
||||||
|
|
||||||
if scmd.is_present("json") {
|
if scmd.is_present("json") {
|
||||||
|
@ -140,21 +137,19 @@ fn list(rt: &Runtime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iterator
|
let rendered = iterator
|
||||||
.map(|(i, deservcard)| {
|
.map(|(i, dvcard)| build_data_object_for_handlebars(i, &dvcard))
|
||||||
let data = build_data_object_for_handlebars(i, &deservcard);
|
.map(|data| list_format.render("format", &data).map_err(Error::from))
|
||||||
|
.trace_unwrap_exit(1)
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
// collect, so that we can have rendered all the things and printing is faster.
|
||||||
|
|
||||||
list_format.render("format", &data)
|
let output = rt.stdout();
|
||||||
.map_err(Error::from)
|
let mut output = output.lock();
|
||||||
.map_err_trace_exit_unwrap(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
// collect, so that we can have rendered all the things and printing is faster.
|
rendered.into_iter().for_each(|s| {
|
||||||
.collect::<Vec<String>>()
|
writeln!(output, "{}", s).to_exit_code().unwrap_or_exit()
|
||||||
.into_iter()
|
});
|
||||||
.for_each(|s| {
|
|
||||||
writeln!(rt.stdout(), "{}", s).to_exit_code().unwrap_or_exit()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
use chrono::naive::NaiveDateTime;
|
use chrono::naive::NaiveDateTime as NDT;
|
||||||
|
|
||||||
use libimagdiary::diaryid::DiaryId;
|
use libimagdiary::diaryid::DiaryId;
|
||||||
use libimagrt::runtime::Runtime;
|
use libimagrt::runtime::Runtime;
|
||||||
|
@ -44,17 +44,10 @@ pub fn delete(rt: &Runtime) {
|
||||||
.value_of("datetime")
|
.value_of("datetime")
|
||||||
.map(|dt| { debug!("DateTime = {:?}", dt); dt })
|
.map(|dt| { debug!("DateTime = {:?}", dt); dt })
|
||||||
.and_then(DateTime::parse)
|
.and_then(DateTime::parse)
|
||||||
.map(|dt| dt.into())
|
.map(Into::into)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| warn_exit("Not deleting entries: missing date/time specification", 1))
|
||||||
warn!("Not deleting entries, because missing date/time specification");
|
.and_then(|dt: NDT| DiaryId::from_datetime(diaryname.clone(), dt).into_storeid())
|
||||||
exit(1);
|
.and_then(|id| rt.store().retrieve(id))
|
||||||
})
|
|
||||||
.and_then(|dt: NaiveDateTime| {
|
|
||||||
DiaryId::from_datetime(diaryname.clone(), dt)
|
|
||||||
.into_storeid()
|
|
||||||
.map(|id| rt.store().retrieve(id))
|
|
||||||
.map_err_trace_exit_unwrap(1)
|
|
||||||
})
|
|
||||||
.map_err_trace_exit_unwrap(1)
|
.map_err_trace_exit_unwrap(1)
|
||||||
.get_location()
|
.get_location()
|
||||||
.clone();
|
.clone();
|
||||||
|
|
|
@ -51,10 +51,9 @@ pub fn list(rt: &Runtime) {
|
||||||
[id.year() as u32, id.month(), id.day(), id.hour(), id.minute(), id.second()]
|
[id.year() as u32, id.month(), id.day(), id.hour(), id.minute(), id.second()]
|
||||||
});
|
});
|
||||||
|
|
||||||
for id in ids.into_iter().map(|id| id.into_storeid().map_err_trace_exit_unwrap(1)) {
|
ids.into_iter()
|
||||||
writeln!(rt.stdout(), "{}", id)
|
.map(IntoStoreId::into_storeid)
|
||||||
.to_exit_code()
|
.trace_unwrap_exit(1)
|
||||||
.unwrap_or_exit();
|
.for_each(|id| writeln!(rt.stdout(), "{}", id).to_exit_code().unwrap_or_exit());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ use libimagstore::store::FileLockEntry;
|
||||||
use libimagstore::store::Store;
|
use libimagstore::store::Store;
|
||||||
use libimagstore::storeid::StoreId;
|
use libimagstore::storeid::StoreId;
|
||||||
use libimaginteraction::ask::ask_bool;
|
use libimaginteraction::ask::ask_bool;
|
||||||
|
use libimagutil::debug_result::DebugResult;
|
||||||
|
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
|
@ -115,20 +116,16 @@ fn create(rt: &Runtime) {
|
||||||
let date = scmd.value_of("create-date").unwrap(); // safe by clap
|
let date = scmd.value_of("create-date").unwrap(); // safe by clap
|
||||||
|
|
||||||
let parsedate = |d, pname| match kairos_parse(d).map_err_trace_exit_unwrap(1) {
|
let parsedate = |d, pname| match kairos_parse(d).map_err_trace_exit_unwrap(1) {
|
||||||
Parsed::TimeType(tt) => match tt.calculate() {
|
Parsed::TimeType(tt) => tt.calculate()
|
||||||
Ok(tt) => match tt.get_moment() {
|
.map_dbg(|y| format!("TimeType yielded: '{:?}'", y))
|
||||||
Some(mom) => mom.date(),
|
.map_err_trace_exit_unwrap(1)
|
||||||
None => {
|
.get_moment()
|
||||||
debug!("TimeType yielded: '{:?}'", tt);
|
.ok_or_else(|| {
|
||||||
error!("Error: '{}' parameter does not yield a point in time", pname);
|
error!("Error: '{}' parameter does not yield a point in time", pname);
|
||||||
exit(1);
|
exit(1)
|
||||||
},
|
})
|
||||||
},
|
.unwrap() // safe by above
|
||||||
Err(e) => {
|
.date(),
|
||||||
error!("Error: '{:?}'", e);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
error!("Error: '{}' parameter does not yield a point in time", pname);
|
error!("Error: '{}' parameter does not yield a point in time", pname);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -68,13 +68,9 @@ impl Debug for OutputProxy {
|
||||||
impl OutputProxy {
|
impl OutputProxy {
|
||||||
pub fn lock(&self) -> LockedOutputProxy {
|
pub fn lock(&self) -> LockedOutputProxy {
|
||||||
match *self {
|
match *self {
|
||||||
OutputProxy::Out(ref r) => {
|
OutputProxy::Out(ref r) => LockedOutputProxy::Out(r.lock()),
|
||||||
LockedOutputProxy::Out(r.lock())
|
OutputProxy::Err(ref r) => LockedOutputProxy::Err(r.lock()),
|
||||||
},
|
OutputProxy::Sink => LockedOutputProxy::Sink,
|
||||||
OutputProxy::Err(ref r) => {
|
|
||||||
LockedOutputProxy::Err(r.lock())
|
|
||||||
},
|
|
||||||
OutputProxy::Sink => LockedOutputProxy::Sink,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,34 +88,12 @@ impl ImagLogger {
|
||||||
::libimaginteraction::format::register_all_format_helpers(&mut handlebars);
|
::libimaginteraction::format::register_all_format_helpers(&mut handlebars);
|
||||||
|
|
||||||
{
|
{
|
||||||
let fmt = aggregate_global_format_trace(config)?;
|
use self::log_lvl_aggregate::*;
|
||||||
handlebars.register_template_string("TRACE", fmt)
|
let _ = aggregate::<Trace>(&mut handlebars, config, "TRACE")?;
|
||||||
.map_err(Error::from)
|
let _ = aggregate::<Debug>(&mut handlebars, config, "DEBUG")?;
|
||||||
.context(err_msg("Handlebars template error"))?; // name must be uppercase
|
let _ = aggregate::<Info>(&mut handlebars, config, "INFO")?;
|
||||||
}
|
let _ = aggregate::<Warn>(&mut handlebars, config, "WARN")?;
|
||||||
{
|
let _ = aggregate::<Error>(&mut handlebars, config, "ERROR")?;
|
||||||
let fmt = aggregate_global_format_debug(config)?;
|
|
||||||
handlebars.register_template_string("DEBUG", fmt)
|
|
||||||
.map_err(Error::from)
|
|
||||||
.context(err_msg("Handlebars template error"))?; // name must be uppercase
|
|
||||||
}
|
|
||||||
{
|
|
||||||
let fmt = aggregate_global_format_info(config)?;
|
|
||||||
handlebars.register_template_string("INFO", fmt)
|
|
||||||
.map_err(Error::from)
|
|
||||||
.context(err_msg("Handlebars template error"))?; // name must be uppercase
|
|
||||||
}
|
|
||||||
{
|
|
||||||
let fmt = aggregate_global_format_warn(config)?;
|
|
||||||
handlebars.register_template_string("WARN", fmt)
|
|
||||||
.map_err(Error::from)
|
|
||||||
.context(err_msg("Handlebars template error"))?; // name must be uppercase
|
|
||||||
}
|
|
||||||
{
|
|
||||||
let fmt = aggregate_global_format_error(config)?;
|
|
||||||
handlebars.register_template_string("ERROR", fmt)
|
|
||||||
.map_err(Error::from)
|
|
||||||
.context(err_msg("Handlebars template error"))?; // name must be uppercase
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ImagLogger {
|
Ok(ImagLogger {
|
||||||
|
@ -289,9 +267,8 @@ fn translate_destinations(raw: &Vec<Value>) -> Result<Vec<LogDestination>> {
|
||||||
acc.and_then(|mut v| {
|
acc.and_then(|mut v| {
|
||||||
let dest = val.as_str()
|
let dest = val.as_str()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
let path = "imag.logging.modules.<mod>.destinations";
|
let msg = "Type error at 'imag.logging.modules.<mod>.destinations', expected Array<String>";
|
||||||
let ty = "Array<String>";
|
Error::from(err_msg(msg))
|
||||||
Error::from(format_err!("Type error at {}, expected {}", path, ty))
|
|
||||||
})
|
})
|
||||||
.and_then(translate_destination)?;
|
.and_then(translate_destination)?;
|
||||||
v.push(dest);
|
v.push(dest);
|
||||||
|
@ -312,9 +289,8 @@ fn aggregate_global_destinations(matches: &ArgMatches, config: Option<&Value>)
|
||||||
.ok_or_else(|| err_msg("Global log destination config missing"))?
|
.ok_or_else(|| err_msg("Global log destination config missing"))?
|
||||||
.as_array()
|
.as_array()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
let path = "imag.logging.destinations";
|
let msg = "Type error at 'imag.logging.destinations', expected 'Array'";
|
||||||
let ty = "Array";
|
Error::from(err_msg(msg))
|
||||||
Error::from(format_err!("Type error at {}, expected {}", path, ty))
|
|
||||||
})
|
})
|
||||||
.and_then(translate_destinations),
|
.and_then(translate_destinations),
|
||||||
None => {
|
None => {
|
||||||
|
@ -335,54 +311,55 @@ fn aggregate_global_destinations(matches: &ArgMatches, config: Option<&Value>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! aggregate_global_format {
|
mod log_lvl_aggregate {
|
||||||
($read_str:expr, $error_msg_if_missing:expr, $config:expr) => {
|
use failure::Fallible as Result;
|
||||||
try!($config.ok_or_else(|| Error::from(err_msg($error_msg_if_missing))))
|
use failure::Error as E;
|
||||||
.read_string($read_str)
|
use failure::ResultExt;
|
||||||
.map_err(Error::from)
|
use failure::err_msg;
|
||||||
.context(EM::TomlQueryError)?
|
use toml::Value;
|
||||||
.ok_or_else(|| Error::from(err_msg($error_msg_if_missing)))
|
use toml_query::read::TomlValueReadTypeExt;
|
||||||
};
|
use handlebars::Handlebars;
|
||||||
}
|
|
||||||
|
|
||||||
fn aggregate_global_format_trace(config: Option<&Value>)
|
use libimagerror::errors::ErrorMsg as EM;
|
||||||
-> Result<String>
|
|
||||||
{
|
|
||||||
aggregate_global_format!("imag.logging.format.trace",
|
|
||||||
"Config missing: Logging format: Trace",
|
|
||||||
config)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn aggregate_global_format_debug(config: Option<&Value>)
|
macro_rules! aggregate_global_format_with {
|
||||||
-> Result<String>
|
($t:ident, $read_str:expr) => {
|
||||||
{
|
pub struct $t;
|
||||||
aggregate_global_format!("imag.logging.format.debug",
|
impl LogLevelAggregator for $t {
|
||||||
"Config missing: Logging format: Debug",
|
fn aggregate(config: Option<&Value>) -> Result<String> {
|
||||||
config)
|
config.ok_or_else(|| {
|
||||||
}
|
E::from(err_msg(concat!("Config missing: Logging format: ", stringify!($t))))
|
||||||
|
})?
|
||||||
|
.read_string($read_str)
|
||||||
|
.map_err(E::from)
|
||||||
|
.context(EM::TomlQueryError)?
|
||||||
|
.ok_or_else(|| {
|
||||||
|
E::from(err_msg(concat!("Config missing: Logging format: ", stringify!($t))))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn aggregate_global_format_info(config: Option<&Value>)
|
pub trait LogLevelAggregator {
|
||||||
-> Result<String>
|
fn aggregate(config: Option<&Value>) -> Result<String>;
|
||||||
{
|
}
|
||||||
aggregate_global_format!("imag.logging.format.info",
|
|
||||||
"Config missing: Logging format: Info",
|
|
||||||
config)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn aggregate_global_format_warn(config: Option<&Value>)
|
pub fn aggregate<T: LogLevelAggregator>(hb: &mut Handlebars, config: Option<&Value>, lvlstr: &str)
|
||||||
-> Result<String>
|
-> Result<()>
|
||||||
{
|
{
|
||||||
aggregate_global_format!("imag.logging.format.warn",
|
hb.register_template_string(lvlstr, T::aggregate(config)?)
|
||||||
"Config missing: Logging format: Warn",
|
.map_err(E::from)
|
||||||
config)
|
.context(err_msg("Handlebars template error"))
|
||||||
}
|
.map_err(E::from)
|
||||||
|
}
|
||||||
|
|
||||||
|
aggregate_global_format_with!(Trace, "imag.logging.format.trace");
|
||||||
|
aggregate_global_format_with!(Debug, "imag.logging.format.debug");
|
||||||
|
aggregate_global_format_with!(Info, "imag.logging.format.info");
|
||||||
|
aggregate_global_format_with!(Warn, "imag.logging.format.warn");
|
||||||
|
aggregate_global_format_with!(Error, "imag.logging.format.error");
|
||||||
|
|
||||||
fn aggregate_global_format_error(config: Option<&Value>)
|
|
||||||
-> Result<String>
|
|
||||||
{
|
|
||||||
aggregate_global_format!("imag.logging.format.error",
|
|
||||||
"Config missing: Logging format: Error",
|
|
||||||
config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>)
|
fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>)
|
||||||
|
@ -414,9 +391,8 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>)
|
||||||
.map(|val| {
|
.map(|val| {
|
||||||
val.as_array()
|
val.as_array()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
let path = "imag.logging.modules.<mod>.destinations";
|
let msg = "Type error at 'imag.logging.modules.<mod>.destinations', expected 'Array'";
|
||||||
let ty = "Array";
|
Error::from(err_msg(msg))
|
||||||
Error::from(format_err!("Type error at {}, expected {}", path, ty))
|
|
||||||
})
|
})
|
||||||
.and_then(translate_destinations)
|
.and_then(translate_destinations)
|
||||||
})
|
})
|
||||||
|
@ -434,9 +410,8 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>)
|
||||||
.context(EM::TomlQueryError)?
|
.context(EM::TomlQueryError)?
|
||||||
.map(|v| v.as_bool().unwrap_or(false))
|
.map(|v| v.as_bool().unwrap_or(false))
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
let path = "imag.logging.modules.<mod>.enabled";
|
let msg = "Type error at 'imag.logging.modules.<mod>.enabled', expected 'Boolean'";
|
||||||
let ty = "Boolean";
|
Error::from(err_msg(msg))
|
||||||
Error::from(format_err!("Type error at {}, expected {}", path, ty))
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let module_settings = ModuleSettings {
|
let module_settings = ModuleSettings {
|
||||||
|
@ -452,9 +427,8 @@ fn aggregate_module_settings(_matches: &ArgMatches, config: Option<&Value>)
|
||||||
Ok(settings)
|
Ok(settings)
|
||||||
},
|
},
|
||||||
Ok(Some(_)) => {
|
Ok(Some(_)) => {
|
||||||
let path = "imag.logging.modules";
|
let msg = "Type error at 'imag.logging.modules', expected 'Table'";
|
||||||
let ty = "Table";
|
Err(Error::from(err_msg(msg)))
|
||||||
Err(Error::from(format_err!("Type error at {}, expected {}", path, ty)))
|
|
||||||
},
|
},
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
// No modules configured. This is okay!
|
// No modules configured. This is okay!
|
||||||
|
|
|
@ -137,13 +137,11 @@ impl<'a> Runtime<'a> {
|
||||||
Store::new(storepath, &config)
|
Store::new(storepath, &config)
|
||||||
};
|
};
|
||||||
|
|
||||||
store_result.map(|store| {
|
store_result.map(|store| Runtime {
|
||||||
Runtime {
|
cli_matches: matches,
|
||||||
cli_matches: matches,
|
configuration: config,
|
||||||
configuration: config,
|
rtp: rtp,
|
||||||
rtp: rtp,
|
store: store,
|
||||||
store: store,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.context(err_msg("Cannot instantiate runtime"))
|
.context(err_msg("Cannot instantiate runtime"))
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
|
@ -390,15 +388,17 @@ impl<'a> Runtime<'a> {
|
||||||
self.cli()
|
self.cli()
|
||||||
.value_of("editor")
|
.value_of("editor")
|
||||||
.map(String::from)
|
.map(String::from)
|
||||||
.or_else(|| {
|
.ok_or_else(|| {
|
||||||
self.config()
|
self.config()
|
||||||
.and_then(|v| match v.read("rt.editor") {
|
.ok_or_else(|| Error::from(err_msg("No Configuration!")))
|
||||||
Ok(Some(&Value::String(ref s))) => Some(s.clone()),
|
.and_then(|v| match v.read("rt.editor")? {
|
||||||
_ => None, // FIXME silently ignore errors in config is bad
|
Some(&Value::String(ref s)) => Ok(Some(s.clone())),
|
||||||
|
Some(_) => Err(Error::from(err_msg("Type error at 'rt.editor', expected 'String'"))),
|
||||||
|
None => Ok(None),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.or(env::var("EDITOR").ok())
|
.or(env::var("EDITOR"))
|
||||||
.ok_or_else(|| Error::from(EM::IO))
|
.map_err(|_| Error::from(EM::IO))
|
||||||
.map_dbg(|s| format!("Editing with '{}'", s))
|
.map_dbg(|s| format!("Editing with '{}'", s))
|
||||||
.and_then(|s| {
|
.and_then(|s| {
|
||||||
let mut split = s.split_whitespace();
|
let mut split = s.split_whitespace();
|
||||||
|
|
|
@ -105,15 +105,14 @@ impl FileAbstraction for FSFileAbstraction {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rename(&self, from: &PathBuf, to: &PathBuf) -> Result<()> {
|
fn rename(&self, from: &PathBuf, to: &PathBuf) -> Result<()> {
|
||||||
match to.parent() {
|
if let Some(p) = to.parent() {
|
||||||
Some(p) => if !p.exists() {
|
if !p.exists() {
|
||||||
debug!("Creating: {:?}", p);
|
debug!("Creating: {:?}", p);
|
||||||
let _ = create_dir_all(&PathBuf::from(p)).context(EM::DirNotCreated)?;
|
let _ = create_dir_all(&p).context(EM::DirNotCreated)?;
|
||||||
},
|
}
|
||||||
None => {
|
} else {
|
||||||
debug!("Failed to find parent. This looks like it will fail now");
|
debug!("Failed to find parent. This looks like it will fail now");
|
||||||
//nothing
|
//nothing
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Renaming {:?} to {:?}", from, to);
|
debug!("Renaming {:?} to {:?}", from, to);
|
||||||
|
@ -149,10 +148,9 @@ impl FileAbstraction for FSFileAbstraction {
|
||||||
/// FileAbstraction::fill implementation that consumes the Drain and writes everything to the
|
/// FileAbstraction::fill implementation that consumes the Drain and writes everything to the
|
||||||
/// filesystem
|
/// filesystem
|
||||||
fn fill(&mut self, mut d: Drain) -> Result<()> {
|
fn fill(&mut self, mut d: Drain) -> Result<()> {
|
||||||
d.iter()
|
d.iter().fold(Ok(()), |acc, (path, element)| {
|
||||||
.fold(Ok(()), |acc, (path, element)| {
|
acc.and_then(|_| self.new_instance(path).write_file_content(&element))
|
||||||
acc.and_then(|_| self.new_instance(path).write_file_content(&element))
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pathes_recursively(&self,
|
fn pathes_recursively(&self,
|
||||||
|
@ -190,11 +188,9 @@ impl PathIterBuilder for WalkDirPathIterBuilder {
|
||||||
|
|
||||||
fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<Option<File>> {
|
fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<Option<File>> {
|
||||||
match OpenOptions::new().write(true).read(true).open(p) {
|
match OpenOptions::new().write(true).read(true).open(p) {
|
||||||
Err(e) => {
|
Err(e) => match e.kind() {
|
||||||
match e.kind() {
|
::std::io::ErrorKind::NotFound => return Ok(None),
|
||||||
::std::io::ErrorKind::NotFound => return Ok(None),
|
_ => return Err(e),
|
||||||
_ => return Err(e),
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Ok(file) => Ok(Some(file))
|
Ok(file) => Ok(Some(file))
|
||||||
}
|
}
|
||||||
|
@ -205,9 +201,7 @@ fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
|
||||||
trace!("'{}' is directory = {}", parent.display(), parent.is_dir());
|
trace!("'{}' is directory = {}", parent.display(), parent.is_dir());
|
||||||
if !parent.is_dir() {
|
if !parent.is_dir() {
|
||||||
trace!("Implicitely creating directory: {:?}", parent);
|
trace!("Implicitely creating directory: {:?}", parent);
|
||||||
if let Err(e) = create_dir_all(parent) {
|
let _ = create_dir_all(parent)?;
|
||||||
return Err(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OpenOptions::new().write(true).read(true).create(true).open(p)
|
OpenOptions::new().write(true).read(true).create(true).open(p)
|
||||||
|
|
|
@ -140,7 +140,7 @@ impl FileAbstraction for InMemoryFileAbstraction {
|
||||||
let mut mtx = self.backend().lock().expect("Locking Mutex failed");
|
let mut mtx = self.backend().lock().expect("Locking Mutex failed");
|
||||||
let backend = mtx.get_mut();
|
let backend = mtx.get_mut();
|
||||||
|
|
||||||
let a = backend.get(from).cloned().ok_or_else(|| EM::FileNotFound)?;
|
let a = backend.remove(from).ok_or_else(|| EM::FileNotFound)?;
|
||||||
backend.insert(to.clone(), a);
|
backend.insert(to.clone(), a);
|
||||||
debug!("Renaming: {:?} -> {:?} worked", from, to);
|
debug!("Renaming: {:?} -> {:?} worked", from, to);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -222,11 +222,13 @@ impl Store {
|
||||||
|
|
||||||
debug!("Creating id: '{}'", id);
|
debug!("Creating id: '{}'", id);
|
||||||
|
|
||||||
let exists = id.exists()? || self.entries
|
let exists =
|
||||||
.read()
|
self.entries
|
||||||
.map(|map| map.contains_key(&id))
|
.read()
|
||||||
.map_err(|_| Error::from(EM::LockError))
|
.map(|map| map.contains_key(&id))
|
||||||
.context(format_err!("CreateCallError: {}", id))?;
|
.map_err(|_| Error::from(EM::LockError))
|
||||||
|
.context(format_err!("CreateCallError: {}", id))? ||
|
||||||
|
self.backend.exists(&id.clone().into_pathbuf()?)?;
|
||||||
|
|
||||||
if exists {
|
if exists {
|
||||||
debug!("Entry exists: {:?}", id);
|
debug!("Entry exists: {:?}", id);
|
||||||
|
@ -304,11 +306,14 @@ impl Store {
|
||||||
|
|
||||||
debug!("Getting id: '{}'", id);
|
debug!("Getting id: '{}'", id);
|
||||||
|
|
||||||
let exists = id.exists()? || self.entries
|
let exists =
|
||||||
.read()
|
self.entries
|
||||||
.map(|map| map.contains_key(&id))
|
.read()
|
||||||
.map_err(|_| Error::from(EM::LockError))
|
.map(|map| map.contains_key(&id))
|
||||||
.context(format_err!("GetCallError: {}", id))?;
|
.map_err(|_| Error::from(EM::LockError))
|
||||||
|
.context(format_err!("CreateCallError: {}", id))? ||
|
||||||
|
self.backend.exists(&id.clone().into_pathbuf()?)?;
|
||||||
|
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
debug!("Does not exist in internal cache or filesystem: {:?}", id);
|
debug!("Does not exist in internal cache or filesystem: {:?}", id);
|
||||||
|
@ -676,8 +681,10 @@ impl<'a> FileLockEntry<'a, > {
|
||||||
|
|
||||||
impl<'a> Debug for FileLockEntry<'a> {
|
impl<'a> Debug for FileLockEntry<'a> {
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FMTError> {
|
fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FMTError> {
|
||||||
write!(fmt, "FileLockEntry(Store = {})", self.store.location.to_str()
|
write!(fmt,
|
||||||
.unwrap_or("Unknown Path"))
|
"FileLockEntry(Store = {store}, location = {location:?})",
|
||||||
|
store = self.store.location.to_str().unwrap_or("Unknown Path"),
|
||||||
|
location = self.entry.get_location())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1214,10 +1221,13 @@ mod store_tests {
|
||||||
assert!(store.entries.read().unwrap().get(&id_mv_with_base).is_some());
|
assert!(store.entries.read().unwrap().get(&id_mv_with_base).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(match store.get(id.clone()) { Ok(None) => true, _ => false },
|
let res = store.get(id.clone());
|
||||||
"Moved id ({:?}) is still there", id);
|
assert!(match res { Ok(None) => true, _ => false },
|
||||||
assert!(match store.get(id_mv.clone()) { Ok(Some(_)) => true, _ => false },
|
"Moved id ({:?}) is still there: {:?}", id, res);
|
||||||
"New id ({:?}) is not in store...", id_mv);
|
|
||||||
|
let res = store.get(id_mv.clone());
|
||||||
|
assert!(match res { Ok(Some(_)) => true, _ => false },
|
||||||
|
"New id ({:?}) is not in store: {:?}", id_mv, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,8 +69,14 @@ pub fn entry_buffer_to_header_content(buf: &str) -> Result<(Value, String)> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
extern crate env_logger;
|
||||||
|
|
||||||
use super::entry_buffer_to_header_content;
|
use super::entry_buffer_to_header_content;
|
||||||
|
|
||||||
|
fn setup_logging() {
|
||||||
|
let _ = env_logger::try_init();
|
||||||
|
}
|
||||||
|
|
||||||
fn mkfile(content: &str) -> String {
|
fn mkfile(content: &str) -> String {
|
||||||
format!(r#"---
|
format!(r#"---
|
||||||
[imag]
|
[imag]
|
||||||
|
@ -97,16 +103,17 @@ version = '{version}'
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_entry_buffer_to_header_content_2() {
|
fn test_entry_buffer_to_header_content_2() {
|
||||||
|
setup_logging();
|
||||||
let content = r#"Hai
|
let content = r#"Hai
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let file = mkfile(&content);
|
let file = mkfile(&content);
|
||||||
eprintln!("FILE: <<<{}>>>", file);
|
debug!("FILE: <<<{}>>>", file);
|
||||||
let res = entry_buffer_to_header_content(&file);
|
let res = entry_buffer_to_header_content(&file);
|
||||||
|
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let (_, res_content) = res.unwrap();
|
let (_, res_content) = res.unwrap();
|
||||||
eprintln!("CONTENT: <<<{}>>>", res_content);
|
debug!("CONTENT: <<<{}>>>", res_content);
|
||||||
assert_eq!(res_content, content)
|
assert_eq!(res_content, content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,4 +194,8 @@ impl<'a> Mail<'a> {
|
||||||
self.get_field("In-Reply-To")
|
self.get_field("In-Reply-To")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fle(&self) -> &FileLockEntry<'a> {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,6 @@ impl<'a> TaskStore<'a> for Store {
|
||||||
// the change. The (maybe modified) second one is
|
// the change. The (maybe modified) second one is
|
||||||
// expected by taskwarrior.
|
// expected by taskwarrior.
|
||||||
let val = serde_to_string(&ttask).context(err_msg("Import error"))?;
|
let val = serde_to_string(&ttask).context(err_msg("Import error"))?;
|
||||||
println!("{}", val);
|
|
||||||
|
|
||||||
// Taskwarrior does not have the concept of deleted tasks, but only modified
|
// Taskwarrior does not have the concept of deleted tasks, but only modified
|
||||||
// ones.
|
// ones.
|
||||||
|
|
Loading…
Reference in a new issue