more style adaptations
again following clippy
This commit is contained in:
parent
7a46df3125
commit
981707c9c9
29 changed files with 298 additions and 352 deletions
|
@ -15,29 +15,29 @@ pub enum LinkErrorKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link_error_type_as_str(e: &LinkErrorKind) -> &'static str {
|
fn link_error_type_as_str(e: &LinkErrorKind) -> &'static str {
|
||||||
match e {
|
match *e {
|
||||||
&LinkErrorKind::EntryHeaderReadError
|
LinkErrorKind::EntryHeaderReadError
|
||||||
=> "Error while reading an entry header",
|
=> "Error while reading an entry header",
|
||||||
|
|
||||||
&LinkErrorKind::EntryHeaderWriteError
|
LinkErrorKind::EntryHeaderWriteError
|
||||||
=> "Error while writing an entry header",
|
=> "Error while writing an entry header",
|
||||||
|
|
||||||
&LinkErrorKind::ExistingLinkTypeWrong
|
LinkErrorKind::ExistingLinkTypeWrong
|
||||||
=> "Existing link entry has wrong type",
|
=> "Existing link entry has wrong type",
|
||||||
|
|
||||||
&LinkErrorKind::LinkTargetDoesNotExist
|
LinkErrorKind::LinkTargetDoesNotExist
|
||||||
=> "Link target does not exist in the store",
|
=> "Link target does not exist in the store",
|
||||||
|
|
||||||
&LinkErrorKind::InternalConversionError
|
LinkErrorKind::InternalConversionError
|
||||||
=> "Error while converting values internally",
|
=> "Error while converting values internally",
|
||||||
|
|
||||||
&LinkErrorKind::InvalidUri
|
LinkErrorKind::InvalidUri
|
||||||
=> "URI is not valid",
|
=> "URI is not valid",
|
||||||
|
|
||||||
&LinkErrorKind::StoreReadError
|
LinkErrorKind::StoreReadError
|
||||||
=> "Store read error",
|
=> "Store read error",
|
||||||
|
|
||||||
&LinkErrorKind::StoreWriteError
|
LinkErrorKind::StoreWriteError
|
||||||
=> "Store write error",
|
=> "Store write error",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ use url::Url;
|
||||||
use crypto::sha1::Sha1;
|
use crypto::sha1::Sha1;
|
||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
|
|
||||||
/// "Link" Type, just an abstraction over FileLockEntry to have some convenience internally.
|
/// "Link" Type, just an abstraction over `FileLockEntry` to have some convenience internally.
|
||||||
struct Link<'a> {
|
struct Link<'a> {
|
||||||
link: FileLockEntry<'a>
|
link: FileLockEntry<'a>
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ impl<'a> Link<'a> {
|
||||||
.map_err(|e| LE::new(LEK::StoreReadError, Some(Box::new(e))))
|
.map_err(|e| LE::new(LEK::StoreReadError, Some(Box::new(e))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a link Url object from a FileLockEntry, ignore errors.
|
/// Get a link Url object from a `FileLockEntry`, ignore errors.
|
||||||
fn get_link_uri_from_filelockentry(file: &FileLockEntry<'a>) -> Option<Url> {
|
fn get_link_uri_from_filelockentry(file: &FileLockEntry<'a>) -> Option<Url> {
|
||||||
file.get_header()
|
file.get_header()
|
||||||
.read("imag.content.uri")
|
.read("imag.content.uri")
|
||||||
|
@ -78,7 +78,7 @@ impl<'a> Link<'a> {
|
||||||
match opt {
|
match opt {
|
||||||
Ok(Some(Value::String(s))) => {
|
Ok(Some(Value::String(s))) => {
|
||||||
Url::parse(&s[..])
|
Url::parse(&s[..])
|
||||||
.map(|s| Some(s))
|
.map(Some)
|
||||||
.map_err(|e| LE::new(LEK::EntryHeaderReadError, Some(Box::new(e))))
|
.map_err(|e| LE::new(LEK::EntryHeaderReadError, Some(Box::new(e))))
|
||||||
},
|
},
|
||||||
Ok(None) => Ok(None),
|
Ok(None) => Ok(None),
|
||||||
|
@ -115,7 +115,7 @@ fn get_external_link_from_file(entry: &FileLockEntry) -> Result<Url> {
|
||||||
.ok_or(LE::new(LEK::StoreReadError, None))
|
.ok_or(LE::new(LEK::StoreReadError, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implement ExternalLinker for Entry, hiding the fact that there is no such thing as an external
|
/// Implement `ExternalLinker` for `Entry`, hiding the fact that there is no such thing as an external
|
||||||
/// link in an entry, but internal links to other entries which serve as external links, as one
|
/// link in an entry, but internal links to other entries which serve as external links, as one
|
||||||
/// entry in the store can only have one external link.
|
/// entry in the store can only have one external link.
|
||||||
impl ExternalLinker for Entry {
|
impl ExternalLinker for Entry {
|
||||||
|
|
|
@ -92,9 +92,9 @@ impl InternalLinker for Entry {
|
||||||
fn links_into_values(links: Vec<StoreId>) -> Vec<Option<Value>> {
|
fn links_into_values(links: Vec<StoreId>) -> Vec<Option<Value>> {
|
||||||
links
|
links
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|s| s.to_str().map(|s| String::from(s)))
|
.map(|s| s.to_str().map(String::from))
|
||||||
.unique()
|
.unique()
|
||||||
.map(|elem| elem.map(|s| Value::String(s)))
|
.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),
|
(&Some(Value::String(ref a)), &Some(Value::String(ref b))) => Ord::cmp(a, b),
|
||||||
|
@ -160,7 +160,7 @@ fn process_rw_result(links: StoreResult<Option<Value>>) -> Result<Vec<Link>> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !links.iter().all(|l| match l { &Value::String(_) => true, _ => false }) {
|
if !links.iter().all(|l| match *l { Value::String(_) => true, _ => false }) {
|
||||||
debug!("At least one of the Values which were expected in the Array of links is a non-String!");
|
debug!("At least one of the Values which were expected in the Array of links is a non-String!");
|
||||||
debug!("Generating LinkError");
|
debug!("Generating LinkError");
|
||||||
return Err(LinkError::new(LinkErrorKind::ExistingLinkTypeWrong, None));
|
return Err(LinkError::new(LinkErrorKind::ExistingLinkTypeWrong, None));
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::Error as FmtError;
|
use std::fmt::Error as FmtError;
|
||||||
use std::clone::Clone;
|
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,11 +14,11 @@ pub enum ListErrorKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn counter_error_type_as_str(err: &ListErrorKind) -> &'static str{
|
fn counter_error_type_as_str(err: &ListErrorKind) -> &'static str{
|
||||||
match err {
|
match *err {
|
||||||
&ListErrorKind::FormatError => "FormatError",
|
ListErrorKind::FormatError => "FormatError",
|
||||||
&ListErrorKind::EntryError => "EntryError",
|
ListErrorKind::EntryError => "EntryError",
|
||||||
&ListErrorKind::IterationError => "IterationError",
|
ListErrorKind::IterationError => "IterationError",
|
||||||
&ListErrorKind::CLIError => "No CLI subcommand for listing entries",
|
ListErrorKind::CLIError => "No CLI subcommand for listing entries",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +56,7 @@ impl ListError {
|
||||||
* Get the error type of this ListError
|
* Get the error type of this ListError
|
||||||
*/
|
*/
|
||||||
pub fn err_type(&self) -> ListErrorKind {
|
pub fn err_type(&self) -> ListErrorKind {
|
||||||
self.err_type.clone()
|
self.err_type
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -65,7 +64,7 @@ impl ListError {
|
||||||
impl Display for ListError {
|
impl Display for ListError {
|
||||||
|
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
||||||
try!(write!(fmt, "[{}]", counter_error_type_as_str(&self.err_type.clone())));
|
try!(write!(fmt, "[{}]", counter_error_type_as_str(&self.err_type)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +73,7 @@ impl Display for ListError {
|
||||||
impl Error for ListError {
|
impl Error for ListError {
|
||||||
|
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
counter_error_type_as_str(&self.err_type.clone())
|
counter_error_type_as_str(&self.err_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cause(&self) -> Option<&Error> {
|
fn cause(&self) -> Option<&Error> {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::Error as FmtError;
|
use std::fmt::Error as FmtError;
|
||||||
use std::clone::Clone;
|
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
@ -12,11 +11,11 @@ pub enum TagErrorKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tag_error_type_as_str(e: &TagErrorKind) -> &'static str {
|
fn tag_error_type_as_str(e: &TagErrorKind) -> &'static str {
|
||||||
match e {
|
match *e {
|
||||||
&TagErrorKind::TagTypeError => "Entry Header Tag Type wrong",
|
TagErrorKind::TagTypeError => "Entry Header Tag Type wrong",
|
||||||
&TagErrorKind::HeaderReadError => "Error while reading entry header",
|
TagErrorKind::HeaderReadError => "Error while reading entry header",
|
||||||
&TagErrorKind::HeaderWriteError => "Error while writing entry header",
|
TagErrorKind::HeaderWriteError => "Error while writing entry header",
|
||||||
&TagErrorKind::NotATag => "String is not a tag",
|
TagErrorKind::NotATag => "String is not a tag",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +48,7 @@ impl TagError {
|
||||||
impl Display for TagError {
|
impl Display for TagError {
|
||||||
|
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
||||||
try!(write!(fmt, "[{}]", tag_error_type_as_str(&self.kind.clone())));
|
try!(write!(fmt, "[{}]", tag_error_type_as_str(&self.kind)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +57,7 @@ impl Display for TagError {
|
||||||
impl Error for TagError {
|
impl Error for TagError {
|
||||||
|
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
tag_error_type_as_str(&self.kind.clone())
|
tag_error_type_as_str(&self.kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cause(&self) -> Option<&Error> {
|
fn cause(&self) -> Option<&Error> {
|
||||||
|
|
|
@ -7,22 +7,20 @@ use tagable::*;
|
||||||
use ui::{get_add_tags, get_remove_tags};
|
use ui::{get_add_tags, get_remove_tags};
|
||||||
|
|
||||||
pub fn exec_cli_for_entry(matches: &ArgMatches, entry: &mut FileLockEntry) -> Result<()> {
|
pub fn exec_cli_for_entry(matches: &ArgMatches, entry: &mut FileLockEntry) -> Result<()> {
|
||||||
match get_add_tags(matches) {
|
if let Some(ts) = get_add_tags(matches) {
|
||||||
Some(ts) => for t in ts {
|
for t in ts {
|
||||||
if let Err(e) = entry.add_tag(t) {
|
if let Err(e) = entry.add_tag(t) {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
None => { },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match get_remove_tags(matches) {
|
if let Some(ts) = get_remove_tags(matches) {
|
||||||
Some(ts) => for t in ts {
|
for t in ts {
|
||||||
if let Err(e) = entry.remove_tag(t) {
|
if let Err(e) = entry.remove_tag(t) {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
None => { },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
pub type Tag = String;
|
pub type Tag = String;
|
||||||
|
pub type TagSlice<'a> = &'a str;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use libimagstore::store::{Entry, EntryHeader, FileLockEntry};
|
||||||
|
|
||||||
use error::{TagError, TagErrorKind};
|
use error::{TagError, TagErrorKind};
|
||||||
use result::Result;
|
use result::Result;
|
||||||
use tag::Tag;
|
use tag::{Tag, TagSlice};
|
||||||
use util::is_tag;
|
use util::is_tag;
|
||||||
|
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
|
@ -15,13 +15,13 @@ use toml::Value;
|
||||||
pub trait Tagable {
|
pub trait Tagable {
|
||||||
|
|
||||||
fn get_tags(&self) -> Result<Vec<Tag>>;
|
fn get_tags(&self) -> Result<Vec<Tag>>;
|
||||||
fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()>;
|
fn set_tags(&mut self, ts: &[Tag]) -> Result<()>;
|
||||||
|
|
||||||
fn add_tag(&mut self, t: Tag) -> Result<()>;
|
fn add_tag(&mut self, t: Tag) -> Result<()>;
|
||||||
fn remove_tag(&mut self, t: Tag) -> Result<()>;
|
fn remove_tag(&mut self, t: Tag) -> Result<()>;
|
||||||
|
|
||||||
fn has_tag(&self, t: &Tag) -> Result<bool>;
|
fn has_tag(&self, t: TagSlice) -> Result<bool>;
|
||||||
fn has_tags(&self, ts: &Vec<Tag>) -> Result<bool>;
|
fn has_tags(&self, ts: &[Tag]) -> Result<bool>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,11 +37,11 @@ impl Tagable for EntryHeader {
|
||||||
|
|
||||||
match tags {
|
match tags {
|
||||||
Some(Value::Array(tags)) => {
|
Some(Value::Array(tags)) => {
|
||||||
if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
|
if !tags.iter().all(|t| match *t { Value::String(_) => true, _ => false }) {
|
||||||
return Err(TagError::new(TagErrorKind::TagTypeError, None));
|
return Err(TagError::new(TagErrorKind::TagTypeError, None));
|
||||||
}
|
}
|
||||||
if tags.iter().any(|t| match t {
|
if tags.iter().any(|t| match *t {
|
||||||
&Value::String(ref s) => !is_tag(&s),
|
Value::String(ref s) => !is_tag(s),
|
||||||
_ => unreachable!()})
|
_ => unreachable!()})
|
||||||
{
|
{
|
||||||
return Err(TagError::new(TagErrorKind::NotATag, None));
|
return Err(TagError::new(TagErrorKind::NotATag, None));
|
||||||
|
@ -62,7 +62,7 @@ impl Tagable for EntryHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()> {
|
fn set_tags(&mut self, ts: &[Tag]) -> Result<()> {
|
||||||
if ts.iter().any(|tag| !is_tag(tag)) {
|
if ts.iter().any(|tag| !is_tag(tag)) {
|
||||||
debug!("Not a tag: '{}'", ts.iter().filter(|t| !is_tag(t)).next().unwrap());
|
debug!("Not a tag: '{}'", ts.iter().filter(|t| !is_tag(t)).next().unwrap());
|
||||||
return Err(TagError::new(TagErrorKind::NotATag, None));
|
return Err(TagError::new(TagErrorKind::NotATag, None));
|
||||||
|
@ -83,7 +83,7 @@ impl Tagable for EntryHeader {
|
||||||
self.get_tags()
|
self.get_tags()
|
||||||
.map(|mut tags| {
|
.map(|mut tags| {
|
||||||
tags.push(t);
|
tags.push(t);
|
||||||
self.set_tags(tags.into_iter().unique().collect())
|
self.set_tags(&tags.into_iter().unique().collect::<Vec<_>>()[..])
|
||||||
})
|
})
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
@ -97,12 +97,12 @@ impl Tagable for EntryHeader {
|
||||||
self.get_tags()
|
self.get_tags()
|
||||||
.map(|mut tags| {
|
.map(|mut tags| {
|
||||||
tags.retain(|tag| tag.clone() != t);
|
tags.retain(|tag| tag.clone() != t);
|
||||||
self.set_tags(tags)
|
self.set_tags(&tags[..])
|
||||||
})
|
})
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_tag(&self, t: &Tag) -> Result<bool> {
|
fn has_tag(&self, t: TagSlice) -> Result<bool> {
|
||||||
let tags = self.read("imag.tags");
|
let tags = self.read("imag.tags");
|
||||||
if tags.is_err() {
|
if tags.is_err() {
|
||||||
let kind = TagErrorKind::HeaderReadError;
|
let kind = TagErrorKind::HeaderReadError;
|
||||||
|
@ -110,21 +110,21 @@ impl Tagable for EntryHeader {
|
||||||
}
|
}
|
||||||
let tags = tags.unwrap();
|
let tags = tags.unwrap();
|
||||||
|
|
||||||
if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
|
if !tags.iter().all(|t| match *t { Value::String(_) => true, _ => false }) {
|
||||||
return Err(TagError::new(TagErrorKind::TagTypeError, None));
|
return Err(TagError::new(TagErrorKind::TagTypeError, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(tags
|
Ok(tags
|
||||||
.iter()
|
.iter()
|
||||||
.any(|tag| {
|
.any(|tag| {
|
||||||
match tag {
|
match *tag {
|
||||||
&Value::String(ref s) => { s == t },
|
Value::String(ref s) => { s == t },
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_tags(&self, tags: &Vec<Tag>) -> Result<bool> {
|
fn has_tags(&self, tags: &[Tag]) -> Result<bool> {
|
||||||
let mut result = true;
|
let mut result = true;
|
||||||
for tag in tags {
|
for tag in tags {
|
||||||
let check = self.has_tag(tag);
|
let check = self.has_tag(tag);
|
||||||
|
@ -147,7 +147,7 @@ impl Tagable for Entry {
|
||||||
self.get_header().get_tags()
|
self.get_header().get_tags()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()> {
|
fn set_tags(&mut self, ts: &[Tag]) -> Result<()> {
|
||||||
self.get_header_mut().set_tags(ts)
|
self.get_header_mut().set_tags(ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +159,11 @@ impl Tagable for Entry {
|
||||||
self.get_header_mut().remove_tag(t)
|
self.get_header_mut().remove_tag(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_tag(&self, t: &Tag) -> Result<bool> {
|
fn has_tag(&self, t: TagSlice) -> Result<bool> {
|
||||||
self.get_header().has_tag(t)
|
self.get_header().has_tag(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_tags(&self, ts: &Vec<Tag>) -> Result<bool> {
|
fn has_tags(&self, ts: &[Tag]) -> Result<bool> {
|
||||||
self.get_header().has_tags(ts)
|
self.get_header().has_tags(ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ impl<'a> Tagable for FileLockEntry<'a> {
|
||||||
self.deref().get_tags()
|
self.deref().get_tags()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()> {
|
fn set_tags(&mut self, ts: &[Tag]) -> Result<()> {
|
||||||
self.deref_mut().set_tags(ts)
|
self.deref_mut().set_tags(ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,11 +187,11 @@ impl<'a> Tagable for FileLockEntry<'a> {
|
||||||
self.deref_mut().remove_tag(t)
|
self.deref_mut().remove_tag(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_tag(&self, t: &Tag) -> Result<bool> {
|
fn has_tag(&self, t: TagSlice) -> Result<bool> {
|
||||||
self.deref().has_tag(t)
|
self.deref().has_tag(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_tags(&self, ts: &Vec<Tag>) -> Result<bool> {
|
fn has_tags(&self, ts: &[Tag]) -> Result<bool> {
|
||||||
self.deref().has_tags(ts)
|
self.deref().has_tags(ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use clap::{Arg, ArgMatches, App, SubCommand};
|
||||||
|
|
||||||
use tag::Tag;
|
use tag::Tag;
|
||||||
|
|
||||||
/// Generates a clap::SubCommand to be integrated in the commandline-ui builder for building a
|
/// Generates a `clap::SubCommand` to be integrated in the commandline-ui builder for building a
|
||||||
/// "tags --add foo --remove bar" subcommand to do tagging action.
|
/// "tags --add foo --remove bar" subcommand to do tagging action.
|
||||||
pub fn tag_subcommand<'a, 'b>() -> App<'a, 'b> {
|
pub fn tag_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
SubCommand::with_name(tag_subcommand_name())
|
SubCommand::with_name(tag_subcommand_name())
|
||||||
|
@ -41,7 +41,7 @@ pub fn tag_subcommand_names() -> Vec<&'static str> {
|
||||||
vec![tag_subcommand_add_arg_name(), tag_subcommand_remove_arg_name()]
|
vec![tag_subcommand_add_arg_name(), tag_subcommand_remove_arg_name()]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a clap::Arg which can be integrated into the commandline-ui builder for building a
|
/// Generates a `clap::Arg` which can be integrated into the commandline-ui builder for building a
|
||||||
/// "-t" or "--tags" argument which takes values for tagging actions (add, remove)
|
/// "-t" or "--tags" argument which takes values for tagging actions (add, remove)
|
||||||
pub fn tag_argument<'a, 'b>() -> Arg<'a, 'b> {
|
pub fn tag_argument<'a, 'b>() -> Arg<'a, 'b> {
|
||||||
Arg::with_name(tag_argument_name())
|
Arg::with_name(tag_argument_name())
|
||||||
|
@ -79,7 +79,7 @@ fn extract_tags(matches: &ArgMatches, specifier: &str, specchar: char) -> Option
|
||||||
.map(|argmatches| {
|
.map(|argmatches| {
|
||||||
argmatches
|
argmatches
|
||||||
.map(String::from)
|
.map(String::from)
|
||||||
.filter(|s| s.chars().next() == Some(specchar))
|
.filter(|s| s.starts_with(specchar))
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
String::from(s.split_at(1).1)
|
String::from(s.split_at(1).1)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
pub fn is_tag(s: &String) -> bool {
|
pub fn is_tag(s: &str) -> bool {
|
||||||
Regex::new("^[a-zA-Z]([a-zA-Z0-9_-]*)$").unwrap().captures(&s[..]).is_some()
|
Regex::new("^[a-zA-Z]([a-zA-Z0-9_-]*)$").unwrap().captures(&s[..]).is_some()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::Error as FmtError;
|
use std::fmt::Error as FmtError;
|
||||||
use std::clone::Clone;
|
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,7 +51,7 @@ impl ViewError {
|
||||||
* Get the error type of this ViewError
|
* Get the error type of this ViewError
|
||||||
*/
|
*/
|
||||||
pub fn err_type(&self) -> ViewErrorKind {
|
pub fn err_type(&self) -> ViewErrorKind {
|
||||||
self.err_type.clone()
|
self.err_type
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -60,7 +59,7 @@ impl ViewError {
|
||||||
impl Display for ViewError {
|
impl Display for ViewError {
|
||||||
|
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
||||||
try!(write!(fmt, "[{}]", counter_error_type_as_str(&self.err_type.clone())));
|
try!(write!(fmt, "[{}]", counter_error_type_as_str(&self.err_type)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +68,7 @@ impl Display for ViewError {
|
||||||
impl Error for ViewError {
|
impl Error for ViewError {
|
||||||
|
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
counter_error_type_as_str(&self.err_type.clone())
|
counter_error_type_as_str(&self.err_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cause(&self) -> Option<&Error> {
|
fn cause(&self) -> Option<&Error> {
|
||||||
|
|
|
@ -40,15 +40,12 @@ fn ask_bool_<R: BufRead>(s: &str, default: Option<bool>, input: &mut R) -> bool
|
||||||
return true
|
return true
|
||||||
} else if R_NO.is_match(&s[..]) {
|
} else if R_NO.is_match(&s[..]) {
|
||||||
return false
|
return false
|
||||||
} else {
|
} else if default.is_some() {
|
||||||
if default.is_some() {
|
|
||||||
return default.unwrap();
|
return default.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// else again...
|
// else again...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Ask the user for an unsigned number. Optionally provide a default value. If none is provided,
|
/// Ask the user for an unsigned number. Optionally provide a default value. If none is provided,
|
||||||
/// this keeps loop{}ing
|
/// this keeps loop{}ing
|
||||||
|
@ -123,18 +120,17 @@ pub fn ask_string_<R: BufRead>(s: &str,
|
||||||
let _ = input.read_line(&mut s);
|
let _ = input.read_line(&mut s);
|
||||||
|
|
||||||
if permit_multiline {
|
if permit_multiline {
|
||||||
if permit_multiline && eof.map(|e| e == s).unwrap_or(false) {
|
if permit_multiline && eof.map_or(false, |e| e == s) {
|
||||||
return v.join("\n");
|
return v.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if permit_empty || v.len() != 0 {
|
if permit_empty || !v.is_empty() {
|
||||||
v.push(s);
|
v.push(s);
|
||||||
}
|
}
|
||||||
print!("{}", prompt);
|
print!("{}", prompt);
|
||||||
} else {
|
} else if s.is_empty() && permit_empty {
|
||||||
if s.len() == 0 && permit_empty {
|
|
||||||
return s;
|
return s;
|
||||||
} else if s.len() == 0 && !permit_empty {
|
} else if s.is_empty() && !permit_empty {
|
||||||
if default.is_some() {
|
if default.is_some() {
|
||||||
return default.unwrap();
|
return default.unwrap();
|
||||||
} else {
|
} else {
|
||||||
|
@ -145,7 +141,6 @@ pub fn ask_string_<R: BufRead>(s: &str,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ask_select_from_list(list: &[&str]) -> Result<String> {
|
pub fn ask_select_from_list(list: &[&str]) -> Result<String> {
|
||||||
pick_from_list(default_menu_cmd().as_mut(), list, "Selection: ")
|
pick_from_list(default_menu_cmd().as_mut(), list, "Selection: ")
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::Error as FmtError;
|
use std::fmt::Error as FmtError;
|
||||||
use std::clone::Clone;
|
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,8 +11,8 @@ pub enum InteractionErrorKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interaction_error_type_as_str(e: &InteractionErrorKind) -> &'static str {
|
fn interaction_error_type_as_str(e: &InteractionErrorKind) -> &'static str {
|
||||||
match e {
|
match *e {
|
||||||
&InteractionErrorKind::Unknown => "Unknown Error",
|
InteractionErrorKind::Unknown => "Unknown Error",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ impl InteractionError {
|
||||||
* Get the error type of this InteractionError
|
* Get the error type of this InteractionError
|
||||||
*/
|
*/
|
||||||
pub fn err_type(&self) -> InteractionErrorKind {
|
pub fn err_type(&self) -> InteractionErrorKind {
|
||||||
self.err_type.clone()
|
self.err_type
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -58,7 +57,7 @@ impl InteractionError {
|
||||||
impl Display for InteractionError {
|
impl Display for InteractionError {
|
||||||
|
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
||||||
try!(write!(fmt, "[{}]", interaction_error_type_as_str(&self.err_type.clone())));
|
try!(write!(fmt, "[{}]", interaction_error_type_as_str(&self.err_type)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +66,7 @@ impl Display for InteractionError {
|
||||||
impl Error for InteractionError {
|
impl Error for InteractionError {
|
||||||
|
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
interaction_error_type_as_str(&self.err_type.clone())
|
interaction_error_type_as_str(&self.err_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cause(&self) -> Option<&Error> {
|
fn cause(&self) -> Option<&Error> {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::Error as FmtError;
|
use std::fmt::Error as FmtError;
|
||||||
use std::clone::Clone;
|
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,11 +15,11 @@ pub enum NoteErrorKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn note_error_type_as_str(e: &NoteErrorKind) -> &'static str {
|
fn note_error_type_as_str(e: &NoteErrorKind) -> &'static str {
|
||||||
match e {
|
match *e {
|
||||||
&NoteErrorKind::StoreWriteError => "Error writing store",
|
NoteErrorKind::StoreWriteError => "Error writing store",
|
||||||
&NoteErrorKind::StoreReadError => "Error reading store",
|
NoteErrorKind::StoreReadError => "Error reading store",
|
||||||
&NoteErrorKind::HeaderTypeError => "Header type error",
|
NoteErrorKind::HeaderTypeError => "Header type error",
|
||||||
&NoteErrorKind::NoteToEntryConversion => "Error converting Note instance to Entry instance",
|
NoteErrorKind::NoteToEntryConversion => "Error converting Note instance to Entry instance",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +57,7 @@ impl NoteError {
|
||||||
* Get the error type of this NoteError
|
* Get the error type of this NoteError
|
||||||
*/
|
*/
|
||||||
pub fn err_type(&self) -> NoteErrorKind {
|
pub fn err_type(&self) -> NoteErrorKind {
|
||||||
self.err_type.clone()
|
self.err_type
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -66,7 +65,7 @@ impl NoteError {
|
||||||
impl Display for NoteError {
|
impl Display for NoteError {
|
||||||
|
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
||||||
try!(write!(fmt, "[{}]", note_error_type_as_str(&self.err_type.clone())));
|
try!(write!(fmt, "[{}]", note_error_type_as_str(&self.err_type)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +74,7 @@ impl Display for NoteError {
|
||||||
impl Error for NoteError {
|
impl Error for NoteError {
|
||||||
|
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
note_error_type_as_str(&self.err_type.clone())
|
note_error_type_as_str(&self.err_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cause(&self) -> Option<&Error> {
|
fn cause(&self) -> Option<&Error> {
|
||||||
|
|
|
@ -10,7 +10,7 @@ use libimagstore::storeid::StoreId;
|
||||||
use libimagstore::storeid::StoreIdIterator;
|
use libimagstore::storeid::StoreIdIterator;
|
||||||
use libimagstore::store::FileLockEntry;
|
use libimagstore::store::FileLockEntry;
|
||||||
use libimagstore::store::Store;
|
use libimagstore::store::Store;
|
||||||
use libimagentrytag::tag::Tag;
|
use libimagentrytag::tag::{Tag, TagSlice};
|
||||||
use libimagentrytag::tagable::Tagable;
|
use libimagentrytag::tagable::Tagable;
|
||||||
use libimagentrytag::result::Result as TagResult;
|
use libimagentrytag::result::Result as TagResult;
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ impl<'a> Tagable for Note<'a> {
|
||||||
self.entry.get_tags()
|
self.entry.get_tags()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_tags(&mut self, ts: Vec<Tag>) -> TagResult<()> {
|
fn set_tags(&mut self, ts: &[Tag]) -> TagResult<()> {
|
||||||
self.entry.set_tags(ts)
|
self.entry.set_tags(ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,23 +136,23 @@ impl<'a> Tagable for Note<'a> {
|
||||||
self.entry.remove_tag(t)
|
self.entry.remove_tag(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_tag(&self, t: &Tag) -> TagResult<bool> {
|
fn has_tag(&self, t: TagSlice) -> TagResult<bool> {
|
||||||
self.entry.has_tag(t)
|
self.entry.has_tag(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_tags(&self, ts: &Vec<Tag>) -> TagResult<bool> {
|
fn has_tags(&self, ts: &[Tag]) -> TagResult<bool> {
|
||||||
self.entry.has_tags(ts)
|
self.entry.has_tags(ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait FromStoreId {
|
trait FromStoreId {
|
||||||
fn from_storeid<'a>(&'a Store, StoreId) -> Result<Note<'a>>;
|
fn from_storeid(&Store, StoreId) -> Result<Note>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromStoreId for Note<'a> {
|
impl<'a> FromStoreId for Note<'a> {
|
||||||
|
|
||||||
fn from_storeid<'b>(store: &'b Store, id: StoreId) -> Result<Note<'b>> {
|
fn from_storeid(store: &Store, id: StoreId) -> Result<Note> {
|
||||||
debug!("Loading note from storeid: '{:?}'", id);
|
debug!("Loading note from storeid: '{:?}'", id);
|
||||||
match store.retrieve(id) {
|
match store.retrieve(id) {
|
||||||
Err(e) => Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))),
|
Err(e) => Err(NE::new(NEK::StoreReadError, Some(Box::new(e)))),
|
||||||
|
|
|
@ -12,17 +12,13 @@ pub mod error {
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::fmt::Error as FmtError;
|
use std::fmt::Error as FmtError;
|
||||||
|
|
||||||
/**
|
/// The kind of an error
|
||||||
* The kind of an error
|
|
||||||
*/
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ConfigErrorKind {
|
pub enum ConfigErrorKind {
|
||||||
NoConfigFileFound,
|
NoConfigFileFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Configuration error type
|
||||||
* Configuration error type
|
|
||||||
*/
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ConfigError {
|
pub struct ConfigError {
|
||||||
kind: ConfigErrorKind,
|
kind: ConfigErrorKind,
|
||||||
|
@ -31,9 +27,7 @@ pub mod error {
|
||||||
|
|
||||||
impl ConfigError {
|
impl ConfigError {
|
||||||
|
|
||||||
/**
|
/// Instantiate a new `ConfigError`, optionally with cause
|
||||||
* Instantiate a new ConfigError, optionally with cause
|
|
||||||
*/
|
|
||||||
pub fn new(kind: ConfigErrorKind, cause: Option<Box<Error>>) -> ConfigError {
|
pub fn new(kind: ConfigErrorKind, cause: Option<Box<Error>>) -> ConfigError {
|
||||||
ConfigError {
|
ConfigError {
|
||||||
kind: kind,
|
kind: kind,
|
||||||
|
@ -41,16 +35,12 @@ pub mod error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
///get the Kind of the Error
|
||||||
* get the Kind of the Error
|
|
||||||
*/
|
|
||||||
pub fn err_type(&self) -> ConfigErrorKind {
|
pub fn err_type(&self) -> ConfigErrorKind {
|
||||||
self.kind.clone()
|
self.kind.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Get the string, the `ConfigError` can be described with
|
||||||
* Get the string, the ConfigError can be described with
|
|
||||||
*/
|
|
||||||
pub fn as_str(e: &ConfigError) -> &'static str {
|
pub fn as_str(e: &ConfigError) -> &'static str {
|
||||||
match e.err_type() {
|
match e.err_type() {
|
||||||
ConfigErrorKind::NoConfigFileFound => "No config file found",
|
ConfigErrorKind::NoConfigFileFound => "No config file found",
|
||||||
|
@ -86,51 +76,39 @@ use self::error::{ConfigError, ConfigErrorKind};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Result type of this module. Either T or ConfigError
|
* Result type of this module. Either `T` or `ConfigError`
|
||||||
*/
|
*/
|
||||||
pub type Result<T> = RResult<T, ConfigError>;
|
pub type Result<T> = RResult<T, ConfigError>;
|
||||||
|
|
||||||
/**
|
/// `Configuration` object
|
||||||
* Configuration object
|
///
|
||||||
*
|
/// Holds all config variables which are globally available plus the configuration object from the
|
||||||
* Holds all config variables which are globally available plus the configuration object from the
|
/// config parser, which can be accessed.
|
||||||
* config parser, which can be accessed.
|
|
||||||
*/
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
|
|
||||||
/**
|
/// The plain configuration object for direct access if necessary
|
||||||
* The plain configuration object for direct access if necessary
|
|
||||||
*/
|
|
||||||
config: Value,
|
config: Value,
|
||||||
|
|
||||||
/**
|
/// The verbosity the program should run with
|
||||||
* The verbosity the program should run with
|
|
||||||
*/
|
|
||||||
verbosity: bool,
|
verbosity: bool,
|
||||||
|
|
||||||
/**
|
/// The editor which should be used
|
||||||
* The editor which should be used
|
|
||||||
*/
|
|
||||||
editor: Option<String>,
|
editor: Option<String>,
|
||||||
|
|
||||||
/**
|
///The options the editor should get when opening some file
|
||||||
* The options the editor should get when opening some file
|
|
||||||
*/
|
|
||||||
editor_opts: String,
|
editor_opts: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Configuration {
|
impl Configuration {
|
||||||
|
|
||||||
/**
|
/// Get a new configuration object.
|
||||||
* Get a new configuration object.
|
///
|
||||||
*
|
/// The passed runtimepath is used for searching the configuration file, whereas several file
|
||||||
* The passed runtimepath is used for searching the configuration file, whereas several file
|
/// names are tested. If that does not work, the home directory and the XDG basedir are tested
|
||||||
* names are tested. If that does not work, the home directory and the XDG basedir are tested
|
/// with all variants.
|
||||||
* with all variants.
|
///
|
||||||
*
|
/// If that doesn't work either, an error is returned.
|
||||||
* If that doesn't work either, an error is returned.
|
|
||||||
*/
|
|
||||||
pub fn new(rtp: &PathBuf) -> Result<Configuration> {
|
pub fn new(rtp: &PathBuf) -> Result<Configuration> {
|
||||||
fetch_config(&rtp).map(|cfg| {
|
fetch_config(&rtp).map(|cfg| {
|
||||||
let verbosity = get_verbosity(&cfg);
|
let verbosity = get_verbosity(&cfg);
|
||||||
|
@ -161,8 +139,8 @@ impl Configuration {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store_config(&self) -> Option<&Value> {
|
pub fn store_config(&self) -> Option<&Value> {
|
||||||
match &self.config {
|
match self.config {
|
||||||
&Value::Table(ref tabl) => tabl.get("store"),
|
Value::Table(ref tabl) => tabl.get("store"),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,27 +157,26 @@ impl Deref for Configuration {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_verbosity(v: &Value) -> bool {
|
fn get_verbosity(v: &Value) -> bool {
|
||||||
match v {
|
match *v {
|
||||||
&Value::Table(ref t) => t.get("verbose")
|
Value::Table(ref t) => t.get("verbose")
|
||||||
.map(|v| match v { &Value::Boolean(b) => b, _ => false, })
|
.map_or(false, |v| match *v { Value::Boolean(b) => b, _ => false, }),
|
||||||
.unwrap_or(false),
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_editor(v: &Value) -> Option<String> {
|
fn get_editor(v: &Value) -> Option<String> {
|
||||||
match v {
|
match *v {
|
||||||
&Value::Table(ref t) => t.get("editor")
|
Value::Table(ref t) => t.get("editor")
|
||||||
.and_then(|v| match v { &Value::String(ref s) => Some(s.clone()), _ => None, }),
|
.and_then(|v| match *v { Value::String(ref s) => Some(s.clone()), _ => None, }),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_editor_opts(v: &Value) -> String {
|
fn get_editor_opts(v: &Value) -> String {
|
||||||
match v {
|
match *v {
|
||||||
&Value::Table(ref t) => t.get("editor-opts")
|
Value::Table(ref t) => t.get("editor-opts")
|
||||||
.and_then(|v| match v { &Value::String(ref s) => Some(s.clone()), _ => None, })
|
.and_then(|v| match *v { Value::String(ref s) => Some(s.clone()), _ => None, })
|
||||||
.unwrap_or(String::new()),
|
.unwrap_or_default(),
|
||||||
_ => String::new(),
|
_ => String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,7 +201,7 @@ fn fetch_config(rtp: &PathBuf) -> Result<Value> {
|
||||||
let variants = vec!["config", "config.toml", "imagrc", "imagrc.toml"];
|
let variants = vec!["config", "config.toml", "imagrc", "imagrc.toml"];
|
||||||
let modifier = |base: &PathBuf, v: &'static str| {
|
let modifier = |base: &PathBuf, v: &'static str| {
|
||||||
let mut base = base.clone();
|
let mut base = base.clone();
|
||||||
base.push(format!("{}", v));
|
base.push(String::from(v));
|
||||||
base
|
base
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -268,6 +245,6 @@ fn fetch_config(rtp: &PathBuf) -> Result<Value> {
|
||||||
.filter(|loaded| loaded.is_some())
|
.filter(|loaded| loaded.is_some())
|
||||||
.nth(0)
|
.nth(0)
|
||||||
.map(|inner| Value::Table(inner.unwrap()))
|
.map(|inner| Value::Table(inner.unwrap()))
|
||||||
.ok_or(ConfigError::new(ConfigErrorKind::NoConfigFileFound, None))
|
.ok_or_else(|| ConfigError::new(ConfigErrorKind::NoConfigFileFound, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,10 +31,10 @@ impl RuntimeError {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runtime_error_kind_as_str(e: &RuntimeErrorKind) -> &'static str {
|
fn runtime_error_kind_as_str(e: &RuntimeErrorKind) -> &'static str {
|
||||||
match e {
|
match *e {
|
||||||
&RuntimeErrorKind::Instantiate => "Could not instantiate",
|
RuntimeErrorKind::Instantiate => "Could not instantiate",
|
||||||
&RuntimeErrorKind::IOError => "IO Error",
|
RuntimeErrorKind::IOError => "IO Error",
|
||||||
&RuntimeErrorKind::ProcessExitFailure => "Process exited with failure",
|
RuntimeErrorKind::ProcessExitFailure => "Process exited with failure",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,22 +55,20 @@ impl<'a> Runtime<'a> {
|
||||||
Runtime::init_logger(is_debugging, is_verbose);
|
Runtime::init_logger(is_debugging, is_verbose);
|
||||||
|
|
||||||
let rtp : PathBuf = matches.value_of("runtimepath")
|
let rtp : PathBuf = matches.value_of("runtimepath")
|
||||||
.map(PathBuf::from)
|
.map_or_else(|| {
|
||||||
.unwrap_or_else(|| {
|
|
||||||
env::var("HOME")
|
env::var("HOME")
|
||||||
.map(PathBuf::from)
|
.map(PathBuf::from)
|
||||||
.map(|mut p| { p.push(".imag"); p})
|
.map(|mut p| { p.push(".imag"); p})
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
panic!("You seem to be $HOME-less. Please get a $HOME before using this software. We are sorry for you and hope you have some accommodation anyways.");
|
panic!("You seem to be $HOME-less. Please get a $HOME before using this software. We are sorry for you and hope you have some accommodation anyways.");
|
||||||
})
|
})
|
||||||
});
|
}, PathBuf::from);
|
||||||
let storepath = matches.value_of("storepath")
|
let storepath = matches.value_of("storepath")
|
||||||
.map(PathBuf::from)
|
.map_or_else(|| {
|
||||||
.unwrap_or({
|
|
||||||
let mut spath = rtp.clone();
|
let mut spath = rtp.clone();
|
||||||
spath.push("store");
|
spath.push("store");
|
||||||
spath
|
spath
|
||||||
});
|
}, PathBuf::from);
|
||||||
|
|
||||||
let cfg = Configuration::new(&rtp);
|
let cfg = Configuration::new(&rtp);
|
||||||
let cfg = if cfg.is_err() {
|
let cfg = if cfg.is_err() {
|
||||||
|
@ -87,9 +85,9 @@ impl<'a> Runtime<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let store_config = {
|
let store_config = {
|
||||||
match &cfg {
|
match cfg {
|
||||||
&Some(ref c) => c.store_config().map(|c| c.clone()),
|
Some(ref c) => c.store_config().cloned(),
|
||||||
&None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -268,8 +266,8 @@ impl<'a> Runtime<'a> {
|
||||||
.value_of("editor")
|
.value_of("editor")
|
||||||
.map(String::from)
|
.map(String::from)
|
||||||
.or({
|
.or({
|
||||||
match &self.configuration {
|
match self.configuration {
|
||||||
&Some(ref c) => c.editor().map(|s| s.clone()),
|
Some(ref c) => c.editor().cloned(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -51,10 +51,13 @@ pub fn config_is_valid(config: &Option<Value>) -> bool {
|
||||||
|
|
||||||
fn has_key_with_string_ary(v: &BTreeMap<String, Value>, key: &str) -> bool {
|
fn has_key_with_string_ary(v: &BTreeMap<String, Value>, key: &str) -> bool {
|
||||||
v.get(key)
|
v.get(key)
|
||||||
.map(|t| match t {
|
.map_or_else(|| {
|
||||||
&Value::Array(ref a) => a.iter().all(|elem| {
|
write!(stderr(), "Required key '{}' is not in store config", key).ok();
|
||||||
match elem {
|
false
|
||||||
&Value::String(_) => true,
|
}, |t| match *t {
|
||||||
|
Value::Array(ref a) => a.iter().all(|elem| {
|
||||||
|
match *elem {
|
||||||
|
Value::String(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -63,9 +66,6 @@ pub fn config_is_valid(config: &Option<Value>) -> bool {
|
||||||
.ok();
|
.ok();
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}).unwrap_or_else(|| {
|
|
||||||
write!(stderr(), "Required key '{}' is not in store config", key).ok();
|
|
||||||
false
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,18 +84,21 @@ pub fn config_is_valid(config: &Option<Value>) -> bool {
|
||||||
where F: Fn(&Value) -> bool
|
where F: Fn(&Value) -> bool
|
||||||
{
|
{
|
||||||
store_config.get(section) // The store config has the section `section`
|
store_config.get(section) // The store config has the section `section`
|
||||||
.map(|section_table| {
|
.map_or_else(|| {
|
||||||
match section_table { // which is
|
write!(stderr(), "Store config expects section '{}' to be present, but isn't.",
|
||||||
&Value::Table(ref section_table) => // a table
|
section).ok();
|
||||||
|
false
|
||||||
|
}, |section_table| {
|
||||||
|
match *section_table { // which is
|
||||||
|
Value::Table(ref section_table) => // a table
|
||||||
section_table
|
section_table
|
||||||
.iter() // which has values,
|
.iter() // which has values,
|
||||||
.all(|(inner_key, cfg)| { // and all of these values
|
.all(|(inner_key, cfg)| { // and all of these values
|
||||||
match cfg {
|
match *cfg {
|
||||||
&Value::Table(ref hook_config) => { // are tables
|
Value::Table(ref hook_config) => { // are tables
|
||||||
hook_config.get(key) // with a key
|
hook_config.get(key) // with a key
|
||||||
// fullfilling this constraint
|
// fullfilling this constraint
|
||||||
.map(|hook_aspect| f(&hook_aspect))
|
.map_or(false, |hook_aspect| f(&hook_aspect))
|
||||||
.unwrap_or(false)
|
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
write!(stderr(), "Store config expects '{}' to be in '{}.{}', but isn't.",
|
write!(stderr(), "Store config expects '{}' to be in '{}.{}', but isn't.",
|
||||||
|
@ -111,16 +114,10 @@ pub fn config_is_valid(config: &Option<Value>) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
|
||||||
write!(stderr(), "Store config expects section '{}' to be present, but isn't.",
|
|
||||||
section).ok();
|
|
||||||
false
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match config {
|
match *config {
|
||||||
&Some(Value::Table(ref t)) => {
|
Some(Value::Table(ref t)) => { has_key_with_string_ary(t, "pre-create-hook-aspects") &&
|
||||||
has_key_with_string_ary(t, "pre-create-hook-aspects") &&
|
|
||||||
has_key_with_string_ary(t, "post-create-hook-aspects") &&
|
has_key_with_string_ary(t, "post-create-hook-aspects") &&
|
||||||
has_key_with_string_ary(t, "pre-retrieve-hook-aspects") &&
|
has_key_with_string_ary(t, "pre-retrieve-hook-aspects") &&
|
||||||
has_key_with_string_ary(t, "post-retrieve-hook-aspects") &&
|
has_key_with_string_ary(t, "post-retrieve-hook-aspects") &&
|
||||||
|
@ -132,15 +129,13 @@ pub fn config_is_valid(config: &Option<Value>) -> bool {
|
||||||
// The section "hooks" has maps which have a key "aspect" which has a value of type
|
// The section "hooks" has maps which have a key "aspect" which has a value of type
|
||||||
// String
|
// String
|
||||||
check_all_inner_maps_have_key_with(t, "hooks", "aspect", |asp| {
|
check_all_inner_maps_have_key_with(t, "hooks", "aspect", |asp| {
|
||||||
let res = match asp { &Value::String(_) => true, _ => false };
|
match *asp { Value::String(_) => true, _ => false }
|
||||||
res
|
|
||||||
}) &&
|
}) &&
|
||||||
|
|
||||||
// The section "aspects" has maps which have a key "parllel" which has a value of type
|
// The section "aspects" has maps which have a key "parllel" which has a value of type
|
||||||
// Boolean
|
// Boolean
|
||||||
check_all_inner_maps_have_key_with(t, "aspects", "parallel", |asp| {
|
check_all_inner_maps_have_key_with(t, "aspects", "parallel", |asp| {
|
||||||
let res = match asp { &Value::Boolean(_) => true, _ => false, };
|
match *asp { Value::Boolean(_) => true, _ => false, }
|
||||||
res
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -199,16 +194,15 @@ impl AspectConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_parallel(init: &Value) -> bool {
|
fn is_parallel(init: &Value) -> bool {
|
||||||
match init {
|
match *init {
|
||||||
&Value::Table(ref t) =>
|
Value::Table(ref t) =>
|
||||||
t.get("parallel")
|
t.get("parallel")
|
||||||
.map(|value| {
|
.map_or(false, |value| {
|
||||||
match value {
|
match *value {
|
||||||
&Value::Boolean(b) => b,
|
Value::Boolean(b) => b,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
.unwrap_or(false),
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,8 +213,8 @@ impl AspectConfig {
|
||||||
///
|
///
|
||||||
/// Returns `None` if one of the keys in the chain is not available
|
/// Returns `None` if one of the keys in the chain is not available
|
||||||
pub fn get_for(v: &Option<Value>, a_name: String) -> Option<AspectConfig> {
|
pub fn get_for(v: &Option<Value>, a_name: String) -> Option<AspectConfig> {
|
||||||
match v {
|
match *v {
|
||||||
&Some(Value::Table(ref tabl)) => tabl.get(&a_name[..])
|
Some(Value::Table(ref tabl)) => tabl.get(&a_name[..])
|
||||||
.map(|asp| AspectConfig::new(asp.clone())),
|
.map(|asp| AspectConfig::new(asp.clone())),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -231,13 +225,13 @@ impl AspectConfig {
|
||||||
fn get_aspect_names_for_aspect_position(config_name: &'static str, value: &Option<Value>) -> Vec<String> {
|
fn get_aspect_names_for_aspect_position(config_name: &'static str, value: &Option<Value>) -> Vec<String> {
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
|
|
||||||
match value {
|
match *value {
|
||||||
&Some(Value::Table(ref t)) => {
|
Some(Value::Table(ref t)) => {
|
||||||
match t.get(config_name) {
|
match t.get(config_name) {
|
||||||
Some(&Value::Array(ref a)) => {
|
Some(&Value::Array(ref a)) => {
|
||||||
for elem in a {
|
for elem in a {
|
||||||
match elem {
|
match *elem {
|
||||||
&Value::String(ref s) => v.push(s.clone()),
|
Value::String(ref s) => v.push(s.clone()),
|
||||||
_ => warn!("Non-String in configuration, inside '{}'", config_name),
|
_ => warn!("Non-String in configuration, inside '{}'", config_name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,7 +239,7 @@ fn get_aspect_names_for_aspect_position(config_name: &'static str, value: &Optio
|
||||||
_ => warn!("'{}' configuration key should contain Array, does not", config_name),
|
_ => warn!("'{}' configuration key should contain Array, does not", config_name),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
&None => warn!("No store configuration"),
|
None => warn!("No store configuration"),
|
||||||
_ => warn!("Configuration is not a table"),
|
_ => warn!("Configuration is not a table"),
|
||||||
}
|
}
|
||||||
v
|
v
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::Error as FmtError;
|
use std::fmt::Error as FmtError;
|
||||||
use std::clone::Clone;
|
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
|
@ -41,35 +40,35 @@ pub enum StoreErrorKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn store_error_type_as_str(e: &StoreErrorKind) -> &'static str {
|
fn store_error_type_as_str(e: &StoreErrorKind) -> &'static str {
|
||||||
match e {
|
match *e {
|
||||||
&StoreErrorKind::ConfigurationError => "Store Configuration Error",
|
StoreErrorKind::ConfigurationError => "Store Configuration Error",
|
||||||
&StoreErrorKind::FileError => "File Error",
|
StoreErrorKind::FileError |
|
||||||
&StoreErrorKind::IdLocked => "ID locked",
|
StoreErrorKind::IoError => "File Error",
|
||||||
&StoreErrorKind::IdNotFound => "ID not found",
|
StoreErrorKind::IdLocked => "ID locked",
|
||||||
&StoreErrorKind::OutOfMemory => "Out of Memory",
|
StoreErrorKind::IdNotFound => "ID not found",
|
||||||
&StoreErrorKind::FileNotFound => "File corresponding to ID not found",
|
StoreErrorKind::OutOfMemory => "Out of Memory",
|
||||||
&StoreErrorKind::FileNotCreated => "File corresponding to ID could not be created",
|
StoreErrorKind::FileNotFound => "File corresponding to ID not found",
|
||||||
&StoreErrorKind::IoError => "File Error",
|
StoreErrorKind::FileNotCreated => "File corresponding to ID could not be created",
|
||||||
&StoreErrorKind::StorePathExists => "Store path exists",
|
StoreErrorKind::StorePathExists |
|
||||||
&StoreErrorKind::StorePathCreate => "Store path create",
|
StoreErrorKind::StorePathCreate => "Store path create",
|
||||||
&StoreErrorKind::LockError => "Error locking datastructure",
|
StoreErrorKind::LockError => "Error locking datastructure",
|
||||||
&StoreErrorKind::LockPoisoned
|
StoreErrorKind::LockPoisoned
|
||||||
=> "The internal Store Lock has been poisoned",
|
=> "The internal Store Lock has been poisoned",
|
||||||
&StoreErrorKind::EntryAlreadyBorrowed => "Entry is already borrowed",
|
StoreErrorKind::EntryAlreadyBorrowed => "Entry is already borrowed",
|
||||||
&StoreErrorKind::EntryAlreadyExists => "Entry already exists",
|
StoreErrorKind::EntryAlreadyExists => "Entry already exists",
|
||||||
&StoreErrorKind::MalformedEntry => "Entry has invalid formatting, missing header",
|
StoreErrorKind::MalformedEntry => "Entry has invalid formatting, missing header",
|
||||||
&StoreErrorKind::HeaderPathSyntaxError => "Syntax error in accessor string",
|
StoreErrorKind::HeaderPathSyntaxError => "Syntax error in accessor string",
|
||||||
&StoreErrorKind::HeaderPathTypeFailure => "Header has wrong type for path",
|
StoreErrorKind::HeaderPathTypeFailure => "Header has wrong type for path",
|
||||||
&StoreErrorKind::HeaderKeyNotFound => "Header Key not found",
|
StoreErrorKind::HeaderKeyNotFound => "Header Key not found",
|
||||||
&StoreErrorKind::HeaderTypeFailure => "Header type is wrong",
|
StoreErrorKind::HeaderTypeFailure => "Header type is wrong",
|
||||||
&StoreErrorKind::HookRegisterError => "Hook register error",
|
StoreErrorKind::HookRegisterError => "Hook register error",
|
||||||
&StoreErrorKind::AspectNameNotFoundError => "Aspect name not found",
|
StoreErrorKind::AspectNameNotFoundError => "Aspect name not found",
|
||||||
&StoreErrorKind::HookExecutionError => "Hook execution error",
|
StoreErrorKind::HookExecutionError => "Hook execution error",
|
||||||
&StoreErrorKind::PreHookExecuteError => "Pre-Hook execution error",
|
StoreErrorKind::PreHookExecuteError => "Pre-Hook execution error",
|
||||||
&StoreErrorKind::PostHookExecuteError => "Post-Hook execution error",
|
StoreErrorKind::PostHookExecuteError => "Post-Hook execution error",
|
||||||
&StoreErrorKind::StorePathLacksVersion => "The supplied store path has no version part",
|
StoreErrorKind::StorePathLacksVersion => "The supplied store path has no version part",
|
||||||
&StoreErrorKind::GlobError => "glob() error",
|
StoreErrorKind::GlobError => "glob() error",
|
||||||
&StoreErrorKind::EncodingError => "Encoding error",
|
StoreErrorKind::EncodingError => "Encoding error",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +108,7 @@ impl StoreError {
|
||||||
* Get the error type of this StoreError
|
* Get the error type of this StoreError
|
||||||
*/
|
*/
|
||||||
pub fn err_type(&self) -> StoreErrorKind {
|
pub fn err_type(&self) -> StoreErrorKind {
|
||||||
self.err_type.clone()
|
self.err_type
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -117,7 +116,7 @@ impl StoreError {
|
||||||
impl Display for StoreError {
|
impl Display for StoreError {
|
||||||
|
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
||||||
try!(write!(fmt, "[{}]", store_error_type_as_str(&self.err_type.clone())));
|
try!(write!(fmt, "[{}]", store_error_type_as_str(&self.err_type)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +125,7 @@ impl Display for StoreError {
|
||||||
impl Error for StoreError {
|
impl Error for StoreError {
|
||||||
|
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
store_error_type_as_str(&self.err_type.clone())
|
store_error_type_as_str(&self.err_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cause(&self) -> Option<&Error> {
|
fn cause(&self) -> Option<&Error> {
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl StoreIdAccessor for Aspect {
|
||||||
use crossbeam;
|
use crossbeam;
|
||||||
|
|
||||||
let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
|
let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
|
||||||
if !accessors.iter().all(|a| match a { &HDA::StoreIdAccess(_) => true, _ => false }) {
|
if !accessors.iter().all(|a| match *a { HDA::StoreIdAccess(_) => true, _ => false }) {
|
||||||
return Err(HE::new(HEK::AccessTypeViolation, None));
|
return Err(HE::new(HEK::AccessTypeViolation, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,8 +50,8 @@ impl StoreIdAccessor for Aspect {
|
||||||
.map(|accessor| {
|
.map(|accessor| {
|
||||||
crossbeam::scope(|scope| {
|
crossbeam::scope(|scope| {
|
||||||
scope.spawn(|| {
|
scope.spawn(|| {
|
||||||
match accessor {
|
match *accessor {
|
||||||
&HDA::StoreIdAccess(accessor) => accessor.access(id),
|
HDA::StoreIdAccess(accessor) => accessor.access(id),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
.map_err(|_| ()) // TODO: We're losing the error cause here
|
.map_err(|_| ()) // TODO: We're losing the error cause here
|
||||||
|
@ -76,9 +76,9 @@ impl MutableHookDataAccessor for Aspect {
|
||||||
let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
|
let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
|
||||||
|
|
||||||
fn is_file_accessor(a: &HDA) -> bool {
|
fn is_file_accessor(a: &HDA) -> bool {
|
||||||
match a {
|
match *a {
|
||||||
&HDA::MutableAccess(_) => true,
|
HDA::MutableAccess(_) |
|
||||||
&HDA::NonMutableAccess(_) => true,
|
HDA::NonMutableAccess(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ impl NonMutableHookDataAccessor for Aspect {
|
||||||
use crossbeam;
|
use crossbeam;
|
||||||
|
|
||||||
let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
|
let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
|
||||||
if !accessors.iter().all(|a| match a { &HDA::NonMutableAccess(_) => true, _ => false }) {
|
if !accessors.iter().all(|a| match *a { HDA::NonMutableAccess(_) => true, _ => false }) {
|
||||||
return Err(HE::new(HEK::AccessTypeViolation, None));
|
return Err(HE::new(HEK::AccessTypeViolation, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,8 +117,8 @@ impl NonMutableHookDataAccessor for Aspect {
|
||||||
.map(|accessor| {
|
.map(|accessor| {
|
||||||
crossbeam::scope(|scope| {
|
crossbeam::scope(|scope| {
|
||||||
scope.spawn(|| {
|
scope.spawn(|| {
|
||||||
match accessor {
|
match *accessor {
|
||||||
&HDA::NonMutableAccess(accessor) => accessor.access(fle),
|
HDA::NonMutableAccess(accessor) => accessor.access(fle),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
.map_err(|_| ()) // TODO: We're losing the error cause here
|
.map_err(|_| ()) // TODO: We're losing the error cause here
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::Error as FmtError;
|
use std::fmt::Error as FmtError;
|
||||||
use std::clone::Clone;
|
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
|
|
||||||
|
@ -35,9 +34,9 @@ impl Into<HookError> for (HookErrorKind, Box<Error>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hook_error_type_as_str(e: &HookErrorKind) -> &'static str {
|
fn hook_error_type_as_str(e: &HookErrorKind) -> &'static str {
|
||||||
match e {
|
match *e {
|
||||||
&HookErrorKind::HookExecutionError => "Hook exec error",
|
HookErrorKind::HookExecutionError => "Hook exec error",
|
||||||
&HookErrorKind::AccessTypeViolation => "Hook access type violation",
|
HookErrorKind::AccessTypeViolation => "Hook access type violation",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +76,7 @@ impl HookError {
|
||||||
* Get the error type of this HookError
|
* Get the error type of this HookError
|
||||||
*/
|
*/
|
||||||
pub fn err_type(&self) -> HookErrorKind {
|
pub fn err_type(&self) -> HookErrorKind {
|
||||||
self.err_type.clone()
|
self.err_type
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -85,7 +84,7 @@ impl HookError {
|
||||||
impl Display for HookError {
|
impl Display for HookError {
|
||||||
|
|
||||||
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
|
||||||
try!(write!(fmt, "[{}]", hook_error_type_as_str(&self.err_type.clone())));
|
try!(write!(fmt, "[{}]", hook_error_type_as_str(&self.err_type)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +93,7 @@ impl Display for HookError {
|
||||||
impl Error for HookError {
|
impl Error for HookError {
|
||||||
|
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
hook_error_type_as_str(&self.err_type.clone())
|
hook_error_type_as_str(&self.err_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cause(&self) -> Option<&Error> {
|
fn cause(&self) -> Option<&Error> {
|
||||||
|
|
|
@ -4,11 +4,9 @@ use std::io::{Seek, SeekFrom};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::fs::{File, OpenOptions, create_dir_all};
|
use std::fs::{File, OpenOptions, create_dir_all};
|
||||||
|
|
||||||
/**
|
/// `LazyFile` type
|
||||||
* LazyFile type
|
///
|
||||||
*
|
/// A lazy file is either absent, but a path to it is available, or it is present.
|
||||||
* A lazy file is either absent, but a path to it is available, or it is present.
|
|
||||||
*/
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum LazyFile {
|
pub enum LazyFile {
|
||||||
Absent(PathBuf),
|
Absent(PathBuf),
|
||||||
|
|
|
@ -140,7 +140,7 @@ impl StoreEntry {
|
||||||
entry
|
entry
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(StoreError::new(StoreErrorKind::EntryAlreadyBorrowed, None))
|
Err(StoreError::new(StoreErrorKind::EntryAlreadyBorrowed, None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,12 +213,10 @@ impl Store {
|
||||||
return Err(StoreError::new(StoreErrorKind::StorePathCreate,
|
return Err(StoreError::new(StoreErrorKind::StorePathCreate,
|
||||||
Some(Box::new(c.unwrap_err()))));
|
Some(Box::new(c.unwrap_err()))));
|
||||||
}
|
}
|
||||||
} else {
|
} else if location.is_file() {
|
||||||
if location.is_file() {
|
|
||||||
debug!("Store path exists as file");
|
debug!("Store path exists as file");
|
||||||
return Err(StoreError::new(StoreErrorKind::StorePathExists, None));
|
return Err(StoreError::new(StoreErrorKind::StorePathExists, None));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let pre_create_aspects = get_pre_create_aspect_names(&store_config)
|
let pre_create_aspects = get_pre_create_aspect_names(&store_config)
|
||||||
.into_iter().map(|n| {
|
.into_iter().map(|n| {
|
||||||
|
@ -468,7 +466,7 @@ impl Store {
|
||||||
|
|
||||||
pub fn register_hook(&mut self,
|
pub fn register_hook(&mut self,
|
||||||
position: HookPosition,
|
position: HookPosition,
|
||||||
aspect_name: &String,
|
aspect_name: &str,
|
||||||
mut h: Box<Hook>)
|
mut h: Box<Hook>)
|
||||||
-> Result<()>
|
-> Result<()>
|
||||||
{
|
{
|
||||||
|
@ -506,16 +504,16 @@ impl Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
let annfe = StoreError::new(StoreErrorKind::AspectNameNotFoundError, None);
|
let annfe = StoreError::new(StoreErrorKind::AspectNameNotFoundError, None);
|
||||||
return Err(StoreError::new(StoreErrorKind::HookRegisterError, Some(Box::new(annfe))));
|
Err(StoreError::new(StoreErrorKind::HookRegisterError, Some(Box::new(annfe))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_config_for_hook(&self, name: &str) -> Option<&Value> {
|
fn get_config_for_hook(&self, name: &str) -> Option<&Value> {
|
||||||
match &self.configuration {
|
match self.configuration {
|
||||||
&Some(Value::Table(ref tabl)) => {
|
Some(Value::Table(ref tabl)) => {
|
||||||
tabl.get("hooks")
|
tabl.get("hooks")
|
||||||
.map(|hook_section| {
|
.map(|hook_section| {
|
||||||
match hook_section {
|
match *hook_section {
|
||||||
&Value::Table(ref tabl) => tabl.get(name),
|
Value::Table(ref tabl) => tabl.get(name),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -635,17 +633,13 @@ impl<'a> Drop for FileLockEntry<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// `EntryContent` type
|
||||||
* EntryContent type
|
|
||||||
*/
|
|
||||||
pub type EntryContent = String;
|
pub type EntryContent = String;
|
||||||
|
|
||||||
/**
|
/// `EntryHeader`
|
||||||
* EntryHeader
|
///
|
||||||
*
|
/// This is basically a wrapper around `toml::Table` which provides convenience to the user of the
|
||||||
* This is basically a wrapper around toml::Table which provides convenience to the user of the
|
/// library.
|
||||||
* librray.
|
|
||||||
*/
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct EntryHeader {
|
pub struct EntryHeader {
|
||||||
header: Value,
|
header: Value,
|
||||||
|
@ -691,8 +685,8 @@ impl EntryHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify(&self) -> Result<()> {
|
pub fn verify(&self) -> Result<()> {
|
||||||
match &self.header {
|
match self.header {
|
||||||
&Value::Table(ref t) => verify_header(&t),
|
Value::Table(ref t) => verify_header(&t),
|
||||||
_ => Err(StoreError::new(StoreErrorKind::HeaderTypeFailure, None)),
|
_ => Err(StoreError::new(StoreErrorKind::HeaderTypeFailure, None)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -751,13 +745,13 @@ impl EntryHeader {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
match destination {
|
match *destination {
|
||||||
&Token::Key(ref s) => { // if the destination shall be an map key
|
Token::Key(ref s) => { // if the destination shall be an map key
|
||||||
match value {
|
match *value {
|
||||||
/*
|
/*
|
||||||
* Put it in there if we have a map
|
* Put it in there if we have a map
|
||||||
*/
|
*/
|
||||||
&mut Value::Table(ref mut t) => {
|
Value::Table(ref mut t) => {
|
||||||
t.insert(s.clone(), v);
|
t.insert(s.clone(), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,13 +762,13 @@ impl EntryHeader {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
&Token::Index(i) => { // if the destination shall be an array
|
Token::Index(i) => { // if the destination shall be an array
|
||||||
match value {
|
match *value {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put it in there if we have an array
|
* Put it in there if we have an array
|
||||||
*/
|
*/
|
||||||
&mut Value::Array(ref mut a) => {
|
Value::Array(ref mut a) => {
|
||||||
a.push(v); // push to the end of the array
|
a.push(v); // push to the end of the array
|
||||||
|
|
||||||
// if the index is inside the array, we swap-remove the element at this
|
// if the index is inside the array, we swap-remove the element at this
|
||||||
|
@ -845,13 +839,13 @@ impl EntryHeader {
|
||||||
let mut value = value.unwrap();
|
let mut value = value.unwrap();
|
||||||
debug!("walked value = {:?}", value);
|
debug!("walked value = {:?}", value);
|
||||||
|
|
||||||
match destination {
|
match *destination {
|
||||||
&Token::Key(ref s) => { // if the destination shall be an map key->value
|
Token::Key(ref s) => { // if the destination shall be an map key->value
|
||||||
match value {
|
match *value {
|
||||||
/*
|
/*
|
||||||
* Put it in there if we have a map
|
* Put it in there if we have a map
|
||||||
*/
|
*/
|
||||||
&mut Value::Table(ref mut t) => {
|
Value::Table(ref mut t) => {
|
||||||
debug!("Matched Key->Table");
|
debug!("Matched Key->Table");
|
||||||
return Ok(t.insert(s.clone(), v));
|
return Ok(t.insert(s.clone(), v));
|
||||||
}
|
}
|
||||||
|
@ -866,13 +860,13 @@ impl EntryHeader {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
&Token::Index(i) => { // if the destination shall be an array
|
Token::Index(i) => { // if the destination shall be an array
|
||||||
match value {
|
match *value {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put it in there if we have an array
|
* Put it in there if we have an array
|
||||||
*/
|
*/
|
||||||
&mut Value::Array(ref mut a) => {
|
Value::Array(ref mut a) => {
|
||||||
debug!("Matched Index->Array");
|
debug!("Matched Index->Array");
|
||||||
a.push(v); // push to the end of the array
|
a.push(v); // push to the end of the array
|
||||||
|
|
||||||
|
@ -971,10 +965,10 @@ impl EntryHeader {
|
||||||
let mut value = value.unwrap();
|
let mut value = value.unwrap();
|
||||||
debug!("walked value = {:?}", value);
|
debug!("walked value = {:?}", value);
|
||||||
|
|
||||||
match destination {
|
match *destination {
|
||||||
&Token::Key(ref s) => { // if the destination shall be an map key->value
|
Token::Key(ref s) => { // if the destination shall be an map key->value
|
||||||
match value {
|
match *value {
|
||||||
&mut Value::Table(ref mut t) => {
|
Value::Table(ref mut t) => {
|
||||||
debug!("Matched Key->Table, removing {:?}", s);
|
debug!("Matched Key->Table, removing {:?}", s);
|
||||||
return Ok(t.remove(s));
|
return Ok(t.remove(s));
|
||||||
},
|
},
|
||||||
|
@ -985,9 +979,9 @@ impl EntryHeader {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
&Token::Index(i) => { // if the destination shall be an array
|
Token::Index(i) => { // if the destination shall be an array
|
||||||
match value {
|
match *value {
|
||||||
&mut Value::Array(ref mut a) => {
|
Value::Array(ref mut a) => {
|
||||||
// if the index is inside the array, we swap-remove the element at this
|
// if the index is inside the array, we swap-remove the element at this
|
||||||
// index
|
// index
|
||||||
if a.len() > i {
|
if a.len() > i {
|
||||||
|
@ -1037,9 +1031,9 @@ impl EntryHeader {
|
||||||
walk_iter(Ok(v), &mut tokens.into_iter())
|
walk_iter(Ok(v), &mut tokens.into_iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_from_table<'a>(v: &'a mut Value, s: &String) -> Result<&'a mut Value> {
|
fn extract_from_table<'a>(v: &'a mut Value, s: &str) -> Result<&'a mut Value> {
|
||||||
match v {
|
match *v {
|
||||||
&mut Value::Table(ref mut t) => {
|
Value::Table(ref mut t) => {
|
||||||
t.get_mut(&s[..])
|
t.get_mut(&s[..])
|
||||||
.ok_or(StoreError::new(StoreErrorKind::HeaderKeyNotFound, None))
|
.ok_or(StoreError::new(StoreErrorKind::HeaderKeyNotFound, None))
|
||||||
},
|
},
|
||||||
|
@ -1048,8 +1042,8 @@ impl EntryHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_from_array(v: &mut Value, i: usize) -> Result<&mut Value> {
|
fn extract_from_array(v: &mut Value, i: usize) -> Result<&mut Value> {
|
||||||
match v {
|
match *v {
|
||||||
&mut Value::Array(ref mut a) => {
|
Value::Array(ref mut a) => {
|
||||||
if a.len() < i {
|
if a.len() < i {
|
||||||
Err(StoreError::new(StoreErrorKind::HeaderKeyNotFound, None))
|
Err(StoreError::new(StoreErrorKind::HeaderKeyNotFound, None))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1061,9 +1055,9 @@ impl EntryHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract<'a>(v: &'a mut Value, token: &Token) -> Result<&'a mut Value> {
|
fn extract<'a>(v: &'a mut Value, token: &Token) -> Result<&'a mut Value> {
|
||||||
match token {
|
match *token {
|
||||||
&Token::Key(ref s) => EntryHeader::extract_from_table(v, s),
|
Token::Key(ref s) => EntryHeader::extract_from_table(v, s),
|
||||||
&Token::Index(i) => EntryHeader::extract_from_array(v, i),
|
Token::Index(i) => EntryHeader::extract_from_array(v, i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1125,7 +1119,7 @@ fn verify_header_consistency(t: Table) -> EntryResult<Table> {
|
||||||
|
|
||||||
fn has_only_tables(t: &Table) -> bool {
|
fn has_only_tables(t: &Table) -> bool {
|
||||||
debug!("Verifying that table has only tables");
|
debug!("Verifying that table has only tables");
|
||||||
t.iter().all(|(_, x)| if let &Value::Table(_) = x { true } else { false })
|
t.iter().all(|(_, x)| if let Value::Table(_) = *x { true } else { false })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_main_section(t: &Table) -> bool {
|
fn has_main_section(t: &Table) -> bool {
|
||||||
|
@ -1140,12 +1134,12 @@ fn has_main_section(t: &Table) -> bool {
|
||||||
fn has_imag_version_in_main_section(t: &Table) -> bool {
|
fn has_imag_version_in_main_section(t: &Table) -> bool {
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
|
|
||||||
match t.get("imag").unwrap() {
|
match *t.get("imag").unwrap() {
|
||||||
&Value::Table(ref sec) => {
|
Value::Table(ref sec) => {
|
||||||
sec.get("version")
|
sec.get("version")
|
||||||
.and_then(|v| {
|
.and_then(|v| {
|
||||||
match v {
|
match *v {
|
||||||
&Value::String(ref s) => {
|
Value::String(ref s) => {
|
||||||
Some(Version::parse(&s[..]).is_ok())
|
Some(Version::parse(&s[..]).is_ok())
|
||||||
},
|
},
|
||||||
_ => Some(false),
|
_ => Some(false),
|
||||||
|
|
|
@ -85,7 +85,7 @@ impl IntoStoreId for StoreId {
|
||||||
|
|
||||||
pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
|
pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
|
||||||
debug!("Checking path element for version");
|
debug!("Checking path element for version");
|
||||||
if path_elem.split("~").last().map(|v| Version::parse(v).is_err()).unwrap_or(false) {
|
if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) {
|
||||||
debug!("Version cannot be parsed from {:?}", path_elem);
|
debug!("Version cannot be parsed from {:?}", path_elem);
|
||||||
debug!("Path does not contain version!");
|
debug!("Path does not contain version!");
|
||||||
return Err(StoreError::new(StoreErrorKind::StorePathLacksVersion, None));
|
return Err(StoreError::new(StoreErrorKind::StorePathLacksVersion, None));
|
||||||
|
@ -95,8 +95,8 @@ pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
|
||||||
debug!("Building path from {:?}", path_elem);
|
debug!("Building path from {:?}", path_elem);
|
||||||
let mut path = store.path().clone();
|
let mut path = store.path().clone();
|
||||||
|
|
||||||
if path_elem.chars().next() == Some('/') {
|
if path_elem.starts_with('/') {
|
||||||
path.push(&path_elem[1..path_elem.len()]);
|
path.push(&path_elem[1..]);
|
||||||
} else {
|
} else {
|
||||||
path.push(path_elem);
|
path.push(path_elem);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,14 +43,14 @@ impl HookDataAccessorProvider for DebugHook {
|
||||||
use libimagstore::hook::accessor::HookDataAccessor as HDA;
|
use libimagstore::hook::accessor::HookDataAccessor as HDA;
|
||||||
|
|
||||||
match self.position {
|
match self.position {
|
||||||
HP::PreCreate => HDA::StoreIdAccess(&self.accessor),
|
HP::PreCreate |
|
||||||
HP::PostCreate => HDA::MutableAccess(&self.accessor),
|
HP::PreRetrieve |
|
||||||
HP::PreRetrieve => HDA::StoreIdAccess(&self.accessor),
|
HP::PreDelete |
|
||||||
HP::PostRetrieve => HDA::MutableAccess(&self.accessor),
|
|
||||||
HP::PreUpdate => HDA::MutableAccess(&self.accessor),
|
|
||||||
HP::PostUpdate => HDA::MutableAccess(&self.accessor),
|
|
||||||
HP::PreDelete => HDA::StoreIdAccess(&self.accessor),
|
|
||||||
HP::PostDelete => HDA::StoreIdAccess(&self.accessor),
|
HP::PostDelete => HDA::StoreIdAccess(&self.accessor),
|
||||||
|
HP::PostCreate |
|
||||||
|
HP::PostRetrieve |
|
||||||
|
HP::PreUpdate |
|
||||||
|
HP::PostUpdate => HDA::MutableAccess(&self.accessor),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,9 @@ pub enum Action {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_to_str(a: &Action) -> &'static str {
|
fn action_to_str(a: &Action) -> &'static str {
|
||||||
match a {
|
match *a {
|
||||||
&Action::Lock => "lock",
|
Action::Lock => "lock",
|
||||||
&Action::Unlock => "unlock",
|
Action::Unlock => "unlock",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,12 +57,10 @@ impl NonMutableHookDataAccessor for LinkedEntriesExistHook {
|
||||||
path.push(link);
|
path.push(link);
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
warn!("File link does not exist: {:?} -> {:?}", fle.get_location(), path);
|
warn!("File link does not exist: {:?} -> {:?}", fle.get_location(), path);
|
||||||
} else {
|
} else if !path.is_file() {
|
||||||
if !path.is_file() {
|
|
||||||
warn!("File link is not a file: {:?} -> {:?}", fle.get_location(), path);
|
warn!("File link is not a file: {:?} -> {:?}", fle.get_location(), path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
warn!("Couldn't execute Link-Verify hook");
|
warn!("Couldn't execute Link-Verify hook");
|
||||||
|
|
|
@ -59,7 +59,7 @@ fn print_trace_maxdepth(idx: u64, e: &Error, max: u64) -> Option<&Error> {
|
||||||
e.cause()
|
e.cause()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Count errors in Error::cause() recursively
|
/// Count errors in `Error::cause()` recursively
|
||||||
fn count_error_causes(e: &Error) -> u64 {
|
fn count_error_causes(e: &Error) -> u64 {
|
||||||
1 + if e.cause().is_some() { count_error_causes(e.cause().unwrap()) } else { 0 }
|
1 + if e.cause().is_some() { count_error_causes(e.cause().unwrap()) } else { 0 }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue