Skip to content

Commit 5b2d8d6

Browse files
mhaggergitster
authored andcommitted
lock_ref_sha1_basic(): improve diagnostics for ref D/F conflicts
If there is a failure to lock a reference that is likely caused by a D/F conflict (e.g., trying to lock "refs/foo/bar" when reference "refs/foo" already exists), invoke verify_refname_available() to try to generate a more helpful error message. That function might not detect an error. For example, some non-reference file might be blocking the deletion of an otherwise-empty directory tree, or there might be a race with another process that just deleted the offending reference. In such cases, generate the strerror-based error message like before. Signed-off-by: Michael Haggerty <[email protected]>
1 parent 4a32b2e commit 5b2d8d6

File tree

2 files changed

+16
-8
lines changed

2 files changed

+16
-8
lines changed

refs.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,8 +2369,12 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
23692369
ref_file = git_path("%s", orig_refname);
23702370
if (remove_empty_directories(ref_file)) {
23712371
last_errno = errno;
2372-
strbuf_addf(err, "there are still refs under '%s'",
2373-
orig_refname);
2372+
2373+
if (!verify_refname_available(orig_refname, extras, skip,
2374+
get_loose_refs(&ref_cache), err))
2375+
strbuf_addf(err, "there are still refs under '%s'",
2376+
orig_refname);
2377+
23742378
goto error_return;
23752379
}
23762380
refname = resolve_ref_unsafe(orig_refname, resolve_flags,
@@ -2380,8 +2384,12 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
23802384
*type_p = type;
23812385
if (!refname) {
23822386
last_errno = errno;
2383-
strbuf_addf(err, "unable to resolve reference %s: %s",
2384-
orig_refname, strerror(errno));
2387+
if (last_errno != ENOTDIR ||
2388+
!verify_refname_available(orig_refname, extras, skip,
2389+
get_loose_refs(&ref_cache), err))
2390+
strbuf_addf(err, "unable to resolve reference %s: %s",
2391+
orig_refname, strerror(last_errno));
2392+
23852393
goto error_return;
23862394
}
23872395
/*

t/t1404-update-ref-df-conflicts.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ test_expect_success 'existing loose ref is a simple prefix of new' '
3636
3737
prefix=refs/1l &&
3838
test_update_rejected $prefix "a c e" false "b c/x d" \
39-
"unable to resolve reference $prefix/c/x: Not a directory"
39+
"$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q"
4040
4141
'
4242

@@ -52,7 +52,7 @@ test_expect_success 'existing loose ref is a deeper prefix of new' '
5252
5353
prefix=refs/2l &&
5454
test_update_rejected $prefix "a c e" false "b c/x/y d" \
55-
"unable to resolve reference $prefix/c/x/y: Not a directory"
55+
"$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q"
5656
5757
'
5858

@@ -68,7 +68,7 @@ test_expect_success 'new ref is a simple prefix of existing loose' '
6868
6969
prefix=refs/3l &&
7070
test_update_rejected $prefix "a c/x e" false "b c d" \
71-
"there are still refs under $Q$prefix/c$Q"
71+
"$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q"
7272
7373
'
7474

@@ -84,7 +84,7 @@ test_expect_success 'new ref is a deeper prefix of existing loose' '
8484
8585
prefix=refs/4l &&
8686
test_update_rejected $prefix "a c/x/y e" false "b c d" \
87-
"there are still refs under $Q$prefix/c$Q"
87+
"$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q"
8888
8989
'
9090

0 commit comments

Comments
 (0)