Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
radicle/storage: Split `WriteRepository::set_head`
Lorenz Leutgeb committed 22 days ago
commit bfb2858054c3168c7eac6ed156502811c235cf4b
parent 0eba6ca
7 files changed +55 -31
modified crates/radicle-node/src/worker/fetch.rs
@@ -131,11 +131,9 @@ impl Handle {
                // points to a repository that is temporary and gets moved by [`mv`].
                let repo = storage.repository(rid)?;
                repo.set_identity_head()?;
-
                match repo.set_head() {
-
                    Ok(head) => {
-
                        if head.is_updated() {
-
                            log::trace!(target: "worker", "Set HEAD to {}", head.new);
-
                        }
+
                match repo.set_head_to_default_branch() {
+
                    Ok(()) => {
+
                        log::trace!(target: "worker", "Set HEAD successfully");
                    }
                    Err(RepositoryError::Quorum(e)) => {
                        log::warn!(target: "worker", "Fetch could not set HEAD for {rid}: {e}")
@@ -352,9 +350,6 @@ fn set_canonical_refs(
    applied: &Applied,
) -> Result<Option<UpdatedCanonicalRefs>, error::Canonical> {
    let identity = repo.identity()?;
-
    // TODO(finto): it's unfortunate that we may end up computing the default
-
    // branch again after `set_head` is called after the fetch. This is due to
-
    // the storage capabilities being leaked to this part of the code base.
    let rules = identity
        .canonical_refs_or_default(|| {
            let rule = identity.doc().default_branch_rule()?;
modified crates/radicle-remote-helper/src/push.rs
@@ -426,14 +426,8 @@ pub(super) fn run(

            // N.b. special case for handling the canonical ref, since it
            // creates a symlink to HEAD
-
            if *refname == canonical_ref
-
                && stored
-
                    .set_head()
-
                    .map(|head| head.is_updated())
-
                    .unwrap_or(false)
-
            {
-
                print_update();
-
                continue;
+
            if *refname == canonical_ref {
+
                stored.set_head_to_default_branch()?;
            }

            match stored.backend.refname_to_id(refname.as_str()) {
modified crates/radicle/src/rad.rs
@@ -143,7 +143,8 @@ where
    )?;
    stored.set_remote_identity_root_to(pk, identity)?;
    stored.set_identity_head_to(identity)?;
-
    stored.set_head()?;
+
    stored.set_head_to_default_branch()?;
+
    stored.set_default_branch_to_canonical_head()?;

    let signed = stored.sign_refs(signer)?;

modified crates/radicle/src/storage.rs
@@ -115,7 +115,7 @@ impl FromIterator<PublicKey> for Namespaces {
    }
}

-
/// Output of [`WriteRepository::set_head`].
+
/// Output of [`WriteRepository::set_default_branch_to_canonical_head`].
pub struct SetHead {
    /// Old branch head.
    pub old: Option<Oid>,
@@ -668,9 +668,16 @@ where

/// Allows read-write access to a repository.
pub trait WriteRepository: ReadRepository + SignRepository {
-
    /// Set the repository head to the canonical branch.
-
    /// This computes the head based on the delegate set.
-
    fn set_head(&self) -> Result<SetHead, RepositoryError>;
+
    /// Sets the symbolic reference `HEAD` to target the default branch.
+
    /// This only depends on the value for the default branch in the identity
+
    /// document, and does not require the canonical reference behind the
+
    /// default branch to be computed, or even exist.
+
    fn set_head_to_default_branch(&self) -> Result<(), RepositoryError>;
+

+
    /// Computes the head of the default branch based on the delegate set,
+
    /// and sets it.
+
    fn set_default_branch_to_canonical_head(&self) -> Result<SetHead, RepositoryError>;
+

    /// Set the repository 'rad/id' to the canonical commit, agreed by quorum.
    fn set_identity_head(&self) -> Result<Oid, RepositoryError> {
        let head = self.canonical_identity_head()?;
modified crates/radicle/src/storage/git.rs
@@ -943,16 +943,42 @@ impl ReadRepository for Repository {
}

impl WriteRepository for Repository {
-
    fn set_head(&self) -> Result<SetHead, RepositoryError> {
+
    fn set_head_to_default_branch(&self) -> Result<(), RepositoryError> {
        let head_ref = refname!("HEAD");
+
        let branch_ref = self.default_branch()?;
+

+
        match self.raw().find_reference(head_ref.as_str()) {
+
            Ok(mut head_ref) => {
+
                if head_ref
+
                    .symbolic_target()
+
                    .is_some_and(|t| t != branch_ref.as_str())
+
                {
+
                    head_ref.symbolic_set_target(branch_ref.as_str(), "set-head (radicle)")?;
+
                }
+
                Ok(())
+
            }
+
            Err(err) if err.is_not_found() => {
+
                self.raw().reference_symbolic(
+
                    head_ref.as_str(),
+
                    branch_ref.as_str(),
+
                    true,
+
                    "set-head (radicle)",
+
                )?;
+
                Ok(())
+
            }
+
            Err(err) => Err(err.into()),
+
        }
+
    }
+

+
    fn set_default_branch_to_canonical_head(&self) -> Result<SetHead, RepositoryError> {
+
        let (branch_ref, new) = self.canonical_head()?;
+

        let old = self
            .raw()
-
            .refname_to_id(&head_ref)
+
            .refname_to_id(&branch_ref)
            .ok()
            .map(|oid| oid.into());

-
        let (branch_ref, new) = self.canonical_head()?;
-

        if old == Some(new) {
            return Ok(SetHead { old, new });
        }
@@ -960,10 +986,6 @@ impl WriteRepository for Repository {
        self.raw()
            .reference(&branch_ref, new.into(), true, "set-local-branch (radicle)")?;

-
        log::debug!(target: "storage", "Setting ref: {head_ref} -> {branch_ref}");
-
        self.raw()
-
            .reference_symbolic(&head_ref, &branch_ref, true, "set-head (radicle)")?;
-

        Ok(SetHead { old, new })
    }

modified crates/radicle/src/test.rs
@@ -59,7 +59,8 @@ pub fn fetch<W: WriteRepository>(
    drop(opts);

    repo.set_identity_head()?;
-
    repo.set_head()?;
+
    repo.set_head_to_default_branch()?;
+
    repo.set_default_branch_to_canonical_head()?;

    let validations = repo.validate()?;
    if !validations.is_empty() {
modified crates/radicle/src/test/storage.rs
@@ -344,7 +344,11 @@ impl WriteRepository for MockRepository {
        todo!()
    }

-
    fn set_head(&self) -> Result<SetHead, RepositoryError> {
+
    fn set_head_to_default_branch(&self) -> Result<(), RepositoryError> {
+
        todo!()
+
    }
+

+
    fn set_default_branch_to_canonical_head(&self) -> Result<SetHead, RepositoryError> {
        todo!()
    }