diff --git a/src/libstore/build.cc b/src/libstore/build.cc index d76c8d172..7fb5271f4 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -10,6 +10,7 @@ #include "builtins.hh" #include "finally.hh" #include "compression.hh" +#include "json.hh" #include #include @@ -2273,9 +2274,18 @@ void DerivationGoal::doExportReferencesGraph() } } - /* Write closure info to `fileName'. */ + /* Write closure info to . */ writeFile(tmpDir + "/" + fileName, worker.store.makeValidityRegistration(paths, false, false)); + + /* Write a more comprehensive JSON serialisation to + .json. */ + std::ostringstream str; + { + JSONPlaceholder jsonRoot(str, true); + worker.store.pathInfoToJSON(jsonRoot, paths, false, true); + } + writeFile(tmpDir + "/" + fileName + ".json", str.str()); } } diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 8fdd62771..a42d11834 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -4,6 +4,7 @@ #include "util.hh" #include "nar-info-disk-cache.hh" #include "thread-pool.hh" +#include "json.hh" #include @@ -439,6 +440,64 @@ string Store::makeValidityRegistration(const PathSet & paths, } +void Store::pathInfoToJSON(JSONPlaceholder & jsonOut, const PathSet & storePaths, + bool includeImpureInfo, bool showClosureSize) +{ + auto jsonList = jsonOut.list(); + + for (auto storePath : storePaths) { + auto info = queryPathInfo(storePath); + storePath = info->path; + + auto jsonPath = jsonList.object(); + jsonPath + .attr("path", storePath) + .attr("narHash", info->narHash.to_string()) + .attr("narSize", info->narSize); + + { + auto jsonRefs = jsonPath.list("references"); + for (auto & ref : info->references) + jsonRefs.elem(ref); + } + + if (info->ca != "") + jsonPath.attr("ca", info->ca); + + if (showClosureSize) + jsonPath.attr("closureSize", getClosureSize(storePath)); + + if (!includeImpureInfo) continue; + + if (info->deriver != "") + jsonPath.attr("deriver", info->deriver); + + if (info->registrationTime) + jsonPath.attr("registrationTime", info->registrationTime); + + if (info->ultimate) + jsonPath.attr("ultimate", info->ultimate); + + if (!info->sigs.empty()) { + auto jsonSigs = jsonPath.list("signatures"); + for (auto & sig : info->sigs) + jsonSigs.elem(sig); + } + } +} + + +unsigned long long Store::getClosureSize(const Path & storePath) +{ + unsigned long long totalSize = 0; + PathSet closure; + computeFSClosure(storePath, closure, false, false); + for (auto & p : closure) + totalSize += queryPathInfo(p)->narSize; + return totalSize; +} + + const Store::Stats & Store::getStats() { { diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index ec3bf5a6f..3fee99907 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -22,6 +22,7 @@ struct Derivation; class FSAccessor; class NarInfoDiskCache; class Store; +class JSONPlaceholder; /* Size of the hash part of store paths, in base-32 characters. */ @@ -469,6 +470,19 @@ public: string makeValidityRegistration(const PathSet & paths, bool showDerivers, bool showHash); + /* Write a JSON representation of store path metadata, such as the + hash and the references. If ‘includeImpureInfo’ is true, + variable elements such as the registration time are + included. If ‘showClosureSize’ is true, the closure size of + each path is included. */ + void pathInfoToJSON(JSONPlaceholder & jsonOut, const PathSet & storePaths, + bool includeImpureInfo, bool showClosureSize); + + /* Return the size of the closure of the specified path, that is, + the sum of the size of the NAR serialisation of each path in + the closure. */ + unsigned long long getClosureSize(const Path & storePath); + /* Optimise the disk space usage of the Nix store by hard-linking files with the same contents. */ virtual void optimiseStore() = 0; diff --git a/src/nix/path-info.cc b/src/nix/path-info.cc index a9b33e187..0f9a1125f 100644 --- a/src/nix/path-info.cc +++ b/src/nix/path-info.cc @@ -65,55 +65,12 @@ struct CmdPathInfo : StorePathsCommand for (auto & storePath : storePaths) pathLen = std::max(pathLen, storePath.size()); - auto getClosureSize = [&](const Path & storePath) -> unsigned long long { - unsigned long long totalSize = 0; - PathSet closure; - store->computeFSClosure(storePath, closure, false, false); - for (auto & p : closure) - totalSize += store->queryPathInfo(p)->narSize; - return totalSize; - }; - if (json) { - JSONList jsonRoot(std::cout, true); - - for (auto storePath : storePaths) { - auto info = store->queryPathInfo(storePath); - storePath = info->path; - - auto jsonPath = jsonRoot.object(); - jsonPath - .attr("path", storePath) - .attr("narHash", info->narHash.to_string()) - .attr("narSize", info->narSize); - - if (showClosureSize) - jsonPath.attr("closureSize", getClosureSize(storePath)); - - if (info->deriver != "") - jsonPath.attr("deriver", info->deriver); - - { - auto jsonRefs = jsonPath.list("references"); - for (auto & ref : info->references) - jsonRefs.elem(ref); - } - - if (info->registrationTime) - jsonPath.attr("registrationTime", info->registrationTime); - - if (info->ultimate) - jsonPath.attr("ultimate", info->ultimate); - - if (info->ca != "") - jsonPath.attr("ca", info->ca); - - if (!info->sigs.empty()) { - auto jsonSigs = jsonPath.list("signatures"); - for (auto & sig : info->sigs) - jsonSigs.elem(sig); - } - } + JSONPlaceholder jsonRoot(std::cout, true); + store->pathInfoToJSON(jsonRoot, + // FIXME: preserve order? + PathSet(storePaths.begin(), storePaths.end()), + true, showClosureSize); } else { @@ -128,7 +85,7 @@ struct CmdPathInfo : StorePathsCommand std::cout << '\t' << std::setw(11) << info->narSize; if (showClosureSize) - std::cout << '\t' << std::setw(11) << getClosureSize(storePath); + std::cout << '\t' << std::setw(11) << store->getClosureSize(storePath); if (showSigs) { std::cout << '\t';