update-ref: allow creation of multiple transactions
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 <ps@pks.im> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Nov 13, 2020 at 09:12 UTC
262a4d28feb26aff89705b3254cdfc015eaa3ef9
3 files changed
+64
-2
Documentation/git-update-ref.txt
+2
-1
@@ -125,7 +125,8 @@ option::
125
start::
126
Start a transaction. In contrast to a non-transactional session, a
127
transaction will automatically abort if the session ends without an
128
- explicit commit.
128
+ explicit commit. This command may create a new empty transaction when
129
+ the current one has been committed or aborted already.
130
131
prepare::
132
Prepare to commit the transaction. This will create lock files for all
builtin/update-ref.c
+12
-1
@@ -446,7 +446,18 @@ static void update_refs_stdin(void)
446
state = cmd->state;
447
break;
448
case UPDATE_REFS_CLOSED:
449
- die("transaction is closed");
449
+ if (cmd->state != UPDATE_REFS_STARTED)
450
+ die("transaction is closed");
451
+
452
+ /*
453
+ * Open a new transaction if we're currently closed and
454
+ * get a "start".
455
+ */
456
+ state = cmd->state;
457
+ transaction = ref_transaction_begin(&err);
458
+ if (!transaction)
459
+ die("%s", err.buf);
460
+
461
break;
462
}
463
t/t1400-update-ref.sh
+50
@@ -1533,4 +1533,54 @@ test_expect_success 'transaction with prepare aborts by default' '
1533
test_must_fail git show-ref --verify -q $b
1534
'
1535
1536
+test_expect_success 'transaction can commit multiple times' '
1537
+ cat >stdin <<-EOF &&
1538
+ start
1539
+ create refs/heads/branch-1 $A
1540
+ commit
1541
+ start
1542
+ create refs/heads/branch-2 $B
1543
+ commit
1544
+ EOF
1545
+ git update-ref --stdin <stdin >actual &&
1546
+ printf "%s: ok\n" start commit start commit >expect &&
1547
+ test_cmp expect actual &&
1548
+ echo "$A" >expect &&
1549
+ git rev-parse refs/heads/branch-1 >actual &&
1550
+ test_cmp expect actual &&
1551
+ echo "$B" >expect &&
1552
+ git rev-parse refs/heads/branch-2 >actual &&
1553
+ test_cmp expect actual
1554
+'
1555
+
1556
+test_expect_success 'transaction can create and delete' '
1557
+ cat >stdin <<-EOF &&
1558
+ start
1559
+ create refs/heads/create-and-delete $A
1560
+ commit
1561
+ start
1562
+ delete refs/heads/create-and-delete $A
1563
+ commit
1564
+ EOF
1565
+ git update-ref --stdin <stdin >actual &&
1566
+ printf "%s: ok\n" start commit start commit >expect &&
1567
+ test_must_fail git show-ref --verify refs/heads/create-and-delete
1568
+'
1569
+
1570
+test_expect_success 'transaction can commit after abort' '
1571
+ cat >stdin <<-EOF &&
1572
+ start
1573
+ create refs/heads/abort $A
1574
+ abort
1575
+ start
1576
+ create refs/heads/abort $A
1577
+ commit
1578
+ EOF
1579
+ git update-ref --stdin <stdin >actual &&
1580
+ printf "%s: ok\n" start abort start commit >expect &&
1581
+ echo "$A" >expect &&
1582
+ git rev-parse refs/heads/abort >actual &&
1583
+ test_cmp expect actual
1584
+'
1585
+
1586
test_done