feat(cli/org): org document edit via --file + purge removes attachments

This commit is contained in:
adlee-was-taken
2026-06-20 21:23:46 -04:00
parent bd323d8b1b
commit 8ec616be5d
3 changed files with 49 additions and 13 deletions

View File

@@ -1001,7 +1001,7 @@ fn resolve_org_query<'a>(
}
}
pub fn run_edit(dir: &Path, query: &str, totp_qr: Option<std::path::PathBuf>) -> Result<()> {
pub fn run_edit(dir: &Path, query: &str, totp_qr: Option<std::path::PathBuf>, file: Option<std::path::PathBuf>) -> Result<()> {
use relicario_core::time::now_unix;
use relicario_core::ItemCore;
@@ -1025,15 +1025,47 @@ pub fn run_edit(dir: &Path, query: &str, totp_qr: Option<std::path::PathBuf>) ->
}
let history = &mut item.field_history;
let mut doc_attachment_rel: Option<String> = None;
let mut new_doc_attachments: Option<Vec<relicario_core::AttachmentRef>> = None;
match &mut item.core {
ItemCore::Login(l) => ib::edit_login(l, history, totp_qr)?,
ItemCore::SecureNote(n) => ib::edit_secure_note(n, history)?,
ItemCore::Identity(i) => ib::edit_identity(i)?,
ItemCore::Card(c) => ib::edit_card(c, history)?,
ItemCore::Key(k) => ib::edit_key(k, history)?,
ItemCore::Document(_) => ib::edit_document_message(),
ItemCore::Document(d) => {
if let Some(path) = &file {
let bytes = std::fs::read(path)
.with_context(|| format!("read {}", path.display()))?;
let enc = relicario_core::encrypt_attachment(
&bytes, vault.key(), crate::org_session::DEFAULT_ORG_ATTACHMENT_MAX_BYTES)?;
vault.remove_item_attachments(&collection, &id)?;
let rel = vault.save_attachment(&collection, &id, &enc)?;
let filename = path
.file_name()
.ok_or_else(|| anyhow::anyhow!("file path has no filename: {}", path.display()))?
.to_string_lossy()
.into_owned();
d.mime_type = crate::parse::guess_mime(&filename);
d.primary_attachment = enc.id.clone();
d.filename = filename.clone();
new_doc_attachments = Some(vec![relicario_core::AttachmentRef {
id: enc.id,
filename,
mime_type: d.mime_type.clone(),
size: bytes.len() as u64,
created: now_unix(),
}]);
doc_attachment_rel = Some(rel);
} else {
ib::edit_document_message();
}
}
ItemCore::Totp(t) => ib::edit_totp(t, history)?,
}
if let Some(atts) = new_doc_attachments {
item.attachments = atts;
}
item.modified = now_unix();
let item_rel = vault.save_item(&collection, &item)?;
@@ -1053,7 +1085,13 @@ pub fn run_edit(dir: &Path, query: &str, totp_qr: Option<std::path::PathBuf>) ->
collection,
item.id.as_str()
);
crate::org_session::org_git_run(&vault.root, &["add", &item_rel, "manifest.enc"], "org edit: git add")?;
let mut add_args: Vec<&str> = vec!["add", &item_rel, "manifest.enc"];
let att_dir_rel;
if doc_attachment_rel.is_some() {
att_dir_rel = format!("attachments/{}/{}", collection, id.as_str());
add_args.push(&att_dir_rel);
}
crate::org_session::org_git_run(&vault.root, &add_args, "org edit: git add")?;
crate::org_session::org_git_run(&vault.root, &["commit", "-m", &commit_msg], "org edit: git commit")?;
println!("Updated {} ({}) in `{}`", item.title, item.id.as_str(), collection);
Ok(())
@@ -1129,12 +1167,14 @@ pub fn run_purge(dir: &Path, query: &str) -> Result<()> {
// Remove the blob from disk, drop the manifest entry, stage with git rm.
vault.remove_item(&collection, &id)?;
vault.remove_item_attachments(&collection, &id)?;
let mut manifest = vault.load_manifest()?;
manifest.entries.retain(|e| e.id != id);
vault.save_manifest(&manifest)?;
let item_rel = format!("items/{}/{}.enc", collection, id.as_str());
crate::helpers::git_rm(&vault.root, &[item_rel], "org purge: git rm")?;
let att_dir_rel = format!("attachments/{}/{}", collection, id.as_str());
crate::helpers::git_rm(&vault.root, &[item_rel, att_dir_rel], "org purge: git rm")?;
crate::org_session::org_git_run(&vault.root, &["add", "manifest.enc"], "org purge: git add manifest")?;
let commit_msg = format!(