mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-24 14:56:15 +02:00
Fix findFile(), coerceToPath()
This commit is contained in:
parent
e7f8aa8bdd
commit
b4c6adfd35
13 changed files with 92 additions and 80 deletions
|
@ -89,17 +89,18 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
|
||||||
return res.finish();
|
return res.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
Path lookupFileArg(EvalState & state, std::string_view s)
|
SourcePath lookupFileArg(EvalState & state, std::string_view s)
|
||||||
{
|
{
|
||||||
if (isUri(s)) {
|
if (isUri(s)) {
|
||||||
return state.store->toRealPath(
|
auto storePath = fetchers::downloadTarball(
|
||||||
fetchers::downloadTarball(
|
state.store, resolveUri(s), "source", false).first.storePath;
|
||||||
state.store, resolveUri(s), "source", false).first.storePath);
|
auto & accessor = state.registerAccessor(makeFSInputAccessor(state.store->toRealPath(storePath)));
|
||||||
|
return {accessor, "/"};
|
||||||
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
||||||
Path p(s.substr(1, s.size() - 2));
|
Path p(s.substr(1, s.size() - 2));
|
||||||
return state.findFile(p);
|
return state.findFile(p);
|
||||||
} else
|
} else
|
||||||
return absPath(std::string(s));
|
return state.rootPath(absPath(std::string(s)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace nix {
|
||||||
class Store;
|
class Store;
|
||||||
class EvalState;
|
class EvalState;
|
||||||
class Bindings;
|
class Bindings;
|
||||||
|
struct SourcePath;
|
||||||
|
|
||||||
struct MixEvalArgs : virtual Args
|
struct MixEvalArgs : virtual Args
|
||||||
{
|
{
|
||||||
|
@ -22,6 +23,6 @@ private:
|
||||||
std::map<std::string, std::string> autoArgs;
|
std::map<std::string, std::string> autoArgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
Path lookupFileArg(EvalState & state, std::string_view s);
|
SourcePath lookupFileArg(EvalState & state, std::string_view s);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,8 +210,7 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
|
||||||
Expr *e =
|
Expr *e =
|
||||||
state->parseExprFromFile(
|
state->parseExprFromFile(
|
||||||
resolveExprPath(
|
resolveExprPath(
|
||||||
state->rootPath(
|
lookupFileArg(*state, *file)));
|
||||||
lookupFileArg(*state, *file))));
|
|
||||||
|
|
||||||
Value root;
|
Value root;
|
||||||
state->eval(e, root);
|
state->eval(e, root);
|
||||||
|
@ -762,7 +761,7 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
||||||
state->eval(e, *vFile);
|
state->eval(e, *vFile);
|
||||||
}
|
}
|
||||||
else if (file)
|
else if (file)
|
||||||
state->evalFile(state->rootPath(lookupFileArg(*state, *file)), *vFile);
|
state->evalFile(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);
|
||||||
|
|
|
@ -485,22 +485,22 @@ EvalState::EvalState(
|
||||||
|
|
||||||
if (rootFS->hasAccessControl()) {
|
if (rootFS->hasAccessControl()) {
|
||||||
for (auto & i : searchPath) {
|
for (auto & i : searchPath) {
|
||||||
auto r = resolveSearchPathElem(i);
|
if (auto path = resolveSearchPathElem(i)) {
|
||||||
if (!r.first) continue;
|
// FIXME
|
||||||
|
#if 0
|
||||||
auto path = r.second;
|
if (store->isInStore(*path)) {
|
||||||
|
try {
|
||||||
if (store->isInStore(r.second)) {
|
StorePathSet closure;
|
||||||
try {
|
store->computeFSClosure(store->toStorePath(*path).first, closure);
|
||||||
StorePathSet closure;
|
for (auto & p : closure)
|
||||||
store->computeFSClosure(store->toStorePath(r.second).first, closure);
|
allowPath(p);
|
||||||
for (auto & path : closure)
|
} catch (InvalidPath &) {
|
||||||
allowPath(path);
|
allowPath(*r);
|
||||||
} catch (InvalidPath &) {
|
}
|
||||||
allowPath(r.second);
|
} else
|
||||||
}
|
allowPath(*r);
|
||||||
} else
|
#endif
|
||||||
allowPath(r.second);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1812,10 +1812,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
||||||
state.throwEvalError(i_pos, "cannot add %1% to a float", showType(vTmp));
|
state.throwEvalError(i_pos, "cannot add %1% to a float", showType(vTmp));
|
||||||
} else {
|
} else {
|
||||||
if (s.empty()) s.reserve(es->size());
|
if (s.empty()) s.reserve(es->size());
|
||||||
/* Skip canonization of first path, which would only be
|
auto part = state.coerceToString(i_pos, vTmp, context, false, firstType == nString);
|
||||||
non-canonical in the first place if it's coming from a
|
|
||||||
./${foo} type path. */
|
|
||||||
auto part = state.coerceToString(i_pos, vTmp, context, false, firstType == nString, !first);
|
|
||||||
sSize += part->size();
|
sSize += part->size();
|
||||||
s.emplace_back(std::move(part));
|
s.emplace_back(std::move(part));
|
||||||
}
|
}
|
||||||
|
@ -2017,7 +2014,7 @@ std::optional<std::string> EvalState::tryAttrsToString(const PosIdx pos, Value &
|
||||||
}
|
}
|
||||||
|
|
||||||
BackedStringView EvalState::coerceToString(const PosIdx pos, Value & v, PathSet & context,
|
BackedStringView EvalState::coerceToString(const PosIdx pos, Value & v, PathSet & context,
|
||||||
bool coerceMore, bool copyToStore, bool canonicalizePath)
|
bool coerceMore, bool copyToStore)
|
||||||
{
|
{
|
||||||
forceValue(v, pos);
|
forceValue(v, pos);
|
||||||
|
|
||||||
|
@ -2105,11 +2102,28 @@ StorePath EvalState::copyPathToStore(PathSet & context, const SourcePath & path)
|
||||||
|
|
||||||
SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, PathSet & context)
|
SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, PathSet & context)
|
||||||
{
|
{
|
||||||
auto path = coerceToString(pos, v, context, false, false).toOwned();
|
forceValue(v, pos);
|
||||||
if (path == "" || path[0] != '/')
|
|
||||||
throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path);
|
if (v.type() == nString) {
|
||||||
// FIXME
|
copyContext(v, context);
|
||||||
return rootPath(path);
|
return {*rootFS, v.string.s};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.type() == nPath)
|
||||||
|
return v.path();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (v.type() == nAttrs) {
|
||||||
|
auto maybeString = tryAttrsToString(pos, v, context, coerceMore, copyToStore);
|
||||||
|
if (maybeString)
|
||||||
|
return std::move(*maybeString);
|
||||||
|
auto i = v.attrs->find(sOutPath);
|
||||||
|
if (i == v.attrs->end()) throwTypeError(pos, "cannot coerce a set to a string");
|
||||||
|
return coerceToString(pos, *i->value, context, coerceMore, copyToStore);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
throwTypeError(pos, "cannot coerce %1% to a path", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -50,14 +50,15 @@ struct Env
|
||||||
void copyContext(const Value & v, PathSet & context);
|
void copyContext(const Value & v, PathSet & context);
|
||||||
|
|
||||||
|
|
||||||
std::ostream & printValue(const EvalState & state, std::ostream & str, const Value & v);
|
// FIXME: maybe change this to an std::variant<SourcePath, URL>.
|
||||||
std::string printValue(const EvalState & state, const Value & v);
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::pair<std::string, std::string> SearchPathElem;
|
typedef std::pair<std::string, std::string> SearchPathElem;
|
||||||
typedef std::list<SearchPathElem> SearchPath;
|
typedef std::list<SearchPathElem> SearchPath;
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream & printValue(const EvalState & state, std::ostream & str, const Value & v);
|
||||||
|
std::string printValue(const EvalState & state, const Value & v);
|
||||||
|
|
||||||
|
|
||||||
/* Initialise the Boehm GC, if applicable. */
|
/* Initialise the Boehm GC, if applicable. */
|
||||||
void initGC();
|
void initGC();
|
||||||
|
|
||||||
|
@ -130,7 +131,7 @@ private:
|
||||||
|
|
||||||
SearchPath searchPath;
|
SearchPath searchPath;
|
||||||
|
|
||||||
std::map<std::string, std::pair<bool, std::string>> searchPathResolved;
|
std::map<std::string, std::optional<SourcePath>> searchPathResolved;
|
||||||
|
|
||||||
/* Cache used by checkSourcePath(). */
|
/* Cache used by checkSourcePath(). */
|
||||||
std::unordered_map<Path, Path> resolvedPaths;
|
std::unordered_map<Path, Path> resolvedPaths;
|
||||||
|
@ -209,11 +210,11 @@ public:
|
||||||
void resetFileCache();
|
void resetFileCache();
|
||||||
|
|
||||||
/* Look up a file in the search path. */
|
/* Look up a file in the search path. */
|
||||||
Path findFile(const std::string_view path);
|
SourcePath findFile(const std::string_view path);
|
||||||
Path findFile(SearchPath & searchPath, const std::string_view path, const PosIdx pos = noPos);
|
SourcePath findFile(SearchPath & searchPath, const std::string_view path, const PosIdx pos = noPos);
|
||||||
|
|
||||||
/* If the specified search path element is a URI, download it. */
|
/* If the specified search path element is a URI, download it. */
|
||||||
std::pair<bool, std::string> resolveSearchPathElem(const SearchPathElem & elem);
|
std::optional<SourcePath> resolveSearchPathElem(const SearchPathElem & elem);
|
||||||
|
|
||||||
/* Evaluate an expression to normal form, storing the result in
|
/* Evaluate an expression to normal form, storing the result in
|
||||||
value `v'. */
|
value `v'. */
|
||||||
|
@ -303,8 +304,7 @@ public:
|
||||||
booleans and lists to a string. If `copyToStore' is set,
|
booleans and lists to a string. If `copyToStore' is set,
|
||||||
referenced paths are copied to the Nix store as a side effect. */
|
referenced paths are copied to the Nix store as a side effect. */
|
||||||
BackedStringView coerceToString(const PosIdx pos, Value & v, PathSet & context,
|
BackedStringView coerceToString(const PosIdx pos, Value & v, PathSet & context,
|
||||||
bool coerceMore = false, bool copyToStore = true,
|
bool coerceMore = false, bool copyToStore = true);
|
||||||
bool canonicalizePath = true);
|
|
||||||
|
|
||||||
StorePath copyPathToStore(PathSet & context, const SourcePath & path);
|
StorePath copyPathToStore(PathSet & context, const SourcePath & path);
|
||||||
|
|
||||||
|
|
|
@ -268,7 +268,7 @@ static Flake readFlake(
|
||||||
PathSet emptyContext = {};
|
PathSet emptyContext = {};
|
||||||
flake.config.settings.emplace(
|
flake.config.settings.emplace(
|
||||||
state.symbols[setting.name],
|
state.symbols[setting.name],
|
||||||
state.coerceToString(setting.pos, *setting.value, emptyContext, false, true, true) .toOwned());
|
state.coerceToString(setting.pos, *setting.value, emptyContext, false, true).toOwned());
|
||||||
}
|
}
|
||||||
else if (setting.value->type() == nInt)
|
else if (setting.value->type() == nInt)
|
||||||
flake.config.settings.emplace(
|
flake.config.settings.emplace(
|
||||||
|
|
|
@ -759,13 +759,13 @@ void EvalState::addToSearchPath(const std::string & s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path EvalState::findFile(const std::string_view path)
|
SourcePath EvalState::findFile(const std::string_view path)
|
||||||
{
|
{
|
||||||
return findFile(searchPath, path);
|
return findFile(searchPath, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path EvalState::findFile(SearchPath & searchPath, const std::string_view path, const PosIdx pos)
|
SourcePath EvalState::findFile(SearchPath & searchPath, const std::string_view path, const PosIdx pos)
|
||||||
{
|
{
|
||||||
for (auto & i : searchPath) {
|
for (auto & i : searchPath) {
|
||||||
std::string suffix;
|
std::string suffix;
|
||||||
|
@ -778,15 +778,14 @@ Path EvalState::findFile(SearchPath & searchPath, const std::string_view path, c
|
||||||
continue;
|
continue;
|
||||||
suffix = path.size() == s ? "" : concatStrings("/", path.substr(s));
|
suffix = path.size() == s ? "" : concatStrings("/", path.substr(s));
|
||||||
}
|
}
|
||||||
auto r = resolveSearchPathElem(i);
|
if (auto path = resolveSearchPathElem(i)) {
|
||||||
if (!r.first) continue;
|
auto res = path->append("/" + suffix);
|
||||||
Path res = r.second + suffix;
|
if (res.pathExists()) return res;
|
||||||
if (pathExists(res)) return canonPath(res);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasPrefix(path, "nix/"))
|
if (hasPrefix(path, "nix/"))
|
||||||
abort();
|
return {*corepkgsFS, (std::string) path.substr(3)};
|
||||||
//return packPath(SourcePath {corepkgsFS, (std::string) path.substr(3)});
|
|
||||||
|
|
||||||
throw ThrownError({
|
throw ThrownError({
|
||||||
.msg = hintfmt(evalSettings.pureEval
|
.msg = hintfmt(evalSettings.pureEval
|
||||||
|
@ -798,38 +797,39 @@ Path EvalState::findFile(SearchPath & searchPath, const std::string_view path, c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathElem & elem)
|
std::optional<SourcePath> EvalState::resolveSearchPathElem(const SearchPathElem & elem)
|
||||||
{
|
{
|
||||||
auto i = searchPathResolved.find(elem.second);
|
auto i = searchPathResolved.find(elem.second);
|
||||||
if (i != searchPathResolved.end()) return i->second;
|
if (i != searchPathResolved.end()) return i->second;
|
||||||
|
|
||||||
std::pair<bool, std::string> res;
|
std::optional<SourcePath> res;
|
||||||
|
|
||||||
if (isUri(elem.second)) {
|
if (isUri(elem.second)) {
|
||||||
try {
|
try {
|
||||||
res = { true, store->toRealPath(fetchers::downloadTarball(
|
auto storePath = fetchers::downloadTarball(
|
||||||
store, resolveUri(elem.second), "source", false).first.storePath) };
|
store, resolveUri(elem.second), "source", false).first.storePath;
|
||||||
|
auto & accessor = registerAccessor(makeFSInputAccessor(store->toRealPath(storePath)));
|
||||||
|
res.emplace(SourcePath {accessor, "/"});
|
||||||
} catch (FileTransferError & e) {
|
} catch (FileTransferError & e) {
|
||||||
logWarning({
|
logWarning({
|
||||||
.msg = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", elem.second)
|
.msg = hintfmt("Nix search path entry '%1%' cannot be downloaded, ignoring", elem.second)
|
||||||
});
|
});
|
||||||
res = { false, "" };
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto path = absPath(elem.second);
|
auto path = rootPath(absPath(elem.second));
|
||||||
if (pathExists(path))
|
if (path.pathExists())
|
||||||
res = { true, path };
|
res.emplace(path);
|
||||||
else {
|
else {
|
||||||
logWarning({
|
logWarning({
|
||||||
.msg = hintfmt("Nix search path entry '%1%' does not exist, ignoring", elem.second)
|
.msg = hintfmt("Nix search path entry '%1%' does not exist, ignoring", elem.second)
|
||||||
});
|
});
|
||||||
res = { false, "" };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(format("resolved search path element '%s' to '%s'") % elem.second % res.second);
|
if (res)
|
||||||
|
debug("resolved search path element '%s' to '%s'", elem.second, *res);
|
||||||
|
|
||||||
searchPathResolved[elem.second] = res;
|
searchPathResolved.emplace(elem.second, res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@ static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, co
|
||||||
}();
|
}();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
#if 0
|
||||||
if (!context.empty()) {
|
if (!context.empty()) {
|
||||||
auto rewrites = state.realiseContext(context);
|
auto rewrites = state.realiseContext(context);
|
||||||
// FIXME: check that path.accessor == rootFS?
|
// FIXME: check that path.accessor == rootFS?
|
||||||
|
@ -120,6 +121,7 @@ static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, co
|
||||||
// FIXME: return store accessor
|
// FIXME: return store accessor
|
||||||
return state.rootPath(realPath);
|
return state.rootPath(realPath);
|
||||||
} else
|
} else
|
||||||
|
#endif
|
||||||
return path;
|
return path;
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(state.positions[pos], "while realising the context of path '%s'", path);
|
e.addTrace(state.positions[pos], "while realising the context of path '%s'", path);
|
||||||
|
@ -1545,12 +1547,7 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V
|
||||||
|
|
||||||
auto path = state.forceStringNoCtx(*args[1], pos);
|
auto path = state.forceStringNoCtx(*args[1], pos);
|
||||||
|
|
||||||
#if 0
|
|
||||||
// FIXME: checkSourcePath?
|
|
||||||
v.mkPath(state.findFile(searchPath, path, pos));
|
v.mkPath(state.findFile(searchPath, path, pos));
|
||||||
#endif
|
|
||||||
|
|
||||||
throw ThrownError("findFile('%s'): not implemented", path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_findFile(RegisterPrimOp::Info {
|
static RegisterPrimOp primop_findFile(RegisterPrimOp::Info {
|
||||||
|
|
|
@ -307,9 +307,8 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
exprs.push_back(
|
exprs.push_back(
|
||||||
state->parseExprFromFile(
|
state->parseExprFromFile(
|
||||||
resolveExprPath(
|
resolveExprPath(
|
||||||
state->rootPath(
|
lookupFileArg(*state,
|
||||||
lookupFileArg(*state,
|
inShebang && !packages ? absPath(i, absPath(dirOf(script))) : i))));
|
||||||
inShebang && !packages ? absPath(i, absPath(dirOf(script))) : i)))));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1475,7 +1475,9 @@ static int main_nix_env(int argc, char * * argv)
|
||||||
globals.state->repair = repair;
|
globals.state->repair = repair;
|
||||||
|
|
||||||
if (file != "")
|
if (file != "")
|
||||||
globals.instSource.nixExprPath = lookupFileArg(*globals.state, file);
|
// FIXME: check that the accessor returned by
|
||||||
|
// lookupFileArg() is the root FS.
|
||||||
|
globals.instSource.nixExprPath = lookupFileArg(*globals.state, file).path;
|
||||||
|
|
||||||
globals.instSource.autoArgs = myArgs.getAutoArgs(*globals.state);
|
globals.instSource.autoArgs = myArgs.getAutoArgs(*globals.state);
|
||||||
|
|
||||||
|
|
|
@ -167,9 +167,8 @@ static int main_nix_instantiate(int argc, char * * argv)
|
||||||
|
|
||||||
if (findFile) {
|
if (findFile) {
|
||||||
for (auto & i : files) {
|
for (auto & i : files) {
|
||||||
Path p = state->findFile(i);
|
auto p = state->findFile(i);
|
||||||
if (p == "") throw Error("unable to find '%1%'", i);
|
std::cout << p.readFile() << std::endl;
|
||||||
std::cout << p << std::endl;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -184,7 +183,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->rootPath(lookupFileArg(*state, i))));
|
: state->parseExprFromFile(resolveExprPath(lookupFileArg(*state, i)));
|
||||||
processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
|
processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
|
||||||
evalOnly, outputKind, xmlOutputSourceLocation, e);
|
evalOnly, outputKind, xmlOutputSourceLocation, e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,7 @@ static int main_nix_prefetch_url(int argc, char * * argv)
|
||||||
Value vRoot;
|
Value vRoot;
|
||||||
state->evalFile(
|
state->evalFile(
|
||||||
resolveExprPath(
|
resolveExprPath(
|
||||||
state->rootPath(lookupFileArg(*state, args.empty() ? "." : args[0]))),
|
lookupFileArg(*state, args.empty() ? "." : args[0])),
|
||||||
vRoot);
|
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);
|
||||||
|
|
|
@ -636,7 +636,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(state->rootPath(lookupFileArg(*state, path)), v);
|
state->evalFile(lookupFileArg(*state, path), v);
|
||||||
state->autoCallFunction(*autoArgs, v, v2);
|
state->autoCallFunction(*autoArgs, v, v2);
|
||||||
addAttrsToScope(v2);
|
addAttrsToScope(v2);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue