Use cached canonical `rad/id` refs

We were recomputing the `rad/id` ref every time it was accessed.
This commit is contained in:
Alexis Sellier 2023-03-30 11:52:15 +02:00
parent 87f47cdc67
commit b20f81eb0c
No known key found for this signature in database
3 changed files with 54 additions and 64 deletions

View File

@ -230,9 +230,12 @@ impl Proposal {
self.description().unwrap_or_default()
);
let current = doc.update(remote, &msg, &signatures.collect::<Vec<_>>(), repo.raw())?;
let head = repo.set_identity_head()?;
assert_eq!(head, current);
Ok(Identity {
head: current,
head,
root: previous.root,
current,
revision: previous.revision + 1,

View File

@ -165,7 +165,6 @@ pub fn fork<G: Signer, S: storage::WriteStorage>(
) -> Result<(), ForkError> {
let me = signer.public_key();
let repository = storage.repository_mut(rid)?;
// TODO: We should get the id branch pointer from a stored canonical reference.
let (canonical_id, _) = repository.identity_doc()?;
let (canonical_branch, canonical_head) = repository.head()?;
let raw = repository.raw();

View File

@ -310,64 +310,6 @@ impl Repository {
Ok(verified)
}
/// Return the canonical identity [`git::Oid`] and document.
pub fn identity_doc(&self) -> Result<(Oid, identity::Doc<Unverified>), IdentityError> {
let head = self.identity_head()?;
Doc::<Unverified>::load_at(head, self)
.map(|(doc, _)| (head, doc))
.map_err(IdentityError::from)
}
/// Return the canonical identity branch head.
pub fn identity_head(&self) -> Result<Oid, IdentityError> {
let mut heads = Vec::new();
for remote in self.remote_ids()? {
let remote = remote?;
let oid = Doc::<Unverified>::head(&remote, self)?;
heads.push(oid.into());
}
// Keep track of the longest identity branch.
let mut longest = heads.pop().ok_or(IdentityError::MissingBranch)?;
for head in &heads {
let base = self.raw().merge_base(*head, longest)?;
if base == longest {
// `head` is a successor of `longest`. Update `longest`.
//
// o head
// |
// o longest (base)
// |
//
longest = *head;
} else if base == *head || *head == longest {
// `head` is an ancestor of `longest`, or equal to it. Do nothing.
//
// o longest o longest, head (base)
// | |
// o head (base) OR o
// | |
//
} else {
// The merge base between `head` and `longest` (`base`)
// is neither `head` nor `longest`. Therefore, the branches have
// diverged.
//
// longest head
// \ /
// o (base)
// |
//
return Err(IdentityError::BranchesDiverge);
}
}
Ok(longest.into())
}
pub fn remote_ids(
&self,
) -> Result<impl Iterator<Item = Result<RemoteId, refs::Error>> + '_, git2::Error> {
@ -554,7 +496,11 @@ impl ReadRepository for Repository {
}
fn identity_doc(&self) -> Result<(Oid, identity::Doc<Unverified>), IdentityError> {
Repository::identity_doc(self)
let head = self.identity_head()?;
Doc::<Unverified>::load_at(head, self)
.map(|(doc, _)| (head, doc))
.map_err(IdentityError::from)
}
fn head(&self) -> Result<(Qualified, Oid), IdentityError> {
@ -568,8 +514,6 @@ impl ReadRepository for Repository {
}
fn canonical_head(&self) -> Result<(Qualified, Oid), IdentityError> {
// TODO: In the `fork` function for example, we call Repository::project_identity again,
// This should only be necessary once.
let (_, doc) = self.identity_doc()?;
let doc = doc.verified()?;
let project = doc.project()?;
@ -601,7 +545,51 @@ impl ReadRepository for Repository {
}
fn canonical_identity_head(&self) -> Result<Oid, IdentityError> {
Repository::identity_head(self)
let mut heads = Vec::new();
for remote in self.remote_ids()? {
let remote = remote?;
let oid = Doc::<Unverified>::head(&remote, self)?;
heads.push(oid.into());
}
// Keep track of the longest identity branch.
let mut longest = heads.pop().ok_or(IdentityError::MissingBranch)?;
for head in &heads {
let base = self.raw().merge_base(*head, longest)?;
if base == longest {
// `head` is a successor of `longest`. Update `longest`.
//
// o head
// |
// o longest (base)
// |
//
longest = *head;
} else if base == *head || *head == longest {
// `head` is an ancestor of `longest`, or equal to it. Do nothing.
//
// o longest o longest, head (base)
// | |
// o head (base) OR o
// | |
//
} else {
// The merge base between `head` and `longest` (`base`)
// is neither `head` nor `longest`. Therefore, the branches have
// diverged.
//
// longest head
// \ /
// o (base)
// |
//
return Err(IdentityError::BranchesDiverge);
}
}
Ok(longest.into())
}
}