nix flake show --json: Add type info

For extensibility, every leaf node is now an object that contains at
least a type field (e.g. "type": "derivation").
This commit is contained in:
Eelco Dolstra 2021-09-14 17:18:29 +02:00
parent f3259af73e
commit 1fbaf36729

View file

@ -876,56 +876,54 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
auto state = getEvalState(); auto state = getEvalState();
auto flake = std::make_shared<LockedFlake>(lockFlake()); auto flake = std::make_shared<LockedFlake>(lockFlake());
std::function<void(eval_cache::AttrCursor & visitor, const std::vector<Symbol> & attrPath, const std::string & headerPrefix, const std::string & nextPrefix)> visit; std::function<nlohmann::json(
eval_cache::AttrCursor & visitor,
const std::vector<Symbol> & attrPath,
const std::string & headerPrefix,
const std::string & nextPrefix)> visit;
nlohmann::json j; visit = [&](
// Populate json attributes along `attrPath` with a leaf value of `name` eval_cache::AttrCursor & visitor,
auto populateJson = [&](const std::vector<Symbol> & attrPath, const std::string name) const std::vector<Symbol> & attrPath,
const std::string & headerPrefix,
const std::string & nextPrefix)
-> nlohmann::json
{ {
nlohmann::json* r = & j; auto j = nlohmann::json::object();
for (const auto & element : attrPath){
(*r)[element] = (*r)[element].is_null() ? nlohmann::json({}) : (*r)[element];
r = & (*r)[element];
}
(*r) = name;
};
visit = [&](eval_cache::AttrCursor & visitor, const std::vector<Symbol> & attrPath, const std::string & headerPrefix, const std::string & nextPrefix)
{
Activity act(*logger, lvlInfo, actUnknown, Activity act(*logger, lvlInfo, actUnknown,
fmt("evaluating '%s'", concatStringsSep(".", attrPath))); fmt("evaluating '%s'", concatStringsSep(".", attrPath)));
try { try {
auto recurse = [&]() auto recurse = [&]()
{ {
if (!json){ if (!json)
logger->cout("%s", headerPrefix); logger->cout("%s", headerPrefix);
}
auto attrs = visitor.getAttrs(); auto attrs = visitor.getAttrs();
for (const auto & [i, attr] : enumerate(attrs)) { for (const auto & [i, attr] : enumerate(attrs)) {
bool last = i + 1 == attrs.size(); bool last = i + 1 == attrs.size();
auto visitor2 = visitor.getAttr(attr); auto visitor2 = visitor.getAttr(attr);
auto attrPath2(attrPath); auto attrPath2(attrPath);
attrPath2.push_back(attr); attrPath2.push_back(attr);
visit(*visitor2, attrPath2, auto j2 = visit(*visitor2, attrPath2,
fmt(ANSI_GREEN "%s%s" ANSI_NORMAL ANSI_BOLD "%s" ANSI_NORMAL, nextPrefix, last ? treeLast : treeConn, attr), fmt(ANSI_GREEN "%s%s" ANSI_NORMAL ANSI_BOLD "%s" ANSI_NORMAL, nextPrefix, last ? treeLast : treeConn, attr),
nextPrefix + (last ? treeNull : treeLine)); nextPrefix + (last ? treeNull : treeLine));
if (json) j.emplace(attr, std::move(j2));
} }
}; };
auto showDerivation = [&]() auto showDerivation = [&]()
{ {
auto name = visitor.getAttr(state->sName)->getString(); auto name = visitor.getAttr(state->sName)->getString();
if (json) {
/* std::optional<std::string> description;
std::string description; if (auto aMeta = visitor.maybeGetAttr("meta")) {
if (auto aDescription = aMeta->maybeGetAttr("description"))
if (auto aMeta = visitor.maybeGetAttr("meta")) { description = aDescription->getString();
if (auto aDescription = aMeta->maybeGetAttr("description")) }
description = aDescription->getString(); j.emplace("type", "derivation");
} j.emplace("name", name);
*/ if (description)
if (json){ j.emplace("description", *description);
populateJson(attrPath,name);
} else { } else {
logger->cout("%s: %s '%s'", logger->cout("%s: %s '%s'",
headerPrefix, headerPrefix,
@ -996,8 +994,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
auto aType = visitor.maybeGetAttr("type"); auto aType = visitor.maybeGetAttr("type");
if (!aType || aType->getString() != "app") if (!aType || aType->getString() != "app")
throw EvalError("not an app definition"); throw EvalError("not an app definition");
if(json){ if (json) {
populateJson(attrPath,"app"); j.emplace("type", "app");
} else { } else {
logger->cout("%s: app", headerPrefix); logger->cout("%s: app", headerPrefix);
} }
@ -1008,21 +1006,23 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
(attrPath.size() == 2 && attrPath[0] == "templates")) (attrPath.size() == 2 && attrPath[0] == "templates"))
{ {
auto description = visitor.getAttr("description")->getString(); auto description = visitor.getAttr("description")->getString();
if(json){ if (json) {
populateJson(attrPath,description); j.emplace("type", "template");
j.emplace("description", description);
} else { } else {
logger->cout("%s: template: " ANSI_BOLD "%s" ANSI_NORMAL, headerPrefix, description); logger->cout("%s: template: " ANSI_BOLD "%s" ANSI_NORMAL, headerPrefix, description);
} }
} }
else { else {
auto description = (attrPath.size() == 1 && attrPath[0] == "overlay") auto [type, description] =
|| (attrPath.size() == 2 && attrPath[0] == "overlays") ? "Nixpkgs overlay" : (attrPath.size() == 1 && attrPath[0] == "overlay")
attrPath.size() == 2 && attrPath[0] == "nixosConfigurations" ? "NixOS configuration" : || (attrPath.size() == 2 && attrPath[0] == "overlays") ? std::make_pair("nixpkgs-overlay", "Nixpkgs overlay") :
attrPath.size() == 2 && attrPath[0] == "nixosModules" ? "NixOS module" : attrPath.size() == 2 && attrPath[0] == "nixosConfigurations" ? std::make_pair("nixos-configuration", "NixOS configuration") :
"unknown"; attrPath.size() == 2 && attrPath[0] == "nixosModules" ? std::make_pair("nixos-module", "NixOS module") :
if(json){ std::make_pair("unknown", "unknown");
populateJson(attrPath,description); if (json) {
j.emplace("type", type);
} else { } else {
logger->cout("%s: " ANSI_WARNING "%s" ANSI_NORMAL, headerPrefix, description); logger->cout("%s: " ANSI_WARNING "%s" ANSI_NORMAL, headerPrefix, description);
} }
@ -1031,14 +1031,15 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
if (!(attrPath.size() > 0 && attrPath[0] == "legacyPackages")) if (!(attrPath.size() > 0 && attrPath[0] == "legacyPackages"))
throw; throw;
} }
return j;
}; };
auto cache = openEvalCache(*state, flake); auto cache = openEvalCache(*state, flake);
visit(*cache->getRoot(), {}, fmt(ANSI_BOLD "%s" ANSI_NORMAL, flake->flake.lockedRef), ""); auto j = visit(*cache->getRoot(), {}, fmt(ANSI_BOLD "%s" ANSI_NORMAL, flake->flake.lockedRef), "");
if(json){ if (json)
logger->cout("%s", j.dump()); logger->cout("%s", j.dump());
}
} }
}; };