haematite_cli/serve/storage/
branches.rs1use haematite::branch::ForkWrite;
4use serde::{Deserialize, Serialize};
5
6use super::{Captured, Failure, Storage, identifier, reads};
7use crate::serve::protocol::Version;
8
9const PROVENANCE_KEY: &[u8] = b"b\0fork";
10
11#[derive(Debug, Serialize, Deserialize)]
12#[serde(deny_unknown_fields)]
13pub struct ForkProvenance {
14 pub branch: String,
15 pub version: Version,
16}
17
18pub(super) fn provenance_write(
19 writer: &haematite::db::branches::BranchDatabase,
20 branch: &str,
21 at: Version,
22) -> Result<ForkWrite, Failure> {
23 Ok(ForkWrite {
24 shard_id: writer.shard_for(PROVENANCE_KEY),
25 key: PROVENANCE_KEY.to_vec(),
26 value: Some(
27 serde_json::to_vec(&ForkProvenance {
28 branch: branch.to_owned(),
29 version: at,
30 })
31 .map_err(Failure::storage)?,
32 ),
33 })
34}
35
36pub(super) fn read_provenance(
37 reader: &haematite::db::ReadOnlyDatabase,
38 at: &Captured,
39) -> Result<ForkProvenance, Failure> {
40 provenance(reader, at)?.ok_or_else(|| {
41 Failure::new(
42 "fork_provenance_missing",
43 "branch has no recorded fork origin",
44 )
45 })
46}
47
48pub(super) fn provenance(
51 reader: &haematite::db::ReadOnlyDatabase,
52 at: &Captured,
53) -> Result<Option<ForkProvenance>, Failure> {
54 let Some(bytes) = reads::get_bytes(reader, at, PROVENANCE_KEY)? else {
55 return Ok(None);
56 };
57 let provenance: ForkProvenance = serde_json::from_slice(&bytes).map_err(Failure::storage)?;
58 identifier(&provenance.branch)?;
59 Ok(Some(provenance))
60}
61
62impl Storage {
63 pub fn fork_provenance(&self, at: &Captured) -> Result<ForkProvenance, Failure> {
68 read_provenance(&self.reader, at)
69 }
70}