use crate::hooks::executor::HookExecutor;
use crate::models::configuration::{Configuration, StoreRegistration, encrypt_store};
use crate::models::password_store::PasswordStore;
use anyhow::{Context, Result};
pub(super) const NO_STORE_FOUND_ERROR: &str =
"No store found in configuration. Run 'pasejo store add ...' first to add one";
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(super) enum StoreMutation {
Unchanged,
Modified,
}
pub(super) fn with_store<F, T>(
configuration: &Configuration,
store_name: Option<&String>,
offline: bool,
f: F,
) -> Result<T>
where
F: FnOnce(&StoreRegistration, &mut PasswordStore) -> Result<(T, StoreMutation)>,
{
with_store_then(configuration, store_name, offline, f, |_| Ok(()))
}
pub(super) fn with_store_then<F, P, T>(
configuration: &Configuration,
store_name: Option<&String>,
offline: bool,
f: F,
then: P,
) -> Result<T>
where
F: FnOnce(&StoreRegistration, &mut PasswordStore) -> Result<(T, StoreMutation)>,
P: FnOnce(&T) -> Result<()>,
{
let registration = configuration
.select_store(store_name)
.context(NO_STORE_FOUND_ERROR)?;
let hooks = HookExecutor {
configuration,
registration,
offline,
force: false,
};
hooks.execute_pull_commands()?;
let mut store = configuration.decrypt_store(registration)?;
let (value, mutation) = f(registration, &mut store)?;
if matches!(mutation, StoreMutation::Modified) {
encrypt_store(registration, &store).context("Cannot encrypt store")?;
}
then(&value)?;
if matches!(mutation, StoreMutation::Modified) {
hooks.execute_push_commands()?;
}
Ok(value)
}