diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index 2b63dda3e..2faf07209 100644 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -81,17 +81,6 @@ echo -n '# foo' >> $flake1Dir/flake.nix git -C $flake1Dir commit -a -m 'Foo' hash2=$(nix flake metadata flake1 --json --refresh | jq -r .revision) -# Test 'nix build' on a flake. -nix build -o $TEST_ROOT/result flake1#foo -[[ -e $TEST_ROOT/result/hello ]] - -# Test packages.default. -nix build -o $TEST_ROOT/result flake1 -[[ -e $TEST_ROOT/result/hello ]] - -nix build -o $TEST_ROOT/result $flake1Dir -nix build -o $TEST_ROOT/result git+file://$flake1Dir - # Check that store symlinks inside a flake are not interpreted as flakes. nix build -o $flake1Dir/result git+file://$flake1Dir nix path-info $flake1Dir/result @@ -105,46 +94,13 @@ nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"$flake1Dir\").packag nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"git+file://$flake1Dir?rev=$hash2\").packages.$system.default" # Building a flake with an unlocked dependency should fail in pure mode. -(! nix build -o $TEST_ROOT/result flake2#bar --no-registries) -(! nix build -o $TEST_ROOT/result flake2#bar --no-use-registries) (! nix eval --expr "builtins.getFlake \"$flake2Dir\"") # But should succeed in impure mode. -(! nix build -o $TEST_ROOT/result flake2#bar --impure) -nix build -o $TEST_ROOT/result flake2#bar --impure --no-write-lock-file nix eval --expr "builtins.getFlake \"$flake2Dir\"" --impure -# Building a local flake with an unlocked dependency should fail with --no-update-lock-file. -expect 1 nix build -o $TEST_ROOT/result $flake2Dir#bar --no-update-lock-file 2>&1 | grep 'requires lock file changes' - -# But it should succeed without that flag. -nix build -o $TEST_ROOT/result $flake2Dir#bar --no-write-lock-file -expect 1 nix build -o $TEST_ROOT/result $flake2Dir#bar --no-update-lock-file 2>&1 | grep 'requires lock file changes' +# set up lockfiles for later tests nix build -o $TEST_ROOT/result $flake2Dir#bar --commit-lock-file -[[ -e $flake2Dir/flake.lock ]] -[[ -z $(git -C $flake2Dir diff main || echo failed) ]] - -# Rerunning the build should not change the lockfile. -nix build -o $TEST_ROOT/result $flake2Dir#bar -[[ -z $(git -C $flake2Dir diff main || echo failed) ]] - -# Building with a lockfile should not require a fetch of the registry. -nix build -o $TEST_ROOT/result --flake-registry file:///no-registry.json $flake2Dir#bar --refresh -nix build -o $TEST_ROOT/result --no-registries $flake2Dir#bar --refresh -nix build -o $TEST_ROOT/result --no-use-registries $flake2Dir#bar --refresh - -# Updating the flake should not change the lockfile. -nix flake lock $flake2Dir -[[ -z $(git -C $flake2Dir diff main || echo failed) ]] - -# Now we should be able to build the flake in pure mode. -nix build -o $TEST_ROOT/result flake2#bar - -# Or without a registry. -nix build -o $TEST_ROOT/result --no-registries git+file://$flake2Dir#bar --refresh -nix build -o $TEST_ROOT/result --no-use-registries git+file://$flake2Dir#bar --refresh - -# Test whether indirect dependencies work. nix build -o $TEST_ROOT/result $flake3Dir#xyzzy git -C $flake3Dir add flake.lock diff --git a/tests/functional2/flakes/test_cli.py b/tests/functional2/flakes/test_cli.py index c122ed32f..a9bb95c28 100644 --- a/tests/functional2/flakes/test_cli.py +++ b/tests/functional2/flakes/test_cli.py @@ -290,6 +290,82 @@ class TestRegistry: @pytest.mark.usefixtures("registry") class TestBuild: + def test_build_attr(self, nix: Nix): + nix.nix(["build", "flake1#foo"]).run().ok() + assert (nix.env.dirs.home / "result/hello").exists() + + def test_build_without_attr_registry(self, nix: Nix): + nix.nix(["build", "flake1"]).run().ok() + assert (nix.env.dirs.home / "result/hello").exists() + + @pytest.mark.parametrize("scheme", ["", "git+file://"]) + def test_build_without_attr_url(self, nix: Nix, flake1: Path, scheme: str): + nix.nix(["build", f"{scheme}{flake1}"]).run().ok() + assert (nix.env.dirs.home / "result/hello").exists() + + @pytest.mark.parametrize("arg", ["--no-registries", "--no-use-registries"]) + def test_pure_build_unlocked_deps_failure(self, nix: Nix, arg: str): + result = nix.nix(["build", "flake2#bar", arg]).run().expect(1).stderr_s + assert ( + "error: 'flake:flake2' is an indirect flake reference, but registry lookups are not allowed" + in result + ) + + def test_impure_build_unlocked_deps_fails(self, nix: Nix): + result = nix.nix(["build", "flake2#bar", "--impure"]).run().expect(1).stderr_s + assert "error: cannot write modified lock file" in result + + def test_impure_build_unlocked_deps_succeeds_with_no_write(self, nix: Nix): + logs = ( + nix.nix(["build", "flake2#bar", "--impure", "--no-write-lock-file"]).run().ok().stderr_s + ) + assert re.search(r"building '.*-simple.drv'", logs) + + def test_build_unlocked_fails_with_no_update(self, nix: Nix, flake2: Path): + logs = nix.nix(["build", f"{flake2}#bar", "--no-update-lock-file"]).run().expect(1).stderr_s + assert "requires lock file changes" in logs + + def test_build_unlocked_succeeds_with_no_write(self, nix: Nix): + logs = nix.nix(["build", "flake2#bar", "--no-write-lock-file"]).run().ok().stderr_s + assert re.search(r"building '.*-simple.drv'", logs) + + class TestLockedFlake2: + @pytest.fixture(autouse=True) + def lock_flake2(self, nix: Nix, flake2: Path, registry: Path): # noqa: ARG002 + nix.nix(["flake", "lock", flake2, "--commit-lock-file"]).run().ok() + + def test_setup_did_commit(self, flake2: Path, git: Git): + assert (flake2 / "flake.lock").exists() + assert not git(flake2, "diff", "HEAD").stdout_s + + def test_rerunning_builds_does_not_change_lockfile(self, nix: Nix, flake2: Path, git: Git): + nix.nix(["build", f"{flake2}#bar", "--no-write-lock-file"]).run().ok() + assert not git(flake2, "diff", "HEAD").stdout_s + + @pytest.mark.parametrize( + "args", + [ + ["--flake-registry", "file:///no-registry.json", "--refresh"], + ["--no-registries", "--refresh"], + ["--no-use-registries", "--refresh"], + [], + ], + ) + @pytest.mark.parametrize("scheme", ["", "git+file://"]) + def test_locked_build_works(self, nix: Nix, flake2: Path, args: list[str], scheme: str): + # registry fetches are not logged anywhere! + nix.nix(["build", *args, f"{scheme}{flake2}#bar"]).run().ok() + + def test_lock_idempotent(self, nix: Nix, flake2: Path, git: Git): + nix.nix(["flake", "lock", flake2]).run().ok() + assert not git(flake2, "diff", "HEAD").stdout_s + + def test_indirect_dependencies(self, nix: Nix, flake3: Path): + logs = nix.nix(["build", f"{flake3}#xyzzy"]).run().ok().stderr_s + assert "Added input 'flake2'" in logs + assert "Added input 'flake2/flake1'" in logs + assert re.search(r"building '.*-simple.drv'", logs) + def test_bare_repo(self, nix: Nix, flake1: Path, git: Git): git(None, "clone", "--bare", flake1, "bare") logs = nix.nix(["build", f"git+file://{nix.env.dirs.home}/bare"]).run().ok().stderr_s