Add a progress bar to the network fetch commands.

This commit is contained in:
Justus Winter 2024-02-09 17:53:10 +01:00
parent 47ec10264e
commit b796ce1b8c
No known key found for this signature in database
GPG Key ID: 686F55B4AB2B3386
3 changed files with 88 additions and 6 deletions

54
Cargo.lock generated
View File

@ -558,6 +558,19 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "console"
version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"unicode-width",
"windows-sys 0.52.0",
]
[[package]]
name = "const-oid"
version = "0.9.6"
@ -987,6 +1000,12 @@ dependencies = [
"log",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "encoding_rs"
version = "0.8.33"
@ -1731,6 +1750,19 @@ dependencies = [
"hashbrown 0.14.3",
]
[[package]]
name = "indicatif"
version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25"
dependencies = [
"console",
"instant",
"number_prefix",
"portable-atomic",
"unicode-width",
]
[[package]]
name = "inout"
version = "0.1.3"
@ -1741,6 +1773,15 @@ dependencies = [
"generic-array",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "ipconfig"
version = "0.3.2"
@ -2181,6 +2222,12 @@ dependencies = [
"libc",
]
[[package]]
name = "number_prefix"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
name = "object"
version = "0.32.2"
@ -2461,6 +2508,12 @@ dependencies = [
"universal-hash",
]
[[package]]
name = "portable-atomic"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
[[package]]
name = "powerfmt"
version = "0.2.0"
@ -3107,6 +3160,7 @@ dependencies = [
"dot-writer",
"fehler",
"humantime",
"indicatif",
"itertools",
"libc",
"predicates",

View File

@ -40,6 +40,7 @@ anyhow = "1.0.18"
chrono = "0.4.10"
clap = { version = "4", features = ["derive", "env", "string", "wrap_help"] }
humantime = "2"
indicatif = "0.17"
itertools = ">=0.10, <0.13"
sequoia-cert-store = "0.4.1"
sequoia-wot = "0.9"

View File

@ -6,6 +6,7 @@ use std::sync::Arc;
use std::time::{Duration, SystemTime};
use anyhow::Context;
use indicatif::ProgressBar;
use tokio::task::JoinSet;
use sequoia_openpgp as openpgp;
@ -499,6 +500,15 @@ struct Response {
}
impl Response {
/// Creates a progress bar.
fn progress_bar(config: &Config) -> ProgressBar {
if config.verbose {
ProgressBar::hidden()
} else {
ProgressBar::new(0)
}
}
/// Collects the responses, and displays failures.
///
/// If `silent_errors` is given, then failure messages are
@ -507,12 +517,14 @@ impl Response {
async fn collect(config: &mut Config<'_>,
mut responses: JoinSet<Response>,
certify: bool,
silent_errors: bool)
silent_errors: bool,
pb: &mut ProgressBar)
-> Result<Vec<Cert>>
{
let mut certs = Vec::new();
let mut errors = Vec::new();
while let Some(response) = responses.join_next().await {
pb.inc(1);
let response = response?;
match response.results {
Ok(returned_certs) => for cert in returned_certs {
@ -540,7 +552,7 @@ impl Response {
if ! silent_errors || config.verbose || certs.is_empty() {
for (method, query, e) in errors {
wprintln!("{}: {}: {}", method, query, e);
pb.suspend(|| wprintln!("{}: {}: {}", method, query, e));
}
}
@ -588,6 +600,8 @@ pub fn dispatch_fetch(mut config: Config, c: cli::network::fetch::Command)
let mut seen_ids = HashSet::new();
let mut queries = Query::parse(&c.query)?;
let mut results = Vec::new();
let mut pb = Response::progress_bar(&config);
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(async {
for _ in 0..FETCH_MAX_QUERY_ITERATIONS {
@ -611,6 +625,7 @@ pub fn dispatch_fetch(mut config: Config, c: cli::network::fetch::Command)
for ks in servers.iter().cloned() {
let query = query.clone();
pb.inc_length(1);
requests.spawn(async move {
let results = match query.clone() {
Query::Handle(h) => ks.get(h).await,
@ -628,6 +643,7 @@ pub fn dispatch_fetch(mut config: Config, c: cli::network::fetch::Command)
if let Some(address) = query.as_address() {
let a = address.to_string();
let http_client = http_client.clone();
pb.inc_length(1);
requests.spawn(async move {
let results =
wkd::get(&http_client, &a).await;
@ -639,6 +655,7 @@ pub fn dispatch_fetch(mut config: Config, c: cli::network::fetch::Command)
});
let a = address.to_string();
pb.inc_length(1);
requests.spawn(async move {
let results = dane::get(&a).await;
Response {
@ -655,7 +672,7 @@ pub fn dispatch_fetch(mut config: Config, c: cli::network::fetch::Command)
}
let mut certs = Response::collect(
&mut config, requests, c.output.is_none(), default_servers).await?;
&mut config, requests, c.output.is_none(), default_servers, &mut pb).await?;
// Expand certs to discover new identifiers to query.
for cert in &certs {
@ -673,6 +690,7 @@ pub fn dispatch_fetch(mut config: Config, c: cli::network::fetch::Command)
Result::Ok(())
})?;
drop(pb);
Response::import_or_emit(config, c.output, c.binary, results)?;
Ok(())
@ -707,12 +725,14 @@ pub fn dispatch_keyserver(mut config: Config,
use crate::cli::network::keyserver::Subcommands::*;
match c.subcommand {
Fetch(c) => rt.block_on(async {
let mut pb = Response::progress_bar(&config);
let queries = Query::parse(&c.query)?;
let mut requests = tokio::task::JoinSet::new();
queries.into_iter().for_each(|query| {
for ks in servers.iter().cloned() {
let query = query.clone();
pb.inc_length(1);
requests.spawn(async move {
let results = match query.clone() {
Query::Handle(h) => ks.get(h).await,
@ -729,7 +749,8 @@ pub fn dispatch_keyserver(mut config: Config,
});
let certs = Response::collect(
&mut config, requests, c.output.is_none(), default_servers).await?;
&mut config, requests, c.output.is_none(), default_servers, &mut pb).await?;
drop(pb);
Response::import_or_emit(config, c.output, c.binary, certs)?;
Result::Ok(())
})?,
@ -819,10 +840,12 @@ pub fn dispatch_wkd(mut config: Config, c: cli::network::wkd::Command)
output.write(config.output_format, &mut std::io::stdout())?;
},
Fetch(c) => rt.block_on(async {
let mut pb = Response::progress_bar(&config);
let http_client = http_client()?;
let queries = Query::parse_addresses(&c.addresses)?;
let mut requests = tokio::task::JoinSet::new();
queries.into_iter().for_each(|query| {
pb.inc_length(1);
let http_client = http_client.clone();
requests.spawn(async move {
let results = wkd::get(
@ -838,7 +861,8 @@ pub fn dispatch_wkd(mut config: Config, c: cli::network::wkd::Command)
});
let certs = Response::collect(
&mut config, requests, c.output.is_none(), false).await?;
&mut config, requests, c.output.is_none(), false, &mut pb).await?;
drop(pb);
Response::import_or_emit(config, c.output, c.binary, certs)?;
Result::Ok(())
})?,
@ -912,9 +936,11 @@ pub fn dispatch_dane(mut config: Config, c: cli::network::dane::Command)
}
},
Fetch(c) => rt.block_on(async {
let mut pb = Response::progress_bar(&config);
let queries = Query::parse_addresses(&c.addresses)?;
let mut requests = tokio::task::JoinSet::new();
queries.into_iter().for_each(|query| {
pb.inc_length(1);
requests.spawn(async move {
let results = dane::get(
query.as_address().expect("parsed only addresses"))
@ -928,7 +954,8 @@ pub fn dispatch_dane(mut config: Config, c: cli::network::dane::Command)
});
let certs = Response::collect(
&mut config, requests, c.output.is_none(), false).await?;
&mut config, requests, c.output.is_none(), false, &mut pb).await?;
drop(pb);
Response::import_or_emit(config, c.output, c.binary, certs)?;
Result::Ok(())
})?,