aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/eval.cc36
-rw-r--r--src/libexpr/eval.hh13
-rw-r--r--src/libstore/build/local-derivation-goal.cc25
-rw-r--r--src/libutil/experimental-features.cc1
-rw-r--r--src/libutil/experimental-features.hh1
-rw-r--r--src/libutil/tests/url.cc21
-rw-r--r--src/libutil/url.cc6
7 files changed, 78 insertions, 25 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 1828b8c2e..a48968656 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -519,6 +519,7 @@ EvalState::EvalState(
static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes");
/* Initialise the Nix expression search path. */
+ evalSettings.nixPath.setDefault(evalSettings.getDefaultNixPath());
if (!evalSettings.pureEval) {
for (auto & i : _searchPath) addToSearchPath(i);
for (auto & i : evalSettings.nixPath.get()) addToSearchPath(i);
@@ -2472,30 +2473,35 @@ std::ostream & operator << (std::ostream & str, const ExternalValueBase & v) {
EvalSettings::EvalSettings()
{
- auto var = getEnv("NIX_PATH");
- if (var) nixPath = parseNixPath(*var);
}
+/* impure => NIX_PATH or a default path
+ * restrict-eval => NIX_PATH
+ * pure-eval => empty
+ */
Strings EvalSettings::getDefaultNixPath()
{
- Strings res;
- auto add = [&](const Path & p, const std::string & s = std::string()) {
- if (pathExists(p)) {
- if (s.empty()) {
- res.push_back(p);
- } else {
- res.push_back(s + "=" + p);
- }
- }
- };
+ if (pureEval)
+ return {};
+
+ auto var = getEnv("NIX_PATH");
+ if (var) {
+ return parseNixPath(*var);
+ } else if (restrictEval) {
+ return {};
+ } else {
+ Strings res;
+ auto add = [&](const Path & p, const std::optional<std::string> & s = std::nullopt) {
+ if (pathExists(p))
+ res.push_back(s ? *s + "=" + p : p);
+ };
- if (!evalSettings.restrictEval && !evalSettings.pureEval) {
add(getHome() + "/.nix-defexpr/channels");
add(settings.nixStateDir + "/profiles/per-user/root/channels/nixpkgs", "nixpkgs");
add(settings.nixStateDir + "/profiles/per-user/root/channels");
- }
- return res;
+ return res;
+ }
}
bool EvalSettings::isPseudoUrl(std::string_view s)
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index e4d5906bd..2340ef67b 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -570,7 +570,7 @@ struct EvalSettings : Config
{
EvalSettings();
- static Strings getDefaultNixPath();
+ Strings getDefaultNixPath();
static bool isPseudoUrl(std::string_view s);
@@ -580,8 +580,15 @@ struct EvalSettings : Config
"Whether builtin functions that allow executing native code should be enabled."};
Setting<Strings> nixPath{
- this, getDefaultNixPath(), "nix-path",
- "List of directories to be searched for `<...>` file references."};
+ this, {}, "nix-path",
+ R"(
+ List of directories to be searched for `<...>` file references.
+
+ If [pure evaluation](#conf-pure-eval) is disabled,
+ this is initialised using the [`NIX_PATH`](@docroot@/command-ref/env-common.md#env-NIX_PATH)
+ environment variable, or, if it is unset and [restricted evaluation](#conf-restrict-eval)
+ is disabled, a default search path including the user's and `root`'s channels.
+ )"};
Setting<bool> restrictEval{
this, false, "restrict-eval",
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index 9ab9b17fe..2b85b20d1 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -2323,11 +2323,28 @@ DrvOutputs LocalDerivationGoal::registerOutputs()
buildUser ? std::optional(buildUser->getUIDRange()) : std::nullopt,
inodesSeen);
- debug("scanning for references for output '%s' in temp location '%s'", outputName, actualPath);
+ bool discardReferences = false;
+ if (auto structuredAttrs = parsedDrv->getStructuredAttrs()) {
+ if (auto udr = get(*structuredAttrs, "unsafeDiscardReferences")) {
+ settings.requireExperimentalFeature(Xp::DiscardReferences);
+ if (auto output = get(*udr, outputName)) {
+ if (!output->is_boolean())
+ throw Error("attribute 'unsafeDiscardReferences.\"%s\"' of derivation '%s' must be a Boolean", outputName, drvPath.to_string());
+ discardReferences = output->get<bool>();
+ }
+ }
+ }
- /* Pass blank Sink as we are not ready to hash data at this stage. */
- NullSink blank;
- auto references = scanForReferences(blank, actualPath, referenceablePaths);
+ StorePathSet references;
+ if (discardReferences)
+ debug("discarding references of output '%s'", outputName);
+ else {
+ debug("scanning for references for output '%s' in temp location '%s'", outputName, actualPath);
+
+ /* Pass blank Sink as we are not ready to hash data at this stage. */
+ NullSink blank;
+ references = scanForReferences(blank, actualPath, referenceablePaths);
+ }
outputReferencesIfUnregistered.insert_or_assign(
outputName,
diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc
index e0902971e..58d762ebb 100644
--- a/src/libutil/experimental-features.cc
+++ b/src/libutil/experimental-features.cc
@@ -16,6 +16,7 @@ std::map<ExperimentalFeature, std::string> stringifiedXpFeatures = {
{ Xp::ReplFlake, "repl-flake" },
{ Xp::AutoAllocateUids, "auto-allocate-uids" },
{ Xp::Cgroups, "cgroups" },
+ { Xp::DiscardReferences, "discard-references" },
};
const std::optional<ExperimentalFeature> parseExperimentalFeature(const std::string_view & name)
diff --git a/src/libutil/experimental-features.hh b/src/libutil/experimental-features.hh
index af775feb0..ac372e03e 100644
--- a/src/libutil/experimental-features.hh
+++ b/src/libutil/experimental-features.hh
@@ -25,6 +25,7 @@ enum struct ExperimentalFeature
ReplFlake,
AutoAllocateUids,
Cgroups,
+ DiscardReferences,
};
/**
diff --git a/src/libutil/tests/url.cc b/src/libutil/tests/url.cc
index c3b233797..e0c438b4d 100644
--- a/src/libutil/tests/url.cc
+++ b/src/libutil/tests/url.cc
@@ -99,6 +99,27 @@ namespace nix {
ASSERT_EQ(parsed, expected);
}
+ TEST(parseURL, parsesFilePlusHttpsUrl) {
+ auto s = "file+https://www.example.org/video.mp4";
+ auto parsed = parseURL(s);
+
+ ParsedURL expected {
+ .url = "file+https://www.example.org/video.mp4",
+ .base = "https://www.example.org/video.mp4",
+ .scheme = "file+https",
+ .authority = "www.example.org",
+ .path = "/video.mp4",
+ .query = (StringMap) { },
+ .fragment = "",
+ };
+
+ ASSERT_EQ(parsed, expected);
+ }
+
+ TEST(parseURL, rejectsAuthorityInUrlsWithFileTransportation) {
+ auto s = "file://www.example.org/video.mp4";
+ ASSERT_THROW(parseURL(s), Error);
+ }
TEST(parseURL, parseIPv4Address) {
auto s = "http://127.0.0.1:8080/file.tar.gz?download=fast&when=now#hello";
diff --git a/src/libutil/url.cc b/src/libutil/url.cc
index 5b7abeb49..4e43455e1 100644
--- a/src/libutil/url.cc
+++ b/src/libutil/url.cc
@@ -30,13 +30,13 @@ ParsedURL parseURL(const std::string & url)
auto & query = match[6];
auto & fragment = match[7];
- auto isFile = scheme.find("file") != std::string::npos;
+ auto transportIsFile = parseUrlScheme(scheme).transport == "file";
- if (authority && *authority != "" && isFile)
+ if (authority && *authority != "" && transportIsFile)
throw BadURL("file:// URL '%s' has unexpected authority '%s'",
url, *authority);
- if (isFile && path.empty())
+ if (transportIsFile && path.empty())
path = "/";
return ParsedURL{