From 7e32f91ea29a79ea8571809dd494459640a0b052 Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Sun, 17 Sep 2023 21:50:59 +0200 Subject: [PATCH] Don't allow the default branch to be deleted As a delegate, you shouldn't be able to delete your default branch. This would most likely happen by mistake, and it prevents the canonical head from being calculated correctly. --- radicle-cli/examples/git/git-push.md | 8 ++++++++ radicle-remote-helper/src/push.rs | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/radicle-cli/examples/git/git-push.md b/radicle-cli/examples/git/git-push.md index fd8572e02..c7762dcb9 100644 --- a/radicle-cli/examples/git/git-push.md +++ b/radicle-cli/examples/git/git-push.md @@ -61,3 +61,11 @@ f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master $ rad sync --announce ✓ Synced with 1 node(s) ``` + +Note that it is forbidden to delete the default/canonical branch: + +``` (fail) (stderr) +$ git push rad :master +error: refusing to delete default branch ref 'refs/heads/master' +error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi' +``` diff --git a/radicle-remote-helper/src/push.rs b/radicle-remote-helper/src/push.rs index d9c91b535..0b002139e 100644 --- a/radicle-remote-helper/src/push.rs +++ b/radicle-remote-helper/src/push.rs @@ -37,6 +37,9 @@ pub enum Error { /// Head being pushed diverges from canonical head. #[error("refusing to update branch to commit that is not a descendant of canonical head")] HeadsDiverge(git::Oid, git::Oid), + /// User tried to delete the canonical branch. + #[error("refusing to delete default branch ref '{0}'")] + DeleteForbidden(git::RefString), /// Identity document error. #[error("doc: {0}")] Doc(#[from] radicle::identity::doc::DocError), @@ -184,6 +187,11 @@ pub fn run( Command::Delete(dst) => { // Delete refs. let refname = nid.to_namespace().join(dst); + let (canonical_ref, _) = &canonical; + + if *dst == canonical_ref.to_ref_string() && delegates.contains(&Did::from(nid)) { + return Err(Error::DeleteForbidden(dst.clone())); + } stored .raw() .find_reference(&refname)