1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 10:11:47 +02:00

Tagging release 2.27.1

-----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCAAxFiEEtUHVUwEnDgvPFcpdgXC0cm1xmN4FAmfheacTHGVkb2xzdHJh
 QGdtYWlsLmNvbQAKCRCBcLRybXGY3kt2B/4tQvs6iDXA12d409ClHbVQjr1d0FLP
 rv8RxZ7Z4+Jaw8r2ra/I+gpr9juI5ULyEJWqfES72hTvbYPjH1Grsrrjak1tx57E
 +STs21oEPojE8LXsFH1oZamGPPIIpyQdxCvTgZs1N6cqUfCRQ3Jx97X6E6SIGJDR
 VqBM4ruSXCY57yT36HqwYydTkxzZHiNP5wwABGfSb7u9pYW5x3r8W7+fQ3udTnCw
 kCRhA5vnfxIQSlxu4j7dJqSCGzOIPnhYB19bXDV4aPhl4sn3pkBCdMZxPBlCWSwx
 it0ngMITf+TeiMpVl2TtvMBOHtlGrbhusbyKcsqzFYULGyGOC9ngTAY3
 =/JzB
 -----END PGP SIGNATURE-----

Merge tag '2.27.1' into detsys-main

Tagging release 2.27.1
This commit is contained in:
Eelco Dolstra 2025-03-24 21:28:03 +01:00
commit dab0ff4f9e
200 changed files with 4734 additions and 1977 deletions

View file

@ -16,7 +16,7 @@ in
{
seed ? 0,
}:
# A simple content-addressed derivation.
# A simple content-addressing derivation.
# The derivation can be arbitrarily modified by passing a different `seed`,
# but the output will always be the same
rec {

View file

@ -12,7 +12,7 @@ drvPath2=$(nix derivation add < "$TEST_HOME"/simple.json)
[[ "$drvPath" = "$drvPath2" ]]
# Content-addressed derivations can be renamed.
# Content-addressing derivations can be renamed.
jq '.name = "foo"' < "$TEST_HOME"/simple.json > "$TEST_HOME"/foo.json
drvPath3=$(nix derivation add --dry-run < "$TEST_HOME"/foo.json)
# With --dry-run nothing is actually written

View file

@ -1,5 +1,7 @@
# shellcheck shell=bash
badTestNames=()
# Golden test support
#
# Test that the output of the given test matches what is expected. If
@ -18,10 +20,11 @@ function diffAndAcceptInner() {
fi
# Diff so we get a nice message
if ! diff --color=always --unified "$expectedOrEmpty" "$got"; then
echo "FAIL: evaluation result of $testName not as expected"
if ! diff >&2 --color=always --unified "$expectedOrEmpty" "$got"; then
echo >&2 "FAIL: evaluation result of $testName not as expected"
# shellcheck disable=SC2034
badDiff=1
badTestNames+=("$testName")
fi
# Update expected if `_NIX_TEST_ACCEPT` is non-empty.
@ -42,14 +45,14 @@ function characterisationTestExit() {
if test -n "${_NIX_TEST_ACCEPT-}"; then
if (( "$badDiff" )); then
set +x
echo 'Output did mot match, but accepted output as the persisted expected output.'
echo 'That means the next time the tests are run, they should pass.'
echo >&2 'Output did mot match, but accepted output as the persisted expected output.'
echo >&2 'That means the next time the tests are run, they should pass.'
set -x
else
set +x
echo 'NOTE: Environment variable _NIX_TEST_ACCEPT is defined,'
echo 'indicating the unexpected output should be accepted as the expected output going forward,'
echo 'but no tests had unexpected output so there was no expected output to update.'
echo >&2 'NOTE: Environment variable _NIX_TEST_ACCEPT is defined,'
echo >&2 'indicating the unexpected output should be accepted as the expected output going forward,'
echo >&2 'but no tests had unexpected output so there was no expected output to update.'
set -x
fi
if (( "$badExitCode" )); then
@ -60,16 +63,21 @@ function characterisationTestExit() {
else
if (( "$badDiff" )); then
set +x
echo ''
echo 'You can rerun this test with:'
echo ''
echo " _NIX_TEST_ACCEPT=1 make tests/functional/${TEST_NAME}.sh.test"
echo ''
echo 'to regenerate the files containing the expected output,'
echo 'and then view the git diff to decide whether a change is'
echo 'good/intentional or bad/unintentional.'
echo 'If the diff contains arbitrary or impure information,'
echo 'please improve the normalization that the test applies to the output.'
echo >&2 ''
echo >&2 'The following tests had unexpected output:'
for testName in "${badTestNames[@]}"; do
echo >&2 " $testName"
done
echo >&2 ''
echo >&2 'You can rerun this test with:'
echo >&2 ''
echo >&2 " _NIX_TEST_ACCEPT=1 meson test ${TEST_NAME}"
echo >&2 ''
echo >&2 'to regenerate the files containing the expected output,'
echo >&2 'and then view the git diff to decide whether a change is'
echo >&2 'good/intentional or bad/unintentional.'
echo >&2 'If the diff contains arbitrary or impure information,'
echo >&2 'please improve the normalization that the test applies to the output.'
set -x
fi
exit $(( "$badExitCode" + "$badDiff" ))

View file

@ -2,6 +2,28 @@
source common.sh
# Regression test for #11503.
mkdir -p "$TEST_ROOT/directory"
cat > "$TEST_ROOT/directory/default.nix" <<EOF
let
root = ./.;
filter = path: type:
let
rootStr = builtins.toString ./.;
in
if builtins.substring 0 (builtins.stringLength rootStr) (builtins.toString path) == rootStr then true
else builtins.throw "root path\n\${rootStr}\nnot prefix of path\n\${builtins.toString path}";
in
builtins.filterSource filter root
EOF
result="$(nix-store --add-fixed --recursive sha256 "$TEST_ROOT/directory")"
nix-instantiate --eval "$result"
nix-instantiate --eval "$result" --store "$TEST_ROOT/2nd-store"
nix-store --add-fixed --recursive sha256 "$TEST_ROOT/directory" --store "$TEST_ROOT/2nd-store"
nix-instantiate --eval "$result" --store "$TEST_ROOT/2nd-store"
# Misc tests.
echo example > "$TEST_ROOT"/example.txt
mkdir -p "$TEST_ROOT/x"

View file

@ -0,0 +1,16 @@
#!/usr/bin/env bash
source common.sh
# Store layer needs bugfix
requireDaemonNewerThan "2.27pre20250205"
TODO_NixOS # can't enable a sandbox feature easily
enableFeatures 'recursive-nix'
restartDaemon
NIX_BIN_DIR="$(dirname "$(type -p nix)")"
export NIX_BIN_DIR
expectStderr 1 nix build -L --file ./non-trivial.nix --no-link | grepQuiet "Building dynamic derivations in one shot is not yet implemented"

View file

@ -0,0 +1,14 @@
#!/usr/bin/env bash
source common.sh
# Store layer needs bugfix
requireDaemonNewerThan "2.27pre20250205"
skipTest "dyn drv input scheduling had to be reverted for 2.27"
expected=100
if [[ -v NIX_DAEMON_PACKAGE ]]; then expected=1; fi # work around the daemon not returning a 100 status correctly
expectStderr "$expected" nix-build ./text-hashed-output.nix -A failingWrapper --no-out-link \
| grepQuiet "build of '.*use-dynamic-drv-in-non-dynamic-drv-wrong.drv' failed"

View file

@ -12,8 +12,10 @@ suites += {
'recursive-mod-json.sh',
'build-built-drv.sh',
'eval-outputOf.sh',
'failing-outer.sh',
'dep-built-drv.sh',
'old-daemon-error-hack.sh',
'dep-built-drv-2.sh',
],
'workdir': meson.current_source_dir(),
}

View file

@ -0,0 +1,77 @@
with import ./config.nix;
builtins.outputOf
(mkDerivation {
name = "make-derivations.drv";
requiredSystemFeatures = [ "recursive-nix" ];
buildCommand = ''
set -e
set -u
PATH=${builtins.getEnv "NIX_BIN_DIR"}:$PATH
export NIX_CONFIG='extra-experimental-features = nix-command ca-derivations dynamic-derivations'
declare -A deps=(
[a]=""
[b]="a"
[c]="a"
[d]="b c"
[e]="b c d"
)
# Cannot just literally include this, or Nix will think it is the
# *outer* derivation that's trying to refer to itself, and
# substitute the string too soon.
placeholder=$(nix eval --raw --expr 'builtins.placeholder "out"')
declare -A drvs=()
for word in a b c d e; do
inputDrvs=""
for dep in ''${deps[$word]}; do
if [[ "$inputDrvs" != "" ]]; then
inputDrvs+=","
fi
read -r -d "" line <<EOF || true
"''${drvs[$dep]}": {
"outputs": ["out"],
"dynamicOutputs": {}
}
EOF
inputDrvs+="$line"
done
read -r -d "" json <<EOF || true
{
"args": ["-c", "set -xeu; echo \"word env vav $word is \$$word\" >> \"\$out\""],
"builder": "${shell}",
"env": {
"out": "$placeholder",
"$word": "hello, from $word!",
"PATH": ${builtins.toJSON path}
},
"inputDrvs": {
$inputDrvs
},
"inputSrcs": [],
"name": "build-$word",
"outputs": {
"out": {
"method": "nar",
"hashAlgo": "sha256"
}
},
"system": "${system}"
}
EOF
drvs[$word]="$(echo "$json" | nix derivation add)"
done
cp "''${drvs[e]}" $out
'';
__contentAddressed = true;
outputHashMode = "text";
outputHashAlgo = "sha256";
}).outPath
"out"

View file

@ -1,6 +1,6 @@
with import ./config.nix;
# A simple content-addressed derivation.
# A simple content-addressing derivation.
# The derivation can be arbitrarily modified by passing a different `seed`,
# but the output will always be the same
rec {

View file

@ -1,6 +1,6 @@
with import ./config.nix;
# A simple content-addressed derivation.
# A simple content-addressing derivation.
# The derivation can be arbitrarily modified by passing a different `seed`,
# but the output will always be the same
rec {
@ -13,6 +13,7 @@ rec {
echo "Hello World" > $out/hello
'';
};
producingDrv = mkDerivation {
name = "hello.drv";
buildCommand = ''
@ -23,6 +24,7 @@ rec {
outputHashMode = "text";
outputHashAlgo = "sha256";
};
wrapper = mkDerivation {
name = "use-dynamic-drv-in-non-dynamic-drv";
buildCommand = ''
@ -30,4 +32,12 @@ rec {
cp -r ${builtins.outputOf producingDrv.outPath "out"} $out
'';
};
failingWrapper = mkDerivation {
name = "use-dynamic-drv-in-non-dynamic-drv-wrong";
buildCommand = ''
echo "Fail at copying the output of the dynamic derivation"
fail ${builtins.outputOf producingDrv.outPath "out"} $out
'';
};
}

View file

@ -65,7 +65,7 @@ git -C $repo add differentbranch
git -C $repo commit -m 'Test2'
git -C $repo checkout master
devrev=$(git -C $repo rev-parse devtest)
nix eval --impure --raw --expr "builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; }"
nix eval --raw --expr "builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; }"
[[ $(nix eval --raw --expr "builtins.readFile (builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; allRefs = true; } + \"/differentbranch\")") = 'different file' ]]
@ -80,7 +80,7 @@ path2=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"
# In pure eval mode, fetchGit with a revision should succeed.
[[ $(nix eval --raw --expr "builtins.readFile (fetchGit { url = file://$repo; rev = \"$rev2\"; } + \"/hello\")") = world ]]
# But without a hash, it fails
# But without a hash, it fails.
expectStderr 1 nix eval --expr 'builtins.fetchGit "file:///foo"' | grepQuiet "'fetchGit' will not fetch unlocked input"
# Fetch again. This should be cached.
@ -142,13 +142,17 @@ path4=$(nix eval --impure --refresh --raw --expr "(builtins.fetchGit file://$rep
[[ $(nix eval --impure --expr "builtins.hasAttr \"dirtyRev\" (builtins.fetchGit $repo)") == "false" ]]
[[ $(nix eval --impure --expr "builtins.hasAttr \"dirtyShortRev\" (builtins.fetchGit $repo)") == "false" ]]
status=0
nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-B5yIPHhEm0eysJKEsO7nqxprh9vcblFxpJG11gXJus1=\"; }).outPath" || status=$?
[[ "$status" = "102" ]]
expect 102 nix eval --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-B5yIPHhEm0eysJKEsO7nqxprh9vcblFxpJG11gXJus1=\"; }).outPath"
path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-Hr8g6AqANb3xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath")
path5=$(nix eval --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-Hr8g6AqANb3xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath")
[[ $path = $path5 ]]
# Ensure that NAR hashes are checked.
expectStderr 102 nix eval --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-Hr8g6AqANb4xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath" | grepQuiet "error: NAR hash mismatch"
# It's allowed to use only a narHash, but you should get a warning.
expectStderr 0 nix eval --raw --expr "(builtins.fetchGit { url = $repo; ref = \"tag2\"; narHash = \"sha256-Hr8g6AqANb3xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath" | grepQuiet "warning: Input .* is unlocked"
# tarball-ttl should be ignored if we specify a rev
echo delft > $repo/hello
git -C $repo add hello
@ -256,7 +260,7 @@ echo "/exported-wonky export-ignore=wonk" >> $repo/.gitattributes
git -C $repo add not-exported-file exported-wonky .gitattributes
git -C $repo commit -m 'Bla6'
rev5=$(git -C $repo rev-parse HEAD)
path12=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev5\"; }).outPath")
path12=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev5\"; }).outPath")
[[ ! -e $path12/not-exported-file ]]
[[ -e $path12/exported-wonky ]]

View file

@ -72,4 +72,7 @@ rec {
# Can use "nar" instead of "recursive" now.
nar-not-recursive = f2 "foo" ./fixed.builder2.sh "nar" "md5" "3670af73070fa14077ad74e0f5ea4e42";
# Experimental feature
git = f2 "foo" ./fixed.builder2.sh "git" "sha1" "cd44baf36915d5dec8374232ea7e2057f3b4494e";
}

View file

@ -0,0 +1,28 @@
#!/usr/bin/env bash
source ./common.sh
requireGit
flakeDir="$TEST_ROOT/flake"
createGitRepo "$flakeDir"
cat >"$flakeDir/flake.nix" <<EOF
{
inputs = {
};
outputs =
_:
let
in
{
packages.$system.default = throw "oh no";
};
}
EOF
git -C "$flakeDir" add flake.nix
# regression #12527 and #11286
echo ":env" | expect 1 nix eval "$flakeDir#packages.${system}.default" --debugger

View file

@ -22,6 +22,11 @@ cat >"$flake1Dir/flake.nix" <<EOF
echo true > \$out
'';
};
stack-depth =
let
f = x: if x == 0 then true else f (x - 1);
in
assert (f 100); self.drv;
ifd = assert (import self.drv); self.drv;
};
}
@ -33,6 +38,12 @@ git -C "$flake1Dir" commit -m "Init"
expect 1 nix build "$flake1Dir#foo.bar" 2>&1 | grepQuiet 'error: breaks'
expect 1 nix build "$flake1Dir#foo.bar" 2>&1 | grepQuiet 'error: breaks'
# Stack overflow error must not be cached
expect 1 nix build --max-call-depth 50 "$flake1Dir#stack-depth" 2>&1 \
| grepQuiet 'error: stack overflow; max-call-depth exceeded'
# If the SO is cached, the following invocation will produce a cached failure; we expect it to succeed
nix build --no-link "$flake1Dir#stack-depth"
# Conditional error should not be cached
expect 1 nix build "$flake1Dir#ifd" --option allow-import-from-derivation false 2>&1 \
| grepQuiet 'error: cannot build .* during evaluation because the option '\''allow-import-from-derivation'\'' is disabled'

View file

@ -27,6 +27,7 @@ git config --global protocol.file.allow always
rootRepo=$TEST_ROOT/rootRepo
subRepo=$TEST_ROOT/submodule
otherRepo=$TEST_ROOT/otherRepo
createGitRepo "$subRepo"
@ -74,9 +75,50 @@ EOF
git -C "$rootRepo" add flake.nix
git -C "$rootRepo" commit -m "Add flake.nix"
storePath=$(nix flake metadata --json "$rootRepo?submodules=1" | jq -r .path)
storePath=$(nix flake prefetch --json "$rootRepo?submodules=1" | jq -r .storePath)
[[ -e "$storePath/submodule" ]]
# Test the use of inputs.self.
cat > "$rootRepo"/flake.nix <<EOF
{
inputs.self.submodules = true;
outputs = { self }: {
foo = self.outPath;
};
}
EOF
git -C "$rootRepo" commit -a -m "Bla"
storePath=$(nix eval --raw "$rootRepo#foo")
[[ -e "$storePath/submodule" ]]
# Test another repo referring to a repo that uses inputs.self.
createGitRepo "$otherRepo"
cat > "$otherRepo"/flake.nix <<EOF
{
inputs.root.url = "git+file://$rootRepo";
outputs = { self, root }: {
foo = root.foo;
};
}
EOF
git -C "$otherRepo" add flake.nix
# The first call should refetch the root repo...
expectStderr 0 nix eval --raw "$otherRepo#foo" -vvvvv | grepQuiet "refetching"
[[ $(jq .nodes.root_2.locked.submodules "$otherRepo/flake.lock") == true ]]
# ... but the second call should have 'submodules = true' in flake.lock, so it should not refetch.
rm -rf "$TEST_HOME/.cache"
clearStore
expectStderr 0 nix eval --raw "$otherRepo#foo" -vvvvv | grepQuietInverse "refetching"
storePath=$(nix eval --raw "$otherRepo#foo")
[[ -e "$storePath/submodule" ]]
# The root repo may use the submodule repo as an input
# through the relative path. This may change in the future;
# see: https://discourse.nixos.org/t/57783 and #9708.

View file

@ -28,6 +28,8 @@ suites += {
'commit-lock-file-summary.sh',
'non-flake-inputs.sh',
'relative-paths.sh',
'symlink-paths.sh',
'debugger.sh'
],
'workdir': meson.current_source_dir(),
}

View file

@ -84,10 +84,10 @@ json=$(nix flake archive --json "$rootFlake" --to "$TEST_ROOT/store2")
[[ $(echo "$json" | jq .inputs.sub0.inputs) = {} ]]
[[ -n $(echo "$json" | jq .path) ]]
#nix flake prefetch --out-link "$TEST_ROOT/result" "$rootFlake"
#outPath=$(readlink "$TEST_ROOT/result")
nix flake prefetch --out-link "$TEST_ROOT/result" "$rootFlake"
outPath=$(readlink "$TEST_ROOT/result")
#[ -e "$TEST_ROOT/store2/nix/store/$(basename "$outPath")" ]
[ -e "$TEST_ROOT/store2/nix/store/$(basename "$outPath")" ]
# Test circular relative path flakes. FIXME: doesn't work at the moment.
if false; then

View file

@ -0,0 +1,75 @@
#!/usr/bin/env bash
source ./common.sh
requireGit
create_flake() {
local flakeDir="$1"
createGitRepo "$flakeDir"
cat > "$flakeDir/flake.nix" <<EOF
{
outputs = { self }: { x = 2; };
}
EOF
git -C "$flakeDir" add flake.nix
git -C "$flakeDir" commit -m Initial
}
test_symlink_points_to_flake() {
create_flake "$TEST_ROOT/flake1"
ln -sn "$TEST_ROOT/flake1" "$TEST_ROOT/flake1_sym"
[[ $(nix eval "$TEST_ROOT/flake1_sym#x") = 2 ]]
rm -rf "$TEST_ROOT/flake1" "$TEST_ROOT/flake1_sym"
}
test_symlink_points_to_flake
test_symlink_points_to_flake_in_subdir() {
create_flake "$TEST_ROOT/subdir/flake1"
ln -sn "$TEST_ROOT/subdir" "$TEST_ROOT/subdir_sym"
[[ $(nix eval "$TEST_ROOT/subdir_sym/flake1#x") = 2 ]]
rm -rf "$TEST_ROOT/subdir" "$TEST_ROOT/subdir_sym"
}
test_symlink_points_to_flake_in_subdir
test_symlink_points_to_dir_in_repo() {
local repoDir="$TEST_ROOT/flake1"
createGitRepo "$repoDir"
mkdir -p "$repoDir/subdir"
cat > "$repoDir/subdir/flake.nix" <<EOF
{
outputs = { self }: { x = 2; };
}
EOF
git -C "$repoDir" add subdir/flake.nix
git -C "$repoDir" commit -m Initial
ln -sn "$TEST_ROOT/flake1/subdir" "$TEST_ROOT/flake1_sym"
[[ $(nix eval "$TEST_ROOT/flake1_sym#x") = 2 ]]
rm -rf "$TEST_ROOT/flake1" "$TEST_ROOT/flake1_sym"
}
test_symlink_points_to_dir_in_repo
test_symlink_from_repo_to_another() {
local repoDir="$TEST_ROOT/repo1"
createGitRepo "$repoDir"
echo "Hello" > "$repoDir/file"
mkdir "$repoDir/subdir"
cat > "$repoDir/subdir/flake.nix" <<EOF
{
outputs = { self }: { x = builtins.readFile ../file; };
}
EOF
git -C "$repoDir" add subdir/flake.nix file
git -C "$repoDir" commit -m Initial
[[ $(nix eval "$TEST_ROOT/repo1/subdir#x") == \"Hello\\n\" ]]
local repo2Dir="$TEST_ROOT/repo2"
createGitRepo "$repo2Dir"
ln -sn "$repoDir/subdir" "$repo2Dir/flake1_sym"
echo "World" > "$repo2Dir/file"
git -C "$repo2Dir" add flake1_sym file
git -C "$repo2Dir" commit -m Initial
[[ $(nix eval "$repo2Dir/flake1_sym#x") == \"Hello\\n\" ]]
rm -rf "$TEST_ROOT/repo1" "$TEST_ROOT/repo2"
}
test_symlink_from_repo_to_another

View file

@ -37,8 +37,8 @@ expectStderr 1 nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/f
nix flake lock "$flake2Dir" --override-input flake1 "$TEST_ROOT/flake1" --allow-dirty-locks
# Using a lock file with a dirty lock requires --allow-dirty-locks as well.
expectStderr 1 nix eval "$flake2Dir#x" |
grepQuiet "Lock file contains unlocked input"
# Using a lock file with a dirty lock does not require --allow-dirty-locks, but should print a warning.
expectStderr 0 nix eval "$flake2Dir#x" |
grepQuiet "warning: Lock file entry .* is unlocked"
[[ $(nix eval "$flake2Dir#x" --allow-dirty-locks) = 456 ]]
[[ $(nix eval "$flake2Dir#x") = 456 ]]

View file

@ -0,0 +1,8 @@
#!/usr/bin/env bash
source common.sh
# Store layer needs bugfix
requireDaemonNewerThan "2.27pre20250122"
nix-build ../fixed.nix -A git --no-out-link

View file

@ -3,6 +3,7 @@ suites += {
'deps': [],
'tests': [
'simple.sh',
'fixed.sh',
],
'workdir': meson.current_source_dir(),
}

View file

@ -2,6 +2,31 @@
source common.sh
function subcommands() {
jq -r '
def recurse($prefix):
to_entries[] |
($prefix + [.key]) as $newPrefix |
(if .value | has("commands") then
($newPrefix, (.value.commands | recurse($newPrefix)))
else
$newPrefix
end);
.args.commands | recurse([]) | join(" ")
'
}
nix __dump-cli | subcommands | while IFS= read -r cmd; do
# shellcheck disable=SC2086 # word splitting of cmd is intended
nix $cmd --help
done
[[ $(type -p man) ]] || skipTest "'man' not installed"
# FIXME: we don't know whether we built the manpages, so we can't
# reliably test them here.
skipTest "we don't know whether we built the manpages, so we can't reliably test them here."
# test help output
nix-build --help
@ -49,22 +74,3 @@ nix-daemon --help
nix-hash --help
nix-instantiate --help
nix-prefetch-url --help
function subcommands() {
jq -r '
def recurse($prefix):
to_entries[] |
($prefix + [.key]) as $newPrefix |
(if .value | has("commands") then
($newPrefix, (.value.commands | recurse($newPrefix)))
else
$newPrefix
end);
.args.commands | recurse([]) | join(" ")
'
}
nix __dump-cli | subcommands | while IFS= read -r cmd; do
# shellcheck disable=SC2086 # word splitting of cmd is intended
nix $cmd --help
done

View file

@ -5,4 +5,4 @@ error:
| ^
2| type = "file";
error: negative value given for fetchTree attr owner: -1
error: negative value given for 'fetchTree' argument 'owner': -1

View file

@ -37,7 +37,7 @@ test_confdata = {
# Done as a subdir() so Meson places it under `common` in the build directory as well.
subdir('common')
config_nix_in = configure_file(
configure_file(
input : 'config.nix.in',
output : 'config.nix',
configuration : test_confdata,
@ -243,8 +243,6 @@ foreach suite : suites
# Used for target dependency/ordering tracking, not adding compiler flags or anything.
depends : suite['deps'],
workdir : workdir,
# Won't pass until man pages are generated
should_fail : suite['name'] == 'main' and script == 'help.sh'
)
endforeach
endforeach

View file

@ -68,4 +68,14 @@ nix-env -i dependencies-top
[ -e $TEST_HOME/.nix-profile/foobar ]
# Test evaluation through a channel symlink (#9882).
nix-instantiate '<foo/dependencies.nix>'
drvPath=$(nix-instantiate '<foo/dependencies.nix>')
# Add a test for the special case behaviour of 'nixpkgs' in the
# channels for root (see EvalSettings::getDefaultNixPath()).
if ! isTestOnNixOS; then
nix-channel --add file://$TEST_ROOT/foo nixpkgs
nix-channel --update
mv $TEST_HOME/.local/state/nix/profiles $TEST_ROOT/var/nix/profiles/per-user/root
drvPath2=$(nix-instantiate '<nixpkgs>')
[[ "$drvPath" = "$drvPath2" ]]
fi

View file

@ -73,13 +73,13 @@ test_tarball .gz gzip
# All entries in tree.tar.gz refer to the same file, and all have the same inode when unpacked by GNU tar.
# We don't preserve the hard links, because that's an optimization we think is not worth the complexity,
# so we only make sure that the contents are copied correctly.
path="$(nix flake prefetch --json "tarball+file://$(pwd)/tree.tar.gz" | jq -r .storePath)"
[[ $(cat "$path/a/b/foo") = bar ]]
[[ $(cat "$path/a/b/xyzzy") = bar ]]
[[ $(cat "$path/a/yyy") = bar ]]
[[ $(cat "$path/a/zzz") = bar ]]
[[ $(cat "$path/c/aap") = bar ]]
[[ $(cat "$path/fnord") = bar ]]
nix flake prefetch --json "tarball+file://$(pwd)/tree.tar.gz" --out-link "$TEST_ROOT/result"
[[ $(cat "$TEST_ROOT/result/a/b/foo") = bar ]]
[[ $(cat "$TEST_ROOT/result/a/b/xyzzy") = bar ]]
[[ $(cat "$TEST_ROOT/result/a/yyy") = bar ]]
[[ $(cat "$TEST_ROOT/result/a/zzz") = bar ]]
[[ $(cat "$TEST_ROOT/result/c/aap") = bar ]]
[[ $(cat "$TEST_ROOT/result/fnord") = bar ]]
# Test a tarball that has multiple top-level directories.
rm -rf "$TEST_ROOT/tar_root"

View file

@ -2,7 +2,7 @@
lib,
nixpkgs,
nixpkgsFor,
self,
nixpkgs-23-11,
}:
let
@ -85,7 +85,7 @@ let
{
imports = [ checkOverrideNixVersion ];
nix.package = lib.mkForce (
self.inputs.nixpkgs-23-11.legacyPackages.${pkgs.stdenv.hostPlatform.system}.nixVersions.nix_2_13.overrideAttrs
nixpkgs-23-11.legacyPackages.${pkgs.stdenv.hostPlatform.system}.nixVersions.nix_2_13.overrideAttrs
(o: {
meta = o.meta // {
knownVulnerabilities = [ ];

View file

@ -0,0 +1,228 @@
{
# mostly copied from https://github.com/NixOS/nix/blob/358c26fd13a902d9a4032a00e6683571be07a384/tests/nixos/fetch-git/test-cases/fetchTree-shallow/default.nix#L1
# ty @DavHau
description = "fetchGit smudges LFS pointers if lfs=true";
script = ''
from tempfile import TemporaryDirectory
expected_max_size_lfs_pointer = 1024 # 1 KiB (values >= than this cannot be pointers, and test files are 1 MiB)
# purge nix git cache to make sure we start with a clean slate
client.succeed("rm -rf ~/.cache/nix")
with subtest("Request lfs fetch without any .gitattributes file"):
client.succeed(f"dd if=/dev/urandom of={repo.path}/regular bs=1M count=1 >&2")
client.succeed(f"{repo.git} add : >&2")
client.succeed(f"{repo.git} commit -m 'no .gitattributes' >&2")
client.succeed(f"{repo.git} push origin main >&2")
# memorize the revision
no_gitattributes_rev = client.succeed(f"{repo.git} rev-parse HEAD").strip()
# fetch with lfs=true, and check that the lack of .gitattributes does not break anything
fetchGit_no_gitattributes_expr = f"""
builtins.fetchGit {{
url = "{repo.remote}";
rev = "{no_gitattributes_rev}";
ref = "main";
lfs = true;
}}
"""
fetched_no_gitattributes = client.succeed(f"""
nix eval --debug --impure --raw --expr '({fetchGit_no_gitattributes_expr}).outPath'
""")
client.succeed(f"cmp {repo.path}/regular {fetched_no_gitattributes}/regular >&2")
with subtest("Add a file that should be tracked by lfs, but isn't"):
# (git lfs cli only throws a warning "Encountered 1 file that should have
# been a pointer, but wasn't")
client.succeed(f"dd if=/dev/urandom of={repo.path}/black_sheep bs=1M count=1 >&2")
client.succeed(f"echo 'black_sheep filter=lfs -text' >>{repo.path}/.gitattributes")
client.succeed(f"{repo.git} add : >&2")
client.succeed(f"{repo.git} commit -m 'add misleading file' >&2")
client.succeed(f"{repo.git} push origin main >&2")
# memorize the revision
bad_lfs_rev = client.succeed(f"{repo.git} rev-parse HEAD").strip()
# test assumption that it can be cloned with regular git first
# (here we see the warning as stated above)
with TemporaryDirectory() as tempdir:
client.succeed(f"git clone -n {repo.remote} {tempdir} >&2")
client.succeed(f"git -C {tempdir} lfs install >&2")
client.succeed(f"git -C {tempdir} checkout {bad_lfs_rev} >&2")
# check that the file is not a pointer, as expected
file_size_git = client.succeed(f"stat -c %s {tempdir}/black_sheep").strip()
assert int(file_size_git) == 1024 * 1024, \
f"non lfs file is {file_size_git}b (!= 1MiB), probably a test implementation error"
lfs_files = client.succeed(f"git -C {tempdir} lfs ls-files").strip()
assert lfs_files == "", "non lfs file is tracked by lfs, probably a test implementation error"
client.succeed(f"cmp {repo.path}/black_sheep {tempdir}/black_sheep >&2")
# now fetch without lfs, check that the file is not a pointer
fetchGit_bad_lfs_without_lfs_expr = f"""
builtins.fetchGit {{
url = "{repo.remote}";
rev = "{bad_lfs_rev}";
ref = "main";
lfs = false;
}}
"""
fetched_bad_lfs_without_lfs = client.succeed(f"""
nix eval --debug --impure --raw --expr '({fetchGit_bad_lfs_without_lfs_expr}).outPath'
""")
# check that file was not somehow turned into a pointer
file_size_bad_lfs_without_lfs = client.succeed(f"stat -c %s {fetched_bad_lfs_without_lfs}/black_sheep").strip()
assert int(file_size_bad_lfs_without_lfs) == 1024 * 1024, \
f"non lfs-enrolled file is {file_size_bad_lfs_without_lfs}b (!= 1MiB), probably a test implementation error"
client.succeed(f"cmp {repo.path}/black_sheep {fetched_bad_lfs_without_lfs}/black_sheep >&2")
# finally fetch with lfs=true, and check that the bad file does not break anything
fetchGit_bad_lfs_with_lfs_expr = f"""
builtins.fetchGit {{
url = "{repo.remote}";
rev = "{bad_lfs_rev}";
ref = "main";
lfs = true;
}}
"""
fetchGit_bad_lfs_with_lfs = client.succeed(f"""
nix eval --debug --impure --raw --expr '({fetchGit_bad_lfs_with_lfs_expr}).outPath'
""")
client.succeed(f"cmp {repo.path}/black_sheep {fetchGit_bad_lfs_with_lfs}/black_sheep >&2")
with subtest("Add an lfs-enrolled file to the repo"):
client.succeed(f"dd if=/dev/urandom of={repo.path}/beeg bs=1M count=1 >&2")
client.succeed(f"{repo.git} lfs install >&2")
client.succeed(f"{repo.git} lfs track --filename beeg >&2")
client.succeed(f"{repo.git} add : >&2")
client.succeed(f"{repo.git} commit -m 'add lfs file' >&2")
client.succeed(f"{repo.git} push origin main >&2")
# memorize the revision
lfs_file_rev = client.succeed(f"{repo.git} rev-parse HEAD").strip()
# first fetch without lfs, check that we did not smudge the file
fetchGit_nolfs_expr = f"""
builtins.fetchGit {{
url = "{repo.remote}";
rev = "{lfs_file_rev}";
ref = "main";
lfs = false;
}}
"""
fetched_nolfs = client.succeed(f"""
nix eval --debug --impure --raw --expr '({fetchGit_nolfs_expr}).outPath'
""")
# check that file was not smudged
file_size_nolfs = client.succeed(f"stat -c %s {fetched_nolfs}/beeg").strip()
assert int(file_size_nolfs) < expected_max_size_lfs_pointer, \
f"did not set lfs=true, yet lfs-enrolled file is {file_size_nolfs}b (>= 1KiB), probably smudged when we should not have"
# now fetch with lfs=true and check that the file was smudged
fetchGit_lfs_expr = f"""
builtins.fetchGit {{
url = "{repo.remote}";
rev = "{lfs_file_rev}";
ref = "main";
lfs = true;
}}
"""
fetched_lfs = client.succeed(f"""
nix eval --debug --impure --raw --expr '({fetchGit_lfs_expr}).outPath'
""")
assert fetched_lfs != fetched_nolfs, \
f"fetching with and without lfs yielded the same store path {fetched_lfs}, fingerprinting error?"
# check that file was smudged
file_size_lfs = client.succeed(f"stat -c %s {fetched_lfs}/beeg").strip()
assert int(file_size_lfs) == 1024 * 1024, \
f"set lfs=true, yet lfs-enrolled file is {file_size_lfs}b (!= 1MiB), probably did not smudge when we should have"
with subtest("Check that default is lfs=false"):
fetchGit_default_expr = f"""
builtins.fetchGit {{
url = "{repo.remote}";
rev = "{lfs_file_rev}";
ref = "main";
}}
"""
fetched_default = client.succeed(f"""
nix eval --debug --impure --raw --expr '({fetchGit_default_expr}).outPath'
""")
# check that file was not smudged
file_size_default = client.succeed(f"stat -c %s {fetched_default}/beeg").strip()
assert int(file_size_default) < expected_max_size_lfs_pointer, \
f"did not set lfs, yet lfs-enrolled file is {file_size_default}b (>= 1KiB), probably bad default value"
with subtest("Use as flake input"):
# May seem reduntant, but this has minor differences compared to raw
# fetchGit which caused failures before
with TemporaryDirectory() as tempdir:
client.succeed(f"mkdir -p {tempdir}")
client.succeed(f"""
printf '{{
inputs = {{
foo = {{
url = "git+{repo.remote}?ref=main&rev={lfs_file_rev}&lfs=1";
flake = false;
}};
}};
outputs = {{ foo, self }}: {{ inherit (foo) outPath; }};
}}' >{tempdir}/flake.nix
""")
fetched_flake = client.succeed(f"""
nix eval --debug --raw {tempdir}#.outPath
""")
assert fetched_lfs == fetched_flake, \
f"fetching as flake input (store path {fetched_flake}) yielded a different result than using fetchGit (store path {fetched_lfs})"
with subtest("Check self.lfs"):
client.succeed(f"""
printf '{{
inputs.self.lfs = true;
outputs = {{ self }}: {{ }};
}}' >{repo.path}/flake.nix
""")
client.succeed(f"{repo.git} add : >&2")
client.succeed(f"{repo.git} commit -m 'add flake' >&2")
client.succeed(f"{repo.git} push origin main >&2")
# memorize the revision
self_lfs_rev = client.succeed(f"{repo.git} rev-parse HEAD").strip()
with TemporaryDirectory() as tempdir:
client.succeed(f"mkdir -p {tempdir}")
client.succeed(f"""
printf '{{
inputs.foo = {{
url = "git+{repo.remote}?ref=main&rev={self_lfs_rev}";
}};
outputs = {{ foo, self }}: {{ inherit (foo) outPath; }};
}}' >{tempdir}/flake.nix
""")
fetched_self_lfs = client.succeed(f"""
nix eval --debug --raw {tempdir}#.outPath
""")
client.succeed(f"cmp {repo.path}/beeg {fetched_self_lfs}/beeg >&2")
'';
}

View file

@ -29,9 +29,16 @@ in
{ pkgs, ... }:
{
services.gitea.enable = true;
services.gitea.settings.service.DISABLE_REGISTRATION = true;
services.gitea.settings.log.LEVEL = "Info";
services.gitea.settings.database.LOG_SQL = false;
services.gitea.lfs.enable = true;
services.gitea.settings = {
service.DISABLE_REGISTRATION = true;
server = {
DOMAIN = "gitea";
HTTP_PORT = 3000;
};
log.LEVEL = "Info";
database.LOG_SQL = false;
};
services.openssh.enable = true;
networking.firewall.allowedTCPPorts = [ 3000 ];
environment.systemPackages = [
@ -54,7 +61,10 @@ in
client =
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.git ];
environment.systemPackages = [
pkgs.git
pkgs.git-lfs
];
};
};
defaults =