Skip to main content

git_policy_cli/
landed_disposal.rs

1//! What:
2//!  Disposal of a landed transaction: its shadow repository, then its transaction directory,
3//!  then the landed-capture records no published transaction still needs.
4//! Why:
5//!  The incumbent's `commit-transaction-workspace.ts` runs these steps in this order.
6//!  A shadow never outlives the directory that names it, and pruning runs last, so the last
7//!  transaction to finish sees no other transaction pinning a landed record.
8//!  A failed removal stops the sequence, so recovery still finds the directory and its records.
9//!
10//! In TS you'd write (pseudocode):
11//! ```ts
12//! await removeShadowRepository(shadowPath);
13//! await removeTransactionDirectory(directory);
14//! await pruneLandedCaptures({ gitDir, registryRoot });
15//! ```
16
17use super::capture_records::prune_landed_captures;
18use super::recovery_error::RecoveryError;
19use super::shadow_git::remove_shadow_repository;
20use super::transaction_registry::remove_transaction_directory;
21use std::path::Path;
22
23/// What:
24///  The paths of one landed transaction that disposal removes or reads.
25/// Why:
26///   Named fields keep the four paths apart at the call site, and the struct is `Copy` so one value serves every step.
27///
28/// In TS you'd write (pseudocode):
29/// ```ts
30/// type LandedTransactionPaths = { shadowPath: string; directory: string; gitDir: string; registryRoot: string };
31/// ```
32#[derive(Clone, Copy, Debug)]
33pub struct LandedTransactionPaths<'a> {
34    /// Shadow repository derived from the transaction ID.
35    pub shadow: &'a Path,
36    /// Durable transaction directory under the registry.
37    pub directory: &'a Path,
38    /// Real Git directory holding the capture store.
39    pub git_dir: &'a Path,
40    /// Transaction registry root whose published entries pin landed records.
41    pub registry_root: &'a Path,
42}
43
44/// What:
45///  Remove the shadow repository and the transaction directory, then prune landed-capture records.
46/// Why:
47///   Each removal is idempotent, so a recovery that finds the work half done can run it again.
48///  The returned count is the number of landed-capture records pruning removed.
49///
50/// In TS you'd write (pseudocode):
51/// ```ts
52/// await removeShadowRepository(shadowPath); await removeTransactionDirectory(directory); return pruneLandedCaptures({ gitDir, registryRoot });
53/// ```
54pub fn dispose_landed_transaction(paths: LandedTransactionPaths) -> Result<usize, RecoveryError> {
55    remove_shadow_repository(paths.shadow)?;
56    remove_transaction_directory(paths.directory)?;
57    return Ok(prune_landed_captures(paths.git_dir, paths.registry_root));
58}
59
60/// Disposal controls stay out of the release executable.
61#[cfg(test)]
62#[path = "landed_disposal_tests.rs"]
63mod tests;