From 8c597d2c4dbf6f66c522a708014a1865d3376741 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 2 Aug 2018 01:41:33 +0200 Subject: [PATCH 01/33] doc: Document new IO story with libimagrt --- doc/src/05100-lib-rt.md | 76 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/doc/src/05100-lib-rt.md b/doc/src/05100-lib-rt.md index ca22256c..eddba923 100644 --- a/doc/src/05100-lib-rt.md +++ b/doc/src/05100-lib-rt.md @@ -9,6 +9,82 @@ It also contains the store object and creates it from configuration. the `libimagrt::runtime::Runtime` object is the first complex object that comes to live in a imag binary. + +### IO with libimagrt + +libimagrt also provides IO primitives which should be used by all imag tools and +libraries: + +The IO story in imag is pretty easy. As imag is mainly a CLI tool, IO is either +`stdout` or `stderr` and `stdin`. + + +#### Output + +libimagrt provides getters for an output stream for "normal" output, like +logging, status information, etc. It also provides an output for "touched +entries". + +Whenever an imag tool touches an entry in any way (either reading or writing), +it should report this to libimagrt. libimagrt then does "the right thing" which +is printing it to stdout or swallowing the output. +Normal output (logging, status information, explicitely queried information) +goes to the right sink automatically, that is: + +* If the user provides the appropriate flags, normal output goes to `stderr` and + "touched entries" go to `stdout`. This allows a user to 'chain' imag calls. +* If the user does not provide these flags, normal output goes to `stdout` (for + piping to other tools, e.g. `grep`) and "touched entries" are not printed. + +* `stdin` can be used for reading store-ids which shall be processed by an imag + tool. For example `imag-tag` can receive a list of entries to add tags to via + `stdin` like this: `echo some/entry some/other | imag tag -I add sometag`. + +With these two settings in place, calls to imag can be chained and mixed with +external tools pretty easily: + +``` +imag -O ids where 'some.header == 1' | \ +imag -I -O tag add foo | \ +imag -I -O category set bar | \ +fzf | \ +imag -I tag add baz +``` + +The first line gets all imag entries where `some.header` equals `1`. The touched +entries are printed to `stdout` (`-O`). +The second line tags all entries which are passed via `stdin` (`-I`) with `foo` +and prints them to `stdout` (`-O`) +The third line sets the category for all entries which are passed via `stdin` +with `bar` and prints them to `stdout`. +The fourth line calls the `fzf` program and lets the user select one entry +and the last line reads that entry via `stdin` and tags it with `baz`. + +Automatically detecting the appropriate input/output settings is possible, but +hidden behind a environment-flag, as it is considered experimental. +To test this, set `IMAG_IO_EXPERIMENTAL=1` in your environment. +Note that `stdin` may be detected as "store id stream" when it is actually not. +`libimagrt` can take care of this when passing `--interactive`. + + +#### Input + +`libimagrt` also provides primitives for input. As documented in the paragraph +on "Output", imag tools may get store ids passed via `stdin`. +Hence, imag tools may/can not interactive when passing store ids via `stdin`. +`libimagrt` provides functionality to query data from the user. These functions +automatically fail if the user passes store-ids via `stdin`. + +The next paragraph documents the details of this and may be skipped. + +The user tells imag that `stdin` contains store-ids by setting the `-I` +(`--ids-in`) flag on the commandline. If that flag is given, the interactive +functionality of libimagrt automatically returns an `Err(_)` which can be used +to tell the user what happened and exit the program accordingly. +The user may also provide `--interactive` to tell imag via libimagrt that +`stdin` is indeed not a stream of store-ids even if a pipe is detected. + + ### Long-term TODO - [ ] Merge with `libimagstore` From 8552843796de9628386e317b1c1452c5ef87c500 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 2 Aug 2018 01:53:44 +0200 Subject: [PATCH 02/33] doc: Add note on IO conventions --- doc/src/03010-conventions.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/src/03010-conventions.md b/doc/src/03010-conventions.md index a6cf4d3e..661745d1 100644 --- a/doc/src/03010-conventions.md +++ b/doc/src/03010-conventions.md @@ -104,3 +104,14 @@ Commandline interfaces should also provide a flag "-I" (that's a big i) which marks that the store IDs shall be read from stdin and are not passed via the commandline. + +### IO + +There are minor restrictions how imag tools should do IO. A good rule of thumb +is (but most certainly only applicable when programming an imag tool in Rust): +use `libimagrt` to do IO of any kind. + +For more information, or if not using Rust as programming language: the +documentation of `libimagrt` describes how IO should happen (which output +stream to use, how input should be done). + From db4e83f18f032b531b09e59f75d857541cdea919 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 27 Sep 2018 14:19:55 +0200 Subject: [PATCH 03/33] Implement ID reporting This patch adds the id reporting feature to libimagrt::runtime::Runtime, where processed ("touched") ids can be reported to the Runtime and then get printed to stdout if stdout is a pipe. Other output is automatically redirected to stderr if stdout is a pipe now. --- lib/core/libimagrt/src/runtime.rs | 54 +++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/core/libimagrt/src/runtime.rs b/lib/core/libimagrt/src/runtime.rs index 83876ec9..e00a93f6 100644 --- a/lib/core/libimagrt/src/runtime.rs +++ b/lib/core/libimagrt/src/runtime.rs @@ -23,6 +23,8 @@ use std::env; use std::process::exit; use std::io::Stdin; use std::sync::Arc; +use std::io::StdoutLock; +use std::borrow::Borrow; pub use clap::App; use clap::AppSettings; @@ -42,9 +44,11 @@ use io::OutputProxy; use libimagerror::errors::ErrorMsg as EM; use libimagerror::trace::*; use libimagstore::store::Store; +use libimagstore::storeid::StoreId; use libimagstore::file_abstraction::InMemoryFileAbstraction; use libimagutil::debug_result::DebugResult; use spec::CliSpec; +use atty; /// The Runtime object /// @@ -55,6 +59,9 @@ pub struct Runtime<'a> { configuration: Option, cli_matches: ArgMatches<'a>, store: Store, + + has_output_pipe: bool, + has_input_pipe: bool, } impl<'a> Runtime<'a> { @@ -142,6 +149,9 @@ impl<'a> Runtime<'a> { configuration: config, rtp: rtp, store: store, + + has_output_pipe: !atty::is(atty::Stream::Stdout), + has_input_pipe: !atty::is(atty::Stream::Stdin), }) .context(err_msg("Cannot instantiate runtime")) .map_err(Error::from) @@ -415,7 +425,11 @@ impl<'a> Runtime<'a> { } pub fn stdout(&self) -> OutputProxy { - OutputProxy::Out(::std::io::stdout()) + if self.has_output_pipe { + OutputProxy::Err(::std::io::stderr()) + } else { + OutputProxy::Out(::std::io::stdout()) + } } pub fn stderr(&self) -> OutputProxy { @@ -423,7 +437,11 @@ impl<'a> Runtime<'a> { } pub fn stdin(&self) -> Option { - Some(::std::io::stdin()) + if self.has_input_pipe { + None + } else { + Some(::std::io::stdin()) + } } /// Helper for handling subcommands which are not available. @@ -504,6 +522,38 @@ impl<'a> Runtime<'a> { .context(EM::IO) .map_err(Error::from) } + + pub fn report_touched(&self, id: &StoreId) -> Result<()> { + let out = ::std::io::stdout(); + let mut lock = out.lock(); + + self.report_touched_id(id, &mut lock) + } + + pub fn report_all_touched(&self, ids: I) -> Result<()> + where ID: Borrow + Sized, + I: Iterator + { + let out = ::std::io::stdout(); + let mut lock = out.lock(); + + for id in ids { + self.report_touched_id(id.borrow(), &mut lock)?; + } + + Ok(()) + } + + #[inline] + fn report_touched_id(&self, id: &StoreId, output: &mut StdoutLock) -> Result<()> { + use std::io::Write; + + if self.has_output_pipe { + writeln!(output, "{}", id)?; + } + + Ok(()) + } } /// Exported for the `imag` command, you probably do not want to use that. From c1c74973e39814cda66f09f56d4132aed3bebc35 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 29 Sep 2018 17:14:37 +0200 Subject: [PATCH 04/33] Implement ID providing in libimagrt With this patch, IDs can be fetched from the CLI via libimagrt. This gives us the possibility to automatically handle "stdin provides IDs" in libimagrt with less boilerplate in the binaries codebases. Signed-off-by: Matthias Beyer --- lib/core/libimagrt/src/runtime.rs | 78 +++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/lib/core/libimagrt/src/runtime.rs b/lib/core/libimagrt/src/runtime.rs index e00a93f6..ab0b398c 100644 --- a/lib/core/libimagrt/src/runtime.rs +++ b/lib/core/libimagrt/src/runtime.rs @@ -144,14 +144,20 @@ impl<'a> Runtime<'a> { Store::new(storepath, &config) }; + let has_output_pipe = !atty::is(atty::Stream::Stdout); + let has_input_pipe = !atty::is(atty::Stream::Stdin); + + debug!("has output pipe = {}", has_output_pipe); + debug!("has input pipe = {}", has_input_pipe); + store_result.map(|store| Runtime { cli_matches: matches, configuration: config, rtp: rtp, store: store, - has_output_pipe: !atty::is(atty::Stream::Stdout), - has_input_pipe: !atty::is(atty::Stream::Stdin), + has_output_pipe, + has_input_pipe, }) .context(err_msg("Cannot instantiate runtime")) .map_err(Error::from) @@ -383,6 +389,33 @@ impl<'a> Runtime<'a> { &self.cli_matches } + pub fn ids_from_stdin(&self) -> bool { + self.has_input_pipe + } + + pub fn ids(&self) -> Result> { + use std::io::Read; + + if self.has_input_pipe { + trace!("Getting IDs from stdin..."); + let stdin = ::std::io::stdin(); + let mut lock = stdin.lock(); + + let mut buf = String::new(); + lock.read_to_string(&mut buf) + .map_err(Error::from) + .and_then(|_| { + trace!("Got IDs = {}", buf); + buf.lines() + .map(PathBuf::from) + .map(|id| StoreId::new_baseless(id).map_err(Error::from)) + .collect() + }) + } else { + Ok(T::get_ids(self.cli())) + } + } + /// Get the configuration object pub fn config(&self) -> Option<&Value> { self.configuration.as_ref() @@ -424,8 +457,12 @@ impl<'a> Runtime<'a> { }) } + pub fn output_is_pipe(&self) -> bool { + self.has_output_pipe + } + pub fn stdout(&self) -> OutputProxy { - if self.has_output_pipe { + if self.output_is_pipe() { OutputProxy::Err(::std::io::stderr()) } else { OutputProxy::Out(::std::io::stdout()) @@ -548,7 +585,8 @@ impl<'a> Runtime<'a> { fn report_touched_id(&self, id: &StoreId, output: &mut StdoutLock) -> Result<()> { use std::io::Write; - if self.has_output_pipe { + if self.output_is_pipe() { + trace!("Reporting: {} to {:?}", id, output); writeln!(output, "{}", id)?; } @@ -556,6 +594,38 @@ impl<'a> Runtime<'a> { } } +/// A trait for the path provider functionality +/// +/// This trait can be implement on a type so that it can provide IDs when given a ArgMatches +/// object. +/// +/// It can be used with Runtime::ids() and libimagrt handles "stdin-provides-ids" cases +/// automatically: +/// +/// ```ignore +/// runtime.ids::()?.iter().for_each(|id| /* ... */) +/// ``` +/// +/// libimagrt does not call the PathProvider if the ids are provided by piping to stdin. +/// +/// +/// # Passed arguments +/// +/// The arguments which are passed into the IdPathProvider::get_ids() function are the _top level +/// ArgMatches_. Traversing might be required in the implementation of the ::get_ids() function. +/// +/// +/// # Returns +/// +/// In case of error, the IdPathProvider::get_ids() function should exit the application +/// with the appropriate error message(s). +/// +/// On success, the StoreId objects to operate on are returned from the ArgMatches. +/// +pub trait IdPathProvider { + fn get_ids(matches: &ArgMatches) -> Vec; +} + /// Exported for the `imag` command, you probably do not want to use that. pub fn get_rtp_match<'a>(matches: &ArgMatches<'a>) -> PathBuf { use std::env; From 01de94a387f97adffb7a12745fa667f4e7966d55 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 29 Sep 2018 17:44:36 +0200 Subject: [PATCH 05/33] Move imag-annotate to ID provider infrastructure --- bin/core/imag-annotate/src/main.rs | 143 +++++++++++++++-------------- bin/core/imag-annotate/src/ui.rs | 62 ++++++++++++- 2 files changed, 135 insertions(+), 70 deletions(-) diff --git a/bin/core/imag-annotate/src/main.rs b/bin/core/imag-annotate/src/main.rs index 639488ea..5beb0c1b 100644 --- a/bin/core/imag-annotate/src/main.rs +++ b/bin/core/imag-annotate/src/main.rs @@ -45,10 +45,8 @@ extern crate libimagstore; extern crate libimagutil; use std::io::Write; -use std::path::PathBuf; use failure::Error; -use failure::err_msg; use libimagentryannotation::annotateable::*; use libimagentryannotation::annotation_fetcher::*; @@ -56,10 +54,10 @@ use libimagentryedit::edit::*; use libimagerror::trace::MapErrTrace; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; +use libimagerror::errors::ErrorMsg as EM; use libimagrt::runtime::Runtime; use libimagrt::setup::generate_runtime_setup; use libimagstore::store::FileLockEntry; -use libimagstore::storeid::IntoStoreId; mod ui; @@ -91,89 +89,96 @@ fn main() { fn add(rt: &Runtime) { let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main() let annotation_name = scmd.value_of("annotation_name").unwrap(); // safed by clap - let entry_name = scmd - .value_of("entry") - .map(PathBuf::from) - .map(|pb| pb.into_storeid().map_err_trace_exit_unwrap(1)) - .unwrap(); // safed by clap + let ids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1); + + ids.into_iter().for_each(|id| { + let _ = rt.store() + .get(id.clone()) + .map_err_trace_exit_unwrap(1) + .ok_or_else(|| EM::EntryNotFound(id.local_display_string())) + .map_err(Error::from) + .map_err_trace_exit_unwrap(1) + .annotate(rt.store(), annotation_name) + .map_err_trace_exit_unwrap(1) + .edit_content(&rt) + .map_err_trace_exit_unwrap(1); + }) - let _ = rt.store() - .get(entry_name) - .map_err_trace_exit_unwrap(1) - .ok_or_else(|| Error::from(err_msg("Entry does not exist".to_owned()))) - .map_err_trace_exit_unwrap(1) - .annotate(rt.store(), annotation_name) - .map_err_trace_exit_unwrap(1) - .edit_content(&rt) - .map_err_trace_exit_unwrap(1); } fn remove(rt: &Runtime) { let scmd = rt.cli().subcommand_matches("remove").unwrap(); // safed by main() - let entry_name = scmd.value_of("entry").unwrap(); // safed by clap let annotation_name = scmd.value_of("annotation_name").unwrap(); // safed by clap let delete = scmd.is_present("delete-annotation"); + let ids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1); - let mut entry = rt.store() - .get(PathBuf::from(entry_name).into_storeid().map_err_trace_exit_unwrap(1)) - .map_err_trace_exit_unwrap(1) - .ok_or_else(|| Error::from(err_msg("Entry does not exist".to_owned()))) - .map_err_trace_exit_unwrap(1); + ids.into_iter().for_each(|id| { + let mut entry = rt.store() + .get(id.clone()) + .map_err_trace_exit_unwrap(1) + .ok_or_else(|| EM::EntryNotFound(id.local_display_string())) + .map_err(Error::from) + .map_err_trace_exit_unwrap(1); - let annotation = entry - .denotate(rt.store(), annotation_name) - .map_err_trace_exit_unwrap(1); + let annotation = entry + .denotate(rt.store(), annotation_name) + .map_err_trace_exit_unwrap(1); - if delete { - debug!("Deleting annotation object"); - if let Some(an) = annotation { - let loc = an.get_location().clone(); - drop(an); + if delete { + debug!("Deleting annotation object"); + if let Some(an) = annotation { + let loc = an.get_location().clone(); + drop(an); - let _ = rt - .store() - .delete(loc) - .map_err_trace_exit_unwrap(1); + let _ = rt + .store() + .delete(loc) + .map_err_trace_exit_unwrap(1); + } else { + warn!("Not having annotation object, cannot delete!"); + } } else { - warn!("Not having annotation object, cannot delete!"); + debug!("Not deleting annotation object"); } - } else { - debug!("Not deleting annotation object"); - } + }) + } fn list(rt: &Runtime) { - let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap - let with_text = scmd.is_present("list-with-text"); - match scmd.value_of("entry").map(PathBuf::from) { - Some(pb) => { - let _ = rt - .store() - .get(pb.into_storeid().map_err_trace_exit_unwrap(1)) - .map_err_trace_exit_unwrap(1) - .ok_or_else(|| Error::from(err_msg("Entry does not exist"))) - .map_err_trace_exit_unwrap(1) - .annotations(rt.store()) - .map_err_trace_exit_unwrap(1) - .enumerate() - .map(|(i, a)| { - list_annotation(&rt, i, a.map_err_trace_exit_unwrap(1), with_text) - }) - .collect::>(); - } + let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap + let with_text = scmd.is_present("list-with-text"); + let ids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1); - None => { - // show them all - let _ = rt - .store() - .all_annotations() - .map_err_trace_exit_unwrap(1) - .enumerate() - .map(|(i, a)| { - list_annotation(&rt, i, a.map_err_trace_exit_unwrap(1), with_text) - }) - .collect::>(); - } + if ids.len() != 0 { + let _ = ids + .into_iter() + .for_each(|id| { + let _ = rt + .store() + .get(id.clone()) + .map_err_trace_exit_unwrap(1) + .ok_or_else(|| EM::EntryNotFound(id.local_display_string())) + .map_err(Error::from) + .map_err_trace_exit_unwrap(1) + .annotations(rt.store()) + .map_err_trace_exit_unwrap(1) + .enumerate() + .map(|(i, a)| { + list_annotation(&rt, i, a.map_err_trace_exit_unwrap(1), with_text) + }) + .collect::>(); + }); + } else { // ids.len() == 0 + // show them all + let _ = rt + .store() + .all_annotations() + .map_err_trace_exit_unwrap(1) + .enumerate() + .map(|(i, a)| { + list_annotation(&rt, i, a.map_err_trace_exit_unwrap(1), with_text) + }) + .collect::>(); } } diff --git a/bin/core/imag-annotate/src/ui.rs b/bin/core/imag-annotate/src/ui.rs index 544cd2a4..1cf119e6 100644 --- a/bin/core/imag-annotate/src/ui.rs +++ b/bin/core/imag-annotate/src/ui.rs @@ -17,7 +17,14 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use clap::{Arg, App, SubCommand}; +use std::path::PathBuf; + +use clap::{Arg, ArgMatches, App, SubCommand}; + +use libimagstore::storeid::StoreId; +use libimagstore::storeid::IntoStoreId; +use libimagrt::runtime::IdPathProvider; +use libimagerror::trace::MapErrTrace; pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { app @@ -86,3 +93,56 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { ) } +pub struct PathProvider; +impl IdPathProvider for PathProvider { + fn get_ids(matches: &ArgMatches) -> Vec { + match matches.subcommand() { + ("add", Some(subm)) => { + subm.values_of("entry") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1) + }, + + ("remove", Some(subm)) => { + subm.values_of("entry") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1) + }, + + ("list", Some(subm)) => { + subm.values_of("entry") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1) + }, + + (other, _) => { + error!("Not a known command: {}", other); + ::std::process::exit(1) + } + } + } +} From 30036d5628017283e5262fadd693080558d999ed Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 29 Sep 2018 17:44:36 +0200 Subject: [PATCH 06/33] Move imag-category to ID provider infrastructure --- bin/core/imag-category/src/main.rs | 53 +----------------- bin/core/imag-category/src/ui.rs | 90 ++++++++++++++++++++++-------- 2 files changed, 69 insertions(+), 74 deletions(-) diff --git a/bin/core/imag-category/src/main.rs b/bin/core/imag-category/src/main.rs index c44d0a26..e13d49e3 100644 --- a/bin/core/imag-category/src/main.rs +++ b/bin/core/imag-category/src/main.rs @@ -47,13 +47,10 @@ use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; use libimagrt::runtime::Runtime; use libimagrt::setup::generate_runtime_setup; -use libimagstore::storeid::IntoStoreId; mod ui; use std::io::Write; -use std::io::Read; -use std::path::PathBuf; use libimagentrycategory::store::CategoryStore; use libimagstore::storeid::StoreIdIterator; @@ -93,29 +90,7 @@ fn main() { fn set(rt: &Runtime) { let scmd = rt.cli().subcommand_matches("set").unwrap(); // safed by main() let name = scmd.value_of("set-name").map(String::from).unwrap(); // safed by clap - let sids = match scmd.value_of("set-ids") { - Some(path) => vec![PathBuf::from(path).into_storeid().map_err_trace_exit_unwrap(1)], - None => if rt.cli().is_present("entries-from-stdin") { - let stdin = rt.stdin().unwrap_or_else(|| { - error!("Cannot get handle to stdin"); - ::std::process::exit(1) - }); - - let mut buf = String::new(); - let _ = stdin.lock().read_to_string(&mut buf).unwrap_or_else(|_| { - error!("Failed to read from stdin"); - ::std::process::exit(1) - }); - - buf.lines() - .map(PathBuf::from) - .map(|p| p.into_storeid().map_err_trace_exit_unwrap(1)) - .collect() - } else { - error!("Something weird happened. I was not able to find the path of the entries to edit"); - ::std::process::exit(1) - } - }; + let sids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1); StoreIdIterator::new(Box::new(sids.into_iter().map(Ok))) .into_get_iter(rt.store()) @@ -132,31 +107,7 @@ fn set(rt: &Runtime) { } fn get(rt: &Runtime) { - let scmd = rt.cli().subcommand_matches("get").unwrap(); // safed by main() - let sids = match scmd.value_of("get-ids") { - Some(path) => vec![PathBuf::from(path).into_storeid().map_err_trace_exit_unwrap(1)], - None => if rt.cli().is_present("entries-from-stdin") { - let stdin = rt.stdin().unwrap_or_else(|| { - error!("Cannot get handle to stdin"); - ::std::process::exit(1) - }); - - let mut buf = String::new(); - let _ = stdin.lock().read_to_string(&mut buf).unwrap_or_else(|_| { - error!("Failed to read from stdin"); - ::std::process::exit(1) - }); - - buf.lines() - .map(PathBuf::from) - .map(|p| p.into_storeid().map_err_trace_exit_unwrap(1)) - .collect() - } else { - error!("Something weird happened. I was not able to find the path of the entries to edit"); - ::std::process::exit(1) - } - }; - + let sids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1); let out = rt.stdout(); let mut outlock = out.lock(); diff --git a/bin/core/imag-category/src/ui.rs b/bin/core/imag-category/src/ui.rs index 6d32711c..62f8b144 100644 --- a/bin/core/imag-category/src/ui.rs +++ b/bin/core/imag-category/src/ui.rs @@ -17,7 +17,14 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use clap::{Arg, ArgGroup, App, SubCommand}; +use std::path::PathBuf; + +use clap::{Arg, ArgMatches, App, SubCommand}; + +use libimagstore::storeid::StoreId; +use libimagstore::storeid::IntoStoreId; +use libimagrt::runtime::IdPathProvider; +use libimagerror::trace::MapErrTrace; pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { app @@ -79,17 +86,6 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .multiple(true) .help("The entries to set the category for") .value_name("ID")) - .arg(Arg::with_name("entries-from-stdin") - .long("ids-from-stdin") - .short("I") - .takes_value(false) - .required(false) - .multiple(false) - .help("Read the ids for the entries from stdin")) - - .group(ArgGroup::with_name("input-method") - .args(&["set-ids", "entries-from-stdin"]) - .required(true)) ) .subcommand(SubCommand::with_name("get") @@ -102,17 +98,65 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .multiple(true) .help("The id of the Entry to get the category for") .value_name("ID")) - .arg(Arg::with_name("entries-from-stdin") - .long("ids-from-stdin") - .short("I") - .takes_value(false) - .required(false) - .multiple(false) - .help("Read the ids for the entries from stdin")) - - .group(ArgGroup::with_name("input-method") - .args(&["get-ids", "entries-from-stdin"]) - .required(true)) ) } +pub struct PathProvider; +impl IdPathProvider for PathProvider { + fn get_ids(matches: &ArgMatches) -> Vec { + match matches.subcommand() { + ("create-category", _) => { + error!("Command does not get IDs as input"); + ::std::process::exit(1) + }, + + ("delete-category", _) => { + error!("Command does not get IDs as input"); + ::std::process::exit(1) + }, + + ("list-categories", _) => { + error!("Command does not get IDs as input"); + ::std::process::exit(1) + }, + + ("list-category", _) => { + error!("Command does not get IDs as input"); + ::std::process::exit(1) + }, + + ("set", Some(subm)) => { + subm.values_of("set-ids") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1) + }, + + ("get", Some(subm)) => { + subm.values_of("get-ids") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1) + }, + + (other, _) => { + error!("Not a known command: {}", other); + ::std::process::exit(1) + } + } + } +} From a805db2a88beffc77ee43a3aad7ce67848db2e8c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 29 Sep 2018 17:44:36 +0200 Subject: [PATCH 07/33] Move imag-edit to ID provider infrastructure --- bin/core/imag-edit/src/main.rs | 30 ++-------------------------- bin/core/imag-edit/src/ui.rs | 36 +++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/bin/core/imag-edit/src/main.rs b/bin/core/imag-edit/src/main.rs index 46c4c3f9..6d4ac384 100644 --- a/bin/core/imag-edit/src/main.rs +++ b/bin/core/imag-edit/src/main.rs @@ -41,15 +41,11 @@ extern crate libimagerror; extern crate libimagstore; extern crate libimagutil; -use std::path::PathBuf; -use std::io::Read; - use libimagerror::trace::MapErrTrace; use libimagerror::iter::TraceIterator; use libimagentryedit::edit::Edit; use libimagentryedit::edit::EditHeader; use libimagrt::setup::generate_runtime_setup; -use libimagstore::storeid::IntoStoreId; use libimagstore::storeid::StoreIdIterator; use libimagstore::iter::get::StoreIdGetIteratorExtension; @@ -62,33 +58,11 @@ fn main() { "Edit store entries with $EDITOR", ui::build_ui); - let sids = match rt.cli().value_of("entry") { - Some(path) => vec![PathBuf::from(path).into_storeid().map_err_trace_exit_unwrap(1)], - None => if rt.cli().is_present("entries-from-stdin") { - let stdin = rt.stdin().unwrap_or_else(|| { - error!("Cannot get handle to stdin"); - ::std::process::exit(1) - }); - - let mut buf = String::new(); - let _ = stdin.lock().read_to_string(&mut buf).unwrap_or_else(|_| { - error!("Failed to read from stdin"); - ::std::process::exit(1) - }); - - buf.lines() - .map(PathBuf::from) - .map(|p| p.into_storeid().map_err_trace_exit_unwrap(1)) - .collect() - } else { - error!("Something weird happened. I was not able to find the path of the entries to edit"); - ::std::process::exit(1) - } - }; - let edit_header = rt.cli().is_present("edit-header"); let edit_header_only = rt.cli().is_present("edit-header-only"); + let sids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1); + StoreIdIterator::new(Box::new(sids.into_iter().map(Ok))) .into_get_iter(rt.store()) .trace_unwrap_exit(1) diff --git a/bin/core/imag-edit/src/ui.rs b/bin/core/imag-edit/src/ui.rs index 2f3e8f66..fbb1d5e3 100644 --- a/bin/core/imag-edit/src/ui.rs +++ b/bin/core/imag-edit/src/ui.rs @@ -17,7 +17,14 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use clap::{Arg, ArgGroup, App}; +use std::path::PathBuf; + +use clap::{Arg, ArgMatches, App}; + +use libimagstore::storeid::IntoStoreId; +use libimagstore::storeid::StoreId; +use libimagrt::runtime::IdPathProvider; +use libimagerror::trace::MapErrTrace; pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { app @@ -28,16 +35,6 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .multiple(true) .help("The entry/entries to edit") .value_name("ENTRY")) - .arg(Arg::with_name("entries-from-stdin") - .long("ids-from-stdin") - .short("I") - .takes_value(false) - .required(false) - .multiple(false) - .help("The entry/entries are piped in via stdin")) - .group(ArgGroup::with_name("input-method") - .args(&["entry", "entries-from-stdin"]) - .required(true)) .arg(Arg::with_name("edit-header") .long("header") @@ -55,3 +52,20 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .help("Only edit the header")) } +pub struct PathProvider; +impl IdPathProvider for PathProvider { + fn get_ids(matches: &ArgMatches) -> Vec { + matches + .values_of("entry") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1) + } +} From 70014e04b139a16fcad96b181231f5d7b3d50eb1 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 29 Sep 2018 17:44:36 +0200 Subject: [PATCH 08/33] Move imag-ids to ID provider infrastructure --- bin/core/imag-ids/src/main.rs | 64 +++++++++++++++++++---------------- bin/core/imag-ids/src/ui.rs | 12 ++++++- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/bin/core/imag-ids/src/main.rs b/bin/core/imag-ids/src/main.rs index 63998ce2..b9afc55a 100644 --- a/bin/core/imag-ids/src/main.rs +++ b/bin/core/imag-ids/src/main.rs @@ -53,6 +53,7 @@ use std::process::exit; use filters::filter::Filter; +use libimagstore::storeid::StoreId; use libimagrt::setup::generate_runtime_setup; use libimagerror::trace::MapErrTrace; use libimagerror::iter::TraceIterator; @@ -88,35 +89,40 @@ fn main() { id_filters::header_filter_lang::parse(&query) }); - rt.store() - .entries() - .map_err_trace_exit_unwrap(1) - .trace_unwrap_exit(1) - .filter(|id| collection_filter.filter(id)) - .filter(|id| match query_filter.as_ref() { - None => true, - Some(qf) => { - let entry = rt - .store() - .get(id.clone()) - .map_err_trace_exit_unwrap(1) - .unwrap_or_else(|| { - error!("Tried to get '{}', but it does not exist!", id); - exit(1) - }); + if rt.ids_from_stdin() { + let ids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1); + Box::new(ids.into_iter().map(Ok)) + as Box>> + } else { + Box::new(rt.store().entries().map_err_trace_exit_unwrap(1)) + as Box>> + } + .trace_unwrap_exit(1) + .filter(|id| collection_filter.filter(id)) + .filter(|id| match query_filter.as_ref() { + None => true, + Some(qf) => { + let entry = rt + .store() + .get(id.clone()) + .map_err_trace_exit_unwrap(1) + .unwrap_or_else(|| { + error!("Tried to get '{}', but it does not exist!", id); + exit(1) + }); - qf.filter(&entry) - } - }) - .map(|id| if print_storepath { - id - } else { - id.without_base() - }) - .for_each(|id| { - let _ = writeln!(rt.stdout(), "{}", id.to_str().map_err_trace_exit_unwrap(1)) - .to_exit_code() - .unwrap_or_exit(); - }) + qf.filter(&entry) + } + }) + .map(|id| if print_storepath { + id + } else { + id.without_base() + }) + .for_each(|id| { + let _ = writeln!(rt.stdout(), "{}", id.to_str().map_err_trace_exit_unwrap(1)) + .to_exit_code() + .unwrap_or_exit(); + }); } diff --git a/bin/core/imag-ids/src/ui.rs b/bin/core/imag-ids/src/ui.rs index 61007f14..8d36b188 100644 --- a/bin/core/imag-ids/src/ui.rs +++ b/bin/core/imag-ids/src/ui.rs @@ -17,7 +17,10 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use clap::{Arg, App, SubCommand}; +use clap::{Arg, ArgMatches, App, SubCommand}; + +use libimagstore::storeid::StoreId; +use libimagrt::runtime::IdPathProvider; pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { app @@ -49,3 +52,10 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .after_help(include_str!("../static/language-doc.md")) } +pub struct PathProvider; +impl IdPathProvider for PathProvider { + fn get_ids(_matches: &ArgMatches) -> Vec { + error!("imag-ids does not get IDs via CLI, only via stdin if applying a filter!"); + ::std::process::exit(1) + } +} From 4856541f5ab2294629ccb6b6431359b4a043283c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 1 Oct 2018 12:47:26 +0200 Subject: [PATCH 09/33] Move imag-gps to ID provider infrastructure --- bin/core/imag-gps/src/main.rs | 123 +++++++++++++++++----------------- bin/core/imag-gps/src/ui.rs | 69 +++++++++++++++++-- 2 files changed, 127 insertions(+), 65 deletions(-) diff --git a/bin/core/imag-gps/src/main.rs b/bin/core/imag-gps/src/main.rs index abf121ac..fac2d0c4 100644 --- a/bin/core/imag-gps/src/main.rs +++ b/bin/core/imag-gps/src/main.rs @@ -45,7 +45,6 @@ extern crate libimagstore; use std::io::Write; use std::process::exit; -use std::path::PathBuf; use std::str::FromStr; use failure::Error; @@ -58,7 +57,6 @@ use libimagrt::runtime::Runtime; use libimagerror::trace::MapErrTrace; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; -use libimagstore::storeid::IntoStoreId; mod ui; @@ -88,13 +86,6 @@ fn main() { } fn add(rt: &Runtime) { - let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main() - - let entry_name = scmd.value_of("entry").unwrap(); // safed by clap - let sid = PathBuf::from(entry_name) - .into_storeid() - .map_err_trace_exit_unwrap(1); - let c = { let parse = |value: &str| -> (i64, i64, i64) { debug!("Parsing '{}' into degree, minute and second", value); @@ -120,6 +111,8 @@ fn add(rt: &Runtime) { (*degree, *minute, *second) }; + let scmd = rt.cli().subcommand_matches("add").unwrap(); // safed by main() + let long = parse(scmd.value_of("longitude").unwrap()); // unwrap safed by clap let lati = parse(scmd.value_of("latitude").unwrap()); // unwrap safed by clap @@ -129,70 +122,78 @@ fn add(rt: &Runtime) { Coordinates::new(long, lati) }; - rt.store() - .get(sid) + rt.ids::<::ui::PathProvider>() .map_err_trace_exit_unwrap(1) - .map(|mut entry| { - let _ = entry.set_coordinates(c).map_err_trace_exit_unwrap(1); - }) - .unwrap_or_else(|| { - error!("No such entry: {}", entry_name); - exit(1) + .into_iter() + .for_each(|id| { + rt.store() + .get(id.clone()) + .map_err_trace_exit_unwrap(1) + .unwrap_or_else(|| { // if we have Ok(None) + error!("No such entry: {}", id); + exit(1) + }) + .set_coordinates(c.clone()) + .map_err_trace_exit_unwrap(1); }); } fn remove(rt: &Runtime) { - let scmd = rt.cli().subcommand_matches("remove").unwrap(); // safed by main() + let print_removed = rt + .cli() + .subcommand_matches("remove") + .unwrap() + .is_present("print-removed"); // safed by main() - let entry_name = scmd.value_of("entry").unwrap(); // safed by clap - let sid = PathBuf::from(entry_name) - .into_storeid() - .map_err_trace_exit_unwrap(1); - - let removed_value = rt - .store() - .get(sid) + rt.ids::<::ui::PathProvider>() .map_err_trace_exit_unwrap(1) - .unwrap_or_else(|| { // if we have Ok(None) - error!("No such entry: {}", entry_name); - exit(1) - }) - .remove_coordinates() - .map_err_trace_exit_unwrap(1) // The delete action failed - .unwrap_or_else(|| { // if we have Ok(None) - error!("Entry had no coordinates: {}", entry_name); - exit(1) - }) - .map_err_trace_exit_unwrap(1); // The parsing of the deleted values failed + .into_iter() + .for_each(|id| { + let removed_value = rt + .store() + .get(id.clone()) + .map_err_trace_exit_unwrap(1) + .unwrap_or_else(|| { // if we have Ok(None) + error!("No such entry: {}", id); + exit(1) + }) + .remove_coordinates() + .map_err_trace_exit_unwrap(1) // The delete action failed + .unwrap_or_else(|| { // if we have Ok(None) + error!("Entry had no coordinates: {}", id); + exit(1) + }) + .map_err_trace_exit_unwrap(1); // The parsing of the deleted values failed - if scmd.is_present("print-removed") { - let _ = writeln!(rt.stdout(), "{}", removed_value).to_exit_code().unwrap_or_exit(); - } + if print_removed { + let _ = writeln!(rt.stdout(), "{}", removed_value).to_exit_code().unwrap_or_exit(); + } + }); } fn get(rt: &Runtime) { - let scmd = rt.cli().subcommand_matches("get").unwrap(); // safed by main() - - let entry_name = scmd.value_of("entry").unwrap(); // safed by clap - let sid = PathBuf::from(entry_name) - .into_storeid() - .map_err_trace_exit_unwrap(1); - - let value = rt - .store() - .get(sid) + let mut stdout = rt.stdout(); + rt.ids::<::ui::PathProvider>() .map_err_trace_exit_unwrap(1) - .unwrap_or_else(|| { // if we have Ok(None) - error!("No such entry: {}", entry_name); - exit(1) - }) - .get_coordinates() - .map_err_trace_exit_unwrap(1) // The get action failed - .unwrap_or_else(|| { // if we have Ok(None) - error!("Entry has no coordinates: {}", entry_name); - exit(1) - }); + .into_iter() + .for_each(|id| { + let value = rt + .store() + .get(id.clone()) + .map_err_trace_exit_unwrap(1) + .unwrap_or_else(|| { // if we have Ok(None) + error!("No such entry: {}", id); + exit(1) + }) + .get_coordinates() + .map_err_trace_exit_unwrap(1) // The get action failed + .unwrap_or_else(|| { // if we have Ok(None) + error!("Entry has no coordinates: {}", id); + exit(1) + }); + + let _ = writeln!(stdout, "{}", value).to_exit_code().unwrap_or_exit(); + }) - let _ = writeln!(rt.stdout(), "{}", value).to_exit_code().unwrap_or_exit(); } diff --git a/bin/core/imag-gps/src/ui.rs b/bin/core/imag-gps/src/ui.rs index 24117109..9bf4a4a1 100644 --- a/bin/core/imag-gps/src/ui.rs +++ b/bin/core/imag-gps/src/ui.rs @@ -17,7 +17,14 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use clap::{Arg, App, SubCommand}; +use std::path::PathBuf; + +use clap::{Arg, ArgMatches, App, SubCommand}; + +use libimagstore::storeid::IntoStoreId; +use libimagstore::storeid::StoreId; +use libimagrt::runtime::IdPathProvider; +use libimagerror::trace::MapErrTrace; pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { app @@ -42,7 +49,7 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .index(1) .takes_value(true) .required(true) - .multiple(false) + .multiple(true) .help("The entry to add the latitude/longitude to") .value_name("ENTRY")) ) @@ -60,7 +67,7 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .index(1) .takes_value(true) .required(true) - .multiple(false) + .multiple(true) .help("The entry to remove the latitude/longitude from") .value_name("ENTRY")) ) @@ -72,7 +79,7 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .index(1) .takes_value(true) .required(true) - .multiple(false) + .multiple(true) .help("The entry to get the latitude/longitude from") .value_name("ENTRY")) .arg(Arg::with_name("format-json") @@ -89,3 +96,57 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .help("Print as = pairs (2 lines, default)")) ) } + +pub struct PathProvider; +impl IdPathProvider for PathProvider { + fn get_ids(matches: &ArgMatches) -> Vec { + match matches.subcommand() { + ("add", Some(subm)) => { + subm.values_of("entry") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1) + }, + + ("remove", Some(subm)) => { + subm.values_of("entry") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1) + }, + + ("get", Some(subm)) => { + subm.values_of("get-ids") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1) + }, + + (other, _) => { + error!("Not a known command: {}", other); + ::std::process::exit(1) + } + } + } +} From 527e0310aeec4dbbc1622ff73fa6561d3bf4323a Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 1 Oct 2018 13:17:19 +0200 Subject: [PATCH 10/33] Move imag-link to ID provider infrastructure --- bin/core/imag-link/src/main.rs | 126 ++++++++++++++------------------- bin/core/imag-link/src/ui.rs | 81 ++++++++++++++++++++- 2 files changed, 134 insertions(+), 73 deletions(-) diff --git a/bin/core/imag-link/src/main.rs b/bin/core/imag-link/src/main.rs index ab4a345e..ee9fe426 100644 --- a/bin/core/imag-link/src/main.rs +++ b/bin/core/imag-link/src/main.rs @@ -188,81 +188,63 @@ fn link_from_to<'a, I>(rt: &'a Runtime, from: &'a str, to: I) } fn remove_linking(rt: &Runtime) { - - fn get_from_entry<'a>(rt: &'a Runtime) -> Option> { - rt.cli() - .subcommand_matches("remove") - .unwrap() // safe, we know there is an "remove" subcommand - .value_of("from") - .and_then(|from_name| { - match get_entry_by_name(rt, from_name) { - Err(e) => { - debug!("We couldn't get the entry from name: '{:?}'", from_name); - trace_error(&e); None - }, - Ok(Some(e)) => Some(e), - Ok(None) => None, - } - - }) - } - - let mut from = match get_from_entry(&rt) { - None => warn_exit("No 'from' entry", 1), - Some(s) => s, - }; - - rt.cli() + let mut from = rt.cli() .subcommand_matches("remove") - .unwrap() - .values_of("to") - .map(|values| { - for (entry, value) in values.map(|v| (get_entry_by_name(rt, v), v)) { - match entry { - Err(e) => trace_error(&e), - Ok(Some(mut to_entry)) => { - let _ = to_entry - .remove_internal_link(&mut from) - .map_err_trace_exit_unwrap(1); - }, - Ok(None) => { - // looks like this is not an entry, but a filesystem URI and therefor an - // external link...? - if PathBuf::from(value).is_file() { - let url = Url::parse(value).unwrap_or_else(|e| { - error!("Error parsing URL: {:?}", e); - ::std::process::exit(1); - }); - from.remove_external_link(rt.store(), url).map_err_trace_exit_unwrap(1); - info!("Ok: {}", value); - } else { - warn!("Entry not found: {:?}", value); - } - } + .unwrap() // safe, we know there is an "remove" subcommand + .value_of("from") + .map(PathBuf::from) + .map(|id| { + rt.store() + .get(id) + .map_err_trace_exit_unwrap(1) + .ok_or_else(|| warn_exit("No 'from' entry", 1)) + .unwrap() // safe by line above + }) + .unwrap(); + + rt.ids::<::ui::PathProvider>() + .map_err_trace_exit_unwrap(1) + .into_iter() + .for_each(|id| match rt.store().get(id.clone()) { + Err(e) => trace_error(&e), + Ok(Some(mut to_entry)) => { + let _ = to_entry + .remove_internal_link(&mut from) + .map_err_trace_exit_unwrap(1); + }, + Ok(None) => { + // looks like this is not an entry, but a filesystem URI and therefor an + // external link...? + if id.local().is_file() { + let pb = id.local().to_str().unwrap_or_else(|| { + warn!("Not StoreId and not a Path: {}", id); + ::std::process::exit(1); + }); + let url = Url::parse(pb).unwrap_or_else(|e| { + error!("Error parsing URL: {:?}", e); + ::std::process::exit(1); + }); + from.remove_external_link(rt.store(), url).map_err_trace_exit_unwrap(1); + info!("Ok: {}", id); + } else { + warn!("Entry not found: {:?}", id); } } }); } fn unlink(rt: &Runtime) { - use libimagerror::iter::TraceIterator; - use libimagstore::iter::get::StoreIdGetIteratorExtension; - - let _ = rt - .cli() - .subcommand_matches("unlink") - .unwrap() // checked in main() - .values_of("from") - .unwrap() // checked by clap - .map(PathBuf::from) - .collect::>().into_iter() // for lifetime inference - .map(StoreId::new_baseless) - .into_get_iter(rt.store()) - .trace_unwrap_exit(1) - .filter_map(|x| x) - .map(|mut entry| entry.unlink(rt.store())) - .trace_unwrap_exit(1) - .collect::>(); + rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1).into_iter().for_each(|id| { + rt.store() + .get(id.clone()) + .map_err_trace_exit_unwrap(1) + .unwrap_or_else(|| { + warn!("No entry for {}", id); + ::std::process::exit(1) + }) + .unlink(rt.store()) + .map_err_trace_exit_unwrap(1) + }); } fn list_linkings(rt: &Runtime) { @@ -276,8 +258,8 @@ fn list_linkings(rt: &Runtime) { let mut tab = ::prettytable::Table::new(); tab.set_titles(row!["#", "Link"]); - for entry in cmd.values_of("entries").unwrap() { // safed by clap - match rt.store().get(PathBuf::from(entry)) { + rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1).into_iter().for_each(|id| { + match rt.store().get(id.clone()) { Ok(Some(entry)) => { for (i, link) in entry.get_internal_links().map_err_trace_exit_unwrap(1).enumerate() { let link = link @@ -315,10 +297,10 @@ fn list_linkings(rt: &Runtime) { }) } }, - Ok(None) => warn!("Not found: {}", entry), + Ok(None) => warn!("Not found: {}", id), Err(e) => trace_error(&e), } - } + }); if !list_plain { let out = rt.stdout(); diff --git a/bin/core/imag-link/src/ui.rs b/bin/core/imag-link/src/ui.rs index 3f3136eb..5ca5fca6 100644 --- a/bin/core/imag-link/src/ui.rs +++ b/bin/core/imag-link/src/ui.rs @@ -17,7 +17,15 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use clap::{Arg, App, SubCommand}; +use std::path::PathBuf; + +use clap::{Arg, ArgMatches, App, SubCommand}; + +use libimagstore::storeid::StoreId; +use libimagstore::storeid::IntoStoreId; +use libimagrt::runtime::IdPathProvider; +use libimagerror::trace::MapErrTrace; + pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { app @@ -101,3 +109,74 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .requires("from") .value_name("ENTRIES")) } + +/// PathProvider +/// +/// This PathProvider does _not_ return the "from" value of the commandline call if no subcommand +/// is given. +/// +/// It has to be fetched by main() by hand. +pub struct PathProvider; +impl IdPathProvider for PathProvider { + fn get_ids(matches: &ArgMatches) -> Vec { + let ids = match matches.subcommand() { + ("remove", Some(subm)) => { + let to = subm.values_of("to") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1); + Some(to) + }, + + ("unlink", Some(subm)) => { + let ids = subm + .values_of("from") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1); + + Some(ids) + }, + + ("list", Some(subm)) => { + let ids = subm + .values_of("entries") + .ok_or_else(|| { + error!("No StoreId found"); + ::std::process::exit(1) + }) + .unwrap() + .into_iter() + .map(PathBuf::from) + .map(|pb| pb.into_storeid()) + .collect::, _>>() + .map_err_trace_exit_unwrap(1); + + Some(ids) + }, + + _ => None, + }; + + ids.unwrap_or_else(|| { + matches.values_of("to") + .unwrap() + .map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap(1)) + .collect() + }) + } +} From f83d72033fa6574bc3f5bf249d52719dd099c131 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 4 Oct 2018 18:18:45 +0200 Subject: [PATCH 11/33] Move imag-tag to ID provider infrastructure --- bin/core/imag-tag/src/main.rs | 47 ++++++----------------------------- bin/core/imag-tag/src/ui.rs | 27 +++++++++++++------- 2 files changed, 25 insertions(+), 49 deletions(-) diff --git a/bin/core/imag-tag/src/main.rs b/bin/core/imag-tag/src/main.rs index 25fb6707..ff96418a 100644 --- a/bin/core/imag-tag/src/main.rs +++ b/bin/core/imag-tag/src/main.rs @@ -56,9 +56,7 @@ extern crate toml_query; #[cfg(test)] extern crate env_logger; -use std::path::PathBuf; use std::io::Write; -use std::io::Read; use libimagrt::runtime::Runtime; use libimagrt::setup::generate_runtime_setup; @@ -84,30 +82,7 @@ fn main() { "Direct interface to the store. Use with great care!", build_ui); - let ids : Vec = rt - .cli() - .values_of("id") - .map(|vals| { - vals.map(PathBuf::from).collect() - }).unwrap_or_else(|| { - if !rt.cli().is_present("ids-from-stdin") { - error!("No ids"); - ::std::process::exit(1) - } - - let stdin = rt.stdin().unwrap_or_else(|| { - error!("Cannot get handle to stdin"); - ::std::process::exit(1) - }); - - let mut buf = String::new(); - let _ = stdin.lock().read_to_string(&mut buf).unwrap_or_else(|_| { - error!("Failed to read from stdin"); - ::std::process::exit(1) - }); - - buf.lines().map(PathBuf::from).collect() - }); + let ids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1); rt.cli() .subcommand_name() @@ -116,14 +91,12 @@ fn main() { list(id, &rt) }, "remove" => for id in ids { - let id = PathBuf::from(id); let add = None; let rem = get_remove_tags(rt.cli()); debug!("id = {:?}, add = {:?}, rem = {:?}", id, add, rem); alter(&rt, id, add, rem); }, "add" => for id in ids { - let id = PathBuf::from(id); let add = get_add_tags(rt.cli()); let rem = None; debug!("id = {:?}, add = {:?}, rem = {:?}", id, add, rem); @@ -139,10 +112,7 @@ fn main() { }); } -fn alter(rt: &Runtime, id: PathBuf, add: Option>, rem: Option>) { - let path = StoreId::new(Some(rt.store().path().clone()), id).map_err_trace_exit_unwrap(1); - debug!("path = {:?}", path); - +fn alter(rt: &Runtime, path: StoreId, add: Option>, rem: Option>) { match rt.store().get(path) { Ok(Some(mut e)) => { debug!("Entry header now = {:?}", e.get_header()); @@ -186,10 +156,7 @@ fn alter(rt: &Runtime, id: PathBuf, add: Option>, rem: Option> } } -fn list(id: PathBuf, rt: &Runtime) { - let path = StoreId::new(Some(rt.store().path().clone()), id).map_err_trace_exit_unwrap(1); - debug!("path = {:?}", path); - +fn list(path: StoreId, rt: &Runtime) { let entry = match rt.store().get(path.clone()).map_err_trace_exit_unwrap(1) { Some(e) => e, None => warn_exit("No entry found.", 1), @@ -330,7 +297,7 @@ mod tests { debug!("Add-tags: {:?}", add); debug!("Altering things"); - alter(&rt, id.clone(), add, None); + alter(&rt, StoreId::new_baseless(id.clone()).unwrap(), add, None); debug!("Altered"); let test_entry = rt.store().get(id).unwrap().unwrap(); @@ -365,7 +332,7 @@ mod tests { debug!("Rem-tags: {:?}", rem); debug!("Altering things"); - alter(&rt, id.clone(), add, rem); + alter(&rt, StoreId::new_baseless(id.clone()).unwrap(), add, rem); debug!("Altered"); let test_entry = rt.store().get(id).unwrap().unwrap(); @@ -393,7 +360,7 @@ mod tests { debug!("Rem-tags: {:?}", rem); debug!("Altering things"); - alter(&rt, id.clone(), add, rem); + alter(&rt, StoreId::new_baseless(id.clone()).unwrap(), add, rem); debug!("Altered"); let test_entry = rt.store().get(id).unwrap().unwrap(); @@ -421,7 +388,7 @@ mod tests { debug!("Rem-tags: {:?}", rem); debug!("Altering things"); - alter(&rt, id.clone(), add, rem); + alter(&rt, StoreId::new_baseless(id.clone()).unwrap(), add, rem); debug!("Altered"); let test_entry = rt.store().get(id).unwrap().unwrap(); diff --git a/bin/core/imag-tag/src/ui.rs b/bin/core/imag-tag/src/ui.rs index ec1a565f..3d6a46f8 100644 --- a/bin/core/imag-tag/src/ui.rs +++ b/bin/core/imag-tag/src/ui.rs @@ -17,8 +17,14 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use clap::{Arg, App, ArgGroup, SubCommand}; +use std::path::PathBuf; +use clap::{Arg, ArgMatches, ArgGroup, App, SubCommand}; + +use libimagstore::storeid::StoreId; +use libimagstore::storeid::IntoStoreId; +use libimagrt::runtime::IdPathProvider; +use libimagerror::trace::MapErrTrace; use libimagentrytag::tag::is_tag; pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { @@ -30,14 +36,6 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .value_name("ID") .help("Entry to use")) - .arg(Arg::with_name("ids-from-stdin") - .long("ids-from-stdin") - .short("I") - .takes_value(false) - .required(false) - .multiple(false) - .help("Read store ids to tag from stdin")) - .subcommand(SubCommand::with_name("add") .about("Add tags") .version("0.1") @@ -104,3 +102,14 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { ) } + +pub struct PathProvider; +impl IdPathProvider for PathProvider { + fn get_ids(matches: &ArgMatches) -> Vec { + matches.values_of("id") + .unwrap() + .map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap(1)) + .collect() + } +} + From 274811243ff8bd90159b74af9aac1dc6d322618c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 4 Oct 2018 18:37:40 +0200 Subject: [PATCH 12/33] Move imag-view to ID provider infrastructure --- bin/core/imag-view/src/main.rs | 89 +++++++++++++--------------------- bin/core/imag-view/src/ui.rs | 30 +++++++----- 2 files changed, 53 insertions(+), 66 deletions(-) diff --git a/bin/core/imag-view/src/main.rs b/bin/core/imag-view/src/main.rs index 43ed4b23..fdcedf6d 100644 --- a/bin/core/imag-view/src/main.rs +++ b/bin/core/imag-view/src/main.rs @@ -49,8 +49,6 @@ extern crate libimagutil; use std::str::FromStr; use std::collections::BTreeMap; use std::io::Write; -use std::io::Read; -use std::path::PathBuf; use std::process::Command; use std::process::exit; @@ -83,9 +81,19 @@ fn main() { "View entries (readonly)", build_ui); - let entry_ids = entry_ids(&rt); let view_header = rt.cli().is_present("view-header"); let hide_content = rt.cli().is_present("not-view-content"); + let entry_ids = rt.ids::<::ui::PathProvider>() + .map_err_trace_exit_unwrap(1) + .into_iter() + .map(|x| Ok(x) as Result<_, StoreError>) + .into_get_iter(rt.store()) + .trace_unwrap_exit(1) + .map(|e| { + e.ok_or_else(|| String::from("Entry not found")) + .map_err(StoreError::from) + .map_err_trace_exit_unwrap(1) + }); if rt.cli().is_present("in") { let files = entry_ids @@ -198,17 +206,19 @@ fn main() { let viewer = MarkdownViewer::new(&rt); let seperator = basesep.map(|s| build_seperator(s, sep_width)); - for (n, entry) in iter.enumerate() { - if n != 0 { - seperator - .as_ref() - .map(|s| writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit()); - } + entry_ids + .enumerate() + .for_each(|(n, entry)| { + if n != 0 { + seperator + .as_ref() + .map(|s| writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit()); + } - viewer - .view_entry(&entry, &mut outlock) - .map_err_trace_exit_unwrap(1); - } + viewer + .view_entry(&entry, &mut outlock) + .map_err_trace_exit_unwrap(1); + }); } else { let mut viewer = StdoutViewer::new(view_header, !hide_content); @@ -228,48 +238,19 @@ fn main() { } let seperator = basesep.map(|s| build_seperator(s, sep_width)); - for (n, entry) in iter.enumerate() { - if n != 0 { - seperator - .as_ref() - .map(|s| writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit()); - } + entry_ids + .enumerate() + .for_each(|(n, entry)| { + if n != 0 { + seperator + .as_ref() + .map(|s| writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit()); + } - viewer - .view_entry(&entry, &mut outlock) - .map_err_trace_exit_unwrap(1); - } - } - } -} - -fn entry_ids(rt: &Runtime) -> StoreIdIterator { - match rt.cli().values_of("id") { - Some(p) => { - let pathes : Vec = p.map(String::from).collect(); - let iter = pathes.into_iter().map(PathBuf::from).map(PathBuf::into_storeid); - StoreIdIterator::new(Box::new(iter)) - }, - - None => if rt.cli().is_present("entries-from-stdin") { - let stdin = rt.stdin().unwrap_or_else(|| { - error!("Cannot get handle to stdin"); - ::std::process::exit(1) - }); - - let mut buf = String::new(); - let _ = stdin.lock().read_to_string(&mut buf).unwrap_or_else(|_| { - error!("Failed to read from stdin"); - ::std::process::exit(1) - }); - - let lines : Vec = buf.lines().map(String::from).collect(); - let iter = lines.into_iter().map(PathBuf::from).map(PathBuf::into_storeid); - - StoreIdIterator::new(Box::new(iter)) - } else { - error!("Something weird happened. I was not able to find the path of the entries to edit"); - ::std::process::exit(1) + viewer + .view_entry(&entry, &mut outlock) + .map_err_trace_exit_unwrap(1); + }); } } } diff --git a/bin/core/imag-view/src/ui.rs b/bin/core/imag-view/src/ui.rs index c97bd3f2..13169640 100644 --- a/bin/core/imag-view/src/ui.rs +++ b/bin/core/imag-view/src/ui.rs @@ -17,17 +17,17 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // -use clap::{Arg, ArgGroup, App}; +use std::path::PathBuf; + +use clap::{Arg, ArgMatches, App}; + +use libimagstore::storeid::StoreId; +use libimagstore::storeid::IntoStoreId; +use libimagrt::runtime::IdPathProvider; +use libimagerror::trace::MapErrTrace; pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { app - .arg(Arg::with_name("entries-from-stdin") - .long("ids-from-stdin") - .short("I") - .required(false) - .multiple(true) - .help("The entry/entries are piped in via stdin")) - .arg(Arg::with_name("id") .index(1) .takes_value(true) @@ -36,10 +36,6 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .help("View these entries at this store path") .value_name("IDs")) - .group(ArgGroup::with_name("input-method") - .args(&["id", "entries-from-stdin"]) - .required(true)) - .arg(Arg::with_name("autowrap") .long("autowrap") .short("w") @@ -91,3 +87,13 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .help("View content. If no value is given, this fails. Possible viewers are configured via the config file.")) } + +pub struct PathProvider; +impl IdPathProvider for PathProvider { + fn get_ids(matches: &ArgMatches) -> Vec { + matches.values_of("id") + .unwrap() + .map(|s| PathBuf::from(s).into_storeid().map_err_trace_exit_unwrap(1)) + .collect() + } +} From 3a6443b3ef97982da46775c26e8870a0cfbf4093 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 29 Sep 2018 18:42:38 +0200 Subject: [PATCH 13/33] Add ID reporting in imag-ids Signed-off-by: Matthias Beyer --- bin/core/imag-ids/src/main.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/bin/core/imag-ids/src/main.rs b/bin/core/imag-ids/src/main.rs index b9afc55a..56c31026 100644 --- a/bin/core/imag-ids/src/main.rs +++ b/bin/core/imag-ids/src/main.rs @@ -89,7 +89,8 @@ fn main() { id_filters::header_filter_lang::parse(&query) }); - if rt.ids_from_stdin() { + let iterator = if rt.ids_from_stdin() { + debug!("Fetching IDs from stdin..."); let ids = rt.ids::<::ui::PathProvider>().map_err_trace_exit_unwrap(1); Box::new(ids.into_iter().map(Ok)) as Box>> @@ -118,11 +119,20 @@ fn main() { id } else { id.without_base() - }) - .for_each(|id| { - let _ = writeln!(rt.stdout(), "{}", id.to_str().map_err_trace_exit_unwrap(1)) - .to_exit_code() - .unwrap_or_exit(); }); + + let mut stdout = rt.stdout(); + trace!("Got output: {:?}", stdout); + + iterator.for_each(|id| { + rt.report_touched(&id).map_err_trace_exit_unwrap(1); + if !rt.output_is_pipe() { + let id = id.to_str().map_err_trace_exit_unwrap(1); + trace!("Writing to {:?}", stdout); + let _ = writeln!(stdout, "{}", id) + .to_exit_code() + .unwrap_or_exit(); + } + }) } From ff809a3750ce98cafa3d655ebd60945a6f5dba13 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 1 Oct 2018 12:48:52 +0200 Subject: [PATCH 14/33] Add ID reporting in imag-gps --- bin/core/imag-gps/src/main.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bin/core/imag-gps/src/main.rs b/bin/core/imag-gps/src/main.rs index fac2d0c4..50c94f61 100644 --- a/bin/core/imag-gps/src/main.rs +++ b/bin/core/imag-gps/src/main.rs @@ -135,6 +135,10 @@ fn add(rt: &Runtime) { }) .set_coordinates(c.clone()) .map_err_trace_exit_unwrap(1); + + let _ = rt + .report_touched(&id) + .map_err_trace_exit_unwrap(1); }); } @@ -168,6 +172,10 @@ fn remove(rt: &Runtime) { if print_removed { let _ = writeln!(rt.stdout(), "{}", removed_value).to_exit_code().unwrap_or_exit(); } + + let _ = rt + .report_touched(&id) + .map_err_trace_exit_unwrap(1); }); } @@ -193,6 +201,10 @@ fn get(rt: &Runtime) { }); let _ = writeln!(stdout, "{}", value).to_exit_code().unwrap_or_exit(); + + let _ = rt + .report_touched(&id) + .map_err_trace_exit_unwrap(1); }) } From 4e5315b0e5a3bb0581024ee241a0bd42335e86bc Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 1 Oct 2018 12:53:01 +0200 Subject: [PATCH 15/33] Add ID reporting in imag-grep --- bin/core/imag-grep/src/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/core/imag-grep/src/main.rs b/bin/core/imag-grep/src/main.rs index 223849c9..e9db9b7b 100644 --- a/bin/core/imag-grep/src/main.rs +++ b/bin/core/imag-grep/src/main.rs @@ -122,5 +122,9 @@ fn show(rt: &Runtime, e: &Entry, re: &Regex, opts: &Options, count: &mut usize) let _ = writeln!(rt.stdout(), "").to_exit_code().unwrap_or_exit(); *count += 1; } + + let _ = rt + .report_touched(e.get_location()) + .map_err_trace_exit_unwrap(1); } From aef969f8bbf14db185707c31c48a4bae5071cc84 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 1 Oct 2018 13:23:56 +0200 Subject: [PATCH 16/33] Add ID reporting in imag-link --- bin/core/imag-link/src/main.rs | 39 +++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/bin/core/imag-link/src/main.rs b/bin/core/imag-link/src/main.rs index ee9fe426..5d83d6be 100644 --- a/bin/core/imag-link/src/main.rs +++ b/bin/core/imag-link/src/main.rs @@ -157,9 +157,12 @@ fn link_from_to<'a, I>(rt: &'a Runtime, from: &'a str, to: I) ::std::process::exit(1); }); - let _ = from_entry + let iter = from_entry .add_external_link(rt.store(), url) - .map_err_trace_exit_unwrap(1); + .map_err_trace_exit_unwrap(1) + .into_iter(); + + let _ = rt.report_all_touched(iter).map_err_trace_exit_unwrap(1); } else { debug!("Linking internally: {:?} -> {:?}", from, entry); @@ -181,10 +184,19 @@ fn link_from_to<'a, I>(rt: &'a Runtime, from: &'a str, to: I) let _ = from_entry .add_internal_link(&mut to_entry) .map_err_trace_exit_unwrap(1); + + let _ = rt + .report_touched(to_entry.get_location()) + .map_err_trace_exit_unwrap(1); } + info!("Ok: {} -> {}", from, entry); } + + let _ = rt + .report_touched(from_entry.get_location()) + .map_err_trace_exit_unwrap(1); } fn remove_linking(rt: &Runtime) { @@ -211,6 +223,10 @@ fn remove_linking(rt: &Runtime) { let _ = to_entry .remove_internal_link(&mut from) .map_err_trace_exit_unwrap(1); + + let _ = rt + .report_touched(to_entry.get_location()) + .map_err_trace_exit_unwrap(1); }, Ok(None) => { // looks like this is not an entry, but a filesystem URI and therefor an @@ -231,6 +247,10 @@ fn remove_linking(rt: &Runtime) { } } }); + + let _ = rt + .report_touched(from.get_location()) + .map_err_trace_exit_unwrap(1); } fn unlink(rt: &Runtime) { @@ -243,7 +263,11 @@ fn unlink(rt: &Runtime) { ::std::process::exit(1) }) .unlink(rt.store()) - .map_err_trace_exit_unwrap(1) + .map_err_trace_exit_unwrap(1); + + let _ = rt + .report_touched(&id) + .map_err_trace_exit_unwrap(1); }); } @@ -296,10 +320,19 @@ fn list_linkings(rt: &Runtime) { } }) } + + let _ = rt + .report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); + }, Ok(None) => warn!("Not found: {}", id), Err(e) => trace_error(&e), } + + let _ = rt + .report_touched(&id) + .map_err_trace_exit_unwrap(1); }); if !list_plain { From d3400167dfe9e5cb5a146c24e99b901a622a38bf Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 4 Oct 2018 18:19:52 +0200 Subject: [PATCH 17/33] Add ID reporting in imag-tag --- bin/core/imag-tag/src/main.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/bin/core/imag-tag/src/main.rs b/bin/core/imag-tag/src/main.rs index ff96418a..2b5349d4 100644 --- a/bin/core/imag-tag/src/main.rs +++ b/bin/core/imag-tag/src/main.rs @@ -113,7 +113,7 @@ fn main() { } fn alter(rt: &Runtime, path: StoreId, add: Option>, rem: Option>) { - match rt.store().get(path) { + match rt.store().get(path.clone()) { Ok(Some(mut e)) => { debug!("Entry header now = {:?}", e.get_header()); @@ -154,6 +154,10 @@ fn alter(rt: &Runtime, path: StoreId, add: Option>, rem: Option Date: Thu, 4 Oct 2018 18:39:47 +0200 Subject: [PATCH 18/33] Add ID reporting in imag-view --- bin/core/imag-view/src/main.rs | 42 +++++++++++++++------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/bin/core/imag-view/src/main.rs b/bin/core/imag-view/src/main.rs index fdcedf6d..859e5af5 100644 --- a/bin/core/imag-view/src/main.rs +++ b/bin/core/imag-view/src/main.rs @@ -58,7 +58,6 @@ use failure::Error; use failure::err_msg; use libimagrt::setup::generate_runtime_setup; -use libimagrt::runtime::Runtime; use libimagerror::trace::MapErrTrace; use libimagerror::iter::TraceIterator; use libimagerror::io::ToExitCode; @@ -66,8 +65,6 @@ use libimagerror::exit::ExitUnwrap; use libimagentryview::builtin::stdout::StdoutViewer; use libimagentryview::builtin::md::MarkdownViewer; use libimagentryview::viewer::Viewer; -use libimagstore::storeid::IntoStoreId; -use libimagstore::storeid::StoreIdIterator; use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagstore::store::FileLockEntry; @@ -83,27 +80,26 @@ fn main() { let view_header = rt.cli().is_present("view-header"); let hide_content = rt.cli().is_present("not-view-content"); - let entry_ids = rt.ids::<::ui::PathProvider>() + let entries = rt.ids::<::ui::PathProvider>() .map_err_trace_exit_unwrap(1) .into_iter() - .map(|x| Ok(x) as Result<_, StoreError>) + .map(Ok) .into_get_iter(rt.store()) .trace_unwrap_exit(1) .map(|e| { - e.ok_or_else(|| String::from("Entry not found")) - .map_err(StoreError::from) + e.ok_or_else(|| err_msg("Entry not found")) + .map_err(Error::from) .map_err_trace_exit_unwrap(1) }); if rt.cli().is_present("in") { - let files = entry_ids - .into_get_iter(rt.store()) - .trace_unwrap_exit(1) - .map(|e| { - e.ok_or_else(|| err_msg("Entry not found")) - .map_err_trace_exit_unwrap(1) + let files = entries + .map(|entry| { + let tmpfile = create_tempfile_for(&entry, view_header, hide_content); + rt.report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); + tmpfile }) - .map(|entry| create_tempfile_for(&entry, view_header, hide_content)) .collect::>(); let mut command = { @@ -178,14 +174,6 @@ fn main() { drop(files); } else { - let iter = entry_ids - .into_get_iter(rt.store()) - .map(|e| { - e.map_err_trace_exit_unwrap(1) - .ok_or_else(|| err_msg("Entry not found")) - .map_err_trace_exit_unwrap(1) - }); - let out = rt.stdout(); let mut outlock = out.lock(); @@ -206,7 +194,7 @@ fn main() { let viewer = MarkdownViewer::new(&rt); let seperator = basesep.map(|s| build_seperator(s, sep_width)); - entry_ids + entries .enumerate() .for_each(|(n, entry)| { if n != 0 { @@ -218,6 +206,9 @@ fn main() { viewer .view_entry(&entry, &mut outlock) .map_err_trace_exit_unwrap(1); + + rt.report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); }); } else { let mut viewer = StdoutViewer::new(view_header, !hide_content); @@ -238,7 +229,7 @@ fn main() { } let seperator = basesep.map(|s| build_seperator(s, sep_width)); - entry_ids + entries .enumerate() .for_each(|(n, entry)| { if n != 0 { @@ -250,6 +241,9 @@ fn main() { viewer .view_entry(&entry, &mut outlock) .map_err_trace_exit_unwrap(1); + + rt.report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); }); } } From d1f087eb57290711c66230ba7d0ff2d6ba4c9396 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 6 Oct 2018 13:15:29 +0200 Subject: [PATCH 19/33] Change libimag{bookmark, entrylink} external linking ...to report newly created entries, so that we can re-use these new entries in the library-using code (for example for ID reporting). Signed-off-by: Matthias Beyer --- lib/domain/libimagbookmark/src/collection.rs | 11 +++-- lib/entry/libimagentrylink/src/external.rs | 52 ++++++++++++++++---- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/lib/domain/libimagbookmark/src/collection.rs b/lib/domain/libimagbookmark/src/collection.rs index 22333690..d5945640 100644 --- a/lib/domain/libimagbookmark/src/collection.rs +++ b/lib/domain/libimagbookmark/src/collection.rs @@ -34,6 +34,7 @@ use libimagstore::store::Store; use libimagstore::store::Entry; use libimagstore::store::FileLockEntry; use libimagstore::storeid::IntoStoreId; +use libimagstore::storeid::StoreId; use libimagentrylink::external::ExternalLinker; use libimagentrylink::external::iter::UrlIter; use libimagentrylink::internal::InternalLinker; @@ -76,10 +77,10 @@ impl<'a> BookmarkCollectionStore<'a> for Store { pub trait BookmarkCollection : Sized + InternalLinker + ExternalLinker { fn links<'a>(&self, store: &'a Store) -> Result>; - fn link_entries(&self) -> Result>; - fn add_link(&mut self, store: &Store, l: Link) -> Result<()>; + fn link_entries(&self) -> Result>; + fn add_link(&mut self, store: &Store, l: Link) -> Result>; fn get_links_matching<'a>(&self, store: &'a Store, r: Regex) -> Result>; - fn remove_link(&mut self, store: &Store, l: Link) -> Result<()>; + fn remove_link(&mut self, store: &Store, l: Link) -> Result>; } impl BookmarkCollection for Entry { @@ -93,7 +94,7 @@ impl BookmarkCollection for Entry { self.get_internal_links().map(|v| v.filter(|id| is_external_link_storeid(id)).collect()) } - fn add_link(&mut self, store: &Store, l: Link) -> Result<()> { + fn add_link(&mut self, store: &Store, l: Link) -> Result> { use link::IntoUrl; l.into_url().and_then(|url| self.add_external_link(store, url)) } @@ -103,7 +104,7 @@ impl BookmarkCollection for Entry { self.get_external_links(store).map(|iter| iter.matching_regex(r)) } - fn remove_link(&mut self, store: &Store, l: Link) -> Result<()> { + fn remove_link(&mut self, store: &Store, l: Link) -> Result> { use link::IntoUrl; l.into_url().and_then(|url| self.remove_external_link(store, url)) } diff --git a/lib/entry/libimagentrylink/src/external.rs b/lib/entry/libimagentrylink/src/external.rs index 6b951d46..d4c6956b 100644 --- a/lib/entry/libimagentrylink/src/external.rs +++ b/lib/entry/libimagentrylink/src/external.rs @@ -108,13 +108,13 @@ pub trait ExternalLinker : InternalLinker { fn get_external_links<'a>(&self, store: &'a Store) -> Result>; /// Set the external links for the implementor object - fn set_external_links(&mut self, store: &Store, links: Vec) -> Result<()>; + fn set_external_links(&mut self, store: &Store, links: Vec) -> Result>; /// Add an external link to the implementor object - fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()>; + fn add_external_link(&mut self, store: &Store, link: Url) -> Result>; /// Remove an external link from the implementor object - fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()>; + fn remove_external_link(&mut self, store: &Store, link: Url) -> Result>; } @@ -322,13 +322,20 @@ impl ExternalLinker for Entry { } /// Set the external links for the implementor object - fn set_external_links(&mut self, store: &Store, links: Vec) -> Result<()> { + /// + /// # Return Value + /// + /// Returns the StoreIds which were newly created for the new external links, if there are more + /// external links than before. + /// If there are less external links than before, an empty vec![] is returned. + /// + fn set_external_links(&mut self, store: &Store, links: Vec) -> Result> { // Take all the links, generate a SHA sum out of each one, filter out the already existing // store entries and store the other URIs in the header of one FileLockEntry each, in // the path /link/external/ debug!("Iterating {} links = {:?}", links.len(), links); - for link in links { // for all links + links.into_iter().map(|link| { let hash = hex::encode(Sha1::digest(&link.as_str().as_bytes())); let file_id = ModuleEntryPath::new(format!("external/{}", hash)).into_storeid() @@ -341,6 +348,8 @@ impl ExternalLinker for Entry { debug!("Hash = '{:?}'", hash); debug!("StoreId = '{:?}'", file_id); + let link_already_exists = store.get(file_id.clone())?.is_some(); + // retrieve the file from the store, which implicitely creates the entry if it does not // exist let mut file = store @@ -375,13 +384,27 @@ impl ExternalLinker for Entry { // then add an internal link to the new file or return an error if this fails let _ = self.add_internal_link(file.deref_mut())?; debug!("Error adding internal link"); - } - debug!("Ready iterating"); - Ok(()) + + Ok((link_already_exists, file_id)) + }) + .filter_map(|res| match res { + Ok((exists, entry)) => if exists { Some(Ok(entry)) } else { None }, + Err(e) => Some(Err(e)) + }) + .collect() } /// Add an external link to the implementor object - fn add_external_link(&mut self, store: &Store, link: Url) -> Result<()> { + /// + /// # Return Value + /// + /// (See ExternalLinker::set_external_links()) + /// + /// Returns the StoreIds which were newly created for the new external links, if there are more + /// external links than before. + /// If there are less external links than before, an empty vec![] is returned. + /// + fn add_external_link(&mut self, store: &Store, link: Url) -> Result> { // get external links, add this one, save them debug!("Getting links"); self.get_external_links(store) @@ -396,7 +419,16 @@ impl ExternalLinker for Entry { } /// Remove an external link from the implementor object - fn remove_external_link(&mut self, store: &Store, link: Url) -> Result<()> { + /// + /// # Return Value + /// + /// (See ExternalLinker::set_external_links()) + /// + /// Returns the StoreIds which were newly created for the new external links, if there are more + /// external links than before. + /// If there are less external links than before, an empty vec![] is returned. + /// + fn remove_external_link(&mut self, store: &Store, link: Url) -> Result> { // get external links, remove this one, save them self.get_external_links(store) .and_then(|links| { From 344aae5f924d0220a202d289da75f954214dd66d Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 6 Oct 2018 12:36:31 +0200 Subject: [PATCH 20/33] Add ID reporting in imag-bookmark --- bin/domain/imag-bookmark/src/main.rs | 29 +++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/bin/domain/imag-bookmark/src/main.rs b/bin/domain/imag-bookmark/src/main.rs index 1a9c1893..eae6fdfa 100644 --- a/bin/domain/imag-bookmark/src/main.rs +++ b/bin/domain/imag-bookmark/src/main.rs @@ -98,10 +98,18 @@ fn add(rt: &Runtime) { .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll)) .map_err_trace_exit_unwrap(1); + let _ = rt + .report_touched(collection.get_location()) + .map_err_trace_exit_unwrap(1); + for url in scmd.values_of("urls").unwrap() { // unwrap saved by clap - let _ = collection + let new_ids = collection .add_link(rt.store(), BookmarkLink::from(url)) .map_err_trace_exit_unwrap(1); + + let _ = rt + .report_all_touched(new_ids.into_iter()) + .map_err_trace_exit_unwrap(1); } info!("Ready"); @@ -112,7 +120,8 @@ fn collection(rt: &Runtime) { if scmd.is_present("add") { // adding a new collection let name = scmd.value_of("add").unwrap(); - if let Ok(_) = BookmarkCollectionStore::new(rt.store(), &name) { + if let Ok(id) = BookmarkCollectionStore::new(rt.store(), &name) { + let _ = rt.report_touched(id.get_location()).map_err_trace_exit_unwrap(1); info!("Created: {}", name); } else { warn!("Creating collection {} failed", name); @@ -139,6 +148,10 @@ fn list(rt: &Runtime) { .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll)) .map_err_trace_exit_unwrap(1); + let _ = rt + .report_touched(collection.get_location()) + .map_err_trace_exit_unwrap(1); + let links = collection.links(rt.store()).map_err_trace_exit_unwrap(1); debug!("Listing..."); for (i, link) in links.enumerate() { @@ -148,8 +161,6 @@ fn list(rt: &Runtime) { } }; debug!("... ready with listing"); - - info!("Ready"); } fn remove(rt: &Runtime) { @@ -161,10 +172,18 @@ fn remove(rt: &Runtime) { .ok_or_else(|| format_err!("No bookmark collection '{}' found", coll)) .map_err_trace_exit_unwrap(1); + let _ = rt + .report_touched(collection.get_location()) + .map_err_trace_exit_unwrap(1); + for url in scmd.values_of("urls").unwrap() { // enforced by clap - collection + let removed_links = collection .remove_link(rt.store(), BookmarkLink::from(url)) .map_err_trace_exit_unwrap(1); + + let _ = rt + .report_all_touched(removed_links.into_iter()) + .map_err_trace_exit_unwrap(1); } info!("Ready"); From 8523ae21206042b2fcf19fa832e8d29acf9e0602 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 6 Oct 2018 12:50:12 +0200 Subject: [PATCH 21/33] Add id reporting in imag-contact --- bin/domain/imag-contact/src/create.rs | 5 ++++- bin/domain/imag-contact/src/main.rs | 25 +++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/bin/domain/imag-contact/src/create.rs b/bin/domain/imag-contact/src/create.rs index edac2b2e..a4ac883e 100644 --- a/bin/domain/imag-contact/src/create.rs +++ b/bin/domain/imag-contact/src/create.rs @@ -200,10 +200,13 @@ pub fn create(rt: &Runtime) { if let Some(location) = location { if !scmd.is_present("dont-track") { - rt.store() + let entry = rt.store() .create_from_path(&location) .map_err_trace_exit_unwrap(1); + let _ = rt.report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); + info!("Created entry in store"); } else { info!("Not creating entry in store"); diff --git a/bin/domain/imag-contact/src/main.rs b/bin/domain/imag-contact/src/main.rs index 80cc92cc..dc862080 100644 --- a/bin/domain/imag-contact/src/main.rs +++ b/bin/domain/imag-contact/src/main.rs @@ -122,6 +122,11 @@ fn list(rt: &Runtime) { .trace_unwrap_exit(1) .map(|fle| fle.ok_or_else(|| Error::from(err_msg("StoreId not found".to_owned())))) .trace_unwrap_exit(1) + .map(|fle| { + let _ = rt.report_touched(fle.get_location()) + .map_err_trace_exit_unwrap(1); + fle + }) .map(|e| e.deser()) .trace_unwrap_exit(1) .enumerate(); @@ -163,21 +168,30 @@ fn import(rt: &Runtime) { } if path.is_file() { - let _ = rt + let entry = rt .store() .retrieve_from_path(&path) .map_err_trace_exit_unwrap(1); + + let _ = rt + .report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); } else if path.is_dir() { for entry in WalkDir::new(path).min_depth(1).into_iter() { let entry = entry .map_err(Error::from) .map_err_trace_exit_unwrap(1); + if entry.file_type().is_file() { let pb = PathBuf::from(entry.path()); - let _ = rt + let fle = rt .store() .retrieve_from_path(&pb) .map_err_trace_exit_unwrap(1); + + let _ = rt + .report_touched(fle.get_location()) + .map_err_trace_exit_unwrap(1); info!("Imported: {}", entry.path().to_str().unwrap_or("")); } else { warn!("Ignoring non-file: {}", entry.path().to_str().unwrap_or("")); @@ -216,6 +230,9 @@ fn show(rt: &Runtime) { .unwrap() // exited above .starts_with(&hash) { + let _ = rt + .report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); Some(deser) } else { None @@ -270,6 +287,10 @@ fn find(rt: &Runtime) { || card.fullname().iter().any(|a| str_contains_any(a, &grepstring)); if take { + let _ = rt + .report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); + // optimization so we don't have to parse again in the next step Some((entry, card)) } else { From 2ca6be8322192373869e577b26da998fed8cd927 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 6 Oct 2018 12:50:20 +0200 Subject: [PATCH 22/33] Add id reporting in imag-diary --- bin/domain/imag-diary/src/create.rs | 2 ++ bin/domain/imag-diary/src/delete.rs | 4 ++++ bin/domain/imag-diary/src/list.rs | 8 +++++++- bin/domain/imag-diary/src/view.rs | 8 ++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/bin/domain/imag-diary/src/create.rs b/bin/domain/imag-diary/src/create.rs index 6fb730f8..9d2adb1f 100644 --- a/bin/domain/imag-diary/src/create.rs +++ b/bin/domain/imag-diary/src/create.rs @@ -43,6 +43,8 @@ pub fn create(rt: &Runtime) { let mut entry = create_entry(rt.store(), &diaryname, rt); + let _ = rt.report_touched(entry.get_location()).map_err_trace_exit_unwrap(1); + let res = if rt.cli().subcommand_matches("create").unwrap().is_present("no-edit") { debug!("Not editing new diary entry"); Ok(()) diff --git a/bin/domain/imag-diary/src/delete.rs b/bin/domain/imag-diary/src/delete.rs index d8ccd47d..ec3592c3 100644 --- a/bin/domain/imag-diary/src/delete.rs +++ b/bin/domain/imag-diary/src/delete.rs @@ -66,6 +66,10 @@ pub fn delete(rt: &Runtime) { return; } + let _ = rt + .report_touched(&to_del_location) + .map_err_trace_exit_unwrap(1); + let _ = rt .store() .delete(to_del_location) diff --git a/bin/domain/imag-diary/src/list.rs b/bin/domain/imag-diary/src/list.rs index e5a2b3ff..31389ae9 100644 --- a/bin/domain/imag-diary/src/list.rs +++ b/bin/domain/imag-diary/src/list.rs @@ -54,6 +54,12 @@ pub fn list(rt: &Runtime) { ids.into_iter() .map(IntoStoreId::into_storeid) .trace_unwrap_exit(1) - .for_each(|id| writeln!(rt.stdout(), "{}", id).to_exit_code().unwrap_or_exit()); + .for_each(|id| { + let _ = rt + .report_touched(&id) + .map_err_trace_exit_unwrap(1); + + writeln!(rt.stdout(), "{}", id).to_exit_code().unwrap_or_exit() + }); } diff --git a/bin/domain/imag-diary/src/view.rs b/bin/domain/imag-diary/src/view.rs index 763d2456..2bd8e047 100644 --- a/bin/domain/imag-diary/src/view.rs +++ b/bin/domain/imag-diary/src/view.rs @@ -41,6 +41,14 @@ pub fn view(rt: &Runtime) { ::std::process::exit(1) })); + let entries = entries.map(|e| { + let _ = rt + .report_touched(e.get_location()) + .map_err_trace_exit_unwrap(1); + + e + }); + let out = rt.stdout(); DV::new(hdr).view_entries(entries, &mut out.lock()) .map_err_trace_exit_unwrap(1); From eceae358f8cce1b7f570641ce8b3d1b6df28e9b4 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 10 Oct 2018 23:17:21 +0200 Subject: [PATCH 23/33] Add ID reporting in imag-notes --- bin/domain/imag-notes/src/main.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/bin/domain/imag-notes/src/main.rs b/bin/domain/imag-notes/src/main.rs index 188fe9a3..c7b11300 100644 --- a/bin/domain/imag-notes/src/main.rs +++ b/bin/domain/imag-notes/src/main.rs @@ -109,6 +109,10 @@ fn create(rt: &Runtime) { .map_warn_err_str("Editing failed") .map_err_trace_exit_unwrap(1); } + + let _ = rt + .report_touched(note.get_location()) + .map_err_trace_exit_unwrap(1); } fn delete(rt: &Runtime) { @@ -129,6 +133,10 @@ fn edit(rt: &Runtime) { .edit_content(rt) .map_warn_err_str("Editing failed") .map_err_trace_exit_unwrap(1); + + let _ = rt + .report_touched(note.get_location()) + .map_err_trace_exit_unwrap(1); }) .unwrap_or_else(|| { error!("Cannot find note with name '{}'", name); @@ -156,9 +164,13 @@ fn list(rt: &Runtime) { .iter() .for_each(|note| { let name = note.get_name().map_err_trace_exit_unwrap(1); - writeln!(rt.stdout(), "{}", name) + let _ = writeln!(rt.stdout(), "{}", name) .to_exit_code() - .unwrap_or_exit() + .unwrap_or_exit(); + + let _ = rt + .report_touched(note.get_location()) + .map_err_trace_exit_unwrap(1); }); } From 860c58cbdfcb0a8229bcc60183b93be74da07b9f Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 11 Oct 2018 00:13:30 +0200 Subject: [PATCH 24/33] Add ID reporting in imag-log --- bin/domain/imag-log/src/main.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/domain/imag-log/src/main.rs b/bin/domain/imag-log/src/main.rs index 56d50189..5b6f01d2 100644 --- a/bin/domain/imag-log/src/main.rs +++ b/bin/domain/imag-log/src/main.rs @@ -57,6 +57,7 @@ use libimagerror::trace::MapErrTrace; use libimagerror::io::ToExitCode; use libimagerror::exit::ExitUnwrap; use libimagerror::iter::TraceIterator; +use libimagerror::exit::ExitCode; use libimagdiary::diary::Diary; use libimaglog::log::Log; use libimagstore::iter::get::StoreIdGetIteratorExtension; @@ -156,7 +157,7 @@ fn show(rt: &Runtime) { .into_iter() .map(|(id, entry)| { debug!("Found entry: {:?}", entry); - writeln!(rt.stdout(), + let _ = writeln!(rt.stdout(), "{dname: >10} - {y: >4}-{m:0>2}-{d:0>2}T{H:0>2}:{M:0>2} - {text}", dname = id.diary_name(), y = id.year(), @@ -165,9 +166,14 @@ fn show(rt: &Runtime) { H = id.hour(), M = id.minute(), text = entry.get_content()) - .to_exit_code() + .to_exit_code()?; + + let _ = rt + .report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); + Ok(()) }) - .collect::, _>>() + .collect::, ExitCode>>() .unwrap_or_exit(); } } From 029a3c448ed02048d479c20a92d9b6ece4550615 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 17 Oct 2018 14:43:21 +0200 Subject: [PATCH 25/33] Change WikiStore::create_wiki() interface to also return the index page. This way a user of the library can use the index page entry right away. Signed-off-by: Matthias Beyer --- lib/domain/libimagwiki/src/store.rs | 18 +++++++++++------- lib/domain/libimagwiki/src/wiki.rs | 11 +++++++++++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/domain/libimagwiki/src/store.rs b/lib/domain/libimagwiki/src/store.rs index 89b7093b..5ee5bd32 100644 --- a/lib/domain/libimagwiki/src/store.rs +++ b/lib/domain/libimagwiki/src/store.rs @@ -17,6 +17,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +use libimagstore::store::FileLockEntry; use libimagstore::store::Store; use libimagstore::storeid::StoreId; use libimagstore::storeid::IntoStoreId; @@ -30,10 +31,10 @@ pub trait WikiStore { fn get_wiki<'a, 'b>(&'a self, name: &'b str) -> Result>>; fn create_wiki<'a, 'b>(&'a self, name: &'b str) - -> Result>; + -> Result<(Wiki<'a, 'b>, FileLockEntry<'a>)>; fn retrieve_wiki<'a, 'b>(&'a self, name: &'b str) - -> Result>; + -> Result<(Wiki<'a, 'b>, FileLockEntry<'a>)>; } @@ -59,20 +60,23 @@ impl WikiStore for Store { /// Ob success, an empty Wiki entry with the name `index` is created inside the wiki. Later, new /// entries are automatically linked to this entry. /// - fn create_wiki<'a, 'b>(&'a self, name: &'b str) -> Result> { + fn create_wiki<'a, 'b>(&'a self, name: &'b str) -> Result<(Wiki<'a, 'b>, FileLockEntry<'a>)> { debug!("Trying to get wiki '{}'", name); let wiki = Wiki::new(self, name); - let _ = wiki.create_index_page()?; - Ok(wiki) + let index = wiki.create_index_page()?; + Ok((wiki, index)) } fn retrieve_wiki<'a, 'b>(&'a self, name: &'b str) - -> Result> + -> Result<(Wiki<'a, 'b>, FileLockEntry<'a>)> { match self.get_wiki(name)? { None => self.create_wiki(name), - Some(wiki) => Ok(wiki), + Some(wiki) => { + let index = wiki.get_index_page()?; + Ok((wiki, index)) + }, } } diff --git a/lib/domain/libimagwiki/src/wiki.rs b/lib/domain/libimagwiki/src/wiki.rs index c3888710..5e87c150 100644 --- a/lib/domain/libimagwiki/src/wiki.rs +++ b/lib/domain/libimagwiki/src/wiki.rs @@ -30,6 +30,7 @@ use libimagstore::storeid::StoreIdIteratorWithStore; use libimagentrylink::internal::InternalLinker; use failure::Fallible as Result; +use failure::Error; use failure::err_msg; pub struct Wiki<'a, 'b>(&'a Store, &'b str); @@ -56,6 +57,16 @@ impl<'a, 'b> Wiki<'a, 'b> { self.0.create(sid) } + pub(crate) fn get_index_page(&self) -> Result> { + let path = PathBuf::from(format!("{}/index", self.1)); + let sid = ::module_path::ModuleEntryPath::new(path).into_storeid()?; + + self.0 + .get(sid) + .map_err(Error::from)? + .ok_or_else(|| Error::from(err_msg("Missing index"))) + } + pub fn get_entry>(&self, entry_name: EN) -> Result>> { let path = PathBuf::from(format!("{}/{}", self.1, entry_name.as_ref())); let sid = ::module_path::ModuleEntryPath::new(path).into_storeid()?; From f3a03efd5d3272bb79b3fc723f2c2a169d4a8e2c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 17 Oct 2018 14:45:58 +0200 Subject: [PATCH 26/33] Add ID reporting in imag-wiki Signed-off-by: Matthias Beyer --- bin/domain/imag-wiki/src/main.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/bin/domain/imag-wiki/src/main.rs b/bin/domain/imag-wiki/src/main.rs index 6e586009..c8f55267 100644 --- a/bin/domain/imag-wiki/src/main.rs +++ b/bin/domain/imag-wiki/src/main.rs @@ -170,19 +170,28 @@ fn create(rt: &Runtime, wiki_name: &str) { .map_warn_err_str("Safed entry") .map_err_trace_exit_unwrap(1); + let id = entry.get_location(); + if scmd.is_present("create-printid") { let out = rt.stdout(); let mut lock = out.lock(); - let id = entry.get_location(); writeln!(lock, "{}", id).to_exit_code().unwrap_or_exit() } + + let _ = rt + .report_touched(&id) + .map_err_trace_exit_unwrap(1); } fn create_wiki(rt: &Runtime) { - let scmd = rt.cli().subcommand_matches("create-wiki").unwrap(); // safed by clap - let wiki_name = String::from(scmd.value_of("create-wiki-name").unwrap()); // safe by clap - let _ = rt.store().create_wiki(&wiki_name).map_err_trace_exit_unwrap(1); + let scmd = rt.cli().subcommand_matches("create-wiki").unwrap(); // safed by clap + let wiki_name = String::from(scmd.value_of("create-wiki-name").unwrap()); // safe by clap + let (_, index) = rt.store().create_wiki(&wiki_name).map_err_trace_exit_unwrap(1); + + let _ = rt + .report_touched(index.get_location()) + .map_err_trace_exit_unwrap(1); } fn show(rt: &Runtime, wiki_name: &str) { @@ -239,6 +248,10 @@ fn show(rt: &Runtime, wiki_name: &str) { writeln!(outlock, "{}", entry.get_content()) .to_exit_code() .unwrap_or_exit(); + + let _ = rt + .report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); } } From 96ad41ea4cbecc1939b780b0b116f8a53751accd Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 1 Nov 2018 17:57:22 +0100 Subject: [PATCH 27/33] Add ID reporting in imag-mv --- bin/core/imag-mv/src/main.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/core/imag-mv/src/main.rs b/bin/core/imag-mv/src/main.rs index 3dfb9798..1e77fce8 100644 --- a/bin/core/imag-mv/src/main.rs +++ b/bin/core/imag-mv/src/main.rs @@ -129,6 +129,9 @@ fn main() { }) .map_err_trace_exit_unwrap(1); + let _ = rt.report_touched(&destname) + .map_err_trace_exit_unwrap(1); + // re-add links to moved entry relink(rt.store(), destname, &mut linked_entries); From 502cdf57216efbb514e837c6f6f3fc318084ed05 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 1 Nov 2018 18:07:57 +0100 Subject: [PATCH 28/33] Add ID reporting in imag-habit --- bin/domain/imag-habit/src/main.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/bin/domain/imag-habit/src/main.rs b/bin/domain/imag-habit/src/main.rs index 7aa49664..8c2c951d 100644 --- a/bin/domain/imag-habit/src/main.rs +++ b/bin/domain/imag-habit/src/main.rs @@ -152,7 +152,8 @@ fn create(rt: &Runtime) { debug!("Builder = {:?}", hb); - hb.build(rt.store()).map_err_trace_exit_unwrap(1); + let fle = hb.build(rt.store()).map_err_trace_exit_unwrap(1); + let _ = rt.report_touched(fle.get_location()).map_err_trace_exit_unwrap(1); } fn delete(rt: &Runtime) { @@ -370,6 +371,13 @@ fn today(rt: &Runtime, future: bool) { { let mut v = vec![format!("{}", i)]; let mut list = lister_fn(&e); + + { + let _ = rt + .report_touched(e.get_location()) + .map_err_trace_exit_unwrap(1); + } + v.append(&mut list); table.add_row(v.iter().map(|s| Cell::new(s)).collect()); empty = false; @@ -426,6 +434,13 @@ fn list(rt: &Runtime) { .for_each(|(i, e)| { let mut v = vec![format!("{}", i)]; let mut list = lister_fn(&e); + + { + let _ = rt + .report_touched(e.get_location()) + .map_err_trace_exit_unwrap(1); + } + v.append(&mut list); table.add_row(v.iter().map(|s| Cell::new(s)).collect()); empty = false; @@ -443,7 +458,6 @@ fn show(rt: &Runtime) { .map(String::from) .unwrap(); // safe by clap - fn instance_lister_fn(i: &FileLockEntry) -> Vec { use libimagutil::date::date_to_string; use libimaghabit::instance::HabitInstance; @@ -499,6 +513,13 @@ fn show(rt: &Runtime) { .for_each(|(i, e)| { let mut v = vec![format!("{}", i)]; let mut instances = instance_lister_fn(&e); + + { + let _ = rt + .report_touched(e.get_location()) + .map_err_trace_exit_unwrap(1); + } + v.append(&mut instances); table.add_row(v.iter().map(|s| Cell::new(s)).collect()); empty = false; @@ -555,6 +576,12 @@ fn done(rt: &Runtime) { next_instance_name); } + { + let _ = rt + .report_touched(r.get_location()) + .map_err_trace_exit_unwrap(1); + } + } info!("Done."); } From c616a5cfafe9c4963b7399f75d3abb3ae152f57d Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 2 Nov 2018 10:57:42 +0100 Subject: [PATCH 29/33] Add ID reporting in imag-ref --- bin/core/imag-ref/src/main.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/bin/core/imag-ref/src/main.rs b/bin/core/imag-ref/src/main.rs index d273ec90..c0f22f95 100644 --- a/bin/core/imag-ref/src/main.rs +++ b/bin/core/imag-ref/src/main.rs @@ -88,16 +88,20 @@ fn deref(rt: &Runtime) { .map_err_trace_exit_unwrap(1); match rt.store().get(id.clone()).map_err_trace_exit_unwrap(1) { - Some(entry) => entry - .get_path() - .map_err_trace_exit_unwrap(1) - .to_str() - .ok_or_else(|| { - error!("Could not transform path into string!"); - exit(1) - }) - .map(|s| info!("{}", s)) - .ok(), // safe here because we exited already in the error case + Some(entry) => { + entry + .get_path() + .map_err_trace_exit_unwrap(1) + .to_str() + .ok_or_else(|| { + error!("Could not transform path into string!"); + exit(1) + }) + .map(|s| info!("{}", s)) + .ok(); // safe here because we exited already in the error case + + let _ = rt.report_touched(&id).map_err_trace_exit_unwrap(1); + }, None => { error!("No entry for id '{}' found", id); exit(1) From f20298cbe8995790af138b0e231e3b4b53ede7e8 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 2 Nov 2018 11:08:22 +0100 Subject: [PATCH 30/33] Add ID reporting in imag-store --- bin/core/imag-store/src/create.rs | 2 ++ bin/core/imag-store/src/get.rs | 7 +++++-- bin/core/imag-store/src/retrieve.rs | 6 ++++-- bin/core/imag-store/src/update.rs | 20 ++++++++++++-------- bin/core/imag-store/src/verify.rs | 1 + 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/bin/core/imag-store/src/create.rs b/bin/core/imag-store/src/create.rs index 6ee5ecfe..866f3aba 100644 --- a/bin/core/imag-store/src/create.rs +++ b/bin/core/imag-store/src/create.rs @@ -62,6 +62,8 @@ pub fn create(rt: &Runtime) { Entry::default_header()) } .map_err_trace_exit_unwrap(1); + + let _ = rt.report_touched(&path).map_err_trace_exit_unwrap(1); } fn create_from_cli_spec(rt: &Runtime, matches: &ArgMatches, path: &StoreId) -> Result<()> { diff --git a/bin/core/imag-store/src/get.rs b/bin/core/imag-store/src/get.rs index b9324fef..666bbb92 100644 --- a/bin/core/imag-store/src/get.rs +++ b/bin/core/imag-store/src/get.rs @@ -34,8 +34,11 @@ pub fn get(rt: &Runtime) { let path = StoreId::new(store, path).map_err_trace_exit_unwrap(1); debug!("path = {:?}", path); - let _ = match rt.store().get(path).map_err_trace_exit_unwrap(1) { - Some(entry) => print_entry(rt, scmd, entry), + let _ = match rt.store().get(path.clone()).map_err_trace_exit_unwrap(1) { + Some(entry) => { + print_entry(rt, scmd, entry); + let _ = rt.report_touched(&path).map_err_trace_exit_unwrap(1); + }, None => info!("No entry found"), }; } diff --git a/bin/core/imag-store/src/retrieve.rs b/bin/core/imag-store/src/retrieve.rs index 68ef5491..69201f8e 100644 --- a/bin/core/imag-store/src/retrieve.rs +++ b/bin/core/imag-store/src/retrieve.rs @@ -42,11 +42,13 @@ pub fn retrieve(rt: &Runtime) { debug!("path = {:?}", path); rt.store() - .retrieve(path) + .retrieve(path.clone()) .map(|e| print_entry(rt, scmd, e)) .map_dbg_str("No entry") .map_dbg(|e| format!("{:?}", e)) - .map_err_trace() + .map_err_trace_exit_unwrap(1); + + let _ = rt.report_touched(&path).map_err_trace_exit_unwrap(1); }); } diff --git a/bin/core/imag-store/src/update.rs b/bin/core/imag-store/src/update.rs index 981c8089..9bb0d943 100644 --- a/bin/core/imag-store/src/update.rs +++ b/bin/core/imag-store/src/update.rs @@ -36,16 +36,20 @@ pub fn update(rt: &Runtime) { let _ = rt.store() .retrieve(path) .map(|mut locked_e| { - let e = locked_e.deref_mut(); + { + let e = locked_e.deref_mut(); - scmd.value_of("content") - .map(|new_content| { - *e.get_content_mut() = String::from(new_content); - debug!("New content set"); - }); + scmd.value_of("content") + .map(|new_content| { + *e.get_content_mut() = String::from(new_content); + debug!("New content set"); + }); - *e.get_header_mut() = build_toml_header(scmd, e.get_header().clone()); - debug!("New header set"); + *e.get_header_mut() = build_toml_header(scmd, e.get_header().clone()); + debug!("New header set"); + } + + let _ = rt.report_touched(locked_e.get_location()).map_err_trace_exit_unwrap(1); }); } diff --git a/bin/core/imag-store/src/verify.rs b/bin/core/imag-store/src/verify.rs index 8fa00981..9abefb5e 100644 --- a/bin/core/imag-store/src/verify.rs +++ b/bin/core/imag-store/src/verify.rs @@ -47,6 +47,7 @@ pub fn verify(rt: &Runtime) { }; info!("{: >6} | {: >14} | {:?}", verify, content_len, p.deref()); + let _ = rt.report_touched(fle.get_location()).map_err_trace_exit_unwrap(1); status }); From be56f9fe75dad8fc23adf97d611fba84daf95ba0 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 2 Nov 2018 11:12:48 +0100 Subject: [PATCH 31/33] Add ID reporting in imag-mail --- bin/domain/imag-mail/src/main.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bin/domain/imag-mail/src/main.rs b/bin/domain/imag-mail/src/main.rs index c7975480..d43653c5 100644 --- a/bin/domain/imag-mail/src/main.rs +++ b/bin/domain/imag-mail/src/main.rs @@ -89,9 +89,11 @@ fn import_mail(rt: &Runtime) { let scmd = rt.cli().subcommand_matches("import-mail").unwrap(); let path = scmd.value_of("path").unwrap(); // enforced by clap - let _ = Mail::import_from_path(rt.store(), path) - .map_err_trace() - .map_info_str("Ok"); + let mail = Mail::import_from_path(rt.store(), path) + .map_info_str("Ok") + .map_err_trace_exit_unwrap(1); + + let _ = rt.report_touched(mail.fle().get_location()).map_err_trace_exit_unwrap(1); } fn list(rt: &Runtime) { @@ -141,7 +143,9 @@ fn list(rt: &Runtime) { id = id, subj = subject, to = to - ).to_exit_code().unwrap_or_exit() + ).to_exit_code().unwrap_or_exit(); + + let _ = rt.report_touched(m.fle().get_location()).map_err_trace_exit_unwrap(1); } let _ = rt.store() From f6483f54db37ce1ea612fec1d51d7735362129bd Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 2 Nov 2018 11:23:48 +0100 Subject: [PATCH 32/33] Add ID reporting in imag-timetrack --- bin/domain/imag-timetrack/src/cont.rs | 9 +++++++-- bin/domain/imag-timetrack/src/day.rs | 3 +++ bin/domain/imag-timetrack/src/list.rs | 3 +++ bin/domain/imag-timetrack/src/month.rs | 3 +++ bin/domain/imag-timetrack/src/start.rs | 19 +++++++++++++------ bin/domain/imag-timetrack/src/stop.rs | 17 ++++++++++++----- bin/domain/imag-timetrack/src/track.rs | 16 ++++++++++------ bin/domain/imag-timetrack/src/week.rs | 3 +++ bin/domain/imag-timetrack/src/year.rs | 3 +++ 9 files changed, 57 insertions(+), 19 deletions(-) diff --git a/bin/domain/imag-timetrack/src/cont.rs b/bin/domain/imag-timetrack/src/cont.rs index 1e81e7af..b9d34f17 100644 --- a/bin/domain/imag-timetrack/src/cont.rs +++ b/bin/domain/imag-timetrack/src/cont.rs @@ -81,11 +81,16 @@ pub fn cont(rt: &Runtime) -> i32 { acc.and_then(|_| { // create a new tracking with the same tag - tracking + let val = tracking .get_timetrack_tag() .and_then(|tag| rt.store().create_timetracking_now(&tag)) .map(|_| 0) - .map_err_trace() + .map_err_trace(); + + let _ = rt.report_touched(tracking.get_location()) + .map_err_trace_exit_unwrap(1); + + val }) }) }, diff --git a/bin/domain/imag-timetrack/src/day.rs b/bin/domain/imag-timetrack/src/day.rs index 378b89dc..e2c05f8d 100644 --- a/bin/domain/imag-timetrack/src/day.rs +++ b/bin/domain/imag-timetrack/src/day.rs @@ -103,6 +103,9 @@ pub fn day(rt: &Runtime) -> i32 { let end = e.get_end_datetime()?; debug!(" -> end = {:?}", end); + let _ = rt.report_touched(e.get_location()) + .map_err_trace_exit_unwrap(1); + Ok((tag, start, end)) }) .trace_unwrap_exit(1) diff --git a/bin/domain/imag-timetrack/src/list.rs b/bin/domain/imag-timetrack/src/list.rs index 13de6412..08545f64 100644 --- a/bin/domain/imag-timetrack/src/list.rs +++ b/bin/domain/imag-timetrack/src/list.rs @@ -162,6 +162,9 @@ pub fn list_impl(rt: &Runtime, .collect(); tab.add_row(Row::new(cells)); + let _ = rt.report_touched(e.get_location()) + .map_err_trace_exit_unwrap(1); + Ok(tab) }) }) diff --git a/bin/domain/imag-timetrack/src/month.rs b/bin/domain/imag-timetrack/src/month.rs index 7a65f64f..1ca7d686 100644 --- a/bin/domain/imag-timetrack/src/month.rs +++ b/bin/domain/imag-timetrack/src/month.rs @@ -118,6 +118,9 @@ pub fn month(rt: &Runtime) -> i32 { let end = e.get_end_datetime()?; debug!(" -> end = {:?}", end); + let _ = rt.report_touched(e.get_location()) + .map_err_trace_exit_unwrap(1); + Ok((tag, start, end)) }) .trace_unwrap_exit(1) diff --git a/bin/domain/imag-timetrack/src/start.rs b/bin/domain/imag-timetrack/src/start.rs index abf18b93..f7db9e08 100644 --- a/bin/domain/imag-timetrack/src/start.rs +++ b/bin/domain/imag-timetrack/src/start.rs @@ -24,9 +24,9 @@ use failure::Error; use libimagrt::runtime::Runtime; use libimagerror::trace::trace_error; +use libimagerror::trace::MapErrTrace; use libimagtimetrack::tag::TimeTrackingTag; use libimagtimetrack::timetrackingstore::TimeTrackStore; -use libimagerror::trace::MapErrTrace; pub fn start(rt: &Runtime) -> i32 { let (_, cmd) = rt.cli().subcommand(); @@ -49,11 +49,18 @@ pub fn start(rt: &Runtime) -> i32 { .map(String::from) .map(TimeTrackingTag::from) .fold(0, |acc, ttt| { - rt.store() - .create_timetracking_at(&start, &ttt) - .map_err_trace() - .map(|_| acc) - .unwrap_or(1) + match rt.store().create_timetracking_at(&start, &ttt) { + Err(e) => { + trace_error(&e); + 1 + }, + Ok(entry) => { + let _ = rt.report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); + + acc + } + } }) } diff --git a/bin/domain/imag-timetrack/src/stop.rs b/bin/domain/imag-timetrack/src/stop.rs index 539c80a4..f46f666d 100644 --- a/bin/domain/imag-timetrack/src/stop.rs +++ b/bin/domain/imag-timetrack/src/stop.rs @@ -34,7 +34,6 @@ use libimagtimetrack::timetrackingstore::*; use libimagtimetrack::iter::filter::has_end_time; use libimagtimetrack::iter::filter::has_one_of_tags; use libimagutil::warn_result::*; -use libimagutil::debug_result::*; pub fn stop(rt: &Runtime) -> i32 { let (_, cmd) = rt.cli().subcommand(); @@ -92,10 +91,18 @@ pub fn stop(rt: &Runtime) -> i32 { // for each of these timetrackings, end them // for each result, print the backtrace (if any) .fold(0, |acc, mut elem| { - elem.set_end_datetime(stop_time.clone()) - .map_dbg(|e| format!("Setting end time worked: {:?}", e)) - .map(|_| acc) - .map_err_trace_exit_unwrap(1) + match elem.set_end_datetime(stop_time.clone()) { + Err(e) => { + trace_error(&e); + 1 + } + Ok(_) => { + format!("Setting end time worked: {:?}", elem); + let _ = rt.report_touched(elem.get_location()) + .map_err_trace_exit_unwrap(1); + acc + } + } }) } diff --git a/bin/domain/imag-timetrack/src/track.rs b/bin/domain/imag-timetrack/src/track.rs index 0e709615..d8f7d7b0 100644 --- a/bin/domain/imag-timetrack/src/track.rs +++ b/bin/domain/imag-timetrack/src/track.rs @@ -81,12 +81,16 @@ pub fn track(rt: &Runtime) -> i32 { .unwrap() // enforced by clap .map(String::from) .map(TimeTrackingTag::from) - .fold(0, |acc, ttt| { - rt.store() - .create_timetracking(&start, &stop, &ttt) - .map_err_trace() - .map(|_| acc) - .unwrap_or(1) + .fold(0, |acc, ttt| match rt.store().create_timetracking(&start, &stop, &ttt) { + Err(e) => { + trace_error(&e); + 1 + }, + Ok(entry) => { + let _ = rt.report_touched(entry.get_location()) + .map_err_trace_exit_unwrap(1); + acc + } }) } diff --git a/bin/domain/imag-timetrack/src/week.rs b/bin/domain/imag-timetrack/src/week.rs index c8a74520..97797967 100644 --- a/bin/domain/imag-timetrack/src/week.rs +++ b/bin/domain/imag-timetrack/src/week.rs @@ -116,6 +116,9 @@ pub fn week(rt: &Runtime) -> i32 { let end = e.get_end_datetime()?; debug!(" -> end = {:?}", end); + let _ = rt.report_touched(e.get_location()) + .map_err_trace_exit_unwrap(1); + Ok((tag, start, end)) }) .trace_unwrap_exit(1) diff --git a/bin/domain/imag-timetrack/src/year.rs b/bin/domain/imag-timetrack/src/year.rs index 2d5c70f1..24fcfc1e 100644 --- a/bin/domain/imag-timetrack/src/year.rs +++ b/bin/domain/imag-timetrack/src/year.rs @@ -116,6 +116,9 @@ pub fn year(rt: &Runtime) -> i32 { let end = e.get_end_datetime()?; debug!(" -> end = {:?}", end); + let _ = rt.report_touched(e.get_location()) + .map_err_trace_exit_unwrap(1); + Ok((tag, start, end)) }) .trace_unwrap_exit(1) From 345970d36bdd2f43bee59d442b1d072f696ca1c0 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 7 Oct 2018 09:56:03 +0200 Subject: [PATCH 33/33] Import new dependencies Because of the changes in the "src/ui.rs" files in the binary implementations, we have new dependencies we need to import into the build-script of the "imag" command, so that it can build the commandline. Signed-off-by: Matthias Beyer --- bin/core/imag/Cargo.toml | 4 ++++ bin/core/imag/build.rs | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/bin/core/imag/Cargo.toml b/bin/core/imag/Cargo.toml index d40da6c3..ba37bdf8 100644 --- a/bin/core/imag/Cargo.toml +++ b/bin/core/imag/Cargo.toml @@ -18,8 +18,11 @@ build = "build.rs" [build-dependencies] clap = ">=2.16.1" libimagrt = { version = "0.9.0", path = "../../../lib/core/libimagrt" } +libimagerror = { version = "0.9.0", path = "../../../lib/core/libimagerror" } +libimagstore = { version = "0.9.0", path = "../../../lib/core/libimagstore" } libimagentrytag = { version = "0.9.0", path = "../../../lib/entry/libimagentrytag" } libimagutil = { version = "0.9.0", path = "../../../lib/etc/libimagutil" } +log = "0.4.0" [badges] travis-ci = { repository = "matthiasbeyer/imag" } @@ -34,6 +37,7 @@ toml = "0.4" toml-query = "0.7" libimagerror = { version = "0.9.0", path = "../../../lib/core/libimagerror" } +libimagstore = { version = "0.9.0", path = "../../../lib/core/libimagstore" } [dependencies.clap] version = "^2.29" diff --git a/bin/core/imag/build.rs b/bin/core/imag/build.rs index fe2766b1..24bf628a 100644 --- a/bin/core/imag/build.rs +++ b/bin/core/imag/build.rs @@ -19,7 +19,11 @@ extern crate clap; #[macro_use] +extern crate log; +#[macro_use] extern crate libimagrt; +extern crate libimagerror; +extern crate libimagstore; extern crate libimagentrytag; extern crate libimagutil; @@ -45,6 +49,7 @@ mod toplevelbuildscript { macro_rules! gen_mods_buildui { ($(($path:expr, $modulename:ident)$(,)*)*) => ( $( + #[allow(unused)] mod $modulename { include!($path); }