nix: Make -f work for compatibility

This commit is contained in:
Eelco Dolstra 2019-04-08 16:11:17 +02:00
parent 9b7eac332b
commit 101d964a59
4 changed files with 61 additions and 91 deletions

View file

@ -74,23 +74,20 @@ struct Installable
struct SourceExprCommand : virtual Args, StoreCommand, MixEvalArgs struct SourceExprCommand : virtual Args, StoreCommand, MixEvalArgs
{ {
std::optional<Path> file; std::optional<Path> file;
std::optional<std::string> flakeUri;
SourceExprCommand(); SourceExprCommand();
/* Return a value representing the Nix expression from which we
are installing. This is either the file specified by --file,
or an attribute set constructed from $NIX_PATH, e.g. { nixpkgs
= import ...; bla = import ...; }. */
Value * getSourceExpr(EvalState & state);
ref<EvalState> getEvalState(); ref<EvalState> getEvalState();
std::vector<std::shared_ptr<Installable>> parseInstallables(
ref<Store> store, std::vector<std::string> ss);
std::shared_ptr<Installable> parseInstallable(
ref<Store> store, const std::string & installable);
private: private:
std::shared_ptr<EvalState> evalState; std::shared_ptr<EvalState> evalState;
Value * vSourceExpr = 0;
}; };
enum RealiseMode { Build, NoBuild, DryRun }; enum RealiseMode { Build, NoBuild, DryRun };
@ -108,8 +105,6 @@ struct InstallablesCommand : virtual Args, SourceExprCommand
void prepare() override; void prepare() override;
virtual bool useDefaultInstallables() { return true; }
private: private:
std::vector<std::string> _installables; std::vector<std::string> _installables;
@ -148,8 +143,6 @@ public:
virtual void run(ref<Store> store, Paths storePaths) = 0; virtual void run(ref<Store> store, Paths storePaths) = 0;
void run(ref<Store> store) override; void run(ref<Store> store) override;
bool useDefaultInstallables() override { return !all; }
}; };
/* A command that operates on exactly one store path. */ /* A command that operates on exactly one store path. */
@ -174,10 +167,6 @@ struct RegisterCommand
} }
}; };
std::shared_ptr<Installable> parseInstallable(
SourceExprCommand & cmd, ref<Store> store, const std::string & installable,
bool useDefaultInstallables);
Buildables build(ref<Store> store, RealiseMode mode, Buildables build(ref<Store> store, RealiseMode mode,
std::vector<std::shared_ptr<Installable>> installables); std::vector<std::shared_ptr<Installable>> installables);

View file

@ -19,33 +19,10 @@ SourceExprCommand::SourceExprCommand()
.shortName('f') .shortName('f')
.longName("file") .longName("file")
.label("file") .label("file")
.description("evaluate FILE rather than use the default installation source") .description("evaluate a set of attributes from FILE (deprecated)")
.dest(&file); .dest(&file);
} }
Value * SourceExprCommand::getSourceExpr(EvalState & state)
{
if (vSourceExpr) return vSourceExpr;
vSourceExpr = state.allocValue();
if (file)
state.evalFile(lookupFileArg(state, *file), *vSourceExpr);
else {
// FIXME: remove "impure" hack, call some non-user-accessible
// variant of getFlake instead.
auto fun = state.parseExprFromString(
"builtins.mapAttrs (flakeName: flakeInfo:"
" (getFlake (\"impure:\" + flakeInfo.uri)).${flakeName}.provides.packages or {})", "/");
auto vFun = state.allocValue();
state.eval(fun, *vFun);
auto vRegistry = makeFlakeRegistryValue(state);
mkApp(*vSourceExpr, *vFun, *vRegistry);
}
return vSourceExpr;
}
ref<EvalState> SourceExprCommand::getEvalState() ref<EvalState> SourceExprCommand::getEvalState()
{ {
if (!evalState) if (!evalState)
@ -140,24 +117,20 @@ struct InstallableExpr : InstallableValue
struct InstallableAttrPath : InstallableValue struct InstallableAttrPath : InstallableValue
{ {
Value * v;
std::string attrPath; std::string attrPath;
InstallableAttrPath(SourceExprCommand & cmd, const std::string & attrPath) InstallableAttrPath(SourceExprCommand & cmd, Value * v, const std::string & attrPath)
: InstallableValue(cmd), attrPath(attrPath) : InstallableValue(cmd), v(v), attrPath(attrPath)
{ } { }
std::string what() override { return attrPath; } std::string what() override { return attrPath; }
Value * toValue(EvalState & state) override Value * toValue(EvalState & state) override
{ {
auto source = cmd.getSourceExpr(state); auto vRes = findAlongAttrPath(state, attrPath, *cmd.getAutoArgs(state), *v);
state.forceValue(*vRes);
Bindings & autoArgs = *cmd.getAutoArgs(state); return vRes;
Value * v = findAlongAttrPath(state, attrPath, autoArgs, *source);
state.forceValue(*v);
return v;
} }
}; };
@ -202,60 +175,66 @@ struct InstallableFlake : InstallableValue
std::string attrRegex = R"([A-Za-z_][A-Za-z0-9-_+]*)"; std::string attrRegex = R"([A-Za-z_][A-Za-z0-9-_+]*)";
static std::regex attrPathRegex(fmt(R"(%1%(\.%1%)*)", attrRegex)); static std::regex attrPathRegex(fmt(R"(%1%(\.%1%)*)", attrRegex));
static std::vector<std::shared_ptr<Installable>> parseInstallables( std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
SourceExprCommand & cmd, ref<Store> store, std::vector<std::string> ss, bool useDefaultInstallables) ref<Store> store, std::vector<std::string> ss)
{ {
std::vector<std::shared_ptr<Installable>> result; std::vector<std::shared_ptr<Installable>> result;
if (ss.empty() && useDefaultInstallables) { if (file) {
if (cmd.file == "") // FIXME: backward compatibility hack
cmd.file = "."; evalSettings.pureEval = false;
ss = {""};
}
for (auto & s : ss) { auto state = getEvalState();
auto vFile = state->allocValue();
state->evalFile(lookupFileArg(*state, *file), *vFile);
if (s.compare(0, 1, "(") == 0) if (ss.empty())
result.push_back(std::make_shared<InstallableExpr>(cmd, s)); ss = {""};
/* for (auto & s : ss)
else if (s.find('/') != std::string::npos) { result.push_back(std::make_shared<InstallableAttrPath>(*this, vFile, s));
auto path = store->toStorePath(store->followLinksToStore(s)); } else {
if (store->isStorePath(path)) for (auto & s : ss) {
result.push_back(std::make_shared<InstallableStorePath>(path));
}
*/
else { size_t colon;
auto colon = s.rfind(':');
if (colon != std::string::npos) { if (s.compare(0, 1, "(") == 0)
result.push_back(std::make_shared<InstallableExpr>(*this, s));
else if ((colon = s.rfind(':')) != std::string::npos) {
auto flakeRef = std::string(s, 0, colon); auto flakeRef = std::string(s, 0, colon);
auto attrPath = std::string(s, colon + 1); auto attrPath = std::string(s, colon + 1);
result.push_back(std::make_shared<InstallableFlake>(cmd, FlakeRef(flakeRef), attrPath)); result.push_back(std::make_shared<InstallableFlake>(*this, FlakeRef(flakeRef), attrPath));
} else {
result.push_back(std::make_shared<InstallableFlake>(cmd, FlakeRef("nixpkgs"), s));
} }
else if (s.find('/') != std::string::npos) {
auto path = store->toStorePath(store->followLinksToStore(s));
result.push_back(std::make_shared<InstallableStorePath>(path));
}
else {
result.push_back(std::make_shared<InstallableFlake>(*this, FlakeRef("nixpkgs"), s));
}
/*
else if (s == "" || std::regex_match(s, attrPathRegex))
result.push_back(std::make_shared<InstallableAttrPath>(cmd, s));
else
throw UsageError("don't know what to do with argument '%s'", s);
*/
} }
/*
else if (s == "" || std::regex_match(s, attrPathRegex))
result.push_back(std::make_shared<InstallableAttrPath>(cmd, s));
else
throw UsageError("don't know what to do with argument '%s'", s);
*/
} }
return result; return result;
} }
std::shared_ptr<Installable> parseInstallable( std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
SourceExprCommand & cmd, ref<Store> store, const std::string & installable, ref<Store> store, const std::string & installable)
bool useDefaultInstallables)
{ {
auto installables = parseInstallables(cmd, store, {installable}, false); auto installables = parseInstallables(store, {installable});
assert(installables.size() == 1); assert(installables.size() == 1);
return installables.front(); return installables.front();
} }
@ -342,12 +321,12 @@ PathSet toDerivations(ref<Store> store,
void InstallablesCommand::prepare() void InstallablesCommand::prepare()
{ {
installables = parseInstallables(*this, getStore(), _installables, useDefaultInstallables()); installables = parseInstallables(getStore(), _installables);
} }
void InstallableCommand::prepare() void InstallableCommand::prepare()
{ {
installable = parseInstallable(*this, getStore(), _installable, false); installable = parseInstallable(getStore(), _installable);
} }
} }

View file

@ -257,7 +257,9 @@ struct CmdSearch : SourceExprCommand, MixJSON
auto cache = writeCache ? std::make_unique<JSONObject>(jsonCacheFile, false) : nullptr; auto cache = writeCache ? std::make_unique<JSONObject>(jsonCacheFile, false) : nullptr;
doExpr(getSourceExpr(*state), "", true, cache.get()); // FIXME
throw Error("NOT IMPLEMENTED");
//doExpr(getSourceExpr(*state), "", true, cache.get());
} catch (std::exception &) { } catch (std::exception &) {
/* Fun fact: catching std::ios::failure does not work /* Fun fact: catching std::ios::failure does not work

View file

@ -74,9 +74,9 @@ struct CmdWhyDepends : SourceExprCommand
void run(ref<Store> store) override void run(ref<Store> store) override
{ {
auto package = parseInstallable(*this, store, _package, false); auto package = parseInstallable(store, _package);
auto packagePath = toStorePath(store, Build, package); auto packagePath = toStorePath(store, Build, package);
auto dependency = parseInstallable(*this, store, _dependency, false); auto dependency = parseInstallable(store, _dependency);
auto dependencyPath = toStorePath(store, NoBuild, dependency); auto dependencyPath = toStorePath(store, NoBuild, dependency);
auto dependencyPathHash = storePathToHash(dependencyPath); auto dependencyPathHash = storePathToHash(dependencyPath);