@@ -2238,15 +2238,58 @@ int submodule_move_head(const char *path, const char *super_prefix,
22382238 return ret ;
22392239}
22402240
2241+ static int check_casefolding_conflict (const char * git_dir ,
2242+ const char * submodule_name ,
2243+ const bool suffixes_match )
2244+ {
2245+ char * p , * modules_dir = xstrdup (git_dir );
2246+ struct dirent * de ;
2247+ DIR * dir = NULL ;
2248+ int ret = 0 ;
2249+
2250+ if ((p = find_last_dir_sep (modules_dir )))
2251+ * p = '\0' ;
2252+
2253+ /* No conflict is possible if modules_dir doesn't exist (first clone) */
2254+ if (!is_directory (modules_dir ))
2255+ goto cleanup ;
2256+
2257+ dir = opendir (modules_dir );
2258+ if (!dir ) {
2259+ ret = -1 ;
2260+ goto cleanup ;
2261+ }
2262+
2263+ /* Check for another directory under .git/modules that differs only in case. */
2264+ while ((de = readdir (dir ))) {
2265+ if (!strcmp (de -> d_name , "." ) || !strcmp (de -> d_name , ".." ))
2266+ continue ;
2267+
2268+ if ((suffixes_match || is_git_directory (git_dir )) &&
2269+ !strcasecmp (de -> d_name , submodule_name ) &&
2270+ strcmp (de -> d_name , submodule_name )) {
2271+ ret = -1 ; /* collision found */
2272+ break ;
2273+ }
2274+ }
2275+
2276+ cleanup :
2277+ if (dir )
2278+ closedir (dir );
2279+ FREE_AND_NULL (modules_dir );
2280+ return ret ;
2281+ }
2282+
22412283/*
22422284 * Encoded gitdir validation function used when extensions.submoduleEncoding is enabled.
22432285 * This does not print errors like the non-encoded version, because encoding is supposed
22442286 * to mitigate / fix all these.
22452287 */
2246- static int validate_submodule_encoded_git_dir (char * git_dir , const char * submodule_name UNUSED )
2288+ static int validate_submodule_encoded_git_dir (char * git_dir , const char * submodule_name )
22472289{
22482290 const char * modules_marker = "/modules/" ;
22492291 char * p = git_dir , * last_submodule_name = NULL ;
2292+ int config_ignorecase = 0 ;
22502293
22512294 if (!the_repository -> repository_format_submodule_encoding )
22522295 BUG ("validate_submodule_encoded_git_dir() must be called with "
@@ -2262,6 +2305,14 @@ static int validate_submodule_encoded_git_dir(char *git_dir, const char *submodu
22622305 if (!last_submodule_name || strchr (last_submodule_name , '/' ))
22632306 return -1 ;
22642307
2308+ /* Prevent conflicts on case-folding filesystems */
2309+ repo_config_get_bool (the_repository , "core.ignorecase" , & config_ignorecase );
2310+ if (ignore_case || config_ignorecase ) {
2311+ bool suffixes_match = !strcmp (last_submodule_name , submodule_name );
2312+ return check_casefolding_conflict (git_dir , submodule_name ,
2313+ suffixes_match );
2314+ }
2315+
22652316 return 0 ;
22662317}
22672318
@@ -2650,13 +2701,37 @@ void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r,
26502701 if (!validate_and_set_submodule_gitdir (buf , submodule_name ))
26512702 return ;
26522703
2653- /* Case 2: Try URI-safe (RFC3986) encoding first, this fixes nested gitdirs */
2704+ /* Case 2.1 : Try URI-safe (RFC3986) encoding first, this fixes nested gitdirs */
26542705 strbuf_reset (buf );
26552706 repo_git_path_append (r , buf , "modules/" );
26562707 strbuf_addstr_urlencode (buf , submodule_name , is_rfc3986_unreserved );
26572708 if (!validate_and_set_submodule_gitdir (buf , submodule_name ))
26582709 return ;
26592710
2711+ /* Case 2.2: Try extended uppercase URI (RFC3986) encoding, to fix case-folding */
2712+ strbuf_reset (buf );
2713+ repo_git_path_append (r , buf , "modules/" );
2714+ strbuf_addstr_urlencode (buf , submodule_name , is_casefolding_rfc3986_unreserved );
2715+ if (!validate_and_set_submodule_gitdir (buf , submodule_name ))
2716+ return ;
2717+
2718+ /* Case 2.3: Try some derived gitdir names, see if one sticks */
2719+ for (char c = '0' ; c <= '9' ; c ++ ) {
2720+ strbuf_reset (buf );
2721+ repo_git_path_append (r , buf , "modules/" );
2722+ strbuf_addstr_urlencode (buf , submodule_name , is_rfc3986_unreserved );
2723+ strbuf_addch (buf , c );
2724+ if (!validate_and_set_submodule_gitdir (buf , submodule_name ))
2725+ return ;
2726+
2727+ strbuf_reset (buf );
2728+ repo_git_path_append (r , buf , "modules/" );
2729+ strbuf_addstr_urlencode (buf , submodule_name , is_casefolding_rfc3986_unreserved );
2730+ strbuf_addch (buf , c );
2731+ if (!validate_and_set_submodule_gitdir (buf , submodule_name ))
2732+ return ;
2733+ }
2734+
26602735 /* Case 3: Nothing worked: error out */
26612736 die (_ ("Cannot construct a valid gitdir path for submodule '%s': "
26622737 "please set a unique git config for 'submodule.%s.gitdir'." ),
0 commit comments