Change sq cert import and sq key import to use stdout.

- Change `sq cert import` and `sq key import` to use `stdout`, not
    `stderr`, for their main output.

  - See #342.
This commit is contained in:
Neal H. Walfield 2024-12-03 18:38:09 +01:00
parent 4b76ba2b81
commit 93217dcfd0
No known key found for this signature in database
GPG Key ID: 6863C9AD5B4D22D3
4 changed files with 71 additions and 53 deletions

View File

@ -41,6 +41,8 @@ where 'store: 'rstore
cmd.input
};
let o = &mut std::io::stdout();
let mut stats = ImportStats::default();
let inner = || -> Result<()> {
@ -81,11 +83,11 @@ where 'store: 'rstore
let result = match typ {
Type::Signature => {
import_rev(
&mut sq, &mut input_reader, &mut stats)
o, &mut sq, &mut input_reader, &mut stats)
}
Type::Keyring => {
import_certs(
&mut sq, &mut input_reader,
o, &mut sq, &mut input_reader,
input.path(), &mut stats)
}
Type::Other => {
@ -110,14 +112,15 @@ where 'store: 'rstore
let result = inner();
weprintln!();
stats.print_summary(&sq)?;
wwriteln!(o);
stats.print_summary(o, &sq)?;
Ok(result?)
}
/// Imports certs encoded as OpenPGP keyring.
fn import_certs(sq: &mut Sq,
fn import_certs(o: &mut dyn std::io::Write,
sq: &mut Sq,
source: &mut Box<dyn BufferedReader<Cookie>>,
source_path: Option<&PathBuf>,
stats: &mut ImportStats)
@ -163,12 +166,12 @@ fn import_certs(sq: &mut Sq,
if let Err(err) = cert_store.update_by(Arc::new(cert.into()),
stats)
{
weprintln!("Error importing {}, {}: {}",
fingerprint, sanitized_userid, err);
wwriteln!(o, "Error importing {}, {}: {}",
fingerprint, sanitized_userid, err);
stats.certs.inc_errors();
continue;
} else {
weprintln!("Imported {}, {}", fingerprint, sanitized_userid);
wwriteln!(o, "Imported {}, {}", fingerprint, sanitized_userid);
}
}
@ -178,14 +181,15 @@ fn import_certs(sq: &mut Sq,
Err(errors.pop().ok_or_else(|| anyhow::anyhow!("no cert found"))?)
} else {
for err in errors {
weprintln!("Error parsing input: {}", err);
wwriteln!(o, "Error parsing input: {}", err);
}
Ok(())
}
}
/// Import a bare revocation certificate.
fn import_rev(sq: &mut Sq,
fn import_rev(o: &mut dyn std::io::Write,
sq: &mut Sq,
source: &mut Box<dyn BufferedReader<Cookie>>,
stats: &mut ImportStats)
-> Result<()>
@ -248,15 +252,17 @@ fn import_rev(sq: &mut Sq,
if let Err(err) = cert_store.update_by(Arc::new(cert.into()),
stats)
{
weprintln!("Error importing revocation certificate \
for {}, {}: {}",
fingerprint, sanitized_userid, err);
wwriteln!(o,
"Error importing revocation certificate \
for {}, {}: {}",
fingerprint, sanitized_userid, err);
stats.certs.inc_errors();
continue;
} else {
weprintln!("Imported revocation certificate \
for {}, {}",
fingerprint, sanitized_userid);
wwriteln!(o,
"Imported revocation certificate \
for {}, {}",
fingerprint, sanitized_userid);
}
return Ok(());
@ -267,17 +273,19 @@ fn import_rev(sq: &mut Sq,
}
let search: Option<&KeyHandle> = if let Some(bad) = bad.first() {
weprintln!("Appears to be a revocation for {}, \
but the certificate is not available.",
bad);
wwriteln!(o,
"Appears to be a revocation for {}, \
but the certificate is not available.",
bad);
Some(bad)
} else if ! missing.is_empty() {
weprintln!("Appears to be a revocation for {}, \
but the certificate is not available.",
missing.iter()
.map(|issuer| issuer.to_string())
.collect::<Vec<_>>()
.join(" or "));
wwriteln!(o,
"Appears to be a revocation for {}, \
but the certificate is not available.",
missing.iter()
.map(|issuer| issuer.to_string())
.collect::<Vec<_>>()
.join(" or "));
Some(missing[0])
} else {
None

View File

@ -11,14 +11,18 @@ use crate::cli::types::FileOrStdin;
use crate::Sq;
use crate::Result;
pub fn import(sq: Sq, command: cli::key::import::Command) -> Result<()> {
pub fn import(sq: Sq, command: cli::key::import::Command)
-> Result<()>
{
let o = &mut std::io::stdout();
let mut stats = Default::default();
let r = import_internal(&sq, command, &mut stats);
stats.print_summary(&sq)?;
let r = import_internal(o, &sq, command, &mut stats);
stats.print_summary(o, &sq)?;
r
}
fn import_internal(sq: &Sq, command: cli::key::import::Command,
fn import_internal(o: &mut dyn std::io::Write,
sq: &Sq, command: cli::key::import::Command,
stats: &mut ImportStats)
-> Result<()>
{
@ -39,7 +43,7 @@ fn import_internal(sq: &Sq, command: cli::key::import::Command,
let cert = match r {
Ok(cert) => cert,
Err(err) => {
weprintln!("Error reading {}: {}", file.display(), err);
wwriteln!(o, "Error reading {}: {}", file.display(), err);
if ret.is_ok() {
ret = Err(err);
}
@ -54,18 +58,18 @@ fn import_internal(sq: &Sq, command: cli::key::import::Command,
let cert_is_tsk = cert.is_tsk();
match sq.import_key(cert, stats) {
Ok((key, cert)) => {
weprintln!("Imported {} from {}: {}",
id, file.display(),
if key == cert {
key.to_string()
} else {
format!("key {}, cert {}", key, cert)
});
wwriteln!(o, "Imported {} from {}: {}",
id, file.display(),
if key == cert {
key.to_string()
} else {
format!("key {}, cert {}", key, cert)
});
}
Err(err) => {
weprintln!("Error importing {} from {}: {}",
id, file.display(), err);
wwriteln!(o, "Error importing {} from {}: {}",
id, file.display(), err);
if ! cert_is_tsk {
sq.hint(format_args!(

View File

@ -113,6 +113,8 @@ pub fn import_certs(sq: &Sq, certs: Vec<Cert>) -> Result<()> {
let mut stats = ImportStats::default();
let o = &mut std::io::stderr();
for cert in certs.iter() {
cert_store.update_by(Arc::new(cert.clone().into()), &mut stats)
.with_context(|| {
@ -123,7 +125,7 @@ pub fn import_certs(sq: &Sq, certs: Vec<Cert>) -> Result<()> {
})?;
}
stats.print_summary(sq)?;
stats.print_summary(o, sq)?;
for vcert in certs.iter()
.filter_map(|cert| cert.with_policy(sq.policy, sq.time).ok())

View File

@ -61,20 +61,23 @@ impl<'a> MergeCerts<'a> for ImportStats {
impl ImportStats {
/// Print key and certificate import summary.
pub fn print_summary(&self, sq: &crate::Sq) -> Result<()> {
pub fn print_summary(&self, o: &mut dyn std::io::Write, sq: &crate::Sq)
-> Result<()>
{
if sq.quiet() {
return Ok(());
}
if ! self.keys.is_empty() {
self.keys.print_summary()?;
self.keys.print_summary(o)?;
}
weprintln!("Imported {}, updated {}, {} unchanged, {}.",
self.certs.new_certs().of("new certificate"),
self.certs.updated_certs().of("certificate"),
self.certs.unchanged_certs().of("certificate"),
self.certs.errors().of("error"));
wwriteln!(o,
"Imported {}, updated {}, {} unchanged, {}.",
self.certs.new_certs().of("new certificate"),
self.certs.updated_certs().of("certificate"),
self.certs.unchanged_certs().of("certificate"),
self.certs.errors().of("error"));
Ok(())
}
}
@ -114,12 +117,13 @@ impl KeyStats {
}
/// Print key and certificate import summary.
pub fn print_summary(&self) -> Result<()> {
weprintln!("Imported {}, updated {}, {} unchanged, {}.",
self.new.of("new key"),
self.updated.of("key"),
self.unchanged.of("key"),
self.errors.of("error"));
pub fn print_summary(&self, o: &mut dyn std::io::Write) -> Result<()> {
wwriteln!(o,
"Imported {}, updated {}, {} unchanged, {}.",
self.new.of("new key"),
self.updated.of("key"),
self.unchanged.of("key"),
self.errors.of("error"));
Ok(())
}
}