Merge branch 'bc/submodule-force-same-hash'

Adding a repository that uses a different hash function is a no-no,
but "git submodule add" did nt prevent it, which has been corrected.

* bc/submodule-force-same-hash:
  read-cache: drop submodule check from add_to_cache()
  object-file: disallow adding submodules of different hash algo
main
Junio C Hamano 2025-11-24 15:46:39 -08:00
commit d91d79f26d
4 changed files with 56 additions and 4 deletions

View File

@ -1661,7 +1661,11 @@ int index_path(struct index_state *istate, struct object_id *oid,
strbuf_release(&sb); strbuf_release(&sb);
break; break;
case S_IFDIR: case S_IFDIR:
return repo_resolve_gitlink_ref(istate->repo, path, "HEAD", oid); if (repo_resolve_gitlink_ref(istate->repo, path, "HEAD", oid))
return error(_("'%s' does not have a commit checked out"), path);
if (&hash_algos[oid->algo] != istate->repo->hash_algo)
return error(_("cannot add a submodule of a different hash algorithm"));
break;
default: default:
return error(_("%s: unsupported file type"), path); return error(_("%s: unsupported file type"), path);
} }

View File

@ -706,7 +706,6 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE| int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
(intent_only ? ADD_CACHE_NEW_ONLY : 0)); (intent_only ? ADD_CACHE_NEW_ONLY : 0));
unsigned hash_flags = pretend ? 0 : INDEX_WRITE_OBJECT; unsigned hash_flags = pretend ? 0 : INDEX_WRITE_OBJECT;
struct object_id oid;


if (flags & ADD_CACHE_RENORMALIZE) if (flags & ADD_CACHE_RENORMALIZE)
hash_flags |= INDEX_RENORMALIZE; hash_flags |= INDEX_RENORMALIZE;
@ -716,8 +715,6 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,


namelen = strlen(path); namelen = strlen(path);
if (S_ISDIR(st_mode)) { if (S_ISDIR(st_mode)) {
if (repo_resolve_gitlink_ref(the_repository, path, "HEAD", &oid) < 0)
return error(_("'%s' does not have a commit checked out"), path);
while (namelen && path[namelen-1] == '/') while (namelen && path[namelen-1] == '/')
namelen--; namelen--;
} }

View File

@ -388,6 +388,7 @@ test_expect_success 'error on a repository with no commits' '
test_must_fail git add empty >actual 2>&1 && test_must_fail git add empty >actual 2>&1 &&
cat >expect <<-EOF && cat >expect <<-EOF &&
error: '"'empty/'"' does not have a commit checked out error: '"'empty/'"' does not have a commit checked out
error: unable to index file '"'empty/'"'
fatal: adding files failed fatal: adding files failed
EOF EOF
test_cmp expect actual test_cmp expect actual
@ -541,6 +542,31 @@ test_expect_success 'all statuses changed in folder if . is given' '
) )
' '


test_expect_success 'cannot add a submodule of a different algorithm' '
git init --object-format=sha256 sha256 &&
(
cd sha256 &&
test_commit abc &&
git init --object-format=sha1 submodule &&
test_commit -C submodule def &&
test_must_fail git add submodule 2>err &&
test_grep "cannot add a submodule of a different hash algorithm" err &&
git ls-files --stage >entries &&
test_grep ! ^160000 entries
) &&
git init --object-format=sha1 sha1 &&
(
cd sha1 &&
test_commit abc &&
git init --object-format=sha256 submodule &&
test_commit -C submodule def &&
test_must_fail git add submodule 2>err &&
test_grep "cannot add a submodule of a different hash algorithm" err &&
git ls-files --stage >entries &&
test_grep ! ^160000 entries
)
'

test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' ' test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' '
path="$(pwd)/BLUB" && path="$(pwd)/BLUB" &&
touch "$path" && touch "$path" &&

View File

@ -407,6 +407,31 @@ test_expect_success 'submodule add in subdirectory with relative path should fai
test_grep toplevel output.err test_grep toplevel output.err
' '


test_expect_success 'submodule add of a different algorithm fails' '
git init --object-format=sha256 sha256 &&
(
cd sha256 &&
test_commit abc &&
git init --object-format=sha1 submodule &&
test_commit -C submodule def &&
test_must_fail git submodule add "$submodurl" submodule 2>err &&
test_grep "cannot add a submodule of a different hash algorithm" err &&
git ls-files --stage >entries &&
test_grep ! ^160000 entries
) &&
git init --object-format=sha1 sha1 &&
(
cd sha1 &&
test_commit abc &&
git init --object-format=sha256 submodule &&
test_commit -C submodule def &&
test_must_fail git submodule add "$submodurl" submodule 2>err &&
test_grep "cannot add a submodule of a different hash algorithm" err &&
git ls-files --stage >entries &&
test_grep ! ^160000 entries
)
'

test_expect_success 'setup - add an example entry to .gitmodules' ' test_expect_success 'setup - add an example entry to .gitmodules' '
git config --file=.gitmodules submodule.example.url git://example.com/init.git git config --file=.gitmodules submodule.example.url git://example.com/init.git
' '