exportReferencesGraph: Export more complete info in JSON format
This writes info about every path in the closure in the same format as ‘nix path-info --json’. Thus it also includes NAR hashes and sizes. Example: [ { "path": "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10", "narHash": "sha256:0ckdc4z20kkmpqdilx0wl6cricxv90lh85xpv2qljppcmz6vzcxl", "narSize": 197648, "references": [ "/nix/store/10h6li26i7g6z3mdpvra09yyf10mmzdr-hello-2.10", "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24" ], "closureSize": 20939776 }, { "path": "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24", "narHash": "sha256:1nfn3m3p98y1c0kd0brp80dn9n5mycwgrk183j17rajya0h7gax3", "narSize": 20742128, "references": [ "/nix/store/27binbdy296qvjycdgr1535v8872vz3z-glibc-2.24" ], "closureSize": 20742128 } ] Fixes #1134.
This commit is contained in:
parent
6de33a9c67
commit
c2b0d8749f
4 changed files with 90 additions and 50 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include "builtins.hh"
|
#include "builtins.hh"
|
||||||
#include "finally.hh"
|
#include "finally.hh"
|
||||||
#include "compression.hh"
|
#include "compression.hh"
|
||||||
|
#include "json.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -2273,9 +2274,18 @@ void DerivationGoal::doExportReferencesGraph()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write closure info to `fileName'. */
|
/* Write closure info to <fileName>. */
|
||||||
writeFile(tmpDir + "/" + fileName,
|
writeFile(tmpDir + "/" + fileName,
|
||||||
worker.store.makeValidityRegistration(paths, false, false));
|
worker.store.makeValidityRegistration(paths, false, false));
|
||||||
|
|
||||||
|
/* Write a more comprehensive JSON serialisation to
|
||||||
|
<fileName>.json. */
|
||||||
|
std::ostringstream str;
|
||||||
|
{
|
||||||
|
JSONPlaceholder jsonRoot(str, true);
|
||||||
|
worker.store.pathInfoToJSON(jsonRoot, paths, false, true);
|
||||||
|
}
|
||||||
|
writeFile(tmpDir + "/" + fileName + ".json", str.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#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 <future>
|
#include <future>
|
||||||
|
|
||||||
|
@ -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()
|
const Store::Stats & Store::getStats()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct Derivation;
|
||||||
class FSAccessor;
|
class FSAccessor;
|
||||||
class NarInfoDiskCache;
|
class NarInfoDiskCache;
|
||||||
class Store;
|
class Store;
|
||||||
|
class JSONPlaceholder;
|
||||||
|
|
||||||
|
|
||||||
/* Size of the hash part of store paths, in base-32 characters. */
|
/* Size of the hash part of store paths, in base-32 characters. */
|
||||||
|
@ -469,6 +470,19 @@ public:
|
||||||
string makeValidityRegistration(const PathSet & paths,
|
string makeValidityRegistration(const PathSet & paths,
|
||||||
bool showDerivers, bool showHash);
|
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
|
/* Optimise the disk space usage of the Nix store by hard-linking files
|
||||||
with the same contents. */
|
with the same contents. */
|
||||||
virtual void optimiseStore() = 0;
|
virtual void optimiseStore() = 0;
|
||||||
|
|
|
@ -65,55 +65,12 @@ struct CmdPathInfo : StorePathsCommand
|
||||||
for (auto & storePath : storePaths)
|
for (auto & storePath : storePaths)
|
||||||
pathLen = std::max(pathLen, storePath.size());
|
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) {
|
if (json) {
|
||||||
JSONList jsonRoot(std::cout, true);
|
JSONPlaceholder jsonRoot(std::cout, true);
|
||||||
|
store->pathInfoToJSON(jsonRoot,
|
||||||
for (auto storePath : storePaths) {
|
// FIXME: preserve order?
|
||||||
auto info = store->queryPathInfo(storePath);
|
PathSet(storePaths.begin(), storePaths.end()),
|
||||||
storePath = info->path;
|
true, showClosureSize);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
@ -128,7 +85,7 @@ struct CmdPathInfo : StorePathsCommand
|
||||||
std::cout << '\t' << std::setw(11) << info->narSize;
|
std::cout << '\t' << std::setw(11) << info->narSize;
|
||||||
|
|
||||||
if (showClosureSize)
|
if (showClosureSize)
|
||||||
std::cout << '\t' << std::setw(11) << getClosureSize(storePath);
|
std::cout << '\t' << std::setw(11) << store->getClosureSize(storePath);
|
||||||
|
|
||||||
if (showSigs) {
|
if (showSigs) {
|
||||||
std::cout << '\t';
|
std::cout << '\t';
|
||||||
|
|
Loading…
Reference in a new issue