From b72e93bca8fc045b37b1e863c423cf0e91e8c479 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 28 Aug 2014 18:57:13 +0200 Subject: [PATCH] Add disallowedReferences / disallowedRequisites For the "stdenv accidentally referring to bootstrap-tools", it seems easier to specify the path that we don't want to depend on, e.g. disallowedRequisites = [ bootstrapTools ]; --- src/libstore/build.cc | 55 +++++++++++++++++++++++-------------------- tests/check-refs.nix | 12 ++++++++++ tests/check-refs.sh | 6 +++++ tests/check-reqs.nix | 14 +++++++++++ tests/check-reqs.sh | 5 ++-- 5 files changed, 64 insertions(+), 28 deletions(-) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 6390a7480..0d290d787 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -2318,33 +2318,36 @@ void DerivationGoal::registerOutputs() debug(format("referenced input: ‘%1%’") % *i); } - /* If the derivation specifies an `allowedReferences' - attribute (containing a list of paths that the output may - refer to), check that all references are in that list. !!! - allowedReferences should really be per-output. */ - if (drv.env.find("allowedReferences") != drv.env.end()) { - PathSet allowed = parseReferenceSpecifiers(drv, get(drv.env, "allowedReferences")); - foreach (PathSet::iterator, i, references) - if (allowed.find(*i) == allowed.end()) - throw BuildError(format("output (‘%1%’) is not allowed to refer to path ‘%2%’") % actualPath % *i); - } + /* Enforce `allowedReferences' and friends. */ + auto checkRefs = [&](const string & attrName, bool allowed, bool recursive) { + if (drv.env.find(attrName) == drv.env.end()) return; - /* If the derivation specifies an `allowedRequisites' - attribute (containing a list of paths that the output may - refer to), check that all requisites are in that list. !!! - allowedRequisites should really be per-output. */ - if (drv.env.find("allowedRequisites") != drv.env.end()) { - PathSet allowed = parseReferenceSpecifiers(drv, get(drv.env, "allowedRequisites")); - PathSet requisites; - /* Our requisites are the union of the closures of our references. */ - foreach (PathSet::iterator, i, references) - /* Don't call computeFSClosure on ourselves. */ - if (actualPath != *i) - computeFSClosure(worker.store, *i, requisites); - foreach (PathSet::iterator, i, requisites) - if (allowed.find(*i) == allowed.end()) - throw BuildError(format("output (‘%1%’) is not allowed to refer to requisite path ‘%2%’") % actualPath % *i); - } + PathSet spec = parseReferenceSpecifiers(drv, get(drv.env, attrName)); + + PathSet used; + if (recursive) { + /* Our requisites are the union of the closures of our references. */ + for (auto & i : references) + /* Don't call computeFSClosure on ourselves. */ + if (actualPath != i) + computeFSClosure(worker.store, i, used); + } else + used = references; + + for (auto & i : used) + if (allowed) { + if (spec.find(i) == spec.end()) + throw BuildError(format("output (‘%1%’) is not allowed to refer to path ‘%2%’") % actualPath % i); + } else { + if (spec.find(i) != spec.end()) + throw BuildError(format("output (‘%1%’) is not allowed to refer to path ‘%2%’") % actualPath % i); + } + }; + + checkRefs("allowedReferences", true, false); + checkRefs("allowedRequisites", true, true); + checkRefs("disallowedReferences", false, false); + checkRefs("disallowedRequisites", false, true); worker.store.optimisePath(path); // FIXME: combine with scanForReferences() diff --git a/tests/check-refs.nix b/tests/check-refs.nix index 63791fe16..9d90b0920 100644 --- a/tests/check-refs.nix +++ b/tests/check-refs.nix @@ -55,4 +55,16 @@ rec { 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]; + }; + } diff --git a/tests/check-refs.sh b/tests/check-refs.sh index 9e103664a..34ee22cfc 100644 --- a/tests/check-refs.sh +++ b/tests/check-refs.sh @@ -32,3 +32,9 @@ 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 diff --git a/tests/check-reqs.nix b/tests/check-reqs.nix index 5af8ea6fa..41436cb48 100644 --- a/tests/check-reqs.nix +++ b/tests/check-reqs.nix @@ -40,4 +40,18 @@ rec { 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]; + }; } diff --git a/tests/check-reqs.sh b/tests/check-reqs.sh index 643c2d0cd..8b2454915 100644 --- a/tests/check-reqs.sh +++ b/tests/check-reqs.sh @@ -2,11 +2,12 @@ source common.sh RESULT=$TEST_ROOT/result -# test1 should succeed. nix-build -o $RESULT check-reqs.nix -A test1 -# test{2,3,4,5} should fail. (! 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) (! 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