git-ents.gitmain
⌘K
foforge
redact.rs78 lines · 2.4 KB · rusthistorycomment on this file
1//! `git ents redact`: record that an object was redacted
2//! (`model.redaction`), refusing any future push that would refill it
3//! (`receive.redaction-ingest`).
4
5use ents_model::{Redaction, namespace};
6use ents_receive::{Identity, propose_entity};
7use gix_ref_store::RefStoreRead;
8
9use super::{actor, signer};
10use crate::error::{Error, Result};
11use crate::mutate::outcome_to_result;
12use crate::root::LocalRoot;
13
14/// `git ents redact list`: every redaction recorded in this repository.
15///
16/// # Errors
17///
18/// Propagates a ref-store or object read failure.
19pub fn list(root: &LocalRoot) -> Result<Vec<(String, Redaction)>> {
20 let mut out = Vec::new();
21 for entry in root.refs.iter_prefix("refs/meta/redactions/")? {
22 let (name, tip) = entry?;
23 let path = name.as_bstr().to_string();
24 let Some(id) = path.strip_prefix("refs/meta/redactions/") else {
25 continue;
26 };
27 let tree = super::commit_tree(&root.objects, tip)?;
28 if let Ok(redaction) = facet_git_tree::deserialize::<Redaction>(&tree, &root.objects) {
29 out.push((id.to_owned(), redaction));
30 }
31 }
32 Ok(out)
33}
34
35/// Run `git ents redact add <oid> --reason ...`.
36///
37/// The record lands at `refs/meta/redactions/<id>`; the gate's default
38/// namespace-authorization arm requires admin-registered provenance for
39/// this namespace, so a non-admin signer is refused here exactly as any
40/// other call site would refuse it (`gate.call-sites`,
41/// `receive.redaction-admin-only`).
42///
43/// # Errors
44///
45/// [`Error::InvalidArgument`] if `oid` does not parse as an object id;
46/// otherwise see [`crate::mutate::outcome_to_result`].
47pub fn add(
48 root: &LocalRoot,
49 oid: &str,
50 reason: String,
51 key: Option<std::path::PathBuf>,
52) -> Result<()> {
53 let target: gix_hash::ObjectId = oid
54 .parse()
55 .map_err(|_source| Error::InvalidArgument(format!("not an object id: {oid}")))?;
56 let redaction = Redaction::new(target, reason);
57 let id = target.to_string();
58 let ref_name = namespace::redaction_ref(&id)?;
59
60 let signer = signer(root, key)?;
61 let identity = Identity {
62 actor: actor(&signer),
63 author: None,
64 sign: &|payload| signer.sign(payload),
65 };
66 let outcome = propose_entity(
67 &root.refs,
68 &root.objects,
69 &root.events,
70 ref_name,
71 &redaction,
72 &identity,
73 &format!("Redact {id}"),
74 root.mode(),
75 )?;
76 outcome_to_result(outcome, None)?;
77 Ok(())
78}