update-ref: add support for 'symref-delete' command
Add a new command 'symref-delete' to allow deletions of symbolic refs in
a transaction via the '--stdin' mode of the 'git-update-ref' command.
The 'symref-delete' command can, when given an <old-target>, delete the
provided <ref> only when it points to <old-target>.
This command is only compatible with the 'no-deref' mode because we
optionally want to check the 'old_target' of the ref being deleted.
De-referencing a symbolic ref would provide a regular ref and we already
have the 'delete' command for regular refs.
While users can also use 'git symbolic-ref -d' to delete symbolic refs,
the 'symref-delete' command in 'git-update-ref' allows users to do so
within a transaction, which promises atomicity of the operation and can
be batched with other commands.
When no 'old_target' is provided it can also delete regular refs,
similar to how the 'delete' command can delete symrefs when no 'old_oid'
is provided.
Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Karthik Nayak committedJun 7, 2024 at 15:33 UTC2343720967aac3725148e1a6690dbe6c98fe5f2e
8 files changed+140-10
Documentation/git-update-ref.txt
+5
index 9fe78b3501..16e02f6979 100644--- a/Documentation/git-update-ref.txt+++ b/Documentation/git-update-ref.txt@@ -65,6 +65,7 @@ performs all modifications together. Specify commands of the form: create SP <ref> SP <new-oid> LF delete SP <ref> [SP <old-oid>] LF verify SP <ref> [SP <old-oid>] LF+ symref-delete SP <ref> [SP <old-target>] LF symref-verify SP <ref> [SP <old-target>] LF option SP <opt> LF start LF@@ -87,6 +88,7 @@ quoting: create SP <ref> NUL <new-oid> NUL delete SP <ref> NUL [<old-oid>] NUL verify SP <ref> NUL [<old-oid>] NUL+ symref-delete SP <ref> [NUL <old-target>] NUL symref-verify SP <ref> [NUL <old-target>] NUL option SP <opt> NUL start NUL@@ -119,6 +121,9 @@ verify:: Verify <ref> against <old-oid> but do not change it. If <old-oid> is zero or missing, the ref must not exist.+symref-delete::+ Delete <ref> after verifying it exists with <old-target>, if given.+ symref-verify:: Verify symbolic <ref> against <old-target> but do not change it. If <old-target> is missing, the ref must not exist. Can only be
builtin/fetch.c
+2-2
index 66840b7c5b..ef286a4a4c 100644--- a/builtin/fetch.c+++ b/builtin/fetch.c@@ -1382,8 +1382,8 @@ static int prune_refs(struct display_state *display_state, if (!dry_run) { if (transaction) { for (ref = stale_refs; ref; ref = ref->next) {- result = ref_transaction_delete(transaction, ref->name, NULL, 0,- "fetch: prune", &err);+ result = ref_transaction_delete(transaction, ref->name, NULL,+ NULL, 0, "fetch: prune", &err); if (result) goto cleanup; }
builtin/receive-pack.c
+2-1
index b150ef39a8..64f82612c7 100644--- a/builtin/receive-pack.c+++ b/builtin/receive-pack.c@@ -1576,7 +1576,8 @@ static const char *update(struct command *cmd, struct shallow_info *si) if (ref_transaction_delete(transaction, namespaced_name, old_oid,- 0, "push", &err)) {+ NULL, 0,+ "push", &err)) { rp_error("%s", err.buf); ret = "failed to delete"; } else {