From 750f4cd31c210057f9de973359e2a4206a5ea140 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 25 Oct 2015 19:56:04 +0100 Subject: [PATCH 01/68] Start adding the BM submodule --- etc/cli.yml | 65 +++++++++++++++++++++++++++++ src/main.rs | 16 ++++++- src/module/bm/mod.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++ src/module/mod.rs | 4 ++ 4 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 src/module/bm/mod.rs diff --git a/etc/cli.yml b/etc/cli.yml index d86660ea..93ab5bf0 100644 --- a/etc/cli.yml +++ b/etc/cli.yml @@ -113,6 +113,71 @@ subcommands: help: Sets the level of debugging information required: false + subcommands: + - add: + about: Add bookmark + version: 0.1 + author: Matthias Beyer + args: + - url: + short: u + long: url + help: Add a new URL as bookmark + required: true + takes_value: true + + - tags: + short: t + long: tags + help: Add these tags to the URL + required: false + takes_value: true + + - list: + about: List bookmarks + version: 0.1 + author: Matthias Beyer + args: + - match: + short: m + long: match + help: Match for regex + required: false + takes_value: true + + - tags: + short: t + long: tags + help: Filter for these tags + required: false + takes_value: true + + - remove: + about: Remove bookmark(s) + version: 0.1 + author: Matthias Beyer + args: + - id: + long: id + help: Delete Bookmark with ID + required: false + takes_value: true + + - match: + short: m + long: match + help: Match for regex + required: false + takes_value: true + + - tags: + short: t + long: tags + help: Filter for these tags + required: false + takes_value: true + + - todo: about: Todo module version: 0.1 diff --git a/src/main.rs b/src/main.rs index f073866d..5d435b48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,14 +4,16 @@ #[macro_use] extern crate serde_json; #[macro_use] extern crate glob; #[macro_use] extern crate uuid; -#[macro_use] extern crate prettytable; +#[macro_use] extern crate regex; extern crate config; -extern crate regex; use cli::CliConfig; use configuration::Configuration; use runtime::{ImagLogger, Runtime}; use clap::App; +use module::Module; +use module::ModuleError; +use module::bm::BMModule; mod cli; mod configuration; @@ -36,5 +38,15 @@ fn main() { debug!("Runtime : {:?}", &rt); + if let Some(matches) = rt.config.cli_matches.subcommand_matches("bm") { + let module : BMModule = Module::new(&rt); + module.execute(&rt); + module.shutdown(&rt); + } else { + // Err(ModuleError::mk("No commandline call")) + info!("No commandline call...") + } + + info!("Hello, world!"); } diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs new file mode 100644 index 00000000..418b6cff --- /dev/null +++ b/src/module/bm/mod.rs @@ -0,0 +1,99 @@ +use runtime::Runtime; +use module::Module; +use module::ModuleResult; +use module::ModuleError; +use std::path::Path; +use std::result::Result; +use clap::ArgMatches; +use regex::Regex; + +pub struct BMModule { + path: Option, +} + +const CALLNAMES : &'static [&'static str] = &[ "bm", "bookmark" ]; + +impl Module for BMModule { + + fn new(rt : &Runtime) -> BMModule { + BMModule { + path: None + } + } + + fn callnames() -> &'static [&'static str] { + CALLNAMES + } + + fn name(&self) -> &'static str{ + "Bookmark" + } + + fn execute(&self, rt : &Runtime) -> ModuleResult { + let cmd = rt.config.cli_matches.subcommand_matches("bm").unwrap(); + match cmd.subcommand_name() { + Some("add") => { add(rt, cmd.subcommand_matches("add").unwrap()) } + Some("list") => { list(rt, cmd.subcommand_matches("list").unwrap()) } + Some("remove") => { list(rt, cmd.subcommand_matches("remove").unwrap()) } + _ => { + info!("Not calling any of add, list, remove"); + Ok(()) + } + } + } + + fn shutdown(&self, rt : &Runtime) -> ModuleResult { + Ok(()) + } +} + +fn add<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { + let url = sub.value_of("url").unwrap(); + let tags = get_tags(rt, sub); + + Ok(()) +} + +fn list<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { + let tags = get_tags(rt, sub); + let matcher = get_matcher(rt, sub); + + Ok(()) +} + +fn remove<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { + let tags = get_tags(rt, sub); + let matcher = get_matcher(rt, sub); + let id = get_id(rt, sub); + + Ok(()) +} + +fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option> { + sub.value_of("tags").and_then(|tags| + Some(tags.split(",") + .collect::>() + .iter() + .map(|s| s.to_string()) + .collect() + ) + ) + +} + +fn get_matcher<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option { + if let Some(s) = sub.value_of("match") { + if let Ok(r) = Regex::new(s) { + return Some(r) + } else { + error!("Regex error, continuing without regex"); + } + } + None + +} + +fn get_id<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option { + sub.value_of("id").and_then(|s| Some(String::from(s))) +} + diff --git a/src/module/mod.rs b/src/module/mod.rs index ceca732f..e846cd57 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -7,7 +7,11 @@ use std::result::Result; use storage::backend::StorageBackend; use self::command::ExecutableCommand; +use module::todo::TodoModule; + mod command; +pub mod todo; +pub mod bm; #[derive(Debug)] pub struct ModuleError { From 15a248060464af12ee064cca74bc5605d67dcf5d Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 25 Oct 2015 21:51:13 +0100 Subject: [PATCH 02/68] Add information on what gets done --- src/module/bm/mod.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 418b6cff..66bf5c9d 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -50,6 +50,7 @@ impl Module for BMModule { fn add<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { let url = sub.value_of("url").unwrap(); let tags = get_tags(rt, sub); + info!("Adding url '{}' with tags '{:?}'", url, tags.unwrap_or(vec!())); Ok(()) } @@ -58,6 +59,17 @@ fn list<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { let tags = get_tags(rt, sub); let matcher = get_matcher(rt, sub); + match matcher { + Some(reg) => { + info!("Listing urls with matcher '{}' and with tags {:?}", + reg.as_str(), + tags.unwrap_or(vec!())); + } + None => { + info!("Listing urls with tags {:?}", tags.unwrap_or(vec!())); + } + } + Ok(()) } @@ -66,6 +78,24 @@ fn remove<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { let matcher = get_matcher(rt, sub); let id = get_id(rt, sub); + match id { + Some(idstr) => { + info!("Removing urls with id '{}'", idstr); + } + None => { + match matcher { + Some(reg) => { + info!("Removing urls with matcher '{}' and with tags {:?}", + reg.as_str(), + tags.unwrap_or(vec!())); + } + None => { + info!("Listing urls with tags {:?}", tags.unwrap_or(vec!())); + } + } + } + } + Ok(()) } From de843541f1fb6ef2c97d031153fc1026fea7b7bf Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 26 Oct 2015 21:30:26 +0100 Subject: [PATCH 03/68] Add some debugging output in bm module --- src/module/bm/mod.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 66bf5c9d..88ceae8d 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -32,9 +32,18 @@ impl Module for BMModule { fn execute(&self, rt : &Runtime) -> ModuleResult { let cmd = rt.config.cli_matches.subcommand_matches("bm").unwrap(); match cmd.subcommand_name() { - Some("add") => { add(rt, cmd.subcommand_matches("add").unwrap()) } - Some("list") => { list(rt, cmd.subcommand_matches("list").unwrap()) } - Some("remove") => { list(rt, cmd.subcommand_matches("remove").unwrap()) } + Some("add") => { + debug!("Calling 'add'..."); + add(rt, cmd.subcommand_matches("add").unwrap()) + } + Some("list") => { + debug!("Calling 'list'..."); + list(rt, cmd.subcommand_matches("list").unwrap()) + } + Some("remove") => { + debug!("Calling 'remove'..."); + list(rt, cmd.subcommand_matches("remove").unwrap()) + } _ => { info!("Not calling any of add, list, remove"); Ok(()) @@ -100,6 +109,7 @@ fn remove<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { } fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option> { + debug!("Fetching tags from commandline"); sub.value_of("tags").and_then(|tags| Some(tags.split(",") .collect::>() @@ -112,6 +122,7 @@ fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option> { } fn get_matcher<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option { + debug!("Fetching matcher from commandline"); if let Some(s) = sub.value_of("match") { if let Ok(r) = Regex::new(s) { return Some(r) @@ -124,6 +135,7 @@ fn get_matcher<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option { } fn get_id<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option { + debug!("Fetching id from commandline"); sub.value_of("id").and_then(|s| Some(String::from(s))) } From 07f223bb8acddf43d9242c56c74f0d8510760a75 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 30 Oct 2015 18:26:04 +0100 Subject: [PATCH 04/68] Add header module with spec --- src/module/bm/header.rs | 18 ++++++++++++++++++ src/module/bm/mod.rs | 2 ++ 2 files changed, 20 insertions(+) create mode 100644 src/module/bm/header.rs diff --git a/src/module/bm/header.rs b/src/module/bm/header.rs new file mode 100644 index 00000000..bbd35d43 --- /dev/null +++ b/src/module/bm/header.rs @@ -0,0 +1,18 @@ +use storage::file::FileHeaderSpec as FHS; + +pub fn get_spec() -> FHS { + FHS::Array { + allowed_types: vec![FHS::Map { + keys: vec![ + FHS::Key { name: "ID", value_type: Box::new(FHS::Text) }, + FHS::Key { name: "URL", value_type: Box::new(FHS::Text) }, + FHS::Key { name: "TAGS", + value_type: Box::new(FHS::Array { + allowed_types: vec![FHS::Text] + }), + }, + ], + }], + } +} + diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 88ceae8d..38de931f 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -7,6 +7,8 @@ use std::result::Result; use clap::ArgMatches; use regex::Regex; +mod header; + pub struct BMModule { path: Option, } From b76d38f4c6cd64bb3a3d79083ee379887b5030e7 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 31 Oct 2015 12:12:40 +0100 Subject: [PATCH 05/68] Rewrite Bookmark FileHeaderSpec One file is one bookmark, so we should have the appropriate header spec for this. --- src/module/bm/header.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/module/bm/header.rs b/src/module/bm/header.rs index bbd35d43..33d4c0b6 100644 --- a/src/module/bm/header.rs +++ b/src/module/bm/header.rs @@ -1,18 +1,15 @@ use storage::file::FileHeaderSpec as FHS; pub fn get_spec() -> FHS { - FHS::Array { - allowed_types: vec![FHS::Map { - keys: vec![ - FHS::Key { name: "ID", value_type: Box::new(FHS::Text) }, - FHS::Key { name: "URL", value_type: Box::new(FHS::Text) }, - FHS::Key { name: "TAGS", - value_type: Box::new(FHS::Array { - allowed_types: vec![FHS::Text] - }), - }, - ], - }], + FHS::Map { + keys: vec![ + FHS::Key { name: "URL", value_type: Box::new(FHS::Text) }, + FHS::Key { name: "TAGS", + value_type: Box::new(FHS::Array { + allowed_types: vec![FHS::Text] + }), + }, + ], } } From 8cffdddab2506cc539b4e1496d586ac1e5b9f270 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 31 Oct 2015 12:13:21 +0100 Subject: [PATCH 06/68] Split header spec into smaller functions --- src/module/bm/header.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/module/bm/header.rs b/src/module/bm/header.rs index 33d4c0b6..273e131e 100644 --- a/src/module/bm/header.rs +++ b/src/module/bm/header.rs @@ -1,15 +1,18 @@ use storage::file::FileHeaderSpec as FHS; pub fn get_spec() -> FHS { - FHS::Map { - keys: vec![ - FHS::Key { name: "URL", value_type: Box::new(FHS::Text) }, - FHS::Key { name: "TAGS", - value_type: Box::new(FHS::Array { - allowed_types: vec![FHS::Text] - }), - }, - ], - } + FHS::Map { keys: vec![ url_key(), tags_key() ] } +} + +fn url_key() -> FHS { + FHS::Key { name: "URL", value_type: Box::new(FHS::Text) } +} + +fn tags_key() -> FHS { + FHS::Key { name: "TAGS", value_type: Box::new(text_array()) } +} + +fn text_array() -> FHS { + FHS::Array { allowed_types: vec![FHS::Text] } } From 9f29f0e1b7ed181090225bae949e035200e7d7b1 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 8 Nov 2015 00:09:07 +0100 Subject: [PATCH 07/68] Reject tasks if they contain spaces --- src/module/bm/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 38de931f..56be105f 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -116,6 +116,13 @@ fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option> { Some(tags.split(",") .collect::>() .iter() + .filter(|e| + if e.contains(" ") { + warn!("Tag contains spaces: '{}'", e); + true + } else { + false + }) .map(|s| s.to_string()) .collect() ) From cd72295c1a5e56a2f5c2b4612a5b8cb310413bcc Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 8 Nov 2015 17:11:48 +0100 Subject: [PATCH 08/68] Add function to build header content --- src/module/bm/header.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/module/bm/header.rs b/src/module/bm/header.rs index 273e131e..41864650 100644 --- a/src/module/bm/header.rs +++ b/src/module/bm/header.rs @@ -1,4 +1,5 @@ use storage::file::FileHeaderSpec as FHS; +use storage::file::FileHeaderData as FHD; pub fn get_spec() -> FHS { FHS::Map { keys: vec![ url_key(), tags_key() ] } @@ -16,3 +17,19 @@ fn text_array() -> FHS { FHS::Array { allowed_types: vec![FHS::Text] } } + +pub fn build_header(url: &String, tags: &Vec) -> FHD { + FHD::Map { + keys: vec![ + FHD::Key { + name: "URL", + value: Box::new(FHD::Text(url.clone())) + }, + FHD::Key { + name: "TAGS", + value: Box::new(FHD::Text(tags.connect(","))) + } + ] + } +} + From 51f6af6346d093ec271d69d6467a50fc939ee338 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 10 Nov 2015 16:53:30 +0100 Subject: [PATCH 09/68] We should really use String here --- src/module/bm/header.rs | 8 ++++---- src/storage/file.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/module/bm/header.rs b/src/module/bm/header.rs index 41864650..616fa6f7 100644 --- a/src/module/bm/header.rs +++ b/src/module/bm/header.rs @@ -6,11 +6,11 @@ pub fn get_spec() -> FHS { } fn url_key() -> FHS { - FHS::Key { name: "URL", value_type: Box::new(FHS::Text) } + FHS::Key { name: String::from("URL"), value_type: Box::new(FHS::Text) } } fn tags_key() -> FHS { - FHS::Key { name: "TAGS", value_type: Box::new(text_array()) } + FHS::Key { name: String::from("TAGS"), value_type: Box::new(text_array()) } } fn text_array() -> FHS { @@ -22,11 +22,11 @@ pub fn build_header(url: &String, tags: &Vec) -> FHD { FHD::Map { keys: vec![ FHD::Key { - name: "URL", + name: String::from("URL"), value: Box::new(FHD::Text(url.clone())) }, FHD::Key { - name: "TAGS", + name: String::from("TAGS"), value: Box::new(FHD::Text(tags.connect(","))) } ] diff --git a/src/storage/file.rs b/src/storage/file.rs index 75bc3b8e..aca195c4 100644 --- a/src/storage/file.rs +++ b/src/storage/file.rs @@ -16,7 +16,7 @@ pub enum FileHeaderSpec { UInteger, Float, Text, - Key { name: &'static str, value_type: Box }, + Key { name: String, value_type: Box }, Map { keys: Vec }, Array { allowed_types: Vec }, } @@ -30,7 +30,7 @@ pub enum FileHeaderData { UInteger(u64), Float(f64), Text(String), - Key { name: &'static str, value: Box }, + Key { name: String, value: Box }, Map { keys: Vec }, Array { values: Box> }, } From 006724a184d3f7bbef2ce25f33b21058ac40770b Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 10 Nov 2015 17:21:36 +0100 Subject: [PATCH 10/68] Refactor get_tags to return no Option --- src/module/bm/mod.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 56be105f..2bcafccd 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -61,7 +61,7 @@ impl Module for BMModule { fn add<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { let url = sub.value_of("url").unwrap(); let tags = get_tags(rt, sub); - info!("Adding url '{}' with tags '{:?}'", url, tags.unwrap_or(vec!())); + info!("Adding url '{}' with tags '{:?}'", url, tags); Ok(()) } @@ -74,10 +74,10 @@ fn list<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { Some(reg) => { info!("Listing urls with matcher '{}' and with tags {:?}", reg.as_str(), - tags.unwrap_or(vec!())); + tags); } None => { - info!("Listing urls with tags {:?}", tags.unwrap_or(vec!())); + info!("Listing urls with tags {:?}", tags); } } @@ -97,11 +97,10 @@ fn remove<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { match matcher { Some(reg) => { info!("Removing urls with matcher '{}' and with tags {:?}", - reg.as_str(), - tags.unwrap_or(vec!())); + reg.as_str(), tags); } None => { - info!("Listing urls with tags {:?}", tags.unwrap_or(vec!())); + info!("Listing urls with tags {:?}", tags); } } } @@ -110,23 +109,21 @@ fn remove<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { Ok(()) } -fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option> { +fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Vec { debug!("Fetching tags from commandline"); sub.value_of("tags").and_then(|tags| Some(tags.split(",") - .collect::>() - .iter() + .into_iter() + .map(|s| s.to_string()) .filter(|e| if e.contains(" ") { warn!("Tag contains spaces: '{}'", e); true } else { false - }) - .map(|s| s.to_string()) - .collect() + }).collect() ) - ) + ).or(Some(vec![])).unwrap() } From 0896f2093bc99c724a83ac31a01376dce7fdf1ee Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 10 Nov 2015 17:26:51 +0100 Subject: [PATCH 11/68] Fixed inverted logic in get_tags() --- src/module/bm/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 2bcafccd..931429df 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -118,9 +118,9 @@ fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Vec { .filter(|e| if e.contains(" ") { warn!("Tag contains spaces: '{}'", e); - true - } else { false + } else { + true }).collect() ) ).or(Some(vec![])).unwrap() From bfccbc32c5dc70b56183683d77f39b4bbed75620 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 10 Nov 2015 17:38:02 +0100 Subject: [PATCH 12/68] Add BMModule::add() implementation --- src/module/bm/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 931429df..9eedee65 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -9,6 +9,10 @@ use regex::Regex; mod header; +use self::header::build_header; +use storage::json::parser::JsonHeaderParser; +use storage::parser::FileHeaderParser; + pub struct BMModule { path: Option, } @@ -63,6 +67,10 @@ fn add<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { let tags = get_tags(rt, sub); info!("Adding url '{}' with tags '{:?}'", url, tags); + let header = build_header(&String::from(url), &tags); + let jheader = JsonHeaderParser::new(None).write(&header); + println!("JSON: {:?}", jheader); + Ok(()) } From 86286cce1b19418a94c457241fa59084102d5622 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 Nov 2015 19:47:04 +0100 Subject: [PATCH 13/68] Remove livetimes --- src/module/mod.rs | 2 -- src/storage/backend.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/module/mod.rs b/src/module/mod.rs index e846cd57..bc7e9065 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -7,10 +7,8 @@ use std::result::Result; use storage::backend::StorageBackend; use self::command::ExecutableCommand; -use module::todo::TodoModule; mod command; -pub mod todo; pub mod bm; #[derive(Debug)] diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 077cf8b4..9fe06952 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -189,7 +189,7 @@ impl StorageBackend { * TODO: Needs refactoring, as there might be an error when reading from * disk OR the id just does not exist. */ - pub fn get_file_by_id<'a, HP>(&self, m: &'a Module, id: &FileID, p: &Parser) -> Option> + pub fn get_file_by_id(&self, id: FileID, p: &Parser) -> Option where HP: FileHeaderParser { debug!("Searching for file with id '{}'", id); From cbd85b3d8e364d83da72609f092fba23db11f5e9 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 Nov 2015 19:54:37 +0100 Subject: [PATCH 14/68] Module should only provide functionality to get a list of commands it can execute These commands can then be executed. --- src/module/command.rs | 3 ++- src/module/mod.rs | 6 +----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/module/command.rs b/src/module/command.rs index e83ce232..df955bab 100644 --- a/src/module/command.rs +++ b/src/module/command.rs @@ -7,5 +7,6 @@ type CommandError = Result; type CommandResult = Result<(), Result>; pub trait ExecutableCommand { - fn exec(StorageBackend) -> CommandResult; + fn get_callname() -> &'static str; + fn exec(&self, rt: &Runtime, s: StorageBackend) -> CommandResult; } diff --git a/src/module/mod.rs b/src/module/mod.rs index bc7e9065..d8476a49 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -49,13 +49,9 @@ pub trait Module { fn new(rt : &Runtime) -> Self; fn callnames() -> &'static [&'static str]; fn name(&self) -> &'static str; - - fn execute(&self, rt : &Runtime) -> ModuleResult; fn shutdown(&self, rt : &Runtime) -> ModuleResult; - fn getCommandBuilder() -> F - where F: FnOnce(StorageBackend) -> T, - T: ExecutableCommand; + fn get_commands(&self, rt: &Runtime) -> Vec; } From 4af971a5d0a28eb1cf93718d564949bd919579c4 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 Nov 2015 20:04:24 +0100 Subject: [PATCH 15/68] Make these types public --- src/module/command.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/module/command.rs b/src/module/command.rs index df955bab..729f52a4 100644 --- a/src/module/command.rs +++ b/src/module/command.rs @@ -3,8 +3,8 @@ use std::result::Result; use super::ModuleError; use storage::backend::{StorageBackend, StorageBackendError}; -type CommandError = Result; -type CommandResult = Result<(), Result>; +pub type CommandError = Result; +pub type CommandResult = Result<(), Result>; pub trait ExecutableCommand { fn get_callname() -> &'static str; From f94f8870e9d48234dcc09fc4d28f0f8a81f52ee5 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 Nov 2015 20:04:43 +0100 Subject: [PATCH 16/68] The exec() function of an ExecutableCommand should get the CLI matches as well --- src/module/command.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/module/command.rs b/src/module/command.rs index 729f52a4..09d2792d 100644 --- a/src/module/command.rs +++ b/src/module/command.rs @@ -1,5 +1,8 @@ use std::result::Result; +use clap::ArgMatches; + +use runtime::Runtime; use super::ModuleError; use storage::backend::{StorageBackend, StorageBackendError}; @@ -8,5 +11,8 @@ pub type CommandResult = Result<(), Result>; pub trait ExecutableCommand { fn get_callname() -> &'static str; - fn exec(&self, rt: &Runtime, s: StorageBackend) -> CommandResult; + fn exec(&self, + rt: &Runtime, + matches: &ArgMatches<'a, 'a>, + s: StorageBackend) -> CommandResult; } From a9a33321f7535347191a71684fbade04ab2319ff Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 Nov 2015 20:05:01 +0100 Subject: [PATCH 17/68] Make command submodule public --- src/module/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/mod.rs b/src/module/mod.rs index d8476a49..2c3d96d1 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -8,7 +8,7 @@ use std::result::Result; use storage::backend::StorageBackend; use self::command::ExecutableCommand; -mod command; +pub mod command; pub mod bm; #[derive(Debug)] From 55361f71fe701c19057b816f89143377cfeca1f1 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 Nov 2015 20:07:47 +0100 Subject: [PATCH 18/68] Add struct for passing environment of command to command execute function --- src/module/command.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/module/command.rs b/src/module/command.rs index 09d2792d..9581cc85 100644 --- a/src/module/command.rs +++ b/src/module/command.rs @@ -9,10 +9,13 @@ use storage::backend::{StorageBackend, StorageBackendError}; pub type CommandError = Result; pub type CommandResult = Result<(), Result>; +pub struct CommandEnv<'a> { + pub rt: &'a Runtime<'a>, + pub matches: &'a ArgMatches<'a, 'a>, + pub backend: StorageBackend +} + pub trait ExecutableCommand { fn get_callname() -> &'static str; - fn exec(&self, - rt: &Runtime, - matches: &ArgMatches<'a, 'a>, - s: StorageBackend) -> CommandResult; + fn exec(&self, env: CommandEnv) -> CommandResult; } From 168852714a05795c099513cecec37393bea0548b Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 Nov 2015 20:15:41 +0100 Subject: [PATCH 19/68] Add modules for commands of BM module --- src/module/bm/commands/mod.rs | 92 +++++++++++++++++++++++++++++++++++ src/module/bm/mod.rs | 14 ++++++ 2 files changed, 106 insertions(+) create mode 100644 src/module/bm/commands/mod.rs diff --git a/src/module/bm/commands/mod.rs b/src/module/bm/commands/mod.rs new file mode 100644 index 00000000..9016b847 --- /dev/null +++ b/src/module/bm/commands/mod.rs @@ -0,0 +1,92 @@ +mod add { + use clap::ArgMatches; + + use module::command::{CommandError, CommandResult, CommandEnv, ExecutableCommand}; + use runtime::Runtime; + use storage::backend::{StorageBackend, StorageBackendError}; + + pub struct AddCommand; + + pub impl AddCommand { + + fn new() -> AddCommand { + AddCommand + } + + } + + pub impl ExecutableCommand for AddCommand { + + fn get_callname() -> &'static str { + "add" + } + + fn exec<'a>(&self, env: CommandEnv<'a>) -> CommandResult + { + } + + } + +} + +mod list { + use clap::ArgMatches; + + use module::command::{CommandError, CommandResult, CommandEnv, ExecutableCommand}; + use runtime::Runtime; + use storage::backend::{StorageBackend, StorageBackendError}; + + pub struct ListCommand; + + pub impl ListCommand { + + fn new() -> ListCommand { + ListCommand + } + + } + + pub impl ExecutableCommand for ListCommand { + + fn get_callname() -> &'static str { + "list" + } + + fn exec<'a>(&self, env: CommandEnv<'a>) -> CommandResult + { + } + + } + +} + +mod remove { + use clap::ArgMatches; + + use module::command::{CommandError, CommandResult, CommandEnv, ExecutableCommand}; + use runtime::Runtime; + use storage::backend::{StorageBackend, StorageBackendError}; + + pub struct RemoveCommand; + + pub impl RemoveCommand { + + fn new() -> RemoveCommand { + RemoveCommand + } + + } + + pub impl ExecutableCommand for RemoveCommand { + + fn get_callname() -> &'static str { + "remove" + } + + fn exec<'a>(&self, env: CommandEnv<'a>) -> CommandResult + { + } + + } + +} diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 9eedee65..4c74cc81 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -8,10 +8,16 @@ use clap::ArgMatches; use regex::Regex; mod header; +mod commands; use self::header::build_header; use storage::json::parser::JsonHeaderParser; use storage::parser::FileHeaderParser; +use module::command::ExecutableCommand; + +use self::commands::add::*; +use self::commands::list::*; +use self::commands::remove::*; pub struct BMModule { path: Option, @@ -60,6 +66,14 @@ impl Module for BMModule { fn shutdown(&self, rt : &Runtime) -> ModuleResult { Ok(()) } + + fn get_commands(&self, rt: &Runtime) -> Vec { + vec![ + AddCommand::new(), + ListCommand::new(), + RemoveCommand::new(), + ] + } } fn add<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { From 8404303dbd30924eca3f96232fc7308d2df17dfe Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 24 Nov 2015 20:19:01 +0100 Subject: [PATCH 20/68] Remove BMModule::execute() which is not required by the trait anymore --- src/module/bm/mod.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 4c74cc81..86273652 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -41,28 +41,6 @@ impl Module for BMModule { "Bookmark" } - fn execute(&self, rt : &Runtime) -> ModuleResult { - let cmd = rt.config.cli_matches.subcommand_matches("bm").unwrap(); - match cmd.subcommand_name() { - Some("add") => { - debug!("Calling 'add'..."); - add(rt, cmd.subcommand_matches("add").unwrap()) - } - Some("list") => { - debug!("Calling 'list'..."); - list(rt, cmd.subcommand_matches("list").unwrap()) - } - Some("remove") => { - debug!("Calling 'remove'..."); - list(rt, cmd.subcommand_matches("remove").unwrap()) - } - _ => { - info!("Not calling any of add, list, remove"); - Ok(()) - } - } - } - fn shutdown(&self, rt : &Runtime) -> ModuleResult { Ok(()) } From a24d3175dd2a686c9c1d618f77dc06747c504d9e Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Fri, 27 Nov 2015 18:27:19 +0100 Subject: [PATCH 21/68] We do not have Module::execute() anymore --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 5d435b48..a03cd737 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,7 @@ fn main() { if let Some(matches) = rt.config.cli_matches.subcommand_matches("bm") { let module : BMModule = Module::new(&rt); - module.execute(&rt); + //module.execute(&rt); module.shutdown(&rt); } else { // Err(ModuleError::mk("No commandline call")) From 84571bef0a7367b55c2cc369ad40afadc9857809 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 11:09:10 +0100 Subject: [PATCH 22/68] get_commands() can return a HashMap, which is command name -> command function --- src/module/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/module/mod.rs b/src/module/mod.rs index 2c3d96d1..d45d494b 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -4,6 +4,7 @@ use std::fmt::Formatter; use std::fmt::Result as FMTResult; use std::fmt::Display; use std::result::Result; +use std::collections::HashMap; use storage::backend::StorageBackend; use self::command::ExecutableCommand; @@ -43,6 +44,7 @@ impl Display for ModuleError { } pub type ModuleResult = Result<(), ModuleError>; +pub type CommandMap<'a> = HashMap<&'a str, fn(&Runtime)>; pub trait Module { @@ -51,7 +53,7 @@ pub trait Module { fn name(&self) -> &'static str; fn shutdown(&self, rt : &Runtime) -> ModuleResult; - fn get_commands(&self, rt: &Runtime) -> Vec; + fn get_commands(&self, rt: &Runtime) -> CommandMap; } From 8af9ba48c04cd5ebfe79a02d62a5fda70c6e166b Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 11:23:27 +0100 Subject: [PATCH 23/68] We dont need the command traits anymore --- src/module/bm/mod.rs | 1 - src/module/command.rs | 21 --------------------- src/module/mod.rs | 4 +--- 3 files changed, 1 insertion(+), 25 deletions(-) delete mode 100644 src/module/command.rs diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 86273652..941a603a 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -13,7 +13,6 @@ mod commands; use self::header::build_header; use storage::json::parser::JsonHeaderParser; use storage::parser::FileHeaderParser; -use module::command::ExecutableCommand; use self::commands::add::*; use self::commands::list::*; diff --git a/src/module/command.rs b/src/module/command.rs deleted file mode 100644 index 9581cc85..00000000 --- a/src/module/command.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::result::Result; - -use clap::ArgMatches; - -use runtime::Runtime; -use super::ModuleError; -use storage::backend::{StorageBackend, StorageBackendError}; - -pub type CommandError = Result; -pub type CommandResult = Result<(), Result>; - -pub struct CommandEnv<'a> { - pub rt: &'a Runtime<'a>, - pub matches: &'a ArgMatches<'a, 'a>, - pub backend: StorageBackend -} - -pub trait ExecutableCommand { - fn get_callname() -> &'static str; - fn exec(&self, env: CommandEnv) -> CommandResult; -} diff --git a/src/module/mod.rs b/src/module/mod.rs index d45d494b..a027321a 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -6,10 +6,8 @@ use std::fmt::Display; use std::result::Result; use std::collections::HashMap; -use storage::backend::StorageBackend; -use self::command::ExecutableCommand; +use storage::backend::{StorageBackend, StorageBackendError}; -pub mod command; pub mod bm; #[derive(Debug)] From 24a6e961afd65b0d09b15b378e2997adde1edece Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 11:09:39 +0100 Subject: [PATCH 24/68] Change get_commands() for latest trait change --- src/module/bm/mod.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 941a603a..8661cc90 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -1,5 +1,6 @@ use runtime::Runtime; use module::Module; +use module::CommandMap; use module::ModuleResult; use module::ModuleError; use std::path::Path; @@ -14,9 +15,7 @@ use self::header::build_header; use storage::json::parser::JsonHeaderParser; use storage::parser::FileHeaderParser; -use self::commands::add::*; -use self::commands::list::*; -use self::commands::remove::*; +use self::commands::*; pub struct BMModule { path: Option, @@ -44,12 +43,12 @@ impl Module for BMModule { Ok(()) } - fn get_commands(&self, rt: &Runtime) -> Vec { - vec![ - AddCommand::new(), - ListCommand::new(), - RemoveCommand::new(), - ] + fn get_commands(&self, rt: &Runtime) -> CommandMap { + let mut hm = CommandMap::new(); + hm.insert("add", add_command); + hm.insert("list", list_command); + hm.insert("remove", remove_command); + hm } } From e10d1bcb659f43afa07766c1127abbf318a1a5ed Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 11:09:50 +0100 Subject: [PATCH 25/68] Reimplement commands for bm --- src/module/bm/commands/mod.rs | 94 +++-------------------------------- 1 file changed, 8 insertions(+), 86 deletions(-) diff --git a/src/module/bm/commands/mod.rs b/src/module/bm/commands/mod.rs index 9016b847..d3ea5469 100644 --- a/src/module/bm/commands/mod.rs +++ b/src/module/bm/commands/mod.rs @@ -1,92 +1,14 @@ -mod add { - use clap::ArgMatches; - - use module::command::{CommandError, CommandResult, CommandEnv, ExecutableCommand}; - use runtime::Runtime; - use storage::backend::{StorageBackend, StorageBackendError}; - - pub struct AddCommand; - - pub impl AddCommand { - - fn new() -> AddCommand { - AddCommand - } - - } - - pub impl ExecutableCommand for AddCommand { - - fn get_callname() -> &'static str { - "add" - } - - fn exec<'a>(&self, env: CommandEnv<'a>) -> CommandResult - { - } - - } +use runtime::Runtime; +pub fn add_command(rt: &Runtime) { + unimplemented!() } -mod list { - use clap::ArgMatches; - - use module::command::{CommandError, CommandResult, CommandEnv, ExecutableCommand}; - use runtime::Runtime; - use storage::backend::{StorageBackend, StorageBackendError}; - - pub struct ListCommand; - - pub impl ListCommand { - - fn new() -> ListCommand { - ListCommand - } - - } - - pub impl ExecutableCommand for ListCommand { - - fn get_callname() -> &'static str { - "list" - } - - fn exec<'a>(&self, env: CommandEnv<'a>) -> CommandResult - { - } - - } - +pub fn list_command(rt: &Runtime) { + unimplemented!() } -mod remove { - use clap::ArgMatches; - - use module::command::{CommandError, CommandResult, CommandEnv, ExecutableCommand}; - use runtime::Runtime; - use storage::backend::{StorageBackend, StorageBackendError}; - - pub struct RemoveCommand; - - pub impl RemoveCommand { - - fn new() -> RemoveCommand { - RemoveCommand - } - - } - - pub impl ExecutableCommand for RemoveCommand { - - fn get_callname() -> &'static str { - "remove" - } - - fn exec<'a>(&self, env: CommandEnv<'a>) -> CommandResult - { - } - - } - +pub fn remove_command(rt: &Runtime) { + unimplemented!() } + From 4a73a317d446905e1143bdb0c18ca167103ef26e Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 11:25:16 +0100 Subject: [PATCH 26/68] Move submodule commands/mod.rs to commands.rs --- src/module/bm/{commands/mod.rs => commands.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/module/bm/{commands/mod.rs => commands.rs} (100%) diff --git a/src/module/bm/commands/mod.rs b/src/module/bm/commands.rs similarity index 100% rename from src/module/bm/commands/mod.rs rename to src/module/bm/commands.rs From 3f19aba7b28bc6eb493133d41c9e4e89a5c6d701 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 11:36:06 +0100 Subject: [PATCH 27/68] Add subcommand calling code in main() --- src/main.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index a03cd737..3ce6ea03 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,17 @@ fn main() { if let Some(matches) = rt.config.cli_matches.subcommand_matches("bm") { let module : BMModule = Module::new(&rt); - //module.execute(&rt); + let commands = module.get_commands(&rt); + if let Some(command) = matches.subcommand_name() { + debug!("Subcommand: {}", command); + match commands.get(command) { + Some(f) => f(&rt), + None => debug!("No command '{}' found", command), + } + } else { + debug!("No subcommand"); + } + module.shutdown(&rt); } else { // Err(ModuleError::mk("No commandline call")) From 18ea01b854ab068baf92bb0388545ecc8e5c6e03 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 11:43:30 +0100 Subject: [PATCH 28/68] Pass StorageBackend to subcommand function --- src/main.rs | 6 +++++- src/module/bm/commands.rs | 7 ++++--- src/module/mod.rs | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3ce6ea03..781c89dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ use clap::App; use module::Module; use module::ModuleError; use module::bm::BMModule; +use storage::backend::StorageBackend; mod cli; mod configuration; @@ -43,8 +44,11 @@ fn main() { let commands = module.get_commands(&rt); if let Some(command) = matches.subcommand_name() { debug!("Subcommand: {}", command); + + let backend = StorageBackend::new(rt.get_rtp()); + match commands.get(command) { - Some(f) => f(&rt), + Some(f) => f(&rt, &backend), None => debug!("No command '{}' found", command), } } else { diff --git a/src/module/bm/commands.rs b/src/module/bm/commands.rs index d3ea5469..60318061 100644 --- a/src/module/bm/commands.rs +++ b/src/module/bm/commands.rs @@ -1,14 +1,15 @@ use runtime::Runtime; +use storage::backend::StorageBackend; -pub fn add_command(rt: &Runtime) { +pub fn add_command(rt: &Runtime, backend: &StorageBackend) { unimplemented!() } -pub fn list_command(rt: &Runtime) { +pub fn list_command(rt: &Runtime, backend: &StorageBackend) { unimplemented!() } -pub fn remove_command(rt: &Runtime) { +pub fn remove_command(rt: &Runtime, backend: &StorageBackend) { unimplemented!() } diff --git a/src/module/mod.rs b/src/module/mod.rs index a027321a..610421aa 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -42,7 +42,7 @@ impl Display for ModuleError { } pub type ModuleResult = Result<(), ModuleError>; -pub type CommandMap<'a> = HashMap<&'a str, fn(&Runtime)>; +pub type CommandMap<'a> = HashMap<&'a str, fn(&Runtime, &StorageBackend)>; pub trait Module { From 9bf9f96ab12ca3fcfb00aa67ee34057102550578 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 11:54:04 +0100 Subject: [PATCH 29/68] Fix: ModuleError::mk() -> pub ModuleError::new() --- src/module/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/mod.rs b/src/module/mod.rs index 610421aa..33b1f8d0 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -16,7 +16,7 @@ pub struct ModuleError { } impl ModuleError { - fn mk(desc: &'static str) -> ModuleError { + pub fn new(desc: &'static str) -> ModuleError { ModuleError { desc: desc.to_owned().to_string(), } From 0a026002b0da6c14f016cad102ce85114fb1ce1f Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 11:54:27 +0100 Subject: [PATCH 30/68] Pass CommandEnv struct to command exec function So we can add parameters rather easily. Also define CommandResult as result type. --- src/module/bm/commands.rs | 9 ++++++--- src/module/mod.rs | 11 ++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/module/bm/commands.rs b/src/module/bm/commands.rs index 60318061..af922fbe 100644 --- a/src/module/bm/commands.rs +++ b/src/module/bm/commands.rs @@ -1,15 +1,18 @@ use runtime::Runtime; use storage::backend::StorageBackend; -pub fn add_command(rt: &Runtime, backend: &StorageBackend) { +use module::CommandResult; +use module::CommandEnv; + +pub fn add_command(env: CommandEnv) -> CommandResult { unimplemented!() } -pub fn list_command(rt: &Runtime, backend: &StorageBackend) { +pub fn list_command(env: CommandEnv) -> CommandResult { unimplemented!() } -pub fn remove_command(rt: &Runtime, backend: &StorageBackend) { +pub fn remove_command(env: CommandEnv) -> CommandResult { unimplemented!() } diff --git a/src/module/mod.rs b/src/module/mod.rs index 33b1f8d0..7ad0ea48 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -6,6 +6,8 @@ use std::fmt::Display; use std::result::Result; use std::collections::HashMap; +use clap::{App, ArgMatches}; + use storage::backend::{StorageBackend, StorageBackendError}; pub mod bm; @@ -41,8 +43,15 @@ impl Display for ModuleError { } } +pub struct CommandEnv<'a> { + pub rt: &'a Runtime<'a>, + pub bk: &'a StorageBackend, + pub matches: &'a ArgMatches<'a, 'a>, +} + pub type ModuleResult = Result<(), ModuleError>; -pub type CommandMap<'a> = HashMap<&'a str, fn(&Runtime, &StorageBackend)>; +pub type CommandResult = ModuleResult; +pub type CommandMap<'a> = HashMap<&'a str, fn(CommandEnv) -> CommandResult>; pub trait Module { From fda2c4feea006d6fc46440549f3868f8f33607cb Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 11:55:40 +0100 Subject: [PATCH 31/68] Add CommandEnv building in command calling code in main() --- src/main.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 781c89dc..c69f1bbc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ use runtime::{ImagLogger, Runtime}; use clap::App; use module::Module; use module::ModuleError; +use module::CommandEnv; use module::bm::BMModule; use storage::backend::StorageBackend; @@ -47,10 +48,18 @@ fn main() { let backend = StorageBackend::new(rt.get_rtp()); - match commands.get(command) { - Some(f) => f(&rt, &backend), - None => debug!("No command '{}' found", command), - } + let cmdenv = CommandEnv { + rt: &rt, + bk: &backend, + matches: matches, + }; + + let result = match commands.get(command) { + Some(f) => f(cmdenv), + None => Err(ModuleError::new("No subcommand found")), + }; + + debug!("Result of command: {:?}", result); } else { debug!("No subcommand"); } From 08d6e8da13f1ecb3e0fc987b8fd0c429b83bee24 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 12:08:20 +0100 Subject: [PATCH 32/68] We need to unwrap here (and it is save) --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index c69f1bbc..8c764e59 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,7 +51,7 @@ fn main() { let cmdenv = CommandEnv { rt: &rt, bk: &backend, - matches: matches, + matches: matches.subcommand_matches(command).unwrap(), }; let result = match commands.get(command) { From ff873c8fe35d6fbee8073f8279d10e3912175c59 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 12:09:00 +0100 Subject: [PATCH 33/68] Transfer old code to new structure --- src/module/bm/commands.rs | 98 +++++++++++++++++++++++++++++++++++++-- src/module/bm/mod.rs | 91 ------------------------------------ 2 files changed, 95 insertions(+), 94 deletions(-) diff --git a/src/module/bm/commands.rs b/src/module/bm/commands.rs index af922fbe..582fb543 100644 --- a/src/module/bm/commands.rs +++ b/src/module/bm/commands.rs @@ -4,15 +4,107 @@ use storage::backend::StorageBackend; use module::CommandResult; use module::CommandEnv; +use module::bm::header::build_header; +use storage::json::parser::JsonHeaderParser; +use storage::parser::FileHeaderParser; + +use clap::ArgMatches; +use regex::Regex; + pub fn add_command(env: CommandEnv) -> CommandResult { - unimplemented!() + let url = env.matches.value_of("url").unwrap(); + let tags = get_tags(env.rt, env.matches); + info!("Adding url '{}' with tags '{:?}'", url, tags); + + let header = build_header(&String::from(url), &tags); + let jheader = JsonHeaderParser::new(None).write(&header); + println!("JSON: {:?}", jheader); + + Ok(()) } pub fn list_command(env: CommandEnv) -> CommandResult { - unimplemented!() + let tags = get_tags(env.rt, env.matches); + let matcher = get_matcher(env.rt, env.matches); + + match matcher { + Some(reg) => { + info!("Listing urls with matcher '{}' and with tags {:?}", + reg.as_str(), + tags); + } + None => { + info!("Listing urls with tags {:?}", tags); + } + } + + Ok(()) } pub fn remove_command(env: CommandEnv) -> CommandResult { - unimplemented!() + let tags = get_tags(env.rt, env.matches); + let matcher = get_matcher(env.rt, env.matches); + let id = get_id(env.rt, env.matches); + + match id { + Some(idstr) => { + info!("Removing urls with id '{}'", idstr); + } + None => { + match matcher { + Some(reg) => { + info!("Removing urls with matcher '{}' and with tags {:?}", + reg.as_str(), tags); + } + None => { + info!("Listing urls with tags {:?}", tags); + } + } + } + } + + Ok(()) +} + +/* + * + * Private helpers + * + */ + +fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Vec { + debug!("Fetching tags from commandline"); + sub.value_of("tags").and_then(|tags| + Some(tags.split(",") + .into_iter() + .map(|s| s.to_string()) + .filter(|e| + if e.contains(" ") { + warn!("Tag contains spaces: '{}'", e); + false + } else { + true + }).collect() + ) + ).or(Some(vec![])).unwrap() + +} + +fn get_matcher<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option { + debug!("Fetching matcher from commandline"); + if let Some(s) = sub.value_of("match") { + if let Ok(r) = Regex::new(s) { + return Some(r) + } else { + error!("Regex error, continuing without regex"); + } + } + None + +} + +fn get_id<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option { + debug!("Fetching id from commandline"); + sub.value_of("id").and_then(|s| Some(String::from(s))) } diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 8661cc90..7054f2a5 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -52,94 +52,3 @@ impl Module for BMModule { } } -fn add<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { - let url = sub.value_of("url").unwrap(); - let tags = get_tags(rt, sub); - info!("Adding url '{}' with tags '{:?}'", url, tags); - - let header = build_header(&String::from(url), &tags); - let jheader = JsonHeaderParser::new(None).write(&header); - println!("JSON: {:?}", jheader); - - Ok(()) -} - -fn list<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { - let tags = get_tags(rt, sub); - let matcher = get_matcher(rt, sub); - - match matcher { - Some(reg) => { - info!("Listing urls with matcher '{}' and with tags {:?}", - reg.as_str(), - tags); - } - None => { - info!("Listing urls with tags {:?}", tags); - } - } - - Ok(()) -} - -fn remove<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> ModuleResult { - let tags = get_tags(rt, sub); - let matcher = get_matcher(rt, sub); - let id = get_id(rt, sub); - - match id { - Some(idstr) => { - info!("Removing urls with id '{}'", idstr); - } - None => { - match matcher { - Some(reg) => { - info!("Removing urls with matcher '{}' and with tags {:?}", - reg.as_str(), tags); - } - None => { - info!("Listing urls with tags {:?}", tags); - } - } - } - } - - Ok(()) -} - -fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Vec { - debug!("Fetching tags from commandline"); - sub.value_of("tags").and_then(|tags| - Some(tags.split(",") - .into_iter() - .map(|s| s.to_string()) - .filter(|e| - if e.contains(" ") { - warn!("Tag contains spaces: '{}'", e); - false - } else { - true - }).collect() - ) - ).or(Some(vec![])).unwrap() - -} - -fn get_matcher<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option { - debug!("Fetching matcher from commandline"); - if let Some(s) = sub.value_of("match") { - if let Ok(r) = Regex::new(s) { - return Some(r) - } else { - error!("Regex error, continuing without regex"); - } - } - None - -} - -fn get_id<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option { - debug!("Fetching id from commandline"); - sub.value_of("id").and_then(|s| Some(String::from(s))) -} - From 7531b5a6d7c5255f8848b6e2600854c88587776e Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 12:35:49 +0100 Subject: [PATCH 34/68] Pass module to subcommand. We need the module in the subcommand for building file paths and so on. To be able to pass it, we must remove the ::new() function from the trait, so we can make the parameter a trait object. This is no object, as the module gets build non-generically from the main(), so everything is fine with this. --- src/main.rs | 4 ++-- src/module/bm/commands.rs | 7 ++++--- src/module/bm/mod.rs | 10 +++++++--- src/module/mod.rs | 5 ++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8c764e59..05e9a879 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,7 @@ fn main() { debug!("Runtime : {:?}", &rt); if let Some(matches) = rt.config.cli_matches.subcommand_matches("bm") { - let module : BMModule = Module::new(&rt); + let module = BMModule::new(&rt); let commands = module.get_commands(&rt); if let Some(command) = matches.subcommand_name() { debug!("Subcommand: {}", command); @@ -55,7 +55,7 @@ fn main() { }; let result = match commands.get(command) { - Some(f) => f(cmdenv), + Some(f) => f(&module, cmdenv), None => Err(ModuleError::new("No subcommand found")), }; diff --git a/src/module/bm/commands.rs b/src/module/bm/commands.rs index 582fb543..31b654a0 100644 --- a/src/module/bm/commands.rs +++ b/src/module/bm/commands.rs @@ -1,6 +1,7 @@ use runtime::Runtime; use storage::backend::StorageBackend; +use module::Module; use module::CommandResult; use module::CommandEnv; @@ -11,7 +12,7 @@ use storage::parser::FileHeaderParser; use clap::ArgMatches; use regex::Regex; -pub fn add_command(env: CommandEnv) -> CommandResult { +pub fn add_command(module: &Module, env: CommandEnv) -> CommandResult { let url = env.matches.value_of("url").unwrap(); let tags = get_tags(env.rt, env.matches); info!("Adding url '{}' with tags '{:?}'", url, tags); @@ -23,7 +24,7 @@ pub fn add_command(env: CommandEnv) -> CommandResult { Ok(()) } -pub fn list_command(env: CommandEnv) -> CommandResult { +pub fn list_command(module: &Module, env: CommandEnv) -> CommandResult { let tags = get_tags(env.rt, env.matches); let matcher = get_matcher(env.rt, env.matches); @@ -41,7 +42,7 @@ pub fn list_command(env: CommandEnv) -> CommandResult { Ok(()) } -pub fn remove_command(env: CommandEnv) -> CommandResult { +pub fn remove_command(module: &Module, env: CommandEnv) -> CommandResult { let tags = get_tags(env.rt, env.matches); let matcher = get_matcher(env.rt, env.matches); let id = get_id(env.rt, env.matches); diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 7054f2a5..861c6271 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -23,15 +23,19 @@ pub struct BMModule { const CALLNAMES : &'static [&'static str] = &[ "bm", "bookmark" ]; -impl Module for BMModule { +impl BMModule { - fn new(rt : &Runtime) -> BMModule { + pub fn new(rt : &Runtime) -> BMModule { BMModule { path: None } } - fn callnames() -> &'static [&'static str] { +} + +impl Module for BMModule { + + fn callnames(&self) -> &'static [&'static str] { CALLNAMES } diff --git a/src/module/mod.rs b/src/module/mod.rs index 7ad0ea48..5b7cc133 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -51,12 +51,11 @@ pub struct CommandEnv<'a> { pub type ModuleResult = Result<(), ModuleError>; pub type CommandResult = ModuleResult; -pub type CommandMap<'a> = HashMap<&'a str, fn(CommandEnv) -> CommandResult>; +pub type CommandMap<'a> = HashMap<&'a str, fn(&Module, CommandEnv) -> CommandResult>; pub trait Module { - fn new(rt : &Runtime) -> Self; - fn callnames() -> &'static [&'static str]; + fn callnames(&self) -> &'static [&'static str]; fn name(&self) -> &'static str; fn shutdown(&self, rt : &Runtime) -> ModuleResult; From 0d751f9ffdac6578395ae4a73786f27b4846689b Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 12:37:27 +0100 Subject: [PATCH 35/68] Add some debug output in StorageBackend::build_filepath_with_id() --- src/storage/backend.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 9fe06952..f9529aef 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -238,8 +238,11 @@ impl StorageBackend { self.prefix_of_files_for_module(owner) + "-" + &id[..] + ".imag" } - fn prefix_of_files_for_module(&self, m: &Module) -> String { - self.storepath.clone() + m.name() + fn build_filepath_with_id(&self, id: FileID) -> String { + debug!("Building filepath with id"); + debug!(" basepath: '{}'", self.basepath); + debug!(" id : '{}'", id); + self.basepath.clone() + &id[..] } } From 593e98ac5d992c406ca3aa13424b1b3fe2e30392 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 12:44:03 +0100 Subject: [PATCH 36/68] A File is bound to a Module A File object must be bound to a Module, as one Module owns the File. This way we can use the Module internally to build the file path later. --- src/storage/backend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index f9529aef..ccc194a7 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -189,7 +189,7 @@ impl StorageBackend { * TODO: Needs refactoring, as there might be an error when reading from * disk OR the id just does not exist. */ - pub fn get_file_by_id(&self, id: FileID, p: &Parser) -> Option + pub fn get_file_by_id<'a, HP>(&self, m: &'a Module, id: FileID, p: &Parser) -> Option> where HP: FileHeaderParser { debug!("Searching for file with id '{}'", id); From 98ec735ea3f412327e517d66549235e2b434852e Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 12:47:30 +0100 Subject: [PATCH 37/68] Add File::owner() - a getter for the owner of a file --- src/storage/file.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/storage/file.rs b/src/storage/file.rs index aca195c4..10a4e218 100644 --- a/src/storage/file.rs +++ b/src/storage/file.rs @@ -285,10 +285,6 @@ impl<'a> File<'a> { self.owning_module } - pub fn matches_with(&self, r: &Regex) -> bool { - r.is_match(&self.data[..]) || self.header.matches_with(r) - } - fn get_new_file_id() -> FileID { use uuid::Uuid; Uuid::new_v4().to_hyphenated_string() From c9ebe3b7a168b2646c20f826d33b37af02922325 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 12:47:58 +0100 Subject: [PATCH 38/68] Pass owner to file path builder helper function --- src/storage/backend.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index ccc194a7..078c623c 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -233,16 +233,8 @@ impl StorageBackend { fn build_filepath_with_id(&self, owner: &Module, id: FileID) -> String { debug!("Building filepath with id"); debug!(" basepath: '{}'", self.basepath); - debug!(" storepath: '{}'", self.storepath); debug!(" id : '{}'", id); - self.prefix_of_files_for_module(owner) + "-" + &id[..] + ".imag" - } - - fn build_filepath_with_id(&self, id: FileID) -> String { - debug!("Building filepath with id"); - debug!(" basepath: '{}'", self.basepath); - debug!(" id : '{}'", id); - self.basepath.clone() + &id[..] + self.basepath.clone() + owner.name() + "-" + &id[..] + ".imag" } } From e78bde72c18d5ebb72d257d7316dd5248ac1d946 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 12:48:50 +0100 Subject: [PATCH 39/68] Implement add_command() with backend --- src/module/bm/commands.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/module/bm/commands.rs b/src/module/bm/commands.rs index 31b654a0..18f71fcb 100644 --- a/src/module/bm/commands.rs +++ b/src/module/bm/commands.rs @@ -7,7 +7,8 @@ use module::CommandEnv; use module::bm::header::build_header; use storage::json::parser::JsonHeaderParser; -use storage::parser::FileHeaderParser; +use storage::parser::{Parser, FileHeaderParser}; +use storage::file::File; use clap::ArgMatches; use regex::Regex; @@ -17,9 +18,10 @@ pub fn add_command(module: &Module, env: CommandEnv) -> CommandResult { let tags = get_tags(env.rt, env.matches); info!("Adding url '{}' with tags '{:?}'", url, tags); - let header = build_header(&String::from(url), &tags); - let jheader = JsonHeaderParser::new(None).write(&header); - println!("JSON: {:?}", jheader); + let header = build_header(&String::from(url), &tags); + let file = File::new_with_header(module, header); + let parser = Parser::new(JsonHeaderParser::new(None)); + let putres = env.bk.put_file(file, &parser); Ok(()) } From 8a2c41ea222e2dc491b0d3d15a339cf387455b5f Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 13:00:28 +0100 Subject: [PATCH 40/68] Fix: Build StorageBackend with runtime --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 05e9a879..ace2b973 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,7 +46,7 @@ fn main() { if let Some(command) = matches.subcommand_name() { debug!("Subcommand: {}", command); - let backend = StorageBackend::new(rt.get_rtp()); + let backend = StorageBackend::new(&rt); let cmdenv = CommandEnv { rt: &rt, From 1038880de9e3266dc2f54f7c7b21939c83e0073c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 13:03:54 +0100 Subject: [PATCH 41/68] Save storepath in extra variable --- src/storage/backend.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 078c623c..5ed062bc 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -233,8 +233,9 @@ impl StorageBackend { fn build_filepath_with_id(&self, owner: &Module, id: FileID) -> String { debug!("Building filepath with id"); debug!(" basepath: '{}'", self.basepath); + debug!(" storepath: '{}'", self.storepath); debug!(" id : '{}'", id); - self.basepath.clone() + owner.name() + "-" + &id[..] + ".imag" + self.storepath.clone() + owner.name() + "-" + &id[..] + ".imag" } } From cf1687e8ba621774ce3e5400df85765c3993df70 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 13:07:30 +0100 Subject: [PATCH 42/68] Convention: module names are lowercase --- src/module/bm/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 861c6271..2b8a712b 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -40,7 +40,7 @@ impl Module for BMModule { } fn name(&self) -> &'static str{ - "Bookmark" + "bookmark" } fn shutdown(&self, rt : &Runtime) -> ModuleResult { From 455d6e88ed49c62e100b0153474a18b39fa47b48 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 13:26:29 +0100 Subject: [PATCH 43/68] Use real array instead of text array to save tags --- src/module/bm/header.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/module/bm/header.rs b/src/module/bm/header.rs index 616fa6f7..62c61a25 100644 --- a/src/module/bm/header.rs +++ b/src/module/bm/header.rs @@ -27,9 +27,14 @@ pub fn build_header(url: &String, tags: &Vec) -> FHD { }, FHD::Key { name: String::from("TAGS"), - value: Box::new(FHD::Text(tags.connect(","))) + value: Box::new(build_tag_array(tags)) } ] } } +fn build_tag_array(tags: &Vec) -> FHD { + let texttags = tags.into_iter().map(|t| FHD::Text(t.clone())).collect(); + FHD::Array { values: Box::new(texttags) } +} + From 21d889e1e25e1c68fd2d7a84c2332afdff8f43c1 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 14:06:03 +0100 Subject: [PATCH 44/68] Add caused_by field in StorageBackend --- src/storage/backend.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 5ed062bc..aa78b5a0 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -241,17 +241,17 @@ impl StorageBackend { } #[derive(Debug)] -pub struct StorageBackendError { +pub struct StorageBackendError<'a> { pub action: String, // The file system action in words pub desc: String, // A short description pub data_dump: Option, // Data dump, if any pub caused_by: Option>, // caused from this error } -impl StorageBackendError { +impl<'a> StorageBackendError<'a> { fn new(action: String, desc : String, - data : Option) -> StorageBackendError + data : Option) -> StorageBackendError<'a> { StorageBackendError { action: action, @@ -275,7 +275,7 @@ impl StorageBackendError { } -impl Error for StorageBackendError { +impl<'a> Error for StorageBackendError<'a> { fn description(&self) -> &str { &self.desc[..] @@ -287,7 +287,7 @@ impl Error for StorageBackendError { } -impl Display for StorageBackendError { +impl<'a> Display for StorageBackendError<'a> { fn fmt(&self, f: &mut Formatter) -> FMTResult { write!(f, "StorageBackendError[{}]: {}", self.action, self.desc) From e0fefc3da441154bf99c731588585d9712f085dd Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 15:01:24 +0100 Subject: [PATCH 45/68] Reimplement StorageBackend::put_file() --- src/storage/backend.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index aa78b5a0..6dc3ae9b 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -109,7 +109,18 @@ impl StorageBackend { pub fn put_file(&self, f: File, p: &Parser) -> BackendOperationResult where HP: FileHeaderParser { - let written = write_with_parser(&f, p); + let written = p.write(f.contents()) + .or_else(|err| { + let mut serr = StorageBackendError::build( + "Parser::write()", + "Cannot parse file contents", + "Cannot translate internal representation of file contents into on-disk representation", + None + ); + serr.caused_by = Some(&err); + Err(serr) + }); + if written.is_err() { return Err(written.err().unwrap()); } let string = written.unwrap(); @@ -117,7 +128,7 @@ impl StorageBackend { debug!("Writing file: {}", path); debug!(" string: {}", string); - FSFile::create(&path).map(|mut file| { + FSFile::create(&path).map(|file| { debug!("Created file at '{}'", path); file.write_all(&string.clone().into_bytes()) .map_err(|ioerr| { @@ -125,9 +136,9 @@ impl StorageBackend { let mut err = StorageBackendError::build( "File::write_all()", "Could not write out File contents", - None + "", None ); - err.caused_by = Some(Box::new(ioerr)); + err.caused_by = Some(&ioerr); err }) }).map_err(|writeerr| { @@ -135,7 +146,7 @@ impl StorageBackend { let mut err = StorageBackendError::build( "File::create()", "Creating file on disk failed", - None + "", None ); err.caused_by = Some(Box::new(writeerr)); err @@ -263,7 +274,7 @@ impl<'a> StorageBackendError<'a> { fn build(action: &'static str, desc: &'static str, - data : Option) -> StorageBackendError + data : Option) -> StorageBackendError<'a> { StorageBackendError { action: String::from(action), From eabf726846bdb8875f4f1be3b123d3f1c7bfec2c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 15:07:07 +0100 Subject: [PATCH 46/68] Outsource file to string parsing --- src/storage/backend.rs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 6dc3ae9b..5d540608 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -109,18 +109,7 @@ impl StorageBackend { pub fn put_file(&self, f: File, p: &Parser) -> BackendOperationResult where HP: FileHeaderParser { - let written = p.write(f.contents()) - .or_else(|err| { - let mut serr = StorageBackendError::build( - "Parser::write()", - "Cannot parse file contents", - "Cannot translate internal representation of file contents into on-disk representation", - None - ); - serr.caused_by = Some(&err); - Err(serr) - }); - + let written = write_with_parser(&f, p); if written.is_err() { return Err(written.err().unwrap()); } let string = written.unwrap(); @@ -306,17 +295,16 @@ impl<'a> Display for StorageBackendError<'a> { } -fn write_with_parser<'a, HP>(f: &File, p: &Parser) -> Result - where HP: FileHeaderParser -{ +fn write_with_parser<'a, HP>(f: &File, p: &Parser) -> Result> { p.write(f.contents()) .or_else(|err| { let mut serr = StorageBackendError::build( "Parser::write()", + "Cannot parse file contents", "Cannot translate internal representation of file contents into on-disk representation", None ); - serr.caused_by = Some(Box::new(err)); + serr.caused_by = Some(&err); Err(serr) }) } From 366121b6ed7694ef2f4699e0fe449cdc6650ccf2 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 15:25:09 +0100 Subject: [PATCH 47/68] Reimplement StorageBackend::update_file() --- src/storage/backend.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 5d540608..71f61107 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -157,27 +157,29 @@ impl StorageBackend { debug!("Writing file: {}", path); debug!(" string: {}", string); - FSFile::open(&path).map(|mut file| { + FSFile::open(&path).map(|file| { debug!("Open file at '{}'", path); file.write_all(&string.clone().into_bytes()) .map_err(|ioerr| { debug!("Could not write file"); let mut err = StorageBackendError::build( "File::write()", + "", "Tried to write contents of this file, though operation did not succeed", Some(string) ); - err.caused_by = Some(Box::new(ioerr)); + err.caused_by = Some(&ioerr); err }) }).map_err(|writeerr| { debug!("Could not write file at '{}'", path); let mut err = StorageBackendError::build( "File::open()", + "", "Tried to update contents of this file, though file doesn't exist", None ); - err.caused_by = Some(Box::new(writeerr)); + err.caused_by = Some(&writeerr); err }).and(Ok(())) } From 4a6d1a74c0d06fb481b16d98ad04f4d6440325e1 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 15:43:40 +0100 Subject: [PATCH 48/68] Retry fixing the StorageBackend::cause() --- src/storage/backend.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 71f61107..0bc7d9c5 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -117,7 +117,7 @@ impl StorageBackend { debug!("Writing file: {}", path); debug!(" string: {}", string); - FSFile::create(&path).map(|file| { + FSFile::create(&path).map(|mut file| { debug!("Created file at '{}'", path); file.write_all(&string.clone().into_bytes()) .map_err(|ioerr| { @@ -127,7 +127,7 @@ impl StorageBackend { "Could not write out File contents", "", None ); - err.caused_by = Some(&ioerr); + err.caused_by = Some(Box::new(ioerr)); err }) }).map_err(|writeerr| { @@ -157,7 +157,7 @@ impl StorageBackend { debug!("Writing file: {}", path); debug!(" string: {}", string); - FSFile::open(&path).map(|file| { + FSFile::open(&path).map(|mut file| { debug!("Open file at '{}'", path); file.write_all(&string.clone().into_bytes()) .map_err(|ioerr| { @@ -168,7 +168,7 @@ impl StorageBackend { "Tried to write contents of this file, though operation did not succeed", Some(string) ); - err.caused_by = Some(&ioerr); + err.caused_by = Some(Box::new(ioerr)); err }) }).map_err(|writeerr| { @@ -179,7 +179,7 @@ impl StorageBackend { "Tried to update contents of this file, though file doesn't exist", None ); - err.caused_by = Some(&writeerr); + err.caused_by = Some(Box::new(writeerr)); err }).and(Ok(())) } @@ -243,14 +243,14 @@ impl StorageBackend { } #[derive(Debug)] -pub struct StorageBackendError<'a> { +pub struct StorageBackendError { pub action: String, // The file system action in words pub desc: String, // A short description pub data_dump: Option, // Data dump, if any pub caused_by: Option>, // caused from this error } -impl<'a> StorageBackendError<'a> { +impl StorageBackendError { fn new(action: String, desc : String, data : Option) -> StorageBackendError<'a> @@ -265,7 +265,7 @@ impl<'a> StorageBackendError<'a> { fn build(action: &'static str, desc: &'static str, - data : Option) -> StorageBackendError<'a> + data : Option) -> StorageBackendError<'a> { StorageBackendError { action: String::from(action), @@ -277,7 +277,7 @@ impl<'a> StorageBackendError<'a> { } -impl<'a> Error for StorageBackendError<'a> { +impl Error for StorageBackendError { fn description(&self) -> &str { &self.desc[..] @@ -289,7 +289,7 @@ impl<'a> Error for StorageBackendError<'a> { } -impl<'a> Display for StorageBackendError<'a> { +impl<'a> Display for StorageBackendError { fn fmt(&self, f: &mut Formatter) -> FMTResult { write!(f, "StorageBackendError[{}]: {}", self.action, self.desc) @@ -297,7 +297,9 @@ impl<'a> Display for StorageBackendError<'a> { } -fn write_with_parser<'a, HP>(f: &File, p: &Parser) -> Result> { +fn write_with_parser<'a, HP>(f: &File, p: &Parser) -> Result + where HP: FileHeaderParser +{ p.write(f.contents()) .or_else(|err| { let mut serr = StorageBackendError::build( @@ -306,7 +308,7 @@ fn write_with_parser<'a, HP>(f: &File, p: &Parser) -> Result Date: Sat, 28 Nov 2015 15:55:22 +0100 Subject: [PATCH 49/68] ModuleError needs a cause as well --- src/module/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/module/mod.rs b/src/module/mod.rs index 5b7cc133..d1e06716 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -15,12 +15,14 @@ pub mod bm; #[derive(Debug)] pub struct ModuleError { desc: String, + caused_by: Option>, } impl ModuleError { pub fn new(desc: &'static str) -> ModuleError { ModuleError { desc: desc.to_owned().to_string(), + caused_by: None, } } } @@ -32,7 +34,7 @@ impl Error for ModuleError { } fn cause(&self) -> Option<&Error> { - None + unimplemented!() } } From 83aa5afcbed03c2e801c40c268c69bfe925105da Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 15:55:37 +0100 Subject: [PATCH 50/68] Build ModuleError out of StorageBackendError if any --- src/module/bm/commands.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/module/bm/commands.rs b/src/module/bm/commands.rs index 18f71fcb..3385f6e4 100644 --- a/src/module/bm/commands.rs +++ b/src/module/bm/commands.rs @@ -2,6 +2,7 @@ use runtime::Runtime; use storage::backend::StorageBackend; use module::Module; +use module::ModuleError; use module::CommandResult; use module::CommandEnv; @@ -23,7 +24,11 @@ pub fn add_command(module: &Module, env: CommandEnv) -> CommandResult { let parser = Parser::new(JsonHeaderParser::new(None)); let putres = env.bk.put_file(file, &parser); - Ok(()) + putres.map_err(|sberr| { + let mut err = ModuleError::new("Storage Backend Error"); + err.caused_by = Some(Box::new(sberr)); + err + }) } pub fn list_command(module: &Module, env: CommandEnv) -> CommandResult { From 144398a2adf94a0ba455c1a25fd3114eb8607bf1 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 16:07:33 +0100 Subject: [PATCH 51/68] Remove explanation member of StorageBackendError to reduce complexibility --- src/storage/backend.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 0bc7d9c5..15035bfb 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -125,7 +125,7 @@ impl StorageBackend { let mut err = StorageBackendError::build( "File::write_all()", "Could not write out File contents", - "", None + None ); err.caused_by = Some(Box::new(ioerr)); err @@ -135,7 +135,7 @@ impl StorageBackend { let mut err = StorageBackendError::build( "File::create()", "Creating file on disk failed", - "", None + None ); err.caused_by = Some(Box::new(writeerr)); err @@ -164,7 +164,6 @@ impl StorageBackend { debug!("Could not write file"); let mut err = StorageBackendError::build( "File::write()", - "", "Tried to write contents of this file, though operation did not succeed", Some(string) ); @@ -175,7 +174,6 @@ impl StorageBackend { debug!("Could not write file at '{}'", path); let mut err = StorageBackendError::build( "File::open()", - "", "Tried to update contents of this file, though file doesn't exist", None ); @@ -253,7 +251,7 @@ pub struct StorageBackendError { impl StorageBackendError { fn new(action: String, desc : String, - data : Option) -> StorageBackendError<'a> + data : Option) -> StorageBackendError { StorageBackendError { action: action, @@ -265,7 +263,7 @@ impl StorageBackendError { fn build(action: &'static str, desc: &'static str, - data : Option) -> StorageBackendError<'a> + data : Option) -> StorageBackendError { StorageBackendError { action: String::from(action), @@ -304,7 +302,6 @@ fn write_with_parser<'a, HP>(f: &File, p: &Parser) -> Result Date: Sat, 28 Nov 2015 16:12:33 +0100 Subject: [PATCH 52/68] Add helper for building file prefix This helper builds the file prefix for the files of a module. --- src/storage/backend.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 15035bfb..5bc27103 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -235,7 +235,11 @@ impl StorageBackend { debug!(" basepath: '{}'", self.basepath); debug!(" storepath: '{}'", self.storepath); debug!(" id : '{}'", id); - self.storepath.clone() + owner.name() + "-" + &id[..] + ".imag" + self.prefix_of_files_for_module(owner) + "-" + &id[..] + ".imag" + } + + fn prefix_of_files_for_module(&self, m: &Module) -> String { + self.storepath.clone() + m.name() } } From 043e607765028937fc16c1b4ec5132878c858bdd Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 28 Nov 2015 16:19:37 +0100 Subject: [PATCH 53/68] Implement StorageBackendError::cause() --- src/module/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/mod.rs b/src/module/mod.rs index d1e06716..1319b90e 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -34,7 +34,7 @@ impl Error for ModuleError { } fn cause(&self) -> Option<&Error> { - unimplemented!() + self.caused_by.as_ref().map(|e| &**e) } } From e515a70ec2cbe5906e58edd77efe4a559a476f32 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 30 Nov 2015 18:33:13 +0100 Subject: [PATCH 54/68] Rewrite Debug for Module --- src/module/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/module/mod.rs b/src/module/mod.rs index 1319b90e..7d0d0562 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -3,6 +3,8 @@ use std::error::Error; use std::fmt::Formatter; use std::fmt::Result as FMTResult; use std::fmt::Display; +use std::fmt::Debug; +use std::path::Path; use std::result::Result; use std::collections::HashMap; @@ -55,7 +57,7 @@ pub type ModuleResult = Result<(), ModuleError>; pub type CommandResult = ModuleResult; pub type CommandMap<'a> = HashMap<&'a str, fn(&Module, CommandEnv) -> CommandResult>; -pub trait Module { +pub trait Module : Debug { fn callnames(&self) -> &'static [&'static str]; fn name(&self) -> &'static str; From 965779fcafba2b079892f2aada4a6e1c58dcff13 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 30 Nov 2015 18:33:30 +0100 Subject: [PATCH 55/68] Impl Debug for BMModule --- src/module/bm/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/module/bm/mod.rs b/src/module/bm/mod.rs index 2b8a712b..e963564b 100644 --- a/src/module/bm/mod.rs +++ b/src/module/bm/mod.rs @@ -5,6 +5,9 @@ use module::ModuleResult; use module::ModuleError; use std::path::Path; use std::result::Result; +use std::fmt::Result as FMTResult; +use std::fmt::Formatter; +use std::fmt::Debug; use clap::ArgMatches; use regex::Regex; @@ -56,3 +59,11 @@ impl Module for BMModule { } } +impl Debug for BMModule { + + fn fmt(&self, fmt: &mut Formatter) -> FMTResult { + write!(fmt, "[Module][BM]"); + Ok(()) + } + +} From e598a475e5b1f9b9e4cd13204db579c193ec37c3 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 30 Nov 2015 19:05:29 +0100 Subject: [PATCH 56/68] Use prettytable to implement TablePrinter --- src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.rs b/src/main.rs index ace2b973..02e9d34c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ #[macro_use] extern crate glob; #[macro_use] extern crate uuid; #[macro_use] extern crate regex; +#[macro_use] extern crate prettytable; extern crate config; use cli::CliConfig; From 103cba0c27897efafbac03dc8296d2f82c1e3e7c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 30 Nov 2015 19:50:24 +0100 Subject: [PATCH 57/68] Add File::matches_with(&Regex) --- src/storage/file.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/storage/file.rs b/src/storage/file.rs index 10a4e218..aca195c4 100644 --- a/src/storage/file.rs +++ b/src/storage/file.rs @@ -285,6 +285,10 @@ impl<'a> File<'a> { self.owning_module } + pub fn matches_with(&self, r: &Regex) -> bool { + r.is_match(&self.data[..]) || self.header.matches_with(r) + } + fn get_new_file_id() -> FileID { use uuid::Uuid; Uuid::new_v4().to_hyphenated_string() From a6ed8e1080d044a0e10ecce743dc0d87d6df7864 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 29 Nov 2015 12:09:30 +0100 Subject: [PATCH 58/68] Pass id as &FileID in StorageBackend::get_file_by_id() --- src/storage/backend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 5bc27103..d4e6c61c 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -189,7 +189,7 @@ impl StorageBackend { * TODO: Needs refactoring, as there might be an error when reading from * disk OR the id just does not exist. */ - pub fn get_file_by_id<'a, HP>(&self, m: &'a Module, id: FileID, p: &Parser) -> Option> + pub fn get_file_by_id<'a, HP>(&self, m: &'a Module, id: &FileID, p: &Parser) -> Option> where HP: FileHeaderParser { debug!("Searching for file with id '{}'", id); From 42181afde56a2896f0a1ffa33e4a5b7611958d46 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sun, 29 Nov 2015 14:23:54 +0100 Subject: [PATCH 59/68] Add tags_of_file() to extract tags from a File --- src/module/bm/header.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/module/bm/header.rs b/src/module/bm/header.rs index 62c61a25..10f20d80 100644 --- a/src/module/bm/header.rs +++ b/src/module/bm/header.rs @@ -1,5 +1,6 @@ use storage::file::FileHeaderSpec as FHS; use storage::file::FileHeaderData as FHD; +use std::ops::Deref; pub fn get_spec() -> FHS { FHS::Map { keys: vec![ url_key(), tags_key() ] } @@ -38,3 +39,41 @@ fn build_tag_array(tags: &Vec) -> FHD { FHD::Array { values: Box::new(texttags) } } +pub fn get_tags_from_header(header: &FHD) -> Vec { + let mut tags : Vec = vec![]; + + fn match_array(a: &Box) -> Vec { + let mut tags : Vec = vec![]; + + match a.deref() { + &FHD::Array{values: ref vs} => { + let values : Vec = vs.deref().clone(); + for value in values { + match value { + FHD::Text(t) => tags.push(t), + _ => warn!("Malformed Header Data: Expected Text, found non-Text"), + } + } + } + _ => warn!("Malformed Header Data: Expected Array, found non-Array"), + } + + tags + } + + match header { + &FHD::Map{keys: ref ks} => { + let keys : Vec = ks.clone(); + for key in keys { + match key { + FHD::Key{name: _, value: ref v} => return match_array(v), + _ => warn!("Malformed Header Data: Expected Key, found non-Key"), + } + } + }, + _ => warn!("Malformed Header Data: Expected Map, found non-Map"), + } + + tags +} + From 6fcccc82973058294844a090a7ff9ed7ee269c81 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Mon, 30 Nov 2015 19:55:13 +0100 Subject: [PATCH 60/68] Implement list_command --- src/module/bm/commands.rs | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/module/bm/commands.rs b/src/module/bm/commands.rs index 3385f6e4..dcb3db17 100644 --- a/src/module/bm/commands.rs +++ b/src/module/bm/commands.rs @@ -7,9 +7,11 @@ use module::CommandResult; use module::CommandEnv; use module::bm::header::build_header; +use module::bm::header::get_tags_from_header; use storage::json::parser::JsonHeaderParser; use storage::parser::{Parser, FileHeaderParser}; use storage::file::File; +use ui::file::{FilePrinter, TablePrinter}; use clap::ArgMatches; use regex::Regex; @@ -33,18 +35,29 @@ pub fn add_command(module: &Module, env: CommandEnv) -> CommandResult { pub fn list_command(module: &Module, env: CommandEnv) -> CommandResult { let tags = get_tags(env.rt, env.matches); - let matcher = get_matcher(env.rt, env.matches); + debug!("Tags: {:?}", tags); + let parser = Parser::new(JsonHeaderParser::new(None)); + let printer = TablePrinter::new(env.rt.is_verbose(), env.rt.is_debugging()); + let files = env.bk.iter_files(module, &parser).and_then(|files| { + let f = files.filter(|file| { + if tags.len() != 0 { + debug!("Checking tags of: {:?}", file.id()); + get_tags_from_header(&file.header()).iter() + .any(|t| tags.contains(t)) + } else { + true + } + }).filter(|file| { + debug!("Checking matches of: {:?}", file.id()); + get_matcher(env.rt, env.matches) + .and_then(|r| Some(file.matches_with(&r))) + .unwrap_or(true) + }).collect::>(); + Some(f) + }).unwrap_or(Vec::::new()).into_iter(); - match matcher { - Some(reg) => { - info!("Listing urls with matcher '{}' and with tags {:?}", - reg.as_str(), - tags); - } - None => { - info!("Listing urls with tags {:?}", tags); - } - } + debug!("Printing files now"); + printer.print_files(files); Ok(()) } From e6e56b9a92e0b7de574acea9416c265cded7e060 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 1 Dec 2015 12:19:26 +0100 Subject: [PATCH 61/68] Add flag --check / -c We have to ensure that there are no references to this bookmark entry from other modules. --- etc/cli.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/etc/cli.yml b/etc/cli.yml index 93ab5bf0..780fe377 100644 --- a/etc/cli.yml +++ b/etc/cli.yml @@ -177,6 +177,12 @@ subcommands: required: false takes_value: true + - check: + short: c + long: check + help: Ensure there are no references to this link + required: false + takes_value: false - todo: about: Todo module From 484b1fb8650e6533771d7fac9bb77e50ed612f48 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 1 Dec 2015 12:38:15 +0100 Subject: [PATCH 62/68] Outsource file retrieving from list_command() into helper function --- src/module/bm/commands.rs | 47 ++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/module/bm/commands.rs b/src/module/bm/commands.rs index dcb3db17..8db00078 100644 --- a/src/module/bm/commands.rs +++ b/src/module/bm/commands.rs @@ -12,6 +12,7 @@ use storage::json::parser::JsonHeaderParser; use storage::parser::{Parser, FileHeaderParser}; use storage::file::File; use ui::file::{FilePrinter, TablePrinter}; +use std::vec::IntoIter; use clap::ArgMatches; use regex::Regex; @@ -34,27 +35,8 @@ pub fn add_command(module: &Module, env: CommandEnv) -> CommandResult { } pub fn list_command(module: &Module, env: CommandEnv) -> CommandResult { - let tags = get_tags(env.rt, env.matches); - debug!("Tags: {:?}", tags); - let parser = Parser::new(JsonHeaderParser::new(None)); let printer = TablePrinter::new(env.rt.is_verbose(), env.rt.is_debugging()); - let files = env.bk.iter_files(module, &parser).and_then(|files| { - let f = files.filter(|file| { - if tags.len() != 0 { - debug!("Checking tags of: {:?}", file.id()); - get_tags_from_header(&file.header()).iter() - .any(|t| tags.contains(t)) - } else { - true - } - }).filter(|file| { - debug!("Checking matches of: {:?}", file.id()); - get_matcher(env.rt, env.matches) - .and_then(|r| Some(file.matches_with(&r))) - .unwrap_or(true) - }).collect::>(); - Some(f) - }).unwrap_or(Vec::::new()).into_iter(); + let files = get_filtered_files_from_backend(module, &env); debug!("Printing files now"); printer.print_files(files); @@ -93,6 +75,31 @@ pub fn remove_command(module: &Module, env: CommandEnv) -> CommandResult { * */ +fn get_filtered_files_from_backend<'a>(module: &'a Module, + env: &CommandEnv) -> IntoIter> +{ + let parser = Parser::new(JsonHeaderParser::new(None)); + let tags = get_tags(env.rt, env.matches); + debug!("Tags: {:?}", tags); + env.bk.iter_files(module, &parser).and_then(|files| { + let f = files.filter(|file| { + if tags.len() != 0 { + debug!("Checking tags of: {:?}", file.id()); + get_tags_from_header(&file.header()).iter() + .any(|t| tags.contains(t)) + } else { + true + } + }).filter(|file| { + debug!("Checking matches of: {:?}", file.id()); + get_matcher(env.rt, env.matches) + .and_then(|r| Some(file.matches_with(&r))) + .unwrap_or(true) + }).collect::>(); + Some(f) + }).unwrap_or(Vec::::new()).into_iter() +} + fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Vec { debug!("Fetching tags from commandline"); sub.value_of("tags").and_then(|tags| From c81d0bf0a8d6016f73040c8994e9a814e9b36a8e Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 1 Dec 2015 16:09:49 +0100 Subject: [PATCH 63/68] Implement remove_command() --- src/module/bm/commands.rs | 64 +++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/src/module/bm/commands.rs b/src/module/bm/commands.rs index 8db00078..74c22d5c 100644 --- a/src/module/bm/commands.rs +++ b/src/module/bm/commands.rs @@ -1,5 +1,5 @@ use runtime::Runtime; -use storage::backend::StorageBackend; +use storage::backend::{StorageBackendError, StorageBackend}; use module::Module; use module::ModuleError; @@ -45,28 +45,54 @@ pub fn list_command(module: &Module, env: CommandEnv) -> CommandResult { } pub fn remove_command(module: &Module, env: CommandEnv) -> CommandResult { - let tags = get_tags(env.rt, env.matches); - let matcher = get_matcher(env.rt, env.matches); - let id = get_id(env.rt, env.matches); + if let Some(id) = get_id(env.rt, env.matches) { + debug!("Remove by id: {}", id); - match id { - Some(idstr) => { - info!("Removing urls with id '{}'", idstr); + let parser = Parser::new(JsonHeaderParser::new(None)); + let file = env.bk.get_file_by_id(module, &id, &parser).unwrap(); + debug!("Remove file : {:?}", file); + + if let Err(e) = env.bk.remove_file(module, file) { + debug!("Remove failed"); + let mut err = ModuleError::new("Removing file failed"); + err.caused_by = Some(Box::new(e)); + Err(err) + } else { + debug!("Remove worked"); + Ok(()) } - None => { - match matcher { - Some(reg) => { - info!("Removing urls with matcher '{}' and with tags {:?}", - reg.as_str(), tags); - } - None => { - info!("Listing urls with tags {:?}", tags); - } - } + } else { + debug!("Remove more than one file"); + + let files = get_filtered_files_from_backend(module, &env); + let nfiles = files.len(); + info!("Removing {} Files", nfiles); + + let errs = files.map(|file| { + debug!("Remove file: {:?}", file); + env.bk.remove_file(module, file) + }) + .filter(|e| e.is_err()) + .map(|e| { + let err = e.err().unwrap(); + warn!("Error occured in Filesystem operation: {}", err); + err + }) + .collect::>(); + + let nerrs = errs.len(); + + if nerrs != 0 { + warn!("{} Errors occured while removing {} files", nerrs, nfiles); + let moderr = ModuleError::new("File removal failed"); + + // TODO : Collect StorageBackendErrors + + Err(moderr) + } else { + Ok(()) } } - - Ok(()) } /* From 4675f79aae44efb689acb78e91fa68fcbf6a5ef5 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 1 Dec 2015 16:32:35 +0100 Subject: [PATCH 64/68] remove_command(): Be able to run in "checked" mode --- src/module/bm/commands.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/module/bm/commands.rs b/src/module/bm/commands.rs index 74c22d5c..80f2bd42 100644 --- a/src/module/bm/commands.rs +++ b/src/module/bm/commands.rs @@ -45,6 +45,8 @@ pub fn list_command(module: &Module, env: CommandEnv) -> CommandResult { } pub fn remove_command(module: &Module, env: CommandEnv) -> CommandResult { + let checked : bool = run_removal_checking(&env); + debug!("Checked mode: {}", checked); if let Some(id) = get_id(env.rt, env.matches) { debug!("Remove by id: {}", id); @@ -52,7 +54,7 @@ pub fn remove_command(module: &Module, env: CommandEnv) -> CommandResult { let file = env.bk.get_file_by_id(module, &id, &parser).unwrap(); debug!("Remove file : {:?}", file); - if let Err(e) = env.bk.remove_file(module, file) { + if let Err(e) = env.bk.remove_file(module, file, checked) { debug!("Remove failed"); let mut err = ModuleError::new("Removing file failed"); err.caused_by = Some(Box::new(e)); @@ -70,7 +72,7 @@ pub fn remove_command(module: &Module, env: CommandEnv) -> CommandResult { let errs = files.map(|file| { debug!("Remove file: {:?}", file); - env.bk.remove_file(module, file) + env.bk.remove_file(module, file, checked) }) .filter(|e| e.is_err()) .map(|e| { @@ -162,3 +164,10 @@ fn get_id<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option { sub.value_of("id").and_then(|s| Some(String::from(s))) } +/* + * Checks whether the commandline call was set to run the removal "checked", + * so if another entry from the store refers to this ID, do not remove the file. + */ +fn run_removal_checking(env: &CommandEnv) -> bool { + env.matches.is_present("check") +} From abee4d4904e60ac6752e50947190bbdd9a9a71ff Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 1 Dec 2015 16:59:52 +0100 Subject: [PATCH 65/68] Implement StorageBackend::remove_file() --- src/storage/backend.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index d4e6c61c..42f734c0 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -6,7 +6,6 @@ use std::path::Path; use std::path::PathBuf; use std::vec::Vec; use std::fs::File as FSFile; -use std::fs::create_dir_all; use std::fs::remove_file; use std::io::Read; use std::io::Write; From 731d13e0ba7f1521f22c179d17e71fce5fb93a52 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 1 Dec 2015 17:31:41 +0100 Subject: [PATCH 66/68] Create store path on storage backend creation --- src/main.rs | 9 +++++++-- src/storage/backend.rs | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 02e9d34c..62834703 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,8 @@ mod module; mod storage; mod ui; +use std::process::exit; + fn main() { let yaml = load_yaml!("../etc/cli.yml"); let app = App::from_yaml(yaml); @@ -41,14 +43,17 @@ fn main() { debug!("Runtime : {:?}", &rt); + let backend = StorageBackend::new(&rt).unwrap_or_else(|e| { + error!("Error: {}", e); + exit(1); + }); + if let Some(matches) = rt.config.cli_matches.subcommand_matches("bm") { let module = BMModule::new(&rt); let commands = module.get_commands(&rt); if let Some(command) = matches.subcommand_name() { debug!("Subcommand: {}", command); - let backend = StorageBackend::new(&rt); - let cmdenv = CommandEnv { rt: &rt, bk: &backend, diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 42f734c0..d4e6c61c 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -6,6 +6,7 @@ use std::path::Path; use std::path::PathBuf; use std::vec::Vec; use std::fs::File as FSFile; +use std::fs::create_dir_all; use std::fs::remove_file; use std::io::Read; use std::io::Write; From 9231049e303dc2bfec05b0fe935eb1ee11b43145 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 2 Dec 2015 12:28:41 +0100 Subject: [PATCH 67/68] Remove StorageBackend::build() --- src/storage/backend.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index d4e6c61c..11e0b7ad 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -52,13 +52,6 @@ impl StorageBackend { }) } - fn build(rt: &Runtime, m: &M) -> StorageBackend { - let path = rt.get_rtp() + m.name() + "/store"; - // TODO: Don't use "/store" but value from configuration - debug!("Building StorageBackend for {}", path); - StorageBackend::new(path) - } - fn get_file_ids(&self, m: &Module) -> Option> { let list = glob(&self.prefix_of_files_for_module(m)[..]); From 05a9803c05220b7fb4f46b61c0d2a285ef396f27 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 2 Dec 2015 12:29:04 +0100 Subject: [PATCH 68/68] Fixup: Member name --- src/storage/backend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage/backend.rs b/src/storage/backend.rs index 11e0b7ad..e89dc049 100644 --- a/src/storage/backend.rs +++ b/src/storage/backend.rs @@ -265,7 +265,7 @@ impl StorageBackendError { StorageBackendError { action: String::from(action), desc: String::from(desc), - dataDump: data, + data_dump: data, caused_by: None, } }