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…
	
	Add table
		Add a link
		
	
		Reference in a new issue