Skip to content

Commit a75481e

Browse files
10ne1gitster
authored andcommitted
submodule: use hashed name for gitdir
If none of the previous steps work and we reach case 2.4, try to hash the submodule name and see if that can be a valid gitdir before giving up and throwing an error. This is a "last resort" type of measure to avoid conflicts since it loses the gitdir human readability. Itis not such a big deal because users are now supposed to use the submodule.<name>.gitdir config as the single source of truth for gitdir paths. This logic will be reached in very rare cases, as can be seen in the test we added. Signed-off-by: Adrian Ratiu <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f9e7677 commit a75481e

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

submodule.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2660,8 +2660,12 @@ static int validate_and_set_submodule_gitdir(struct strbuf *gitdir_path,
26602660
void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r,
26612661
const char *submodule_name)
26622662
{
2663+
unsigned char raw_name_hash[GIT_MAX_RAWSZ];
2664+
char hex_name_hash[GIT_MAX_HEXSZ + 1];
2665+
struct git_hash_ctx ctx;
26632666
const char *gitdir;
2664-
char *key;
2667+
char *key, header[128];
2668+
int header_len;
26652669

26662670
repo_git_path_append(r, buf, "modules/");
26672671
strbuf_addstr(buf, submodule_name);
@@ -2732,6 +2736,20 @@ void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r,
27322736
return;
27332737
}
27342738

2739+
/* Case 2.4: If all the above failed, try a hash of the name as a last resort */
2740+
header_len = snprintf(header, sizeof(header), "blob %zu", strlen(submodule_name));
2741+
the_hash_algo->init_fn(&ctx);
2742+
the_hash_algo->update_fn(&ctx, header, header_len);
2743+
the_hash_algo->update_fn(&ctx, "\0", 1);
2744+
the_hash_algo->update_fn(&ctx, submodule_name, strlen(submodule_name));
2745+
the_hash_algo->final_fn(raw_name_hash, &ctx);
2746+
hash_to_hex_algop_r(hex_name_hash, raw_name_hash, the_hash_algo);
2747+
strbuf_reset(buf);
2748+
repo_git_path_append(r, buf, "modules/");
2749+
strbuf_addstr(buf, hex_name_hash);
2750+
if (!validate_and_set_submodule_gitdir(buf, submodule_name))
2751+
return;
2752+
27352753
/* Case 3: Nothing worked: error out */
27362754
die(_("Cannot construct a valid gitdir path for submodule '%s': "
27372755
"please set a unique git config for 'submodule.%s.gitdir'."),

t/t7425-submodule-encoding.sh

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,63 @@ test_expect_success CASE_INSENSITIVE_FS 'verify case-folding conflicts are corre
196196
verify_submodule_gitdir_path cloned-folding "fooBar" "modules/fooBar0"
197197
'
198198

199+
test_expect_success CASE_INSENSITIVE_FS 'verify hashing conflict resolution as a last resort' '
200+
git clone -c extensions.submoduleEncoding=true main cloned-hash &&
201+
(
202+
cd cloned-hash &&
203+
204+
# conflict: add all submodule conflicting variants until we reach the
205+
# final hashing conflict resolution for submodule "foo"
206+
git submodule add ../new-sub "foo" &&
207+
git submodule add ../new-sub "foo0" &&
208+
git submodule add ../new-sub "foo1" &&
209+
git submodule add ../new-sub "foo2" &&
210+
git submodule add ../new-sub "foo3" &&
211+
git submodule add ../new-sub "foo4" &&
212+
git submodule add ../new-sub "foo5" &&
213+
git submodule add ../new-sub "foo6" &&
214+
git submodule add ../new-sub "foo7" &&
215+
git submodule add ../new-sub "foo8" &&
216+
git submodule add ../new-sub "foo9" &&
217+
git submodule add ../new-sub "%46oo" &&
218+
git submodule add ../new-sub "%46oo0" &&
219+
git submodule add ../new-sub "%46oo1" &&
220+
git submodule add ../new-sub "%46oo2" &&
221+
git submodule add ../new-sub "%46oo3" &&
222+
git submodule add ../new-sub "%46oo4" &&
223+
git submodule add ../new-sub "%46oo5" &&
224+
git submodule add ../new-sub "%46oo6" &&
225+
git submodule add ../new-sub "%46oo7" &&
226+
git submodule add ../new-sub "%46oo8" &&
227+
git submodule add ../new-sub "%46oo9" &&
228+
test_commit add-foo-variants &&
229+
git submodule add ../new-sub "Foo" &&
230+
test_commit add-uppercase-foo
231+
) &&
232+
verify_submodule_gitdir_path cloned-hash "foo" "modules/foo" &&
233+
verify_submodule_gitdir_path cloned-hash "foo0" "modules/foo0" &&
234+
verify_submodule_gitdir_path cloned-hash "foo1" "modules/foo1" &&
235+
verify_submodule_gitdir_path cloned-hash "foo2" "modules/foo2" &&
236+
verify_submodule_gitdir_path cloned-hash "foo3" "modules/foo3" &&
237+
verify_submodule_gitdir_path cloned-hash "foo4" "modules/foo4" &&
238+
verify_submodule_gitdir_path cloned-hash "foo5" "modules/foo5" &&
239+
verify_submodule_gitdir_path cloned-hash "foo6" "modules/foo6" &&
240+
verify_submodule_gitdir_path cloned-hash "foo7" "modules/foo7" &&
241+
verify_submodule_gitdir_path cloned-hash "foo8" "modules/foo8" &&
242+
verify_submodule_gitdir_path cloned-hash "foo9" "modules/foo9" &&
243+
verify_submodule_gitdir_path cloned-hash "%46oo" "modules/%46oo" &&
244+
verify_submodule_gitdir_path cloned-hash "%46oo0" "modules/%46oo0" &&
245+
verify_submodule_gitdir_path cloned-hash "%46oo1" "modules/%46oo1" &&
246+
verify_submodule_gitdir_path cloned-hash "%46oo2" "modules/%46oo2" &&
247+
verify_submodule_gitdir_path cloned-hash "%46oo3" "modules/%46oo3" &&
248+
verify_submodule_gitdir_path cloned-hash "%46oo4" "modules/%46oo4" &&
249+
verify_submodule_gitdir_path cloned-hash "%46oo5" "modules/%46oo5" &&
250+
verify_submodule_gitdir_path cloned-hash "%46oo6" "modules/%46oo6" &&
251+
verify_submodule_gitdir_path cloned-hash "%46oo7" "modules/%46oo7" &&
252+
verify_submodule_gitdir_path cloned-hash "%46oo8" "modules/%46oo8" &&
253+
verify_submodule_gitdir_path cloned-hash "%46oo9" "modules/%46oo9" &&
254+
hash=$(printf "Foo" | git hash-object --stdin) &&
255+
verify_submodule_gitdir_path cloned-hash "Foo" "modules/${hash}"
256+
'
257+
199258
test_done

0 commit comments

Comments
 (0)