]> git.ipfire.org Git - thirdparty/git.git/commit - builtin/update-ref.c
update-ref: implement interactive transaction handling
authorPatrick Steinhardt <ps@pks.im>
Thu, 2 Apr 2020 07:10:02 +0000 (09:10 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 2 Apr 2020 18:09:49 +0000 (11:09 -0700)
commite48cf33b61b8fecf1558fb32fcf5ee2987e82890
tree39e57596523fdf5bc71b71e6f047a4e0f9f9f642
parent94fd491a54b955990146f63e7283e9813dc85fef
update-ref: implement interactive transaction handling

The git-update-ref(1) command can only handle queueing transactions
right now via its "--stdin" parameter, but there is no way for users to
handle the transaction itself in a more explicit way. E.g. in a
replicated scenario, one may imagine a coordinator that spawns
git-update-ref(1) for multiple repositories and only if all agree that
an update is possible will the coordinator send a commit. Such a
transactional session could look like

    > start
    < start: ok
    > update refs/heads/master $OLD $NEW
    > prepare
    < prepare: ok
    # All nodes have returned "ok"
    > commit
    < commit: ok

or

    > start
    < start: ok
    > create refs/heads/master $OLD $NEW
    > prepare
    < fatal: cannot lock ref 'refs/heads/master': reference already exists
    # On all other nodes:
    > abort
    < abort: ok

In order to allow for such transactional sessions, this commit
introduces four new commands for git-update-ref(1), which matches those
we have internally already with the exception of "start":

    - start: start a new transaction

    - prepare: prepare the transaction, that is try to lock all
               references and verify their current value matches the
               expected one

    - commit: explicitly commit a session, that is update references to
              match their new expected state

    - abort: abort a session and roll back all changes

By design, git-update-ref(1) will commit as soon as standard input is
being closed. While fine in a non-transactional world, it is definitely
unexpected in a transactional world. Because of this, as soon as any of
the new transactional commands is used, the default will change to
aborting without an explicit "commit". To avoid a race between queueing
updates and the first "prepare" that starts a transaction, the "start"
command has been added to start an explicit transaction.

Add some tests to exercise this new functionality.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-update-ref.txt
builtin/update-ref.c
t/t1400-update-ref.sh