fix(cli): trash empty unlocks vault once, not per item
Extracted purge_item helper so cmd_trash_empty loops over it without re-prompting for passphrase per item. Single git commit per trash empty summarizing the count. Caught in Task 12 review.
This commit is contained in:
@@ -992,9 +992,32 @@ fn cmd_restore(query: String) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmd_purge(query: String) -> Result<()> {
|
/// Inner purge: assumes vault is already unlocked and manifest is loaded.
|
||||||
|
/// Caller is responsible for saving the manifest and committing afterwards.
|
||||||
|
fn purge_item(
|
||||||
|
vault: &crate::session::UnlockedVault,
|
||||||
|
manifest: &mut relicario_core::Manifest,
|
||||||
|
id: &relicario_core::ItemId,
|
||||||
|
title: &str,
|
||||||
|
) -> Result<()> {
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
|
let item_path = vault.item_path(id);
|
||||||
|
if item_path.exists() { fs::remove_file(&item_path)?; }
|
||||||
|
let att_dir = vault.root().join("attachments").join(id.as_str());
|
||||||
|
if att_dir.exists() { fs::remove_dir_all(&att_dir)?; }
|
||||||
|
manifest.remove(id);
|
||||||
|
|
||||||
|
let _ = crate::helpers::git_command(vault.root(), &["rm", "-rf", "--ignore-unmatch",
|
||||||
|
&format!("items/{}.enc", id.as_str()),
|
||||||
|
&format!("attachments/{}", id.as_str()),
|
||||||
|
]).status()?;
|
||||||
|
// Note: caller adds+commits manifest.enc after processing all purges.
|
||||||
|
eprintln!("Purged: {title}");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cmd_purge(query: String) -> Result<()> {
|
||||||
let vault = crate::session::UnlockedVault::unlock_interactive()?;
|
let vault = crate::session::UnlockedVault::unlock_interactive()?;
|
||||||
let mut manifest = vault.load_manifest()?;
|
let mut manifest = vault.load_manifest()?;
|
||||||
let entry = resolve_query(&manifest, &query)?;
|
let entry = resolve_query(&manifest, &query)?;
|
||||||
@@ -1002,25 +1025,14 @@ fn cmd_purge(query: String) -> Result<()> {
|
|||||||
let title = entry.title.clone();
|
let title = entry.title.clone();
|
||||||
let _ = entry;
|
let _ = entry;
|
||||||
|
|
||||||
// Remove the item file, its attachments directory, and drop the manifest entry.
|
purge_item(&vault, &mut manifest, &id, &title)?;
|
||||||
let item_path = vault.item_path(&id);
|
|
||||||
if item_path.exists() { fs::remove_file(&item_path)?; }
|
|
||||||
let att_dir = vault.root().join("attachments").join(id.as_str());
|
|
||||||
if att_dir.exists() { fs::remove_dir_all(&att_dir)?; }
|
|
||||||
manifest.remove(&id);
|
|
||||||
vault.save_manifest(&manifest)?;
|
vault.save_manifest(&manifest)?;
|
||||||
|
|
||||||
// `git rm -rf --ignore-unmatch` stages the deletions. Then add manifest and commit.
|
|
||||||
let _ = crate::helpers::git_command(vault.root(), &["rm", "-rf", "--ignore-unmatch",
|
|
||||||
&format!("items/{}.enc", id.as_str()),
|
|
||||||
&format!("attachments/{}", id.as_str()),
|
|
||||||
]).status()?;
|
|
||||||
let status = crate::helpers::git_command(vault.root(), &["add", "manifest.enc"]).status()?;
|
let status = crate::helpers::git_command(vault.root(), &["add", "manifest.enc"]).status()?;
|
||||||
if !status.success() { anyhow::bail!("git add manifest.enc failed"); }
|
if !status.success() { anyhow::bail!("git add manifest.enc failed"); }
|
||||||
let status = crate::helpers::git_command(vault.root(),
|
let status = crate::helpers::git_command(vault.root(),
|
||||||
&["commit", "-m", &format!("purge: {} ({})", title, id.as_str())]).status()?;
|
&["commit", "-m", &format!("purge: {} ({})", title, id.as_str())]).status()?;
|
||||||
if !status.success() { anyhow::bail!("git commit failed"); }
|
if !status.success() { anyhow::bail!("git commit failed"); }
|
||||||
eprintln!("Purged: {title}");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1033,8 +1045,9 @@ fn cmd_trash(action: TrashAction) -> Result<()> {
|
|||||||
|
|
||||||
fn cmd_trash_empty() -> Result<()> {
|
fn cmd_trash_empty() -> Result<()> {
|
||||||
use relicario_core::time::now_unix;
|
use relicario_core::time::now_unix;
|
||||||
|
|
||||||
let vault = crate::session::UnlockedVault::unlock_interactive()?;
|
let vault = crate::session::UnlockedVault::unlock_interactive()?;
|
||||||
let manifest = vault.load_manifest()?;
|
let mut manifest = vault.load_manifest()?;
|
||||||
let settings = vault.load_settings()?;
|
let settings = vault.load_settings()?;
|
||||||
let now = now_unix();
|
let now = now_unix();
|
||||||
|
|
||||||
@@ -1051,10 +1064,20 @@ fn cmd_trash_empty() -> Result<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut purged_titles = Vec::new();
|
||||||
for (id, title) in purgeable {
|
for (id, title) in purgeable {
|
||||||
cmd_purge(id.as_str().to_string())?;
|
purge_item(&vault, &mut manifest, &id, &title)?;
|
||||||
eprintln!(" purged {title}");
|
purged_titles.push(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vault.save_manifest(&manifest)?;
|
||||||
|
let status = crate::helpers::git_command(vault.root(), &["add", "manifest.enc"]).status()?;
|
||||||
|
if !status.success() { anyhow::bail!("git add manifest.enc failed"); }
|
||||||
|
let status = crate::helpers::git_command(vault.root(),
|
||||||
|
&["commit", "-m", &format!("trash empty: purged {} item(s)", purged_titles.len())]).status()?;
|
||||||
|
if !status.success() { anyhow::bail!("git commit failed"); }
|
||||||
|
|
||||||
|
eprintln!("Emptied trash: {} item(s)", purged_titles.len());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn cmd_attach(_q: String, _file: PathBuf) -> Result<()> { bail!("not yet implemented"); }
|
fn cmd_attach(_q: String, _file: PathBuf) -> Result<()> { bail!("not yet implemented"); }
|
||||||
|
|||||||
Reference in New Issue
Block a user