update-ref: fix "verify" command with missing <oldvalue>

If "git update-ref --stdin" was given a "verify" command with no "<newvalue>" at all (not even zeros), the code was mistakenly setting have_old=0 (and leaving old_sha1 uninitialized). But this is incorrect: this command is supposed to verify that the reference doesn't exist. So in this case we really need old_sha1 to be set to null_sha1 and have_old to be set to 1. Moreover, since have_old was being set to zero, *no* check of the old value was being done, so the new value of the reference was being set unconditionally to the value in new_sha1. new_sha1, in turn, was set to null_sha1 in the expectation that that was the old value and it shouldn't be changed. But because the precondition was not being checked, the result was that the reference was being deleted unconditionally. So, if <oldvalue> is missing, set have_old unconditionally and set old_sha1 to null_sha1. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Acked-by: Brad King <brad.king@kitware.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Dec 11, 2014 at 00:47 UTC 0e729c7ed5b3c0c6be38bf8d8405b1b7f5a74a3f
2 files changed +7 -11
builtin/update-ref.c
+5 -9
@@ -282,26 +282,22 @@ static const char *parse_cmd_verify(struct ref_transaction *transaction,
282 char *refname;
283 unsigned char new_sha1[20];
284 unsigned char old_sha1[20];
285 - int have_old;
285
286 refname = parse_refname(input, &next);
287 if (!refname)
288 die("verify: missing <ref>");
289
290 if (parse_next_sha1(input, &next, old_sha1, "verify", refname,
292 - PARSE_SHA1_OLD)) {
293 - hashclr(new_sha1);
294 - have_old = 0;
295 - } else {
296 - hashcpy(new_sha1, old_sha1);
297 - have_old = 1;
298 - }
291 + PARSE_SHA1_OLD))
292 + hashclr(old_sha1);
293 +
294 + hashcpy(new_sha1, old_sha1);
295
296 if (*next != line_termination)
297 die("verify %s: extra input: %s", refname, next);
298
299 if (ref_transaction_update(transaction, refname, new_sha1, old_sha1,
304 - update_flags, have_old, msg, &err))
300 + update_flags, 1, msg, &err))
301 die("%s", err.buf);
302
303 update_flags = 0;
t/t1400-update-ref.sh
+2 -2
@@ -655,7 +655,7 @@ test_expect_success 'stdin verify fails for mistaken null value' '
655 test_cmp expect actual
656 '
657
658 -test_expect_failure 'stdin verify fails for mistaken empty value' '
658 +test_expect_success 'stdin verify fails for mistaken empty value' '
659 M=$(git rev-parse $m) &&
660 test_when_finished "git update-ref $m $M" &&
661 git rev-parse $m >expect &&
@@ -1020,7 +1020,7 @@ test_expect_success 'stdin -z verify fails for mistaken null value' '
1020 test_cmp expect actual
1021 '
1022
1023 -test_expect_failure 'stdin -z verify fails for mistaken empty value' '
1023 +test_expect_success 'stdin -z verify fails for mistaken empty value' '
1024 M=$(git rev-parse $m) &&
1025 test_when_finished "git update-ref $m $M" &&
1026 git rev-parse $m >expect &&