Subject: [PATCH v2 0/7] update-ref: add symref oriented commands

From: Karthik Nayak <[email-masked]>
Date: Fri, 12 Apr 2024 11:59:01 +0200

From: Karthik Nayak <[email-masked]>

The 'git-update-ref(1)' command allows transactional reference updates.
But currently only supports regular reference updates. Meaning, if one
wants to update HEAD (symbolic ref) in a transaction, there is no tool
to do so.

One option to obtain transactional updates for the HEAD ref is to
manually create the HEAD.lock file and commit. This is intrusive, where
the user needs to mimic internal git behavior. Also, this only works
when using the files backend.

At GitLab, we've been using the manual process till date, to allow users
to set and change their default branch. But with the introduction of
reftables as a reference backend, this becomes a necessity to be solved
within git.

This patch series goes about introducing a set of commands
symref-{create,verify,delete,update} to work with symrefs complimenting
the existing commands for the regular refs within 'git-update-ref(1)'.

The 'symref-verify' command can be used to verify if a symref exists and
its existing value.

The 'symref-create' command can be used to create a new symref.

The 'symref-delete' command can be used to delete an existing symref while
optionally checking its existing value.

The 'symref-update' command can be used to update a symref, create a symref,
delete a symref or even convert an existing regular ref to a symref. Wherein
like the regular 'update' command, the zero OID can be used to create/delete
a symref.

V1 of the patch series can be found here:
https://lore.kernel.org/git/[email-masked]/

I'm not adding a range diff here, cause I redid the whole series, things which
have changed:
1. The earlier series simply propagated a 'symref_target' and only supported the
'symref-update' command, without checks for existing values and such. Now we
support the entire fleet of commands with support for checking old_values.
2. The flow is now changedc to send an old_ref, new_ref pair in supplement to
the existing old_oid, new_oid pair to the reference backends. This allows the
backends to simply do a combination of changes based on what values are set.
This allows us to do symref-update's where we change a regular ref to a symref
while also validating its old OID.
3. I added a lot more tests to cover reflog checks and also '-z' input.
4. The entered <old-ref> and <new-ref> values are checked within update-ref, to
ensure we don't create dangling refs. This could be extended in the future with
a flag, maybe "REF_ALLOW_DANGLING_SYMREF" and a corresponding option within
update-ref.
5. Removed some commits where reftable backend code was reused for symref creation.
This actually caused issues since the reused code also created a reflog along with
the symref but we should defer reflog creations only after all ref creations have
taken place. There is a bit of DRY here, but I think overall its still much cleaner.

Thanks all for the review and discussion in the previous version. Patrick, I did
incorporate the changes you suggested, but I just noticed that I didn't reply to
your emails.

Karthik Nayak (7):
  refs: accept symref values in `ref_transaction[_add]_update`
  update-ref: add support for symref-verify
  update-ref: add support for symref-delete
  files-backend: extract out `create_symref_lock`
  update-ref: add support for symref-create
  update-ref: add support for symref-update
  refs: support symrefs in 'reference-transaction' hook

 Documentation/git-update-ref.txt |  25 +++
 Documentation/githooks.txt       |  13 +-
 branch.c                         |   2 +-
 builtin/clone.c                  |   2 +-
 builtin/fast-import.c            |   5 +-
 builtin/fetch.c                  |   4 +-
 builtin/receive-pack.c           |   4 +-
 builtin/replace.c                |   2 +-
 builtin/tag.c                    |   1 +
 builtin/update-ref.c             | 202 +++++++++++++++++--
 refs.c                           |  74 +++++--
 refs.h                           |  15 +-
 refs/files-backend.c             | 143 +++++++++++---
 refs/refs-internal.h             |  21 ++
 refs/reftable-backend.c          |  51 ++++-
 sequencer.c                      |   9 +-
 t/t0600-reffiles-backend.sh      |  32 ++++
 t/t1400-update-ref.sh            | 320 ++++++++++++++++++++++++++++++-
 t/t1416-ref-transaction-hooks.sh |  41 ++++
 walker.c                         |   2 +-
 20 files changed, 886 insertions(+), 82 deletions(-)

-- 
2.43.GIT