[PATCH 21/31] refs.c allow multiple updates of the same ref in a transaction

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allow multiple updates of a ref in the same transaction as long as
each update has have_old and old_sha1 matches the new_sha1 of the
previous update.

Add a test that verifies that a valid sequence such as
  create ref a
  update ref b a
  update ref c b
works and a test that an invalid sequence such as this still fails:
  update ref a c
  update ref b b
  update ref c c

Signed-off-by: Ronnie Sahlberg <sahlberg@xxxxxxxxxx>
---
 refs.c                | 23 +++++++++++++++++------
 t/t1400-update-ref.sh | 23 +++++++++++++++++++++--
 2 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/refs.c b/refs.c
index 76cab6e..87cdd91 100644
--- a/refs.c
+++ b/refs.c
@@ -3455,12 +3455,6 @@ int transaction_update_sha1(struct ref_transaction *transaction,
 	if (update->lock)
 		return 0;
 
-	/* If we could not lock the ref it means we either collided with a
-	   different command or that we tried to perform a second update to
-	   the same ref from within the same transaction.
-	*/
-	transaction->status = REF_TRANSACTION_ERROR;
-
 	/* -1 is the update we just added. Start at -2 and find the most recent
 	   previous update for this ref.
 	*/
@@ -3472,6 +3466,23 @@ int transaction_update_sha1(struct ref_transaction *transaction,
 			    update->refname))
 			break;
 	}
+	/* If the current update has_old==1 and old_sha1 matches the new_sha1
+	 * of the previous update then merge the two updates into one.
+	 */
+	if (i >= 0 && update->have_old && !hashcmp(update->old_sha1,
+			   transaction->updates[i]->new_sha1)) {
+		hashcpy(transaction->updates[i]->new_sha1, update->new_sha1);
+		transaction->nr--;
+		free((char *)transaction->updates[transaction->nr]->msg);
+		free(transaction->updates[transaction->nr]);
+		return 0;
+	}
+	/* If we could not lock the ref it means we either collided with a
+	   different command or that we tried to perform a second update to
+	   the same ref from within the same transaction.
+	*/
+	transaction->status = REF_TRANSACTION_ERROR;
+
 	if (err)
 		if (i >= 0) {
 			const char *str =
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index f9b7bef..078cd4b 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -446,7 +446,7 @@ test_expect_success 'stdin fails option with unknown name' '
 	grep "fatal: option unknown: unknown" err
 '
 
-test_expect_success 'stdin fails with duplicate refs' '
+test_expect_success 'stdin fails with duplicate create refs' '
 	cat >stdin <<-EOF &&
 	create $a $m
 	create $b $m
@@ -464,6 +464,25 @@ test_expect_success 'stdin create ref works' '
 	test_cmp expect actual
 '
 
+test_expect_success 'stdin succeeds with correctly chained update refs' '
+	cat >stdin <<-EOF &&
+	update $a $A $m
+	update $a $B $A
+	update $a $C $B
+	EOF
+	git update-ref --stdin <stdin
+'
+
+test_expect_success 'stdin fails with incorrectly chained update refs' '
+	cat >stdin <<-EOF &&
+	update $a $A $C
+	update $a $B $B
+	update $a $B $B
+	EOF
+	test_must_fail git update-ref --stdin <stdin &&
+	grep "fatal: Multiple updates for ref '"'"'$a'"'"' not allowed." err
+'
+
 test_expect_success 'stdin succeeds with quoted argument' '
 	git update-ref -d $a &&
 	echo "create $a \"$m\"" >stdin &&
@@ -786,7 +805,7 @@ test_expect_success 'stdin -z fails option with unknown name' '
 	grep "fatal: option unknown: unknown" err
 '
 
-test_expect_success 'stdin -z fails with duplicate refs' '
+test_expect_success 'stdin -z fails with duplicate create refs' '
 	printf $F "create $a" "$m" "create $b" "$m" "create $a" "$m" >stdin &&
 	test_must_fail git update-ref -z --stdin <stdin 2>err &&
 	grep "fatal: Multiple updates for ref '"'"'$a'"'"' not allowed." err
-- 
2.0.0.rc3.506.g3739a35

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]