forked from lix-project/lix
Replace src/libutil/json.cc with nlohmann json generation
This commit is contained in:
parent
62960f3291
commit
09f00dd4d0
|
@ -7,7 +7,6 @@
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh"
|
||||||
#include "filetransfer.hh"
|
#include "filetransfer.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "function-trace.hh"
|
#include "function-trace.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -21,6 +20,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#if HAVE_BOEHMGC
|
#if HAVE_BOEHMGC
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
static char * allocString(size_t size)
|
static char * allocString(size_t size)
|
||||||
|
@ -2441,97 +2443,97 @@ void EvalState::printStats()
|
||||||
std::fstream fs;
|
std::fstream fs;
|
||||||
if (outPath != "-")
|
if (outPath != "-")
|
||||||
fs.open(outPath, std::fstream::out);
|
fs.open(outPath, std::fstream::out);
|
||||||
JSONObject topObj(outPath == "-" ? std::cerr : fs, true);
|
json topObj = json::object();
|
||||||
topObj.attr("cpuTime",cpuTime);
|
topObj["cpuTime"] = cpuTime;
|
||||||
{
|
topObj["envs"] = {
|
||||||
auto envs = topObj.object("envs");
|
{"number", nrEnvs},
|
||||||
envs.attr("number", nrEnvs);
|
{"elements", nrValuesInEnvs},
|
||||||
envs.attr("elements", nrValuesInEnvs);
|
{"bytes", bEnvs},
|
||||||
envs.attr("bytes", bEnvs);
|
};
|
||||||
}
|
topObj["list"] = {
|
||||||
{
|
{"elements", nrListElems},
|
||||||
auto lists = topObj.object("list");
|
{"bytes", bLists},
|
||||||
lists.attr("elements", nrListElems);
|
{"concats", nrListConcats},
|
||||||
lists.attr("bytes", bLists);
|
};
|
||||||
lists.attr("concats", nrListConcats);
|
topObj["values"] = {
|
||||||
}
|
{"number", nrValues},
|
||||||
{
|
{"bytes", bValues},
|
||||||
auto values = topObj.object("values");
|
};
|
||||||
values.attr("number", nrValues);
|
topObj["symbols"] = {
|
||||||
values.attr("bytes", bValues);
|
{"number", symbols.size()},
|
||||||
}
|
{"bytes", symbols.totalSize()},
|
||||||
{
|
};
|
||||||
auto syms = topObj.object("symbols");
|
topObj["sets"] = {
|
||||||
syms.attr("number", symbols.size());
|
{"number", nrAttrsets},
|
||||||
syms.attr("bytes", symbols.totalSize());
|
{"bytes", bAttrsets},
|
||||||
}
|
{"elements", nrAttrsInAttrsets},
|
||||||
{
|
};
|
||||||
auto sets = topObj.object("sets");
|
topObj["sizes"] = {
|
||||||
sets.attr("number", nrAttrsets);
|
{"Env", sizeof(Env)},
|
||||||
sets.attr("bytes", bAttrsets);
|
{"Value", sizeof(Value)},
|
||||||
sets.attr("elements", nrAttrsInAttrsets);
|
{"Bindings", sizeof(Bindings)},
|
||||||
}
|
{"Attr", sizeof(Attr)},
|
||||||
{
|
};
|
||||||
auto sizes = topObj.object("sizes");
|
topObj["nrOpUpdates"] = nrOpUpdates;
|
||||||
sizes.attr("Env", sizeof(Env));
|
topObj["nrOpUpdateValuesCopied"] = nrOpUpdateValuesCopied;
|
||||||
sizes.attr("Value", sizeof(Value));
|
topObj["nrThunks"] = nrThunks;
|
||||||
sizes.attr("Bindings", sizeof(Bindings));
|
topObj["nrAvoided"] = nrAvoided;
|
||||||
sizes.attr("Attr", sizeof(Attr));
|
topObj["nrLookups"] = nrLookups;
|
||||||
}
|
topObj["nrPrimOpCalls"] = nrPrimOpCalls;
|
||||||
topObj.attr("nrOpUpdates", nrOpUpdates);
|
topObj["nrFunctionCalls"] = nrFunctionCalls;
|
||||||
topObj.attr("nrOpUpdateValuesCopied", nrOpUpdateValuesCopied);
|
|
||||||
topObj.attr("nrThunks", nrThunks);
|
|
||||||
topObj.attr("nrAvoided", nrAvoided);
|
|
||||||
topObj.attr("nrLookups", nrLookups);
|
|
||||||
topObj.attr("nrPrimOpCalls", nrPrimOpCalls);
|
|
||||||
topObj.attr("nrFunctionCalls", nrFunctionCalls);
|
|
||||||
#if HAVE_BOEHMGC
|
#if HAVE_BOEHMGC
|
||||||
{
|
topObj["gc"] = {
|
||||||
auto gc = topObj.object("gc");
|
{"heapSize", heapSize},
|
||||||
gc.attr("heapSize", heapSize);
|
{"totalBytes", totalBytes},
|
||||||
gc.attr("totalBytes", totalBytes);
|
};
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (countCalls) {
|
if (countCalls) {
|
||||||
|
topObj["primops"] = primOpCalls;
|
||||||
{
|
{
|
||||||
auto obj = topObj.object("primops");
|
auto& list = topObj["functions"];
|
||||||
for (auto & i : primOpCalls)
|
list = json::array();
|
||||||
obj.attr(i.first, i.second);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto list = topObj.list("functions");
|
|
||||||
for (auto & [fun, count] : functionCalls) {
|
for (auto & [fun, count] : functionCalls) {
|
||||||
auto obj = list.object();
|
json obj = json::object();
|
||||||
if (fun->name)
|
if (fun->name)
|
||||||
obj.attr("name", (std::string_view) symbols[fun->name]);
|
obj["name"] = (std::string_view) symbols[fun->name];
|
||||||
else
|
else
|
||||||
obj.attr("name", nullptr);
|
obj["name"] = nullptr;
|
||||||
if (auto pos = positions[fun->pos]) {
|
if (auto pos = positions[fun->pos]) {
|
||||||
obj.attr("file", (std::string_view) pos.file);
|
obj["file"] = (std::string_view) pos.file;
|
||||||
obj.attr("line", pos.line);
|
obj["line"] = pos.line;
|
||||||
obj.attr("column", pos.column);
|
obj["column"] = pos.column;
|
||||||
}
|
}
|
||||||
obj.attr("count", count);
|
obj["count"] = count;
|
||||||
|
list.push_back(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto list = topObj.list("attributes");
|
auto list = topObj["attributes"];
|
||||||
|
list = json::array();
|
||||||
for (auto & i : attrSelects) {
|
for (auto & i : attrSelects) {
|
||||||
auto obj = list.object();
|
json obj = json::object();
|
||||||
if (auto pos = positions[i.first]) {
|
if (auto pos = positions[i.first]) {
|
||||||
obj.attr("file", (const std::string &) pos.file);
|
obj["file"] = (const std::string &) pos.file;
|
||||||
obj.attr("line", pos.line);
|
obj["line"] = pos.line;
|
||||||
obj.attr("column", pos.column);
|
obj["column"] = pos.column;
|
||||||
}
|
}
|
||||||
obj.attr("count", i.second);
|
obj["count"] = i.second;
|
||||||
|
list.push_back(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getEnv("NIX_SHOW_SYMBOLS").value_or("0") != "0") {
|
if (getEnv("NIX_SHOW_SYMBOLS").value_or("0") != "0") {
|
||||||
auto list = topObj.list("symbols");
|
// XXX: overrides earlier assignment
|
||||||
symbols.dump([&](const std::string & s) { list.elem(s); });
|
topObj["symbols"] = json::array();
|
||||||
|
auto &list = topObj["symbols"];
|
||||||
|
symbols.dump([&](const std::string & s) { list.emplace_back(s); });
|
||||||
|
}
|
||||||
|
if (outPath == "-") {
|
||||||
|
std::cerr << topObj.dump(2) << std::endl;
|
||||||
|
} else {
|
||||||
|
fs << topObj.dump(2) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
#include "references.hh"
|
#include "references.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "value-to-json.hh"
|
#include "value-to-json.hh"
|
||||||
#include "value-to-xml.hh"
|
#include "value-to-xml.hh"
|
||||||
#include "primops.hh"
|
#include "primops.hh"
|
||||||
|
|
||||||
#include <boost/container/small_vector.hpp>
|
#include <boost/container/small_vector.hpp>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -1011,6 +1011,7 @@ static void prim_second(EvalState & state, const PosIdx pos, Value * * args, Val
|
||||||
derivation. */
|
derivation. */
|
||||||
static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
|
using nlohmann::json;
|
||||||
state.forceAttrs(*args[0], pos);
|
state.forceAttrs(*args[0], pos);
|
||||||
|
|
||||||
/* Figure out the name first (for stack backtraces). */
|
/* Figure out the name first (for stack backtraces). */
|
||||||
|
@ -1032,11 +1033,10 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * *
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check whether attributes should be passed as a JSON file. */
|
/* Check whether attributes should be passed as a JSON file. */
|
||||||
std::ostringstream jsonBuf;
|
std::optional<json> jsonObject;
|
||||||
std::unique_ptr<JSONObject> jsonObject;
|
|
||||||
attr = args[0]->attrs->find(state.sStructuredAttrs);
|
attr = args[0]->attrs->find(state.sStructuredAttrs);
|
||||||
if (attr != args[0]->attrs->end() && state.forceBool(*attr->value, pos))
|
if (attr != args[0]->attrs->end() && state.forceBool(*attr->value, pos))
|
||||||
jsonObject = std::make_unique<JSONObject>(jsonBuf);
|
jsonObject = json::object();
|
||||||
|
|
||||||
/* Check whether null attributes should be ignored. */
|
/* Check whether null attributes should be ignored. */
|
||||||
bool ignoreNulls = false;
|
bool ignoreNulls = false;
|
||||||
|
@ -1138,8 +1138,7 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * *
|
||||||
|
|
||||||
if (i->name == state.sStructuredAttrs) continue;
|
if (i->name == state.sStructuredAttrs) continue;
|
||||||
|
|
||||||
auto placeholder(jsonObject->placeholder(key));
|
(*jsonObject)[key] = printValueAsJSON(state, true, *i->value, pos, context);
|
||||||
printValueAsJSON(state, true, *i->value, pos, placeholder, context);
|
|
||||||
|
|
||||||
if (i->name == state.sBuilder)
|
if (i->name == state.sBuilder)
|
||||||
drv.builder = state.forceString(*i->value, context, posDrvName);
|
drv.builder = state.forceString(*i->value, context, posDrvName);
|
||||||
|
@ -1183,8 +1182,8 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * *
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonObject) {
|
if (jsonObject) {
|
||||||
|
drv.env.emplace("__json", jsonObject->dump());
|
||||||
jsonObject.reset();
|
jsonObject.reset();
|
||||||
drv.env.emplace("__json", jsonBuf.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Everything in the context of the strings in the derivation
|
/* Everything in the context of the strings in the derivation
|
||||||
|
|
|
@ -1,84 +1,82 @@
|
||||||
#include "value-to-json.hh"
|
#include "value-to-json.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
using json = nlohmann::json;
|
||||||
void printValueAsJSON(EvalState & state, bool strict,
|
json printValueAsJSON(EvalState & state, bool strict,
|
||||||
Value & v, const PosIdx pos, JSONPlaceholder & out, PathSet & context, bool copyToStore)
|
Value & v, const PosIdx pos, PathSet & context, bool copyToStore)
|
||||||
{
|
{
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
|
|
||||||
if (strict) state.forceValue(v, pos);
|
if (strict) state.forceValue(v, pos);
|
||||||
|
|
||||||
|
json out;
|
||||||
|
|
||||||
switch (v.type()) {
|
switch (v.type()) {
|
||||||
|
|
||||||
case nInt:
|
case nInt:
|
||||||
out.write(v.integer);
|
out = v.integer;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nBool:
|
case nBool:
|
||||||
out.write(v.boolean);
|
out = v.boolean;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nString:
|
case nString:
|
||||||
copyContext(v, context);
|
copyContext(v, context);
|
||||||
out.write(v.string.s);
|
out = v.string.s;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nPath:
|
case nPath:
|
||||||
if (copyToStore)
|
if (copyToStore)
|
||||||
out.write(state.copyPathToStore(context, v.path));
|
out = state.copyPathToStore(context, v.path);
|
||||||
else
|
else
|
||||||
out.write(v.path);
|
out = v.path;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nNull:
|
case nNull:
|
||||||
out.write(nullptr);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nAttrs: {
|
case nAttrs: {
|
||||||
auto maybeString = state.tryAttrsToString(pos, v, context, false, false);
|
auto maybeString = state.tryAttrsToString(pos, v, context, false, false);
|
||||||
if (maybeString) {
|
if (maybeString) {
|
||||||
out.write(*maybeString);
|
out = *maybeString;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto i = v.attrs->find(state.sOutPath);
|
auto i = v.attrs->find(state.sOutPath);
|
||||||
if (i == v.attrs->end()) {
|
if (i == v.attrs->end()) {
|
||||||
auto obj(out.object());
|
out = json::object();
|
||||||
StringSet names;
|
StringSet names;
|
||||||
for (auto & j : *v.attrs)
|
for (auto & j : *v.attrs)
|
||||||
names.emplace(state.symbols[j.name]);
|
names.emplace(state.symbols[j.name]);
|
||||||
for (auto & j : names) {
|
for (auto & j : names) {
|
||||||
Attr & a(*v.attrs->find(state.symbols.create(j)));
|
Attr & a(*v.attrs->find(state.symbols.create(j)));
|
||||||
auto placeholder(obj.placeholder(j));
|
out[j] = printValueAsJSON(state, strict, *a.value, a.pos, context, copyToStore);
|
||||||
printValueAsJSON(state, strict, *a.value, a.pos, placeholder, context, copyToStore);
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
printValueAsJSON(state, strict, *i->value, i->pos, out, context, copyToStore);
|
return printValueAsJSON(state, strict, *i->value, i->pos, context, copyToStore);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case nList: {
|
case nList: {
|
||||||
auto list(out.list());
|
out = json::array();
|
||||||
for (auto elem : v.listItems()) {
|
for (auto elem : v.listItems())
|
||||||
auto placeholder(list.placeholder());
|
out.push_back(printValueAsJSON(state, strict, *elem, pos, context, copyToStore));
|
||||||
printValueAsJSON(state, strict, *elem, pos, placeholder, context, copyToStore);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case nExternal:
|
case nExternal:
|
||||||
v.external->printValueAsJSON(state, strict, out, context, copyToStore);
|
return v.external->printValueAsJSON(state, strict, context, copyToStore);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nFloat:
|
case nFloat:
|
||||||
out.write(v.fpoint);
|
out = v.fpoint;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nThunk:
|
case nThunk:
|
||||||
|
@ -91,17 +89,17 @@ void printValueAsJSON(EvalState & state, bool strict,
|
||||||
state.debugThrowLastTrace(e);
|
state.debugThrowLastTrace(e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printValueAsJSON(EvalState & state, bool strict,
|
void printValueAsJSON(EvalState & state, bool strict,
|
||||||
Value & v, const PosIdx pos, std::ostream & str, PathSet & context, bool copyToStore)
|
Value & v, const PosIdx pos, std::ostream & str, PathSet & context, bool copyToStore)
|
||||||
{
|
{
|
||||||
JSONPlaceholder out(str);
|
str << printValueAsJSON(state, strict, v, pos, context, copyToStore);
|
||||||
printValueAsJSON(state, strict, v, pos, out, context, copyToStore);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExternalValueBase::printValueAsJSON(EvalState & state, bool strict,
|
json ExternalValueBase::printValueAsJSON(EvalState & state, bool strict,
|
||||||
JSONPlaceholder & out, PathSet & context, bool copyToStore) const
|
PathSet & context, bool copyToStore) const
|
||||||
{
|
{
|
||||||
state.debugThrowLastTrace(TypeError("cannot convert %1% to JSON", showType()));
|
state.debugThrowLastTrace(TypeError("cannot convert %1% to JSON", showType()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,12 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <nlohmann/json_fwd.hpp>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
class JSONPlaceholder;
|
nlohmann::json printValueAsJSON(EvalState & state, bool strict,
|
||||||
|
Value & v, const PosIdx pos, PathSet & context, bool copyToStore = true);
|
||||||
void printValueAsJSON(EvalState & state, bool strict,
|
|
||||||
Value & v, const PosIdx pos, JSONPlaceholder & out, PathSet & context, bool copyToStore = true);
|
|
||||||
|
|
||||||
void printValueAsJSON(EvalState & state, bool strict,
|
void printValueAsJSON(EvalState & state, bool strict,
|
||||||
Value & v, const PosIdx pos, std::ostream & str, PathSet & context, bool copyToStore = true);
|
Value & v, const PosIdx pos, std::ostream & str, PathSet & context, bool copyToStore = true);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#if HAVE_BOEHMGC
|
#if HAVE_BOEHMGC
|
||||||
#include <gc/gc_allocator.h>
|
#include <gc/gc_allocator.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <nlohmann/json_fwd.hpp>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -62,7 +63,6 @@ class StorePath;
|
||||||
class Store;
|
class Store;
|
||||||
class EvalState;
|
class EvalState;
|
||||||
class XMLWriter;
|
class XMLWriter;
|
||||||
class JSONPlaceholder;
|
|
||||||
|
|
||||||
|
|
||||||
typedef int64_t NixInt;
|
typedef int64_t NixInt;
|
||||||
|
@ -98,8 +98,8 @@ class ExternalValueBase
|
||||||
virtual bool operator ==(const ExternalValueBase & b) const;
|
virtual bool operator ==(const ExternalValueBase & b) const;
|
||||||
|
|
||||||
/* Print the value as JSON. Defaults to unconvertable, i.e. throws an error */
|
/* Print the value as JSON. Defaults to unconvertable, i.e. throws an error */
|
||||||
virtual void printValueAsJSON(EvalState & state, bool strict,
|
virtual nlohmann::json printValueAsJSON(EvalState & state, bool strict,
|
||||||
JSONPlaceholder & out, PathSet & context, bool copyToStore = true) const;
|
PathSet & context, bool copyToStore = true) const;
|
||||||
|
|
||||||
/* Print the value as XML. Defaults to unevaluated */
|
/* Print the value as XML. Defaults to unevaluated */
|
||||||
virtual void printValueAsXML(EvalState & state, bool strict, bool location,
|
virtual void printValueAsXML(EvalState & state, bool strict, bool location,
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "remote-fs-accessor.hh"
|
#include "remote-fs-accessor.hh"
|
||||||
#include "nar-info-disk-cache.hh"
|
#include "nar-info-disk-cache.hh"
|
||||||
#include "nar-accessor.hh"
|
#include "nar-accessor.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "thread-pool.hh"
|
#include "thread-pool.hh"
|
||||||
#include "callback.hh"
|
#include "callback.hh"
|
||||||
|
|
||||||
|
@ -194,19 +193,12 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
|
||||||
/* Optionally write a JSON file containing a listing of the
|
/* Optionally write a JSON file containing a listing of the
|
||||||
contents of the NAR. */
|
contents of the NAR. */
|
||||||
if (writeNARListing) {
|
if (writeNARListing) {
|
||||||
std::ostringstream jsonOut;
|
nlohmann::json j = {
|
||||||
|
{"version", 1},
|
||||||
|
{"root", listNar(ref<FSAccessor>(narAccessor), "", true)},
|
||||||
|
};
|
||||||
|
|
||||||
{
|
upsertFile(std::string(info.path.hashPart()) + ".ls", j.dump(), "application/json");
|
||||||
JSONObject jsonRoot(jsonOut);
|
|
||||||
jsonRoot.attr("version", 1);
|
|
||||||
|
|
||||||
{
|
|
||||||
auto res = jsonRoot.placeholder("root");
|
|
||||||
listNar(res, ref<FSAccessor>(narAccessor), "", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
upsertFile(std::string(info.path.hashPart()) + ".ls", jsonOut.str(), "application/json");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Optionally maintain an index of DWARF debug info files
|
/* Optionally maintain an index of DWARF debug info files
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "finally.hh"
|
#include "finally.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "compression.hh"
|
#include "compression.hh"
|
||||||
#include "worker-protocol.hh"
|
#include "worker-protocol.hh"
|
||||||
#include "topo-sort.hh"
|
#include "topo-sort.hh"
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "finally.hh"
|
#include "finally.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "compression.hh"
|
#include "compression.hh"
|
||||||
#include "daemon.hh"
|
#include "daemon.hh"
|
||||||
#include "worker-protocol.hh"
|
#include "worker-protocol.hh"
|
||||||
|
@ -56,6 +55,7 @@
|
||||||
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "nar-accessor.hh"
|
#include "nar-accessor.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "json.hh"
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
@ -243,42 +242,43 @@ ref<FSAccessor> makeLazyNarAccessor(const std::string & listing,
|
||||||
return make_ref<NarAccessor>(listing, getNarBytes);
|
return make_ref<NarAccessor>(listing, getNarBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void listNar(JSONPlaceholder & res, ref<FSAccessor> accessor,
|
using nlohmann::json;
|
||||||
const Path & path, bool recurse)
|
json listNar(ref<FSAccessor> accessor, const Path & path, bool recurse)
|
||||||
{
|
{
|
||||||
auto st = accessor->stat(path);
|
auto st = accessor->stat(path);
|
||||||
|
|
||||||
auto obj = res.object();
|
json obj = json::object();
|
||||||
|
|
||||||
switch (st.type) {
|
switch (st.type) {
|
||||||
case FSAccessor::Type::tRegular:
|
case FSAccessor::Type::tRegular:
|
||||||
obj.attr("type", "regular");
|
obj["type"] = "regular";
|
||||||
obj.attr("size", st.fileSize);
|
obj["size"] = st.fileSize;
|
||||||
if (st.isExecutable)
|
if (st.isExecutable)
|
||||||
obj.attr("executable", true);
|
obj["executable"] = true;
|
||||||
if (st.narOffset)
|
if (st.narOffset)
|
||||||
obj.attr("narOffset", st.narOffset);
|
obj["narOffset"] = st.narOffset;
|
||||||
break;
|
break;
|
||||||
case FSAccessor::Type::tDirectory:
|
case FSAccessor::Type::tDirectory:
|
||||||
obj.attr("type", "directory");
|
obj["type"] = "directory";
|
||||||
{
|
{
|
||||||
auto res2 = obj.object("entries");
|
obj["entries"] = json::object();
|
||||||
|
json &res2 = obj["entries"];
|
||||||
for (auto & name : accessor->readDirectory(path)) {
|
for (auto & name : accessor->readDirectory(path)) {
|
||||||
if (recurse) {
|
if (recurse) {
|
||||||
auto res3 = res2.placeholder(name);
|
res2[name] = listNar(accessor, path + "/" + name, true);
|
||||||
listNar(res3, accessor, path + "/" + name, true);
|
|
||||||
} else
|
} else
|
||||||
res2.object(name);
|
res2[name] = json::object();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FSAccessor::Type::tSymlink:
|
case FSAccessor::Type::tSymlink:
|
||||||
obj.attr("type", "symlink");
|
obj["type"] = "symlink";
|
||||||
obj.attr("target", accessor->readLink(path));
|
obj["target"] = accessor->readLink(path);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw Error("path '%s' does not exist in NAR", path);
|
throw Error("path '%s' does not exist in NAR", path);
|
||||||
}
|
}
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
#include <nlohmann/json_fwd.hpp>
|
||||||
#include "fs-accessor.hh"
|
#include "fs-accessor.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
@ -24,11 +25,8 @@ ref<FSAccessor> makeLazyNarAccessor(
|
||||||
const std::string & listing,
|
const std::string & listing,
|
||||||
GetNarBytes getNarBytes);
|
GetNarBytes getNarBytes);
|
||||||
|
|
||||||
class JSONPlaceholder;
|
|
||||||
|
|
||||||
/* Write a JSON representation of the contents of a NAR (except file
|
/* Write a JSON representation of the contents of a NAR (except file
|
||||||
contents). */
|
contents). */
|
||||||
void listNar(JSONPlaceholder & res, ref<FSAccessor> accessor,
|
nlohmann::json listNar(ref<FSAccessor> accessor, const Path & path, bool recurse);
|
||||||
const Path & path, bool recurse);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include "json.hh"
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -144,17 +143,12 @@ std::optional<nlohmann::json> ParsedDerivation::prepareStructuredAttrs(Store & s
|
||||||
auto e = json.find("exportReferencesGraph");
|
auto e = json.find("exportReferencesGraph");
|
||||||
if (e != json.end() && e->is_object()) {
|
if (e != json.end() && e->is_object()) {
|
||||||
for (auto i = e->begin(); i != e->end(); ++i) {
|
for (auto i = e->begin(); i != e->end(); ++i) {
|
||||||
std::ostringstream str;
|
|
||||||
{
|
|
||||||
JSONPlaceholder jsonRoot(str, true);
|
|
||||||
StorePathSet storePaths;
|
StorePathSet storePaths;
|
||||||
for (auto & p : *i)
|
for (auto & p : *i)
|
||||||
storePaths.insert(store.parseStorePath(p.get<std::string>()));
|
storePaths.insert(store.parseStorePath(p.get<std::string>()));
|
||||||
store.pathInfoToJSON(jsonRoot,
|
json[i.key()] = store.pathInfoToJSON(
|
||||||
store.exportReferences(storePaths, inputPaths), false, true);
|
store.exportReferences(storePaths, inputPaths), false, true);
|
||||||
}
|
}
|
||||||
json[i.key()] = nlohmann::json::parse(str.str()); // urgh
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
#include "remote-fs-accessor.hh"
|
#include "remote-fs-accessor.hh"
|
||||||
#include "nar-accessor.hh"
|
#include "nar-accessor.hh"
|
||||||
#include "json.hh"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -38,10 +38,8 @@ ref<FSAccessor> RemoteFSAccessor::addToCache(std::string_view hashPart, std::str
|
||||||
|
|
||||||
if (cacheDir != "") {
|
if (cacheDir != "") {
|
||||||
try {
|
try {
|
||||||
std::ostringstream str;
|
nlohmann::json j = listNar(narAccessor, "", true);
|
||||||
JSONPlaceholder jsonRoot(str);
|
writeFile(makeCacheFile(hashPart, "ls"), j.dump());
|
||||||
listNar(jsonRoot, narAccessor, "", true);
|
|
||||||
writeFile(makeCacheFile(hashPart, "ls"), str.str());
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
ignoreException();
|
ignoreException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,16 @@
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "nar-info-disk-cache.hh"
|
#include "nar-info-disk-cache.hh"
|
||||||
#include "thread-pool.hh"
|
#include "thread-pool.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "url.hh"
|
#include "url.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "callback.hh"
|
#include "callback.hh"
|
||||||
#include "remote-store.hh"
|
#include "remote-store.hh"
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
|
@ -838,56 +840,53 @@ StorePathSet Store::exportReferences(const StorePathSet & storePaths, const Stor
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json Store::pathInfoToJSON(const StorePathSet & storePaths,
|
||||||
void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const StorePathSet & storePaths,
|
|
||||||
bool includeImpureInfo, bool showClosureSize,
|
bool includeImpureInfo, bool showClosureSize,
|
||||||
Base hashBase,
|
Base hashBase,
|
||||||
AllowInvalidFlag allowInvalid)
|
AllowInvalidFlag allowInvalid)
|
||||||
{
|
{
|
||||||
auto jsonList = jsonOut.list();
|
json::array_t jsonList = json::array();
|
||||||
|
|
||||||
for (auto & storePath : storePaths) {
|
for (auto & storePath : storePaths) {
|
||||||
auto jsonPath = jsonList.object();
|
auto& jsonPath = jsonList.emplace_back(json::object());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto info = queryPathInfo(storePath);
|
auto info = queryPathInfo(storePath);
|
||||||
|
|
||||||
jsonPath.attr("path", printStorePath(info->path));
|
jsonPath["path"] = printStorePath(info->path);
|
||||||
jsonPath
|
jsonPath["narHash"] = info->narHash.to_string(hashBase, true);
|
||||||
.attr("narHash", info->narHash.to_string(hashBase, true))
|
jsonPath["narSize"] = info->narSize;
|
||||||
.attr("narSize", info->narSize);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
auto jsonRefs = jsonPath.list("references");
|
auto& jsonRefs = (jsonPath["references"] = json::array());
|
||||||
for (auto & ref : info->references)
|
for (auto & ref : info->references)
|
||||||
jsonRefs.elem(printStorePath(ref));
|
jsonRefs.emplace_back(printStorePath(ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->ca)
|
if (info->ca)
|
||||||
jsonPath.attr("ca", renderContentAddress(info->ca));
|
jsonPath["ca"] = renderContentAddress(info->ca);
|
||||||
|
|
||||||
std::pair<uint64_t, uint64_t> closureSizes;
|
std::pair<uint64_t, uint64_t> closureSizes;
|
||||||
|
|
||||||
if (showClosureSize) {
|
if (showClosureSize) {
|
||||||
closureSizes = getClosureSize(info->path);
|
closureSizes = getClosureSize(info->path);
|
||||||
jsonPath.attr("closureSize", closureSizes.first);
|
jsonPath["closureSize"] = closureSizes.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeImpureInfo) {
|
if (includeImpureInfo) {
|
||||||
|
|
||||||
if (info->deriver)
|
if (info->deriver)
|
||||||
jsonPath.attr("deriver", printStorePath(*info->deriver));
|
jsonPath["deriver"] = printStorePath(*info->deriver);
|
||||||
|
|
||||||
if (info->registrationTime)
|
if (info->registrationTime)
|
||||||
jsonPath.attr("registrationTime", info->registrationTime);
|
jsonPath["registrationTime"] = info->registrationTime;
|
||||||
|
|
||||||
if (info->ultimate)
|
if (info->ultimate)
|
||||||
jsonPath.attr("ultimate", info->ultimate);
|
jsonPath["ultimate"] = info->ultimate;
|
||||||
|
|
||||||
if (!info->sigs.empty()) {
|
if (!info->sigs.empty()) {
|
||||||
auto jsonSigs = jsonPath.list("signatures");
|
|
||||||
for (auto & sig : info->sigs)
|
for (auto & sig : info->sigs)
|
||||||
jsonSigs.elem(sig);
|
jsonPath["signatures"].push_back(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto narInfo = std::dynamic_pointer_cast<const NarInfo>(
|
auto narInfo = std::dynamic_pointer_cast<const NarInfo>(
|
||||||
|
@ -895,21 +894,22 @@ void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const StorePathSet & store
|
||||||
|
|
||||||
if (narInfo) {
|
if (narInfo) {
|
||||||
if (!narInfo->url.empty())
|
if (!narInfo->url.empty())
|
||||||
jsonPath.attr("url", narInfo->url);
|
jsonPath["url"] = narInfo->url;
|
||||||
if (narInfo->fileHash)
|
if (narInfo->fileHash)
|
||||||
jsonPath.attr("downloadHash", narInfo->fileHash->to_string(hashBase, true));
|
jsonPath["downloadHash"] = narInfo->fileHash->to_string(hashBase, true);
|
||||||
if (narInfo->fileSize)
|
if (narInfo->fileSize)
|
||||||
jsonPath.attr("downloadSize", narInfo->fileSize);
|
jsonPath["downloadSize"] = narInfo->fileSize;
|
||||||
if (showClosureSize)
|
if (showClosureSize)
|
||||||
jsonPath.attr("closureDownloadSize", closureSizes.second);
|
jsonPath["closureDownloadSize"] = closureSizes.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (InvalidPath &) {
|
} catch (InvalidPath &) {
|
||||||
jsonPath.attr("path", printStorePath(storePath));
|
jsonPath["path"] = printStorePath(storePath);
|
||||||
jsonPath.attr("valid", false);
|
jsonPath["valid"] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return jsonList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "path-info.hh"
|
#include "path-info.hh"
|
||||||
#include "repair-flag.hh"
|
#include "repair-flag.hh"
|
||||||
|
|
||||||
|
#include <nlohmann/json_fwd.hpp>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -68,7 +69,6 @@ struct Derivation;
|
||||||
class FSAccessor;
|
class FSAccessor;
|
||||||
class NarInfoDiskCache;
|
class NarInfoDiskCache;
|
||||||
class Store;
|
class Store;
|
||||||
class JSONPlaceholder;
|
|
||||||
|
|
||||||
|
|
||||||
enum CheckSigsFlag : bool { NoCheckSigs = false, CheckSigs = true };
|
enum CheckSigsFlag : bool { NoCheckSigs = false, CheckSigs = true };
|
||||||
|
@ -512,7 +512,7 @@ public:
|
||||||
variable elements such as the registration time are
|
variable elements such as the registration time are
|
||||||
included. If ‘showClosureSize’ is true, the closure size of
|
included. If ‘showClosureSize’ is true, the closure size of
|
||||||
each path is included. */
|
each path is included. */
|
||||||
void pathInfoToJSON(JSONPlaceholder & jsonOut, const StorePathSet & storePaths,
|
nlohmann::json pathInfoToJSON(const StorePathSet & storePaths,
|
||||||
bool includeImpureInfo, bool showClosureSize,
|
bool includeImpureInfo, bool showClosureSize,
|
||||||
Base hashBase = Base32,
|
Base hashBase = Base32,
|
||||||
AllowInvalidFlag allowInvalid = DisallowInvalid);
|
AllowInvalidFlag allowInvalid = DisallowInvalid);
|
||||||
|
|
|
@ -1,203 +0,0 @@
|
||||||
#include "json.hh"
|
|
||||||
|
|
||||||
#include <iomanip>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace nix {
|
|
||||||
|
|
||||||
template<>
|
|
||||||
void toJSON<std::string_view>(std::ostream & str, const std::string_view & s)
|
|
||||||
{
|
|
||||||
constexpr size_t BUF_SIZE = 4096;
|
|
||||||
char buf[BUF_SIZE + 7]; // BUF_SIZE + largest single sequence of puts
|
|
||||||
size_t bufPos = 0;
|
|
||||||
|
|
||||||
const auto flush = [&] {
|
|
||||||
str.write(buf, bufPos);
|
|
||||||
bufPos = 0;
|
|
||||||
};
|
|
||||||
const auto put = [&] (char c) {
|
|
||||||
buf[bufPos++] = c;
|
|
||||||
};
|
|
||||||
|
|
||||||
put('"');
|
|
||||||
for (auto i = s.begin(); i != s.end(); i++) {
|
|
||||||
if (bufPos >= BUF_SIZE) flush();
|
|
||||||
if (*i == '\"' || *i == '\\') { put('\\'); put(*i); }
|
|
||||||
else if (*i == '\n') { put('\\'); put('n'); }
|
|
||||||
else if (*i == '\r') { put('\\'); put('r'); }
|
|
||||||
else if (*i == '\t') { put('\\'); put('t'); }
|
|
||||||
else if (*i >= 0 && *i < 32) {
|
|
||||||
const char hex[17] = "0123456789abcdef";
|
|
||||||
put('\\');
|
|
||||||
put('u');
|
|
||||||
put(hex[(uint16_t(*i) >> 12) & 0xf]);
|
|
||||||
put(hex[(uint16_t(*i) >> 8) & 0xf]);
|
|
||||||
put(hex[(uint16_t(*i) >> 4) & 0xf]);
|
|
||||||
put(hex[(uint16_t(*i) >> 0) & 0xf]);
|
|
||||||
}
|
|
||||||
else put(*i);
|
|
||||||
}
|
|
||||||
put('"');
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void toJSON(std::ostream & str, const char * s)
|
|
||||||
{
|
|
||||||
if (!s) str << "null"; else toJSON(str, std::string_view(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> void toJSON<int>(std::ostream & str, const int & n) { str << n; }
|
|
||||||
template<> void toJSON<unsigned int>(std::ostream & str, const unsigned int & n) { str << n; }
|
|
||||||
template<> void toJSON<long>(std::ostream & str, const long & n) { str << n; }
|
|
||||||
template<> void toJSON<unsigned long>(std::ostream & str, const unsigned long & n) { str << n; }
|
|
||||||
template<> void toJSON<long long>(std::ostream & str, const long long & n) { str << n; }
|
|
||||||
template<> void toJSON<unsigned long long>(std::ostream & str, const unsigned long long & n) { str << n; }
|
|
||||||
template<> void toJSON<float>(std::ostream & str, const float & n) { str << n; }
|
|
||||||
template<> void toJSON<double>(std::ostream & str, const double & n) { str << n; }
|
|
||||||
template<> void toJSON<std::string>(std::ostream & str, const std::string & s) { toJSON(str, (std::string_view) s); }
|
|
||||||
|
|
||||||
template<> void toJSON<bool>(std::ostream & str, const bool & b)
|
|
||||||
{
|
|
||||||
str << (b ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> void toJSON<std::nullptr_t>(std::ostream & str, const std::nullptr_t & b)
|
|
||||||
{
|
|
||||||
str << "null";
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONWriter::JSONWriter(std::ostream & str, bool indent)
|
|
||||||
: state(new JSONState(str, indent))
|
|
||||||
{
|
|
||||||
state->stack++;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONWriter::JSONWriter(JSONState * state)
|
|
||||||
: state(state)
|
|
||||||
{
|
|
||||||
state->stack++;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONWriter::~JSONWriter()
|
|
||||||
{
|
|
||||||
if (state) {
|
|
||||||
assertActive();
|
|
||||||
state->stack--;
|
|
||||||
if (state->stack == 0) delete state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONWriter::comma()
|
|
||||||
{
|
|
||||||
assertActive();
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
state->str << ',';
|
|
||||||
}
|
|
||||||
if (state->indent) indent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONWriter::indent()
|
|
||||||
{
|
|
||||||
state->str << '\n' << std::string(state->depth * 2, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONList::open()
|
|
||||||
{
|
|
||||||
state->depth++;
|
|
||||||
state->str << '[';
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONList::~JSONList()
|
|
||||||
{
|
|
||||||
state->depth--;
|
|
||||||
if (state->indent && !first) indent();
|
|
||||||
state->str << "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONList JSONList::list()
|
|
||||||
{
|
|
||||||
comma();
|
|
||||||
return JSONList(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject JSONList::object()
|
|
||||||
{
|
|
||||||
comma();
|
|
||||||
return JSONObject(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONPlaceholder JSONList::placeholder()
|
|
||||||
{
|
|
||||||
comma();
|
|
||||||
return JSONPlaceholder(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONObject::open()
|
|
||||||
{
|
|
||||||
state->depth++;
|
|
||||||
state->str << '{';
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject::~JSONObject()
|
|
||||||
{
|
|
||||||
if (state) {
|
|
||||||
state->depth--;
|
|
||||||
if (state->indent && !first) indent();
|
|
||||||
state->str << "}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JSONObject::attr(std::string_view s)
|
|
||||||
{
|
|
||||||
comma();
|
|
||||||
toJSON(state->str, s);
|
|
||||||
state->str << ':';
|
|
||||||
if (state->indent) state->str << ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONList JSONObject::list(std::string_view name)
|
|
||||||
{
|
|
||||||
attr(name);
|
|
||||||
return JSONList(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject JSONObject::object(std::string_view name)
|
|
||||||
{
|
|
||||||
attr(name);
|
|
||||||
return JSONObject(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONPlaceholder JSONObject::placeholder(std::string_view name)
|
|
||||||
{
|
|
||||||
attr(name);
|
|
||||||
return JSONPlaceholder(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONList JSONPlaceholder::list()
|
|
||||||
{
|
|
||||||
assertValid();
|
|
||||||
first = false;
|
|
||||||
return JSONList(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject JSONPlaceholder::object()
|
|
||||||
{
|
|
||||||
assertValid();
|
|
||||||
first = false;
|
|
||||||
return JSONObject(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONPlaceholder::~JSONPlaceholder()
|
|
||||||
{
|
|
||||||
if (first) {
|
|
||||||
assert(std::uncaught_exceptions());
|
|
||||||
if (state->stack != 0)
|
|
||||||
write(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,185 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
namespace nix {
|
|
||||||
|
|
||||||
void toJSON(std::ostream & str, const char * s);
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void toJSON(std::ostream & str, const T & n);
|
|
||||||
|
|
||||||
class JSONWriter
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
struct JSONState
|
|
||||||
{
|
|
||||||
std::ostream & str;
|
|
||||||
bool indent;
|
|
||||||
size_t depth = 0;
|
|
||||||
size_t stack = 0;
|
|
||||||
JSONState(std::ostream & str, bool indent) : str(str), indent(indent) { }
|
|
||||||
~JSONState()
|
|
||||||
{
|
|
||||||
assert(stack == 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
JSONState * state;
|
|
||||||
|
|
||||||
bool first = true;
|
|
||||||
|
|
||||||
JSONWriter(std::ostream & str, bool indent);
|
|
||||||
|
|
||||||
JSONWriter(JSONState * state);
|
|
||||||
|
|
||||||
~JSONWriter();
|
|
||||||
|
|
||||||
void assertActive()
|
|
||||||
{
|
|
||||||
assert(state->stack != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void comma();
|
|
||||||
|
|
||||||
void indent();
|
|
||||||
};
|
|
||||||
|
|
||||||
class JSONObject;
|
|
||||||
class JSONPlaceholder;
|
|
||||||
|
|
||||||
class JSONList : JSONWriter
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
friend class JSONObject;
|
|
||||||
friend class JSONPlaceholder;
|
|
||||||
|
|
||||||
void open();
|
|
||||||
|
|
||||||
JSONList(JSONState * state)
|
|
||||||
: JSONWriter(state)
|
|
||||||
{
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
JSONList(std::ostream & str, bool indent = false)
|
|
||||||
: JSONWriter(str, indent)
|
|
||||||
{
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
|
|
||||||
~JSONList();
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
JSONList & elem(const T & v)
|
|
||||||
{
|
|
||||||
comma();
|
|
||||||
toJSON(state->str, v);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONList list();
|
|
||||||
|
|
||||||
JSONObject object();
|
|
||||||
|
|
||||||
JSONPlaceholder placeholder();
|
|
||||||
};
|
|
||||||
|
|
||||||
class JSONObject : JSONWriter
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
friend class JSONList;
|
|
||||||
friend class JSONPlaceholder;
|
|
||||||
|
|
||||||
void open();
|
|
||||||
|
|
||||||
JSONObject(JSONState * state)
|
|
||||||
: JSONWriter(state)
|
|
||||||
{
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
|
|
||||||
void attr(std::string_view s);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
JSONObject(std::ostream & str, bool indent = false)
|
|
||||||
: JSONWriter(str, indent)
|
|
||||||
{
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject(const JSONObject & obj) = delete;
|
|
||||||
|
|
||||||
JSONObject(JSONObject && obj)
|
|
||||||
: JSONWriter(obj.state)
|
|
||||||
{
|
|
||||||
obj.state = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
~JSONObject();
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
JSONObject & attr(std::string_view name, const T & v)
|
|
||||||
{
|
|
||||||
attr(name);
|
|
||||||
toJSON(state->str, v);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONList list(std::string_view name);
|
|
||||||
|
|
||||||
JSONObject object(std::string_view name);
|
|
||||||
|
|
||||||
JSONPlaceholder placeholder(std::string_view name);
|
|
||||||
};
|
|
||||||
|
|
||||||
class JSONPlaceholder : JSONWriter
|
|
||||||
{
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
friend class JSONList;
|
|
||||||
friend class JSONObject;
|
|
||||||
|
|
||||||
JSONPlaceholder(JSONState * state)
|
|
||||||
: JSONWriter(state)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void assertValid()
|
|
||||||
{
|
|
||||||
assertActive();
|
|
||||||
assert(first);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
JSONPlaceholder(std::ostream & str, bool indent = false)
|
|
||||||
: JSONWriter(str, indent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~JSONPlaceholder();
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void write(const T & v)
|
|
||||||
{
|
|
||||||
assertValid();
|
|
||||||
first = false;
|
|
||||||
toJSON(state->str, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONList list();
|
|
||||||
|
|
||||||
JSONObject object();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,193 +0,0 @@
|
||||||
#include "json.hh"
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace nix {
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* toJSON
|
|
||||||
* --------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
TEST(toJSON, quotesCharPtr) {
|
|
||||||
const char* input = "test";
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, input);
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "\"test\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, quotesStdString) {
|
|
||||||
std::string input = "test";
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, input);
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "\"test\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, convertsNullptrtoNull) {
|
|
||||||
auto input = nullptr;
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, input);
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "null");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, convertsNullToNull) {
|
|
||||||
const char* input = 0;
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, input);
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "null");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST(toJSON, convertsFloat) {
|
|
||||||
auto input = 1.024f;
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, input);
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "1.024");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, convertsDouble) {
|
|
||||||
const double input = 1.024;
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, input);
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "1.024");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, convertsBool) {
|
|
||||||
auto input = false;
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, input);
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, quotesTab) {
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, "\t");
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "\"\\t\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, quotesNewline) {
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, "\n");
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "\"\\n\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, quotesCreturn) {
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, "\r");
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "\"\\r\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, quotesCreturnNewLine) {
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, "\r\n");
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "\"\\r\\n\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, quotesDoublequotes) {
|
|
||||||
std::stringstream out;
|
|
||||||
toJSON(out, "\"");
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "\"\\\"\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(toJSON, substringEscape) {
|
|
||||||
std::stringstream out;
|
|
||||||
std::string_view s = "foo\t";
|
|
||||||
toJSON(out, s.substr(3));
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), "\"\\t\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* JSONObject
|
|
||||||
* --------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
TEST(JSONObject, emptyObject) {
|
|
||||||
std::stringstream out;
|
|
||||||
{
|
|
||||||
JSONObject t(out);
|
|
||||||
}
|
|
||||||
ASSERT_EQ(out.str(), "{}");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(JSONObject, objectWithList) {
|
|
||||||
std::stringstream out;
|
|
||||||
{
|
|
||||||
JSONObject t(out);
|
|
||||||
auto l = t.list("list");
|
|
||||||
l.elem("element");
|
|
||||||
}
|
|
||||||
ASSERT_EQ(out.str(), R"#({"list":["element"]})#");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(JSONObject, objectWithListIndent) {
|
|
||||||
std::stringstream out;
|
|
||||||
{
|
|
||||||
JSONObject t(out, true);
|
|
||||||
auto l = t.list("list");
|
|
||||||
l.elem("element");
|
|
||||||
}
|
|
||||||
ASSERT_EQ(out.str(),
|
|
||||||
R"#({
|
|
||||||
"list": [
|
|
||||||
"element"
|
|
||||||
]
|
|
||||||
})#");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(JSONObject, objectWithPlaceholderAndList) {
|
|
||||||
std::stringstream out;
|
|
||||||
{
|
|
||||||
JSONObject t(out);
|
|
||||||
auto l = t.placeholder("list");
|
|
||||||
l.list().elem("element");
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), R"#({"list":["element"]})#");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(JSONObject, objectWithPlaceholderAndObject) {
|
|
||||||
std::stringstream out;
|
|
||||||
{
|
|
||||||
JSONObject t(out);
|
|
||||||
auto l = t.placeholder("object");
|
|
||||||
l.object().attr("key", "value");
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_EQ(out.str(), R"#({"object":{"key":"value"}})#");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* JSONList
|
|
||||||
* --------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
TEST(JSONList, empty) {
|
|
||||||
std::stringstream out;
|
|
||||||
{
|
|
||||||
JSONList l(out);
|
|
||||||
}
|
|
||||||
ASSERT_EQ(out.str(), R"#([])#");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(JSONList, withElements) {
|
|
||||||
std::stringstream out;
|
|
||||||
{
|
|
||||||
JSONList l(out);
|
|
||||||
l.elem("one");
|
|
||||||
l.object();
|
|
||||||
l.placeholder().write("three");
|
|
||||||
}
|
|
||||||
ASSERT_EQ(out.str(), R"#(["one",{},"three"])#");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include "local-fs-store.hh"
|
#include "local-fs-store.hh"
|
||||||
#include "user-env.hh"
|
#include "user-env.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "value-to-json.hh"
|
#include "value-to-json.hh"
|
||||||
#include "xml-writer.hh"
|
#include "xml-writer.hh"
|
||||||
#include "legacy.hh"
|
#include "legacy.hh"
|
||||||
|
@ -26,6 +25,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
using std::cout;
|
using std::cout;
|
||||||
|
@ -911,43 +911,47 @@ static VersionDiff compareVersionAgainstSet(
|
||||||
|
|
||||||
static void queryJSON(Globals & globals, std::vector<DrvInfo> & elems, bool printOutPath, bool printMeta)
|
static void queryJSON(Globals & globals, std::vector<DrvInfo> & elems, bool printOutPath, bool printMeta)
|
||||||
{
|
{
|
||||||
JSONObject topObj(cout, true);
|
using nlohmann::json;
|
||||||
|
json topObj = json::object();
|
||||||
for (auto & i : elems) {
|
for (auto & i : elems) {
|
||||||
try {
|
try {
|
||||||
if (i.hasFailed()) continue;
|
if (i.hasFailed()) continue;
|
||||||
|
|
||||||
JSONObject pkgObj = topObj.object(i.attrPath);
|
|
||||||
|
|
||||||
auto drvName = DrvName(i.queryName());
|
auto drvName = DrvName(i.queryName());
|
||||||
pkgObj.attr("name", drvName.fullName);
|
json &pkgObj = topObj[i.attrPath];
|
||||||
pkgObj.attr("pname", drvName.name);
|
pkgObj = {
|
||||||
pkgObj.attr("version", drvName.version);
|
{"name", drvName.fullName},
|
||||||
pkgObj.attr("system", i.querySystem());
|
{"pname", drvName.name},
|
||||||
pkgObj.attr("outputName", i.queryOutputName());
|
{"version", drvName.version},
|
||||||
|
{"system", i.querySystem()},
|
||||||
|
{"outputName", i.queryOutputName()},
|
||||||
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
DrvInfo::Outputs outputs = i.queryOutputs(printOutPath);
|
DrvInfo::Outputs outputs = i.queryOutputs(printOutPath);
|
||||||
JSONObject outputObj = pkgObj.object("outputs");
|
json &outputObj = pkgObj["outputs"];
|
||||||
|
outputObj = json::object();
|
||||||
for (auto & j : outputs) {
|
for (auto & j : outputs) {
|
||||||
if (j.second)
|
if (j.second)
|
||||||
outputObj.attr(j.first, globals.state->store->printStorePath(*j.second));
|
outputObj[j.first] = globals.state->store->printStorePath(*j.second);
|
||||||
else
|
else
|
||||||
outputObj.attr(j.first, nullptr);
|
outputObj[j.first] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (printMeta) {
|
if (printMeta) {
|
||||||
JSONObject metaObj = pkgObj.object("meta");
|
json &metaObj = pkgObj["meta"];
|
||||||
|
metaObj = json::object();
|
||||||
StringSet metaNames = i.queryMetaNames();
|
StringSet metaNames = i.queryMetaNames();
|
||||||
for (auto & j : metaNames) {
|
for (auto & j : metaNames) {
|
||||||
Value * v = i.queryMeta(j);
|
Value * v = i.queryMeta(j);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
printError("derivation '%s' has invalid meta attribute '%s'", i.queryName(), j);
|
printError("derivation '%s' has invalid meta attribute '%s'", i.queryName(), j);
|
||||||
metaObj.attr(j, nullptr);
|
metaObj[j] = nullptr;
|
||||||
} else {
|
} else {
|
||||||
auto placeholder = metaObj.placeholder(j);
|
|
||||||
PathSet context;
|
PathSet context;
|
||||||
printValueAsJSON(*globals.state, true, *v, noPos, placeholder, context);
|
metaObj[j] = printValueAsJSON(*globals.state, true, *v, noPos, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -958,6 +962,7 @@ static void queryJSON(Globals & globals, std::vector<DrvInfo> & elems, bool prin
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::cout << topObj.dump(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,11 @@
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "value-to-json.hh"
|
#include "value-to-json.hh"
|
||||||
#include "progress-bar.hh"
|
#include "progress-bar.hh"
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
struct CmdEval : MixJSON, InstallableCommand
|
struct CmdEval : MixJSON, InstallableCommand
|
||||||
|
@ -115,9 +116,7 @@ struct CmdEval : MixJSON, InstallableCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (json) {
|
else if (json) {
|
||||||
JSONPlaceholder jsonOut(std::cout);
|
std::cout << printValueAsJSON(*state, true, *v, pos, context, false).dump() << std::endl;
|
||||||
printValueAsJSON(*state, true, *v, pos, jsonOut, context, false);
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include "attr-path.hh"
|
#include "attr-path.hh"
|
||||||
#include "fetchers.hh"
|
#include "fetchers.hh"
|
||||||
#include "registry.hh"
|
#include "registry.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "eval-cache.hh"
|
#include "eval-cache.hh"
|
||||||
#include "markdown.hh"
|
#include "markdown.hh"
|
||||||
|
|
||||||
|
@ -21,6 +20,7 @@
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
using namespace nix::flake;
|
using namespace nix::flake;
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
class FlakeCommand : virtual Args, public MixFlakeOptions
|
class FlakeCommand : virtual Args, public MixFlakeOptions
|
||||||
{
|
{
|
||||||
|
@ -917,35 +917,44 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun
|
||||||
{
|
{
|
||||||
auto flake = lockFlake();
|
auto flake = lockFlake();
|
||||||
|
|
||||||
auto jsonRoot = json ? std::optional<JSONObject>(std::cout) : std::nullopt;
|
|
||||||
|
|
||||||
StorePathSet sources;
|
StorePathSet sources;
|
||||||
|
|
||||||
sources.insert(flake.flake.sourceInfo->storePath);
|
sources.insert(flake.flake.sourceInfo->storePath);
|
||||||
if (jsonRoot)
|
|
||||||
jsonRoot->attr("path", store->printStorePath(flake.flake.sourceInfo->storePath));
|
|
||||||
|
|
||||||
// FIXME: use graph output, handle cycles.
|
// FIXME: use graph output, handle cycles.
|
||||||
std::function<void(const Node & node, std::optional<JSONObject> & jsonObj)> traverse;
|
std::function<nlohmann::json(const Node & node)> traverse;
|
||||||
traverse = [&](const Node & node, std::optional<JSONObject> & jsonObj)
|
traverse = [&](const Node & node)
|
||||||
{
|
{
|
||||||
auto jsonObj2 = jsonObj ? jsonObj->object("inputs") : std::optional<JSONObject>();
|
nlohmann::json jsonObj2 = json ? json::object() : nlohmann::json(nullptr);
|
||||||
for (auto & [inputName, input] : node.inputs) {
|
for (auto & [inputName, input] : node.inputs) {
|
||||||
if (auto inputNode = std::get_if<0>(&input)) {
|
if (auto inputNode = std::get_if<0>(&input)) {
|
||||||
auto jsonObj3 = jsonObj2 ? jsonObj2->object(inputName) : std::optional<JSONObject>();
|
|
||||||
auto storePath =
|
auto storePath =
|
||||||
dryRun
|
dryRun
|
||||||
? (*inputNode)->lockedRef.input.computeStorePath(*store)
|
? (*inputNode)->lockedRef.input.computeStorePath(*store)
|
||||||
: (*inputNode)->lockedRef.input.fetch(store).first.storePath;
|
: (*inputNode)->lockedRef.input.fetch(store).first.storePath;
|
||||||
if (jsonObj3)
|
if (json) {
|
||||||
jsonObj3->attr("path", store->printStorePath(storePath));
|
auto& jsonObj3 = jsonObj2[inputName];
|
||||||
|
jsonObj3["path"] = store->printStorePath(storePath);
|
||||||
sources.insert(std::move(storePath));
|
sources.insert(std::move(storePath));
|
||||||
traverse(**inputNode, jsonObj3);
|
jsonObj3["inputs"] = traverse(**inputNode);
|
||||||
|
} else {
|
||||||
|
sources.insert(std::move(storePath));
|
||||||
|
traverse(**inputNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return jsonObj2;
|
||||||
};
|
};
|
||||||
|
|
||||||
traverse(*flake.lockFile.root, jsonRoot);
|
if (json) {
|
||||||
|
nlohmann::json jsonRoot = {
|
||||||
|
{"path", store->printStorePath(flake.flake.sourceInfo->storePath)},
|
||||||
|
{"inputs", traverse(*flake.lockFile.root)},
|
||||||
|
};
|
||||||
|
std::cout << jsonRoot.dump() << std::endl;
|
||||||
|
} else {
|
||||||
|
traverse(*flake.lockFile.root);
|
||||||
|
}
|
||||||
|
|
||||||
if (!dryRun && !dstUri.empty()) {
|
if (!dryRun && !dstUri.empty()) {
|
||||||
ref<Store> dstStore = dstUri.empty() ? openStore() : openStore(dstUri);
|
ref<Store> dstStore = dstUri.empty() ? openStore() : openStore(dstUri);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "fs-accessor.hh"
|
#include "fs-accessor.hh"
|
||||||
#include "nar-accessor.hh"
|
#include "nar-accessor.hh"
|
||||||
#include "common-args.hh"
|
#include "common-args.hh"
|
||||||
#include "json.hh"
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
|
@ -91,10 +91,9 @@ struct MixLs : virtual Args, MixJSON
|
||||||
if (path == "/") path = "";
|
if (path == "/") path = "";
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
JSONPlaceholder jsonRoot(std::cout);
|
|
||||||
if (showDirectory)
|
if (showDirectory)
|
||||||
throw UsageError("'--directory' is useless with '--json'");
|
throw UsageError("'--directory' is useless with '--json'");
|
||||||
listNar(jsonRoot, accessor, path, recursive);
|
std::cout << listNar(accessor, path, recursive);
|
||||||
} else
|
} else
|
||||||
listText(accessor);
|
listText(accessor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,13 @@
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "make-content-addressed.hh"
|
#include "make-content-addressed.hh"
|
||||||
#include "common-args.hh"
|
#include "common-args.hh"
|
||||||
#include "json.hh"
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
|
using nlohmann::json;
|
||||||
|
|
||||||
struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, MixJSON
|
struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, MixJSON
|
||||||
{
|
{
|
||||||
CmdMakeContentAddressed()
|
CmdMakeContentAddressed()
|
||||||
|
@ -25,6 +28,7 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand,
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using StorePathsCommand::run;
|
||||||
void run(ref<Store> srcStore, StorePaths && storePaths) override
|
void run(ref<Store> srcStore, StorePaths && storePaths) override
|
||||||
{
|
{
|
||||||
auto dstStore = dstUri.empty() ? openStore() : openStore(dstUri);
|
auto dstStore = dstUri.empty() ? openStore() : openStore(dstUri);
|
||||||
|
@ -33,13 +37,13 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand,
|
||||||
StorePathSet(storePaths.begin(), storePaths.end()));
|
StorePathSet(storePaths.begin(), storePaths.end()));
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
JSONObject jsonRoot(std::cout);
|
nlohmann::json jsonRewrites = json::object();
|
||||||
JSONObject jsonRewrites(jsonRoot.object("rewrites"));
|
|
||||||
for (auto & path : storePaths) {
|
for (auto & path : storePaths) {
|
||||||
auto i = remappings.find(path);
|
auto i = remappings.find(path);
|
||||||
assert(i != remappings.end());
|
assert(i != remappings.end());
|
||||||
jsonRewrites.attr(srcStore->printStorePath(path), srcStore->printStorePath(i->second));
|
jsonRewrites[srcStore->printStorePath(path)] = srcStore->printStorePath(i->second);
|
||||||
}
|
}
|
||||||
|
std::cout << json::object({"rewrites", jsonRewrites}).dump();
|
||||||
} else {
|
} else {
|
||||||
for (auto & path : storePaths) {
|
for (auto & path : storePaths) {
|
||||||
auto i = remappings.find(path);
|
auto i = remappings.find(path);
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#include "command.hh"
|
#include "command.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "common-args.hh"
|
#include "common-args.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
struct CmdPathInfo : StorePathsCommand, MixJSON
|
struct CmdPathInfo : StorePathsCommand, MixJSON
|
||||||
|
@ -86,11 +87,10 @@ struct CmdPathInfo : StorePathsCommand, MixJSON
|
||||||
pathLen = std::max(pathLen, store->printStorePath(storePath).size());
|
pathLen = std::max(pathLen, store->printStorePath(storePath).size());
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
JSONPlaceholder jsonRoot(std::cout);
|
std::cout << store->pathInfoToJSON(
|
||||||
store->pathInfoToJSON(jsonRoot,
|
|
||||||
// FIXME: preserve order?
|
// FIXME: preserve order?
|
||||||
StorePathSet(storePaths.begin(), storePaths.end()),
|
StorePathSet(storePaths.begin(), storePaths.end()),
|
||||||
true, showClosureSize, SRI, AllowInvalid);
|
true, showClosureSize, SRI, AllowInvalid).dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "names.hh"
|
#include "names.hh"
|
||||||
#include "get-drvs.hh"
|
#include "get-drvs.hh"
|
||||||
#include "common-args.hh"
|
#include "common-args.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "eval-cache.hh"
|
#include "eval-cache.hh"
|
||||||
#include "attr-path.hh"
|
#include "attr-path.hh"
|
||||||
|
@ -13,8 +12,10 @@
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
std::string wrap(std::string prefix, std::string s)
|
std::string wrap(std::string prefix, std::string s)
|
||||||
{
|
{
|
||||||
|
@ -84,7 +85,8 @@ struct CmdSearch : InstallableCommand, MixJSON
|
||||||
|
|
||||||
auto state = getEvalState();
|
auto state = getEvalState();
|
||||||
|
|
||||||
auto jsonOut = json ? std::make_unique<JSONObject>(std::cout) : nullptr;
|
std::optional<nlohmann::json> jsonOut;
|
||||||
|
if (json) jsonOut = json::object();
|
||||||
|
|
||||||
uint64_t results = 0;
|
uint64_t results = 0;
|
||||||
|
|
||||||
|
@ -151,10 +153,11 @@ struct CmdSearch : InstallableCommand, MixJSON
|
||||||
{
|
{
|
||||||
results++;
|
results++;
|
||||||
if (json) {
|
if (json) {
|
||||||
auto jsonElem = jsonOut->object(attrPath2);
|
(*jsonOut)[attrPath2] = {
|
||||||
jsonElem.attr("pname", name.name);
|
{"pname", name.name},
|
||||||
jsonElem.attr("version", name.version);
|
{"version", name.version},
|
||||||
jsonElem.attr("description", description);
|
{"description", description},
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
auto name2 = hiliteMatches(name.name, nameMatches, ANSI_GREEN, "\e[0;2m");
|
auto name2 = hiliteMatches(name.name, nameMatches, ANSI_GREEN, "\e[0;2m");
|
||||||
if (results > 1) logger->cout("");
|
if (results > 1) logger->cout("");
|
||||||
|
@ -193,6 +196,10 @@ struct CmdSearch : InstallableCommand, MixJSON
|
||||||
for (auto & cursor : installable->getCursors(*state))
|
for (auto & cursor : installable->getCursors(*state))
|
||||||
visit(*cursor, cursor->getAttrPath(), true);
|
visit(*cursor, cursor->getAttrPath(), true);
|
||||||
|
|
||||||
|
if (json) {
|
||||||
|
std::cout << jsonOut->dump() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
if (!json && !results)
|
if (!json && !results)
|
||||||
throw Error("no results for the given search term(s)!");
|
throw Error("no results for the given search term(s)!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
#include "common-args.hh"
|
#include "common-args.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
#include "json.hh"
|
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
struct CmdShowDerivation : InstallablesCommand
|
struct CmdShowDerivation : InstallablesCommand
|
||||||
{
|
{
|
||||||
|
@ -48,77 +49,63 @@ struct CmdShowDerivation : InstallablesCommand
|
||||||
drvPaths = std::move(closure);
|
drvPaths = std::move(closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
json jsonRoot = json::object();
|
||||||
|
|
||||||
JSONObject jsonRoot(std::cout, true);
|
|
||||||
|
|
||||||
for (auto & drvPath : drvPaths) {
|
for (auto & drvPath : drvPaths) {
|
||||||
if (!drvPath.isDerivation()) continue;
|
if (!drvPath.isDerivation()) continue;
|
||||||
|
|
||||||
auto drvObj(jsonRoot.object(store->printStorePath(drvPath)));
|
json& drvObj = jsonRoot[store->printStorePath(drvPath)];
|
||||||
|
|
||||||
auto drv = store->readDerivation(drvPath);
|
auto drv = store->readDerivation(drvPath);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto outputsObj(drvObj.object("outputs"));
|
json& outputsObj = drvObj["outputs"];
|
||||||
|
outputsObj = json::object();
|
||||||
for (auto & [_outputName, output] : drv.outputs) {
|
for (auto & [_outputName, output] : drv.outputs) {
|
||||||
auto & outputName = _outputName; // work around clang bug
|
auto & outputName = _outputName; // work around clang bug
|
||||||
auto outputObj { outputsObj.object(outputName) };
|
auto& outputObj = outputsObj[outputName];
|
||||||
|
outputObj = json::object();
|
||||||
std::visit(overloaded {
|
std::visit(overloaded {
|
||||||
[&](const DerivationOutput::InputAddressed & doi) {
|
[&](const DerivationOutput::InputAddressed & doi) {
|
||||||
outputObj.attr("path", store->printStorePath(doi.path));
|
outputObj["path"] = store->printStorePath(doi.path);
|
||||||
},
|
},
|
||||||
[&](const DerivationOutput::CAFixed & dof) {
|
[&](const DerivationOutput::CAFixed & dof) {
|
||||||
outputObj.attr("path", store->printStorePath(dof.path(*store, drv.name, outputName)));
|
outputObj["path"] = store->printStorePath(dof.path(*store, drv.name, outputName));
|
||||||
outputObj.attr("hashAlgo", dof.hash.printMethodAlgo());
|
outputObj["hashAlgo"] = dof.hash.printMethodAlgo();
|
||||||
outputObj.attr("hash", dof.hash.hash.to_string(Base16, false));
|
outputObj["hash"] = dof.hash.hash.to_string(Base16, false);
|
||||||
},
|
},
|
||||||
[&](const DerivationOutput::CAFloating & dof) {
|
[&](const DerivationOutput::CAFloating & dof) {
|
||||||
outputObj.attr("hashAlgo", makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType));
|
outputObj["hashAlgo"] = makeFileIngestionPrefix(dof.method) + printHashType(dof.hashType);
|
||||||
},
|
},
|
||||||
[&](const DerivationOutput::Deferred &) {},
|
[&](const DerivationOutput::Deferred &) {},
|
||||||
[&](const DerivationOutput::Impure & doi) {
|
[&](const DerivationOutput::Impure & doi) {
|
||||||
outputObj.attr("hashAlgo", makeFileIngestionPrefix(doi.method) + printHashType(doi.hashType));
|
outputObj["hashAlgo"] = makeFileIngestionPrefix(doi.method) + printHashType(doi.hashType);
|
||||||
outputObj.attr("impure", true);
|
outputObj["impure"] = true;
|
||||||
},
|
},
|
||||||
}, output.raw());
|
}, output.raw());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto inputsList(drvObj.list("inputSrcs"));
|
auto& inputsList = drvObj["inputSrcs"];
|
||||||
|
inputsList = json::array();
|
||||||
for (auto & input : drv.inputSrcs)
|
for (auto & input : drv.inputSrcs)
|
||||||
inputsList.elem(store->printStorePath(input));
|
inputsList.emplace_back(store->printStorePath(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto inputDrvsObj(drvObj.object("inputDrvs"));
|
auto& inputDrvsObj = drvObj["inputDrvs"];
|
||||||
for (auto & input : drv.inputDrvs) {
|
inputDrvsObj = json::object();
|
||||||
auto inputList(inputDrvsObj.list(store->printStorePath(input.first)));
|
for (auto & input : drv.inputDrvs)
|
||||||
for (auto & outputId : input.second)
|
inputDrvsObj[store->printStorePath(input.first)] = input.second;
|
||||||
inputList.elem(outputId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drvObj.attr("system", drv.platform);
|
drvObj["system"] = drv.platform;
|
||||||
drvObj.attr("builder", drv.builder);
|
drvObj["builder"] = drv.builder;
|
||||||
|
drvObj["args"] = drv.args;
|
||||||
{
|
drvObj["env"] = drv.env;
|
||||||
auto argsList(drvObj.list("args"));
|
|
||||||
for (auto & arg : drv.args)
|
|
||||||
argsList.elem(arg);
|
|
||||||
}
|
}
|
||||||
|
std::cout << jsonRoot.dump(2) << std::endl;
|
||||||
{
|
|
||||||
auto envObj(drvObj.object("env"));
|
|
||||||
for (auto & var : drv.env)
|
|
||||||
envObj.attr(var.first, var.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "\n";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue