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 <mhagger@xxxxxxxxxxxx> --- refs.c | 16 ++++++++++++---- t/t1404-update-ref-df-conflicts.sh | 8 ++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/refs.c b/refs.c index ff9b9cf..ce993bd 100644 --- a/refs.c +++ b/refs.c @@ -2369,8 +2369,12 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname, ref_file = git_path("%s", orig_refname); if (remove_empty_directories(ref_file)) { last_errno = errno; - strbuf_addf(err, "there are still refs under '%s'", - orig_refname); + + if (!verify_refname_available(orig_refname, extras, skip, + get_loose_refs(&ref_cache), err)) + strbuf_addf(err, "there are still refs under '%s'", + orig_refname); + goto error_return; } refname = resolve_ref_unsafe(orig_refname, resolve_flags, @@ -2380,8 +2384,12 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname, *type_p = type; if (!refname) { last_errno = errno; - strbuf_addf(err, "unable to resolve reference %s: %s", - orig_refname, strerror(errno)); + if (last_errno != ENOTDIR || + !verify_refname_available(orig_refname, extras, skip, + get_loose_refs(&ref_cache), err)) + strbuf_addf(err, "unable to resolve reference %s: %s", + orig_refname, strerror(last_errno)); + goto error_return; } /* diff --git a/t/t1404-update-ref-df-conflicts.sh b/t/t1404-update-ref-df-conflicts.sh index b0bb7d4..348a07a 100755 --- a/t/t1404-update-ref-df-conflicts.sh +++ b/t/t1404-update-ref-df-conflicts.sh @@ -36,7 +36,7 @@ test_expect_success 'existing loose ref is a simple prefix of new' ' prefix=refs/1l && test_update_rejected $prefix "a c e" false "b c/x d" \ - "unable to resolve reference $prefix/c/x: Not a directory" + "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q" ' @@ -52,7 +52,7 @@ test_expect_success 'existing loose ref is a deeper prefix of new' ' prefix=refs/2l && test_update_rejected $prefix "a c e" false "b c/x/y d" \ - "unable to resolve reference $prefix/c/x/y: Not a directory" + "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q" ' @@ -68,7 +68,7 @@ test_expect_success 'new ref is a simple prefix of existing loose' ' prefix=refs/3l && test_update_rejected $prefix "a c/x e" false "b c d" \ - "there are still refs under $Q$prefix/c$Q" + "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q" ' @@ -84,7 +84,7 @@ test_expect_success 'new ref is a deeper prefix of existing loose' ' prefix=refs/4l && test_update_rejected $prefix "a c/x/y e" false "b c d" \ - "there are still refs under $Q$prefix/c$Q" + "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q" ' -- 2.1.4 -- 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