@@ -653,6 +653,26 @@ static void unlock_ref(struct ref_lock *lock)
653653 }
654654}
655655
656+ /*
657+ * Check if the transaction has another update with a case-insensitive refname
658+ * match.
659+ *
660+ * If the update is part of the transaction, we only check up to that index.
661+ * Further updates are expected to call this function to match previous indices.
662+ */
663+ static bool transaction_has_case_conflicting_update (struct ref_transaction * transaction ,
664+ struct ref_update * update )
665+ {
666+ for (size_t i = 0 ; i < transaction -> nr ; i ++ ) {
667+ if (transaction -> updates [i ] == update )
668+ break ;
669+
670+ if (!strcasecmp (transaction -> updates [i ]-> refname , update -> refname ))
671+ return true;
672+ }
673+ return false;
674+ }
675+
656676/*
657677 * Lock refname, without following symrefs, and set *lock_p to point
658678 * at a newly-allocated lock object. Fill in lock->old_oid, referent,
@@ -683,16 +703,17 @@ static void unlock_ref(struct ref_lock *lock)
683703 * - Generate informative error messages in the case of failure
684704 */
685705static enum ref_transaction_error lock_raw_ref (struct files_ref_store * refs ,
686- struct ref_update * update ,
706+ struct ref_transaction * transaction ,
687707 size_t update_idx ,
688708 int mustexist ,
689709 struct string_list * refnames_to_check ,
690- const struct string_list * extras ,
691710 struct ref_lock * * lock_p ,
692711 struct strbuf * referent ,
693712 struct strbuf * err )
694713{
695714 enum ref_transaction_error ret = REF_TRANSACTION_ERROR_GENERIC ;
715+ struct ref_update * update = transaction -> updates [update_idx ];
716+ const struct string_list * extras = & transaction -> refnames ;
696717 const char * refname = update -> refname ;
697718 unsigned int * type = & update -> type ;
698719 struct ref_lock * lock ;
@@ -782,6 +803,24 @@ static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs,
782803 goto retry ;
783804 } else {
784805 unable_to_lock_message (ref_file .buf , myerr , err );
806+ if (myerr == EEXIST ) {
807+ if (ignore_case &&
808+ transaction_has_case_conflicting_update (transaction , update )) {
809+ /*
810+ * In case-insensitive filesystems, ensure that conflicts within a
811+ * given transaction are handled. Pre-existing refs on a
812+ * case-insensitive system will be overridden without any issue.
813+ */
814+ ret = REF_TRANSACTION_ERROR_CASE_CONFLICT ;
815+ } else {
816+ /*
817+ * Pre-existing case-conflicting reference locks should also be
818+ * specially categorized to avoid failing all batched updates.
819+ */
820+ ret = REF_TRANSACTION_ERROR_CREATE_EXISTS ;
821+ }
822+ }
823+
785824 goto error_return ;
786825 }
787826 }
@@ -837,21 +876,22 @@ static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs,
837876 goto error_return ;
838877 } else if (remove_dir_recursively (& ref_file ,
839878 REMOVE_DIR_EMPTY_ONLY )) {
879+ ret = REF_TRANSACTION_ERROR_NAME_CONFLICT ;
840880 if (refs_verify_refname_available (
841881 & refs -> base , refname ,
842882 extras , NULL , 0 , err )) {
843883 /*
844884 * The error message set by
845885 * verify_refname_available() is OK.
846886 */
847- ret = REF_TRANSACTION_ERROR_NAME_CONFLICT ;
848887 goto error_return ;
849888 } else {
850889 /*
851- * We can't delete the directory,
852- * but we also don't know of any
853- * references that it should
854- * contain.
890+ * Directory conflicts can occur if there
891+ * is an existing lock file in the directory
892+ * or if the filesystem is case-insensitive
893+ * and the directory contains a valid reference
894+ * but conflicts with the update.
855895 */
856896 strbuf_addf (err , "there is a non-empty directory '%s' "
857897 "blocking reference '%s'" ,
@@ -873,8 +913,23 @@ static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs,
873913 * If the ref did not exist and we are creating it, we have to
874914 * make sure there is no existing packed ref that conflicts
875915 * with refname. This check is deferred so that we can batch it.
916+ *
917+ * For case-insensitive filesystems, we should also check for F/D
918+ * conflicts between 'foo' and 'Foo/bar'. So let's lowercase
919+ * the refname.
876920 */
877- item = string_list_append (refnames_to_check , refname );
921+ if (ignore_case ) {
922+ struct strbuf lower = STRBUF_INIT ;
923+
924+ strbuf_addstr (& lower , refname );
925+ strbuf_tolower (& lower );
926+
927+ item = string_list_append_nodup (refnames_to_check ,
928+ strbuf_detach (& lower , NULL ));
929+ } else {
930+ item = string_list_append (refnames_to_check , refname );
931+ }
932+
878933 item -> util = xmalloc (sizeof (update_idx ));
879934 memcpy (item -> util , & update_idx , sizeof (update_idx ));
880935 }
@@ -2616,9 +2671,8 @@ static enum ref_transaction_error lock_ref_for_update(struct files_ref_store *re
26162671 if (lock ) {
26172672 lock -> count ++ ;
26182673 } else {
2619- ret = lock_raw_ref (refs , update , update_idx , mustexist ,
2620- refnames_to_check , & transaction -> refnames ,
2621- & lock , & referent , err );
2674+ ret = lock_raw_ref (refs , transaction , update_idx , mustexist ,
2675+ refnames_to_check , & lock , & referent , err );
26222676 if (ret ) {
26232677 char * reason ;
26242678
@@ -2858,7 +2912,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
28582912 "ref_transaction_prepare" );
28592913 size_t i ;
28602914 int ret = 0 ;
2861- struct string_list refnames_to_check = STRING_LIST_INIT_NODUP ;
2915+ struct string_list refnames_to_check = STRING_LIST_INIT_DUP ;
28622916 char * head_ref = NULL ;
28632917 int head_type ;
28642918 struct files_transaction_backend_data * backend_data ;
0 commit comments