mod apply;
mod error;
mod files;
mod memory;
mod open;
pub mod paths;
mod reftable;
mod routing;
mod semantics;
mod transaction;
mod types;
mod validation;
pub use error::RefStoreError;
pub use files::{FilesRefStore, FilesRefStoreConfig};
pub use memory::MemoryRefStore;
pub use open::open_ref_store;
pub(crate) use open::{open_files_ref_store, open_ref_store_uncached};
pub use reftable::ReftableRefStore;
pub use transaction::RefTransaction;
pub use types::{
Expected, RawRef, RefCaseOnlyRename, RefEntry, RefName, RefReflogRename, RefStorageFormat,
RefUpdate, RefUpdateFlags, ReflogUpdate,
};
use std::fmt::Debug;
use std::ops::ControlFlow;
use crate::error::Result;
use crate::objects::ObjectId;
use crate::reflog::ReflogEntry;
use crate::refs::SYMREF_MAXDEPTH;
type StoreResult<T> = std::result::Result<T, RefStoreError>;
pub trait PreparedRefTransaction: Send {
fn commit(self: Box<Self>) -> StoreResult<()>;
fn abort(self: Box<Self>) -> StoreResult<()>;
}
pub trait RefStore: Send + Sync + Debug {
fn format(&self) -> RefStorageFormat;
fn read_raw(&self, name: &str) -> Result<Option<RawRef>>;
fn resolve(&self, name: &str) -> Result<ObjectId> {
resolve_store(self, name)
}
fn for_each_ref(
&self,
prefix: &str,
f: &mut dyn FnMut(&RefEntry) -> ControlFlow<()>,
) -> Result<()>;
fn prepare(
&self,
txn: RefTransaction,
) -> StoreResult<Box<dyn PreparedRefTransaction + Send + '_>>;
fn reflog_exists(&self, name: &str) -> Result<bool>;
fn for_each_reflog_entry(
&self,
name: &str,
reverse: bool,
f: &mut dyn FnMut(&ReflogEntry) -> ControlFlow<()>,
) -> Result<()>;
fn create_reflog(&self, name: &str) -> Result<()>;
fn delete_reflog(&self, name: &str) -> Result<()>;
fn replace_reflog(&self, name: &str, entries: Vec<ReflogEntry>) -> Result<()>;
fn for_each_reflog_ref(&self, f: &mut dyn FnMut(&str) -> ControlFlow<()>) -> Result<()>;
}
pub fn resolve_store<S: RefStore + ?Sized>(store: &S, name: &str) -> Result<ObjectId> {
resolve_via_raw(store, name, 0).map_err(Into::into)
}
fn resolve_via_raw<S: RefStore + ?Sized>(
store: &S,
name: &str,
depth: usize,
) -> StoreResult<ObjectId> {
if depth >= SYMREF_MAXDEPTH {
return Err(RefStoreError::SymrefLoop);
}
match store
.read_raw(name)
.map_err(|err| RefStoreError::Corrupt(err.to_string()))?
{
None => Err(RefStoreError::not_found(name)),
Some(RawRef::Direct(oid)) => Ok(oid),
Some(RawRef::Symbolic(target)) => resolve_via_raw(store, &target, depth + 1),
}
}