Re-use `HEAD` reference if it exists
Since the `HEAD` reference is trusted (we set it locally), use that when possible, instead of re-computing it. Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
parent
2ec320acec
commit
1906124497
|
|
@ -31,8 +31,12 @@ pub const PROTOCOL_PORT: u16 = 9418;
|
|||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum RefError {
|
||||
#[error("invalid ref name '{0}'")]
|
||||
InvalidName(format::RefString),
|
||||
#[error("ref name is not valid UTF-8")]
|
||||
InvalidName,
|
||||
#[error("unexpected symbolic ref: {0}")]
|
||||
Symbolic(RefString),
|
||||
#[error("unexpected unqualified ref: {0}")]
|
||||
Unqualified(RefString),
|
||||
#[error("invalid ref format: {0}")]
|
||||
Format(#[from] format::Error),
|
||||
#[error("expected ref to begin with 'refs/namespaces' but found '{0}'")]
|
||||
|
|
@ -67,8 +71,20 @@ pub mod refs {
|
|||
/// Where project information is kept.
|
||||
pub static IDENTITY_BRANCH: Lazy<RefString> = Lazy::new(|| refname!("radicle/id"));
|
||||
|
||||
pub mod storage {
|
||||
/// Try to get a qualified reference from a generic reference.
|
||||
pub fn qualified_from<'a>(r: &'a git2::Reference) -> Result<(Qualified<'a>, Oid), RefError> {
|
||||
let name = r.name().ok_or(RefError::InvalidName)?;
|
||||
let refstr = RefStr::try_from_str(name)?;
|
||||
let target = r
|
||||
.target()
|
||||
.ok_or_else(|| RefError::Symbolic(refstr.to_owned()))?;
|
||||
let qualified = Qualified::from_refstr(refstr)
|
||||
.ok_or_else(|| RefError::Unqualified(refstr.to_owned()))?;
|
||||
|
||||
Ok((qualified, target.into()))
|
||||
}
|
||||
|
||||
pub mod storage {
|
||||
use super::*;
|
||||
|
||||
/// Create the [`Namespaced`] `branch` under the `remote` namespace, i.e.
|
||||
|
|
@ -157,7 +173,7 @@ where
|
|||
match input.to_namespaced() {
|
||||
None => {
|
||||
let refname = Qualified::from_refstr(input)
|
||||
.ok_or_else(|| RefError::InvalidName(input.to_owned()))?;
|
||||
.ok_or_else(|| RefError::Unqualified(input.to_owned()))?;
|
||||
|
||||
Ok((None, refname))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,15 +154,13 @@ pub fn fork<G: Signer, S: storage::WriteStorage>(
|
|||
) -> Result<(), ForkError> {
|
||||
let me = signer.public_key();
|
||||
let repository = storage.repository(proj)?;
|
||||
let (canonical_id, project) = repository.project_identity()?;
|
||||
let (canonical_head, _) = repository.head()?;
|
||||
// TODO: We should get the id branch pointer from a stored canonical reference.
|
||||
let (canonical_id, _) = repository.project_identity()?;
|
||||
let (canonical_branch, canonical_head) = repository.head()?;
|
||||
let raw = repository.raw();
|
||||
|
||||
// TODO: We should only get the project HEAD once we've stored the canonical identity
|
||||
// branch on disk. This way it can use what we stored, instead of recomputing it.
|
||||
|
||||
raw.reference(
|
||||
&git::refs::storage::branch(me, &project.default_branch),
|
||||
&canonical_branch.with_namespace(me.into()),
|
||||
*canonical_head,
|
||||
false,
|
||||
&format!("creating default branch for {me}"),
|
||||
|
|
@ -353,7 +351,7 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let project_repo = storage.repository(proj).unwrap();
|
||||
let (head, _) = project_repo.head().unwrap();
|
||||
let (_, head) = project_repo.head().unwrap();
|
||||
|
||||
// Test canonical refs.
|
||||
assert_eq!(project_repo.raw().refname_to_id("HEAD").unwrap(), *head);
|
||||
|
|
|
|||
|
|
@ -242,10 +242,20 @@ pub trait ReadRepository {
|
|||
|
||||
fn blob_at<'a>(&'a self, oid: Oid, path: &'a Path) -> Result<git2::Blob<'a>, git_ext::Error>;
|
||||
|
||||
/// Get the canonical head of this repository.
|
||||
/// Get the head of this repository.
|
||||
///
|
||||
/// Returns the value of `HEAD` if it is set, otherwise computes the canonical head
|
||||
/// using [`ReadRepository::canonical_head`].
|
||||
///
|
||||
/// Returns the [`Oid`] as well as the qualified reference name.
|
||||
fn head(&self) -> Result<(Oid, Qualified), ProjectError>;
|
||||
fn head(&self) -> Result<(Qualified, Oid), ProjectError>;
|
||||
|
||||
/// Compute the canonical head of this repository.
|
||||
///
|
||||
/// Ignores any existing `HEAD` reference.
|
||||
///
|
||||
/// Returns the [`Oid`] as well as the qualified reference name.
|
||||
fn canonical_head(&self) -> Result<(Qualified, Oid), ProjectError>;
|
||||
|
||||
/// Get the `reference` for the given `remote`.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -487,10 +487,18 @@ impl ReadRepository for Repository {
|
|||
Repository::project(self)
|
||||
}
|
||||
|
||||
fn head(&self) -> Result<(Oid, Qualified), ProjectError> {
|
||||
// TODO: We shouldn't need to re-construct the history here; we should use the cached
|
||||
// document head of the "trusted" (local) user for this project.
|
||||
// In the `fork` function for example, we call Repository::project_identity again,
|
||||
fn head(&self) -> Result<(Qualified, Oid), ProjectError> {
|
||||
// If `HEAD` is already set locally, just return that.
|
||||
if let Ok(head) = self.backend.head() {
|
||||
if let Ok((name, oid)) = git::refs::qualified_from(&head) {
|
||||
return Ok((name.to_owned(), oid));
|
||||
}
|
||||
}
|
||||
self.canonical_head()
|
||||
}
|
||||
|
||||
fn canonical_head(&self) -> Result<(Qualified, Oid), ProjectError> {
|
||||
// TODO: In the `fork` function for example, we call Repository::project_identity again,
|
||||
// This should only be necessary once.
|
||||
let (_, project) = self.project_identity()?;
|
||||
let branch_ref = Qualified::from(lit::refs_heads(&project.default_branch));
|
||||
|
|
@ -509,7 +517,7 @@ impl ReadRepository for Repository {
|
|||
heads => raw.merge_base_many(heads),
|
||||
}?;
|
||||
|
||||
Ok((oid.into(), branch_ref))
|
||||
Ok((branch_ref, oid.into()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -631,7 +639,7 @@ impl WriteRepository for Repository {
|
|||
|
||||
fn set_head(&self) -> Result<Oid, ProjectError> {
|
||||
let head_ref = refname!("HEAD");
|
||||
let (head, branch_ref) = self.head()?;
|
||||
let (branch_ref, head) = self.canonical_head()?;
|
||||
|
||||
log::debug!("Setting ref {:?} -> {:?}", &branch_ref, head);
|
||||
self.raw()
|
||||
|
|
|
|||
|
|
@ -78,7 +78,11 @@ impl ReadRepository for MockRepository {
|
|||
Ok(true)
|
||||
}
|
||||
|
||||
fn head(&self) -> Result<(Oid, fmt::Qualified), ProjectError> {
|
||||
fn head(&self) -> Result<(fmt::Qualified, Oid), ProjectError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn canonical_head(&self) -> Result<(fmt::Qualified, Oid), ProjectError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue