diff --git a/imag-link/Cargo.toml b/imag-link/Cargo.toml new file mode 100644 index 00000000..87b9ac55 --- /dev/null +++ b/imag-link/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "imag-link" +version = "0.1.0" +authors = ["Matthias Beyer "] + +[dependencies] +semver = "0.2.1" +clap = "2.1.1" +log = "0.3.5" +version = "2.0.1" +toml = "0.1.25" + +[dependencies.libimagstore] +path = "../libimagstore" + +[dependencies.libimagrt] +path = "../libimagrt" + +[dependencies.libimaglink] +path = "../libimaglink" + +[dependencies.libimagutil] +path = "../libimagutil" + diff --git a/imag-link/src/main.rs b/imag-link/src/main.rs new file mode 100644 index 00000000..5934987a --- /dev/null +++ b/imag-link/src/main.rs @@ -0,0 +1,147 @@ +#[macro_use] extern crate log; +extern crate clap; +#[macro_use] extern crate semver; +extern crate toml; +#[macro_use] extern crate version; + +extern crate libimaglink; +extern crate libimagrt; +extern crate libimagstore; +extern crate libimagutil; + +use std::process::exit; +use std::ops::Deref; +use std::error::Error; + +use libimagrt::runtime::Runtime; +use libimagstore::error::StoreError; +use libimagstore::store::Entry; +use libimagstore::store::FileLockEntry; +use libimagstore::store::Store; +use libimagutil::trace::trace_error; + +mod ui; + +use ui::build_ui; + +fn main() { + let name = "imag-link"; + let version = &version!()[..]; + let about = "Link entries"; + let ui = build_ui(Runtime::get_default_cli_builder(name, version, about)); + let rt = { + let rt = Runtime::new(ui); + if rt.is_ok() { + rt.unwrap() + } else { + println!("Could not set up Runtime"); + println!("{:?}", rt.err().unwrap()); + exit(1); + } + }; + + rt.init_logger(); + + debug!("Hello. Logging was just enabled"); + debug!("I already set up the Runtime object and build the commandline interface parser."); + debug!("Lets get rollin' ..."); + + rt.cli() + .subcommand_name() + .map(|name| { + match name { + "internal" => handle_internal_linking(&rt), + "external" => { unimplemented!() }, + _ => { + warn!("No commandline call"); + exit(1); + }, + } + }); +} + +fn handle_internal_linking(rt: &Runtime) { + use libimaglink::internal::InternalLinker; + use libimagutil::trace::trace_error; + + let mut from = { + let mut from = get_from_entry(&rt); + if from.is_none() { + warn!("No 'from' entry"); + exit(1); + } + from.unwrap() + }; + debug!("Link from = {:?}", from.deref()); + + let mut to = { + let mut to = get_to_entries(&rt); + if to.is_none() { + warn!("No 'to' entry"); + exit(1); + } + to.unwrap() + }; + debug!("Link to = {:?}", to.iter().map(|f| f.deref()).collect::>()); + + match rt.cli().subcommand_matches("internal").unwrap().subcommand_name() { + Some("add") => { + for mut to_entry in to { + if let Err(e) = to_entry.add_internal_link(&mut from) { + trace_error(&e); + exit(1); + } + } + }, + + Some("remove") => { + for mut to_entry in to { + if let Err(e) = to_entry.remove_internal_link(&mut from) { + trace_error(&e); + exit(1); + } + } + }, + + _ => unreachable!(), + // as the get_from_entry()/get_to_entries() would have errored + } +} + +fn get_from_entry<'a>(rt: &'a Runtime) -> Option> { + rt.cli() + .subcommand_matches("internal") + .unwrap() // safe, we know there is an "internal" subcommand" + .value_of("from") + .and_then(|from_name| { + match get_entry_by_name(rt, from_name) { + Err(e) => { trace_error(&e); None }, + Ok(e) => Some(e), + } + + }) +} + +fn get_to_entries<'a>(rt: &'a Runtime) -> Option>> { + rt.cli() + .subcommand_matches("internal") + .unwrap() // safe, we know there is an "internal" subcommand" + .values_of("to") + .map(|values| { + let mut v = vec![]; + for entry in values.map(|v| get_entry_by_name(rt, v)) { + match entry { + Err(e) => trace_error(&e), + Ok(e) => v.push(e), + } + } + v + }) +} + +fn get_entry_by_name<'a>(rt: &'a Runtime, name: &str) -> Result, StoreError> { + use libimagstore::storeid::build_entry_path; + build_entry_path(rt.store(), name) + .and_then(|path| rt.store().retrieve(path)) +} + diff --git a/imag-link/src/ui.rs b/imag-link/src/ui.rs new file mode 100644 index 00000000..39828e15 --- /dev/null +++ b/imag-link/src/ui.rs @@ -0,0 +1,91 @@ +use clap::{Arg, App, SubCommand}; + +pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + app + .subcommand(SubCommand::with_name("internal") + .about("Add, remove and list internal links") + .version("0.1") + .subcommand(SubCommand::with_name("add") + .about("Add link from one entry to another (and vice-versa)") + .version("0.1") + .arg(Arg::with_name("from") + .long("from") + .short("f") + .takes_value(true) + .required(true) + .help("Link from this entry")) + .arg(Arg::with_name("to") + .long("to") + .short("t") + .takes_value(true) + .required(true) + .multiple(true) + .help("Link to this entries")) + ) + + .subcommand(SubCommand::with_name("remove") + .about("Remove a link between two or more entries") + .version("0.1") + .arg(Arg::with_name("from") + .long("from") + .short("f") + .takes_value(true) + .required(true) + .help("Remove Link from this entry")) + .arg(Arg::with_name("to") + .long("to") + .short("t") + .takes_value(true) + .required(true) + .multiple(true) + .help("Remove links to these entries")) + ) + + .arg(Arg::with_name("list") + .long("list") + .short("l") + .takes_value(false) + .required(false) + .help("List links to this entry")) + ) + .subcommand(SubCommand::with_name("external") + .about("Add and remove external links") + .version("0.1") + + .arg(Arg::with_name("id") + .long("id") + .short("i") + .takes_value(true) + .required(true) + .help("Modify external link of this entry")) + + .arg(Arg::with_name("set") + .long("set") + .short("s") + .takes_value(true) + .required(false) + .help("Set this URI as external link")) + + .arg(Arg::with_name("remove") + .long("remove") + .short("r") + .takes_value(false) + .required(false) + .help("Remove external link")) + + .arg(Arg::with_name("list") + .long("list") + .short("l") + .takes_value(false) + .required(false) + .help("List external link")) + + .arg(Arg::with_name("show") + .long("show") + .short("s") + .takes_value(false) + .required(false) + .help("List external link (alias for --list)")) + ) +} +