use serde::{Deserialize, Serialize};
use crate::error::VcsError;
use crate::hash::ObjectId;
use crate::object::Object;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum HeadState {
Branch(String),
Detached(ObjectId),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ReflogEntry {
pub old_id: Option<ObjectId>,
pub new_id: ObjectId,
pub author: String,
pub timestamp: u64,
pub message: String,
}
pub trait Store {
fn has(&self, id: &ObjectId) -> bool;
fn get(&self, id: &ObjectId) -> Result<Object, VcsError>;
fn put(&mut self, object: &Object) -> Result<ObjectId, VcsError>;
fn get_ref(&self, name: &str) -> Result<Option<ObjectId>, VcsError>;
fn set_ref(&mut self, name: &str, id: ObjectId) -> Result<(), VcsError>;
fn delete_ref(&mut self, name: &str) -> Result<(), VcsError>;
fn list_refs(&self, prefix: &str) -> Result<Vec<(String, ObjectId)>, VcsError>;
fn get_head(&self) -> Result<HeadState, VcsError>;
fn set_head(&mut self, state: HeadState) -> Result<(), VcsError>;
fn list_objects(&self) -> Result<Vec<ObjectId>, VcsError>;
fn delete_object(&mut self, id: &ObjectId) -> Result<(), VcsError>;
fn append_reflog(&mut self, ref_name: &str, entry: ReflogEntry) -> Result<(), VcsError>;
fn read_reflog(
&self,
ref_name: &str,
limit: Option<usize>,
) -> Result<Vec<ReflogEntry>, VcsError>;
}
pub fn resolve_head(store: &dyn Store) -> Result<Option<ObjectId>, VcsError> {
match store.get_head()? {
HeadState::Branch(name) => {
let ref_name = format!("refs/heads/{name}");
store.get_ref(&ref_name)
}
HeadState::Detached(id) => Ok(Some(id)),
}
}