mod apply;
pub mod backend;
mod error;
mod files;
mod linked_worktree;
mod memory;
mod open;
pub mod paths;
mod reftable;
mod routing;
mod semantics;
mod transaction;
mod types;
mod validation;
pub use error::{BackendError, RefStoreError};
pub use files::{FilesRefStore, FilesRefStoreConfig};
pub(crate) use linked_worktree::LinkedWorktreeRefStore;
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<()>;
fn as_files(&self) -> Option<&FilesRefStore> {
None
}
}
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| match err {
crate::error::Error::RefStore(err) => err,
other => RefStoreError::Corrupt(other.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),
}
}