While git-update-ref has recently grown commands which allow interactive control of transactions in e48cf33b61 (update-ref: implement interactive transaction handling, 2020-04-02), it is not yet possible to create multiple transactions in a single session. To do so, one currently still needs to invoke the executable multiple times. This commit addresses this shortcoming by allowing the "start" command to create a new transaction if the current transaction has already been either committed or aborted. Signed-off-by: Patrick Steinhardt --- Documentation/git-update-ref.txt | 3 +- builtin/update-ref.c | 13 ++++++++- t/t1400-update-ref.sh | 50 ++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt index d401234b03..48b6683071 100644 --- a/Documentation/git-update-ref.txt +++ b/Documentation/git-update-ref.txt @@ -125,7 +125,8 @@ option:: start:: Start a transaction. In contrast to a non-transactional session, a transaction will automatically abort if the session ends without an - explicit commit. + explicit commit. This command may create a new empty transaction when + the current one has been committed or aborted already. prepare:: Prepare to commit the transaction. This will create lock files for all diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 8a2df4459c..bb65129012 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -446,7 +446,18 @@ static void update_refs_stdin(void) state = cmd->state; break; case UPDATE_REFS_CLOSED: - die("transaction is closed"); + if (cmd->state != UPDATE_REFS_STARTED) + die("transaction is closed"); + + /* + * Open a new transaction if we're currently closed and + * get a "start". + */ + state = cmd->state; + transaction = ref_transaction_begin(&err); + if (!transaction) + die("%s", err.buf); + break; } diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index 957bef272d..7ed41bb328 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -1533,4 +1533,54 @@ test_expect_success 'transaction with prepare aborts by default' ' test_must_fail git show-ref --verify -q $b ' +test_expect_success 'transaction can commit multiple times' ' + cat >stdin <<-EOF && + start + create refs/heads/branch-1 $A + commit + start + create refs/heads/branch-2 $B + commit + EOF + git update-ref --stdin actual && + printf "%s: ok\n" start commit start commit >expect && + test_cmp expect actual && + echo "$A" >expect && + git rev-parse refs/heads/branch-1 >actual && + test_cmp expect actual && + echo "$B" >expect && + git rev-parse refs/heads/branch-2 >actual && + test_cmp expect actual +' + +test_expect_success 'transaction can create and delete' ' + cat >stdin <<-EOF && + start + create refs/heads/create-and-delete $A + commit + start + delete refs/heads/create-and-delete $A + commit + EOF + git update-ref --stdin actual && + printf "%s: ok\n" start commit start commit >expect && + test_must_fail git show-ref --verify refs/heads/create-and-delete +' + +test_expect_success 'transaction can commit after abort' ' + cat >stdin <<-EOF && + start + create refs/heads/abort $A + abort + start + create refs/heads/abort $A + commit + EOF + git update-ref --stdin actual && + printf "%s: ok\n" start abort start commit >expect && + echo "$A" >expect && + git rev-parse refs/heads/abort >actual && + test_cmp expect actual +' + test_done -- 2.29.2