aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/common-eval-args.cc2
-rw-r--r--src/libexpr/eval.cc1
-rw-r--r--src/libexpr/eval.hh8
-rw-r--r--src/libexpr/flake/flake.cc17
-rw-r--r--src/libexpr/flake/flake.hh1
-rw-r--r--src/libexpr/flake/flakeref.cc1
-rw-r--r--src/libexpr/flake/lockfile.cc1
-rw-r--r--src/libexpr/json-to-value.cc8
-rw-r--r--src/libexpr/local.mk2
-rw-r--r--src/libexpr/parser.y5
-rw-r--r--src/libexpr/primops.cc34
-rw-r--r--src/libexpr/primops/derivation.nix27
-rw-r--r--src/libexpr/primops/fetchMercurial.cc3
-rw-r--r--src/libexpr/primops/fetchTree.cc4
14 files changed, 81 insertions, 33 deletions
diff --git a/src/libexpr/common-eval-args.cc b/src/libexpr/common-eval-args.cc
index d71aa22f1..10c1a6975 100644
--- a/src/libexpr/common-eval-args.cc
+++ b/src/libexpr/common-eval-args.cc
@@ -76,7 +76,7 @@ Path lookupFileArg(EvalState & state, string s)
if (isUri(s)) {
return state.store->toRealPath(
fetchers::downloadTarball(
- state.store, resolveUri(s), Headers {}, "source", false).first.storePath);
+ state.store, resolveUri(s), "source", false).first.storePath);
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
Path p = s.substr(1, s.size() - 2);
return state.findFile(p);
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 139067f20..883fc27a7 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -356,6 +356,7 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
, sEpsilon(symbols.create(""))
, repair(NoRepair)
, store(store)
+ , regexCache(makeRegexCache())
, baseEnv(allocEnv(128))
, staticBaseEnv(false, 0)
{
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 80078d8a5..0e1f61baa 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -6,7 +6,6 @@
#include "symbol-table.hh"
#include "config.hh"
-#include <regex>
#include <map>
#include <optional>
#include <unordered_map>
@@ -65,6 +64,11 @@ typedef std::list<SearchPathElem> SearchPath;
void initGC();
+struct RegexCache;
+
+std::shared_ptr<RegexCache> makeRegexCache();
+
+
class EvalState
{
public:
@@ -120,7 +124,7 @@ private:
std::unordered_map<Path, Path> resolvedPaths;
/* Cache used by prim_match(). */
- std::unordered_map<std::string, std::regex> regexCache;
+ std::shared_ptr<RegexCache> regexCache;
public:
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 01f464859..b4ede542c 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -48,17 +48,17 @@ static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
resolvedRef = originalRef.resolve(state.store);
auto fetchedResolved = lookupInFlakeCache(flakeCache, originalRef);
if (!fetchedResolved) fetchedResolved.emplace(resolvedRef.fetchTree(state.store));
- flakeCache.push_back({resolvedRef, fetchedResolved.value()});
- fetched.emplace(fetchedResolved.value());
+ flakeCache.push_back({resolvedRef, *fetchedResolved});
+ fetched.emplace(*fetchedResolved);
}
else {
throw Error("'%s' is an indirect flake reference, but registry lookups are not allowed", originalRef);
}
}
- flakeCache.push_back({originalRef, fetched.value()});
+ flakeCache.push_back({originalRef, *fetched});
}
- auto [tree, lockedRef] = fetched.value();
+ auto [tree, lockedRef] = *fetched;
debug("got tree '%s' from '%s'",
state.store->printStorePath(tree.storePath), lockedRef);
@@ -215,10 +215,9 @@ static Flake getFlake(
if (auto outputs = vInfo.attrs->get(sOutputs)) {
expectType(state, tLambda, *outputs->value, *outputs->pos);
- flake.vOutputs = allocRootValue(outputs->value);
- if ((*flake.vOutputs)->lambda.fun->matchAttrs) {
- for (auto & formal : (*flake.vOutputs)->lambda.fun->formals->formals) {
+ if (outputs->value->lambda.fun->matchAttrs) {
+ for (auto & formal : outputs->value->lambda.fun->formals->formals) {
if (formal.name != state.sSelf)
flake.inputs.emplace(formal.name, FlakeInput {
.ref = parseFlakeRef(formal.name)
@@ -248,7 +247,7 @@ Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool allowLookup
}
/* Compute an in-memory lock file for the specified top-level flake,
- and optionally write it to file, it the flake is writable. */
+ and optionally write it to file, if the flake is writable. */
LockedFlake lockFlake(
EvalState & state,
const FlakeRef & topRef,
@@ -367,7 +366,7 @@ LockedFlake lockFlake(
/* If we have an --update-input flag for an input
of this input, then we must fetch the flake to
- to update it. */
+ update it. */
auto lb = lockFlags.inputUpdates.lower_bound(inputPath);
auto hasChildUpdate =
diff --git a/src/libexpr/flake/flake.hh b/src/libexpr/flake/flake.hh
index c2bb2888b..69c779af8 100644
--- a/src/libexpr/flake/flake.hh
+++ b/src/libexpr/flake/flake.hh
@@ -34,7 +34,6 @@ struct Flake
std::optional<std::string> description;
std::shared_ptr<const fetchers::Tree> sourceInfo;
FlakeInputs inputs;
- RootValue vOutputs;
~Flake();
};
diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc
index 6363446f6..d5c2ffe66 100644
--- a/src/libexpr/flake/flakeref.cc
+++ b/src/libexpr/flake/flakeref.cc
@@ -1,6 +1,7 @@
#include "flakeref.hh"
#include "store-api.hh"
#include "url.hh"
+#include "url-parts.hh"
#include "fetchers.hh"
#include "registry.hh"
diff --git a/src/libexpr/flake/lockfile.cc b/src/libexpr/flake/lockfile.cc
index a74846944..78431f000 100644
--- a/src/libexpr/flake/lockfile.cc
+++ b/src/libexpr/flake/lockfile.cc
@@ -1,5 +1,6 @@
#include "lockfile.hh"
#include "store-api.hh"
+#include "url-parts.hh"
#include <nlohmann/json.hpp>
diff --git a/src/libexpr/json-to-value.cc b/src/libexpr/json-to-value.cc
index 76e1a26bf..9ca5ac86d 100644
--- a/src/libexpr/json-to-value.cc
+++ b/src/libexpr/json-to-value.cc
@@ -115,6 +115,14 @@ public:
{
return handle_value<void(Value&, const char*)>(mkString, val.c_str());
}
+#if NLOHMANN_JSON_VERSION_MAJOR >= 3 && NLOHMANN_JSON_VERSION_MINOR >= 8
+ bool binary(binary_t&)
+ {
+ // This function ought to be unreachable
+ assert(false);
+ return true;
+ }
+#endif
bool start_object(std::size_t len)
{
diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk
index d84b150e0..687a8ccda 100644
--- a/src/libexpr/local.mk
+++ b/src/libexpr/local.mk
@@ -42,6 +42,6 @@ $(eval $(call install-file-in, $(d)/nix-expr.pc, $(prefix)/lib/pkgconfig, 0644))
$(foreach i, $(wildcard src/libexpr/flake/*.hh), \
$(eval $(call install-file-in, $(i), $(includedir)/nix/flake, 0644)))
-$(d)/primops.cc: $(d)/imported-drv-to-derivation.nix.gen.hh
+$(d)/primops.cc: $(d)/imported-drv-to-derivation.nix.gen.hh $(d)/primops/derivation.nix.gen.hh
$(d)/flake/flake.cc: $(d)/flake/call-flake.nix.gen.hh
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 28e31f46b..a4c84c526 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -614,8 +614,7 @@ Path resolveExprPath(Path path)
// Basic cycle/depth limit to avoid infinite loops.
if (++followCount >= maxFollow)
throw Error("too many symbolic links encountered while traversing the path '%s'", path);
- if (lstat(path.c_str(), &st))
- throw SysError("getting status of '%s'", path);
+ st = lstat(path);
if (!S_ISLNK(st.st_mode)) break;
path = absPath(readLink(path), dirOf(path));
}
@@ -719,7 +718,7 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl
if (isUri(elem.second)) {
try {
res = { true, store->toRealPath(fetchers::downloadTarball(
- store, resolveUri(elem.second), Headers {}, "source", false).first.storePath) };
+ store, resolveUri(elem.second), "source", false).first.storePath) };
} catch (FileTransferError & e) {
logWarning({
.name = "Entry download",
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index d0b0c57b2..2b304aab0 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -2236,6 +2236,10 @@ static RegisterPrimOp primop_catAttrs({
static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
state.forceValue(*args[0], pos);
+ if (args[0]->type == tPrimOpApp || args[0]->type == tPrimOp) {
+ state.mkAttrs(v, 0);
+ return;
+ }
if (args[0]->type != tLambda)
throw TypeError({
.hint = hintfmt("'functionArgs' requires a function"),
@@ -3085,17 +3089,25 @@ static RegisterPrimOp primop_hashString({
.fun = prim_hashString,
});
-/* Match a regular expression against a string and return either
- ‘null’ or a list containing substring matches. */
+struct RegexCache
+{
+ std::unordered_map<std::string, std::regex> cache;
+};
+
+std::shared_ptr<RegexCache> makeRegexCache()
+{
+ return std::make_shared<RegexCache>();
+}
+
void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
auto re = state.forceStringNoCtx(*args[0], pos);
try {
- auto regex = state.regexCache.find(re);
- if (regex == state.regexCache.end())
- regex = state.regexCache.emplace(re, std::regex(re, std::regex::extended)).first;
+ auto regex = state.regexCache->cache.find(re);
+ if (regex == state.regexCache->cache.end())
+ regex = state.regexCache->cache.emplace(re, std::regex(re, std::regex::extended)).first;
PathSet context;
const std::string str = state.forceString(*args[1], context, pos);
@@ -3565,13 +3577,11 @@ void EvalState::createBaseEnv()
/* Add a wrapper around the derivation primop that computes the
`drvPath' and `outPath' attributes lazily. */
- try {
- string path = canonPath(settings.nixDataDir + "/nix/corepkgs/derivation.nix", true);
- sDerivationNix = symbols.create(path);
- evalFile(path, v);
- addConstant("derivation", v);
- } catch (SysError &) {
- }
+ sDerivationNix = symbols.create("//builtin/derivation.nix");
+ eval(parse(
+ #include "primops/derivation.nix.gen.hh"
+ , foFile, sDerivationNix, "/", staticBaseEnv), v);
+ addConstant("derivation", v);
/* Now that we've added all primops, sort the `builtins' set,
because attribute lookups expect it to be sorted. */
diff --git a/src/libexpr/primops/derivation.nix b/src/libexpr/primops/derivation.nix
new file mode 100644
index 000000000..c0fbe8082
--- /dev/null
+++ b/src/libexpr/primops/derivation.nix
@@ -0,0 +1,27 @@
+/* This is the implementation of the ‘derivation’ builtin function.
+ It's actually a wrapper around the ‘derivationStrict’ primop. */
+
+drvAttrs @ { outputs ? [ "out" ], ... }:
+
+let
+
+ strict = derivationStrict drvAttrs;
+
+ commonAttrs = drvAttrs // (builtins.listToAttrs outputsList) //
+ { all = map (x: x.value) outputsList;
+ inherit drvAttrs;
+ };
+
+ outputToAttrListElement = outputName:
+ { name = outputName;
+ value = commonAttrs // {
+ outPath = builtins.getAttr outputName strict;
+ drvPath = strict.drvPath;
+ type = "derivation";
+ inherit outputName;
+ };
+ };
+
+ outputsList = map outputToAttrListElement outputs;
+
+in (builtins.head outputsList).value
diff --git a/src/libexpr/primops/fetchMercurial.cc b/src/libexpr/primops/fetchMercurial.cc
index cef85cfef..1a064ed5c 100644
--- a/src/libexpr/primops/fetchMercurial.cc
+++ b/src/libexpr/primops/fetchMercurial.cc
@@ -3,8 +3,7 @@
#include "store-api.hh"
#include "fetchers.hh"
#include "url.hh"
-
-#include <regex>
+#include "url-parts.hh"
namespace nix {
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
index 3001957b4..06e8304b8 100644
--- a/src/libexpr/primops/fetchTree.cc
+++ b/src/libexpr/primops/fetchTree.cc
@@ -201,8 +201,8 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
auto storePath =
unpack
- ? fetchers::downloadTarball(state.store, *url, Headers {}, name, (bool) expectedHash).first.storePath
- : fetchers::downloadFile(state.store, *url, Headers{}, name, (bool) expectedHash).storePath;
+ ? fetchers::downloadTarball(state.store, *url, name, (bool) expectedHash).first.storePath
+ : fetchers::downloadFile(state.store, *url, name, (bool) expectedHash).storePath;
auto path = state.store->toRealPath(storePath);