Merge branch 'libimagcalendar/init' into master

This commit is contained in:
Matthias Beyer 2019-10-11 21:35:39 +02:00
commit 712eda074d
8 changed files with 260 additions and 0 deletions

View file

@ -34,6 +34,7 @@ members = [
"lib/core/libimagrt",
"lib/core/libimagstore",
"lib/domain/libimagbookmark",
"lib/domain/libimagcalendar",
"lib/domain/libimagcontact",
"lib/domain/libimagdiary",
"lib/domain/libimaghabit",

View file

@ -0,0 +1,10 @@
## libimagcalendar
This library helps tracking (vcard) events in imag.
It does nothing more than create one imag entry per VEVENT UID, giving the user
the ability to "link" to each event individually.
It uses the libimagentryref library for refering to the actual file holding the
data.

View file

@ -0,0 +1,35 @@
[package]
name = "libimagcalendar"
version = "0.10.0"
authors = ["Matthias Beyer <mail@beyermatthias.de>"]
description = "Library for the imag core distribution"
keywords = ["imag", "PIM", "personal", "information", "management"]
readme = "../../../README.md"
license = "LGPL-2.1"
documentation = "https://matthiasbeyer.github.io/imag/imag_documentation/index.html"
repository = "https://github.com/matthiasbeyer/imag"
homepage = "http://imag-pim.org"
[badges]
travis-ci = { repository = "matthiasbeyer/imag" }
is-it-maintained-issue-resolution = { repository = "matthiasbeyer/imag" }
is-it-maintained-open-issues = { repository = "matthiasbeyer/imag" }
maintenance = { status = "actively-developed" }
[dependencies]
failure = "0.1"
log = "0.4"
toml = "0.5"
toml-query = "0.9"
vobject = "0.7"
chrono = "0.4"
libimagentrylink = { version = "0.10.0", path = "../../../lib/entry/libimagentrylink" }
libimagentryref = { version = "0.10.0", path = "../../../lib/entry/libimagentryref" }
libimagentryutil = { version = "0.10.0", path = "../../../lib/entry/libimagentryutil" }
libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" }
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }

View file

@ -0,0 +1 @@
../../../doc/src/05100-lib-calendar.md

View file

@ -0,0 +1,37 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015-2019 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use failure::Fallible as Result;
use libimagentryutil::isa::Is;
use libimagentryutil::isa::IsKindHeaderPathProvider;
use libimagstore::store::Entry;
provide_kindflag_path!(pub IsEvent, "calendar.event.is_event");
pub trait Event {
fn is_event(&self) -> Result<bool>;
}
impl Event for Entry {
fn is_event(&self) -> Result<bool> {
self.is::<IsEvent>()
}
}

View file

@ -0,0 +1,56 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015-2019 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#![forbid(unsafe_code)]
#![deny(
dead_code,
non_camel_case_types,
non_snake_case,
path_statements,
trivial_numeric_casts,
unstable_features,
unused_allocation,
unused_import_braces,
unused_imports,
unused_must_use,
unused_mut,
unused_qualifications,
while_true,
)]
#![recursion_limit="128"]
#[macro_use] extern crate log;
#[macro_use] extern crate failure;
extern crate vobject;
extern crate toml;
extern crate toml_query;
#[macro_use] extern crate libimagstore;
extern crate libimagerror;
extern crate libimagentryref;
#[macro_use] extern crate libimagentryutil;
module_entry_path_mod!("calendar");
pub mod event;
pub mod store;

View file

@ -0,0 +1,119 @@
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015-2019 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use std::path::Path;
use failure::Fallible as Result;
use toml::Value;
use toml_query::insert::TomlValueInsertExt;
use vobject::ICalendar;
use libimagentryutil::isa::Is;
use libimagentryref::reference::Config;
use libimagentryref::reference::MutRef;
use libimagentryref::hasher::default::DefaultHasher;
use libimagentryref::reference::RefFassade;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::iter::Entries;
use crate::event::IsEvent;
pub trait EventStore<'a> {
/// Imports events from a filepath
///
/// # Note
///
/// Because one icalendar file can theoretically hold several events, this function returns a
/// list of entries.
///
/// # Parameters
///
/// This function is basically a wrapper around `libimagentryref::reference::RefMut::make_ref()`
/// which also does some parsing and Store::create() ing entry objects.
///
/// Because of the former function, this requires some parameters which are documented in the
/// documentation of this function:
///
/// libimagentryref::reference::RefMut::make_ref()
///
/// Normally, `force` should be set to `false`.
///
fn import_from_path<P, Coll>(&'a self, p: P, basepath_name: Coll, refconfig: &Config, force: bool)
-> Result<Vec<Result<FileLockEntry<'a>>>>
where P: AsRef<Path>,
Coll: AsRef<str>;
fn get_event_by_uid<ID>(&'a self, id: ID) -> Result<Option<FileLockEntry<'a>>>
where ID: AsRef<str>;
/// Get all events
fn all_events(&'a self) -> Result<Entries<'a>>;
}
impl<'a> EventStore<'a> for Store {
fn import_from_path<P, Coll>(&'a self, p: P, basepath_name: Coll, refconfig: &Config, force: bool)
-> Result<Vec<Result<FileLockEntry<'a>>>>
where P: AsRef<Path>,
Coll: AsRef<str>
{
let text = std::fs::read_to_string(p.as_ref())?;
Ok(ICalendar::build(&text)?
.events()
.filter_map(|rresult| match rresult {
Ok(event) => Some(event),
Err(component) => {
debug!("Ignoring non-event Component in {}: {}", p.as_ref().display(), component.name);
None
}
})
.map(|event| {
let uid = event.uid().ok_or_else(|| {
format_err!("Event in {} has no UID, but icalendar events must have one.", p.as_ref().display())
})?;
let sid = crate::module_path::new_id(uid.raw())?;
let uid_header = Value::String(uid.into_raw());
let mut entry = self.create(sid)?;
let _ = entry
.as_ref_with_hasher_mut::<DefaultHasher>()
.make_ref(p.as_ref(), basepath_name.as_ref(), refconfig, force)?;
let _ = entry.get_header_mut().insert("calendar.event.uid", uid_header)?;
let _ = entry.set_isflag::<IsEvent>()?;
Ok(entry)
})
.collect())
}
fn get_event_by_uid<ID>(&'a self, id: ID) -> Result<Option<FileLockEntry<'a>>>
where ID: AsRef<str>
{
self.get(crate::module_path::new_id(id.as_ref())?)
}
/// Get all events
///
/// Uses Store::entries(), so there might be false positives.
fn all_events(&'a self) -> Result<Entries<'a>> {
self.entries().and_then(|es| es.in_collection("calendar"))
}
}

View file

@ -29,6 +29,7 @@ CRATES=(
./lib/entry/libimagentrymarkdown
./lib/entry/libimagentryannotation
./lib/domain/libimagbookmark
./lib/domain/libimagcalendar
./lib/domain/libimaghabit
./lib/domain/libimagnotes
./lib/domain/libimagcontact