diff options
| -rw-r--r-- | CHANGELOG.md | 4 | ||||
| -rw-r--r-- | pkgs/populate/default.nix | 15 | ||||
| -rw-r--r-- | tests/scenarios.nix | 9 | ||||
| -rw-r--r-- | tests/vm.nix | 5 |
4 files changed, 27 insertions, 6 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index d71c57e..730a9d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +- Drawing an input from a source that isn't a directory stops populate, + instead of locking the flake with an empty URL, which Nix takes for the + current directory, copying it into the store: on a remote target, the + login directory. - Git can't take a `git` source's `url` or `ref`, or a `pass` source's `name`, for an option. - `git` sources also refuse work trees whose `.git` directory contains diff --git a/pkgs/populate/default.nix b/pkgs/populate/default.nix index 7b22662..163f1de 100644 --- a/pkgs/populate/default.nix +++ b/pkgs/populate/default.nix @@ -383,18 +383,23 @@ let ++ inputChecks from (drop (length parent) path); # Sets the positional parameters to nix flake lock's arguments for # drawing the inputs of the flake in source name from other sources. + # URLs get assigned first, so failing to find one stops the script, + # which a command substitution in an argument wouldn't: Nix would take + # the empty URL for the current directory. overrideArgs = name: /* sh */ '' set -- ${concatMapStrings (x: /* sh */ '' - set -- "$@" --override-input ${quote (concatStringsSep "/" (drawnPath name x.path))} ${url (check name x.source)} + drawn_url=${url (check name x.source)} + set -- "$@" --override-input ${quote (concatStringsSep "/" (drawnPath name x.path))} "$drawn_url" '') (flakeFollows sources.${name})} ''; # Rewrites the lock file of the flake in a file or git source in place. rewrite = name: /* sh */ '' ( ${overrideArgs name} + own_url=$(flake_url ${quote name}) own_lock "$(readlink -f ${quote "${target.path}/${name}"})" - nix flake lock "$@" "$(flake_url ${quote name})" >&2 + nix flake lock "$@" "$own_url" >&2 ) ''; # Derives what the target path of a flake or flake-input source gets from @@ -489,8 +494,9 @@ let fi ${optionalString rewriteLock /* sh */ '' ${overrideArgs name} + own_url=$(flake_url ${quote name}) own_lock ${quote targetPath} - nix flake lock "$@" "$(flake_url ${quote name})" >&2 + nix flake lock "$@" "$own_url" >&2 ''} '' else /* sh */ '' if test -e ${quote "${dir}/key"} && @@ -674,8 +680,9 @@ let ${concatMapStrings (x: /* sh */ '' set -- "$@" --override-input ${quote (concatStringsSep "/" x.path)} "path:$locks_dir" '') follows} + own_url=$(own_flake_url ${quote name}) if ! nix flake metadata --json --no-write-lock-file "$@" \ - "$(own_flake_url ${quote name})" > "$locks_dir"/${quote name}.json; then + "$own_url" > "$locks_dir"/${quote name}.json; then >&2 printf 'error: source %s draws inputs from other sources, but its flake can'"'"'t be locked\n' \ ${quote name} exit 1 diff --git a/tests/scenarios.nix b/tests/scenarios.nix index 43b63b4..e01c5a9 100644 --- a/tests/scenarios.nix +++ b/tests/scenarios.nix @@ -109,10 +109,12 @@ let # evaluation fail. env sets environment variables for populate, as # arguments of env. interrupt ends populate after that many seconds, # which it's expected not to finish before. output lists what a - # succeeding populate is expected to print. + # succeeding populate is expected to print, and unexpected what populate + # is expected not to print, succeeding or not. phase = { sources, backup ? false, prune ? false, deploy ? null, targetPath ? path, env ? "", interrupt ? null, output ? [], + unexpected ? [], expect ? "success", control ? null, controlTargetPath ? null, check ? "", mutate ? null, checkDeployer ? null, mutateDeployer ? null, }: let @@ -147,7 +149,7 @@ let null else { populate = toString (command sources targetPath); - inherit env interrupt output; + inherit env interrupt output unexpected; expect = if expect == "success" then null else expect.fail; # No phase gets around checking the canaries. check = script (check + "\ncanary_check\n"); @@ -1258,6 +1260,9 @@ assert !(krops.isLocalTarget (targets.remote "/")); p.pipe = "/fixtures/pipe"; }; expect.fail = "error: source p is not a directory"; + # Locking the flake with an empty URL would lock the current + # directory, the login directory on a remote target. + unexpected = [ "while fetching the input" ]; }]; }) (s "noinput-nested" { diff --git a/tests/vm.nix b/tests/vm.nix index d7b2f60..7c362f5 100644 --- a/tests/vm.nix +++ b/tests/vm.nix @@ -158,6 +158,11 @@ in pkgs.testers.runNixOSTest { f"env HOME=/root {phase['env']} timeout {limit} {phase['populate']} </dev/null 2>&1", timeout=900, ) + for unexpected in phase["unexpected"]: + if unexpected in out: + raise Exception( + f"populate {i} prints {unexpected!r}:\n{out}" + ) if phase["interrupt"] is not None: if status != 124: raise Exception(f"populate {i} ends on its own:\n{out}") |
