use anyhow::Result;
use clap::ArgMatches;
use prs_lib::{crypto::prelude::*, Store};
use thiserror::Error;
use crate::cmd::matcher::{copy::CopyMatcher, MainMatcher, Matcher};
#[cfg(all(feature = "tomb", target_os = "linux"))]
use crate::util::tomb;
use crate::util::{clipboard, secret, select};
pub struct Copy<'a> {
cmd_matches: &'a ArgMatches,
}
impl<'a> Copy<'a> {
pub fn new(cmd_matches: &'a ArgMatches) -> Self {
Self { cmd_matches }
}
pub fn invoke(&self) -> Result<()> {
let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
let matcher_copy = CopyMatcher::with(self.cmd_matches).unwrap();
let store = Store::open(matcher_main.store()).map_err(Err::Store)?;
#[cfg(all(feature = "tomb", target_os = "linux"))]
let mut tomb = store.tomb(
!matcher_main.verbose(),
matcher_main.verbose(),
matcher_main.force(),
);
#[cfg(all(feature = "tomb", target_os = "linux"))]
tomb::prepare_tomb(&mut tomb, &matcher_main).map_err(Err::Tomb)?;
let secret =
select::store_select_secret(&store, matcher_copy.query()).ok_or(Err::NoneSelected)?;
secret::print_name(matcher_copy.query(), &secret, &store, matcher_main.quiet());
let mut plaintext = crate::crypto::context(&matcher_main)?
.decrypt_file(&secret.path)
.map_err(Err::Read)?;
if let Some(property) = matcher_copy.property() {
plaintext = plaintext.property(property).map_err(Err::Property)?;
} else if !matcher_copy.all() {
plaintext = plaintext.first_line()?;
}
clipboard::copy_plaintext(
plaintext,
false,
!matcher_main.force(),
matcher_main.quiet(),
matcher_main.verbose(),
matcher_copy.timeout()?,
)?;
#[cfg(all(feature = "tomb", target_os = "linux"))]
tomb::finalize_tomb(&mut tomb, &matcher_main, false).map_err(Err::Tomb)?;
Ok(())
}
}
#[derive(Debug, Error)]
pub enum Err {
#[error("failed to access password store")]
Store(#[source] anyhow::Error),
#[cfg(all(feature = "tomb", target_os = "linux"))]
#[error("failed to prepare password store tomb for usage")]
Tomb(#[source] anyhow::Error),
#[error("no secret selected")]
NoneSelected,
#[error("failed to read secret")]
Read(#[source] anyhow::Error),
#[error("failed to select property from secret")]
Property(#[source] anyhow::Error),
}