Skip to main content

git_zero_core/
cache.rs

1use crate::{
2    Error, ObjectId, Repository, Result,
3    io::{SliceWriter, Write},
4    pack,
5};
6
7pub mod selected;
8
9/// Immutable complete packs, keyed by snapshot HEAD and encoder format.
10/// Backends own storage, eviction, concurrency and persistence. There is no
11/// allocation requirement. Async platform caches can use these keys outside Rust.
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
13pub struct Key {
14    pub head: ObjectId,
15    pub encoder_version: u32,
16}
17
18pub trait PackCache {
19    fn get(&self, key: Key) -> Result<Option<&[u8]>>;
20    fn put(&mut self, key: Key, pack: &[u8]) -> Result<()>;
21}
22
23pub struct NoCache;
24
25impl PackCache for NoCache {
26    fn get(&self, _: Key) -> Result<Option<&[u8]>> {
27        Ok(None)
28    }
29    fn put(&mut self, _: Key, _: &[u8]) -> Result<()> {
30        Ok(())
31    }
32}
33
34/// Hits stream directly. Misses generate into caller scratch before insertion.
35/// Cache failures propagate; use `pack::write` when caching is unnecessary.
36/// Independent ref roots return `Unsupported` before accessing the backend:
37/// a HEAD-only key cannot identify their union or a selected closure.
38pub fn write(
39    repository: &impl Repository,
40    cache: &mut impl PackCache,
41    scratch: &mut [u8],
42    output: &mut impl Write,
43) -> Result<()> {
44    // A multi-ref union may change while HEAD stays fixed. These legacy keys
45    // cannot identify it; reject before consulting or modifying the cache.
46    if !crate::repository::uses_only_head(repository) {
47        return Err(Error::Unsupported);
48    }
49    let key = Key {
50        head: repository.head(),
51        encoder_version: 1,
52    };
53    if let Some(bytes) = cache.get(key)? {
54        return output.write_all(bytes);
55    }
56    let mut pack_buffer = SliceWriter::new(scratch);
57    pack::write(repository, &mut pack_buffer)?;
58    let bytes = pack_buffer.finish();
59    cache.put(key, bytes)?;
60    output.write_all(bytes)
61}