mirror of
https://github.com/NixOS/nix
synced 2025-07-07 01:51:47 +02:00
Merge branch '2.19-maintenance' into ifd-buildStore-2.19
This commit is contained in:
commit
2e4239f9e3
1101 changed files with 16483 additions and 8593 deletions
45
tests/functional/add.sh
Normal file
45
tests/functional/add.sh
Normal file
|
@ -0,0 +1,45 @@
|
|||
source common.sh
|
||||
|
||||
path1=$(nix-store --add ./dummy)
|
||||
echo $path1
|
||||
|
||||
path2=$(nix-store --add-fixed sha256 --recursive ./dummy)
|
||||
echo $path2
|
||||
|
||||
if test "$path1" != "$path2"; then
|
||||
echo "nix-store --add and --add-fixed mismatch"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
path3=$(nix-store --add-fixed sha256 ./dummy)
|
||||
echo $path3
|
||||
test "$path1" != "$path3" || exit 1
|
||||
|
||||
path4=$(nix-store --add-fixed sha1 --recursive ./dummy)
|
||||
echo $path4
|
||||
test "$path1" != "$path4" || exit 1
|
||||
|
||||
hash1=$(nix-store -q --hash $path1)
|
||||
echo $hash1
|
||||
|
||||
hash2=$(nix-hash --type sha256 --base32 ./dummy)
|
||||
echo $hash2
|
||||
|
||||
test "$hash1" = "sha256:$hash2"
|
||||
|
||||
#### New style commands
|
||||
|
||||
clearStore
|
||||
|
||||
(
|
||||
path1=$(nix store add ./dummy)
|
||||
path2=$(nix store add --mode nar ./dummy)
|
||||
path3=$(nix store add-path ./dummy)
|
||||
[[ "$path1" == "$path2" ]]
|
||||
[[ "$path1" == "$path3" ]]
|
||||
)
|
||||
(
|
||||
path1=$(nix store add --mode flat ./dummy)
|
||||
path2=$(nix store add-file ./dummy)
|
||||
[[ "$path1" == "$path2" ]]
|
||||
)
|
BIN
tests/functional/bad.tar.xz
Normal file
BIN
tests/functional/bad.tar.xz
Normal file
Binary file not shown.
9
tests/functional/bash-profile.sh
Normal file
9
tests/functional/bash-profile.sh
Normal file
|
@ -0,0 +1,9 @@
|
|||
source common.sh
|
||||
|
||||
sed -e "s|@localstatedir@|$TEST_ROOT/profile-var|g" -e "s|@coreutils@|$coreutils|g" < ../../scripts/nix-profile.sh.in > $TEST_ROOT/nix-profile.sh
|
||||
|
||||
user=$(whoami)
|
||||
rm -rf $TEST_HOME $TEST_ROOT/profile-var
|
||||
mkdir -p $TEST_HOME
|
||||
USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh; set"
|
||||
USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh" # test idempotency
|
13
tests/functional/big-derivation-attr.nix
Normal file
13
tests/functional/big-derivation-attr.nix
Normal file
|
@ -0,0 +1,13 @@
|
|||
let
|
||||
sixteenBytes = "0123456789abcdef";
|
||||
times16 = s: builtins.concatStringsSep "" [s s s s s s s s s s s s s s s s];
|
||||
exp = n: x: if n == 1 then x else times16 (exp (n - 1) x);
|
||||
sixteenMegabyte = exp 6 sixteenBytes;
|
||||
in
|
||||
assert builtins.stringLength sixteenMegabyte == 16777216;
|
||||
derivation {
|
||||
name = "big-derivation-attr";
|
||||
builder = "/x";
|
||||
system = "y";
|
||||
bigAttr = sixteenMegabyte;
|
||||
}
|
16
tests/functional/binary-cache-build-remote.sh
Normal file
16
tests/functional/binary-cache-build-remote.sh
Normal file
|
@ -0,0 +1,16 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
clearCacheCache
|
||||
|
||||
# Fails without remote builders
|
||||
(! nix-build --store "file://$cacheDir" dependencies.nix)
|
||||
|
||||
# Succeeds with default store as build remote.
|
||||
outPath=$(nix-build --store "file://$cacheDir" --builders 'auto - - 1 1' -j0 dependencies.nix)
|
||||
|
||||
# Test that the path exactly exists in the destination store.
|
||||
nix path-info --store "file://$cacheDir" $outPath
|
||||
|
||||
# Succeeds without any build capability because no-op
|
||||
nix-build --store "file://$cacheDir" -j0 dependencies.nix
|
286
tests/functional/binary-cache.sh
Normal file
286
tests/functional/binary-cache.sh
Normal file
|
@ -0,0 +1,286 @@
|
|||
source common.sh
|
||||
|
||||
needLocalStore "'--no-require-sigs' can’t be used with the daemon"
|
||||
|
||||
# We can produce drvs directly into the binary cache
|
||||
clearStore
|
||||
clearCacheCache
|
||||
nix-instantiate --store "file://$cacheDir" dependencies.nix
|
||||
|
||||
# Create the binary cache.
|
||||
clearStore
|
||||
clearCache
|
||||
outPath=$(nix-build dependencies.nix --no-out-link)
|
||||
|
||||
nix copy --to file://$cacheDir $outPath
|
||||
|
||||
# Test copying build logs to the binary cache.
|
||||
expect 1 nix log --store file://$cacheDir $outPath 2>&1 | grep 'is not available'
|
||||
nix store copy-log --to file://$cacheDir $outPath
|
||||
nix log --store file://$cacheDir $outPath | grep FOO
|
||||
rm -rf $TEST_ROOT/var/log/nix
|
||||
expect 1 nix log $outPath 2>&1 | grep 'is not available'
|
||||
nix log --substituters file://$cacheDir $outPath | grep FOO
|
||||
|
||||
# Test copying build logs from the binary cache.
|
||||
nix store copy-log --from file://$cacheDir $(nix-store -qd $outPath)^'*'
|
||||
nix log $outPath | grep FOO
|
||||
|
||||
basicDownloadTests() {
|
||||
# No uploading tests bcause upload with force HTTP doesn't work.
|
||||
|
||||
# By default, a binary cache doesn't support "nix-env -qas", but does
|
||||
# support installation.
|
||||
clearStore
|
||||
clearCacheCache
|
||||
|
||||
nix-env --substituters "file://$cacheDir" -f dependencies.nix -qas \* | grep -- "---"
|
||||
|
||||
nix-store --substituters "file://$cacheDir" --no-require-sigs -r $outPath
|
||||
|
||||
[ -x $outPath/program ]
|
||||
|
||||
|
||||
# But with the right configuration, "nix-env -qas" should also work.
|
||||
clearStore
|
||||
clearCacheCache
|
||||
echo "WantMassQuery: 1" >> $cacheDir/nix-cache-info
|
||||
|
||||
nix-env --substituters "file://$cacheDir" -f dependencies.nix -qas \* | grep -- "--S"
|
||||
nix-env --substituters "file://$cacheDir" -f dependencies.nix -qas \* | grep -- "--S"
|
||||
|
||||
x=$(nix-env -f dependencies.nix -qas \* --prebuilt-only)
|
||||
[ -z "$x" ]
|
||||
|
||||
nix-store --substituters "file://$cacheDir" --no-require-sigs -r $outPath
|
||||
|
||||
nix-store --check-validity $outPath
|
||||
nix-store -qR $outPath | grep input-2
|
||||
|
||||
echo "WantMassQuery: 0" >> $cacheDir/nix-cache-info
|
||||
}
|
||||
|
||||
|
||||
# Test LocalBinaryCacheStore.
|
||||
basicDownloadTests
|
||||
|
||||
|
||||
# Test HttpBinaryCacheStore.
|
||||
export _NIX_FORCE_HTTP=1
|
||||
basicDownloadTests
|
||||
|
||||
|
||||
# Test whether Nix notices if the NAR doesn't match the hash in the NAR info.
|
||||
clearStore
|
||||
|
||||
nar=$(ls $cacheDir/nar/*.nar.xz | head -n1)
|
||||
mv $nar $nar.good
|
||||
mkdir -p $TEST_ROOT/empty
|
||||
nix-store --dump $TEST_ROOT/empty | xz > $nar
|
||||
|
||||
expect 1 nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log
|
||||
grepQuiet "hash mismatch" $TEST_ROOT/log
|
||||
|
||||
mv $nar.good $nar
|
||||
|
||||
|
||||
# Test whether this unsigned cache is rejected if the user requires signed caches.
|
||||
clearStore
|
||||
clearCacheCache
|
||||
|
||||
if nix-store --substituters "file://$cacheDir" -r $outPath; then
|
||||
echo "unsigned binary cache incorrectly accepted"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Test whether fallback works if a NAR has disappeared. This does not require --fallback.
|
||||
clearStore
|
||||
|
||||
mv $cacheDir/nar $cacheDir/nar2
|
||||
|
||||
nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result
|
||||
|
||||
mv $cacheDir/nar2 $cacheDir/nar
|
||||
|
||||
|
||||
# Test whether fallback works if a NAR is corrupted. This does require --fallback.
|
||||
clearStore
|
||||
|
||||
mv $cacheDir/nar $cacheDir/nar2
|
||||
mkdir $cacheDir/nar
|
||||
for i in $(cd $cacheDir/nar2 && echo *); do touch $cacheDir/nar/$i; done
|
||||
|
||||
(! nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result)
|
||||
|
||||
nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result --fallback
|
||||
|
||||
rm -rf $cacheDir/nar
|
||||
mv $cacheDir/nar2 $cacheDir/nar
|
||||
|
||||
|
||||
# Test whether building works if the binary cache contains an
|
||||
# incomplete closure.
|
||||
clearStore
|
||||
|
||||
rm -v $(grep -l "StorePath:.*dependencies-input-2" $cacheDir/*.narinfo)
|
||||
|
||||
nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log
|
||||
grepQuiet "copying path.*input-0" $TEST_ROOT/log
|
||||
grepQuiet "copying path.*input-2" $TEST_ROOT/log
|
||||
grepQuiet "copying path.*top" $TEST_ROOT/log
|
||||
|
||||
|
||||
# Idem, but without cached .narinfo.
|
||||
clearStore
|
||||
clearCacheCache
|
||||
|
||||
nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log
|
||||
grepQuiet "don't know how to build" $TEST_ROOT/log
|
||||
grepQuiet "building.*input-1" $TEST_ROOT/log
|
||||
grepQuiet "building.*input-2" $TEST_ROOT/log
|
||||
grepQuiet "copying path.*input-0" $TEST_ROOT/log
|
||||
grepQuiet "copying path.*top" $TEST_ROOT/log
|
||||
|
||||
|
||||
# Create a signed binary cache.
|
||||
clearCache
|
||||
clearCacheCache
|
||||
|
||||
nix key generate-secret --key-name test.nixos.org-1 > $TEST_ROOT/sk1
|
||||
publicKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk1)
|
||||
|
||||
nix key generate-secret --key-name test.nixos.org-1 > $TEST_ROOT/sk2
|
||||
badKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk2)
|
||||
|
||||
nix key generate-secret --key-name foo.nixos.org-1 > $TEST_ROOT/sk3
|
||||
otherKey=$(nix key convert-secret-to-public < $TEST_ROOT/sk3)
|
||||
|
||||
_NIX_FORCE_HTTP= nix copy --to file://$cacheDir?secret-key=$TEST_ROOT/sk1 $outPath
|
||||
|
||||
|
||||
# Downloading should fail if we don't provide a key.
|
||||
clearStore
|
||||
clearCacheCache
|
||||
|
||||
(! nix-store -r $outPath --substituters "file://$cacheDir")
|
||||
|
||||
|
||||
# And it should fail if we provide an incorrect key.
|
||||
clearStore
|
||||
clearCacheCache
|
||||
|
||||
(! nix-store -r $outPath --substituters "file://$cacheDir" --trusted-public-keys "$badKey")
|
||||
|
||||
|
||||
# It should succeed if we provide the correct key.
|
||||
nix-store -r $outPath --substituters "file://$cacheDir" --trusted-public-keys "$otherKey $publicKey"
|
||||
|
||||
|
||||
# It should fail if we corrupt the .narinfo.
|
||||
clearStore
|
||||
|
||||
cacheDir2=$TEST_ROOT/binary-cache-2
|
||||
rm -rf $cacheDir2
|
||||
cp -r $cacheDir $cacheDir2
|
||||
|
||||
for i in $cacheDir2/*.narinfo; do
|
||||
grep -v References $i > $i.tmp
|
||||
mv $i.tmp $i
|
||||
done
|
||||
|
||||
clearCacheCache
|
||||
|
||||
(! nix-store -r $outPath --substituters "file://$cacheDir2" --trusted-public-keys "$publicKey")
|
||||
|
||||
# If we provide a bad and a good binary cache, it should succeed.
|
||||
|
||||
nix-store -r $outPath --substituters "file://$cacheDir2 file://$cacheDir" --trusted-public-keys "$publicKey"
|
||||
|
||||
|
||||
unset _NIX_FORCE_HTTP
|
||||
|
||||
|
||||
# Test 'nix verify --all' on a binary cache.
|
||||
nix store verify -vvvvv --all --store file://$cacheDir --no-trust
|
||||
|
||||
|
||||
# Test local NAR caching.
|
||||
narCache=$TEST_ROOT/nar-cache
|
||||
rm -rf $narCache
|
||||
mkdir $narCache
|
||||
|
||||
[[ $(nix store cat --store "file://$cacheDir?local-nar-cache=$narCache" $outPath/foobar) = FOOBAR ]]
|
||||
|
||||
rm -rfv "$cacheDir/nar"
|
||||
|
||||
[[ $(nix store cat --store "file://$cacheDir?local-nar-cache=$narCache" $outPath/foobar) = FOOBAR ]]
|
||||
|
||||
(! nix store cat --store file://$cacheDir $outPath/foobar)
|
||||
|
||||
|
||||
# Test NAR listing generation.
|
||||
clearCache
|
||||
|
||||
outPath=$(nix-build --no-out-link -E '
|
||||
with import ./config.nix;
|
||||
mkDerivation {
|
||||
name = "nar-listing";
|
||||
buildCommand = "mkdir $out; echo foo > $out/bar; ln -s xyzzy $out/link";
|
||||
}
|
||||
')
|
||||
|
||||
nix copy --to file://$cacheDir?write-nar-listing=1 $outPath
|
||||
|
||||
diff -u \
|
||||
<(jq -S < $cacheDir/$(basename $outPath | cut -c1-32).ls) \
|
||||
<(echo '{"version":1,"root":{"type":"directory","entries":{"bar":{"type":"regular","size":4,"narOffset":232},"link":{"type":"symlink","target":"xyzzy"}}}}' | jq -S)
|
||||
|
||||
|
||||
# Test debug info index generation.
|
||||
clearCache
|
||||
|
||||
outPath=$(nix-build --no-out-link -E '
|
||||
with import ./config.nix;
|
||||
mkDerivation {
|
||||
name = "debug-info";
|
||||
buildCommand = "mkdir -p $out/lib/debug/.build-id/02; echo foo > $out/lib/debug/.build-id/02/623eda209c26a59b1a8638ff7752f6b945c26b.debug";
|
||||
}
|
||||
')
|
||||
|
||||
nix copy --to "file://$cacheDir?index-debug-info=1&compression=none" $outPath
|
||||
|
||||
diff -u \
|
||||
<(cat $cacheDir/debuginfo/02623eda209c26a59b1a8638ff7752f6b945c26b.debug | jq -S) \
|
||||
<(echo '{"archive":"../nar/100vxs724qr46phz8m24iswmg9p3785hsyagz0kchf6q6gf06sw6.nar","member":"lib/debug/.build-id/02/623eda209c26a59b1a8638ff7752f6b945c26b.debug"}' | jq -S)
|
||||
|
||||
# Test against issue https://github.com/NixOS/nix/issues/3964
|
||||
#
|
||||
expr='
|
||||
with import ./config.nix;
|
||||
mkDerivation {
|
||||
name = "multi-output";
|
||||
buildCommand = "mkdir -p $out; echo foo > $doc; echo $doc > $out/docref";
|
||||
outputs = ["out" "doc"];
|
||||
}
|
||||
'
|
||||
outPath=$(nix-build --no-out-link -E "$expr")
|
||||
docPath=$(nix-store -q --references $outPath)
|
||||
|
||||
# $ nix-store -q --tree $outPath
|
||||
# ...-multi-output
|
||||
# +---...-multi-output-doc
|
||||
|
||||
nix copy --to "file://$cacheDir" $outPath
|
||||
|
||||
hashpart() {
|
||||
basename "$1" | cut -c1-32
|
||||
}
|
||||
|
||||
# break the closure of out by removing doc
|
||||
rm $cacheDir/$(hashpart $docPath).narinfo
|
||||
|
||||
nix-store --delete $outPath $docPath
|
||||
# -vvv is the level that logs during the loop
|
||||
timeout 60 nix-build --no-out-link -E "$expr" --option substituters "file://$cacheDir" \
|
||||
--option trusted-binary-caches "file://$cacheDir" --no-require-sigs
|
21
tests/functional/brotli.sh
Normal file
21
tests/functional/brotli.sh
Normal file
|
@ -0,0 +1,21 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
clearCache
|
||||
|
||||
cacheURI="file://$cacheDir?compression=br"
|
||||
|
||||
outPath=$(nix-build dependencies.nix --no-out-link)
|
||||
|
||||
nix copy --to $cacheURI $outPath
|
||||
|
||||
HASH=$(nix hash path $outPath)
|
||||
|
||||
clearStore
|
||||
clearCacheCache
|
||||
|
||||
nix copy --from $cacheURI $outPath --no-check-sigs
|
||||
|
||||
HASH2=$(nix hash path $outPath)
|
||||
|
||||
[[ $HASH = $HASH2 ]]
|
54
tests/functional/build-delete.sh
Normal file
54
tests/functional/build-delete.sh
Normal file
|
@ -0,0 +1,54 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
|
||||
# https://github.com/NixOS/nix/issues/6572
|
||||
issue_6572_independent_outputs() {
|
||||
nix build -f multiple-outputs.nix --json independent --no-link > $TEST_ROOT/independent.json
|
||||
|
||||
# Make sure that 'nix build' can build a derivation that depends on both outputs of another derivation.
|
||||
p=$(nix build -f multiple-outputs.nix use-independent --no-link --print-out-paths)
|
||||
nix-store --delete "$p" # Clean up for next test
|
||||
|
||||
# Make sure that 'nix build' tracks input-outputs correctly when a single output is already present.
|
||||
nix-store --delete "$(jq -r <$TEST_ROOT/independent.json .[0].outputs.first)"
|
||||
p=$(nix build -f multiple-outputs.nix use-independent --no-link --print-out-paths)
|
||||
cmp $p <<EOF
|
||||
first
|
||||
second
|
||||
EOF
|
||||
nix-store --delete "$p" # Clean up for next test
|
||||
|
||||
# Make sure that 'nix build' tracks input-outputs correctly when a single output is already present.
|
||||
nix-store --delete "$(jq -r <$TEST_ROOT/independent.json .[0].outputs.second)"
|
||||
p=$(nix build -f multiple-outputs.nix use-independent --no-link --print-out-paths)
|
||||
cmp $p <<EOF
|
||||
first
|
||||
second
|
||||
EOF
|
||||
nix-store --delete "$p" # Clean up for next test
|
||||
}
|
||||
issue_6572_independent_outputs
|
||||
|
||||
|
||||
# https://github.com/NixOS/nix/issues/6572
|
||||
issue_6572_dependent_outputs() {
|
||||
|
||||
nix build -f multiple-outputs.nix --json a --no-link > $TEST_ROOT/a.json
|
||||
|
||||
# # Make sure that 'nix build' can build a derivation that depends on both outputs of another derivation.
|
||||
p=$(nix build -f multiple-outputs.nix use-a --no-link --print-out-paths)
|
||||
nix-store --delete "$p" # Clean up for next test
|
||||
|
||||
# Make sure that 'nix build' tracks input-outputs correctly when a single output is already present.
|
||||
nix-store --delete "$(jq -r <$TEST_ROOT/a.json .[0].outputs.second)"
|
||||
p=$(nix build -f multiple-outputs.nix use-a --no-link --print-out-paths)
|
||||
cmp $p <<EOF
|
||||
first
|
||||
second
|
||||
EOF
|
||||
nix-store --delete "$p" # Clean up for next test
|
||||
}
|
||||
if isDaemonNewer "2.12pre0"; then
|
||||
issue_6572_dependent_outputs
|
||||
fi
|
67
tests/functional/build-dry.sh
Normal file
67
tests/functional/build-dry.sh
Normal file
|
@ -0,0 +1,67 @@
|
|||
source common.sh
|
||||
|
||||
###################################################
|
||||
# Check that --dry-run isn't confused with read-only mode
|
||||
# https://github.com/NixOS/nix/issues/1795
|
||||
|
||||
clearStore
|
||||
clearCache
|
||||
|
||||
# Ensure this builds successfully first
|
||||
nix build --no-link -f dependencies.nix
|
||||
|
||||
clearStore
|
||||
clearCache
|
||||
|
||||
# Try --dry-run using old command first
|
||||
nix-build --no-out-link dependencies.nix --dry-run 2>&1 | grep "will be built"
|
||||
# Now new command:
|
||||
nix build -f dependencies.nix --dry-run 2>&1 | grep "will be built"
|
||||
|
||||
clearStore
|
||||
clearCache
|
||||
|
||||
# Try --dry-run using new command first
|
||||
nix build -f dependencies.nix --dry-run 2>&1 | grep "will be built"
|
||||
# Now old command:
|
||||
nix-build --no-out-link dependencies.nix --dry-run 2>&1 | grep "will be built"
|
||||
|
||||
###################################################
|
||||
# Check --dry-run doesn't create links with --dry-run
|
||||
# https://github.com/NixOS/nix/issues/1849
|
||||
clearStore
|
||||
clearCache
|
||||
|
||||
RESULT=$TEST_ROOT/result-link
|
||||
rm -f $RESULT
|
||||
|
||||
nix-build dependencies.nix -o $RESULT --dry-run
|
||||
|
||||
[[ ! -h $RESULT ]] || fail "nix-build --dry-run created output link"
|
||||
|
||||
nix build -f dependencies.nix -o $RESULT --dry-run
|
||||
|
||||
[[ ! -h $RESULT ]] || fail "nix build --dry-run created output link"
|
||||
|
||||
nix build -f dependencies.nix -o $RESULT
|
||||
|
||||
[[ -h $RESULT ]]
|
||||
|
||||
###################################################
|
||||
# Check the JSON output
|
||||
clearStore
|
||||
clearCache
|
||||
|
||||
RES=$(nix build -f dependencies.nix --dry-run --json)
|
||||
|
||||
if [[ -z "${NIX_TESTS_CA_BY_DEFAULT-}" ]]; then
|
||||
echo "$RES" | jq '.[0] | [
|
||||
(.drvPath | test("'$NIX_STORE_DIR'.*\\.drv")),
|
||||
(.outputs.out | test("'$NIX_STORE_DIR'"))
|
||||
] | all'
|
||||
else
|
||||
echo "$RES" | jq '.[0] | [
|
||||
(.drvPath | test("'$NIX_STORE_DIR'.*\\.drv")),
|
||||
.outputs.out == null
|
||||
] | all'
|
||||
fi
|
61
tests/functional/build-hook-ca-fixed.nix
Normal file
61
tests/functional/build-hook-ca-fixed.nix
Normal file
|
@ -0,0 +1,61 @@
|
|||
{ busybox }:
|
||||
|
||||
with import ./config.nix;
|
||||
|
||||
let
|
||||
|
||||
mkDerivation = args:
|
||||
derivation ({
|
||||
inherit system;
|
||||
builder = busybox;
|
||||
args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" ''
|
||||
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
|
||||
eval "$buildCommand"
|
||||
'')];
|
||||
outputHashMode = "recursive";
|
||||
outputHashAlgo = "sha256";
|
||||
} // removeAttrs args ["builder" "meta" "passthru"])
|
||||
// { meta = args.meta or {}; passthru = args.passthru or {}; };
|
||||
|
||||
input1 = mkDerivation {
|
||||
shell = busybox;
|
||||
name = "build-remote-input-1";
|
||||
buildCommand = "echo hi-input1; echo FOO > $out";
|
||||
requiredSystemFeatures = ["foo"];
|
||||
outputHash = "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=";
|
||||
};
|
||||
|
||||
input2 = mkDerivation {
|
||||
shell = busybox;
|
||||
name = "build-remote-input-2";
|
||||
buildCommand = "echo hi; echo BAR > $out";
|
||||
requiredSystemFeatures = ["bar"];
|
||||
outputHash = "sha256-XArauVH91AVwP9hBBQNlkX9ccuPpSYx9o0zeIHb6e+Q=";
|
||||
};
|
||||
|
||||
input3 = mkDerivation {
|
||||
shell = busybox;
|
||||
name = "build-remote-input-3";
|
||||
buildCommand = ''
|
||||
echo hi-input3
|
||||
read x < ${input2}
|
||||
echo $x BAZ > $out
|
||||
'';
|
||||
requiredSystemFeatures = ["baz"];
|
||||
outputHash = "sha256-daKAcPp/+BYMQsVi/YYMlCKoNAxCNDsaivwSHgQqD2s=";
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
mkDerivation {
|
||||
shell = busybox;
|
||||
name = "build-remote";
|
||||
passthru = { inherit input1 input2 input3; };
|
||||
buildCommand =
|
||||
''
|
||||
read x < ${input1}
|
||||
read y < ${input3}
|
||||
echo "$x $y" > $out
|
||||
'';
|
||||
outputHash = "sha256-5SxbkUw6xe2l9TE1uwCvTtTDysD1vhRor38OtDF0LqQ=";
|
||||
}
|
6
tests/functional/build-hook-ca-floating.nix
Normal file
6
tests/functional/build-hook-ca-floating.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{ busybox }:
|
||||
|
||||
import ./build-hook.nix {
|
||||
inherit busybox;
|
||||
contentAddressed = true;
|
||||
}
|
62
tests/functional/build-hook.nix
Normal file
62
tests/functional/build-hook.nix
Normal file
|
@ -0,0 +1,62 @@
|
|||
{ busybox, contentAddressed ? false }:
|
||||
|
||||
with import ./config.nix;
|
||||
|
||||
let
|
||||
|
||||
caArgs = if contentAddressed then {
|
||||
outputHashMode = "recursive";
|
||||
outputHashAlgo = "sha256";
|
||||
__contentAddressed = true;
|
||||
} else {};
|
||||
|
||||
mkDerivation = args:
|
||||
derivation ({
|
||||
inherit system;
|
||||
builder = busybox;
|
||||
args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" ''
|
||||
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
|
||||
eval "$buildCommand"
|
||||
'')];
|
||||
} // removeAttrs args ["builder" "meta" "passthru"]
|
||||
// caArgs)
|
||||
// { meta = args.meta or {}; passthru = args.passthru or {}; };
|
||||
|
||||
input1 = mkDerivation {
|
||||
shell = busybox;
|
||||
name = "build-remote-input-1";
|
||||
buildCommand = "echo hi-input1; echo FOO > $out";
|
||||
requiredSystemFeatures = ["foo"];
|
||||
};
|
||||
|
||||
input2 = mkDerivation {
|
||||
shell = busybox;
|
||||
name = "build-remote-input-2";
|
||||
buildCommand = "echo hi; echo BAR > $out";
|
||||
requiredSystemFeatures = ["bar"];
|
||||
};
|
||||
|
||||
input3 = mkDerivation {
|
||||
shell = busybox;
|
||||
name = "build-remote-input-3";
|
||||
buildCommand = ''
|
||||
echo hi-input3
|
||||
read x < ${input2}
|
||||
echo $x BAZ > $out
|
||||
'';
|
||||
requiredSystemFeatures = ["baz"];
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
mkDerivation {
|
||||
shell = busybox;
|
||||
name = "build-remote";
|
||||
passthru = { inherit input1 input2 input3; };
|
||||
buildCommand =
|
||||
''
|
||||
read x < ${input1}
|
||||
read y < ${input3}
|
||||
echo "$x $y" > $out
|
||||
'';
|
||||
}
|
5
tests/functional/build-remote-content-addressed-fixed.sh
Normal file
5
tests/functional/build-remote-content-addressed-fixed.sh
Normal file
|
@ -0,0 +1,5 @@
|
|||
source common.sh
|
||||
|
||||
file=build-hook-ca-fixed.nix
|
||||
|
||||
source build-remote.sh
|
|
@ -0,0 +1,9 @@
|
|||
source common.sh
|
||||
|
||||
file=build-hook-ca-floating.nix
|
||||
|
||||
enableFeatures "ca-derivations"
|
||||
|
||||
CONTENT_ADDRESSED=true
|
||||
|
||||
source build-remote.sh
|
33
tests/functional/build-remote-input-addressed.sh
Normal file
33
tests/functional/build-remote-input-addressed.sh
Normal file
|
@ -0,0 +1,33 @@
|
|||
source common.sh
|
||||
|
||||
file=build-hook.nix
|
||||
|
||||
source build-remote.sh
|
||||
|
||||
# Add a `post-build-hook` option to the nix conf.
|
||||
# This hook will be executed both for the local machine and the remote builders
|
||||
# (because they share the same config).
|
||||
registerBuildHook () {
|
||||
# Dummy post-build-hook just to ensure that it's executed correctly.
|
||||
# (we can't reuse the one from `$PWD/push-to-store.sh` because of
|
||||
# https://github.com/NixOS/nix/issues/4341)
|
||||
cat <<EOF > $TEST_ROOT/post-build-hook.sh
|
||||
#!/bin/sh
|
||||
|
||||
echo "Post hook ran successfully"
|
||||
# Add an empty line to a counter file, just to check that this hook ran properly
|
||||
echo "" >> $TEST_ROOT/post-hook-counter
|
||||
EOF
|
||||
chmod +x $TEST_ROOT/post-build-hook.sh
|
||||
rm -f $TEST_ROOT/post-hook-counter
|
||||
|
||||
echo "post-build-hook = $TEST_ROOT/post-build-hook.sh" >> $NIX_CONF_DIR/nix.conf
|
||||
}
|
||||
|
||||
registerBuildHook
|
||||
source build-remote.sh
|
||||
|
||||
# `build-hook.nix` has four derivations to build, and the hook runs twice for
|
||||
# each derivation (once on the builder and once on the host), so the counter
|
||||
# should contain eight lines now
|
||||
[[ $(cat $TEST_ROOT/post-hook-counter | wc -l) -eq 8 ]]
|
2
tests/functional/build-remote-trustless-after.sh
Normal file
2
tests/functional/build-remote-trustless-after.sh
Normal file
|
@ -0,0 +1,2 @@
|
|||
outPath=$(readlink -f $TEST_ROOT/result)
|
||||
grep 'FOO BAR BAZ' ${remoteDir}/${outPath}
|
29
tests/functional/build-remote-trustless-should-fail-0.sh
Normal file
29
tests/functional/build-remote-trustless-should-fail-0.sh
Normal file
|
@ -0,0 +1,29 @@
|
|||
source common.sh
|
||||
|
||||
enableFeatures "daemon-trust-override"
|
||||
|
||||
restartDaemon
|
||||
|
||||
[[ $busybox =~ busybox ]] || skipTest "no busybox"
|
||||
|
||||
unset NIX_STORE_DIR
|
||||
unset NIX_STATE_DIR
|
||||
|
||||
# We first build a dependency of the derivation we eventually want to
|
||||
# build.
|
||||
nix-build build-hook.nix -A passthru.input2 \
|
||||
-o "$TEST_ROOT/input2" \
|
||||
--arg busybox "$busybox" \
|
||||
--store "$TEST_ROOT/local" \
|
||||
--option system-features bar
|
||||
|
||||
# Now when we go to build that downstream derivation, Nix will try to
|
||||
# copy our already-build `input2` to the remote store. That store object
|
||||
# is input-addressed, so this will fail.
|
||||
|
||||
file=build-hook.nix
|
||||
prog=$(readlink -e ./nix-daemon-untrusting.sh)
|
||||
proto=ssh-ng
|
||||
|
||||
expectStderr 1 source build-remote-trustless.sh \
|
||||
| grepQuiet "cannot add path '[^ ]*' because it lacks a signature by a trusted key"
|
9
tests/functional/build-remote-trustless-should-pass-0.sh
Normal file
9
tests/functional/build-remote-trustless-should-pass-0.sh
Normal file
|
@ -0,0 +1,9 @@
|
|||
source common.sh
|
||||
|
||||
# Remote trusts us
|
||||
file=build-hook.nix
|
||||
prog=nix-store
|
||||
proto=ssh
|
||||
|
||||
source build-remote-trustless.sh
|
||||
source build-remote-trustless-after.sh
|
9
tests/functional/build-remote-trustless-should-pass-1.sh
Normal file
9
tests/functional/build-remote-trustless-should-pass-1.sh
Normal file
|
@ -0,0 +1,9 @@
|
|||
source common.sh
|
||||
|
||||
# Remote trusts us
|
||||
file=build-hook.nix
|
||||
prog=nix-daemon
|
||||
proto=ssh-ng
|
||||
|
||||
source build-remote-trustless.sh
|
||||
source build-remote-trustless-after.sh
|
13
tests/functional/build-remote-trustless-should-pass-2.sh
Normal file
13
tests/functional/build-remote-trustless-should-pass-2.sh
Normal file
|
@ -0,0 +1,13 @@
|
|||
source common.sh
|
||||
|
||||
enableFeatures "daemon-trust-override"
|
||||
|
||||
restartDaemon
|
||||
|
||||
# Remote doesn't trust us
|
||||
file=build-hook.nix
|
||||
prog=$(readlink -e ./nix-daemon-untrusting.sh)
|
||||
proto=ssh-ng
|
||||
|
||||
source build-remote-trustless.sh
|
||||
source build-remote-trustless-after.sh
|
14
tests/functional/build-remote-trustless-should-pass-3.sh
Normal file
14
tests/functional/build-remote-trustless-should-pass-3.sh
Normal file
|
@ -0,0 +1,14 @@
|
|||
source common.sh
|
||||
|
||||
enableFeatures "daemon-trust-override"
|
||||
|
||||
restartDaemon
|
||||
|
||||
# Remote doesn't trusts us, but this is fine because we are only
|
||||
# building (fixed) CA derivations.
|
||||
file=build-hook-ca-fixed.nix
|
||||
prog=$(readlink -e ./nix-daemon-untrusting.sh)
|
||||
proto=ssh-ng
|
||||
|
||||
source build-remote-trustless.sh
|
||||
source build-remote-trustless-after.sh
|
14
tests/functional/build-remote-trustless.sh
Normal file
14
tests/functional/build-remote-trustless.sh
Normal file
|
@ -0,0 +1,14 @@
|
|||
requireSandboxSupport
|
||||
[[ $busybox =~ busybox ]] || skipTest "no busybox"
|
||||
|
||||
unset NIX_STORE_DIR
|
||||
unset NIX_STATE_DIR
|
||||
|
||||
remoteDir=$TEST_ROOT/remote
|
||||
|
||||
# Note: ssh{-ng}://localhost bypasses ssh. See tests/functional/build-remote.sh for
|
||||
# more details.
|
||||
nix-build $file -o $TEST_ROOT/result --max-jobs 0 \
|
||||
--arg busybox $busybox \
|
||||
--store $TEST_ROOT/local \
|
||||
--builders "$proto://localhost?remote-program=$prog&remote-store=${remoteDir}%3Fsystem-features=foo%20bar%20baz - - 1 1 foo,bar,baz"
|
84
tests/functional/build-remote.sh
Normal file
84
tests/functional/build-remote.sh
Normal file
|
@ -0,0 +1,84 @@
|
|||
requireSandboxSupport
|
||||
[[ $busybox =~ busybox ]] || skipTest "no busybox"
|
||||
|
||||
# Avoid store dir being inside sandbox build-dir
|
||||
unset NIX_STORE_DIR
|
||||
unset NIX_STATE_DIR
|
||||
|
||||
function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }
|
||||
|
||||
EXTRA_SYSTEM_FEATURES=()
|
||||
if [[ -n "${CONTENT_ADDRESSED-}" ]]; then
|
||||
EXTRA_SYSTEM_FEATURES=("ca-derivations")
|
||||
fi
|
||||
|
||||
builders=(
|
||||
# system-features will automatically be added to the outer URL, but not inner
|
||||
# remote-store URL.
|
||||
"ssh://localhost?remote-store=$TEST_ROOT/machine1?system-features=$(join_by "%20" foo ${EXTRA_SYSTEM_FEATURES[@]}) - - 1 1 $(join_by "," foo ${EXTRA_SYSTEM_FEATURES[@]})"
|
||||
"$TEST_ROOT/machine2 - - 1 1 $(join_by "," bar ${EXTRA_SYSTEM_FEATURES[@]})"
|
||||
"ssh-ng://localhost?remote-store=$TEST_ROOT/machine3?system-features=$(join_by "%20" baz ${EXTRA_SYSTEM_FEATURES[@]}) - - 1 1 $(join_by "," baz ${EXTRA_SYSTEM_FEATURES[@]})"
|
||||
)
|
||||
|
||||
chmod -R +w $TEST_ROOT/machine* || true
|
||||
rm -rf $TEST_ROOT/machine* || true
|
||||
|
||||
# Note: ssh://localhost bypasses ssh, directly invoking nix-store as a
|
||||
# child process. This allows us to test LegacySSHStore::buildDerivation().
|
||||
# ssh-ng://... likewise allows us to test RemoteStore::buildDerivation().
|
||||
nix build -L -v -f $file -o $TEST_ROOT/result --max-jobs 0 \
|
||||
--arg busybox $busybox \
|
||||
--store $TEST_ROOT/machine0 \
|
||||
--builders "$(join_by '; ' "${builders[@]}")"
|
||||
|
||||
outPath=$(readlink -f $TEST_ROOT/result)
|
||||
|
||||
grep 'FOO BAR BAZ' $TEST_ROOT/machine0/$outPath
|
||||
|
||||
testPrintOutPath=$(nix build -L -v -f $file --no-link --print-out-paths --max-jobs 0 \
|
||||
--arg busybox $busybox \
|
||||
--store $TEST_ROOT/machine0 \
|
||||
--builders "$(join_by '; ' "${builders[@]}")"
|
||||
)
|
||||
|
||||
[[ $testPrintOutPath =~ store.*build-remote ]]
|
||||
|
||||
# Ensure that input1 was built on store1 due to the required feature.
|
||||
output=$(nix path-info --store $TEST_ROOT/machine1 --all)
|
||||
echo "$output" | grepQuiet builder-build-remote-input-1.sh
|
||||
echo "$output" | grepQuietInverse builder-build-remote-input-2.sh
|
||||
echo "$output" | grepQuietInverse builder-build-remote-input-3.sh
|
||||
unset output
|
||||
|
||||
# Ensure that input2 was built on store2 due to the required feature.
|
||||
output=$(nix path-info --store $TEST_ROOT/machine2 --all)
|
||||
echo "$output" | grepQuietInverse builder-build-remote-input-1.sh
|
||||
echo "$output" | grepQuiet builder-build-remote-input-2.sh
|
||||
echo "$output" | grepQuietInverse builder-build-remote-input-3.sh
|
||||
unset output
|
||||
|
||||
# Ensure that input3 was built on store3 due to the required feature.
|
||||
output=$(nix path-info --store $TEST_ROOT/machine3 --all)
|
||||
echo "$output" | grepQuietInverse builder-build-remote-input-1.sh
|
||||
echo "$output" | grepQuietInverse builder-build-remote-input-2.sh
|
||||
echo "$output" | grepQuiet builder-build-remote-input-3.sh
|
||||
unset output
|
||||
|
||||
|
||||
for i in input1 input3; do
|
||||
nix log --store $TEST_ROOT/machine0 --file "$file" --arg busybox $busybox passthru."$i" | grep hi-$i
|
||||
done
|
||||
|
||||
# Behavior of keep-failed
|
||||
out="$(nix-build 2>&1 failing.nix \
|
||||
--no-out-link \
|
||||
--builders "$(join_by '; ' "${builders[@]}")" \
|
||||
--keep-failed \
|
||||
--store $TEST_ROOT/machine0 \
|
||||
-j0 \
|
||||
--arg busybox $busybox)" || true
|
||||
|
||||
[[ "$out" =~ .*"note: keeping build directory".* ]]
|
||||
|
||||
build_dir="$(grep "note: keeping build" <<< "$out" | sed -E "s/^(.*)note: keeping build directory '(.*)'(.*)$/\2/")"
|
||||
[[ "foo" = $(<"$build_dir"/bar) ]]
|
135
tests/functional/build.sh
Normal file
135
tests/functional/build.sh
Normal file
|
@ -0,0 +1,135 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
|
||||
# Make sure that 'nix build' returns all outputs by default.
|
||||
nix build -f multiple-outputs.nix --json a b --no-link | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-a.drv")) and
|
||||
(.outputs |
|
||||
(keys | length == 2) and
|
||||
(.first | match(".*multiple-outputs-a-first")) and
|
||||
(.second | match(".*multiple-outputs-a-second"))))
|
||||
and (.[1] |
|
||||
(.drvPath | match(".*multiple-outputs-b.drv")) and
|
||||
(.outputs |
|
||||
(keys | length == 1) and
|
||||
(.out | match(".*multiple-outputs-b"))))
|
||||
'
|
||||
|
||||
# Test output selection using the '^' syntax.
|
||||
nix build -f multiple-outputs.nix --json a^first --no-link | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-a.drv")) and
|
||||
(.outputs | keys == ["first"]))
|
||||
'
|
||||
|
||||
nix build -f multiple-outputs.nix --json a^second,first --no-link | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-a.drv")) and
|
||||
(.outputs | keys == ["first", "second"]))
|
||||
'
|
||||
|
||||
nix build -f multiple-outputs.nix --json 'a^*' --no-link | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-a.drv")) and
|
||||
(.outputs | keys == ["first", "second"]))
|
||||
'
|
||||
|
||||
# Test that 'outputsToInstall' is respected by default.
|
||||
nix build -f multiple-outputs.nix --json e --no-link | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-e.drv")) and
|
||||
(.outputs | keys == ["a_a", "b"]))
|
||||
'
|
||||
|
||||
# But not when it's overriden.
|
||||
nix build -f multiple-outputs.nix --json e^a_a --no-link
|
||||
nix build -f multiple-outputs.nix --json e^a_a --no-link | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-e.drv")) and
|
||||
(.outputs | keys == ["a_a"]))
|
||||
'
|
||||
|
||||
nix build -f multiple-outputs.nix --json 'e^*' --no-link | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-e.drv")) and
|
||||
(.outputs | keys == ["a_a", "b", "c"]))
|
||||
'
|
||||
|
||||
# test buidling from non-drv attr path
|
||||
|
||||
nix build -f multiple-outputs.nix --json 'e.a_a.outPath' --no-link | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-e.drv")) and
|
||||
(.outputs | keys == ["a_a"]))
|
||||
'
|
||||
|
||||
# Illegal type of string context
|
||||
expectStderr 1 nix build -f multiple-outputs.nix 'e.a_a.drvPath' \
|
||||
| grepQuiet "has a context which refers to a complete source and binary closure."
|
||||
|
||||
# No string context
|
||||
expectStderr 1 nix build --expr '""' --no-link \
|
||||
| grepQuiet "has 0 entries in its context. It should only have exactly one entry"
|
||||
|
||||
# Too much string context
|
||||
expectStderr 1 nix build --impure --expr 'with (import ./multiple-outputs.nix).e.a_a; "${drvPath}${outPath}"' --no-link \
|
||||
| grepQuiet "has 2 entries in its context. It should only have exactly one entry"
|
||||
|
||||
nix build --impure --json --expr 'builtins.unsafeDiscardOutputDependency (import ./multiple-outputs.nix).e.a_a.drvPath' --no-link | jq --exit-status '
|
||||
(.[0] | match(".*multiple-outputs-e.drv"))
|
||||
'
|
||||
|
||||
# Test building from raw store path to drv not expression.
|
||||
|
||||
drv=$(nix eval -f multiple-outputs.nix --raw a.drvPath)
|
||||
if nix build "$drv^not-an-output" --no-link --json; then
|
||||
fail "'not-an-output' should fail to build"
|
||||
fi
|
||||
|
||||
if nix build "$drv^" --no-link --json; then
|
||||
fail "'empty outputs list' should fail to build"
|
||||
fi
|
||||
|
||||
if nix build "$drv^*nope" --no-link --json; then
|
||||
fail "'* must be entire string' should fail to build"
|
||||
fi
|
||||
|
||||
nix build "$drv^first" --no-link --json | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-a.drv")) and
|
||||
(.outputs |
|
||||
(keys | length == 1) and
|
||||
(.first | match(".*multiple-outputs-a-first")) and
|
||||
(has("second") | not)))
|
||||
'
|
||||
|
||||
nix build "$drv^first,second" --no-link --json | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-a.drv")) and
|
||||
(.outputs |
|
||||
(keys | length == 2) and
|
||||
(.first | match(".*multiple-outputs-a-first")) and
|
||||
(.second | match(".*multiple-outputs-a-second"))))
|
||||
'
|
||||
|
||||
nix build "$drv^*" --no-link --json | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-a.drv")) and
|
||||
(.outputs |
|
||||
(keys | length == 2) and
|
||||
(.first | match(".*multiple-outputs-a-first")) and
|
||||
(.second | match(".*multiple-outputs-a-second"))))
|
||||
'
|
||||
|
||||
# Make sure that `--impure` works (regression test for https://github.com/NixOS/nix/issues/6488)
|
||||
nix build --impure -f multiple-outputs.nix --json e --no-link | jq --exit-status '
|
||||
(.[0] |
|
||||
(.drvPath | match(".*multiple-outputs-e.drv")) and
|
||||
(.outputs | keys == ["a_a", "b"]))
|
||||
'
|
||||
|
||||
# Make sure that `--stdin` works and does not apply any defaults
|
||||
printf "" | nix build --no-link --stdin --json | jq --exit-status '. == []'
|
||||
printf "%s\n" "$drv^*" | nix build --no-link --stdin --json | jq --exit-status '.[0]|has("drvPath")'
|
1
tests/functional/ca-shell.nix
Normal file
1
tests/functional/ca-shell.nix
Normal file
|
@ -0,0 +1 @@
|
|||
{ inNixShell ? false, ... }@args: import ./shell.nix (args // { contentAddressed = true; })
|
51
tests/functional/ca/build-cache.sh
Normal file
51
tests/functional/ca/build-cache.sh
Normal file
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
# The substituters didn't work prior to this time.
|
||||
requireDaemonNewerThan "2.18.0pre20230808"
|
||||
|
||||
drv=$(nix-instantiate ./content-addressed.nix -A rootCA --arg seed 1)^out
|
||||
nix derivation show "$drv" --arg seed 1
|
||||
|
||||
buildAttr () {
|
||||
local derivationPath=$1
|
||||
local seedValue=$2
|
||||
shift; shift
|
||||
local args=("./content-addressed.nix" "-A" "$derivationPath" --arg seed "$seedValue" "--no-out-link")
|
||||
args+=("$@")
|
||||
nix-build "${args[@]}"
|
||||
}
|
||||
|
||||
copyAttr () {
|
||||
local derivationPath=$1
|
||||
local seedValue=$2
|
||||
shift; shift
|
||||
local args=("-f" "./content-addressed.nix" "$derivationPath" --arg seed "$seedValue")
|
||||
args+=("$@")
|
||||
# Note: to copy CA derivations, we need to copy the realisations, which
|
||||
# currently requires naming the installables, not just the derivation output
|
||||
# path.
|
||||
nix copy --to file://$cacheDir "${args[@]}"
|
||||
}
|
||||
|
||||
testRemoteCacheFor () {
|
||||
local derivationPath=$1
|
||||
clearCache
|
||||
copyAttr "$derivationPath" 1
|
||||
clearStore
|
||||
# Check nothing gets built.
|
||||
buildAttr "$derivationPath" 1 --option substituters file://$cacheDir --no-require-sigs |& grepQuietInverse " will be built:"
|
||||
}
|
||||
|
||||
testRemoteCache () {
|
||||
testRemoteCacheFor rootCA
|
||||
testRemoteCacheFor dependentCA
|
||||
testRemoteCacheFor dependentNonCA
|
||||
testRemoteCacheFor dependentFixedOutput
|
||||
testRemoteCacheFor dependentForBuildCA
|
||||
testRemoteCacheFor dependentForBuildNonCA
|
||||
}
|
||||
|
||||
clearStore
|
||||
testRemoteCache
|
6
tests/functional/ca/build-dry.sh
Normal file
6
tests/functional/ca/build-dry.sh
Normal file
|
@ -0,0 +1,6 @@
|
|||
source common.sh
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
|
||||
cd .. && source build-dry.sh
|
||||
|
21
tests/functional/ca/build-with-garbage-path.sh
Executable file
21
tests/functional/ca/build-with-garbage-path.sh
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Regression test for https://github.com/NixOS/nix/issues/4858
|
||||
|
||||
source common.sh
|
||||
|
||||
requireDaemonNewerThan "2.4pre20210621"
|
||||
|
||||
# Get the output path of `rootCA`, and put some garbage instead
|
||||
outPath="$(nix-build ./content-addressed.nix -A rootCA --no-out-link)"
|
||||
nix-store --delete $(nix-store -q --referrers-closure "$outPath")
|
||||
touch "$outPath"
|
||||
|
||||
# The build should correctly remove the garbage and put the expected path instead
|
||||
nix-build ./content-addressed.nix -A rootCA --no-out-link
|
||||
|
||||
# Rebuild it. This shouldn’t overwrite the existing path
|
||||
oldInode=$(stat -c '%i' "$outPath")
|
||||
nix-build ./content-addressed.nix -A rootCA --no-out-link --arg seed 2
|
||||
newInode=$(stat -c '%i' "$outPath")
|
||||
[[ "$oldInode" == "$newInode" ]]
|
67
tests/functional/ca/build.sh
Normal file
67
tests/functional/ca/build.sh
Normal file
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
drv=$(nix-instantiate ./content-addressed.nix -A rootCA --arg seed 1)^out
|
||||
nix derivation show "$drv" --arg seed 1
|
||||
|
||||
buildAttr () {
|
||||
local derivationPath=$1
|
||||
local seedValue=$2
|
||||
shift; shift
|
||||
local args=("./content-addressed.nix" "-A" "$derivationPath" --arg seed "$seedValue" "--no-out-link")
|
||||
args+=("$@")
|
||||
nix-build "${args[@]}"
|
||||
}
|
||||
|
||||
testDeterministicCA () {
|
||||
[[ $(buildAttr rootCA 1) = $(buildAttr rootCA 2) ]]
|
||||
}
|
||||
|
||||
testCutoffFor () {
|
||||
local out1 out2
|
||||
out1=$(buildAttr $1 1)
|
||||
# The seed only changes the root derivation, and not it's output, so the
|
||||
# dependent derivations should only need to be built once.
|
||||
buildAttr rootCA 2
|
||||
out2=$(buildAttr $1 2 -j0)
|
||||
test "$out1" == "$out2"
|
||||
}
|
||||
|
||||
testCutoff () {
|
||||
# Don't directly build dependentCA, that way we'll make sure we don't rely on
|
||||
# dependent derivations always being already built.
|
||||
#testDerivation dependentCA
|
||||
testCutoffFor transitivelyDependentCA
|
||||
testCutoffFor dependentNonCA
|
||||
testCutoffFor dependentFixedOutput
|
||||
}
|
||||
|
||||
testGC () {
|
||||
nix-instantiate ./content-addressed.nix -A rootCA --arg seed 5
|
||||
nix-collect-garbage --option keep-derivations true
|
||||
clearStore
|
||||
buildAttr rootCA 1 --out-link $TEST_ROOT/rootCA
|
||||
nix-collect-garbage
|
||||
buildAttr rootCA 1 -j0
|
||||
}
|
||||
|
||||
testNixCommand () {
|
||||
clearStore
|
||||
nix build --file ./content-addressed.nix --no-link
|
||||
}
|
||||
|
||||
# Regression test for https://github.com/NixOS/nix/issues/4775
|
||||
testNormalization () {
|
||||
clearStore
|
||||
outPath=$(buildAttr rootCA 1)
|
||||
test "$(stat -c %Y $outPath)" -eq 1
|
||||
}
|
||||
|
||||
clearStore
|
||||
testNormalization
|
||||
testDeterministicCA
|
||||
clearStore
|
||||
testCutoff
|
||||
testGC
|
||||
testNixCommand
|
5
tests/functional/ca/common.sh
Normal file
5
tests/functional/ca/common.sh
Normal file
|
@ -0,0 +1,5 @@
|
|||
source ../common.sh
|
||||
|
||||
enableFeatures "ca-derivations"
|
||||
|
||||
restartDaemon
|
18
tests/functional/ca/concurrent-builds.sh
Executable file
18
tests/functional/ca/concurrent-builds.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Ensure that we can’t build twice the same derivation concurrently.
|
||||
# Regression test for https://github.com/NixOS/nix/issues/5029
|
||||
|
||||
source common.sh
|
||||
|
||||
buggyNeedLocalStore "For some reason, this deadlocks with the daemon"
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
|
||||
clearStore
|
||||
|
||||
for i in {0..5}; do
|
||||
nix build --no-link --file ./racy.nix &
|
||||
done
|
||||
|
||||
wait
|
1
tests/functional/ca/config.nix.in
Symbolic link
1
tests/functional/ca/config.nix.in
Symbolic link
|
@ -0,0 +1 @@
|
|||
../config.nix.in
|
100
tests/functional/ca/content-addressed.nix
Normal file
100
tests/functional/ca/content-addressed.nix
Normal file
|
@ -0,0 +1,100 @@
|
|||
with import ./config.nix;
|
||||
|
||||
let mkCADerivation = args: mkDerivation ({
|
||||
__contentAddressed = true;
|
||||
outputHashMode = "recursive";
|
||||
outputHashAlgo = "sha256";
|
||||
} // args);
|
||||
in
|
||||
|
||||
{ seed ? 0 }:
|
||||
# A simple content-addressed derivation.
|
||||
# The derivation can be arbitrarily modified by passing a different `seed`,
|
||||
# but the output will always be the same
|
||||
rec {
|
||||
rootLegacy = mkDerivation {
|
||||
name = "simple-input-addressed";
|
||||
buildCommand = ''
|
||||
set -x
|
||||
echo "Building a legacy derivation"
|
||||
mkdir -p $out
|
||||
echo "Hello World" > $out/hello
|
||||
'';
|
||||
};
|
||||
rootCA = mkCADerivation {
|
||||
name = "rootCA";
|
||||
outputs = [ "out" "dev" "foo" ];
|
||||
buildCommand = ''
|
||||
echo "building a CA derivation"
|
||||
echo "The seed is ${toString seed}"
|
||||
mkdir -p $out
|
||||
echo ${rootLegacy}/hello > $out/dep
|
||||
ln -s $out $out/self
|
||||
# test symlinks at root
|
||||
ln -s $out $dev
|
||||
ln -s $out $foo
|
||||
'';
|
||||
};
|
||||
dependentCA = mkCADerivation {
|
||||
name = "dependent";
|
||||
buildCommand = ''
|
||||
echo "building a dependent derivation"
|
||||
mkdir -p $out
|
||||
cat ${rootCA}/self/dep
|
||||
echo ${rootCA}/self/dep > $out/dep
|
||||
'';
|
||||
};
|
||||
transitivelyDependentCA = mkCADerivation {
|
||||
name = "transitively-dependent";
|
||||
buildCommand = ''
|
||||
echo "building transitively-dependent"
|
||||
cat ${dependentCA}/dep
|
||||
echo ${dependentCA} > $out
|
||||
'';
|
||||
};
|
||||
dependentNonCA = mkDerivation {
|
||||
name = "dependent-non-ca";
|
||||
buildCommand = ''
|
||||
echo "Didn't cut-off"
|
||||
echo "building dependent-non-ca"
|
||||
mkdir -p $out
|
||||
echo ${rootCA}/non-ca-hello > $out/dep
|
||||
'';
|
||||
};
|
||||
dependentForBuildCA = mkCADerivation {
|
||||
name = "dependent-for-build-ca";
|
||||
buildCommand = ''
|
||||
echo "Depends on rootCA for building only"
|
||||
mkdir -p $out
|
||||
echo ${rootCA}
|
||||
touch $out
|
||||
'';
|
||||
};
|
||||
dependentForBuildNonCA = mkDerivation {
|
||||
name = "dependent-for-build-non-ca";
|
||||
buildCommand = ''
|
||||
echo "Depends on rootCA for building only"
|
||||
mkdir -p $out
|
||||
echo ${rootCA}
|
||||
touch $out
|
||||
'';
|
||||
};
|
||||
dependentFixedOutput = mkDerivation {
|
||||
name = "dependent-fixed-output";
|
||||
outputHashMode = "recursive";
|
||||
outputHash = "sha512-7aJcmSuEuYP5tGKcmGY8bRr/lrCjJlOxP2mIUjO/vMQeg6gx/65IbzRWES8EKiPDOs9z+wF30lEfcwxM/cT4pw==";
|
||||
buildCommand = ''
|
||||
cat ${dependentCA}/dep
|
||||
echo foo > $out
|
||||
'';
|
||||
};
|
||||
runnable = mkCADerivation rec {
|
||||
name = "runnable-thing";
|
||||
buildCommand = ''
|
||||
mkdir -p $out/bin
|
||||
echo ${rootCA} # Just to make it depend on it
|
||||
echo "#! ${shell}" > $out/bin/${name}
|
||||
chmod +x $out/bin/${name}
|
||||
'';
|
||||
};
|
||||
}
|
29
tests/functional/ca/derivation-json.sh
Normal file
29
tests/functional/ca/derivation-json.sh
Normal file
|
@ -0,0 +1,29 @@
|
|||
source common.sh
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
|
||||
drvPath=$(nix-instantiate ../simple.nix)
|
||||
|
||||
nix derivation show $drvPath | jq .[] > $TEST_HOME/simple.json
|
||||
|
||||
drvPath2=$(nix derivation add < $TEST_HOME/simple.json)
|
||||
|
||||
[[ "$drvPath" = "$drvPath2" ]]
|
||||
|
||||
# Content-addressed 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
|
||||
[[ ! -e "$drvPath3" ]]
|
||||
|
||||
# But the JSON is rejected without the experimental feature
|
||||
expectStderr 1 nix derivation add < $TEST_HOME/foo.json --experimental-features nix-command | grepQuiet "experimental Nix feature 'ca-derivations' is disabled"
|
||||
|
||||
# Without --dry-run it is actually written
|
||||
drvPath4=$(nix derivation add < $TEST_HOME/foo.json)
|
||||
[[ "$drvPath4" = "$drvPath3" ]]
|
||||
[[ -e "$drvPath3" ]]
|
||||
|
||||
# The modified derivation read back as JSON matches
|
||||
nix derivation show $drvPath3 | jq .[] > $TEST_HOME/foo-read.json
|
||||
diff $TEST_HOME/foo.json $TEST_HOME/foo-read.json
|
26
tests/functional/ca/duplicate-realisation-in-closure.sh
Normal file
26
tests/functional/ca/duplicate-realisation-in-closure.sh
Normal file
|
@ -0,0 +1,26 @@
|
|||
source ./common.sh
|
||||
|
||||
requireDaemonNewerThan "2.4pre20210625"
|
||||
|
||||
export REMOTE_STORE_DIR="$TEST_ROOT/remote_store"
|
||||
export REMOTE_STORE="file://$REMOTE_STORE_DIR"
|
||||
|
||||
rm -rf $REMOTE_STORE_DIR
|
||||
clearStore
|
||||
|
||||
# Build dep1 and push that to the binary cache.
|
||||
# This entails building (and pushing) current-time.
|
||||
nix copy --to "$REMOTE_STORE" -f nondeterministic.nix dep1
|
||||
clearStore
|
||||
sleep 2 # To make sure that `$(date)` will be different
|
||||
# Build dep2.
|
||||
# As we’ve cleared the cache, we’ll have to rebuild current-time. And because
|
||||
# the current time isn’t the same as before, this will yield a new (different)
|
||||
# realisation
|
||||
nix build -f nondeterministic.nix dep2 --no-link
|
||||
|
||||
# Build something that depends both on dep1 and dep2.
|
||||
# If everything goes right, we should rebuild dep2 rather than fetch it from
|
||||
# the cache (because that would mean duplicating `current-time` in the closure),
|
||||
# and have `dep1 == dep2`.
|
||||
nix build --substituters "$REMOTE_STORE" -f nondeterministic.nix toplevel --no-require-sigs --no-link
|
3
tests/functional/ca/flake.nix
Normal file
3
tests/functional/ca/flake.nix
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
outputs = { self }: import ./content-addressed.nix {};
|
||||
}
|
10
tests/functional/ca/gc.sh
Executable file
10
tests/functional/ca/gc.sh
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Ensure that garbage collection works properly with ca derivations
|
||||
|
||||
source common.sh
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
|
||||
cd ..
|
||||
source gc.sh
|
6
tests/functional/ca/import-derivation.sh
Normal file
6
tests/functional/ca/import-derivation.sh
Normal file
|
@ -0,0 +1,6 @@
|
|||
source common.sh
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
|
||||
cd .. && source import-derivation.sh
|
||||
|
28
tests/functional/ca/local.mk
Normal file
28
tests/functional/ca/local.mk
Normal file
|
@ -0,0 +1,28 @@
|
|||
ca-tests := \
|
||||
$(d)/build-with-garbage-path.sh \
|
||||
$(d)/build.sh \
|
||||
$(d)/build-cache.sh \
|
||||
$(d)/concurrent-builds.sh \
|
||||
$(d)/derivation-json.sh \
|
||||
$(d)/duplicate-realisation-in-closure.sh \
|
||||
$(d)/gc.sh \
|
||||
$(d)/import-derivation.sh \
|
||||
$(d)/new-build-cmd.sh \
|
||||
$(d)/nix-copy.sh \
|
||||
$(d)/nix-run.sh \
|
||||
$(d)/nix-shell.sh \
|
||||
$(d)/post-hook.sh \
|
||||
$(d)/recursive.sh \
|
||||
$(d)/repl.sh \
|
||||
$(d)/selfref-gc.sh \
|
||||
$(d)/signatures.sh \
|
||||
$(d)/substitute.sh \
|
||||
$(d)/why-depends.sh
|
||||
|
||||
install-tests-groups += ca
|
||||
|
||||
clean-files += \
|
||||
$(d)/config.nix
|
||||
|
||||
test-deps += \
|
||||
tests/functional/ca/config.nix
|
5
tests/functional/ca/new-build-cmd.sh
Normal file
5
tests/functional/ca/new-build-cmd.sh
Normal file
|
@ -0,0 +1,5 @@
|
|||
source common.sh
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
cd ..
|
||||
source ./build.sh
|
31
tests/functional/ca/nix-copy.sh
Executable file
31
tests/functional/ca/nix-copy.sh
Executable file
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
export REMOTE_STORE_DIR="$TEST_ROOT/remote_store"
|
||||
export REMOTE_STORE="file://$REMOTE_STORE_DIR"
|
||||
|
||||
ensureCorrectlyCopied () {
|
||||
attrPath="$1"
|
||||
nix build --store "$REMOTE_STORE" --file ./content-addressed.nix "$attrPath"
|
||||
}
|
||||
|
||||
testOneCopy () {
|
||||
clearStore
|
||||
rm -rf "$REMOTE_STORE_DIR"
|
||||
|
||||
attrPath="$1"
|
||||
nix copy --to $REMOTE_STORE "$attrPath" --file ./content-addressed.nix
|
||||
|
||||
ensureCorrectlyCopied "$attrPath"
|
||||
|
||||
# Ensure that we can copy back what we put in the store
|
||||
clearStore
|
||||
nix copy --from $REMOTE_STORE \
|
||||
--file ./content-addressed.nix "$attrPath" \
|
||||
--no-check-sigs
|
||||
}
|
||||
|
||||
for attrPath in rootCA dependentCA transitivelyDependentCA dependentNonCA dependentFixedOutput; do
|
||||
testOneCopy "$attrPath"
|
||||
done
|
7
tests/functional/ca/nix-run.sh
Executable file
7
tests/functional/ca/nix-run.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
FLAKE_PATH=path:$PWD
|
||||
|
||||
nix run --no-write-lock-file $FLAKE_PATH#runnable
|
8
tests/functional/ca/nix-shell.sh
Executable file
8
tests/functional/ca/nix-shell.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
CONTENT_ADDRESSED=true
|
||||
cd ..
|
||||
source ./nix-shell.sh
|
||||
|
35
tests/functional/ca/nondeterministic.nix
Normal file
35
tests/functional/ca/nondeterministic.nix
Normal file
|
@ -0,0 +1,35 @@
|
|||
with import ./config.nix;
|
||||
|
||||
let mkCADerivation = args: mkDerivation ({
|
||||
__contentAddressed = true;
|
||||
outputHashMode = "recursive";
|
||||
outputHashAlgo = "sha256";
|
||||
} // args);
|
||||
in
|
||||
|
||||
rec {
|
||||
currentTime = mkCADerivation {
|
||||
name = "current-time";
|
||||
buildCommand = ''
|
||||
mkdir $out
|
||||
echo $(date) > $out/current-time
|
||||
'';
|
||||
};
|
||||
dep = seed: mkCADerivation {
|
||||
name = "dep";
|
||||
inherit seed;
|
||||
buildCommand = ''
|
||||
echo ${currentTime} > $out
|
||||
'';
|
||||
};
|
||||
dep1 = dep 1;
|
||||
dep2 = dep 2;
|
||||
toplevel = mkCADerivation {
|
||||
name = "toplevel";
|
||||
buildCommand = ''
|
||||
test ${dep1} == ${dep2}
|
||||
touch $out
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
11
tests/functional/ca/post-hook.sh
Executable file
11
tests/functional/ca/post-hook.sh
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
requireDaemonNewerThan "2.4pre20210626"
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
cd ..
|
||||
source ./post-hook.sh
|
||||
|
||||
|
15
tests/functional/ca/racy.nix
Normal file
15
tests/functional/ca/racy.nix
Normal file
|
@ -0,0 +1,15 @@
|
|||
# A derivation that would certainly fail if several builders tried to
|
||||
# build it at once.
|
||||
|
||||
|
||||
with import ./config.nix;
|
||||
|
||||
mkDerivation {
|
||||
name = "simple";
|
||||
buildCommand = ''
|
||||
mkdir $out
|
||||
echo bar >> $out/foo
|
||||
sleep 3
|
||||
[[ "$(cat $out/foo)" == bar ]]
|
||||
'';
|
||||
}
|
9
tests/functional/ca/recursive.sh
Executable file
9
tests/functional/ca/recursive.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
requireDaemonNewerThan "2.4pre20210623"
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
cd ..
|
||||
source ./recursive.sh
|
5
tests/functional/ca/repl.sh
Normal file
5
tests/functional/ca/repl.sh
Normal file
|
@ -0,0 +1,5 @@
|
|||
source common.sh
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
|
||||
cd .. && source repl.sh
|
11
tests/functional/ca/selfref-gc.sh
Executable file
11
tests/functional/ca/selfref-gc.sh
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
requireDaemonNewerThan "2.4pre20210626"
|
||||
|
||||
enableFeatures "ca-derivations nix-command flakes"
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
cd ..
|
||||
source ./selfref-gc.sh
|
36
tests/functional/ca/signatures.sh
Normal file
36
tests/functional/ca/signatures.sh
Normal file
|
@ -0,0 +1,36 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
clearCache
|
||||
|
||||
nix-store --generate-binary-cache-key cache1.example.org $TEST_ROOT/sk1 $TEST_ROOT/pk1
|
||||
pk1=$(cat $TEST_ROOT/pk1)
|
||||
|
||||
export REMOTE_STORE_DIR="$TEST_ROOT/remote_store"
|
||||
export REMOTE_STORE="file://$REMOTE_STORE_DIR"
|
||||
|
||||
ensureCorrectlyCopied () {
|
||||
attrPath="$1"
|
||||
nix build --store "$REMOTE_STORE" --file ./content-addressed.nix "$attrPath"
|
||||
}
|
||||
|
||||
testOneCopy () {
|
||||
clearStore
|
||||
rm -rf "$REMOTE_STORE_DIR"
|
||||
|
||||
attrPath="$1"
|
||||
nix copy -vvvv --to $REMOTE_STORE "$attrPath" --file ./content-addressed.nix \
|
||||
--secret-key-files "$TEST_ROOT/sk1" --show-trace
|
||||
|
||||
ensureCorrectlyCopied "$attrPath"
|
||||
|
||||
# Ensure that we can copy back what we put in the store
|
||||
clearStore
|
||||
nix copy --from $REMOTE_STORE \
|
||||
--file ./content-addressed.nix "$attrPath" \
|
||||
--trusted-public-keys $pk1
|
||||
}
|
||||
|
||||
for attrPath in rootCA dependentCA transitivelyDependentCA dependentNonCA dependentFixedOutput; do
|
||||
testOneCopy "$attrPath"
|
||||
done
|
71
tests/functional/ca/substitute.sh
Normal file
71
tests/functional/ca/substitute.sh
Normal file
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Ensure that binary substitution works properly with ca derivations
|
||||
|
||||
source common.sh
|
||||
|
||||
needLocalStore "“--no-require-sigs” can’t be used with the daemon"
|
||||
|
||||
rm -rf $TEST_ROOT/binary_cache
|
||||
|
||||
export REMOTE_STORE_DIR=$TEST_ROOT/binary_cache
|
||||
export REMOTE_STORE=file://$REMOTE_STORE_DIR
|
||||
|
||||
buildDrvs () {
|
||||
nix build --file ./content-addressed.nix -L --no-link "$@"
|
||||
}
|
||||
|
||||
# Populate the remote cache
|
||||
clearStore
|
||||
nix copy --to $REMOTE_STORE --file ./content-addressed.nix
|
||||
|
||||
# Restart the build on an empty store, ensuring that we don't build
|
||||
clearStore
|
||||
buildDrvs --substitute --substituters $REMOTE_STORE --no-require-sigs -j0 transitivelyDependentCA
|
||||
# Check that the thing we’ve just substituted has its realisation stored
|
||||
nix realisation info --file ./content-addressed.nix transitivelyDependentCA
|
||||
# Check that its dependencies have it too
|
||||
nix realisation info --file ./content-addressed.nix dependentCA
|
||||
# nix realisation info --file ./content-addressed.nix rootCA --outputs out
|
||||
|
||||
if isDaemonNewer "2.13"; then
|
||||
pushToStore="../push-to-store.sh"
|
||||
else
|
||||
pushToStore="../push-to-store-old.sh"
|
||||
fi
|
||||
|
||||
# Same thing, but
|
||||
# 1. With non-ca derivations
|
||||
# 2. Erasing the realisations on the remote store
|
||||
#
|
||||
# Even in that case, realising the derivations should still produce the right
|
||||
# realisations on the local store
|
||||
#
|
||||
# Regression test for #4725
|
||||
clearStore
|
||||
nix build --file ../simple.nix -L --no-link --post-build-hook "$pushToStore"
|
||||
clearStore
|
||||
rm -r "$REMOTE_STORE_DIR/realisations"
|
||||
nix build --file ../simple.nix -L --no-link --substitute --substituters "$REMOTE_STORE" --no-require-sigs -j0
|
||||
# There's no easy way to check whether a realisation is present on the local
|
||||
# store − short of manually querying the db, but the build environment doesn't
|
||||
# have the sqlite binary − so we instead push things again, and check that the
|
||||
# realisations have correctly been pushed to the remote store
|
||||
nix copy --to "$REMOTE_STORE" --file ../simple.nix
|
||||
if [[ -z "$(ls "$REMOTE_STORE_DIR/realisations")" ]]; then
|
||||
echo "Realisations not rebuilt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test the local realisation disk cache
|
||||
buildDrvs --post-build-hook "$pushToStore"
|
||||
clearStore
|
||||
# Add the realisations of rootCA to the cachecache
|
||||
clearCacheCache
|
||||
export _NIX_FORCE_HTTP=1
|
||||
buildDrvs --substitute --substituters $REMOTE_STORE --no-require-sigs -j0
|
||||
# Try rebuilding, but remove the realisations from the remote cache to force
|
||||
# using the cachecache
|
||||
clearStore
|
||||
rm $REMOTE_STORE_DIR/realisations/*
|
||||
buildDrvs --substitute --substituters $REMOTE_STORE --no-require-sigs -j0
|
5
tests/functional/ca/why-depends.sh
Normal file
5
tests/functional/ca/why-depends.sh
Normal file
|
@ -0,0 +1,5 @@
|
|||
source common.sh
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
|
||||
cd .. && source why-depends.sh
|
19
tests/functional/case-hack.sh
Normal file
19
tests/functional/case-hack.sh
Normal file
|
@ -0,0 +1,19 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
|
||||
rm -rf $TEST_ROOT/case
|
||||
|
||||
opts="--option use-case-hack true"
|
||||
|
||||
# Check whether restoring and dumping a NAR that contains case
|
||||
# collisions is round-tripping, even on a case-insensitive system.
|
||||
nix-store $opts --restore $TEST_ROOT/case < case.nar
|
||||
nix-store $opts --dump $TEST_ROOT/case > $TEST_ROOT/case.nar
|
||||
cmp case.nar $TEST_ROOT/case.nar
|
||||
[ "$(nix-hash $opts --type sha256 $TEST_ROOT/case)" = "$(nix-hash --flat --type sha256 case.nar)" ]
|
||||
|
||||
# Check whether we detect true collisions (e.g. those remaining after
|
||||
# removal of the suffix).
|
||||
touch "$TEST_ROOT/case/xt_CONNMARK.h~nix~case~hack~3"
|
||||
(! nix-store $opts --dump $TEST_ROOT/case > /dev/null)
|
BIN
tests/functional/case.nar
Normal file
BIN
tests/functional/case.nar
Normal file
Binary file not shown.
77
tests/functional/check-refs.nix
Normal file
77
tests/functional/check-refs.nix
Normal file
|
@ -0,0 +1,77 @@
|
|||
with import ./config.nix;
|
||||
|
||||
rec {
|
||||
|
||||
dep = import ./dependencies.nix {};
|
||||
|
||||
makeTest = nr: args: mkDerivation ({
|
||||
name = "check-refs-" + toString nr;
|
||||
} // args);
|
||||
|
||||
src = builtins.toFile "aux-ref" "bla bla";
|
||||
|
||||
test1 = makeTest 1 {
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link";
|
||||
inherit dep;
|
||||
};
|
||||
|
||||
test2 = makeTest 2 {
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s ${src} $out/link";
|
||||
inherit dep;
|
||||
};
|
||||
|
||||
test3 = makeTest 3 {
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link";
|
||||
allowedReferences = [];
|
||||
inherit dep;
|
||||
};
|
||||
|
||||
test4 = makeTest 4 {
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link";
|
||||
allowedReferences = [dep];
|
||||
inherit dep;
|
||||
};
|
||||
|
||||
test5 = makeTest 5 {
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out";
|
||||
allowedReferences = [];
|
||||
inherit dep;
|
||||
};
|
||||
|
||||
test6 = makeTest 6 {
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $out $out/link";
|
||||
allowedReferences = [];
|
||||
inherit dep;
|
||||
};
|
||||
|
||||
test7 = makeTest 7 {
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $out $out/link";
|
||||
allowedReferences = ["out"];
|
||||
inherit dep;
|
||||
};
|
||||
|
||||
test8 = makeTest 8 {
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s ${test1} $out/link";
|
||||
inherit dep;
|
||||
};
|
||||
|
||||
test9 = makeTest 9 {
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $dep $out/link";
|
||||
inherit dep;
|
||||
disallowedReferences = [dep];
|
||||
};
|
||||
|
||||
test10 = makeTest 10 {
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; echo $test5; ln -s $dep $out/link";
|
||||
inherit dep test5;
|
||||
disallowedReferences = [test5];
|
||||
};
|
||||
|
||||
test11 = makeTest 11 {
|
||||
__structuredAttrs = true;
|
||||
unsafeDiscardReferences.out = true;
|
||||
outputChecks.out.allowedReferences = [];
|
||||
buildCommand = ''echo ${dep} > "''${outputs[out]}"'';
|
||||
};
|
||||
|
||||
}
|
53
tests/functional/check-refs.sh
Normal file
53
tests/functional/check-refs.sh
Normal file
|
@ -0,0 +1,53 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
|
||||
RESULT=$TEST_ROOT/result
|
||||
|
||||
dep=$(nix-build -o $RESULT check-refs.nix -A dep)
|
||||
|
||||
# test1 references dep, not itself.
|
||||
test1=$(nix-build -o $RESULT check-refs.nix -A test1)
|
||||
nix-store -q --references $test1 | grepQuietInverse $test1
|
||||
nix-store -q --references $test1 | grepQuiet $dep
|
||||
|
||||
# test2 references src, not itself nor dep.
|
||||
test2=$(nix-build -o $RESULT check-refs.nix -A test2)
|
||||
nix-store -q --references $test2 | grepQuietInverse $test2
|
||||
nix-store -q --references $test2 | grepQuietInverse $dep
|
||||
nix-store -q --references $test2 | grepQuiet aux-ref
|
||||
|
||||
# test3 should fail (unallowed ref).
|
||||
(! nix-build -o $RESULT check-refs.nix -A test3)
|
||||
|
||||
# test4 should succeed.
|
||||
nix-build -o $RESULT check-refs.nix -A test4
|
||||
|
||||
# test5 should succeed.
|
||||
nix-build -o $RESULT check-refs.nix -A test5
|
||||
|
||||
# test6 should fail (unallowed self-ref).
|
||||
(! nix-build -o $RESULT check-refs.nix -A test6)
|
||||
|
||||
# test7 should succeed (allowed self-ref).
|
||||
nix-build -o $RESULT check-refs.nix -A test7
|
||||
|
||||
# test8 should fail (toFile depending on derivation output).
|
||||
(! nix-build -o $RESULT check-refs.nix -A test8)
|
||||
|
||||
# test9 should fail (disallowed reference).
|
||||
(! nix-build -o $RESULT check-refs.nix -A test9)
|
||||
|
||||
# test10 should succeed (no disallowed references).
|
||||
nix-build -o $RESULT check-refs.nix -A test10
|
||||
|
||||
if isDaemonNewer 2.12pre20230103; then
|
||||
if ! isDaemonNewer 2.16.0; then
|
||||
enableFeatures discard-references
|
||||
restartDaemon
|
||||
fi
|
||||
|
||||
# test11 should succeed.
|
||||
test11=$(nix-build -o $RESULT check-refs.nix -A test11)
|
||||
[[ -z $(nix-store -q --references "$test11") ]]
|
||||
fi
|
57
tests/functional/check-reqs.nix
Normal file
57
tests/functional/check-reqs.nix
Normal file
|
@ -0,0 +1,57 @@
|
|||
with import ./config.nix;
|
||||
|
||||
rec {
|
||||
dep1 = mkDerivation {
|
||||
name = "check-reqs-dep1";
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; touch $out/file1";
|
||||
};
|
||||
|
||||
dep2 = mkDerivation {
|
||||
name = "check-reqs-dep2";
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; touch $out/file2";
|
||||
};
|
||||
|
||||
deps = mkDerivation {
|
||||
name = "check-reqs-deps";
|
||||
dep1 = dep1;
|
||||
dep2 = dep2;
|
||||
builder = builtins.toFile "builder.sh" ''
|
||||
mkdir $out
|
||||
ln -s $dep1/file1 $out/file1
|
||||
ln -s $dep2/file2 $out/file2
|
||||
'';
|
||||
};
|
||||
|
||||
makeTest = nr: allowreqs: mkDerivation {
|
||||
name = "check-reqs-" + toString nr;
|
||||
inherit deps;
|
||||
builder = builtins.toFile "builder.sh" ''
|
||||
mkdir $out
|
||||
ln -s $deps $out/depdir1
|
||||
'';
|
||||
allowedRequisites = allowreqs;
|
||||
};
|
||||
|
||||
# When specifying all the requisites, the build succeeds.
|
||||
test1 = makeTest 1 [ dep1 dep2 deps ];
|
||||
|
||||
# But missing anything it fails.
|
||||
test2 = makeTest 2 [ dep2 deps ];
|
||||
test3 = makeTest 3 [ dep1 deps ];
|
||||
test4 = makeTest 4 [ deps ];
|
||||
test5 = makeTest 5 [];
|
||||
|
||||
test6 = mkDerivation {
|
||||
name = "check-reqs";
|
||||
inherit deps;
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $deps $out/depdir1";
|
||||
disallowedRequisites = [dep1];
|
||||
};
|
||||
|
||||
test7 = mkDerivation {
|
||||
name = "check-reqs";
|
||||
inherit deps;
|
||||
builder = builtins.toFile "builder.sh" "mkdir $out; ln -s $deps $out/depdir1";
|
||||
disallowedRequisites = [test1];
|
||||
};
|
||||
}
|
16
tests/functional/check-reqs.sh
Normal file
16
tests/functional/check-reqs.sh
Normal file
|
@ -0,0 +1,16 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
|
||||
RESULT=$TEST_ROOT/result
|
||||
|
||||
nix-build -o $RESULT check-reqs.nix -A test1
|
||||
|
||||
(! nix-build -o $RESULT check-reqs.nix -A test2)
|
||||
(! nix-build -o $RESULT check-reqs.nix -A test3)
|
||||
(! nix-build -o $RESULT check-reqs.nix -A test4) 2>&1 | grepQuiet 'check-reqs-dep1'
|
||||
(! nix-build -o $RESULT check-reqs.nix -A test4) 2>&1 | grepQuiet 'check-reqs-dep2'
|
||||
(! nix-build -o $RESULT check-reqs.nix -A test5)
|
||||
(! nix-build -o $RESULT check-reqs.nix -A test6)
|
||||
|
||||
nix-build -o $RESULT check-reqs.nix -A test7
|
55
tests/functional/check.nix
Normal file
55
tests/functional/check.nix
Normal file
|
@ -0,0 +1,55 @@
|
|||
{checkBuildId ? 0}:
|
||||
|
||||
with import ./config.nix;
|
||||
|
||||
{
|
||||
nondeterministic = mkDerivation {
|
||||
inherit checkBuildId;
|
||||
name = "nondeterministic";
|
||||
buildCommand =
|
||||
''
|
||||
mkdir $out
|
||||
date +%s.%N > $out/date
|
||||
echo "CHECK_TMPDIR=$TMPDIR"
|
||||
echo "checkBuildId=$checkBuildId"
|
||||
echo "$checkBuildId" > $TMPDIR/checkBuildId
|
||||
'';
|
||||
};
|
||||
|
||||
deterministic = mkDerivation {
|
||||
inherit checkBuildId;
|
||||
name = "deterministic";
|
||||
buildCommand =
|
||||
''
|
||||
mkdir $out
|
||||
echo date > $out/date
|
||||
echo "CHECK_TMPDIR=$TMPDIR"
|
||||
echo "checkBuildId=$checkBuildId"
|
||||
echo "$checkBuildId" > $TMPDIR/checkBuildId
|
||||
'';
|
||||
};
|
||||
|
||||
failed = mkDerivation {
|
||||
inherit checkBuildId;
|
||||
name = "failed";
|
||||
buildCommand =
|
||||
''
|
||||
mkdir $out
|
||||
echo date > $out/date
|
||||
echo "CHECK_TMPDIR=$TMPDIR"
|
||||
echo "checkBuildId=$checkBuildId"
|
||||
echo "$checkBuildId" > $TMPDIR/checkBuildId
|
||||
false
|
||||
'';
|
||||
};
|
||||
|
||||
hashmismatch = import <nix/fetchurl.nix> {
|
||||
url = "file://" + builtins.getEnv "TEST_ROOT" + "/dummy";
|
||||
sha256 = "0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73";
|
||||
};
|
||||
|
||||
fetchurl = import <nix/fetchurl.nix> {
|
||||
url = "file://" + toString ./lang/eval-okay-xml.exp.xml;
|
||||
sha256 = "sha256-behBlX+DQK/Pjvkuc8Tx68Jwi4E5v86wDq+ZLaHyhQE=";
|
||||
};
|
||||
}
|
91
tests/functional/check.sh
Normal file
91
tests/functional/check.sh
Normal file
|
@ -0,0 +1,91 @@
|
|||
source common.sh
|
||||
|
||||
# XXX: This shouldn’t be, but #4813 cause this test to fail
|
||||
buggyNeedLocalStore "see #4813"
|
||||
|
||||
checkBuildTempDirRemoved ()
|
||||
{
|
||||
buildDir=$(sed -n 's/CHECK_TMPDIR=//p' $1 | head -1)
|
||||
checkBuildIdFile=${buildDir}/checkBuildId
|
||||
[[ ! -f $checkBuildIdFile ]] || ! grep $checkBuildId $checkBuildIdFile
|
||||
}
|
||||
|
||||
# written to build temp directories to verify created by this instance
|
||||
checkBuildId=$(date +%s%N)
|
||||
|
||||
clearStore
|
||||
|
||||
nix-build dependencies.nix --no-out-link
|
||||
nix-build dependencies.nix --no-out-link --check
|
||||
|
||||
# Build failure exit codes (100, 104, etc.) are from
|
||||
# doc/manual/src/command-ref/status-build-failure.md
|
||||
|
||||
# check for dangling temporary build directories
|
||||
# only retain if build fails and --keep-failed is specified, or...
|
||||
# ...build is non-deterministic and --check and --keep-failed are both specified
|
||||
nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \
|
||||
--no-out-link 2> $TEST_ROOT/log || status=$?
|
||||
[ "$status" = "100" ]
|
||||
checkBuildTempDirRemoved $TEST_ROOT/log
|
||||
|
||||
nix-build check.nix -A failed --argstr checkBuildId $checkBuildId \
|
||||
--no-out-link --keep-failed 2> $TEST_ROOT/log || status=$?
|
||||
[ "$status" = "100" ]
|
||||
if checkBuildTempDirRemoved $TEST_ROOT/log; then false; fi
|
||||
|
||||
nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \
|
||||
--no-out-link 2> $TEST_ROOT/log
|
||||
checkBuildTempDirRemoved $TEST_ROOT/log
|
||||
|
||||
nix-build check.nix -A deterministic --argstr checkBuildId $checkBuildId \
|
||||
--no-out-link --check --keep-failed 2> $TEST_ROOT/log
|
||||
if grepQuiet 'may not be deterministic' $TEST_ROOT/log; then false; fi
|
||||
checkBuildTempDirRemoved $TEST_ROOT/log
|
||||
|
||||
nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \
|
||||
--no-out-link 2> $TEST_ROOT/log
|
||||
checkBuildTempDirRemoved $TEST_ROOT/log
|
||||
|
||||
nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \
|
||||
--no-out-link --check 2> $TEST_ROOT/log || status=$?
|
||||
grep 'may not be deterministic' $TEST_ROOT/log
|
||||
[ "$status" = "104" ]
|
||||
checkBuildTempDirRemoved $TEST_ROOT/log
|
||||
|
||||
nix-build check.nix -A nondeterministic --argstr checkBuildId $checkBuildId \
|
||||
--no-out-link --check --keep-failed 2> $TEST_ROOT/log || status=$?
|
||||
grep 'may not be deterministic' $TEST_ROOT/log
|
||||
[ "$status" = "104" ]
|
||||
if checkBuildTempDirRemoved $TEST_ROOT/log; then false; fi
|
||||
|
||||
clearStore
|
||||
|
||||
path=$(nix-build check.nix -A fetchurl --no-out-link)
|
||||
|
||||
chmod +w $path
|
||||
echo foo > $path
|
||||
chmod -w $path
|
||||
|
||||
nix-build check.nix -A fetchurl --no-out-link --check
|
||||
# Note: "check" doesn't repair anything, it just compares to the hash stored in the database.
|
||||
[[ $(cat $path) = foo ]]
|
||||
|
||||
nix-build check.nix -A fetchurl --no-out-link --repair
|
||||
[[ $(cat $path) != foo ]]
|
||||
|
||||
echo 'Hello World' > $TEST_ROOT/dummy
|
||||
nix-build check.nix -A hashmismatch --no-out-link || status=$?
|
||||
[ "$status" = "102" ]
|
||||
|
||||
echo -n > $TEST_ROOT/dummy
|
||||
nix-build check.nix -A hashmismatch --no-out-link
|
||||
echo 'Hello World' > $TEST_ROOT/dummy
|
||||
|
||||
nix-build check.nix -A hashmismatch --no-out-link --check || status=$?
|
||||
[ "$status" = "102" ]
|
||||
|
||||
# Multiple failures with --keep-going
|
||||
nix-build check.nix -A nondeterministic --no-out-link
|
||||
nix-build check.nix -A nondeterministic -A hashmismatch --no-out-link --check --keep-going || status=$?
|
||||
[ "$status" = "110" ]
|
12
tests/functional/common.sh
Normal file
12
tests/functional/common.sh
Normal file
|
@ -0,0 +1,12 @@
|
|||
set -eu -o pipefail
|
||||
|
||||
if [[ -z "${COMMON_SH_SOURCED-}" ]]; then
|
||||
|
||||
COMMON_SH_SOURCED=1
|
||||
|
||||
source "$(readlink -f "$(dirname "${BASH_SOURCE[0]-$0}")")/common/vars-and-functions.sh"
|
||||
if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then
|
||||
startDaemon
|
||||
fi
|
||||
|
||||
fi # COMMON_SH_SOURCED
|
276
tests/functional/common/vars-and-functions.sh.in
Normal file
276
tests/functional/common/vars-and-functions.sh.in
Normal file
|
@ -0,0 +1,276 @@
|
|||
set -eu -o pipefail
|
||||
|
||||
if [[ -z "${COMMON_VARS_AND_FUNCTIONS_SH_SOURCED-}" ]]; then
|
||||
|
||||
COMMON_VARS_AND_FUNCTIONS_SH_SOURCED=1
|
||||
|
||||
set +x
|
||||
|
||||
export TEST_ROOT=$(realpath ${TMPDIR:-/tmp}/nix-test)/${TEST_NAME:-default/tests\/functional//}
|
||||
export NIX_STORE_DIR
|
||||
if ! NIX_STORE_DIR=$(readlink -f $TEST_ROOT/store 2> /dev/null); then
|
||||
# Maybe the build directory is symlinked.
|
||||
export NIX_IGNORE_SYMLINK_STORE=1
|
||||
NIX_STORE_DIR=$TEST_ROOT/store
|
||||
fi
|
||||
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
|
||||
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
|
||||
export NIX_STATE_DIR=$TEST_ROOT/var/nix
|
||||
export NIX_CONF_DIR=$TEST_ROOT/etc
|
||||
export NIX_DAEMON_SOCKET_PATH=$TEST_ROOT/dSocket
|
||||
unset NIX_USER_CONF_FILES
|
||||
export _NIX_TEST_SHARED=$TEST_ROOT/shared
|
||||
if [[ -n $NIX_STORE ]]; then
|
||||
export _NIX_TEST_NO_SANDBOX=1
|
||||
fi
|
||||
export _NIX_IN_TEST=$TEST_ROOT/shared
|
||||
export _NIX_TEST_NO_LSOF=1
|
||||
export NIX_REMOTE=${NIX_REMOTE_-}
|
||||
unset NIX_PATH
|
||||
export TEST_HOME=$TEST_ROOT/test-home
|
||||
export HOME=$TEST_HOME
|
||||
unset XDG_STATE_HOME
|
||||
unset XDG_DATA_HOME
|
||||
unset XDG_CONFIG_HOME
|
||||
unset XDG_CONFIG_DIRS
|
||||
unset XDG_CACHE_HOME
|
||||
mkdir -p $TEST_HOME
|
||||
|
||||
export PATH=@bindir@:$PATH
|
||||
if [[ -n "${NIX_CLIENT_PACKAGE:-}" ]]; then
|
||||
export PATH="$NIX_CLIENT_PACKAGE/bin":$PATH
|
||||
fi
|
||||
DAEMON_PATH="$PATH"
|
||||
if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then
|
||||
DAEMON_PATH="${NIX_DAEMON_PACKAGE}/bin:$DAEMON_PATH"
|
||||
fi
|
||||
coreutils=@coreutils@
|
||||
|
||||
export dot=@dot@
|
||||
export SHELL="@bash@"
|
||||
export PAGER=cat
|
||||
export busybox="@sandbox_shell@"
|
||||
|
||||
export version=@PACKAGE_VERSION@
|
||||
export system=@system@
|
||||
|
||||
export BUILD_SHARED_LIBS=@BUILD_SHARED_LIBS@
|
||||
|
||||
export IMPURE_VAR1=foo
|
||||
export IMPURE_VAR2=bar
|
||||
|
||||
cacheDir=$TEST_ROOT/binary-cache
|
||||
|
||||
readLink() {
|
||||
ls -l "$1" | sed 's/.*->\ //'
|
||||
}
|
||||
|
||||
clearProfiles() {
|
||||
profiles="$HOME"/.local/state/nix/profiles
|
||||
rm -rf "$profiles"
|
||||
}
|
||||
|
||||
clearStore() {
|
||||
echo "clearing store..."
|
||||
chmod -R +w "$NIX_STORE_DIR"
|
||||
rm -rf "$NIX_STORE_DIR"
|
||||
mkdir "$NIX_STORE_DIR"
|
||||
rm -rf "$NIX_STATE_DIR"
|
||||
mkdir "$NIX_STATE_DIR"
|
||||
clearProfiles
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
rm -rf "$cacheDir"
|
||||
}
|
||||
|
||||
clearCacheCache() {
|
||||
rm -f $TEST_HOME/.cache/nix/binary-cache*
|
||||
}
|
||||
|
||||
startDaemon() {
|
||||
# Don’t start the daemon twice, as this would just make it loop indefinitely
|
||||
if [[ "${_NIX_TEST_DAEMON_PID-}" != '' ]]; then
|
||||
return
|
||||
fi
|
||||
# Start the daemon, wait for the socket to appear.
|
||||
rm -f $NIX_DAEMON_SOCKET_PATH
|
||||
PATH=$DAEMON_PATH nix-daemon &
|
||||
_NIX_TEST_DAEMON_PID=$!
|
||||
export _NIX_TEST_DAEMON_PID
|
||||
for ((i = 0; i < 300; i++)); do
|
||||
if [[ -S $NIX_DAEMON_SOCKET_PATH ]]; then
|
||||
DAEMON_STARTED=1
|
||||
break;
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
if [[ -z ${DAEMON_STARTED+x} ]]; then
|
||||
fail "Didn’t manage to start the daemon"
|
||||
fi
|
||||
trap "killDaemon" EXIT
|
||||
# Save for if daemon is killed
|
||||
NIX_REMOTE_OLD=$NIX_REMOTE
|
||||
export NIX_REMOTE=daemon
|
||||
}
|
||||
|
||||
killDaemon() {
|
||||
# Don’t fail trying to stop a non-existant daemon twice
|
||||
if [[ "${_NIX_TEST_DAEMON_PID-}" == '' ]]; then
|
||||
return
|
||||
fi
|
||||
kill $_NIX_TEST_DAEMON_PID
|
||||
for i in {0..100}; do
|
||||
kill -0 $_NIX_TEST_DAEMON_PID 2> /dev/null || break
|
||||
sleep 0.1
|
||||
done
|
||||
kill -9 $_NIX_TEST_DAEMON_PID 2> /dev/null || true
|
||||
wait $_NIX_TEST_DAEMON_PID || true
|
||||
rm -f $NIX_DAEMON_SOCKET_PATH
|
||||
# Indicate daemon is stopped
|
||||
unset _NIX_TEST_DAEMON_PID
|
||||
# Restore old nix remote
|
||||
NIX_REMOTE=$NIX_REMOTE_OLD
|
||||
trap "" EXIT
|
||||
}
|
||||
|
||||
restartDaemon() {
|
||||
[[ -z "${_NIX_TEST_DAEMON_PID:-}" ]] && return 0
|
||||
|
||||
killDaemon
|
||||
startDaemon
|
||||
}
|
||||
|
||||
if [[ $(uname) == Linux ]] && [[ -L /proc/self/ns/user ]] && unshare --user true; then
|
||||
_canUseSandbox=1
|
||||
fi
|
||||
|
||||
isDaemonNewer () {
|
||||
[[ -n "${NIX_DAEMON_PACKAGE:-}" ]] || return 0
|
||||
local requiredVersion="$1"
|
||||
local daemonVersion=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3)
|
||||
[[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''$requiredVersion''") -ge 0 ]]
|
||||
}
|
||||
|
||||
skipTest () {
|
||||
echo "$1, skipping this test..." >&2
|
||||
exit 99
|
||||
}
|
||||
|
||||
requireDaemonNewerThan () {
|
||||
isDaemonNewer "$1" || skipTest "Daemon is too old"
|
||||
}
|
||||
|
||||
canUseSandbox() {
|
||||
[[ ${_canUseSandbox-} ]]
|
||||
}
|
||||
|
||||
requireSandboxSupport () {
|
||||
canUseSandbox || skipTest "Sandboxing not supported"
|
||||
}
|
||||
|
||||
requireGit() {
|
||||
[[ $(type -p git) ]] || skipTest "Git not installed"
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Run a command failing if it didn't exit with the expected exit code.
|
||||
#
|
||||
# Has two advantages over the built-in `!`:
|
||||
#
|
||||
# 1. `!` conflates all non-0 codes. `expect` allows testing for an exact
|
||||
# code.
|
||||
#
|
||||
# 2. `!` unexpectedly negates `set -e`, and cannot be used on individual
|
||||
# pipeline stages with `set -o pipefail`. It only works on the entire
|
||||
# pipeline, which is useless if we want, say, `nix ...` invocation to
|
||||
# *fail*, but a grep on the error message it outputs to *succeed*.
|
||||
expect() {
|
||||
local expected res
|
||||
expected="$1"
|
||||
shift
|
||||
"$@" && res=0 || res="$?"
|
||||
if [[ $res -ne $expected ]]; then
|
||||
echo "Expected exit code '$expected' but got '$res' from command ${*@Q}" >&2
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Better than just doing `expect ... >&2` because the "Expected..."
|
||||
# message below will *not* be redirected.
|
||||
expectStderr() {
|
||||
local expected res
|
||||
expected="$1"
|
||||
shift
|
||||
"$@" 2>&1 && res=0 || res="$?"
|
||||
if [[ $res -ne $expected ]]; then
|
||||
echo "Expected exit code '$expected' but got '$res' from command ${*@Q}" >&2
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
needLocalStore() {
|
||||
if [[ "$NIX_REMOTE" == "daemon" ]]; then
|
||||
skipTest "Can’t run through the daemon ($1)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Just to make it easy to find which tests should be fixed
|
||||
buggyNeedLocalStore() {
|
||||
needLocalStore "$1"
|
||||
}
|
||||
|
||||
enableFeatures() {
|
||||
local features="$1"
|
||||
sed -i 's/experimental-features .*/& '"$features"'/' "$NIX_CONF_DIR"/nix.conf
|
||||
}
|
||||
|
||||
set -x
|
||||
|
||||
onError() {
|
||||
set +x
|
||||
echo "$0: test failed at:" >&2
|
||||
for ((i = 1; i < ${#BASH_SOURCE[@]}; i++)); do
|
||||
if [[ -z ${BASH_SOURCE[i]} ]]; then break; fi
|
||||
echo " ${FUNCNAME[i]} in ${BASH_SOURCE[i]}:${BASH_LINENO[i-1]}" >&2
|
||||
done
|
||||
}
|
||||
|
||||
# `grep -v` doesn't work well for exit codes. We want `!(exist line l. l
|
||||
# matches)`. It gives us `exist line l. !(l matches)`.
|
||||
#
|
||||
# `!` normally doesn't work well with `set -e`, but when we wrap in a
|
||||
# function it *does*.
|
||||
grepInverse() {
|
||||
! grep "$@"
|
||||
}
|
||||
|
||||
# A shorthand, `> /dev/null` is a bit noisy.
|
||||
#
|
||||
# `grep -q` would seem to do this, no function necessary, but it is a
|
||||
# bad fit with pipes and `set -o pipefail`: `-q` will exit after the
|
||||
# first match, and then subsequent writes will result in broken pipes.
|
||||
#
|
||||
# Note that reproducing the above is a bit tricky as it depends on
|
||||
# non-deterministic properties such as the timing between the match and
|
||||
# the closing of the pipe, the buffering of the pipe, and the speed of
|
||||
# the producer into the pipe. But rest assured we've seen it happen in
|
||||
# CI reliably.
|
||||
grepQuiet() {
|
||||
grep "$@" > /dev/null
|
||||
}
|
||||
|
||||
# The previous two, combined
|
||||
grepQuietInverse() {
|
||||
! grep "$@" > /dev/null
|
||||
}
|
||||
|
||||
trap onError ERR
|
||||
|
||||
fi # COMMON_VARS_AND_FUNCTIONS_SH_SOURCED
|
73
tests/functional/completions.sh
Normal file
73
tests/functional/completions.sh
Normal file
|
@ -0,0 +1,73 @@
|
|||
source common.sh
|
||||
|
||||
cd "$TEST_ROOT"
|
||||
|
||||
mkdir -p dep
|
||||
cat <<EOF > dep/flake.nix
|
||||
{
|
||||
outputs = i: { };
|
||||
}
|
||||
EOF
|
||||
mkdir -p foo
|
||||
cat <<EOF > foo/flake.nix
|
||||
{
|
||||
inputs.a.url = "path:$(realpath dep)";
|
||||
|
||||
outputs = i: {
|
||||
sampleOutput = 1;
|
||||
};
|
||||
}
|
||||
EOF
|
||||
mkdir -p bar
|
||||
cat <<EOF > bar/flake.nix
|
||||
{
|
||||
inputs.b.url = "path:$(realpath dep)";
|
||||
|
||||
outputs = i: {
|
||||
sampleOutput = 1;
|
||||
};
|
||||
}
|
||||
EOF
|
||||
mkdir -p err
|
||||
cat <<EOF > err/flake.nix
|
||||
throw "error"
|
||||
EOF
|
||||
|
||||
# Test the completion of a subcommand
|
||||
[[ "$(NIX_GET_COMPLETIONS=1 nix buil)" == $'normal\nbuild\t' ]]
|
||||
[[ "$(NIX_GET_COMPLETIONS=2 nix flake metad)" == $'normal\nmetadata\t' ]]
|
||||
|
||||
# Filename completion
|
||||
[[ "$(NIX_GET_COMPLETIONS=2 nix build ./f)" == $'filenames\n./foo\t' ]]
|
||||
[[ "$(NIX_GET_COMPLETIONS=2 nix build ./nonexistent)" == $'filenames' ]]
|
||||
|
||||
# Input override completion
|
||||
[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --override-input '')" == $'normal\na\t' ]]
|
||||
[[ "$(NIX_GET_COMPLETIONS=5 nix flake show ./foo --override-input '')" == $'normal\na\t' ]]
|
||||
cd ./foo
|
||||
[[ "$(NIX_GET_COMPLETIONS=3 nix flake update '')" == $'normal\na\t' ]]
|
||||
cd ..
|
||||
[[ "$(NIX_GET_COMPLETIONS=5 nix flake update --flake './foo' '')" == $'normal\na\t' ]]
|
||||
## With multiple input flakes
|
||||
[[ "$(NIX_GET_COMPLETIONS=5 nix build ./foo ./bar --override-input '')" == $'normal\na\t\nb\t' ]]
|
||||
## With tilde expansion
|
||||
[[ "$(HOME=$PWD NIX_GET_COMPLETIONS=4 nix build '~/foo' --override-input '')" == $'normal\na\t' ]]
|
||||
[[ "$(HOME=$PWD NIX_GET_COMPLETIONS=5 nix flake update --flake '~/foo' '')" == $'normal\na\t' ]]
|
||||
## Out of order
|
||||
[[ "$(NIX_GET_COMPLETIONS=3 nix build --override-input '' '' ./foo)" == $'normal\na\t' ]]
|
||||
[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --override-input '' '' ./bar)" == $'normal\na\t\nb\t' ]]
|
||||
|
||||
# Cli flag completion
|
||||
NIX_GET_COMPLETIONS=2 nix build --log-form | grep -- "--log-format"
|
||||
|
||||
# Config option completion
|
||||
## With `--option`
|
||||
NIX_GET_COMPLETIONS=3 nix build --option allow-import-from | grep -- "allow-import-from-derivation"
|
||||
## As a cli flag – not working atm
|
||||
# NIX_GET_COMPLETIONS=2 nix build --allow-import-from | grep -- "allow-import-from-derivation"
|
||||
|
||||
# Attr path completions
|
||||
[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./foo\#sam)" == $'attrs\n./foo#sampleOutput\t' ]]
|
||||
[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./foo/flake.nix outp)" == $'attrs\noutputs\t' ]]
|
||||
[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./err/flake.nix outp 2>&1)" == $'attrs' ]]
|
||||
[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./err\# 2>&1)" == $'attrs' ]]
|
22
tests/functional/compression-levels.sh
Normal file
22
tests/functional/compression-levels.sh
Normal file
|
@ -0,0 +1,22 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
clearCache
|
||||
|
||||
outPath=$(nix-build dependencies.nix --no-out-link)
|
||||
|
||||
cacheURI="file://$cacheDir?compression=xz&compression-level=0"
|
||||
|
||||
nix copy --to $cacheURI $outPath
|
||||
|
||||
FILESIZES=$(cat ${cacheDir}/*.narinfo | awk '/FileSize: /{sum+=$2}END{print sum}')
|
||||
|
||||
clearCache
|
||||
|
||||
cacheURI="file://$cacheDir?compression=xz&compression-level=5"
|
||||
|
||||
nix copy --to $cacheURI $outPath
|
||||
|
||||
FILESIZES2=$(cat ${cacheDir}/*.narinfo | awk '/FileSize: /{sum+=$2}END{print sum}')
|
||||
|
||||
[[ $FILESIZES -gt $FILESIZES2 ]]
|
7
tests/functional/compute-levels.sh
Normal file
7
tests/functional/compute-levels.sh
Normal file
|
@ -0,0 +1,7 @@
|
|||
source common.sh
|
||||
|
||||
if [[ $(uname -ms) = "Linux x86_64" ]]; then
|
||||
# x86_64 CPUs must always support the baseline
|
||||
# microarchitecture level.
|
||||
nix -vv --version | grepQuiet "x86_64-v1-linux"
|
||||
fi
|
30
tests/functional/config.nix.in
Normal file
30
tests/functional/config.nix.in
Normal file
|
@ -0,0 +1,30 @@
|
|||
let
|
||||
contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1";
|
||||
caArgs = if contentAddressedByDefault then {
|
||||
__contentAddressed = true;
|
||||
outputHashMode = "recursive";
|
||||
outputHashAlgo = "sha256";
|
||||
} else {};
|
||||
in
|
||||
|
||||
rec {
|
||||
shell = "@bash@";
|
||||
|
||||
path = "@coreutils@";
|
||||
|
||||
system = "@system@";
|
||||
|
||||
shared = builtins.getEnv "_NIX_TEST_SHARED";
|
||||
|
||||
mkDerivation = args:
|
||||
derivation ({
|
||||
inherit system;
|
||||
builder = shell;
|
||||
args = ["-e" args.builder or (builtins.toFile "builder-${args.name}.sh" ''
|
||||
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
|
||||
eval "$buildCommand"
|
||||
'')];
|
||||
PATH = path;
|
||||
} // caArgs // removeAttrs args ["builder" "meta"])
|
||||
// { meta = args.meta or {}; };
|
||||
}
|
59
tests/functional/config.sh
Normal file
59
tests/functional/config.sh
Normal file
|
@ -0,0 +1,59 @@
|
|||
source common.sh
|
||||
|
||||
# Isolate the home for this test.
|
||||
# Other tests (e.g. flake registry tests) could be writing to $HOME in parallel.
|
||||
export HOME=$TEST_ROOT/userhome
|
||||
|
||||
# Test that using XDG_CONFIG_HOME works
|
||||
# Assert the config folder didn't exist initially.
|
||||
[ ! -e "$HOME/.config" ]
|
||||
# Without XDG_CONFIG_HOME, creates $HOME/.config
|
||||
unset XDG_CONFIG_HOME
|
||||
# Run against the nix registry to create the config dir
|
||||
# (Tip: this relies on removing non-existent entries being a no-op!)
|
||||
nix registry remove userhome-without-xdg
|
||||
# Verifies it created it
|
||||
[ -e "$HOME/.config" ]
|
||||
# Remove the directory it created
|
||||
rm -rf "$HOME/.config"
|
||||
# Run the same test, but with XDG_CONFIG_HOME
|
||||
export XDG_CONFIG_HOME=$TEST_ROOT/confighome
|
||||
# Assert the XDG_CONFIG_HOME/nix path does not exist yet.
|
||||
[ ! -e "$TEST_ROOT/confighome/nix" ]
|
||||
nix registry remove userhome-with-xdg
|
||||
# Verifies the confighome path has been created
|
||||
[ -e "$TEST_ROOT/confighome/nix" ]
|
||||
# Assert the .config folder hasn't been created.
|
||||
[ ! -e "$HOME/.config" ]
|
||||
|
||||
# Test that files are loaded from XDG by default
|
||||
export XDG_CONFIG_HOME=$TEST_ROOT/confighome
|
||||
export XDG_CONFIG_DIRS=$TEST_ROOT/dir1:$TEST_ROOT/dir2
|
||||
files=$(nix-build --verbose --version | grep "User config" | cut -d ':' -f2- | xargs)
|
||||
[[ $files == "$TEST_ROOT/confighome/nix/nix.conf:$TEST_ROOT/dir1/nix/nix.conf:$TEST_ROOT/dir2/nix/nix.conf" ]]
|
||||
|
||||
# Test that setting NIX_USER_CONF_FILES overrides all the default user config files
|
||||
export NIX_USER_CONF_FILES=$TEST_ROOT/file1.conf:$TEST_ROOT/file2.conf
|
||||
files=$(nix-build --verbose --version | grep "User config" | cut -d ':' -f2- | xargs)
|
||||
[[ $files == "$TEST_ROOT/file1.conf:$TEST_ROOT/file2.conf" ]]
|
||||
|
||||
# Test that it's possible to load the config from a custom location
|
||||
here=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")
|
||||
export NIX_USER_CONF_FILES=$here/config/nix-with-substituters.conf
|
||||
var=$(nix show-config | grep '^substituters =' | cut -d '=' -f 2 | xargs)
|
||||
[[ $var == https://example.com ]]
|
||||
|
||||
# Test that it's possible to load config from the environment
|
||||
prev=$(nix show-config | grep '^cores' | cut -d '=' -f 2 | xargs)
|
||||
export NIX_CONFIG="cores = 4242"$'\n'"experimental-features = nix-command flakes"
|
||||
exp_cores=$(nix show-config | grep '^cores' | cut -d '=' -f 2 | xargs)
|
||||
exp_features=$(nix show-config | grep '^experimental-features' | cut -d '=' -f 2 | xargs)
|
||||
[[ $prev != $exp_cores ]]
|
||||
[[ $exp_cores == "4242" ]]
|
||||
# flakes implies fetch-tree
|
||||
[[ $exp_features == "fetch-tree flakes nix-command" ]]
|
||||
|
||||
# Test that it's possible to retrieve a single setting's value
|
||||
val=$(nix show-config | grep '^warn-dirty' | cut -d '=' -f 2 | xargs)
|
||||
val2=$(nix show-config warn-dirty)
|
||||
[[ $val == $val2 ]]
|
2
tests/functional/config/nix-with-substituters.conf
Normal file
2
tests/functional/config/nix-with-substituters.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
experimental-features = nix-command
|
||||
substituters = https://example.com
|
28
tests/functional/db-migration.sh
Normal file
28
tests/functional/db-migration.sh
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Test that we can successfully migrate from an older db schema
|
||||
|
||||
source common.sh
|
||||
|
||||
# Only run this if we have an older Nix available
|
||||
# XXX: This assumes that the `daemon` package is older than the `client` one
|
||||
if [[ -z "${NIX_DAEMON_PACKAGE-}" ]]; then
|
||||
skipTest "not using the Nix daemon"
|
||||
fi
|
||||
|
||||
killDaemon
|
||||
|
||||
# Fill the db using the older Nix
|
||||
PATH_WITH_NEW_NIX="$PATH"
|
||||
export PATH="${NIX_DAEMON_PACKAGE}/bin:$PATH"
|
||||
clearStore
|
||||
nix-build simple.nix --no-out-link
|
||||
nix-store --generate-binary-cache-key cache1.example.org $TEST_ROOT/sk1 $TEST_ROOT/pk1
|
||||
dependenciesOutPath=$(nix-build dependencies.nix --no-out-link --secret-key-files "$TEST_ROOT/sk1")
|
||||
fixedOutPath=$(IMPURE_VAR1=foo IMPURE_VAR2=bar nix-build fixed.nix -A good.0 --no-out-link)
|
||||
|
||||
# Migrate to the new schema and ensure that everything's there
|
||||
export PATH="$PATH_WITH_NEW_NIX"
|
||||
info=$(nix path-info --json $dependenciesOutPath)
|
||||
[[ $info =~ '"ultimate":true' ]]
|
||||
[[ $info =~ 'cache1.example.org' ]]
|
||||
nix verify -r "$fixedOutPath"
|
||||
nix verify -r "$dependenciesOutPath" --sigs-needed 1 --trusted-public-keys $(cat $TEST_ROOT/pk1)
|
16
tests/functional/dependencies.builder0.sh
Normal file
16
tests/functional/dependencies.builder0.sh
Normal file
|
@ -0,0 +1,16 @@
|
|||
[ "${input1: -2}" = /. ]
|
||||
[ "${input2: -2}" = /. ]
|
||||
|
||||
mkdir $out
|
||||
echo $(cat $input1/foo)$(cat $input2/bar) > $out/foobar
|
||||
|
||||
ln -s $input2 $out/reference-to-input-2
|
||||
|
||||
# Self-reference.
|
||||
ln -s $out $out/self
|
||||
|
||||
# Executable.
|
||||
echo program > $out/program
|
||||
chmod +x $out/program
|
||||
|
||||
echo FOO
|
48
tests/functional/dependencies.nix
Normal file
48
tests/functional/dependencies.nix
Normal file
|
@ -0,0 +1,48 @@
|
|||
{ hashInvalidator ? "" }:
|
||||
with import ./config.nix;
|
||||
|
||||
let {
|
||||
|
||||
input0 = mkDerivation {
|
||||
name = "dependencies-input-0";
|
||||
buildCommand = "mkdir $out; echo foo > $out/bar";
|
||||
};
|
||||
|
||||
input1 = mkDerivation {
|
||||
name = "dependencies-input-1";
|
||||
buildCommand = "mkdir $out; echo FOO > $out/foo";
|
||||
};
|
||||
|
||||
input2 = mkDerivation {
|
||||
name = "dependencies-input-2";
|
||||
buildCommand = ''
|
||||
mkdir $out
|
||||
echo BAR > $out/bar
|
||||
echo ${input0} > $out/input0
|
||||
'';
|
||||
};
|
||||
|
||||
fod_input = mkDerivation {
|
||||
name = "fod-input";
|
||||
buildCommand = ''
|
||||
echo ${hashInvalidator}
|
||||
echo FOD > $out
|
||||
'';
|
||||
outputHashMode = "flat";
|
||||
outputHashAlgo = "sha256";
|
||||
outputHash = "1dq9p0hnm1y75q2x40fws5887bq1r840hzdxak0a9djbwvx0b16d";
|
||||
};
|
||||
|
||||
body = mkDerivation {
|
||||
name = "dependencies-top";
|
||||
builder = ./dependencies.builder0.sh + "/FOOBAR/../.";
|
||||
input1 = input1 + "/.";
|
||||
input2 = "${input2}/.";
|
||||
input1_drv = input1;
|
||||
input2_drv = input2;
|
||||
input0_drv = input0;
|
||||
fod_input_drv = fod_input;
|
||||
meta.description = "Random test package";
|
||||
};
|
||||
|
||||
}
|
72
tests/functional/dependencies.sh
Normal file
72
tests/functional/dependencies.sh
Normal file
|
@ -0,0 +1,72 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
|
||||
drvPath=$(nix-instantiate dependencies.nix)
|
||||
|
||||
echo "derivation is $drvPath"
|
||||
|
||||
nix-store -q --tree "$drvPath" | grep '───.*builder-dependencies-input-1.sh'
|
||||
|
||||
# Test Graphviz graph generation.
|
||||
nix-store -q --graph "$drvPath" > $TEST_ROOT/graph
|
||||
if test -n "$dot"; then
|
||||
# Does it parse?
|
||||
$dot < $TEST_ROOT/graph
|
||||
fi
|
||||
|
||||
# Test GraphML graph generation
|
||||
nix-store -q --graphml "$drvPath" > $TEST_ROOT/graphml
|
||||
|
||||
outPath=$(nix-store -rvv "$drvPath") || fail "build failed"
|
||||
|
||||
# Test Graphviz graph generation.
|
||||
nix-store -q --graph "$outPath" > $TEST_ROOT/graph
|
||||
if test -n "$dot"; then
|
||||
# Does it parse?
|
||||
$dot < $TEST_ROOT/graph
|
||||
fi
|
||||
|
||||
nix-store -q --tree "$outPath" | grep '───.*dependencies-input-2'
|
||||
|
||||
echo "output path is $outPath"
|
||||
|
||||
text=$(cat "$outPath"/foobar)
|
||||
if test "$text" != "FOOBAR"; then exit 1; fi
|
||||
|
||||
deps=$(nix-store -quR "$drvPath")
|
||||
|
||||
echo "output closure contains $deps"
|
||||
|
||||
# The output path should be in the closure.
|
||||
echo "$deps" | grepQuiet "$outPath"
|
||||
|
||||
# Input-1 is not retained.
|
||||
if echo "$deps" | grepQuiet "dependencies-input-1"; then exit 1; fi
|
||||
|
||||
# Input-2 is retained.
|
||||
input2OutPath=$(echo "$deps" | grep "dependencies-input-2")
|
||||
|
||||
# The referrers closure of input-2 should include outPath.
|
||||
nix-store -q --referrers-closure "$input2OutPath" | grep "$outPath"
|
||||
|
||||
# Check that the derivers are set properly.
|
||||
test $(nix-store -q --deriver "$outPath") = "$drvPath"
|
||||
nix-store -q --deriver "$input2OutPath" | grepQuiet -- "-input-2.drv"
|
||||
|
||||
# --valid-derivers returns the currently single valid .drv file
|
||||
test "$(nix-store -q --valid-derivers "$outPath")" = "$drvPath"
|
||||
|
||||
# instantiate a different drv with the same output
|
||||
drvPath2=$(nix-instantiate dependencies.nix --argstr hashInvalidator yay)
|
||||
|
||||
# now --valid-derivers returns both
|
||||
test "$(nix-store -q --valid-derivers "$outPath" | sort)" = "$(sort <<< "$drvPath"$'\n'"$drvPath2")"
|
||||
|
||||
# check that nix-store --valid-derivers only returns existing drv
|
||||
nix-store --delete "$drvPath"
|
||||
test "$(nix-store -q --valid-derivers "$outPath")" = "$drvPath2"
|
||||
|
||||
# check that --valid-derivers returns nothing when there are no valid derivers
|
||||
nix-store --delete "$drvPath2"
|
||||
test -z "$(nix-store -q --valid-derivers "$outPath")"
|
12
tests/functional/derivation-json.sh
Normal file
12
tests/functional/derivation-json.sh
Normal file
|
@ -0,0 +1,12 @@
|
|||
source common.sh
|
||||
|
||||
drvPath=$(nix-instantiate simple.nix)
|
||||
|
||||
nix derivation show $drvPath | jq .[] > $TEST_HOME/simple.json
|
||||
|
||||
drvPath2=$(nix derivation add < $TEST_HOME/simple.json)
|
||||
|
||||
[[ "$drvPath" = "$drvPath2" ]]
|
||||
|
||||
# Input addressed derivations cannot be renamed.
|
||||
jq '.name = "foo"' < $TEST_HOME/simple.json | expectStderr 1 nix derivation add | grepQuiet "has incorrect output"
|
1
tests/functional/dummy
Normal file
1
tests/functional/dummy
Normal file
|
@ -0,0 +1 @@
|
|||
Hello World
|
22
tests/functional/dump-db.sh
Normal file
22
tests/functional/dump-db.sh
Normal file
|
@ -0,0 +1,22 @@
|
|||
source common.sh
|
||||
|
||||
needLocalStore "--dump-db requires a local store"
|
||||
|
||||
clearStore
|
||||
|
||||
path=$(nix-build dependencies.nix -o $TEST_ROOT/result)
|
||||
|
||||
deps="$(nix-store -qR $TEST_ROOT/result)"
|
||||
|
||||
nix-store --dump-db > $TEST_ROOT/dump
|
||||
|
||||
rm -rf $NIX_STATE_DIR/db
|
||||
|
||||
nix-store --load-db < $TEST_ROOT/dump
|
||||
|
||||
deps2="$(nix-store -qR $TEST_ROOT/result)"
|
||||
|
||||
[ "$deps" = "$deps2" ];
|
||||
|
||||
nix-store --dump-db > $TEST_ROOT/dump2
|
||||
cmp $TEST_ROOT/dump $TEST_ROOT/dump2
|
21
tests/functional/dyn-drv/build-built-drv.sh
Normal file
21
tests/functional/dyn-drv/build-built-drv.sh
Normal file
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
# In the corresponding nix file, we have two derivations: the first, named `hello`,
|
||||
# is a normal recursive derivation, while the second, named dependent, has the
|
||||
# new outputHashMode "text". Note that in "dependent", we don't refer to the
|
||||
# build output of `hello`, but only to the path of the drv file. For this reason,
|
||||
# we only need to:
|
||||
#
|
||||
# - instantiate `hello`
|
||||
# - build `producingDrv`
|
||||
# - check that the path of the output coincides with that of the original derivation
|
||||
|
||||
out1=$(nix build -f ./text-hashed-output.nix hello --no-link)
|
||||
|
||||
clearStore
|
||||
|
||||
drvDep=$(nix-instantiate ./text-hashed-output.nix -A producingDrv)
|
||||
|
||||
expectStderr 1 nix build "${drvDep}^out^out" --no-link | grepQuiet "Building dynamic derivations in one shot is not yet implemented"
|
8
tests/functional/dyn-drv/common.sh
Normal file
8
tests/functional/dyn-drv/common.sh
Normal file
|
@ -0,0 +1,8 @@
|
|||
source ../common.sh
|
||||
|
||||
# Need backend to support text-hashing too
|
||||
requireDaemonNewerThan "2.16.0pre20230419"
|
||||
|
||||
enableFeatures "ca-derivations dynamic-derivations"
|
||||
|
||||
restartDaemon
|
1
tests/functional/dyn-drv/config.nix.in
Symbolic link
1
tests/functional/dyn-drv/config.nix.in
Symbolic link
|
@ -0,0 +1 @@
|
|||
../config.nix.in
|
11
tests/functional/dyn-drv/dep-built-drv.sh
Normal file
11
tests/functional/dyn-drv/dep-built-drv.sh
Normal file
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
out1=$(nix-build ./text-hashed-output.nix -A hello --no-out-link)
|
||||
|
||||
clearStore
|
||||
|
||||
expectStderr 1 nix-build ./text-hashed-output.nix -A wrapper --no-out-link | grepQuiet "Building dynamic derivations in one shot is not yet implemented"
|
||||
|
||||
# diff -r $out1 $out2
|
80
tests/functional/dyn-drv/eval-outputOf.sh
Normal file
80
tests/functional/dyn-drv/eval-outputOf.sh
Normal file
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source ./common.sh
|
||||
|
||||
# Without the dynamic-derivations XP feature, we don't have the builtin.
|
||||
nix --experimental-features 'nix-command' eval --impure --expr \
|
||||
'assert ! (builtins ? outputOf); ""'
|
||||
|
||||
# Test that a string is required.
|
||||
#
|
||||
# We currently require a string to be passed, rather than a derivation
|
||||
# object that could be coerced to a string. We might liberalise this in
|
||||
# the future so it does work, but there are some design questions to
|
||||
# resolve first. Adding a test so we don't liberalise it by accident.
|
||||
expectStderr 1 nix --experimental-features 'nix-command dynamic-derivations' eval --impure --expr \
|
||||
'builtins.outputOf (import ../dependencies.nix {}) "out"' \
|
||||
| grepQuiet "value is a set while a string was expected"
|
||||
|
||||
# Test that "DrvDeep" string contexts are not supported at this time
|
||||
#
|
||||
# Like the above, this is a restriction we could relax later.
|
||||
expectStderr 1 nix --experimental-features 'nix-command dynamic-derivations' eval --impure --expr \
|
||||
'builtins.outputOf (import ../dependencies.nix {}).drvPath "out"' \
|
||||
| grepQuiet "has a context which refers to a complete source and binary closure. This is not supported at this time"
|
||||
|
||||
# Test using `builtins.outputOf` with static derivations
|
||||
testStaticHello () {
|
||||
nix eval --impure --expr \
|
||||
'with (import ./text-hashed-output.nix); let
|
||||
a = hello.outPath;
|
||||
b = builtins.outputOf (builtins.unsafeDiscardOutputDependency hello.drvPath) "out";
|
||||
in builtins.trace a
|
||||
(builtins.trace b
|
||||
(assert a == b; null))'
|
||||
}
|
||||
|
||||
# Test with a regular old input-addresed derivation
|
||||
#
|
||||
# `builtins.outputOf` works without ca-derivations and doesn't create a
|
||||
# placeholder but just returns the output path.
|
||||
testStaticHello
|
||||
|
||||
# Test with content addressed derivation.
|
||||
NIX_TESTS_CA_BY_DEFAULT=1 testStaticHello
|
||||
|
||||
# Test with derivation-producing derivation
|
||||
#
|
||||
# This is hardly different from the preceding cases, except that we're
|
||||
# only taking 1 outputOf out of 2 possible outputOfs. Note that
|
||||
# `.outPath` could be defined as `outputOf drvPath`, which is what we're
|
||||
# testing here. The other `outputOf` that we're not testing here is the
|
||||
# use of _dynamic_ derivations.
|
||||
nix eval --impure --expr \
|
||||
'with (import ./text-hashed-output.nix); let
|
||||
a = producingDrv.outPath;
|
||||
b = builtins.outputOf (builtins.builtins.unsafeDiscardOutputDependency producingDrv.drvPath) "out";
|
||||
in builtins.trace a
|
||||
(builtins.trace b
|
||||
(assert a == b; null))'
|
||||
|
||||
# Test with unbuilt output of derivation-producing derivation.
|
||||
#
|
||||
# This function similar to `testStaticHello` used above, but instead of
|
||||
# checking the property on a constant derivation, we check it on a
|
||||
# derivation that's from another derivation's output (outPath).
|
||||
testDynamicHello () {
|
||||
nix eval --impure --expr \
|
||||
'with (import ./text-hashed-output.nix); let
|
||||
a = builtins.outputOf producingDrv.outPath "out";
|
||||
b = builtins.outputOf (builtins.outputOf (builtins.unsafeDiscardOutputDependency producingDrv.drvPath) "out") "out";
|
||||
in builtins.trace a
|
||||
(builtins.trace b
|
||||
(assert a == b; null))'
|
||||
}
|
||||
|
||||
# inner dynamic derivation is input-addressed
|
||||
testDynamicHello
|
||||
|
||||
# inner dynamic derivation is content-addressed
|
||||
NIX_TESTS_CA_BY_DEFAULT=1 testDynamicHello
|
15
tests/functional/dyn-drv/local.mk
Normal file
15
tests/functional/dyn-drv/local.mk
Normal file
|
@ -0,0 +1,15 @@
|
|||
dyn-drv-tests := \
|
||||
$(d)/text-hashed-output.sh \
|
||||
$(d)/recursive-mod-json.sh \
|
||||
$(d)/build-built-drv.sh \
|
||||
$(d)/eval-outputOf.sh \
|
||||
$(d)/dep-built-drv.sh \
|
||||
$(d)/old-daemon-error-hack.sh
|
||||
|
||||
install-tests-groups += dyn-drv
|
||||
|
||||
clean-files += \
|
||||
$(d)/config.nix
|
||||
|
||||
test-deps += \
|
||||
tests/functional/dyn-drv/config.nix
|
20
tests/functional/dyn-drv/old-daemon-error-hack.nix
Normal file
20
tests/functional/dyn-drv/old-daemon-error-hack.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
with import ./config.nix;
|
||||
|
||||
# A simple content-addressed derivation.
|
||||
# The derivation can be arbitrarily modified by passing a different `seed`,
|
||||
# but the output will always be the same
|
||||
rec {
|
||||
stub = mkDerivation {
|
||||
name = "stub";
|
||||
buildCommand = ''
|
||||
echo stub > $out
|
||||
'';
|
||||
};
|
||||
wrapper = mkDerivation {
|
||||
name = "has-dynamic-drv-dep";
|
||||
buildCommand = ''
|
||||
exit 1 # we're not building this derivation
|
||||
${builtins.outputOf stub.outPath "out"}
|
||||
'';
|
||||
};
|
||||
}
|
11
tests/functional/dyn-drv/old-daemon-error-hack.sh
Normal file
11
tests/functional/dyn-drv/old-daemon-error-hack.sh
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Purposely bypassing our usual common for this subgroup
|
||||
source ../common.sh
|
||||
|
||||
# Need backend to support text-hashing too
|
||||
isDaemonNewer "2.18.0pre20230906" && skipTest "Daemon is too new"
|
||||
|
||||
enableFeatures "ca-derivations dynamic-derivations"
|
||||
|
||||
restartDaemon
|
||||
|
||||
expectStderr 1 nix-instantiate --read-write-mode ./old-daemon-error-hack.nix | grepQuiet "the daemon is too old to understand dependencies on dynamic derivations"
|
33
tests/functional/dyn-drv/recursive-mod-json.nix
Normal file
33
tests/functional/dyn-drv/recursive-mod-json.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
with import ./config.nix;
|
||||
|
||||
let innerName = "foo"; in
|
||||
|
||||
mkDerivation rec {
|
||||
name = "${innerName}.drv";
|
||||
SHELL = shell;
|
||||
|
||||
requiredSystemFeatures = [ "recursive-nix" ];
|
||||
|
||||
drv = builtins.unsafeDiscardOutputDependency (import ./text-hashed-output.nix).hello.drvPath;
|
||||
|
||||
buildCommand = ''
|
||||
export NIX_CONFIG='experimental-features = nix-command ca-derivations'
|
||||
|
||||
PATH=${builtins.getEnv "EXTRA_PATH"}:$PATH
|
||||
|
||||
# JSON of pre-existing drv
|
||||
nix derivation show $drv | jq .[] > drv0.json
|
||||
|
||||
# Fix name
|
||||
jq < drv0.json '.name = "${innerName}"' > drv1.json
|
||||
|
||||
# Extend `buildCommand`
|
||||
jq < drv1.json '.env.buildCommand += "echo \"I am alive!\" >> $out/hello\n"' > drv0.json
|
||||
|
||||
# Used as our output
|
||||
cp $(nix derivation add < drv0.json) $out
|
||||
'';
|
||||
__contentAddressed = true;
|
||||
outputHashMode = "text";
|
||||
outputHashAlgo = "sha256";
|
||||
}
|
27
tests/functional/dyn-drv/recursive-mod-json.sh
Normal file
27
tests/functional/dyn-drv/recursive-mod-json.sh
Normal file
|
@ -0,0 +1,27 @@
|
|||
source common.sh
|
||||
|
||||
# FIXME
|
||||
if [[ $(uname) != Linux ]]; then skipTest "Not running Linux"; fi
|
||||
|
||||
export NIX_TESTS_CA_BY_DEFAULT=1
|
||||
|
||||
enableFeatures 'recursive-nix'
|
||||
restartDaemon
|
||||
|
||||
clearStore
|
||||
|
||||
rm -f $TEST_ROOT/result
|
||||
|
||||
EXTRA_PATH=$(dirname $(type -p nix)):$(dirname $(type -p jq))
|
||||
export EXTRA_PATH
|
||||
|
||||
# Will produce a drv
|
||||
metaDrv=$(nix-instantiate ./recursive-mod-json.nix)
|
||||
|
||||
# computed "dynamic" derivation
|
||||
drv=$(nix-store -r $metaDrv)
|
||||
|
||||
# build that dyn drv
|
||||
res=$(nix-store -r $drv)
|
||||
|
||||
grep 'I am alive!' $res/hello
|
33
tests/functional/dyn-drv/text-hashed-output.nix
Normal file
33
tests/functional/dyn-drv/text-hashed-output.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
with import ./config.nix;
|
||||
|
||||
# A simple content-addressed derivation.
|
||||
# The derivation can be arbitrarily modified by passing a different `seed`,
|
||||
# but the output will always be the same
|
||||
rec {
|
||||
hello = mkDerivation {
|
||||
name = "hello";
|
||||
buildCommand = ''
|
||||
set -x
|
||||
echo "Building a CA derivation"
|
||||
mkdir -p $out
|
||||
echo "Hello World" > $out/hello
|
||||
'';
|
||||
};
|
||||
producingDrv = mkDerivation {
|
||||
name = "hello.drv";
|
||||
buildCommand = ''
|
||||
echo "Copying the derivation"
|
||||
cp ${builtins.unsafeDiscardOutputDependency hello.drvPath} $out
|
||||
'';
|
||||
__contentAddressed = true;
|
||||
outputHashMode = "text";
|
||||
outputHashAlgo = "sha256";
|
||||
};
|
||||
wrapper = mkDerivation {
|
||||
name = "use-dynamic-drv-in-non-dynamic-drv";
|
||||
buildCommand = ''
|
||||
echo "Copying the output of the dynamic derivation"
|
||||
cp -r ${builtins.outputOf producingDrv.outPath "out"} $out
|
||||
'';
|
||||
};
|
||||
}
|
26
tests/functional/dyn-drv/text-hashed-output.sh
Normal file
26
tests/functional/dyn-drv/text-hashed-output.sh
Normal file
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source common.sh
|
||||
|
||||
# In the corresponding nix file, we have two derivations: the first, named root,
|
||||
# is a normal recursive derivation, while the second, named dependent, has the
|
||||
# new outputHashMode "text". Note that in "dependent", we don't refer to the
|
||||
# build output of root, but only to the path of the drv file. For this reason,
|
||||
# we only need to:
|
||||
#
|
||||
# - instantiate the root derivation
|
||||
# - build the dependent derivation
|
||||
# - check that the path of the output coincides with that of the original derivation
|
||||
|
||||
drv=$(nix-instantiate ./text-hashed-output.nix -A hello)
|
||||
nix show-derivation "$drv"
|
||||
|
||||
drvProducingDrv=$(nix-instantiate ./text-hashed-output.nix -A producingDrv)
|
||||
nix show-derivation "$drvProducingDrv"
|
||||
|
||||
out1=$(nix-build ./text-hashed-output.nix -A producingDrv --no-out-link)
|
||||
|
||||
nix path-info $drv --derivation --json | jq
|
||||
nix path-info $out1 --derivation --json | jq
|
||||
|
||||
test $out1 == $drv
|
38
tests/functional/eval-store.sh
Normal file
38
tests/functional/eval-store.sh
Normal file
|
@ -0,0 +1,38 @@
|
|||
source common.sh
|
||||
|
||||
# Using `--eval-store` with the daemon will eventually copy everything
|
||||
# to the build store, invalidating most of the tests here
|
||||
needLocalStore "“--eval-store” doesn't achieve much with the daemon"
|
||||
|
||||
eval_store=$TEST_ROOT/eval-store
|
||||
|
||||
clearStore
|
||||
rm -rf "$eval_store"
|
||||
|
||||
nix build -f dependencies.nix --eval-store "$eval_store" -o "$TEST_ROOT/result"
|
||||
[[ -e $TEST_ROOT/result/foobar ]]
|
||||
(! ls $NIX_STORE_DIR/*.drv)
|
||||
ls $eval_store/nix/store/*.drv
|
||||
|
||||
clearStore
|
||||
rm -rf "$eval_store"
|
||||
|
||||
nix-instantiate dependencies.nix --eval-store "$eval_store"
|
||||
(! ls $NIX_STORE_DIR/*.drv)
|
||||
ls $eval_store/nix/store/*.drv
|
||||
|
||||
clearStore
|
||||
rm -rf "$eval_store"
|
||||
|
||||
nix-build dependencies.nix --eval-store "$eval_store" -o "$TEST_ROOT/result"
|
||||
[[ -e $TEST_ROOT/result/foobar ]]
|
||||
(! ls $NIX_STORE_DIR/*.drv)
|
||||
ls $eval_store/nix/store/*.drv
|
||||
|
||||
clearStore
|
||||
rm -rf "$eval_store"
|
||||
|
||||
# Confirm that import-from-derivation builds on the build store
|
||||
[[ $(nix eval --eval-store "$eval_store?require-sigs=false" --impure --raw --file ./ifd.nix) = hi ]]
|
||||
ls $NIX_STORE_DIR/*dependencies-top/foobar
|
||||
(! ls $eval_store/nix/store/*dependencies-top/foobar)
|
5
tests/functional/eval.nix
Normal file
5
tests/functional/eval.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
int = 123;
|
||||
str = "foo";
|
||||
attr.foo = "bar";
|
||||
}
|
43
tests/functional/eval.sh
Normal file
43
tests/functional/eval.sh
Normal file
|
@ -0,0 +1,43 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
|
||||
testStdinHeredoc=$(nix eval -f - <<EOF
|
||||
{
|
||||
bar = 3 + 1;
|
||||
foo = 2 + 2;
|
||||
}
|
||||
EOF
|
||||
)
|
||||
[[ $testStdinHeredoc == '{ bar = 4; foo = 4; }' ]]
|
||||
|
||||
nix eval --expr 'assert 1 + 2 == 3; true'
|
||||
|
||||
[[ $(nix eval int -f "./eval.nix") == 123 ]]
|
||||
[[ $(nix eval str -f "./eval.nix") == '"foo"' ]]
|
||||
[[ $(nix eval str --raw -f "./eval.nix") == 'foo' ]]
|
||||
[[ "$(nix eval attr -f "./eval.nix")" == '{ foo = "bar"; }' ]]
|
||||
[[ $(nix eval attr --json -f "./eval.nix") == '{"foo":"bar"}' ]]
|
||||
[[ $(nix eval int -f - < "./eval.nix") == 123 ]]
|
||||
[[ "$(nix eval --expr '{"assert"=1;bar=2;}')" == '{ "assert" = 1; bar = 2; }' ]]
|
||||
|
||||
# Check if toFile can be utilized during restricted eval
|
||||
[[ $(nix eval --restrict-eval --expr 'import (builtins.toFile "source" "42")') == 42 ]]
|
||||
|
||||
nix-instantiate --eval -E 'assert 1 + 2 == 3; true'
|
||||
[[ $(nix-instantiate -A int --eval "./eval.nix") == 123 ]]
|
||||
[[ $(nix-instantiate -A str --eval "./eval.nix") == '"foo"' ]]
|
||||
[[ "$(nix-instantiate -A attr --eval "./eval.nix")" == '{ foo = "bar"; }' ]]
|
||||
[[ $(nix-instantiate -A attr --eval --json "./eval.nix") == '{"foo":"bar"}' ]]
|
||||
[[ $(nix-instantiate -A int --eval - < "./eval.nix") == 123 ]]
|
||||
[[ "$(nix-instantiate --eval -E '{"assert"=1;bar=2;}')" == '{ "assert" = 1; bar = 2; }' ]]
|
||||
|
||||
# Check that symlink cycles don't cause a hang.
|
||||
ln -sfn cycle.nix $TEST_ROOT/cycle.nix
|
||||
(! nix eval --file $TEST_ROOT/cycle.nix)
|
||||
|
||||
# Check that relative symlinks are resolved correctly.
|
||||
mkdir -p $TEST_ROOT/xyzzy $TEST_ROOT/foo
|
||||
ln -sfn ../xyzzy $TEST_ROOT/foo/bar
|
||||
printf 123 > $TEST_ROOT/xyzzy/default.nix
|
||||
[[ $(nix eval --impure --expr "import $TEST_ROOT/foo/bar") = 123 ]]
|
86
tests/functional/experimental-features.sh
Normal file
86
tests/functional/experimental-features.sh
Normal file
|
@ -0,0 +1,86 @@
|
|||
source common.sh
|
||||
|
||||
# Skipping these two for now, because we actually *do* want flags and
|
||||
# config settings to always show up in the manual, just be marked
|
||||
# experimental. Will reenable once the manual generation takes advantage
|
||||
# of the JSON metadata on this.
|
||||
#
|
||||
# # Without flakes, flake options should not show up
|
||||
# # With flakes, flake options should show up
|
||||
#
|
||||
# function grep_both_ways {
|
||||
# nix --experimental-features 'nix-command' "$@" | grepQuietInverse flake
|
||||
# nix --experimental-features 'nix-command flakes' "$@" | grepQuiet flake
|
||||
#
|
||||
# # Also, the order should not matter
|
||||
# nix "$@" --experimental-features 'nix-command' | grepQuietInverse flake
|
||||
# nix "$@" --experimental-features 'nix-command flakes' | grepQuiet flake
|
||||
# }
|
||||
#
|
||||
# # Simple case, the configuration effects the running command
|
||||
# grep_both_ways show-config
|
||||
#
|
||||
# # Medium case, the configuration effects --help
|
||||
# grep_both_ways store gc --help
|
||||
|
||||
# Test settings that are gated on experimental features; the setting is ignored
|
||||
# with a warning if the experimental feature is not enabled. The order of the
|
||||
# `setting = value` lines in the configuration should not matter.
|
||||
|
||||
# 'flakes' experimental-feature is disabled before, ignore and warn
|
||||
NIX_CONFIG='
|
||||
experimental-features = nix-command
|
||||
accept-flake-config = true
|
||||
' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr
|
||||
grepQuiet "false" $TEST_ROOT/stdout
|
||||
grepQuiet "Ignoring setting 'accept-flake-config' because experimental feature 'flakes' is not enabled" $TEST_ROOT/stderr
|
||||
|
||||
# 'flakes' experimental-feature is disabled after, ignore and warn
|
||||
NIX_CONFIG='
|
||||
accept-flake-config = true
|
||||
experimental-features = nix-command
|
||||
' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr
|
||||
grepQuiet "false" $TEST_ROOT/stdout
|
||||
grepQuiet "Ignoring setting 'accept-flake-config' because experimental feature 'flakes' is not enabled" $TEST_ROOT/stderr
|
||||
|
||||
# 'flakes' experimental-feature is enabled before, process
|
||||
NIX_CONFIG='
|
||||
experimental-features = nix-command flakes
|
||||
accept-flake-config = true
|
||||
' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr
|
||||
grepQuiet "true" $TEST_ROOT/stdout
|
||||
grepQuietInverse "Ignoring setting 'accept-flake-config'" $TEST_ROOT/stderr
|
||||
|
||||
# 'flakes' experimental-feature is enabled after, process
|
||||
NIX_CONFIG='
|
||||
accept-flake-config = true
|
||||
experimental-features = nix-command flakes
|
||||
' nix show-config accept-flake-config 1>$TEST_ROOT/stdout 2>$TEST_ROOT/stderr
|
||||
grepQuiet "true" $TEST_ROOT/stdout
|
||||
grepQuietInverse "Ignoring setting 'accept-flake-config'" $TEST_ROOT/stderr
|
||||
|
||||
function exit_code_both_ways {
|
||||
expect 1 nix --experimental-features 'nix-command' "$@" 1>/dev/null
|
||||
nix --experimental-features 'nix-command flakes' "$@" 1>/dev/null
|
||||
|
||||
# Also, the order should not matter
|
||||
expect 1 nix "$@" --experimental-features 'nix-command' 1>/dev/null
|
||||
nix "$@" --experimental-features 'nix-command flakes' 1>/dev/null
|
||||
}
|
||||
|
||||
exit_code_both_ways show-config --flake-registry 'https://no'
|
||||
|
||||
# Double check these are stable
|
||||
nix --experimental-features '' --help 1>/dev/null
|
||||
nix --experimental-features '' doctor --help 1>/dev/null
|
||||
nix --experimental-features '' repl --help 1>/dev/null
|
||||
nix --experimental-features '' upgrade-nix --help 1>/dev/null
|
||||
|
||||
# These 3 arguments are currently given to all commands, which is wrong (as not
|
||||
# all care). To deal with fixing later, we simply make them require the
|
||||
# nix-command experimental features --- it so happens that the commands we wish
|
||||
# stabilizing to do not need them anyways.
|
||||
for arg in '--print-build-logs' '--offline' '--refresh'; do
|
||||
nix --experimental-features 'nix-command' "$arg" --help 1>/dev/null
|
||||
expect 1 nix --experimental-features '' "$arg" --help 1>/dev/null
|
||||
done
|
29
tests/functional/export-graph.nix
Normal file
29
tests/functional/export-graph.nix
Normal file
|
@ -0,0 +1,29 @@
|
|||
with import ./config.nix;
|
||||
|
||||
rec {
|
||||
|
||||
printRefs =
|
||||
''
|
||||
echo $exportReferencesGraph
|
||||
while read path; do
|
||||
read drv
|
||||
read nrRefs
|
||||
echo "$path has $nrRefs references"
|
||||
echo "$path" >> $out
|
||||
for ((n = 0; n < $nrRefs; n++)); do read ref; echo "ref $ref"; test -e "$ref"; done
|
||||
done < refs
|
||||
'';
|
||||
|
||||
foo."bar.runtimeGraph" = mkDerivation {
|
||||
name = "dependencies";
|
||||
builder = builtins.toFile "build-graph-builder" "${printRefs}";
|
||||
exportReferencesGraph = ["refs" (import ./dependencies.nix {})];
|
||||
};
|
||||
|
||||
foo."bar.buildGraph" = mkDerivation {
|
||||
name = "dependencies";
|
||||
builder = builtins.toFile "build-graph-builder" "${printRefs}";
|
||||
exportReferencesGraph = ["refs" (import ./dependencies.nix {}).drvPath];
|
||||
};
|
||||
|
||||
}
|
30
tests/functional/export-graph.sh
Normal file
30
tests/functional/export-graph.sh
Normal file
|
@ -0,0 +1,30 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
clearProfiles
|
||||
|
||||
checkRef() {
|
||||
nix-store -q --references $TEST_ROOT/result | grepQuiet "$1"'$' || fail "missing reference $1"
|
||||
}
|
||||
|
||||
# Test the export of the runtime dependency graph.
|
||||
|
||||
outPath=$(nix-build ./export-graph.nix -A 'foo."bar.runtimeGraph"' -o $TEST_ROOT/result)
|
||||
|
||||
test $(nix-store -q --references $TEST_ROOT/result | wc -l) = 3 || fail "bad nr of references"
|
||||
|
||||
checkRef input-2
|
||||
for i in $(cat $outPath); do checkRef $i; done
|
||||
|
||||
# Test the export of the build-time dependency graph.
|
||||
|
||||
nix-store --gc # should force rebuild of input-1
|
||||
|
||||
outPath=$(nix-build ./export-graph.nix -A 'foo."bar.buildGraph"' -o $TEST_ROOT/result)
|
||||
|
||||
checkRef input-1
|
||||
checkRef input-1.drv
|
||||
checkRef input-2
|
||||
checkRef input-2.drv
|
||||
|
||||
for i in $(cat $outPath); do checkRef $i; done
|
36
tests/functional/export.sh
Normal file
36
tests/functional/export.sh
Normal file
|
@ -0,0 +1,36 @@
|
|||
source common.sh
|
||||
|
||||
clearStore
|
||||
|
||||
outPath=$(nix-build dependencies.nix --no-out-link)
|
||||
|
||||
nix-store --export $outPath > $TEST_ROOT/exp
|
||||
|
||||
nix-store --export $(nix-store -qR $outPath) > $TEST_ROOT/exp_all
|
||||
|
||||
if nix-store --export $outPath >/dev/full ; then
|
||||
echo "exporting to a bad file descriptor should fail"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
clearStore
|
||||
|
||||
if nix-store --import < $TEST_ROOT/exp; then
|
||||
echo "importing a non-closure should fail"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
clearStore
|
||||
|
||||
nix-store --import < $TEST_ROOT/exp_all
|
||||
|
||||
nix-store --export $(nix-store -qR $outPath) > $TEST_ROOT/exp_all2
|
||||
|
||||
|
||||
clearStore
|
||||
|
||||
# Regression test: the derivers in exp_all2 are empty, which shouldn't
|
||||
# cause a failure.
|
||||
nix-store --import < $TEST_ROOT/exp_all2
|
25
tests/functional/failing.nix
Normal file
25
tests/functional/failing.nix
Normal file
|
@ -0,0 +1,25 @@
|
|||
{ busybox }:
|
||||
with import ./config.nix;
|
||||
let
|
||||
|
||||
mkDerivation = args:
|
||||
derivation ({
|
||||
inherit system;
|
||||
builder = busybox;
|
||||
args = ["sh" "-e" args.builder or (builtins.toFile "builder-${args.name}.sh" ''
|
||||
if [ -e "$NIX_ATTRS_SH_FILE" ]; then source $NIX_ATTRS_SH_FILE; fi;
|
||||
eval "$buildCommand"
|
||||
'')];
|
||||
} // removeAttrs args ["builder" "meta"])
|
||||
// { meta = args.meta or {}; };
|
||||
in
|
||||
{
|
||||
|
||||
failing = mkDerivation {
|
||||
name = "failing";
|
||||
buildCommand = ''
|
||||
echo foo > bar
|
||||
exit 1
|
||||
'';
|
||||
};
|
||||
}
|
150
tests/functional/fetchClosure.sh
Normal file
150
tests/functional/fetchClosure.sh
Normal file
|
@ -0,0 +1,150 @@
|
|||
source common.sh
|
||||
|
||||
enableFeatures "fetch-closure"
|
||||
|
||||
clearStore
|
||||
clearCacheCache
|
||||
|
||||
# Old daemons don't properly zero out the self-references when
|
||||
# calculating the CA hashes, so this breaks `nix store
|
||||
# make-content-addressed` which expects the client and the daemon to
|
||||
# compute the same hash
|
||||
requireDaemonNewerThan "2.16.0pre20230524"
|
||||
|
||||
# Initialize binary cache.
|
||||
nonCaPath=$(nix build --json --file ./dependencies.nix --no-link | jq -r .[].outputs.out)
|
||||
caPath=$(nix store make-content-addressed --json $nonCaPath | jq -r '.rewrites | map(.) | .[]')
|
||||
nix copy --to file://$cacheDir $nonCaPath
|
||||
|
||||
# Test basic fetchClosure rewriting from non-CA to CA.
|
||||
clearStore
|
||||
|
||||
[ ! -e $nonCaPath ]
|
||||
[ ! -e $caPath ]
|
||||
|
||||
[[ $(nix eval -v --raw --expr "
|
||||
builtins.fetchClosure {
|
||||
fromStore = \"file://$cacheDir\";
|
||||
fromPath = $nonCaPath;
|
||||
toPath = $caPath;
|
||||
}
|
||||
") = $caPath ]]
|
||||
|
||||
[ ! -e $nonCaPath ]
|
||||
[ -e $caPath ]
|
||||
|
||||
clearStore
|
||||
|
||||
# The daemon will reject input addressed paths unless configured to trust the
|
||||
# cache key or the user. This behavior should be covered by another test, so we
|
||||
# skip this part when using the daemon.
|
||||
if [[ "$NIX_REMOTE" != "daemon" ]]; then
|
||||
|
||||
# If we want to return a non-CA path, we have to be explicit about it.
|
||||
expectStderr 1 nix eval --raw --no-require-sigs --expr "
|
||||
builtins.fetchClosure {
|
||||
fromStore = \"file://$cacheDir\";
|
||||
fromPath = $nonCaPath;
|
||||
}
|
||||
" | grepQuiet -E "The .fromPath. value .* is input-addressed, but .inputAddressed. is set to .false."
|
||||
|
||||
# TODO: Should the closure be rejected, despite single user mode?
|
||||
# [ ! -e $nonCaPath ]
|
||||
|
||||
[ ! -e $caPath ]
|
||||
|
||||
# We can use non-CA paths when we ask explicitly.
|
||||
[[ $(nix eval --raw --no-require-sigs --expr "
|
||||
builtins.fetchClosure {
|
||||
fromStore = \"file://$cacheDir\";
|
||||
fromPath = $nonCaPath;
|
||||
inputAddressed = true;
|
||||
}
|
||||
") = $nonCaPath ]]
|
||||
|
||||
[ -e $nonCaPath ]
|
||||
[ ! -e $caPath ]
|
||||
|
||||
|
||||
fi
|
||||
|
||||
[ ! -e $caPath ]
|
||||
|
||||
# 'toPath' set to empty string should fail but print the expected path.
|
||||
expectStderr 1 nix eval -v --json --expr "
|
||||
builtins.fetchClosure {
|
||||
fromStore = \"file://$cacheDir\";
|
||||
fromPath = $nonCaPath;
|
||||
toPath = \"\";
|
||||
}
|
||||
" | grep "error: rewriting.*$nonCaPath.*yielded.*$caPath"
|
||||
|
||||
# If fromPath is CA, then toPath isn't needed.
|
||||
nix copy --to file://$cacheDir $caPath
|
||||
|
||||
clearStore
|
||||
|
||||
[ ! -e $caPath ]
|
||||
|
||||
[[ $(nix eval -v --raw --expr "
|
||||
builtins.fetchClosure {
|
||||
fromStore = \"file://$cacheDir\";
|
||||
fromPath = $caPath;
|
||||
}
|
||||
") = $caPath ]]
|
||||
|
||||
[ -e $caPath ]
|
||||
|
||||
# Check that URL query parameters aren't allowed.
|
||||
clearStore
|
||||
narCache=$TEST_ROOT/nar-cache
|
||||
rm -rf $narCache
|
||||
(! nix eval -v --raw --expr "
|
||||
builtins.fetchClosure {
|
||||
fromStore = \"file://$cacheDir?local-nar-cache=$narCache\";
|
||||
fromPath = $caPath;
|
||||
}
|
||||
")
|
||||
(! [ -e $narCache ])
|
||||
|
||||
# If toPath is specified but wrong, we check it (only) when the path is missing.
|
||||
clearStore
|
||||
|
||||
badPath=$(echo $caPath | sed -e 's!/store/................................-!/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-!')
|
||||
|
||||
[ ! -e $badPath ]
|
||||
|
||||
expectStderr 1 nix eval -v --raw --expr "
|
||||
builtins.fetchClosure {
|
||||
fromStore = \"file://$cacheDir\";
|
||||
fromPath = $nonCaPath;
|
||||
toPath = $badPath;
|
||||
}
|
||||
" | grep "error: rewriting.*$nonCaPath.*yielded.*$caPath.*while.*$badPath.*was expected"
|
||||
|
||||
[ ! -e $badPath ]
|
||||
|
||||
# We only check it when missing, as a performance optimization similar to what we do for fixed output derivations. So if it's already there, we don't check it.
|
||||
# It would be nice for this to fail, but checking it would be too(?) slow.
|
||||
[ -e $caPath ]
|
||||
|
||||
[[ $(nix eval -v --raw --expr "
|
||||
builtins.fetchClosure {
|
||||
fromStore = \"file://$cacheDir\";
|
||||
fromPath = $badPath;
|
||||
toPath = $caPath;
|
||||
}
|
||||
") = $caPath ]]
|
||||
|
||||
|
||||
# However, if the output address is unexpected, we can report it
|
||||
|
||||
|
||||
expectStderr 1 nix eval -v --raw --expr "
|
||||
builtins.fetchClosure {
|
||||
fromStore = \"file://$cacheDir\";
|
||||
fromPath = $caPath;
|
||||
inputAddressed = true;
|
||||
}
|
||||
" | grepQuiet 'error.*The store object referred to by.*fromPath.* at .* is not input-addressed, but .*inputAddressed.* is set to .*true.*'
|
||||
|
258
tests/functional/fetchGit.sh
Normal file
258
tests/functional/fetchGit.sh
Normal file
|
@ -0,0 +1,258 @@
|
|||
source common.sh
|
||||
|
||||
requireGit
|
||||
|
||||
clearStore
|
||||
|
||||
# Intentionally not in a canonical form
|
||||
# See https://github.com/NixOS/nix/issues/6195
|
||||
repo=$TEST_ROOT/./git
|
||||
|
||||
export _NIX_FORCE_HTTP=1
|
||||
|
||||
rm -rf $repo ${repo}-tmp $TEST_HOME/.cache/nix $TEST_ROOT/worktree $TEST_ROOT/shallow $TEST_ROOT/minimal
|
||||
|
||||
git init $repo
|
||||
git -C $repo config user.email "foobar@example.com"
|
||||
git -C $repo config user.name "Foobar"
|
||||
|
||||
echo utrecht > $repo/hello
|
||||
touch $repo/.gitignore
|
||||
git -C $repo add hello .gitignore
|
||||
git -C $repo commit -m 'Bla1'
|
||||
rev1=$(git -C $repo rev-parse HEAD)
|
||||
git -C $repo tag -a tag1 -m tag1
|
||||
|
||||
echo world > $repo/hello
|
||||
git -C $repo commit -m 'Bla2' -a
|
||||
git -C $repo worktree add $TEST_ROOT/worktree
|
||||
echo hello >> $TEST_ROOT/worktree/hello
|
||||
rev2=$(git -C $repo rev-parse HEAD)
|
||||
git -C $repo tag -a tag2 -m tag2
|
||||
|
||||
# Fetch a worktree
|
||||
unset _NIX_FORCE_HTTP
|
||||
path0=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$TEST_ROOT/worktree).outPath")
|
||||
path0_=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = file://$TEST_ROOT/worktree; }).outPath")
|
||||
[[ $path0 = $path0_ ]]
|
||||
path0_=$(nix eval --impure --raw --expr "(builtins.fetchTree git+file://$TEST_ROOT/worktree).outPath")
|
||||
[[ $path0 = $path0_ ]]
|
||||
export _NIX_FORCE_HTTP=1
|
||||
[[ $(tail -n 1 $path0/hello) = "hello" ]]
|
||||
|
||||
# Fetch the default branch.
|
||||
path=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath")
|
||||
[[ $(cat $path/hello) = world ]]
|
||||
|
||||
# Fetch a rev from another branch
|
||||
git -C $repo checkout -b devtest
|
||||
echo "different file" >> $TEST_ROOT/git/differentbranch
|
||||
git -C $repo add differentbranch
|
||||
git -C $repo commit -m 'Test2'
|
||||
git -C $repo checkout master
|
||||
devrev=$(git -C $repo rev-parse devtest)
|
||||
out=$(nix eval --impure --raw --expr "builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; }" 2>&1) || status=$?
|
||||
[[ $status == 1 ]]
|
||||
[[ $out =~ 'Cannot find Git revision' ]]
|
||||
|
||||
[[ $(nix eval --raw --expr "builtins.readFile (builtins.fetchGit { url = file://$repo; rev = \"$devrev\"; allRefs = true; } + \"/differentbranch\")") = 'different file' ]]
|
||||
|
||||
# In pure eval mode, fetchGit without a revision should fail.
|
||||
[[ $(nix eval --impure --raw --expr "builtins.readFile (fetchGit file://$repo + \"/hello\")") = world ]]
|
||||
(! nix eval --raw --expr "builtins.readFile (fetchGit file://$repo + \"/hello\")")
|
||||
|
||||
# Fetch using an explicit revision hash.
|
||||
path2=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev2\"; }).outPath")
|
||||
[[ $path = $path2 ]]
|
||||
|
||||
# In pure eval mode, fetchGit with a revision should succeed.
|
||||
[[ $(nix eval --raw --expr "builtins.readFile (fetchGit { url = file://$repo; rev = \"$rev2\"; } + \"/hello\")") = world ]]
|
||||
|
||||
# Fetch again. This should be cached.
|
||||
mv $repo ${repo}-tmp
|
||||
path2=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath")
|
||||
[[ $path = $path2 ]]
|
||||
|
||||
[[ $(nix eval --impure --expr "(builtins.fetchGit file://$repo).revCount") = 2 ]]
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).rev") = $rev2 ]]
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).shortRev") = ${rev2:0:7} ]]
|
||||
|
||||
# Fetching with a explicit hash should succeed.
|
||||
path2=$(nix eval --refresh --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev2\"; }).outPath")
|
||||
[[ $path = $path2 ]]
|
||||
|
||||
path2=$(nix eval --refresh --raw --expr "(builtins.fetchGit { url = file://$repo; rev = \"$rev1\"; }).outPath")
|
||||
[[ $(cat $path2/hello) = utrecht ]]
|
||||
|
||||
mv ${repo}-tmp $repo
|
||||
|
||||
# Using a clean working tree should produce the same result.
|
||||
path2=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath")
|
||||
[[ $path = $path2 ]]
|
||||
|
||||
# Using an unclean tree should yield the tracked but uncommitted changes.
|
||||
mkdir $repo/dir1 $repo/dir2
|
||||
echo foo > $repo/dir1/foo
|
||||
echo bar > $repo/bar
|
||||
echo bar > $repo/dir2/bar
|
||||
git -C $repo add dir1/foo
|
||||
git -C $repo rm hello
|
||||
|
||||
unset _NIX_FORCE_HTTP
|
||||
path2=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath")
|
||||
[ ! -e $path2/hello ]
|
||||
[ ! -e $path2/bar ]
|
||||
[ ! -e $path2/dir2/bar ]
|
||||
[ ! -e $path2/.git ]
|
||||
[[ $(cat $path2/dir1/foo) = foo ]]
|
||||
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).rev") = 0000000000000000000000000000000000000000 ]]
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).dirtyRev") = "${rev2}-dirty" ]]
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).dirtyShortRev") = "${rev2:0:7}-dirty" ]]
|
||||
|
||||
# ... unless we're using an explicit ref or rev.
|
||||
path3=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"master\"; }).outPath")
|
||||
[[ $path = $path3 ]]
|
||||
|
||||
path3=$(nix eval --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; }).outPath")
|
||||
[[ $path = $path3 ]]
|
||||
|
||||
# Committing should not affect the store path.
|
||||
git -C $repo commit -m 'Bla3' -a
|
||||
|
||||
path4=$(nix eval --impure --refresh --raw --expr "(builtins.fetchGit file://$repo).outPath")
|
||||
[[ $path2 = $path4 ]]
|
||||
|
||||
[[ $(nix eval --impure --expr "builtins.hasAttr \"rev\" (builtins.fetchGit $repo)") == "true" ]]
|
||||
[[ $(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" ]]
|
||||
|
||||
path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; rev = \"$rev2\"; narHash = \"sha256-Hr8g6AqANb3xqX28eu1XnjK/3ab8Gv6TJSnkb1LezG9=\"; }).outPath")
|
||||
[[ $path = $path5 ]]
|
||||
|
||||
# tarball-ttl should be ignored if we specify a rev
|
||||
echo delft > $repo/hello
|
||||
git -C $repo add hello
|
||||
git -C $repo commit -m 'Bla4'
|
||||
rev3=$(git -C $repo rev-parse HEAD)
|
||||
nix eval --tarball-ttl 3600 --expr "builtins.fetchGit { url = $repo; rev = \"$rev3\"; }" >/dev/null
|
||||
|
||||
# Update 'path' to reflect latest master
|
||||
path=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath")
|
||||
|
||||
# Check behavior when non-master branch is used
|
||||
git -C $repo checkout $rev2 -b dev
|
||||
echo dev > $repo/hello
|
||||
|
||||
# File URI uses dirty tree unless specified otherwise
|
||||
path2=$(nix eval --impure --raw --expr "(builtins.fetchGit file://$repo).outPath")
|
||||
[ $(cat $path2/hello) = dev ]
|
||||
|
||||
# Using local path with branch other than 'master' should work when clean or dirty
|
||||
path3=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath")
|
||||
# (check dirty-tree handling was used)
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).rev") = 0000000000000000000000000000000000000000 ]]
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).shortRev") = 0000000 ]]
|
||||
# Making a dirty tree clean again and fetching it should
|
||||
# record correct revision information. See: #4140
|
||||
echo world > $repo/hello
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit $repo).rev") = $rev2 ]]
|
||||
|
||||
# Committing shouldn't change store path, or switch to using 'master'
|
||||
echo dev > $repo/hello
|
||||
git -C $repo commit -m 'Bla5' -a
|
||||
path4=$(nix eval --impure --raw --expr "(builtins.fetchGit $repo).outPath")
|
||||
[[ $(cat $path4/hello) = dev ]]
|
||||
[[ $path3 = $path4 ]]
|
||||
|
||||
# Using remote path with branch other than 'master' should fetch the HEAD revision.
|
||||
# (--tarball-ttl 0 to prevent using the cached repo above)
|
||||
export _NIX_FORCE_HTTP=1
|
||||
path4=$(nix eval --tarball-ttl 0 --impure --raw --expr "(builtins.fetchGit $repo).outPath")
|
||||
[[ $(cat $path4/hello) = dev ]]
|
||||
[[ $path3 = $path4 ]]
|
||||
unset _NIX_FORCE_HTTP
|
||||
|
||||
# Confirm same as 'dev' branch
|
||||
path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"dev\"; }).outPath")
|
||||
[[ $path3 = $path5 ]]
|
||||
|
||||
|
||||
# Nuke the cache
|
||||
rm -rf $TEST_HOME/.cache/nix
|
||||
|
||||
# Try again, but without 'git' on PATH. This should fail.
|
||||
NIX=$(command -v nix)
|
||||
(! PATH= $NIX eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"dev\"; }).outPath" )
|
||||
|
||||
# Try again, with 'git' available. This should work.
|
||||
path5=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = $repo; ref = \"dev\"; }).outPath")
|
||||
[[ $path3 = $path5 ]]
|
||||
|
||||
# Fetching from a repo with only a specific revision and no branches should
|
||||
# not fall back to copying files and record correct revision information. See: #5302
|
||||
mkdir $TEST_ROOT/minimal
|
||||
git -C $TEST_ROOT/minimal init
|
||||
git -C $TEST_ROOT/minimal fetch $repo $rev2
|
||||
git -C $TEST_ROOT/minimal checkout $rev2
|
||||
[[ $(nix eval --impure --raw --expr "(builtins.fetchGit { url = $TEST_ROOT/minimal; }).rev") = $rev2 ]]
|
||||
|
||||
# Fetching a shallow repo shouldn't work by default, because we can't
|
||||
# return a revCount.
|
||||
git clone --depth 1 file://$repo $TEST_ROOT/shallow
|
||||
(! nix eval --impure --raw --expr "(builtins.fetchGit { url = $TEST_ROOT/shallow; ref = \"dev\"; }).outPath")
|
||||
|
||||
# But you can request a shallow clone, which won't return a revCount.
|
||||
path6=$(nix eval --impure --raw --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow\"; ref = \"dev\"; shallow = true; }).outPath")
|
||||
[[ $path3 = $path6 ]]
|
||||
[[ $(nix eval --impure --expr "(builtins.fetchTree { type = \"git\"; url = \"file://$TEST_ROOT/shallow\"; ref = \"dev\"; shallow = true; }).revCount or 123") == 123 ]]
|
||||
|
||||
# Explicit ref = "HEAD" should work, and produce the same outPath as without ref
|
||||
path7=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; }).outPath")
|
||||
path8=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; }).outPath")
|
||||
[[ $path7 = $path8 ]]
|
||||
|
||||
# ref = "HEAD" should fetch the HEAD revision
|
||||
rev4=$(git -C $repo rev-parse HEAD)
|
||||
rev4_nix=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; }).rev")
|
||||
[[ $rev4 = $rev4_nix ]]
|
||||
|
||||
# The name argument should be handled
|
||||
path9=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"HEAD\"; name = \"foo\"; }).outPath")
|
||||
[[ $path9 =~ -foo$ ]]
|
||||
|
||||
# Specifying a ref without a rev shouldn't pick a cached rev for a different ref
|
||||
export _NIX_FORCE_HTTP=1
|
||||
rev_tag1_nix=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"refs/tags/tag1\"; }).rev")
|
||||
rev_tag1=$(git -C $repo rev-parse refs/tags/tag1)
|
||||
[[ $rev_tag1_nix = $rev_tag1 ]]
|
||||
rev_tag2_nix=$(nix eval --impure --raw --expr "(builtins.fetchGit { url = \"file://$repo\"; ref = \"refs/tags/tag2\"; }).rev")
|
||||
rev_tag2=$(git -C $repo rev-parse refs/tags/tag2)
|
||||
[[ $rev_tag2_nix = $rev_tag2 ]]
|
||||
unset _NIX_FORCE_HTTP
|
||||
|
||||
# should fail if there is no repo
|
||||
rm -rf $repo/.git
|
||||
(! nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath")
|
||||
|
||||
# should succeed for a repo without commits
|
||||
git init $repo
|
||||
path10=$(nix eval --impure --raw --expr "(builtins.fetchGit \"file://$repo\").outPath")
|
||||
|
||||
# should succeed for a path with a space
|
||||
# regression test for #7707
|
||||
repo="$TEST_ROOT/a b"
|
||||
git init "$repo"
|
||||
git -C "$repo" config user.email "foobar@example.com"
|
||||
git -C "$repo" config user.name "Foobar"
|
||||
|
||||
echo utrecht > "$repo/hello"
|
||||
touch "$repo/.gitignore"
|
||||
git -C "$repo" add hello .gitignore
|
||||
git -C "$repo" commit -m 'Bla1'
|
||||
cd "$repo"
|
||||
path11=$(nix eval --impure --raw --expr "(builtins.fetchGit ./.).outPath")
|
108
tests/functional/fetchGitRefs.sh
Normal file
108
tests/functional/fetchGitRefs.sh
Normal file
|
@ -0,0 +1,108 @@
|
|||
source common.sh
|
||||
|
||||
requireGit
|
||||
|
||||
clearStore
|
||||
|
||||
repo="$TEST_ROOT/git"
|
||||
|
||||
rm -rf "$repo" "${repo}-tmp" "$TEST_HOME/.cache/nix"
|
||||
|
||||
git init "$repo"
|
||||
git -C "$repo" config user.email "foobar@example.com"
|
||||
git -C "$repo" config user.name "Foobar"
|
||||
|
||||
echo utrecht > "$repo"/hello
|
||||
git -C "$repo" add hello
|
||||
git -C "$repo" commit -m 'Bla1'
|
||||
|
||||
path=$(nix eval --raw --impure --expr "(builtins.fetchGit { url = $repo; ref = \"master\"; }).outPath")
|
||||
|
||||
# Test various combinations of ref names
|
||||
# (taken from the git project)
|
||||
|
||||
# git help check-ref-format
|
||||
# Git imposes the following rules on how references are named:
|
||||
#
|
||||
# 1. They can include slash / for hierarchical (directory) grouping, but no slash-separated component can begin with a dot . or end with the sequence .lock.
|
||||
# 2. They must contain at least one /. This enforces the presence of a category like heads/, tags/ etc. but the actual names are not restricted. If the --allow-onelevel option is used, this rule is waived.
|
||||
# 3. They cannot have two consecutive dots .. anywhere.
|
||||
# 4. They cannot have ASCII control characters (i.e. bytes whose values are lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon : anywhere.
|
||||
# 5. They cannot have question-mark ?, asterisk *, or open bracket [ anywhere. See the --refspec-pattern option below for an exception to this rule.
|
||||
# 6. They cannot begin or end with a slash / or contain multiple consecutive slashes (see the --normalize option below for an exception to this rule)
|
||||
# 7. They cannot end with a dot ..
|
||||
# 8. They cannot contain a sequence @{.
|
||||
# 9. They cannot be the single character @.
|
||||
# 10. They cannot contain a \.
|
||||
|
||||
valid_ref() {
|
||||
{ set +x; printf >&2 '\n>>>>>>>>>> valid_ref %s\b <<<<<<<<<<\n' $(printf %s "$1" | sed -n -e l); set -x; }
|
||||
git check-ref-format --branch "$1" >/dev/null
|
||||
git -C "$repo" branch "$1" master >/dev/null
|
||||
path1=$(nix eval --raw --impure --expr "(builtins.fetchGit { url = $repo; ref = ''$1''; }).outPath")
|
||||
[[ $path1 = $path ]]
|
||||
git -C "$repo" branch -D "$1" >/dev/null
|
||||
}
|
||||
|
||||
invalid_ref() {
|
||||
{ set +x; printf >&2 '\n>>>>>>>>>> invalid_ref %s\b <<<<<<<<<<\n' $(printf %s "$1" | sed -n -e l); set -x; }
|
||||
# special case for a sole @:
|
||||
# --branch @ will try to interpret @ as a branch reference and not fail. Thus we need --allow-onelevel
|
||||
if [ "$1" = "@" ]; then
|
||||
(! git check-ref-format --allow-onelevel "$1" >/dev/null 2>&1)
|
||||
else
|
||||
(! git check-ref-format --branch "$1" >/dev/null 2>&1)
|
||||
fi
|
||||
expect 1 nix --debug eval --raw --impure --expr "(builtins.fetchGit { url = $repo; ref = ''$1''; }).outPath" 2>&1 | grep 'invalid Git branch/tag name' >/dev/null
|
||||
}
|
||||
|
||||
|
||||
valid_ref 'foox'
|
||||
valid_ref '1337'
|
||||
valid_ref 'foo.baz'
|
||||
valid_ref 'foo/bar/baz'
|
||||
valid_ref 'foo./bar'
|
||||
valid_ref 'heads/foo@bar'
|
||||
valid_ref "$(printf 'heads/fu\303\237')"
|
||||
valid_ref 'foo-bar-baz'
|
||||
valid_ref '$1'
|
||||
valid_ref 'foo.locke'
|
||||
|
||||
invalid_ref 'refs///heads/foo'
|
||||
invalid_ref 'heads/foo/'
|
||||
invalid_ref '///heads/foo'
|
||||
invalid_ref '.foo'
|
||||
invalid_ref './foo'
|
||||
invalid_ref './foo/bar'
|
||||
invalid_ref 'foo/./bar'
|
||||
invalid_ref 'foo/bar/.'
|
||||
invalid_ref 'foo bar'
|
||||
invalid_ref 'foo?bar'
|
||||
invalid_ref 'foo^bar'
|
||||
invalid_ref 'foo~bar'
|
||||
invalid_ref 'foo:bar'
|
||||
invalid_ref 'foo[bar'
|
||||
invalid_ref 'foo/bar/.'
|
||||
invalid_ref '.refs/foo'
|
||||
invalid_ref 'refs/heads/foo.'
|
||||
invalid_ref 'heads/foo..bar'
|
||||
invalid_ref 'heads/foo?bar'
|
||||
invalid_ref 'heads/foo.lock'
|
||||
invalid_ref 'heads///foo.lock'
|
||||
invalid_ref 'foo.lock/bar'
|
||||
invalid_ref 'foo.lock///bar'
|
||||
invalid_ref 'heads/v@{ation'
|
||||
invalid_ref 'heads/foo\.ar' # should fail due to \
|
||||
invalid_ref 'heads/foo\bar' # should fail due to \
|
||||
invalid_ref "$(printf 'heads/foo\t')" # should fail because it has a TAB
|
||||
invalid_ref "$(printf 'heads/foo\177')"
|
||||
invalid_ref '@'
|
||||
|
||||
invalid_ref 'foo/*'
|
||||
invalid_ref '*/foo'
|
||||
invalid_ref 'foo/*/bar'
|
||||
invalid_ref '*'
|
||||
invalid_ref 'foo/*/*'
|
||||
invalid_ref '*/foo/*'
|
||||
invalid_ref '/foo'
|
||||
invalid_ref ''
|
128
tests/functional/fetchGitSubmodules.sh
Normal file
128
tests/functional/fetchGitSubmodules.sh
Normal file
|
@ -0,0 +1,128 @@
|
|||
source common.sh
|
||||
|
||||
set -u
|
||||
|
||||
requireGit
|
||||
|
||||
clearStore
|
||||
|
||||
rootRepo=$TEST_ROOT/gitSubmodulesRoot
|
||||
subRepo=$TEST_ROOT/gitSubmodulesSub
|
||||
|
||||
rm -rf ${rootRepo} ${subRepo} $TEST_HOME/.cache/nix
|
||||
|
||||
# Submodules can't be fetched locally by default, which can cause
|
||||
# information leakage vulnerabilities, but for these tests our
|
||||
# submodule is intentionally local and it's all trusted, so we
|
||||
# disable this restriction. Setting it per repo is not sufficient, as
|
||||
# the repo-local config does not apply to the commands run from
|
||||
# outside the repos by Nix.
|
||||
export XDG_CONFIG_HOME=$TEST_HOME/.config
|
||||
git config --global protocol.file.allow always
|
||||
|
||||
initGitRepo() {
|
||||
git init $1
|
||||
git -C $1 config user.email "foobar@example.com"
|
||||
git -C $1 config user.name "Foobar"
|
||||
}
|
||||
|
||||
addGitContent() {
|
||||
echo "lorem ipsum" > $1/content
|
||||
git -C $1 add content
|
||||
git -C $1 commit -m "Initial commit"
|
||||
}
|
||||
|
||||
initGitRepo $subRepo
|
||||
addGitContent $subRepo
|
||||
|
||||
initGitRepo $rootRepo
|
||||
|
||||
git -C $rootRepo submodule init
|
||||
git -C $rootRepo submodule add $subRepo sub
|
||||
git -C $rootRepo add sub
|
||||
git -C $rootRepo commit -m "Add submodule"
|
||||
|
||||
rev=$(git -C $rootRepo rev-parse HEAD)
|
||||
|
||||
r1=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; }).outPath")
|
||||
r2=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = false; }).outPath")
|
||||
r3=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = true; }).outPath")
|
||||
|
||||
[[ $r1 == $r2 ]]
|
||||
[[ $r2 != $r3 ]]
|
||||
|
||||
r4=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; }).outPath")
|
||||
r5=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = false; }).outPath")
|
||||
r6=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = true; }).outPath")
|
||||
r7=$(nix eval --raw --expr "(builtins.fetchGit { url = $rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = true; }).outPath")
|
||||
r8=$(nix eval --raw --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; submodules = true; }).outPath")
|
||||
|
||||
[[ $r1 == $r4 ]]
|
||||
[[ $r4 == $r5 ]]
|
||||
[[ $r3 == $r6 ]]
|
||||
[[ $r6 == $r7 ]]
|
||||
[[ $r7 == $r8 ]]
|
||||
|
||||
have_submodules=$(nix eval --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; }).submodules")
|
||||
[[ $have_submodules == false ]]
|
||||
|
||||
have_submodules=$(nix eval --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; submodules = false; }).submodules")
|
||||
[[ $have_submodules == false ]]
|
||||
|
||||
have_submodules=$(nix eval --expr "(builtins.fetchGit { url = $rootRepo; rev = \"$rev\"; submodules = true; }).submodules")
|
||||
[[ $have_submodules == true ]]
|
||||
|
||||
pathWithoutSubmodules=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; }).outPath")
|
||||
pathWithSubmodules=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = true; }).outPath")
|
||||
pathWithSubmodulesAgain=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev\"; submodules = true; }).outPath")
|
||||
pathWithSubmodulesAgainWithRef=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; ref = \"master\"; rev = \"$rev\"; submodules = true; }).outPath")
|
||||
|
||||
# The resulting store path cannot be the same.
|
||||
[[ $pathWithoutSubmodules != $pathWithSubmodules ]]
|
||||
|
||||
# Checking out the same repo with submodules returns in the same store path.
|
||||
[[ $pathWithSubmodules == $pathWithSubmodulesAgain ]]
|
||||
|
||||
# Checking out the same repo with submodules returns in the same store path.
|
||||
[[ $pathWithSubmodulesAgain == $pathWithSubmodulesAgainWithRef ]]
|
||||
|
||||
# The submodules flag is actually honored.
|
||||
[[ ! -e $pathWithoutSubmodules/sub/content ]]
|
||||
[[ -e $pathWithSubmodules/sub/content ]]
|
||||
|
||||
[[ -e $pathWithSubmodulesAgainWithRef/sub/content ]]
|
||||
|
||||
# No .git directory or submodule reference files must be left
|
||||
test "$(find "$pathWithSubmodules" -name .git)" = ""
|
||||
|
||||
# Git repos without submodules can be fetched with submodules = true.
|
||||
subRev=$(git -C $subRepo rev-parse HEAD)
|
||||
noSubmoduleRepoBaseline=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$subRepo; rev = \"$subRev\"; }).outPath")
|
||||
noSubmoduleRepo=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$subRepo; rev = \"$subRev\"; submodules = true; }).outPath")
|
||||
|
||||
[[ $noSubmoduleRepoBaseline == $noSubmoduleRepo ]]
|
||||
|
||||
# Test relative submodule URLs.
|
||||
rm $TEST_HOME/.cache/nix/fetcher-cache*
|
||||
rm -rf $rootRepo/.git $rootRepo/.gitmodules $rootRepo/sub
|
||||
initGitRepo $rootRepo
|
||||
git -C $rootRepo submodule add ../gitSubmodulesSub sub
|
||||
git -C $rootRepo commit -m "Add submodule"
|
||||
rev2=$(git -C $rootRepo rev-parse HEAD)
|
||||
pathWithRelative=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$rootRepo; rev = \"$rev2\"; submodules = true; }).outPath")
|
||||
diff -r -x .gitmodules $pathWithSubmodules $pathWithRelative
|
||||
|
||||
# Test clones that have an upstream with relative submodule URLs.
|
||||
rm $TEST_HOME/.cache/nix/fetcher-cache*
|
||||
cloneRepo=$TEST_ROOT/a/b/gitSubmodulesClone # NB /a/b to make the relative path not work relative to $cloneRepo
|
||||
git clone $rootRepo $cloneRepo
|
||||
pathIndirect=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$cloneRepo; rev = \"$rev2\"; submodules = true; }).outPath")
|
||||
[[ $pathIndirect = $pathWithRelative ]]
|
||||
|
||||
# Test that if the clone has the submodule already, we're not fetching
|
||||
# it again.
|
||||
git -C $cloneRepo submodule update --init
|
||||
rm $TEST_HOME/.cache/nix/fetcher-cache*
|
||||
rm -rf $subRepo
|
||||
pathSubmoduleGone=$(nix eval --raw --expr "(builtins.fetchGit { url = file://$cloneRepo; rev = \"$rev2\"; submodules = true; }).outPath")
|
||||
[[ $pathSubmoduleGone = $pathWithRelative ]]
|
76
tests/functional/fetchGitVerification.sh
Normal file
76
tests/functional/fetchGitVerification.sh
Normal file
|
@ -0,0 +1,76 @@
|
|||
source common.sh
|
||||
|
||||
requireGit
|
||||
[[ $(type -p ssh-keygen) ]] || skipTest "ssh-keygen not installed" # require ssh-keygen
|
||||
|
||||
enableFeatures "verified-fetches"
|
||||
|
||||
clearStore
|
||||
|
||||
repo="$TEST_ROOT/git"
|
||||
|
||||
# generate signing keys
|
||||
keysDir=$TEST_ROOT/.ssh
|
||||
mkdir -p "$keysDir"
|
||||
ssh-keygen -f "$keysDir/testkey1" -t ed25519 -P "" -C "test key 1"
|
||||
key1File="$keysDir/testkey1.pub"
|
||||
publicKey1=$(awk '{print $2}' "$key1File")
|
||||
ssh-keygen -f "$keysDir/testkey2" -t rsa -P "" -C "test key 2"
|
||||
key2File="$keysDir/testkey2.pub"
|
||||
publicKey2=$(awk '{print $2}' "$key2File")
|
||||
|
||||
git init $repo
|
||||
git -C $repo config user.email "foobar@example.com"
|
||||
git -C $repo config user.name "Foobar"
|
||||
git -C $repo config gpg.format ssh
|
||||
|
||||
echo 'hello' > $repo/text
|
||||
git -C $repo add text
|
||||
git -C $repo -c "user.signingkey=$key1File" commit -S -m 'initial commit'
|
||||
|
||||
out=$(nix eval --impure --raw --expr "builtins.fetchGit { url = \"file://$repo\"; keytype = \"ssh-rsa\"; publicKey = \"$publicKey2\"; }" 2>&1) || status=$?
|
||||
[[ $status == 1 ]]
|
||||
[[ $out =~ 'No principal matched.' ]]
|
||||
[[ $(nix eval --impure --raw --expr "builtins.readFile (builtins.fetchGit { url = \"file://$repo\"; publicKey = \"$publicKey1\"; } + \"/text\")") = 'hello' ]]
|
||||
|
||||
echo 'hello world' > $repo/text
|
||||
git -C $repo add text
|
||||
git -C $repo -c "user.signingkey=$key2File" commit -S -m 'second commit'
|
||||
|
||||
[[ $(nix eval --impure --raw --expr "builtins.readFile (builtins.fetchGit { url = \"file://$repo\"; publicKeys = [{key = \"$publicKey1\";} {type = \"ssh-rsa\"; key = \"$publicKey2\";}]; } + \"/text\")") = 'hello world' ]]
|
||||
|
||||
# Flake input test
|
||||
flakeDir="$TEST_ROOT/flake"
|
||||
mkdir -p "$flakeDir"
|
||||
cat > "$flakeDir/flake.nix" <<EOF
|
||||
{
|
||||
inputs.test = {
|
||||
type = "git";
|
||||
url = "file://$repo";
|
||||
flake = false;
|
||||
publicKeys = [
|
||||
{ type = "ssh-rsa"; key = "$publicKey2"; }
|
||||
];
|
||||
};
|
||||
|
||||
outputs = { test, ... }: { test = test.outPath; };
|
||||
}
|
||||
EOF
|
||||
nix build --out-link "$flakeDir/result" "$flakeDir#test"
|
||||
[[ $(cat "$flakeDir/result/text") = 'hello world' ]]
|
||||
|
||||
cat > "$flakeDir/flake.nix" <<EOF
|
||||
{
|
||||
inputs.test = {
|
||||
type = "git";
|
||||
url = "file://$repo";
|
||||
flake = false;
|
||||
publicKey= "$publicKey1";
|
||||
};
|
||||
|
||||
outputs = { test, ... }: { test = test.outPath; };
|
||||
}
|
||||
EOF
|
||||
out=$(nix build "$flakeDir#test" 2>&1) || status=$?
|
||||
[[ $status == 1 ]]
|
||||
[[ $out =~ 'No principal matched.' ]]
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue