From 0273a55087e2614323d6ebd145b08c56b370a483 Mon Sep 17 00:00:00 2001 From: tv Date: Fri, 13 Nov 2026 21:09:04 +0000 Subject: populate: check the hooks and submodules of Git work trees git submodule update uses the .git of a submodule as it finds it in the work tree: a repository of its own, with configuration that runs commands, or a file naming a repository elsewhere. So git_problems also requires each .git below the work tree to be a file naming a repository in .git/modules. And it refuses hooks in .git/hooks, which populate's Git doesn't run, but Nix's does, writing the lock file of a flake in a git source. It's a shell function now, taking the work tree at run time, so drawing inputs can use it too. git-submodule plants a submodule's .git in the work tree: a repository of its own whose configuration names a filter, and a file naming a repository elsewhere. The fixture withsub has gitsrc as its submodule sub. --- tests/fixtures.sh | 17 +++++++++++++++ tests/scenarios.nix | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) (limited to 'tests') diff --git a/tests/fixtures.sh b/tests/fixtures.sh index ccd55a0..85701a1 100755 --- a/tests/fixtures.sh +++ b/tests/fixtures.sh @@ -307,6 +307,23 @@ mkdir /fixtures/git git clone -q --bare /fixtures/gitsrc /fixtures/git/gitsrc.git git -C /fixtures/git/gitsrc.git config uploadpack.allowReachableSHA1InWant true +# withsub: a Git repository with gitsrc as its submodule sub, served by git +# daemon like gitsrc, which the tests reach as git://deployer/gitsrc.git. +mkdir /fixtures/withsub +cat > /fixtures/withsub/.gitmodules <<'GIT' +[submodule "sub"] + path = sub + url = git://deployer/gitsrc.git +GIT +( + cd /fixtures/withsub + git init -q -b master + git update-index --add --cacheinfo 160000,"$git_head",sub + git add .gitmodules + git commit -q -m withsub +) +git clone -q --bare /fixtures/withsub /fixtures/git/withsub.git + # pass: password stores with x/a, without and with Git. if ! gpg --list-secret-keys spam@krebsco.de >/dev/null 2>&1; then gpg --batch --passphrase '' --quick-gen-key spam@krebsco.de default default never diff --git a/tests/scenarios.nix b/tests/scenarios.nix index 8093e02..5d08e2e 100644 --- a/tests/scenarios.nix +++ b/tests/scenarios.nix @@ -2104,6 +2104,66 @@ assert !(krops.isLocalTarget (targets.remote "/")); } ]; })) + # A Git work tree whose submodule's .git, which Git uses as it finds it, + # isn't the gitfile git clone made, naming the repository in + # .git/modules: a repository of its own, whose configuration names a + # command, and a gitfile naming a repository elsewhere. + (s "git-submodule" (let + elsewhere = "/var/krops-elsewhere"; + url = dirOf gitUrl + "/withsub.git"; + git = reclone: { x.git = { inherit url reclone; ref = "master"; }; }; + untouched = '' + test ! -e ${elsewhere}/ran || fail "a command in a .git directory ran" + expect_eq "HEAD elsewhere" "$(git -C ${elsewhere}/repo rev-parse HEAD)" ${gitFirst} + ''; + in { + isolate = true; + prepare = '' + rm -fR ${elsewhere} + git clone -q ${gitUrl} ${elsewhere}/repo + git -C ${elsewhere}/repo checkout -q ${gitFirst} + ''; + phases = [ + { + sources = git false; + check = untouched + '' + expect_eq "sub HEAD" "$(git -C "$T"/x/sub rev-parse HEAD)" ${gitHead} + ''; + mutate = '' + rm "$T"/x/sub/.git + cp -R "$T"/x/.git/modules/sub "$T"/x/sub/.git + git config --file "$T"/x/sub/.git/config --unset core.worktree + git config --file "$T"/x/sub/.git/config \ + filter.x.smudge "touch ${elsewhere}/ran; cat" + echo '* filter=x' > "$T"/x/sub/.git/info/attributes + git -C "$T"/x/sub update-ref --no-deref HEAD ${gitFirst} + git -C "$T"/x/sub read-tree ${gitFirst} + rm "$T"/x/sub/two + ''; + } + { + sources = git false; + expect.fail = "error: populate doesn't use the Git work tree"; + check = untouched; + mutate = '' + rm -fR "$T"/x/sub + mkdir "$T"/x/sub + echo gitdir: ${elsewhere}/repo/.git > "$T"/x/sub/.git + ''; + } + { + sources = git false; + expect.fail = "error: populate doesn't use the Git work tree"; + check = untouched; + } + { + sources = git true; + check = untouched + '' + expect_eq "sub HEAD" "$(git -C "$T"/x/sub rev-parse HEAD)" ${gitHead} + ''; + } + ]; + })) # A ref that git fetch would take for an option: --upload-pack runs a # command where the repository is local. (s "git-ref-option" (let -- cgit v1.3.1