Skip to content

Commit 26597cb

Browse files
committed
Merge branch 'ma/create-pseudoref-with-null-old-oid'
"git update-ref A B" is supposed to ensure that ref A does not yet exist when B is a NULL OID, but this check was not done correctly for pseudo-refs outside refs/ hierarchy, e.g. MERGE_HEAD. * ma/create-pseudoref-with-null-old-oid: refs: handle zero oid for pseudorefs t1400: add tests around adding/deleting pseudorefs refs.c: refer to "object ID", not "sha1", in error messages
2 parents cf31579 + db0210d commit 26597cb

File tree

2 files changed

+77
-5
lines changed

2 files changed

+77
-5
lines changed

refs.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,21 @@ static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
681681
if (old_oid) {
682682
struct object_id actual_old_oid;
683683

684-
if (read_ref(pseudoref, &actual_old_oid))
685-
die("could not read ref '%s'", pseudoref);
686-
if (oidcmp(&actual_old_oid, old_oid)) {
687-
strbuf_addf(err, "unexpected sha1 when writing '%s'", pseudoref);
684+
if (read_ref(pseudoref, &actual_old_oid)) {
685+
if (!is_null_oid(old_oid)) {
686+
strbuf_addf(err, "could not read ref '%s'",
687+
pseudoref);
688+
rollback_lock_file(&lock);
689+
goto done;
690+
}
691+
} else if (is_null_oid(old_oid)) {
692+
strbuf_addf(err, "ref '%s' already exists",
693+
pseudoref);
694+
rollback_lock_file(&lock);
695+
goto done;
696+
} else if (oidcmp(&actual_old_oid, old_oid)) {
697+
strbuf_addf(err, "unexpected object ID when writing '%s'",
698+
pseudoref);
688699
rollback_lock_file(&lock);
689700
goto done;
690701
}
@@ -725,7 +736,8 @@ static int delete_pseudoref(const char *pseudoref, const struct object_id *old_o
725736
if (read_ref(pseudoref, &actual_old_oid))
726737
die("could not read ref '%s'", pseudoref);
727738
if (oidcmp(&actual_old_oid, old_oid)) {
728-
warning("Unexpected sha1 when deleting %s", pseudoref);
739+
error("unexpected object ID when deleting '%s'",
740+
pseudoref);
729741
rollback_lock_file(&lock);
730742
return -1;
731743
}

t/t1400-update-ref.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,66 @@ test_expect_success 'git cat-file blob master@{2005-05-26 23:42}:F (expect OTHER
457457
test OTHER = $(git cat-file blob "master@{2005-05-26 23:42}:F")
458458
'
459459

460+
# Test adding and deleting pseudorefs
461+
462+
test_expect_success 'given old value for missing pseudoref, do not create' '
463+
test_must_fail git update-ref PSEUDOREF $A $B 2>err &&
464+
test_path_is_missing .git/PSEUDOREF &&
465+
grep "could not read ref" err
466+
'
467+
468+
test_expect_success 'create pseudoref' '
469+
git update-ref PSEUDOREF $A &&
470+
test $A = $(cat .git/PSEUDOREF)
471+
'
472+
473+
test_expect_success 'overwrite pseudoref with no old value given' '
474+
git update-ref PSEUDOREF $B &&
475+
test $B = $(cat .git/PSEUDOREF)
476+
'
477+
478+
test_expect_success 'overwrite pseudoref with correct old value' '
479+
git update-ref PSEUDOREF $C $B &&
480+
test $C = $(cat .git/PSEUDOREF)
481+
'
482+
483+
test_expect_success 'do not overwrite pseudoref with wrong old value' '
484+
test_must_fail git update-ref PSEUDOREF $D $E 2>err &&
485+
test $C = $(cat .git/PSEUDOREF) &&
486+
grep "unexpected object ID" err
487+
'
488+
489+
test_expect_success 'delete pseudoref' '
490+
git update-ref -d PSEUDOREF &&
491+
test_path_is_missing .git/PSEUDOREF
492+
'
493+
494+
test_expect_success 'do not delete pseudoref with wrong old value' '
495+
git update-ref PSEUDOREF $A &&
496+
test_must_fail git update-ref -d PSEUDOREF $B 2>err &&
497+
test $A = $(cat .git/PSEUDOREF) &&
498+
grep "unexpected object ID" err
499+
'
500+
501+
test_expect_success 'delete pseudoref with correct old value' '
502+
git update-ref -d PSEUDOREF $A &&
503+
test_path_is_missing .git/PSEUDOREF
504+
'
505+
506+
test_expect_success 'create pseudoref with old OID zero' '
507+
git update-ref PSEUDOREF $A $Z &&
508+
test $A = $(cat .git/PSEUDOREF)
509+
'
510+
511+
test_expect_success 'do not overwrite pseudoref with old OID zero' '
512+
test_when_finished git update-ref -d PSEUDOREF &&
513+
test_must_fail git update-ref PSEUDOREF $B $Z 2>err &&
514+
test $A = $(cat .git/PSEUDOREF) &&
515+
grep "already exists" err
516+
'
517+
518+
# Test --stdin
519+
460520
a=refs/heads/a
461521
b=refs/heads/b
462522
c=refs/heads/c

0 commit comments

Comments
 (0)