use std::{
fs::{read, write},
path::PathBuf,
};
use clap::Parser;
use log::info;
use crate::{
store::{EncryptedStore, EncryptedStoreError, Store, StoreError},
Config, LeafCommand,
};
#[derive(Debug, Parser)]
pub struct ExportCommand {
filename: PathBuf,
}
impl LeafCommand for ExportCommand {
type Error = ExportError;
fn run(&self, config: &Config) -> Result<(), ExportError> {
let store = EncryptedStore::new(config.sop(), config.store()).read_store()?;
info!("loaded store OK");
let json = serde_json::to_string_pretty(&store).map_err(ExportError::ToJson)?;
write(&self.filename, &json)
.map_err(|err| ExportError::WriteFile(self.filename.clone(), err))?;
Ok(())
}
}
#[derive(Debug, Parser)]
pub struct ImportCommand {
filename: PathBuf,
}
impl LeafCommand for ImportCommand {
type Error = ExportError;
fn run(&self, config: &Config) -> Result<(), ExportError> {
let encrypted = EncryptedStore::new(config.sop(), config.store());
let mut store = encrypted.read_store()?;
let data = read(&self.filename)
.map_err(|err| ExportError::ReadFile(self.filename.clone(), err))?;
let imported: Store = serde_json::from_slice(&data).map_err(ExportError::FromJson)?;
store.import(&imported);
encrypted.write_store(&store)?;
Ok(())
}
}
#[derive(Debug, thiserror::Error)]
pub enum ExportError {
#[error(transparent)]
Encrypted(#[from] EncryptedStoreError),
#[error(transparent)]
Store(#[from] StoreError),
#[error("failed to serialize store as JSON")]
ToJson(#[source] serde_json::Error),
#[error("failed to parse exported data as JSON")]
FromJson(#[source] serde_json::Error),
#[error("failed to read exported data from file {0}")]
ReadFile(PathBuf, #[source] std::io::Error),
#[error("failed to write exported data to file {0}")]
WriteFile(PathBuf, #[source] std::io::Error),
}