mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-27 08:16:14 +02:00
Checkpoint
This commit is contained in:
parent
2d572a250f
commit
c56e17b718
17 changed files with 428 additions and 79 deletions
|
@ -184,9 +184,11 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
|
||||||
if (file) {
|
if (file) {
|
||||||
evalSettings.pureEval = false;
|
evalSettings.pureEval = false;
|
||||||
auto state = getEvalState();
|
auto state = getEvalState();
|
||||||
Expr *e = state->parseExprFromFile(
|
Expr *e =
|
||||||
resolveExprPath(state->checkSourcePath(lookupFileArg(*state, *file)))
|
state->parseExprFromFile(
|
||||||
);
|
resolveExprPath(
|
||||||
|
state->rootPath(
|
||||||
|
lookupFileArg(*state, *file))));
|
||||||
|
|
||||||
Value root;
|
Value root;
|
||||||
state->eval(e, root);
|
state->eval(e, root);
|
||||||
|
@ -700,8 +702,9 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
||||||
if (file == "-") {
|
if (file == "-") {
|
||||||
auto e = state->parseStdin();
|
auto e = state->parseStdin();
|
||||||
state->eval(e, *vFile);
|
state->eval(e, *vFile);
|
||||||
} else if (file)
|
}
|
||||||
state->evalFile(lookupFileArg(*state, *file), *vFile);
|
else if (file)
|
||||||
|
state->evalFile(state->rootPath(lookupFileArg(*state, *file)), *vFile);
|
||||||
else {
|
else {
|
||||||
auto e = state->parseExprFromString(*expr, absPath("."));
|
auto e = state->parseExprFromString(*expr, absPath("."));
|
||||||
state->eval(e, *vFile);
|
state->eval(e, *vFile);
|
||||||
|
|
|
@ -450,6 +450,7 @@ EvalState::EvalState(
|
||||||
, sPrefix(symbols.create("prefix"))
|
, sPrefix(symbols.create("prefix"))
|
||||||
, repair(NoRepair)
|
, repair(NoRepair)
|
||||||
, emptyBindings(0)
|
, emptyBindings(0)
|
||||||
|
, rootFS(makeFSInputAccessor(""))
|
||||||
, store(store)
|
, store(store)
|
||||||
, buildStore(buildStore ? buildStore : store)
|
, buildStore(buildStore ? buildStore : store)
|
||||||
, regexCache(makeRegexCache())
|
, regexCache(makeRegexCache())
|
||||||
|
@ -527,6 +528,7 @@ void EvalState::allowAndSetStorePathString(const StorePath &storePath, Value & v
|
||||||
v.mkString(path, PathSet({path}));
|
v.mkString(path, PathSet({path}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
Path EvalState::checkSourcePath(const Path & path_)
|
Path EvalState::checkSourcePath(const Path & path_)
|
||||||
{
|
{
|
||||||
if (!allowedPaths) return path_;
|
if (!allowedPaths) return path_;
|
||||||
|
@ -572,6 +574,7 @@ Path EvalState::checkSourcePath(const Path & path_)
|
||||||
|
|
||||||
throw RestrictedPathError("access to canonical path '%1%' is forbidden in restricted mode", path);
|
throw RestrictedPathError("access to canonical path '%1%' is forbidden in restricted mode", path);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void EvalState::checkURI(const std::string & uri)
|
void EvalState::checkURI(const std::string & uri)
|
||||||
|
@ -593,12 +596,14 @@ void EvalState::checkURI(const std::string & uri)
|
||||||
/* If the URI is a path, then check it against allowedPaths as
|
/* If the URI is a path, then check it against allowedPaths as
|
||||||
well. */
|
well. */
|
||||||
if (hasPrefix(uri, "/")) {
|
if (hasPrefix(uri, "/")) {
|
||||||
checkSourcePath(uri);
|
// FIXME: use rootPath
|
||||||
|
//checkSourcePath(uri);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasPrefix(uri, "file://")) {
|
if (hasPrefix(uri, "file://")) {
|
||||||
checkSourcePath(std::string(uri, 7));
|
// FIXME: use rootPath
|
||||||
|
//checkSourcePath(std::string(uri, 7));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -970,17 +975,23 @@ Value * ExprPath::maybeThunk(EvalState & state, Env & env)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EvalState::evalFile(const Path & path_, Value & v, bool mustBeTrivial)
|
void EvalState::evalFile(const SourcePath & path_, Value & v, bool mustBeTrivial)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
auto path = checkSourcePath(path_);
|
auto path = checkSourcePath(path_);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto path = packPath(path_);
|
||||||
|
|
||||||
|
// FIXME: use SourcePath as cache key
|
||||||
FileEvalCache::iterator i;
|
FileEvalCache::iterator i;
|
||||||
if ((i = fileEvalCache.find(path)) != fileEvalCache.end()) {
|
if ((i = fileEvalCache.find(path)) != fileEvalCache.end()) {
|
||||||
v = i->second;
|
v = i->second;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path resolvedPath = resolveExprPath(path);
|
auto resolvedPath_ = resolveExprPath(path_);
|
||||||
|
auto resolvedPath = packPath(resolvedPath_);
|
||||||
if ((i = fileEvalCache.find(resolvedPath)) != fileEvalCache.end()) {
|
if ((i = fileEvalCache.find(resolvedPath)) != fileEvalCache.end()) {
|
||||||
v = i->second;
|
v = i->second;
|
||||||
return;
|
return;
|
||||||
|
@ -994,7 +1005,10 @@ void EvalState::evalFile(const Path & path_, Value & v, bool mustBeTrivial)
|
||||||
e = j->second;
|
e = j->second;
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
|
e = parseExprFromFile(resolvedPath_);
|
||||||
|
#if 0
|
||||||
e = parseExprFromFile(checkSourcePath(resolvedPath));
|
e = parseExprFromFile(checkSourcePath(resolvedPath));
|
||||||
|
#endif
|
||||||
|
|
||||||
cacheFile(path, resolvedPath, e, v, mustBeTrivial);
|
cacheFile(path, resolvedPath, e, v, mustBeTrivial);
|
||||||
}
|
}
|
||||||
|
@ -2045,9 +2059,19 @@ std::string EvalState::copyPathToStore(PathSet & context, const Path & path)
|
||||||
if (i != srcToStore.end())
|
if (i != srcToStore.end())
|
||||||
dstPath = store->printStorePath(i->second);
|
dstPath = store->printStorePath(i->second);
|
||||||
else {
|
else {
|
||||||
|
// FIXME: use SourcePath
|
||||||
|
printError("COPY %s", path);
|
||||||
|
auto path2 = unpackPath(path);
|
||||||
|
#if 0
|
||||||
auto p = settings.readOnlyMode
|
auto p = settings.readOnlyMode
|
||||||
? store->computeStorePathForPath(std::string(baseNameOf(path)), checkSourcePath(path)).first
|
? store->computeStorePathForPath(std::string(baseNameOf(path)), canonPath(path)).first
|
||||||
: store->addToStore(std::string(baseNameOf(path)), checkSourcePath(path), FileIngestionMethod::Recursive, htSHA256, defaultPathFilter, repair);
|
: store->addToStore(std::string(baseNameOf(path)), canonPath(path), FileIngestionMethod::Recursive, htSHA256, defaultPathFilter, repair);
|
||||||
|
#endif
|
||||||
|
auto source = sinkToSource([&](Sink & sink) {
|
||||||
|
path2.accessor->dumpPath(path2.path, sink);
|
||||||
|
});
|
||||||
|
// FIXME: readOnlyMode
|
||||||
|
auto p = store->addToStoreFromDump(*source, std::string(baseNameOf(path)), FileIngestionMethod::Recursive, htSHA256, repair);
|
||||||
dstPath = store->printStorePath(p);
|
dstPath = store->printStorePath(p);
|
||||||
allowPath(p);
|
allowPath(p);
|
||||||
srcToStore.insert_or_assign(path, std::move(p));
|
srcToStore.insert_or_assign(path, std::move(p));
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "symbol-table.hh"
|
#include "symbol-table.hh"
|
||||||
#include "config.hh"
|
#include "config.hh"
|
||||||
#include "experimental-features.hh"
|
#include "experimental-features.hh"
|
||||||
|
#include "input-accessor.hh"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -20,6 +21,7 @@ namespace nix {
|
||||||
class Store;
|
class Store;
|
||||||
class EvalState;
|
class EvalState;
|
||||||
class StorePath;
|
class StorePath;
|
||||||
|
struct SourcePath;
|
||||||
enum RepairFlag : bool;
|
enum RepairFlag : bool;
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,6 +97,10 @@ public:
|
||||||
|
|
||||||
Bindings emptyBindings;
|
Bindings emptyBindings;
|
||||||
|
|
||||||
|
ref<InputAccessor> rootFS;
|
||||||
|
|
||||||
|
std::unordered_map<size_t, ref<InputAccessor>> inputAccessors;
|
||||||
|
|
||||||
/* Store used to materialise .drv files. */
|
/* Store used to materialise .drv files. */
|
||||||
const ref<Store> store;
|
const ref<Store> store;
|
||||||
|
|
||||||
|
@ -153,6 +159,12 @@ public:
|
||||||
|
|
||||||
SearchPath getSearchPath() { return searchPath; }
|
SearchPath getSearchPath() { return searchPath; }
|
||||||
|
|
||||||
|
Path packPath(const SourcePath & path);
|
||||||
|
|
||||||
|
SourcePath unpackPath(const Path & path);
|
||||||
|
|
||||||
|
SourcePath rootPath(const Path & path);
|
||||||
|
|
||||||
/* Allow access to a path. */
|
/* Allow access to a path. */
|
||||||
void allowPath(const Path & path);
|
void allowPath(const Path & path);
|
||||||
|
|
||||||
|
@ -163,10 +175,6 @@ public:
|
||||||
/* Allow access to a store path and return it as a string. */
|
/* Allow access to a store path and return it as a string. */
|
||||||
void allowAndSetStorePathString(const StorePath & storePath, Value & v);
|
void allowAndSetStorePathString(const StorePath & storePath, Value & v);
|
||||||
|
|
||||||
/* Check whether access to a path is allowed and throw an error if
|
|
||||||
not. Otherwise return the canonicalised path. */
|
|
||||||
Path checkSourcePath(const Path & path);
|
|
||||||
|
|
||||||
void checkURI(const std::string & uri);
|
void checkURI(const std::string & uri);
|
||||||
|
|
||||||
/* When using a diverted store and 'path' is in the Nix store, map
|
/* When using a diverted store and 'path' is in the Nix store, map
|
||||||
|
@ -179,8 +187,8 @@ public:
|
||||||
Path toRealPath(const Path & path, const PathSet & context);
|
Path toRealPath(const Path & path, const PathSet & context);
|
||||||
|
|
||||||
/* Parse a Nix expression from the specified file. */
|
/* Parse a Nix expression from the specified file. */
|
||||||
Expr * parseExprFromFile(const Path & path);
|
Expr * parseExprFromFile(const SourcePath & path);
|
||||||
Expr * parseExprFromFile(const Path & path, StaticEnv & staticEnv);
|
Expr * parseExprFromFile(const SourcePath & path, StaticEnv & staticEnv);
|
||||||
|
|
||||||
/* Parse a Nix expression from the specified string. */
|
/* Parse a Nix expression from the specified string. */
|
||||||
Expr * parseExprFromString(std::string s, const Path & basePath, StaticEnv & staticEnv);
|
Expr * parseExprFromString(std::string s, const Path & basePath, StaticEnv & staticEnv);
|
||||||
|
@ -191,7 +199,7 @@ public:
|
||||||
/* Evaluate an expression read from the given file to normal
|
/* Evaluate an expression read from the given file to normal
|
||||||
form. Optionally enforce that the top-level expression is
|
form. Optionally enforce that the top-level expression is
|
||||||
trivial (i.e. doesn't require arbitrary computation). */
|
trivial (i.e. doesn't require arbitrary computation). */
|
||||||
void evalFile(const Path & path, Value & v, bool mustBeTrivial = false);
|
void evalFile(const SourcePath & path, Value & v, bool mustBeTrivial = false);
|
||||||
|
|
||||||
/* Like `cacheFile`, but with an already parsed expression. */
|
/* Like `cacheFile`, but with an already parsed expression. */
|
||||||
void cacheFile(
|
void cacheFile(
|
||||||
|
@ -269,6 +277,7 @@ public:
|
||||||
/* Path coercion. Converts strings, paths and derivations to a
|
/* Path coercion. Converts strings, paths and derivations to a
|
||||||
path. The result is guaranteed to be a canonicalised, absolute
|
path. The result is guaranteed to be a canonicalised, absolute
|
||||||
path. Nothing is copied to the store. */
|
path. Nothing is copied to the store. */
|
||||||
|
// FIXME: return SourcePath
|
||||||
Path coerceToPath(const Pos & pos, Value & v, PathSet & context);
|
Path coerceToPath(const Pos & pos, Value & v, PathSet & context);
|
||||||
|
|
||||||
/* Like coerceToPath, but the result must be a store path. */
|
/* Like coerceToPath, but the result must be a store path. */
|
||||||
|
@ -427,7 +436,7 @@ std::string showType(const Value & v);
|
||||||
NixStringContextElem decodeContext(const Store & store, std::string_view s);
|
NixStringContextElem decodeContext(const Store & store, std::string_view s);
|
||||||
|
|
||||||
/* If `path' refers to a directory, then append "/default.nix". */
|
/* If `path' refers to a directory, then append "/default.nix". */
|
||||||
Path resolveExprPath(Path path);
|
SourcePath resolveExprPath(const SourcePath & path);
|
||||||
|
|
||||||
struct InvalidPathError : EvalError
|
struct InvalidPathError : EvalError
|
||||||
{
|
{
|
||||||
|
|
|
@ -216,7 +216,8 @@ static Flake getFlake(
|
||||||
throw Error("source tree referenced by '%s' does not contain a '%s/flake.nix' file", lockedRef, lockedRef.subdir);
|
throw Error("source tree referenced by '%s' does not contain a '%s/flake.nix' file", lockedRef, lockedRef.subdir);
|
||||||
|
|
||||||
Value vInfo;
|
Value vInfo;
|
||||||
state.evalFile(flakeFile, vInfo, true); // FIXME: symlink attack
|
// FIXME: use accessor
|
||||||
|
state.evalFile(state.rootPath(flakeFile), vInfo, true); // FIXME: symlink attack
|
||||||
|
|
||||||
expectType(state, nAttrs, vInfo, Pos(foFile, state.symbols.create(flakeFile), 0, 0));
|
expectType(state, nAttrs, vInfo, Pos(foFile, state.symbols.create(flakeFile), 0, 0));
|
||||||
|
|
||||||
|
|
|
@ -674,10 +674,9 @@ Expr * EvalState::parse(char * text, size_t length, FileOrigin origin,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path resolveExprPath(Path path)
|
SourcePath resolveExprPath(const SourcePath & path)
|
||||||
{
|
{
|
||||||
assert(path[0] == '/');
|
#if 0
|
||||||
|
|
||||||
unsigned int followCount = 0, maxFollow = 1024;
|
unsigned int followCount = 0, maxFollow = 1024;
|
||||||
|
|
||||||
/* If `path' is a symlink, follow it. This is so that relative
|
/* If `path' is a symlink, follow it. This is so that relative
|
||||||
|
@ -697,21 +696,30 @@ Path resolveExprPath(Path path)
|
||||||
path = canonPath(path + "/default.nix");
|
path = canonPath(path + "/default.nix");
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
auto path2 = path.path + "/default.nix";
|
||||||
|
if (path.accessor->pathExists(path2))
|
||||||
|
return {path.accessor, path2};
|
||||||
|
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Expr * EvalState::parseExprFromFile(const Path & path)
|
Expr * EvalState::parseExprFromFile(const SourcePath & path)
|
||||||
{
|
{
|
||||||
return parseExprFromFile(path, staticBaseEnv);
|
return parseExprFromFile(path, staticBaseEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Expr * EvalState::parseExprFromFile(const Path & path, StaticEnv & staticEnv)
|
Expr * EvalState::parseExprFromFile(const SourcePath & path, StaticEnv & staticEnv)
|
||||||
{
|
{
|
||||||
auto buffer = readFile(path);
|
auto packed = packPath(path);
|
||||||
// readFile should have left some extra space for terminators
|
auto buffer = path.accessor->readFile(path.path);
|
||||||
|
// readFile hopefully have left some extra space for terminators
|
||||||
buffer.append("\0\0", 2);
|
buffer.append("\0\0", 2);
|
||||||
return parse(buffer.data(), buffer.size(), foFile, path, dirOf(path), staticEnv);
|
return parse(buffer.data(), buffer.size(), foFile, packed, dirOf(packed), staticEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
39
src/libexpr/paths.cc
Normal file
39
src/libexpr/paths.cc
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include "eval.hh"
|
||||||
|
#include "util.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
static constexpr std::string_view marker = "/__virtual/";
|
||||||
|
|
||||||
|
Path EvalState::packPath(const SourcePath & path)
|
||||||
|
{
|
||||||
|
printError("PACK %s", path.path);
|
||||||
|
assert(hasPrefix(path.path, "/"));
|
||||||
|
inputAccessors.emplace(path.accessor->number, path.accessor);
|
||||||
|
return std::string(marker) + std::to_string(path.accessor->number) + path.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
SourcePath EvalState::unpackPath(const Path & path)
|
||||||
|
{
|
||||||
|
if (hasPrefix(path, marker)) {
|
||||||
|
auto s = path.substr(marker.size());
|
||||||
|
auto slash = s.find('/');
|
||||||
|
assert(slash != s.npos);
|
||||||
|
auto n = std::stoi(s.substr(0, slash));
|
||||||
|
printError("GOT %d", n);
|
||||||
|
auto i = inputAccessors.find(n);
|
||||||
|
assert(i != inputAccessors.end());
|
||||||
|
return {i->second, s.substr(slash)};
|
||||||
|
} else {
|
||||||
|
printError("FIXME: %s", path);
|
||||||
|
return rootPath(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SourcePath EvalState::rootPath(const Path & path)
|
||||||
|
{
|
||||||
|
printError("ROOT %s", path);
|
||||||
|
return {rootFS, path};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -96,20 +96,23 @@ struct RealisePathFlags {
|
||||||
bool checkForPureEval = true;
|
bool checkForPureEval = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Path realisePath(EvalState & state, const Pos & pos, Value & v, const RealisePathFlags flags = {})
|
static SourcePath realisePath(EvalState & state, const Pos & pos, Value & v, const RealisePathFlags flags = {})
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
|
|
||||||
auto path = [&]()
|
auto path = [&]()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return state.coerceToPath(pos, v, context);
|
return state.unpackPath(state.coerceToPath(pos, v, context));
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(pos, "while realising the context of a path");
|
e.addTrace(pos, "while realising the context of a path");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
return path;
|
||||||
|
|
||||||
|
#if 0
|
||||||
try {
|
try {
|
||||||
StringMap rewrites = state.realiseContext(context);
|
StringMap rewrites = state.realiseContext(context);
|
||||||
|
|
||||||
|
@ -122,6 +125,7 @@ static Path realisePath(EvalState & state, const Pos & pos, Value & v, const Rea
|
||||||
e.addTrace(pos, "while realising the context of path '%s'", path);
|
e.addTrace(pos, "while realising the context of path '%s'", path);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add and attribute to the given attribute map from the output name to
|
/* Add and attribute to the given attribute map from the output name to
|
||||||
|
@ -161,6 +165,18 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS
|
||||||
{
|
{
|
||||||
auto path = realisePath(state, pos, vPath);
|
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
|
||||||
// FIXME
|
// FIXME
|
||||||
auto isValidDerivationInStore = [&]() -> std::optional<StorePath> {
|
auto isValidDerivationInStore = [&]() -> std::optional<StorePath> {
|
||||||
if (!state.store->isStorePath(path))
|
if (!state.store->isStorePath(path))
|
||||||
|
@ -200,6 +216,7 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS
|
||||||
state.forceAttrs(v, pos);
|
state.forceAttrs(v, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: use InputAccessor
|
||||||
else if (path == corepkgsPrefix + "fetchurl.nix") {
|
else if (path == corepkgsPrefix + "fetchurl.nix") {
|
||||||
state.eval(state.parseExprFromString(
|
state.eval(state.parseExprFromString(
|
||||||
#include "fetchurl.nix.gen.hh"
|
#include "fetchurl.nix.gen.hh"
|
||||||
|
@ -232,6 +249,7 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS
|
||||||
e->eval(state, *env, v);
|
e->eval(state, *env, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_scopedImport(RegisterPrimOp::Info {
|
static RegisterPrimOp primop_scopedImport(RegisterPrimOp::Info {
|
||||||
|
@ -312,6 +330,9 @@ extern "C" typedef void (*ValueInitializer)(EvalState & state, Value & v);
|
||||||
/* Load a ValueInitializer from a DSO and return whatever it initializes */
|
/* Load a ValueInitializer from a DSO and return whatever it initializes */
|
||||||
void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
|
throw UnimplementedError("importNative");
|
||||||
|
|
||||||
|
#if 0
|
||||||
auto path = realisePath(state, pos, *args[0]);
|
auto path = realisePath(state, pos, *args[0]);
|
||||||
|
|
||||||
std::string sym(state.forceStringNoCtx(*args[1], pos));
|
std::string sym(state.forceStringNoCtx(*args[1], pos));
|
||||||
|
@ -334,6 +355,7 @@ void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
(func)(state, v);
|
(func)(state, v);
|
||||||
|
|
||||||
/* We don't dlclose because v may be a primop referencing a function in the shared object file */
|
/* We don't dlclose because v may be a primop referencing a function in the shared object file */
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1343,7 +1365,8 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V
|
||||||
});
|
});
|
||||||
|
|
||||||
PathSet context;
|
PathSet context;
|
||||||
Path path = state.checkSourcePath(state.coerceToPath(pos, *args[0], context));
|
// FIXME: check rootPath
|
||||||
|
Path path = state.coerceToPath(pos, *args[0], context);
|
||||||
/* Resolve symlinks in ‘path’, unless ‘path’ itself is a symlink
|
/* Resolve symlinks in ‘path’, unless ‘path’ itself is a symlink
|
||||||
directly in the store. The latter condition is necessary so
|
directly in the store. The latter condition is necessary so
|
||||||
e.g. nix-push does the right thing. */
|
e.g. nix-push does the right thing. */
|
||||||
|
@ -1388,7 +1411,7 @@ static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args,
|
||||||
auto path = realisePath(state, pos, *args[0], { .checkForPureEval = false });
|
auto path = realisePath(state, pos, *args[0], { .checkForPureEval = false });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
v.mkBool(pathExists(state.checkSourcePath(path)));
|
v.mkBool(path.accessor->pathExists(path.path));
|
||||||
} catch (SysError & e) {
|
} catch (SysError & e) {
|
||||||
/* Don't give away info from errors while canonicalising
|
/* Don't give away info from errors while canonicalising
|
||||||
‘path’ in restricted mode. */
|
‘path’ in restricted mode. */
|
||||||
|
@ -1453,16 +1476,15 @@ static RegisterPrimOp primop_dirOf({
|
||||||
static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
auto path = realisePath(state, pos, *args[0]);
|
auto path = realisePath(state, pos, *args[0]);
|
||||||
auto s = readFile(path);
|
auto s = path.accessor->readFile(path.path);
|
||||||
if (s.find((char) 0) != std::string::npos)
|
if (s.find((char) 0) != std::string::npos)
|
||||||
throw Error("the contents of the file '%1%' cannot be represented as a Nix string", path);
|
throw Error("the contents of the file '%1%' cannot be represented as a Nix string", path);
|
||||||
StorePathSet refs;
|
auto refs =
|
||||||
if (state.store->isInStore(path)) {
|
#if 0
|
||||||
try {
|
state.store->isInStore(path) ?
|
||||||
refs = state.store->queryPathInfo(state.store->toStorePath(path).first)->references;
|
state.store->queryPathInfo(state.store->toStorePath(path).first)->references :
|
||||||
} catch (Error &) { // FIXME: should be InvalidPathError
|
#endif
|
||||||
}
|
StorePathSet{};
|
||||||
}
|
|
||||||
auto context = state.store->printStorePathSet(refs);
|
auto context = state.store->printStorePathSet(refs);
|
||||||
v.mkString(s, context);
|
v.mkString(s, context);
|
||||||
}
|
}
|
||||||
|
@ -1480,6 +1502,7 @@ static RegisterPrimOp primop_readFile({
|
||||||
which are desugared to 'findFile __nixPath "x"'. */
|
which are desugared to 'findFile __nixPath "x"'. */
|
||||||
static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
state.forceList(*args[0], pos);
|
state.forceList(*args[0], pos);
|
||||||
|
|
||||||
SearchPath searchPath;
|
SearchPath searchPath;
|
||||||
|
@ -1500,26 +1523,18 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
pos
|
pos
|
||||||
);
|
);
|
||||||
|
|
||||||
PathSet context;
|
auto path = realisePath(state, pos, *i->value, { .requireAbsolutePath = false });
|
||||||
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);
|
searchPath.emplace_back(prefix, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto path = state.forceStringNoCtx(*args[1], pos);
|
auto path = state.forceStringNoCtx(*args[1], pos);
|
||||||
|
|
||||||
v.mkPath(state.checkSourcePath(state.findFile(searchPath, path, pos)));
|
// FIXME: checkSourcePath?
|
||||||
|
v.mkPath(state.findFile(searchPath, path, pos));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
throw UnimplementedError("findFile");
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_findFile(RegisterPrimOp::Info {
|
static RegisterPrimOp primop_findFile(RegisterPrimOp::Info {
|
||||||
|
@ -1541,7 +1556,8 @@ static void prim_hashFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
|
|
||||||
auto path = realisePath(state, pos, *args[1]);
|
auto path = realisePath(state, pos, *args[1]);
|
||||||
|
|
||||||
v.mkString(hashFile(*ht, path).to_string(Base16, false));
|
// FIXME: state.toRealPath(path, context)
|
||||||
|
v.mkString(hashString(*ht, path.accessor->readFile(path.path)).to_string(Base16, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_hashFile({
|
static RegisterPrimOp primop_hashFile({
|
||||||
|
@ -1560,17 +1576,19 @@ static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Val
|
||||||
{
|
{
|
||||||
auto path = realisePath(state, pos, *args[0]);
|
auto path = realisePath(state, pos, *args[0]);
|
||||||
|
|
||||||
DirEntries entries = readDirectory(path);
|
auto entries = path.accessor->readDirectory(path.path);
|
||||||
|
|
||||||
auto attrs = state.buildBindings(entries.size());
|
auto attrs = state.buildBindings(entries.size());
|
||||||
|
|
||||||
for (auto & ent : entries) {
|
for (auto & [name, type] : entries) {
|
||||||
if (ent.type == DT_UNKNOWN)
|
#if 0
|
||||||
ent.type = getFileType(path + "/" + ent.name);
|
// FIXME?
|
||||||
attrs.alloc(ent.name).mkString(
|
if (type == InputAccessor::Type::Misc)
|
||||||
ent.type == DT_REG ? "regular" :
|
ent.type = getFileType(path + "/" + name);
|
||||||
ent.type == DT_DIR ? "directory" :
|
#endif
|
||||||
ent.type == DT_LNK ? "symlink" :
|
attrs.alloc(name).mkString(
|
||||||
|
type == InputAccessor::Type::tRegular ? "regular" :
|
||||||
|
type == InputAccessor::Type::tDirectory ? "directory" :
|
||||||
|
type == InputAccessor::Type::tSymlink ? "symlink" :
|
||||||
"unknown");
|
"unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1902,9 +1920,12 @@ static void addPath(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
#if 0
|
||||||
path = evalSettings.pureEval && expectedHash
|
path = evalSettings.pureEval && expectedHash
|
||||||
? path
|
? path
|
||||||
: state.checkSourcePath(path);
|
: state.checkSourcePath(path);
|
||||||
|
#endif
|
||||||
|
|
||||||
PathFilter filter = filterFun ? ([&](const Path & path) {
|
PathFilter filter = filterFun ? ([&](const Path & path) {
|
||||||
auto st = lstat(path);
|
auto st = lstat(path);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "path.hh"
|
#include "path.hh"
|
||||||
#include "attrs.hh"
|
#include "attrs.hh"
|
||||||
#include "url.hh"
|
#include "url.hh"
|
||||||
|
#include "input-accessor.hh"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
@ -27,7 +28,6 @@ struct InputScheme;
|
||||||
* "fromURL()" or "fromAttrs()" static functions which are provided
|
* "fromURL()" or "fromAttrs()" static functions which are provided
|
||||||
* the url or attrset specified in the flake file.
|
* the url or attrset specified in the flake file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct Input
|
struct Input
|
||||||
{
|
{
|
||||||
friend struct InputScheme;
|
friend struct InputScheme;
|
||||||
|
@ -98,7 +98,6 @@ public:
|
||||||
std::optional<time_t> getLastModified() const;
|
std::optional<time_t> getLastModified() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The InputScheme represents a type of fetcher. Each fetcher
|
/* The InputScheme represents a type of fetcher. Each fetcher
|
||||||
* registers with nix at startup time. When processing an input for a
|
* registers with nix at startup time. When processing an input for a
|
||||||
* flake, each scheme is given an opportunity to "recognize" that
|
* flake, each scheme is given an opportunity to "recognize" that
|
||||||
|
@ -107,7 +106,6 @@ public:
|
||||||
* recognized. The Input object contains the information the fetcher
|
* recognized. The Input object contains the information the fetcher
|
||||||
* needs to actually perform the "fetch()" when called.
|
* needs to actually perform the "fetch()" when called.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct InputScheme
|
struct InputScheme
|
||||||
{
|
{
|
||||||
virtual ~InputScheme()
|
virtual ~InputScheme()
|
||||||
|
@ -133,6 +131,11 @@ struct InputScheme
|
||||||
virtual void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg);
|
virtual void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg);
|
||||||
|
|
||||||
virtual std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) = 0;
|
virtual std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) = 0;
|
||||||
|
|
||||||
|
virtual ref<InputAccessor> getAccessor()
|
||||||
|
{
|
||||||
|
throw UnimplementedError("getAccessor");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);
|
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);
|
||||||
|
|
178
src/libfetchers/input-accessor.cc
Normal file
178
src/libfetchers/input-accessor.cc
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
#include "input-accessor.hh"
|
||||||
|
#include "util.hh"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
static std::atomic<size_t> nextNumber{0};
|
||||||
|
|
||||||
|
InputAccessor::InputAccessor()
|
||||||
|
: number(++nextNumber)
|
||||||
|
{
|
||||||
|
printError("CREATE %d", number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: merge with archive.cc.
|
||||||
|
const std::string narVersionMagic1 = "nix-archive-1";
|
||||||
|
|
||||||
|
static string caseHackSuffix = "~nix~case~hack~";
|
||||||
|
|
||||||
|
void InputAccessor::dumpPath(
|
||||||
|
const Path & path,
|
||||||
|
Sink & sink,
|
||||||
|
PathFilter & filter)
|
||||||
|
{
|
||||||
|
auto dumpContents = [&](std::string_view path)
|
||||||
|
{
|
||||||
|
// FIXME: pipe
|
||||||
|
auto s = readFile(path);
|
||||||
|
sink << "contents" << s.size();
|
||||||
|
sink(s);
|
||||||
|
writePadding(s.size(), sink);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::function<void(const std::string & path)> dump;
|
||||||
|
|
||||||
|
dump = [&](const std::string & path) {
|
||||||
|
checkInterrupt();
|
||||||
|
|
||||||
|
auto st = lstat(path);
|
||||||
|
|
||||||
|
sink << "(";
|
||||||
|
|
||||||
|
if (st.type == tRegular) {
|
||||||
|
sink << "type" << "regular";
|
||||||
|
if (st.isExecutable)
|
||||||
|
sink << "executable" << "";
|
||||||
|
dumpContents(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (st.type == tDirectory) {
|
||||||
|
sink << "type" << "directory";
|
||||||
|
|
||||||
|
/* If we're on a case-insensitive system like macOS, undo
|
||||||
|
the case hack applied by restorePath(). */
|
||||||
|
std::map<string, string> unhacked;
|
||||||
|
for (auto & i : readDirectory(path))
|
||||||
|
if (/* archiveSettings.useCaseHack */ false) { // FIXME
|
||||||
|
string name(i.first);
|
||||||
|
size_t pos = i.first.find(caseHackSuffix);
|
||||||
|
if (pos != string::npos) {
|
||||||
|
debug(format("removing case hack suffix from '%s'") % (path + "/" + i.first));
|
||||||
|
name.erase(pos);
|
||||||
|
}
|
||||||
|
if (!unhacked.emplace(name, i.first).second)
|
||||||
|
throw Error("file name collision in between '%s' and '%s'",
|
||||||
|
(path + "/" + unhacked[name]),
|
||||||
|
(path + "/" + i.first));
|
||||||
|
} else
|
||||||
|
unhacked.emplace(i.first, i.first);
|
||||||
|
|
||||||
|
for (auto & i : unhacked)
|
||||||
|
if (filter(path + "/" + i.first)) {
|
||||||
|
sink << "entry" << "(" << "name" << i.first << "node";
|
||||||
|
dump(path + "/" + i.second);
|
||||||
|
sink << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (st.type == tSymlink)
|
||||||
|
sink << "type" << "symlink" << "target" << readLink(path);
|
||||||
|
|
||||||
|
else throw Error("file '%s' has an unsupported type", path);
|
||||||
|
|
||||||
|
sink << ")";
|
||||||
|
};
|
||||||
|
|
||||||
|
sink << narVersionMagic1;
|
||||||
|
dump(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FSInputAccessor : InputAccessor
|
||||||
|
{
|
||||||
|
Path root;
|
||||||
|
|
||||||
|
FSInputAccessor(const Path & root)
|
||||||
|
: root(root)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
std::string readFile(std::string_view path) override
|
||||||
|
{
|
||||||
|
auto absPath = makeAbsPath(path);
|
||||||
|
printError("READ %s", absPath);
|
||||||
|
checkAllowed(absPath);
|
||||||
|
return nix::readFile(absPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pathExists(std::string_view path) override
|
||||||
|
{
|
||||||
|
auto absPath = makeAbsPath(path);
|
||||||
|
printError("EXISTS %s", absPath);
|
||||||
|
return isAllowed(absPath) && nix::pathExists(absPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stat lstat(std::string_view path) override
|
||||||
|
{
|
||||||
|
auto absPath = makeAbsPath(path);
|
||||||
|
printError("LSTAT %s", absPath);
|
||||||
|
checkAllowed(absPath);
|
||||||
|
auto st = nix::lstat(absPath);
|
||||||
|
return Stat {
|
||||||
|
.type =
|
||||||
|
S_ISREG(st.st_mode) ? tRegular :
|
||||||
|
S_ISDIR(st.st_mode) ? tDirectory :
|
||||||
|
S_ISLNK(st.st_mode) ? tSymlink :
|
||||||
|
tMisc,
|
||||||
|
.isExecutable = S_ISREG(st.st_mode) && st.st_mode & S_IXUSR
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
DirEntries readDirectory(std::string_view path) override
|
||||||
|
{
|
||||||
|
auto absPath = makeAbsPath(path);
|
||||||
|
printError("READDIR %s", absPath);
|
||||||
|
checkAllowed(absPath);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string readLink(std::string_view path) override
|
||||||
|
{
|
||||||
|
auto absPath = makeAbsPath(path);
|
||||||
|
printError("READLINK %s", absPath);
|
||||||
|
checkAllowed(absPath);
|
||||||
|
return nix::readLink(absPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Path makeAbsPath(std::string_view path)
|
||||||
|
{
|
||||||
|
assert(hasPrefix(path, "/"));
|
||||||
|
return canonPath(root + std::string(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkAllowed(std::string_view absPath)
|
||||||
|
{
|
||||||
|
if (!isAllowed(absPath))
|
||||||
|
throw Error("access to path '%s' is not allowed", absPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isAllowed(std::string_view absPath)
|
||||||
|
{
|
||||||
|
if (!isDirOrInDir(absPath, root))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ref<InputAccessor> makeFSInputAccessor(const Path & root)
|
||||||
|
{
|
||||||
|
return make_ref<FSInputAccessor>(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream & operator << (std::ostream & str, const SourcePath & path)
|
||||||
|
{
|
||||||
|
str << path.path; // FIXME
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
57
src/libfetchers/input-accessor.hh
Normal file
57
src/libfetchers/input-accessor.hh
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ref.hh"
|
||||||
|
#include "types.hh"
|
||||||
|
#include "archive.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
struct InputAccessor
|
||||||
|
{
|
||||||
|
const size_t number;
|
||||||
|
|
||||||
|
InputAccessor();
|
||||||
|
|
||||||
|
virtual ~InputAccessor()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual std::string readFile(std::string_view path) = 0;
|
||||||
|
|
||||||
|
virtual bool pathExists(std::string_view path) = 0;
|
||||||
|
|
||||||
|
enum Type { tRegular, tSymlink, tDirectory, tMisc };
|
||||||
|
|
||||||
|
struct Stat
|
||||||
|
{
|
||||||
|
Type type = tMisc;
|
||||||
|
//uint64_t fileSize = 0; // regular files only
|
||||||
|
bool isExecutable = false; // regular files only
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual Stat lstat(std::string_view path) = 0;
|
||||||
|
|
||||||
|
typedef std::optional<Type> DirEntry;
|
||||||
|
|
||||||
|
typedef std::map<std::string, DirEntry> DirEntries;
|
||||||
|
|
||||||
|
virtual DirEntries readDirectory(std::string_view path) = 0;
|
||||||
|
|
||||||
|
virtual std::string readLink(std::string_view path) = 0;
|
||||||
|
|
||||||
|
virtual void dumpPath(
|
||||||
|
const Path & path,
|
||||||
|
Sink & sink,
|
||||||
|
PathFilter & filter = defaultPathFilter);
|
||||||
|
};
|
||||||
|
|
||||||
|
ref<InputAccessor> makeFSInputAccessor(const Path & root);
|
||||||
|
|
||||||
|
struct SourcePath
|
||||||
|
{
|
||||||
|
ref<InputAccessor> accessor;
|
||||||
|
Path path;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream & operator << (std::ostream & str, const SourcePath & path);
|
||||||
|
|
||||||
|
}
|
|
@ -304,7 +304,11 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
else
|
else
|
||||||
/* If we're in a #! script, interpret filenames
|
/* If we're in a #! script, interpret filenames
|
||||||
relative to the script. */
|
relative to the script. */
|
||||||
exprs.push_back(state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state,
|
exprs.push_back(
|
||||||
|
state->parseExprFromFile(
|
||||||
|
resolveExprPath(
|
||||||
|
state->rootPath(
|
||||||
|
lookupFileArg(*state,
|
||||||
inShebang && !packages ? absPath(i, absPath(dirOf(script))) : i)))));
|
inShebang && !packages ? absPath(i, absPath(dirOf(script))) : i)))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,7 @@ static void loadSourceExpr(EvalState & state, const Path & path, Value & v)
|
||||||
throw SysError("getting information about '%1%'", path);
|
throw SysError("getting information about '%1%'", path);
|
||||||
|
|
||||||
if (isNixExpr(path, st))
|
if (isNixExpr(path, st))
|
||||||
state.evalFile(path, v);
|
state.evalFile(state.rootPath(path), v);
|
||||||
|
|
||||||
/* The path is a directory. Put the Nix expressions in the
|
/* The path is a directory. Put the Nix expressions in the
|
||||||
directory in a set, with the file name of each expression as
|
directory in a set, with the file name of each expression as
|
||||||
|
|
|
@ -22,7 +22,7 @@ DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
|
||||||
Path manifestFile = userEnv + "/manifest.nix";
|
Path manifestFile = userEnv + "/manifest.nix";
|
||||||
if (pathExists(manifestFile)) {
|
if (pathExists(manifestFile)) {
|
||||||
Value v;
|
Value v;
|
||||||
state.evalFile(manifestFile, v);
|
state.evalFile(state.rootPath(manifestFile), v);
|
||||||
Bindings & bindings(*state.allocBindings(0));
|
Bindings & bindings(*state.allocBindings(0));
|
||||||
getDerivations(state, v, "", bindings, elems, false);
|
getDerivations(state, v, "", bindings, elems, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,7 +182,7 @@ static int main_nix_instantiate(int argc, char * * argv)
|
||||||
for (auto & i : files) {
|
for (auto & i : files) {
|
||||||
Expr * e = fromArgs
|
Expr * e = fromArgs
|
||||||
? state->parseExprFromString(i, absPath("."))
|
? state->parseExprFromString(i, absPath("."))
|
||||||
: state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state, i))));
|
: state->parseExprFromFile(resolveExprPath(state->rootPath(lookupFileArg(*state, i))));
|
||||||
processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
|
processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
|
||||||
evalOnly, outputKind, xmlOutputSourceLocation, e);
|
evalOnly, outputKind, xmlOutputSourceLocation, e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,9 +192,11 @@ static int main_nix_prefetch_url(int argc, char * * argv)
|
||||||
throw UsageError("you must specify a URL");
|
throw UsageError("you must specify a URL");
|
||||||
url = args[0];
|
url = args[0];
|
||||||
} else {
|
} else {
|
||||||
Path path = resolveExprPath(lookupFileArg(*state, args.empty() ? "." : args[0]));
|
|
||||||
Value vRoot;
|
Value vRoot;
|
||||||
state->evalFile(path, vRoot);
|
state->evalFile(
|
||||||
|
resolveExprPath(
|
||||||
|
state->rootPath(lookupFileArg(*state, args.empty() ? "." : args[0]))),
|
||||||
|
vRoot);
|
||||||
Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot).first);
|
Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot).first);
|
||||||
state->forceAttrs(v, noPos);
|
state->forceAttrs(v, noPos);
|
||||||
|
|
||||||
|
|
|
@ -624,7 +624,7 @@ void NixRepl::loadFile(const Path & path)
|
||||||
loadedFiles.remove(path);
|
loadedFiles.remove(path);
|
||||||
loadedFiles.push_back(path);
|
loadedFiles.push_back(path);
|
||||||
Value v, v2;
|
Value v, v2;
|
||||||
state->evalFile(lookupFileArg(*state, path), v);
|
state->evalFile(state->rootPath(lookupFileArg(*state, path)), v);
|
||||||
state->autoCallFunction(*autoArgs, v, v2);
|
state->autoCallFunction(*autoArgs, v, v2);
|
||||||
addAttrsToScope(v2);
|
addAttrsToScope(v2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,4 @@ libplugintest_ALLOW_UNDEFINED := 1
|
||||||
|
|
||||||
libplugintest_EXCLUDE_FROM_LIBRARY_LIST := 1
|
libplugintest_EXCLUDE_FROM_LIBRARY_LIST := 1
|
||||||
|
|
||||||
libplugintest_CXXFLAGS := -I src/libutil -I src/libexpr
|
libplugintest_CXXFLAGS := -I src/libutil -I src/libexpr -I src/libfetchers
|
||||||
|
|
Loading…
Reference in a new issue