refs: return conflict error when checking packed refs

The TRANSACTION_NAME_CONFLICT error code refers to a failure to create a ref due to a name conflict with another ref. An example of this is a directory/file conflict such as ref names A/B and A. "git fetch" uses this error code to more accurately describe the error by recommending to the user that they try running "git remote prune" to remove any old refs that are deleted by the remote which would clear up any directory/file conflicts. This helpful error message is not displayed when the conflicted ref is stored in packed refs. This change fixes this by ensuring error return code consistency in `lock_raw_ref`. Signed-off-by: Ivan Tse <ivan.tse1@gmail.com> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ivan Tse committed May 4, 2024 at 03:04 UTC 9339fca23efbe1a2f9dc916356be9d0a22d233c2
2 files changed +19 -1
refs/files-backend.c
+3 -1
@@ -794,8 +794,10 @@ retry:
794 */
795 if (refs_verify_refname_available(
796 refs->packed_ref_store, refname,
797 - extras, NULL, err))
797 + extras, NULL, err)) {
798 + ret = TRANSACTION_NAME_CONFLICT;
799 goto error_return;
800 + }
801 }
802
803 ret = 0;
t/t5510-fetch.sh
+16
@@ -1091,6 +1091,22 @@ test_expect_success 'branchname D/F conflict resolved by --prune' '
1091 test_cmp expect actual
1092 '
1093
1094 +test_expect_success 'branchname D/F conflict rejected with targeted error message' '
1095 + git clone . df-conflict-error &&
1096 + git branch dir_conflict &&
1097 + (
1098 + cd df-conflict-error &&
1099 + git update-ref refs/remotes/origin/dir_conflict/file HEAD &&
1100 + test_must_fail git fetch 2>err &&
1101 + test_grep "error: some local refs could not be updated; try running" err &&
1102 + test_grep " ${SQ}git remote prune origin${SQ} to remove any old, conflicting branches" err &&
1103 + git pack-refs --all &&
1104 + test_must_fail git fetch 2>err-packed &&
1105 + test_grep "error: some local refs could not be updated; try running" err-packed &&
1106 + test_grep " ${SQ}git remote prune origin${SQ} to remove any old, conflicting branches" err-packed
1107 + )
1108 +'
1109 +
1110 test_expect_success 'fetching a one-level ref works' '
1111 test_commit extra &&
1112 git reset --hard HEAD^ &&