summaryrefslogtreecommitdiffstats
path: root/tool
diff options
context:
space:
mode:
authorJustus Winter <justus@pep-project.org>2018-01-09 17:00:30 +0100
committerJustus Winter <justus@sequoia-pgp.org>2018-01-11 14:50:58 +0100
commit6f1a94f2dd0c7cb7c5e264d4c620a48c1b72152c (patch)
treef2bb9b3563c05585725c6408cde33df9d7ab26d3 /tool
parenta3e1899cb4f52c4b87b7165afe1923d2f023f09d (diff)
store: Implement iteration over stores, bindings, and keys.
- Also add corresponding commands to the tool.
Diffstat (limited to 'tool')
-rw-r--r--tool/Cargo.toml1
-rw-r--r--tool/src/main.rs82
-rw-r--r--tool/src/usage.rs97
3 files changed, 180 insertions, 0 deletions
diff --git a/tool/Cargo.toml b/tool/Cargo.toml
index 3becea63..f0118c1a 100644
--- a/tool/Cargo.toml
+++ b/tool/Cargo.toml
@@ -9,6 +9,7 @@ sequoia-core = { path = "../core" }
sequoia-net = { path = "../net" }
sequoia-store = { path = "../store" }
clap = "2.27.1"
+prettytable-rs = "0.6.7"
[[bin]]
name = "sq"
diff --git a/tool/src/main.rs b/tool/src/main.rs
index dd791252..0df05a36 100644
--- a/tool/src/main.rs
+++ b/tool/src/main.rs
@@ -1,8 +1,13 @@
/// A command-line frontend for Sequoia.
extern crate clap;
+#[macro_use]
+extern crate prettytable;
use clap::{Arg, App, SubCommand, AppSettings};
+use prettytable::Table;
+use prettytable::cell::Cell;
+use prettytable::row::Row;
use std::fs::File;
use std::io;
use std::process::exit;
@@ -113,6 +118,8 @@ fn real_main() -> Result<()> {
.arg(Arg::with_name("name").value_name("NAME")
.required(true)
.help("Name of the store"))
+ .subcommand(SubCommand::with_name("list")
+ .about("Lists keys in the store"))
.subcommand(SubCommand::with_name("add")
.about("Add a key identified by fingerprint")
.arg(Arg::with_name("label").value_name("LABEL")
@@ -160,6 +167,18 @@ fn real_main() -> Result<()> {
.arg(Arg::with_name("label").value_name("LABEL")
.required(true)
.help("Label to use"))))
+ .subcommand(SubCommand::with_name("list")
+ .about("Lists key stores and known keys")
+ .subcommand(SubCommand::with_name("stores")
+ .about("Lists key stores")
+ .arg(Arg::with_name("prefix").value_name("PREFIX")
+ .help("List only stores with the given domain prefix")))
+ .subcommand(SubCommand::with_name("bindings")
+ .about("Lists all bindings in all key stores")
+ .arg(Arg::with_name("prefix").value_name("PREFIX")
+ .help("List only bindings from stores with the given domain prefix")))
+ .subcommand(SubCommand::with_name("keys")
+ .about("Lists all keys in the common key pool")))
.get_matches();
let policy = match matches.value_of("policy") {
@@ -271,6 +290,9 @@ fn real_main() -> Result<()> {
.expect("Failed to open store");
match m.subcommand() {
+ ("list", Some(_)) => {
+ list_bindings(&store);
+ },
("add", Some(m)) => {
let fp = Fingerprint::from_hex(m.value_of("fingerprint").unwrap())
.expect("Malformed fingerprint");
@@ -333,6 +355,53 @@ fn real_main() -> Result<()> {
},
}
},
+ ("list", Some(m)) => {
+ match m.subcommand() {
+ ("stores", Some(m)) => {
+ let mut table = Table::new();
+ table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
+ table.set_titles(row!["domain", "name", "network policy", "# of entries"]);
+
+ for item in Store::list(&ctx, m.value_of("prefix").unwrap_or(""))
+ .expect("Failed to iterate over stores") {
+ table.add_row(Row::new(vec![
+ Cell::new(&item.domain),
+ Cell::new(&item.name),
+ Cell::new(&format!("{:?}", item.network_policy)),
+ Cell::new(&format!("{}", item.entries))])
+ );
+ }
+
+ table.printstd();
+ },
+ ("bindings", Some(m)) => {
+ for item in Store::list(&ctx, m.value_of("prefix").unwrap_or(""))
+ .expect("Failed to iterate over stores") {
+ println!("Domain {:?} Name {:?}:", item.domain, item.name);
+ list_bindings(&item.store);
+ }
+ },
+ ("keys", Some(_)) => {
+ let mut table = Table::new();
+ table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
+ table.set_titles(row!["fingerprint", "# of bindings"]);
+
+ for item in Store::list_keys(&ctx)
+ .expect("Failed to iterate over keys") {
+ table.add_row(Row::new(vec![
+ Cell::new(&item.fingerprint.to_string()),
+ Cell::new(&format!("{}", item.bindings))])
+ );
+ }
+
+ table.printstd();
+ },
+ _ => {
+ eprintln!("No list subcommand given.");
+ exit(1);
+ },
+ }
+ },
_ => {
eprintln!("No subcommand given.");
exit(1);
@@ -342,4 +411,17 @@ fn real_main() -> Result<()> {
return Ok(())
}
+fn list_bindings(store: &Store) {
+ let mut table = Table::new();
+ table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
+ table.set_titles(row!["label", "fingerprint"]);
+ for item in store.iter().expect("Failed to iterate over bindings") {
+ table.add_row(Row::new(vec![
+ Cell::new(&item.label),
+ Cell::new(&item.fingerprint.to_string())]));
+ }
+ table.printstd();
+}
+
+
fn main() { real_main().expect("An error occured"); }
diff --git a/tool/src/usage.rs b/tool/src/usage.rs
index 07cdc099..213ac00b 100644
--- a/tool/src/usage.rs
+++ b/tool/src/usage.rs
@@ -22,6 +22,7 @@
//! enarmor Applies ASCII Armor to a file
//! help Prints this message or the help of the given subcommand(s)
//! keyserver Interacts with keyservers
+//! list Lists key stores and known keys
//! store Interacts with key stores
//! ```
//!
@@ -135,6 +136,70 @@
//! -i, --input <FILE> Sets the input file to use
//! ```
//!
+//! ## Subcommand list
+//!
+//! ```text
+//! Lists key stores and known keys
+//!
+//! USAGE:
+//! sq list [SUBCOMMAND]
+//!
+//! FLAGS:
+//! -h, --help Prints help information
+//! -V, --version Prints version information
+//!
+//! SUBCOMMANDS:
+//! bindings Lists all bindings in all key stores
+//! help Prints this message or the help of the given subcommand(s)
+//! keys Lists all keys in the common key pool
+//! stores Lists key stores
+//! ```
+//!
+//! ### Subcommand list bindings
+//!
+//! ```text
+//! Lists all bindings in all key stores
+//!
+//! USAGE:
+//! sq list bindings [PREFIX]
+//!
+//! FLAGS:
+//! -h, --help Prints help information
+//! -V, --version Prints version information
+//!
+//! ARGS:
+//! <PREFIX> List only bindings from stores with the given domain prefix
+//! ```
+//!
+//! ### Subcommand list keys
+//!
+//! ```text
+//! Lists all keys in the common key pool
+//!
+//! USAGE:
+//! sq list keys
+//!
+//! FLAGS:
+//! -h, --help Prints help information
+//! -V, --version Prints version information
+//! ```
+//!
+//! ### Subcommand list stores
+//!
+//! ```text
+//! Lists key stores
+//!
+//! USAGE:
+//! sq list stores [PREFIX]
+//!
+//! FLAGS:
+//! -h, --help Prints help information
+//! -V, --version Prints version information
+//!
+//! ARGS:
+//! <PREFIX> List only stores with the given domain prefix
+//! ```
+//!
//! ## Subcommand store
//!
//! ```text
@@ -152,9 +217,11 @@
//!
//! SUBCOMMANDS:
//! add Add a key identified by fingerprint
+//! delete Deletes bindings or stores
//! export Exports a key
//! help Prints this message or the help of the given subcommand(s)
//! import Imports a key
+//! list Lists keys in the store
//! stats Get stats for the given label
//! ```
//!
@@ -175,6 +242,23 @@
//! <FINGERPRINT> Key to add
//! ```
//!
+//! ### Subcommand store delete
+//!
+//! ```text
+//! Deletes bindings or stores
+//!
+//! USAGE:
+//! sq store <NAME> delete [FLAGS] [LABEL]
+//!
+//! FLAGS:
+//! -h, --help Prints help information
+//! --the-store Delete the whole store
+//! -V, --version Prints version information
+//!
+//! ARGS:
+//! <LABEL> Delete binding with this label
+//! ```
+//!
//! ### Subcommand store export
//!
//! ```text
@@ -215,6 +299,19 @@
//! <LABEL> Label to use
//! ```
//!
+//! ### Subcommand store list
+//!
+//! ```text
+//! Lists keys in the store
+//!
+//! USAGE:
+//! sq store <NAME> list
+//!
+//! FLAGS:
+//! -h, --help Prints help information
+//! -V, --version Prints version information
+//! ```
+//!
//! ### Subcommand store stats
//!
//! ```text