Skip to main content

coven_foundation/files/
deletion.rs

1//! The record of a store's deletion from a device that leaves the store
2//! (E1, ยง11.6).
3//!
4//! `delete_store` journals this device's removal in the store's database,
5//! and the store's data can go only once that removal has applied. So just
6//! before it journals the removal, the deletion records itself here, in the
7//! store's directory, with what it does with unsent work. From the record
8//! on, opening the store is refused and the listing shows it as being
9//! deleted, until the deletion finishes and the directory goes with it.
10
11use std::path::Path;
12
13use serde::{Deserialize, Serialize};
14
15use super::{atomic_file, FileError};
16
17const RECORD: &str = "deleting.json";
18
19/// What `delete_store` does with writes and files not yet uploaded.
20#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
21pub enum IfUnsent {
22    /// Refuse with `StoreDeletionError::Unsent`, deleting nothing.
23    Refuse,
24    /// Delete them with the store.
25    Discard,
26}
27
28#[derive(Serialize, Deserialize)]
29#[serde(deny_unknown_fields)]
30struct DeletionRecord {
31    unsent: IfUnsent,
32}
33
34/// The recorded deletion's choice for unsent work, when one is recorded.
35pub(super) fn read(directory: &Path) -> Result<Option<IfUnsent>, FileError> {
36    Ok(atomic_file::read_json::<DeletionRecord>(&directory.join(RECORD), "read deletion record")?
37        .map(|record| record.unsent))
38}
39
40/// Record the deletion, durably, before its removal is journaled.
41pub(super) fn record(directory: &Path, unsent: IfUnsent) -> Result<(), FileError> {
42    let bytes = serde_json::to_vec(&DeletionRecord { unsent }).expect("deletion record encodes");
43    atomic_file::replace(&directory.join(RECORD), &bytes)
44}
45
46/// Remove the record of a deletion that ended before its removal was
47/// journaled: the store is as it was.
48pub(super) fn forget(directory: &Path) -> Result<(), FileError> {
49    atomic_file::remove(&directory.join(RECORD))
50}
51
52#[cfg(test)]
53#[path = "deletion_tests.rs"]
54mod tests;