nix path-info: Add --json flag
Also, factor out JSON generation from value-to-json.{cc,hh}, and
support producing indented JSON.
			
			
This commit is contained in:
		
							parent
							
								
									9fa21765e7
								
							
						
					
					
						commit
						c0a7b84748
					
				
					 7 changed files with 476 additions and 133 deletions
				
			
		|  | @ -1,4 +1,5 @@ | |||
| #include "value-to-json.hh" | ||||
| #include "json.hh" | ||||
| #include "eval-inline.hh" | ||||
| #include "util.hh" | ||||
| 
 | ||||
|  | @ -8,24 +9,8 @@ | |||
| 
 | ||||
| namespace nix { | ||||
| 
 | ||||
| 
 | ||||
| void escapeJSON(std::ostream & str, const string & s) | ||||
| { | ||||
|     str << "\""; | ||||
|     for (auto & i : s) | ||||
|         if (i == '\"' || i == '\\') str << "\\" << i; | ||||
|         else if (i == '\n') str << "\\n"; | ||||
|         else if (i == '\r') str << "\\r"; | ||||
|         else if (i == '\t') str << "\\t"; | ||||
|         else if (i >= 0 && i < 32) | ||||
|             str << "\\u" << std::setfill('0') << std::setw(4) << std::hex << (uint16_t) i << std::dec; | ||||
|         else str << i; | ||||
|     str << "\""; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void printValueAsJSON(EvalState & state, bool strict, | ||||
|     Value & v, std::ostream & str, PathSet & context) | ||||
|     Value & v, JSONPlaceholder & out, PathSet & context) | ||||
| { | ||||
|     checkInterrupt(); | ||||
| 
 | ||||
|  | @ -34,58 +19,58 @@ void printValueAsJSON(EvalState & state, bool strict, | |||
|     switch (v.type) { | ||||
| 
 | ||||
|         case tInt: | ||||
|             str << v.integer; | ||||
|             out.write(v.integer); | ||||
|             break; | ||||
| 
 | ||||
|         case tBool: | ||||
|             str << (v.boolean ? "true" : "false"); | ||||
|             out.write(v.boolean); | ||||
|             break; | ||||
| 
 | ||||
|         case tString: | ||||
|             copyContext(v, context); | ||||
|             escapeJSON(str, v.string.s); | ||||
|             out.write(v.string.s); | ||||
|             break; | ||||
| 
 | ||||
|         case tPath: | ||||
|             escapeJSON(str, state.copyPathToStore(context, v.path)); | ||||
|             out.write(state.copyPathToStore(context, v.path)); | ||||
|             break; | ||||
| 
 | ||||
|         case tNull: | ||||
|             str << "null"; | ||||
|             out.write(nullptr); | ||||
|             break; | ||||
| 
 | ||||
|         case tAttrs: { | ||||
|             Bindings::iterator i = v.attrs->find(state.sOutPath); | ||||
|             if (i == v.attrs->end()) { | ||||
|                 JSONObject json(str); | ||||
|                 auto obj(out.object()); | ||||
|                 StringSet names; | ||||
|                 for (auto & j : *v.attrs) | ||||
|                     names.insert(j.name); | ||||
|                 for (auto & j : names) { | ||||
|                     Attr & a(*v.attrs->find(state.symbols.create(j))); | ||||
|                     json.attr(j); | ||||
|                     printValueAsJSON(state, strict, *a.value, str, context); | ||||
|                     auto placeholder(obj.placeholder(j)); | ||||
|                     printValueAsJSON(state, strict, *a.value, placeholder, context); | ||||
|                 } | ||||
|             } else | ||||
|                 printValueAsJSON(state, strict, *i->value, str, context); | ||||
|                 printValueAsJSON(state, strict, *i->value, out, context); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case tList1: case tList2: case tListN: { | ||||
|             JSONList json(str); | ||||
|             auto list(out.list()); | ||||
|             for (unsigned int n = 0; n < v.listSize(); ++n) { | ||||
|                 json.elem(); | ||||
|                 printValueAsJSON(state, strict, *v.listElems()[n], str, context); | ||||
|                 auto placeholder(list.placeholder()); | ||||
|                 printValueAsJSON(state, strict, *v.listElems()[n], placeholder, context); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case tExternal: | ||||
|             v.external->printValueAsJSON(state, strict, str, context); | ||||
|             v.external->printValueAsJSON(state, strict, out, context); | ||||
|             break; | ||||
| 
 | ||||
|         case tFloat: | ||||
|             str << v.fpoint; | ||||
|             out.write(v.fpoint); | ||||
|             break; | ||||
| 
 | ||||
|         default: | ||||
|  | @ -93,9 +78,15 @@ void printValueAsJSON(EvalState & state, bool strict, | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void printValueAsJSON(EvalState & state, bool strict, | ||||
|     Value & v, std::ostream & str, PathSet & context) | ||||
| { | ||||
|     JSONPlaceholder out(str); | ||||
|     printValueAsJSON(state, strict, v, out, context); | ||||
| } | ||||
| 
 | ||||
| void ExternalValueBase::printValueAsJSON(EvalState & state, bool strict, | ||||
|       std::ostream & str, PathSet & context) const | ||||
|     JSONPlaceholder & out, PathSet & context) const | ||||
| { | ||||
|     throw TypeError(format("cannot convert %1% to JSON") % showType()); | ||||
| } | ||||
|  |  | |||
|  | @ -8,73 +8,12 @@ | |||
| 
 | ||||
| namespace nix { | ||||
| 
 | ||||
| class JSONPlaceholder; | ||||
| 
 | ||||
| void printValueAsJSON(EvalState & state, bool strict, | ||||
|     Value & v, std::ostream & out, PathSet & context); | ||||
|     Value & v, JSONPlaceholder & out, PathSet & context); | ||||
| 
 | ||||
| void escapeJSON(std::ostream & str, const string & s); | ||||
| 
 | ||||
| struct JSONObject | ||||
| { | ||||
|     std::ostream & str; | ||||
|     bool first; | ||||
|     JSONObject(std::ostream & str) : str(str), first(true) | ||||
|     { | ||||
|         str << "{"; | ||||
|     } | ||||
|     ~JSONObject() | ||||
|     { | ||||
|         str << "}"; | ||||
|     } | ||||
|     void attr(const string & s) | ||||
|     { | ||||
|         if (!first) str << ","; else first = false; | ||||
|         escapeJSON(str, s); | ||||
|         str << ":"; | ||||
|     } | ||||
|     void attr(const string & s, const string & t) | ||||
|     { | ||||
|         attr(s); | ||||
|         escapeJSON(str, t); | ||||
|     } | ||||
|     void attr(const string & s, const char * t) | ||||
|     { | ||||
|         attr(s); | ||||
|         escapeJSON(str, t); | ||||
|     } | ||||
|     void attr(const string & s, bool b) | ||||
|     { | ||||
|         attr(s); | ||||
|         str << (b ? "true" : "false"); | ||||
|     } | ||||
|     template<typename T> | ||||
|     void attr(const string & s, const T & n) | ||||
|     { | ||||
|         attr(s); | ||||
|         str << n; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| struct JSONList | ||||
| { | ||||
|     std::ostream & str; | ||||
|     bool first; | ||||
|     JSONList(std::ostream & str) : str(str), first(true) | ||||
|     { | ||||
|         str << "["; | ||||
|     } | ||||
|     ~JSONList() | ||||
|     { | ||||
|         str << "]"; | ||||
|     } | ||||
|     void elem() | ||||
|     { | ||||
|         if (!first) str << ","; else first = false; | ||||
|     } | ||||
|     void elem(const string & s) | ||||
|     { | ||||
|         elem(); | ||||
|         escapeJSON(str, s); | ||||
|     } | ||||
| }; | ||||
| void printValueAsJSON(EvalState & state, bool strict, | ||||
|     Value & v, std::ostream & str, PathSet & context); | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ class Symbol; | |||
| struct Pos; | ||||
| class EvalState; | ||||
| class XMLWriter; | ||||
| class JSONPlaceholder; | ||||
| 
 | ||||
| 
 | ||||
| typedef long NixInt; | ||||
|  | @ -73,7 +74,7 @@ class ExternalValueBase | |||
| 
 | ||||
|     /* Print the value as JSON. Defaults to unconvertable, i.e. throws an error */ | ||||
|     virtual void printValueAsJSON(EvalState & state, bool strict, | ||||
|         std::ostream & str, PathSet & context) const; | ||||
|         JSONPlaceholder & out, PathSet & context) const; | ||||
| 
 | ||||
|     /* Print the value as XML. Defaults to unevaluated */ | ||||
|     virtual void printValueAsXML(EvalState & state, bool strict, bool location, | ||||
|  |  | |||
							
								
								
									
										171
									
								
								src/libutil/json.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								src/libutil/json.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,171 @@ | |||
| #include "json.hh" | ||||
| 
 | ||||
| #include <iomanip> | ||||
| #include <cstring> | ||||
| 
 | ||||
| namespace nix { | ||||
| 
 | ||||
| void toJSON(std::ostream & str, const char * start, const char * end) | ||||
| { | ||||
|     str << '"'; | ||||
|     for (auto i = start; i != end; i++) | ||||
|         if (*i == '\"' || *i == '\\') str << '\\' << *i; | ||||
|         else if (*i == '\n') str << "\\n"; | ||||
|         else if (*i == '\r') str << "\\r"; | ||||
|         else if (*i == '\t') str << "\\t"; | ||||
|         else if (*i >= 0 && *i < 32) | ||||
|             str << "\\u" << std::setfill('0') << std::setw(4) << std::hex << (uint16_t) *i << std::dec; | ||||
|         else str << *i; | ||||
|     str << '"'; | ||||
| } | ||||
| 
 | ||||
| void toJSON(std::ostream & str, const std::string & s) | ||||
| { | ||||
|     toJSON(str, s.c_str(), s.c_str() + s.size()); | ||||
| } | ||||
| 
 | ||||
| void toJSON(std::ostream & str, const char * s) | ||||
| { | ||||
|     if (!s) str << "null"; else toJSON(str, s, s + strlen(s)); | ||||
| } | ||||
| 
 | ||||
| void toJSON(std::ostream & str, unsigned long n) | ||||
| { | ||||
|     str << n; | ||||
| } | ||||
| 
 | ||||
| void toJSON(std::ostream & str, long n) | ||||
| { | ||||
|     str << n; | ||||
| } | ||||
| 
 | ||||
| void toJSON(std::ostream & str, double f) | ||||
| { | ||||
|     str << f; | ||||
| } | ||||
| 
 | ||||
| void toJSON(std::ostream & str, bool b) | ||||
| { | ||||
|     str << (b ? "true" : "false"); | ||||
| } | ||||
| 
 | ||||
| JSONWriter::JSONWriter(std::ostream & str, bool indent) | ||||
|     : state(new JSONState(str, indent)) | ||||
| { | ||||
|     state->stack.push_back(this); | ||||
| } | ||||
| 
 | ||||
| JSONWriter::JSONWriter(JSONState * state) | ||||
|     : state(state) | ||||
| { | ||||
|     state->stack.push_back(this); | ||||
| } | ||||
| 
 | ||||
| JSONWriter::~JSONWriter() | ||||
| { | ||||
|     assertActive(); | ||||
|     state->stack.pop_back(); | ||||
|     if (state->stack.empty()) 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() | ||||
| { | ||||
|     state->depth--; | ||||
|     if (state->indent && !first) indent(); | ||||
|     state->str << "}"; | ||||
| } | ||||
| 
 | ||||
| void JSONObject::attr(const std::string & s) | ||||
| { | ||||
|     comma(); | ||||
|     toJSON(state->str, s); | ||||
|     state->str << ':'; | ||||
|     if (state->indent) state->str << ' '; | ||||
| } | ||||
| 
 | ||||
| JSONList JSONObject::list(const std::string & name) | ||||
| { | ||||
|     attr(name); | ||||
|     return JSONList(state); | ||||
| } | ||||
| 
 | ||||
| JSONObject JSONObject::object(const std::string & name) | ||||
| { | ||||
|     attr(name); | ||||
|     return JSONObject(state); | ||||
| } | ||||
| 
 | ||||
| JSONPlaceholder JSONObject::placeholder(const std::string & name) | ||||
| { | ||||
|     attr(name); | ||||
|     return JSONPlaceholder(state); | ||||
| } | ||||
| 
 | ||||
| JSONList JSONPlaceholder::list() | ||||
| { | ||||
|     assertValid(); | ||||
|     first = false; | ||||
|     return JSONList(state); | ||||
| } | ||||
| 
 | ||||
| JSONObject JSONPlaceholder::object() | ||||
| { | ||||
|     assertValid(); | ||||
|     first = false; | ||||
|     return JSONObject(state); | ||||
| } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										183
									
								
								src/libutil/json.hh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								src/libutil/json.hh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,183 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
| #include <cassert> | ||||
| 
 | ||||
| namespace nix { | ||||
| 
 | ||||
| void toJSON(std::ostream & str, const char * start, const char * end); | ||||
| void toJSON(std::ostream & str, const std::string & s); | ||||
| void toJSON(std::ostream & str, const char * s); | ||||
| void toJSON(std::ostream & str, unsigned long n); | ||||
| void toJSON(std::ostream & str, long n); | ||||
| void toJSON(std::ostream & str, double f); | ||||
| void toJSON(std::ostream & str, bool b); | ||||
| 
 | ||||
| class JSONWriter | ||||
| { | ||||
| protected: | ||||
| 
 | ||||
|     struct JSONState | ||||
|     { | ||||
|         std::ostream & str; | ||||
|         bool indent; | ||||
|         size_t depth = 0; | ||||
|         std::vector<JSONWriter *> stack; | ||||
|         JSONState(std::ostream & str, bool indent) : str(str), indent(indent) { } | ||||
|         ~JSONState() | ||||
|         { | ||||
|             assert(stack.empty()); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     JSONState * state; | ||||
| 
 | ||||
|     bool first = true; | ||||
| 
 | ||||
|     JSONWriter(std::ostream & str, bool indent); | ||||
| 
 | ||||
|     JSONWriter(JSONState * state); | ||||
| 
 | ||||
|     ~JSONWriter(); | ||||
| 
 | ||||
|     void assertActive() | ||||
|     { | ||||
|         assert(!state->stack.empty() && state->stack.back() == this); | ||||
|     } | ||||
| 
 | ||||
|     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(const std::string & s); | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     JSONObject(std::ostream & str, bool indent = false) | ||||
|         : JSONWriter(str, indent) | ||||
|     { | ||||
|         open(); | ||||
|     } | ||||
| 
 | ||||
|     ~JSONObject(); | ||||
| 
 | ||||
|     template<typename T> | ||||
|     JSONObject & attr(const std::string & name, const T & v) | ||||
|     { | ||||
|         attr(name); | ||||
|         toJSON(state->str, v); | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     JSONList list(const std::string & name); | ||||
| 
 | ||||
|     JSONObject object(const std::string & name); | ||||
| 
 | ||||
|     JSONPlaceholder placeholder(const std::string & 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() | ||||
|     { | ||||
|         assert(!first || std::uncaught_exception()); | ||||
|     } | ||||
| 
 | ||||
|     template<typename T> | ||||
|     void write(const T & v) | ||||
|     { | ||||
|         assertValid(); | ||||
|         first = false; | ||||
|         toJSON(state->str, v); | ||||
|     } | ||||
| 
 | ||||
|     JSONList list(); | ||||
| 
 | ||||
|     JSONObject object(); | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | @ -10,6 +10,7 @@ | |||
| #include "store-api.hh" | ||||
| #include "user-env.hh" | ||||
| #include "util.hh" | ||||
| #include "json.hh" | ||||
| #include "value-to-json.hh" | ||||
| #include "xml-writer.hh" | ||||
| 
 | ||||
|  | @ -860,26 +861,24 @@ static VersionDiff compareVersionAgainstSet( | |||
| 
 | ||||
| static void queryJSON(Globals & globals, vector<DrvInfo> & elems) | ||||
| { | ||||
|     JSONObject topObj(cout); | ||||
|     JSONObject topObj(cout, true); | ||||
|     for (auto & i : elems) { | ||||
|         topObj.attr(i.attrPath); | ||||
|         JSONObject pkgObj(cout); | ||||
|         JSONObject pkgObj = topObj.object(i.attrPath); | ||||
| 
 | ||||
|         pkgObj.attr("name", i.name); | ||||
|         pkgObj.attr("system", i.system); | ||||
| 
 | ||||
|         pkgObj.attr("meta"); | ||||
|         JSONObject metaObj(cout); | ||||
|         JSONObject metaObj = pkgObj.object("meta"); | ||||
|         StringSet metaNames = i.queryMetaNames(); | ||||
|         for (auto & j : metaNames) { | ||||
|             metaObj.attr(j); | ||||
|             auto placeholder = metaObj.placeholder(j); | ||||
|             Value * v = i.queryMeta(j); | ||||
|             if (!v) { | ||||
|                 printMsg(lvlError, format("derivation ‘%1%’ has invalid meta attribute ‘%2%’") % i.name % j); | ||||
|                 cout << "null"; | ||||
|                 placeholder.write(nullptr); | ||||
|             } else { | ||||
|                 PathSet context; | ||||
|                 printValueAsJSON(*globals.state, true, *v, cout, context); | ||||
|                 printValueAsJSON(*globals.state, true, *v, placeholder, context); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -2,6 +2,10 @@ | |||
| #include "shared.hh" | ||||
| #include "store-api.hh" | ||||
| 
 | ||||
| 
 | ||||
| #include "json.hh" | ||||
| 
 | ||||
| 
 | ||||
| #include <iomanip> | ||||
| #include <algorithm> | ||||
| 
 | ||||
|  | @ -12,12 +16,14 @@ struct CmdPathInfo : StorePathsCommand | |||
|     bool showSize = false; | ||||
|     bool showClosureSize = false; | ||||
|     bool showSigs = false; | ||||
|     bool json = false; | ||||
| 
 | ||||
|     CmdPathInfo() | ||||
|     { | ||||
|         mkFlag('s', "size", "print size of the NAR dump of each path", &showSize); | ||||
|         mkFlag('S', "closure-size", "print sum size of the NAR dumps of the closure of each path", &showClosureSize); | ||||
|         mkFlag(0, "sigs", "show signatures", &showSigs); | ||||
|         mkFlag(0, "json", "produce JSON output", &json); | ||||
|     } | ||||
| 
 | ||||
|     std::string name() override | ||||
|  | @ -41,6 +47,10 @@ struct CmdPathInfo : StorePathsCommand | |||
|                 "To check the existence of a path in a binary cache:", | ||||
|                 "nix path-info -r /nix/store/7qvk5c91...-geeqie-1.1 --store https://cache.nixos.org/" | ||||
|             }, | ||||
|             Example{ | ||||
|                 "To print the 10 most recently added paths (using --json and the jq(1) command):", | ||||
|                 "nix path-info --all --json | jq -r 'sort_by(.registrationTime)[-11:-1][].path'" | ||||
|             }, | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|  | @ -50,36 +60,85 @@ struct CmdPathInfo : StorePathsCommand | |||
|         for (auto & storePath : storePaths) | ||||
|             pathLen = std::max(pathLen, storePath.size()); | ||||
| 
 | ||||
|         for (auto storePath : storePaths) { | ||||
|             auto info = store->queryPathInfo(storePath); | ||||
|             storePath = info->path; // FIXME: screws up padding
 | ||||
|         auto getClosureSize = [&](const Path & storePath) { | ||||
|             size_t totalSize = 0; | ||||
|             PathSet closure; | ||||
|             store->computeFSClosure(storePath, closure, false, false); | ||||
|             for (auto & p : closure) | ||||
|                 totalSize += store->queryPathInfo(p)->narSize; | ||||
|             return totalSize; | ||||
|         }; | ||||
| 
 | ||||
|             std::cout << storePath << std::string(std::max(0, (int) pathLen - (int) storePath.size()), ' '); | ||||
|         if (json) { | ||||
|             JSONList jsonRoot(std::cout, true); | ||||
| 
 | ||||
|             if (showSize) { | ||||
|                 std::cout << '\t' << std::setw(11) << info->narSize; | ||||
|             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); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (showClosureSize) { | ||||
|                 size_t totalSize = 0; | ||||
|                 PathSet closure; | ||||
|                 store->computeFSClosure(storePath, closure, false, false); | ||||
|                 for (auto & p : closure) | ||||
|                     totalSize += store->queryPathInfo(p)->narSize; | ||||
|                 std::cout << '\t' << std::setw(11) << totalSize; | ||||
|             } | ||||
| 
 | ||||
|             if (showSigs) { | ||||
|                 std::cout << '\t'; | ||||
|                 Strings ss; | ||||
|                 if (info->ultimate) ss.push_back("ultimate"); | ||||
|                 if (info->ca != "") ss.push_back("ca:" + info->ca); | ||||
|                 for (auto & sig : info->sigs) ss.push_back(sig); | ||||
|                 std::cout << concatStringsSep(" ", ss); | ||||
|             } | ||||
| 
 | ||||
|             std::cout << std::endl; | ||||
|         } | ||||
| 
 | ||||
|         else { | ||||
| 
 | ||||
|             for (auto storePath : storePaths) { | ||||
|                 auto info = store->queryPathInfo(storePath); | ||||
|                 storePath = info->path; // FIXME: screws up padding
 | ||||
| 
 | ||||
|                 std::cout << storePath << std::string(std::max(0, (int) pathLen - (int) storePath.size()), ' '); | ||||
| 
 | ||||
|                 if (showSize) | ||||
|                     std::cout << '\t' << std::setw(11) << info->narSize; | ||||
| 
 | ||||
|                 if (showClosureSize) | ||||
|                     std::cout << '\t' << std::setw(11) << getClosureSize(storePath); | ||||
| 
 | ||||
|                 if (showSigs) { | ||||
|                     std::cout << '\t'; | ||||
|                     Strings ss; | ||||
|                     if (info->ultimate) ss.push_back("ultimate"); | ||||
|                     if (info->ca != "") ss.push_back("ca:" + info->ca); | ||||
|                     for (auto & sig : info->sigs) ss.push_back(sig); | ||||
|                     std::cout << concatStringsSep(" ", ss); | ||||
|                 } | ||||
| 
 | ||||
|                 std::cout << std::endl; | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue