diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 2c62f28d3..80f8986a8 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -451,6 +451,7 @@ EvalState::EvalState( , repair(NoRepair) , emptyBindings(0) , rootFS(makeFSInputAccessor("")) + , corepkgsFS(makeMemoryInputAccessor()) , store(store) , buildStore(buildStore ? buildStore : store) , regexCache(makeRegexCache()) @@ -500,6 +501,11 @@ EvalState::EvalState( } createBaseEnv(); + + corepkgsFS->addFile( + "/fetchurl.nix", + #include "fetchurl.nix.gen.hh" + ); } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 482223036..efc4dd8ec 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -98,6 +98,7 @@ public: Bindings emptyBindings; ref rootFS; + ref corepkgsFS; std::unordered_map> inputAccessors; @@ -514,8 +515,6 @@ struct EvalSettings : Config extern EvalSettings evalSettings; -static const std::string corepkgsPrefix{"/__corepkgs__/"}; - } #include "eval-inline.hh" diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 2d92455b2..bf3240dab 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -788,7 +788,7 @@ Path EvalState::findFile(SearchPath & searchPath, const std::string_view path, c } if (hasPrefix(path, "nix/")) - return concatStrings(corepkgsPrefix, path.substr(4)); + return packPath(SourcePath {corepkgsFS, (std::string) path.substr(3)}); throw ThrownError({ .msg = hintfmt(evalSettings.pureEval diff --git a/src/libexpr/paths.cc b/src/libexpr/paths.cc index 3b19066aa..baf5b24f4 100644 --- a/src/libexpr/paths.cc +++ b/src/libexpr/paths.cc @@ -7,6 +7,7 @@ static constexpr std::string_view marker = "/__virtual/"; Path EvalState::packPath(const SourcePath & path) { + // FIXME: canonPath(path) ? printError("PACK %s", path.path); assert(hasPrefix(path.path, "/")); inputAccessors.emplace(path.accessor->number, path.accessor); diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index d238adfdc..ec2060c9d 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -165,15 +165,6 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS { auto path = realisePath(state, pos, vPath); - #if 0 - // FIXME: use InputAccessor - if (path == corepkgsPrefix + "fetchurl.nix") { - state.eval(state.parseExprFromString( - #include "fetchurl.nix.gen.hh" - , "/"), v); - } - #endif - state.evalFile(path, v); #if 0 @@ -216,13 +207,6 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS state.forceAttrs(v, pos); } - // FIXME: use InputAccessor - else if (path == corepkgsPrefix + "fetchurl.nix") { - state.eval(state.parseExprFromString( - #include "fetchurl.nix.gen.hh" - , "/"), v); - } - else { if (!vScope) state.evalFile(path, v); @@ -1502,7 +1486,6 @@ static RegisterPrimOp primop_readFile({ which are desugared to 'findFile __nixPath "x"'. */ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Value & v) { - #if 0 state.forceList(*args[0], pos); SearchPath searchPath; @@ -1523,7 +1506,18 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va pos ); - auto path = realisePath(state, pos, *i->value, { .requireAbsolutePath = false }); + PathSet context; + auto path = state.coerceToString(pos, *i->value, context, false, false).toOwned(); + + try { + auto rewrites = state.realiseContext(context); + path = rewriteStrings(path, rewrites); + } catch (InvalidPathError & e) { + throw EvalError({ + .msg = hintfmt("cannot find '%1%', since path '%2%' is not valid", path, e.path), + .errPos = pos + }); + } searchPath.emplace_back(prefix, path); } @@ -1532,9 +1526,6 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va // FIXME: checkSourcePath? v.mkPath(state.findFile(searchPath, path, pos)); - #endif - - throw UnimplementedError("findFile"); } static RegisterPrimOp primop_findFile(RegisterPrimOp::Info { diff --git a/src/libfetchers/input-accessor.cc b/src/libfetchers/input-accessor.cc index b548f1baf..19c85bf8c 100644 --- a/src/libfetchers/input-accessor.cc +++ b/src/libfetchers/input-accessor.cc @@ -23,7 +23,7 @@ void InputAccessor::dumpPath( Sink & sink, PathFilter & filter) { - auto dumpContents = [&](std::string_view path) + auto dumpContents = [&](PathView path) { // FIXME: pipe auto s = readFile(path); @@ -97,7 +97,7 @@ struct FSInputAccessor : InputAccessor : root(root) { } - std::string readFile(std::string_view path) override + std::string readFile(PathView path) override { auto absPath = makeAbsPath(path); printError("READ %s", absPath); @@ -105,14 +105,14 @@ struct FSInputAccessor : InputAccessor return nix::readFile(absPath); } - bool pathExists(std::string_view path) override + bool pathExists(PathView path) override { auto absPath = makeAbsPath(path); printError("EXISTS %s", absPath); return isAllowed(absPath) && nix::pathExists(absPath); } - Stat lstat(std::string_view path) override + Stat lstat(PathView path) override { auto absPath = makeAbsPath(path); printError("LSTAT %s", absPath); @@ -128,7 +128,7 @@ struct FSInputAccessor : InputAccessor }; } - DirEntries readDirectory(std::string_view path) override + DirEntries readDirectory(PathView path) override { auto absPath = makeAbsPath(path); printError("READDIR %s", absPath); @@ -136,7 +136,7 @@ struct FSInputAccessor : InputAccessor abort(); } - std::string readLink(std::string_view path) override + std::string readLink(PathView path) override { auto absPath = makeAbsPath(path); printError("READLINK %s", absPath); @@ -144,19 +144,19 @@ struct FSInputAccessor : InputAccessor return nix::readLink(absPath); } - Path makeAbsPath(std::string_view path) + Path makeAbsPath(PathView path) { assert(hasPrefix(path, "/")); return canonPath(root + std::string(path)); } - void checkAllowed(std::string_view absPath) + void checkAllowed(PathView absPath) { if (!isAllowed(absPath)) throw Error("access to path '%s' is not allowed", absPath); } - bool isAllowed(std::string_view absPath) + bool isAllowed(PathView absPath) { if (!isDirOrInDir(absPath, root)) return false; @@ -175,4 +175,48 @@ std::ostream & operator << (std::ostream & str, const SourcePath & path) return str; } +struct MemoryInputAccessorImpl : MemoryInputAccessor +{ + std::map files; + + std::string readFile(PathView path) override + { + auto i = files.find((Path) path); + if (i == files.end()) + throw Error("file '%s' does not exist", path); + return i->second; + } + + bool pathExists(PathView path) override + { + auto i = files.find((Path) path); + return i != files.end(); + } + + Stat lstat(PathView path) override + { + throw UnimplementedError("MemoryInputAccessor::lstat"); + } + + DirEntries readDirectory(PathView path) override + { + return {}; + } + + std::string readLink(PathView path) override + { + throw UnimplementedError("MemoryInputAccessor::readLink"); + } + + void addFile(PathView path, std::string && contents) override + { + files.emplace(path, std::move(contents)); + } +}; + +ref makeMemoryInputAccessor() +{ + return make_ref(); +} + } diff --git a/src/libfetchers/input-accessor.hh b/src/libfetchers/input-accessor.hh index d2fe9c4ed..d4260518a 100644 --- a/src/libfetchers/input-accessor.hh +++ b/src/libfetchers/input-accessor.hh @@ -15,9 +15,9 @@ struct InputAccessor virtual ~InputAccessor() { } - virtual std::string readFile(std::string_view path) = 0; + virtual std::string readFile(PathView path) = 0; - virtual bool pathExists(std::string_view path) = 0; + virtual bool pathExists(PathView path) = 0; enum Type { tRegular, tSymlink, tDirectory, tMisc }; @@ -28,15 +28,15 @@ struct InputAccessor bool isExecutable = false; // regular files only }; - virtual Stat lstat(std::string_view path) = 0; + virtual Stat lstat(PathView path) = 0; typedef std::optional DirEntry; typedef std::map DirEntries; - virtual DirEntries readDirectory(std::string_view path) = 0; + virtual DirEntries readDirectory(PathView path) = 0; - virtual std::string readLink(std::string_view path) = 0; + virtual std::string readLink(PathView path) = 0; virtual void dumpPath( const Path & path, @@ -46,6 +46,13 @@ struct InputAccessor ref makeFSInputAccessor(const Path & root); +struct MemoryInputAccessor : InputAccessor +{ + virtual void addFile(PathView path, std::string && contents) = 0; +}; + +ref makeMemoryInputAccessor(); + struct SourcePath { ref accessor;