aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/eval.cc148
-rw-r--r--src/libexpr/parser.y159
2 files changed, 148 insertions, 159 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index d3d1eb7f1..35b09f4d5 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -16,6 +16,7 @@
#include "print.hh"
#include "gc-small-vector.hh"
#include "fetch-to-store.hh"
+#include "flake/flakeref.hh"
#include <algorithm>
#include <chrono>
@@ -2658,6 +2659,153 @@ void EvalState::printStatistics()
}
+SourcePath resolveExprPath(SourcePath path)
+{
+ unsigned int followCount = 0, maxFollow = 1024;
+
+ /* If `path' is a symlink, follow it. This is so that relative
+ path references work. */
+ while (true) {
+ // 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 (path.lstat().type != InputAccessor::tSymlink) break;
+ path = {CanonPath(path.readLink(), path.path.parent().value_or(CanonPath::root))};
+ }
+
+ /* If `path' refers to a directory, append `/default.nix'. */
+ if (path.lstat().type == InputAccessor::tDirectory)
+ return path + "default.nix";
+
+ return path;
+}
+
+
+Expr * EvalState::parseExprFromFile(const SourcePath & path)
+{
+ return parseExprFromFile(path, staticBaseEnv);
+}
+
+
+Expr * EvalState::parseExprFromFile(const SourcePath & path, std::shared_ptr<StaticEnv> & staticEnv)
+{
+ auto buffer = path.readFile();
+ // readFile hopefully have left some extra space for terminators
+ buffer.append("\0\0", 2);
+ return parse(buffer.data(), buffer.size(), Pos::Origin(path), path.parent(), staticEnv);
+}
+
+
+Expr * EvalState::parseExprFromString(std::string s_, const SourcePath & basePath, std::shared_ptr<StaticEnv> & staticEnv)
+{
+ auto s = make_ref<std::string>(std::move(s_));
+ s->append("\0\0", 2);
+ return parse(s->data(), s->size(), Pos::String{.source = s}, basePath, staticEnv);
+}
+
+
+Expr * EvalState::parseExprFromString(std::string s, const SourcePath & basePath)
+{
+ return parseExprFromString(std::move(s), basePath, staticBaseEnv);
+}
+
+
+Expr * EvalState::parseStdin()
+{
+ //Activity act(*logger, lvlTalkative, "parsing standard input");
+ auto buffer = drainFD(0);
+ // drainFD should have left some extra space for terminators
+ buffer.append("\0\0", 2);
+ auto s = make_ref<std::string>(std::move(buffer));
+ return parse(s->data(), s->size(), Pos::Stdin{.source = s}, rootPath(CanonPath::fromCwd()), staticBaseEnv);
+}
+
+
+SourcePath EvalState::findFile(const std::string_view path)
+{
+ return findFile(searchPath, path);
+}
+
+
+SourcePath EvalState::findFile(const SearchPath & searchPath, const std::string_view path, const PosIdx pos)
+{
+ for (auto & i : searchPath.elements) {
+ auto suffixOpt = i.prefix.suffixIfPotentialMatch(path);
+
+ if (!suffixOpt) continue;
+ auto suffix = *suffixOpt;
+
+ auto rOpt = resolveSearchPathPath(i.path);
+ if (!rOpt) continue;
+ auto r = *rOpt;
+
+ Path res = suffix == "" ? r : concatStrings(r, "/", suffix);
+ if (pathExists(res)) return CanonPath(canonPath(res));
+ }
+
+ if (hasPrefix(path, "nix/"))
+ return CanonPath(concatStrings(corepkgsPrefix, path.substr(4)));
+
+ debugThrow(ThrownError({
+ .msg = hintfmt(evalSettings.pureEval
+ ? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)"
+ : "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)",
+ path),
+ .errPos = positions[pos]
+ }), 0, 0);
+}
+
+
+std::optional<std::string> EvalState::resolveSearchPathPath(const SearchPath::Path & value0)
+{
+ auto & value = value0.s;
+ auto i = searchPathResolved.find(value);
+ if (i != searchPathResolved.end()) return i->second;
+
+ std::optional<std::string> res;
+
+ if (EvalSettings::isPseudoUrl(value)) {
+ try {
+ auto storePath = fetchers::downloadTarball(
+ store, EvalSettings::resolvePseudoUrl(value), "source", false).tree.storePath;
+ res = { store->toRealPath(storePath) };
+ } catch (FileTransferError & e) {
+ logWarning({
+ .msg = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", value)
+ });
+ res = std::nullopt;
+ }
+ }
+
+ else if (hasPrefix(value, "flake:")) {
+ experimentalFeatureSettings.require(Xp::Flakes);
+ auto flakeRef = parseFlakeRef(value.substr(6), {}, true, false);
+ debug("fetching flake search path element '%s''", value);
+ auto storePath = flakeRef.resolve(store).fetchTree(store).first.storePath;
+ res = { store->toRealPath(storePath) };
+ }
+
+ else {
+ auto path = absPath(value);
+ if (pathExists(path))
+ res = { path };
+ else {
+ logWarning({
+ .msg = hintfmt("Nix search path entry '%1%' does not exist, ignoring", value)
+ });
+ res = std::nullopt;
+ }
+ }
+
+ if (res)
+ debug("resolved search path element '%s' to '%s'", value, *res);
+ else
+ debug("failed to resolve search path element '%s'", value);
+
+ searchPathResolved[value] = res;
+ return res;
+}
+
std::string ExternalValueBase::coerceToString(const Pos & pos, NixStringContext & context, bool copyMore, bool copyToStore) const
{
throw TypeError({
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 41414d69e..0d28d7961 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -388,22 +388,11 @@ formal
%%
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
#include "eval.hh"
-#include "filetransfer.hh"
-#include "fetchers.hh"
-#include "store-api.hh"
-#include "flake/flake.hh"
namespace nix {
-
Expr * EvalState::parse(
char * text,
size_t length,
@@ -431,152 +420,4 @@ Expr * EvalState::parse(
}
-SourcePath resolveExprPath(SourcePath path)
-{
- unsigned int followCount = 0, maxFollow = 1024;
-
- /* If `path' is a symlink, follow it. This is so that relative
- path references work. */
- while (true) {
- // 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 (path.lstat().type != InputAccessor::tSymlink) break;
- path = {CanonPath(path.readLink(), path.path.parent().value_or(CanonPath::root))};
- }
-
- /* If `path' refers to a directory, append `/default.nix'. */
- if (path.lstat().type == InputAccessor::tDirectory)
- return path + "default.nix";
-
- return path;
-}
-
-
-Expr * EvalState::parseExprFromFile(const SourcePath & path)
-{
- return parseExprFromFile(path, staticBaseEnv);
-}
-
-
-Expr * EvalState::parseExprFromFile(const SourcePath & path, std::shared_ptr<StaticEnv> & staticEnv)
-{
- auto buffer = path.readFile();
- // readFile hopefully have left some extra space for terminators
- buffer.append("\0\0", 2);
- return parse(buffer.data(), buffer.size(), Pos::Origin(path), path.parent(), staticEnv);
-}
-
-
-Expr * EvalState::parseExprFromString(std::string s_, const SourcePath & basePath, std::shared_ptr<StaticEnv> & staticEnv)
-{
- auto s = make_ref<std::string>(std::move(s_));
- s->append("\0\0", 2);
- return parse(s->data(), s->size(), Pos::String{.source = s}, basePath, staticEnv);
-}
-
-
-Expr * EvalState::parseExprFromString(std::string s, const SourcePath & basePath)
-{
- return parseExprFromString(std::move(s), basePath, staticBaseEnv);
-}
-
-
-Expr * EvalState::parseStdin()
-{
- //Activity act(*logger, lvlTalkative, "parsing standard input");
- auto buffer = drainFD(0);
- // drainFD should have left some extra space for terminators
- buffer.append("\0\0", 2);
- auto s = make_ref<std::string>(std::move(buffer));
- return parse(s->data(), s->size(), Pos::Stdin{.source = s}, rootPath(CanonPath::fromCwd()), staticBaseEnv);
-}
-
-
-SourcePath EvalState::findFile(const std::string_view path)
-{
- return findFile(searchPath, path);
-}
-
-
-SourcePath EvalState::findFile(const SearchPath & searchPath, const std::string_view path, const PosIdx pos)
-{
- for (auto & i : searchPath.elements) {
- auto suffixOpt = i.prefix.suffixIfPotentialMatch(path);
-
- if (!suffixOpt) continue;
- auto suffix = *suffixOpt;
-
- auto rOpt = resolveSearchPathPath(i.path);
- if (!rOpt) continue;
- auto r = *rOpt;
-
- Path res = suffix == "" ? r : concatStrings(r, "/", suffix);
- if (pathExists(res)) return CanonPath(canonPath(res));
- }
-
- if (hasPrefix(path, "nix/"))
- return CanonPath(concatStrings(corepkgsPrefix, path.substr(4)));
-
- debugThrow(ThrownError({
- .msg = hintfmt(evalSettings.pureEval
- ? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)"
- : "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)",
- path),
- .errPos = positions[pos]
- }), 0, 0);
-}
-
-
-std::optional<std::string> EvalState::resolveSearchPathPath(const SearchPath::Path & value0)
-{
- auto & value = value0.s;
- auto i = searchPathResolved.find(value);
- if (i != searchPathResolved.end()) return i->second;
-
- std::optional<std::string> res;
-
- if (EvalSettings::isPseudoUrl(value)) {
- try {
- auto storePath = fetchers::downloadTarball(
- store, EvalSettings::resolvePseudoUrl(value), "source", false).tree.storePath;
- res = { store->toRealPath(storePath) };
- } catch (FileTransferError & e) {
- logWarning({
- .msg = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", value)
- });
- res = std::nullopt;
- }
- }
-
- else if (hasPrefix(value, "flake:")) {
- experimentalFeatureSettings.require(Xp::Flakes);
- auto flakeRef = parseFlakeRef(value.substr(6), {}, true, false);
- debug("fetching flake search path element '%s''", value);
- auto storePath = flakeRef.resolve(store).fetchTree(store).first.storePath;
- res = { store->toRealPath(storePath) };
- }
-
- else {
- auto path = absPath(value);
- if (pathExists(path))
- res = { path };
- else {
- logWarning({
- .msg = hintfmt("Nix search path entry '%1%' does not exist, ignoring", value)
- });
- res = std::nullopt;
- }
- }
-
- if (res)
- debug("resolved search path element '%s' to '%s'", value, *res);
- else
- debug("failed to resolve search path element '%s'", value);
-
- searchPathResolved[value] = res;
- return res;
-}
-
-
}