Add --info
This commit is contained in:
135
src/main.rs
135
src/main.rs
@@ -3,7 +3,10 @@ use std::io::{Read, Write};
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashMap;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
use anyhow::{Context, Result, Error, anyhow};
|
use anyhow::{Context, Result, Error, anyhow};
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
@@ -81,27 +84,31 @@ struct Args {
|
|||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
struct ModeArgs {
|
struct ModeArgs {
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["get", "list", "update", "delete", "status"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["get", "list", "update", "delete", "info", "status"]))]
|
||||||
#[arg(help("Save an item using any tags or metadata provided"))]
|
#[arg(help("Save an item using any tags or metadata provided"))]
|
||||||
save: bool,
|
save: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "list", "update", "delete", "status"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "list", "update", "delete", "info", "status"]))]
|
||||||
#[arg(help("Get an item either by it's ID or by a combination of matching tags and metatdata"))]
|
#[arg(help("Get an item either by it's ID or by a combination of matching tags and metatdata"))]
|
||||||
get: bool,
|
get: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "update", "delete", "status"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "update", "delete", "info", "status"]))]
|
||||||
#[arg(help("List items, filtering on tags or metadata if given"))]
|
#[arg(help("List items, filtering on tags or metadata if given"))]
|
||||||
list: bool,
|
list: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "list", "delete", "status"]), requires("ids_or_tags"))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "list", "delete", "info", "status"]), requires("ids_or_tags"))]
|
||||||
#[arg(help("Update a specified item ID's tags and/or metadata"))]
|
#[arg(help("Update a specified item ID's tags and/or metadata"))]
|
||||||
update: bool,
|
update: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "list", "update", "status"]), requires("ids_or_tags"))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "list", "update", "info", "status"]), requires("ids_or_tags"))]
|
||||||
#[arg(help("Delete items either by ID or by matching tags"))]
|
#[arg(help("Delete items either by ID or by matching tags"))]
|
||||||
delete: bool,
|
delete: bool,
|
||||||
|
|
||||||
#[arg(group("mode"), help_heading("Mode Options"), short('S'), long, conflicts_with_all(["save", "get", "list", "update", "delete"]))]
|
#[arg(group("mode"), help_heading("Mode Options"), short, long, conflicts_with_all(["save", "get", "list", "update", "delete", "status"]), requires("ids_or_tags"))]
|
||||||
|
#[arg(help("Get an item either by it's ID or by a combination of matching tags and metatdata"))]
|
||||||
|
info: bool,
|
||||||
|
|
||||||
|
#[arg(group("mode"), help_heading("Mode Options"), short('S'), long, conflicts_with_all(["save", "get", "list", "update", "delete", "info"]))]
|
||||||
#[arg(help("Show status of directories and supported compression algorithms"))]
|
#[arg(help("Show status of directories and supported compression algorithms"))]
|
||||||
status: bool
|
status: bool
|
||||||
}
|
}
|
||||||
@@ -125,6 +132,10 @@ struct OptionsArgs {
|
|||||||
#[arg(help("Specify the directory to use for storage"))]
|
#[arg(help("Specify the directory to use for storage"))]
|
||||||
dir: Option<PathBuf>,
|
dir: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[arg(long, env("KEEP_LIST_META"), default_value("hostname"))]
|
||||||
|
#[arg(help("A comma separated list of item metadata names to display with --list"))]
|
||||||
|
list_meta: String,
|
||||||
|
|
||||||
#[arg(short, long, action = clap::ArgAction::Count, conflicts_with("quiet"))]
|
#[arg(short, long, action = clap::ArgAction::Count, conflicts_with("quiet"))]
|
||||||
#[arg(help("Increase message verbosity, can be given more than once"))]
|
#[arg(help("Increase message verbosity, can be given more than once"))]
|
||||||
verbose: u8,
|
verbose: u8,
|
||||||
@@ -143,6 +154,7 @@ enum KeepModes {
|
|||||||
List,
|
List,
|
||||||
Update,
|
Update,
|
||||||
Delete,
|
Delete,
|
||||||
|
Info,
|
||||||
Status
|
Status
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +234,8 @@ fn main() -> Result<(), Error> {
|
|||||||
mode = KeepModes::Delete;
|
mode = KeepModes::Delete;
|
||||||
} else if args.mode.update {
|
} else if args.mode.update {
|
||||||
mode = KeepModes::Update;
|
mode = KeepModes::Update;
|
||||||
|
} else if args.mode.info {
|
||||||
|
mode = KeepModes::Info;
|
||||||
} else if args.mode.status {
|
} else if args.mode.status {
|
||||||
mode = KeepModes::Status;
|
mode = KeepModes::Status;
|
||||||
}
|
}
|
||||||
@@ -270,6 +284,7 @@ fn main() -> Result<(), Error> {
|
|||||||
KeepModes::Get => mode_get(&mut cmd, args, ids, tags, &mut conn, data_path)?,
|
KeepModes::Get => mode_get(&mut cmd, args, ids, tags, &mut conn, data_path)?,
|
||||||
KeepModes::List => mode_list(&mut cmd, args, ids, tags, &mut conn, data_path)?,
|
KeepModes::List => mode_list(&mut cmd, args, ids, tags, &mut conn, data_path)?,
|
||||||
KeepModes::Update => mode_update(&mut cmd, args, ids, tags, &mut conn)?,
|
KeepModes::Update => mode_update(&mut cmd, args, ids, tags, &mut conn)?,
|
||||||
|
KeepModes::Info => mode_info(&mut cmd, args, ids, tags, &mut conn, data_path)?,
|
||||||
KeepModes::Delete => mode_delete(&mut cmd, args, ids, tags, &mut conn, data_path)?,
|
KeepModes::Delete => mode_delete(&mut cmd, args, ids, tags, &mut conn, data_path)?,
|
||||||
KeepModes::Status => mode_status(&mut cmd, args, data_path, db_path)?,
|
KeepModes::Status => mode_status(&mut cmd, args, data_path, db_path)?,
|
||||||
_ => todo!()
|
_ => todo!()
|
||||||
@@ -569,6 +584,112 @@ fn mode_update(cmd: &mut Command, args: Args, ids: &mut Vec<i64>, tags: &mut Vec
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mode_info(cmd: &mut Command, args: Args, ids: &mut Vec<i64>, tags: &mut Vec<String>, conn: &mut Connection, data_path: PathBuf) -> Result<()> {
|
||||||
|
if ! ids.is_empty() && ! tags.is_empty() {
|
||||||
|
cmd.error(ErrorKind::InvalidValue, "Both ID and tags given, you must supply exactly one ID or atleast one tag when using --info").exit();
|
||||||
|
} else if ids.len() > 1 {
|
||||||
|
cmd.error(ErrorKind::InvalidValue, "More than one ID given, you must supply exactly one ID or atleast one tag when using --info").exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut meta: HashMap<String, String> = HashMap::new();
|
||||||
|
for item in args.item.meta.iter() {
|
||||||
|
let item = item.clone();
|
||||||
|
meta.insert(item.key, item.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
let item_maybe = match tags.is_empty() && meta.is_empty() {
|
||||||
|
true => match ids.iter().next() {
|
||||||
|
Some(item_id) => db::get_item(conn, *item_id)?,
|
||||||
|
None => db::get_item_last(conn)?
|
||||||
|
},
|
||||||
|
false => db::get_item_matching(conn, tags, &meta)?
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if let Some(item) = item_maybe {
|
||||||
|
debug!("MAIN: Found item {:?}", item);
|
||||||
|
let item_id = item.id.unwrap();
|
||||||
|
|
||||||
|
let item_tags: Vec<String> = db::get_item_tags(conn, &item)?
|
||||||
|
.into_iter()
|
||||||
|
.map(|x| {x.name})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
|
||||||
|
let mut table = Table::new();
|
||||||
|
if std::io::stdout().is_terminal() {
|
||||||
|
table.set_format(*FORMAT_BOX_CHARS_NO_BORDER_LINE_SEPARATOR);
|
||||||
|
} else {
|
||||||
|
table.set_format(*FORMAT_NO_BORDER_LINE_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.add_row(Row::new(vec![
|
||||||
|
Cell::new("ID").with_style(Attr::Bold),
|
||||||
|
Cell::new(&item_id.to_string())
|
||||||
|
]));
|
||||||
|
|
||||||
|
let ts_cell = Cell::new(&item.ts.with_timezone(&Local).format("%F %T").to_string());
|
||||||
|
|
||||||
|
table.add_row(Row::new(vec![
|
||||||
|
Cell::new("Timestamp").with_style(Attr::Bold),
|
||||||
|
ts_cell
|
||||||
|
]));
|
||||||
|
|
||||||
|
|
||||||
|
let mut item_path = data_path.clone();
|
||||||
|
item_path.push(item.id.unwrap().to_string());
|
||||||
|
|
||||||
|
table.add_row(Row::new(vec![
|
||||||
|
Cell::new("Path").with_style(Attr::Bold),
|
||||||
|
Cell::new(item_path.to_str().expect("Unable to get item path"))
|
||||||
|
]));
|
||||||
|
|
||||||
|
let size_cell = match item.size {
|
||||||
|
Some(size) => Cell::new(format_size(size as u64, BINARY).as_str()),
|
||||||
|
None => Cell::new("Missing").with_style(Attr::ForegroundColor(color::RED)).with_style(Attr::Bold)
|
||||||
|
};
|
||||||
|
|
||||||
|
table.add_row(Row::new(vec![
|
||||||
|
Cell::new("Stream Size").with_style(Attr::Bold),
|
||||||
|
size_cell
|
||||||
|
]));
|
||||||
|
|
||||||
|
|
||||||
|
let compression_type = CompressionType::from_str(&item.compression)?;
|
||||||
|
table.add_row(Row::new(vec![
|
||||||
|
Cell::new("Compression").with_style(Attr::Bold),
|
||||||
|
Cell::new(&compression_type.to_string())
|
||||||
|
]));
|
||||||
|
|
||||||
|
let file_size_cell = match item_path.metadata() {
|
||||||
|
Ok(metadata) => Cell::new(format_size(metadata.len(), BINARY).as_str()),
|
||||||
|
Err(_) => Cell::new("Missing").with_style(Attr::ForegroundColor(color::RED)).with_style(Attr::Bold)
|
||||||
|
};
|
||||||
|
|
||||||
|
table.add_row(Row::new(vec![
|
||||||
|
Cell::new("File Size").with_style(Attr::Bold),
|
||||||
|
file_size_cell
|
||||||
|
]));
|
||||||
|
|
||||||
|
table.add_row(Row::new(vec![
|
||||||
|
Cell::new("Tags").with_style(Attr::Bold),
|
||||||
|
Cell::new(&item_tags.join(" "))
|
||||||
|
]));
|
||||||
|
|
||||||
|
for meta in db::get_item_meta(conn, &item)? {
|
||||||
|
let meta_name = format!("Meta: {}", &meta.name);
|
||||||
|
table.add_row(Row::new(vec![
|
||||||
|
Cell::new(meta_name.as_str()).with_style(Attr::Bold),
|
||||||
|
Cell::new(&meta.value)
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
table.printstd();
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("Unable to find matching item in database"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn mode_delete(cmd: &mut Command, _args: Args, ids: &mut Vec<i64>, tags: &mut Vec<String>, conn: &mut Connection, data_path: PathBuf) -> Result<()> {
|
fn mode_delete(cmd: &mut Command, _args: Args, ids: &mut Vec<i64>, tags: &mut Vec<String>, conn: &mut Connection, data_path: PathBuf) -> Result<()> {
|
||||||
if ids.is_empty() {
|
if ids.is_empty() {
|
||||||
|
|||||||
Reference in New Issue
Block a user