1use crate::{
2 Error, ObjectId, Repository, Result,
3 io::{SliceWriter, Write},
4 pack,
5};
6
7pub mod selected;
8
9#[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
34pub fn write(
39 repository: &impl Repository,
40 cache: &mut impl PackCache,
41 scratch: &mut [u8],
42 output: &mut impl Write,
43) -> Result<()> {
44 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}