1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 12:06:01 +01:00
This commit is contained in:
John Ericson 2025-11-08 14:35:44 +01:00 committed by GitHub
commit ec67014102
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 191 additions and 101 deletions

View file

@ -22,7 +22,15 @@ The store path info JSON format has been updated from version 1 to version 2:
- New: `"ca": {"method": "nar", "hash": {"algorithm": "sha256", "format": "base64", "hash": "EMIJ+giQ..."}}` - New: `"ca": {"method": "nar", "hash": {"algorithm": "sha256", "format": "base64", "hash": "EMIJ+giQ..."}}`
- Still `null` values for input-addressed store objects - Still `null` values for input-addressed store objects
Version 1 format is still accepted when reading for backward compatibility. - **Structured hash fields**:
Hash values (`narHash` and `downloadHash`) are now structured JSON objects instead of strings:
- Old: `"narHash": "sha256:FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="`
- New: `"narHash": {"algorithm": "sha256", "format": "base64", "hash": "FePFYIlM..."}`
- Same structure applies to `downloadHash` in NAR info contexts
Nix currently only produces, and doesn't consume this format.
**Affected command**: `nix path-info --json` **Affected command**: `nix path-info --json`

View file

@ -71,7 +71,7 @@ $defs:
Note: This field may not be present in all contexts, such as when the path is used as the key and the the store object info the value in map. Note: This field may not be present in all contexts, such as when the path is used as the key and the the store object info the value in map.
narHash: narHash:
type: string "$ref": "./hash-v1.yaml"
title: NAR Hash title: NAR Hash
description: | description: |
Hash of the [file system object](@docroot@/store/file-system-object.md) part of the store object when serialized as a [Nix Archive](@docroot@/store/file-system-object/content-address.md#serial-nix-archive). Hash of the [file system object](@docroot@/store/file-system-object.md) part of the store object when serialized as a [Nix Archive](@docroot@/store/file-system-object/content-address.md#serial-nix-archive).
@ -229,7 +229,7 @@ $defs:
> This is an impure "`.narinfo`" field that may not be included in certain contexts. > This is an impure "`.narinfo`" field that may not be included in certain contexts.
downloadHash: downloadHash:
type: string "$ref": "./hash-v1.yaml"
title: Download Hash title: Download Hash
description: | description: |
A digest for the compressed archive itself, as opposed to the data contained within. A digest for the compressed archive itself, as opposed to the data contained within.

View file

@ -9,9 +9,17 @@
}, },
"compression": "xz", "compression": "xz",
"deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", "deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
"downloadHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "downloadHash": {
"algorithm": "sha256",
"format": "base64",
"hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="
},
"downloadSize": 4029176, "downloadSize": 4029176,
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "narHash": {
"algorithm": "sha256",
"format": "base64",
"hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="
},
"narSize": 34878, "narSize": 34878,
"references": [ "references": [
"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",

View file

@ -7,7 +7,11 @@
}, },
"method": "nar" "method": "nar"
}, },
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "narHash": {
"algorithm": "sha256",
"format": "base64",
"hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="
},
"narSize": 34878, "narSize": 34878,
"references": [ "references": [
"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",

View file

@ -1,7 +1,11 @@
{ {
"ca": null, "ca": null,
"deriver": null, "deriver": null,
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "narHash": {
"algorithm": "sha256",
"format": "base64",
"hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="
},
"narSize": 0, "narSize": 0,
"references": [], "references": [],
"registrationTime": null, "registrationTime": null,

View file

@ -1,6 +1,10 @@
{ {
"ca": null, "ca": null,
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "narHash": {
"algorithm": "sha256",
"format": "base64",
"hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="
},
"narSize": 0, "narSize": 0,
"references": [], "references": [],
"version": 2 "version": 2

View file

@ -8,7 +8,11 @@
"method": "nar" "method": "nar"
}, },
"deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", "deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "narHash": {
"algorithm": "sha256",
"format": "base64",
"hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="
},
"narSize": 34878, "narSize": 34878,
"references": [ "references": [
"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",

View file

@ -7,7 +7,11 @@
}, },
"method": "nar" "method": "nar"
}, },
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", "narHash": {
"algorithm": "sha256",
"format": "base64",
"hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="
},
"narSize": 34878, "narSize": 34878,
"references": [ "references": [
"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",

View file

@ -59,24 +59,24 @@ static NarInfo makeNarInfo(const Store & store, bool includeImpureInfo)
return info; return info;
} }
#define JSON_TEST(STEM, PURE) \ #define JSON_TEST(STEM, PURE) \
TEST_F(NarInfoTest, NarInfo_##STEM##_from_json) \ TEST_F(NarInfoTest, NarInfo_##STEM##_from_json) \
{ \ { \
readTest(#STEM, [&](const auto & encoded_) { \ readTest(#STEM, [&](const auto & encoded_) { \
auto encoded = json::parse(encoded_); \ auto encoded = json::parse(encoded_); \
auto expected = makeNarInfo(*store, PURE); \ auto expected = makeNarInfo(*store, PURE); \
NarInfo got = NarInfo::fromJSON(*store, expected.path, encoded); \ auto got = UnkeyedNarInfo::fromJSON(&*store, encoded); \
ASSERT_EQ(got, expected); \ ASSERT_EQ(got, expected); \
}); \ }); \
} \ } \
\ \
TEST_F(NarInfoTest, NarInfo_##STEM##_to_json) \ TEST_F(NarInfoTest, NarInfo_##STEM##_to_json) \
{ \ { \
writeTest( \ writeTest( \
#STEM, \ #STEM, \
[&]() -> json { return makeNarInfo(*store, PURE).toJSON(*store, PURE, HashFormat::SRI); }, \ [&]() -> json { return makeNarInfo(*store, PURE).toJSON(&*store, PURE); }, \
[](const auto & file) { return json::parse(readFile(file)); }, \ [](const auto & file) { return json::parse(readFile(file)); }, \
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
} }
JSON_TEST(pure, false) JSON_TEST(pure, false)

View file

@ -70,7 +70,7 @@ static UnkeyedValidPathInfo makeFull(const Store & store, bool includeImpureInfo
{ \ { \
readTest(#STEM, [&](const auto & encoded_) { \ readTest(#STEM, [&](const auto & encoded_) { \
auto encoded = json::parse(encoded_); \ auto encoded = json::parse(encoded_); \
UnkeyedValidPathInfo got = UnkeyedValidPathInfo::fromJSON(*store, encoded); \ UnkeyedValidPathInfo got = UnkeyedValidPathInfo::fromJSON(&*store, encoded); \
auto expected = OBJ; \ auto expected = OBJ; \
ASSERT_EQ(got, expected); \ ASSERT_EQ(got, expected); \
}); \ }); \
@ -80,7 +80,7 @@ static UnkeyedValidPathInfo makeFull(const Store & store, bool includeImpureInfo
{ \ { \
writeTest( \ writeTest( \
#STEM, \ #STEM, \
[&]() -> json { return OBJ.toJSON(*store, PURE, HashFormat::SRI); }, \ [&]() -> json { return OBJ.toJSON(&*store, PURE); }, \
[](const auto & file) { return json::parse(readFile(file)); }, \ [](const auto & file) { return json::parse(readFile(file)); }, \
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
} }

View file

@ -423,15 +423,6 @@ void adl_serializer<DerivationOptions>::to_json(json & json, const DerivationOpt
json["allowSubstitutes"] = o.allowSubstitutes; json["allowSubstitutes"] = o.allowSubstitutes;
} }
template<typename T>
static inline std::optional<T> ptrToOwned(const json * ptr)
{
if (ptr)
return std::optional{*ptr};
else
return std::nullopt;
}
DerivationOptions::OutputChecks adl_serializer<DerivationOptions::OutputChecks>::from_json(const json & json_) DerivationOptions::OutputChecks adl_serializer<DerivationOptions::OutputChecks>::from_json(const json & json_)
{ {
auto & json = getObject(json_); auto & json = getObject(json_);

View file

@ -9,17 +9,38 @@ namespace nix {
struct StoreDirConfig; struct StoreDirConfig;
struct NarInfo : ValidPathInfo struct UnkeyedNarInfo : virtual UnkeyedValidPathInfo
{ {
std::string url; std::string url;
std::string compression; std::string compression;
std::optional<Hash> fileHash; std::optional<Hash> fileHash;
uint64_t fileSize = 0; uint64_t fileSize = 0;
UnkeyedNarInfo(UnkeyedValidPathInfo info)
: UnkeyedValidPathInfo(std::move(info))
{
}
bool operator==(const UnkeyedNarInfo &) const = default;
// TODO libc++ 16 (used by darwin) missing `std::optional::operator <=>`, can't do yet
// auto operator <=>(const NarInfo &) const = default;
nlohmann::json toJSON(const StoreDirConfig * store, bool includeImpureInfo) const override;
static UnkeyedNarInfo fromJSON(const StoreDirConfig * store, const nlohmann::json & json);
};
/**
* Key and the extra NAR fields
*/
struct NarInfo : ValidPathInfo, UnkeyedNarInfo
{
NarInfo() = delete; NarInfo() = delete;
NarInfo(ValidPathInfo info) NarInfo(ValidPathInfo info)
: ValidPathInfo{std::move(info)} : UnkeyedValidPathInfo(std::move(static_cast<UnkeyedValidPathInfo &&>(info)))
// later moves will be partially ignored
, ValidPathInfo(std::move(info))
, UnkeyedNarInfo(std::move(info))
{ {
} }
@ -37,13 +58,10 @@ struct NarInfo : ValidPathInfo
NarInfo(const StoreDirConfig & store, const std::string & s, const std::string & whence); NarInfo(const StoreDirConfig & store, const std::string & s, const std::string & whence);
bool operator==(const NarInfo &) const = default; bool operator==(const NarInfo &) const = default;
// TODO libc++ 16 (used by darwin) missing `std::optional::operator <=>`, can't do yet
// auto operator <=>(const NarInfo &) const = default;
std::string to_string(const StoreDirConfig & store) const; std::string to_string(const StoreDirConfig & store) const;
nlohmann::json toJSON(const StoreDirConfig & store, bool includeImpureInfo, HashFormat hashFormat) const override;
static NarInfo fromJSON(const StoreDirConfig & store, const StorePath & path, const nlohmann::json & json);
}; };
} // namespace nix } // namespace nix
JSON_IMPL(nix::UnkeyedNarInfo)

View file

@ -117,11 +117,11 @@ struct UnkeyedValidPathInfo
* @param includeImpureInfo If true, variable elements such as the * @param includeImpureInfo If true, variable elements such as the
* registration time are included. * registration time are included.
*/ */
virtual nlohmann::json toJSON(const StoreDirConfig & store, bool includeImpureInfo, HashFormat hashFormat) const; virtual nlohmann::json toJSON(const StoreDirConfig * store, bool includeImpureInfo) const;
static UnkeyedValidPathInfo fromJSON(const StoreDirConfig & store, const nlohmann::json & json); static UnkeyedValidPathInfo fromJSON(const StoreDirConfig * store, const nlohmann::json & json);
}; };
struct ValidPathInfo : UnkeyedValidPathInfo struct ValidPathInfo : virtual UnkeyedValidPathInfo
{ {
StorePath path; StorePath path;
@ -174,10 +174,14 @@ struct ValidPathInfo : UnkeyedValidPathInfo
ValidPathInfo(StorePath && path, UnkeyedValidPathInfo info) ValidPathInfo(StorePath && path, UnkeyedValidPathInfo info)
: UnkeyedValidPathInfo(info) : UnkeyedValidPathInfo(info)
, path(std::move(path)) {}; , path(std::move(path))
{
}
ValidPathInfo(const StorePath & path, UnkeyedValidPathInfo info) ValidPathInfo(const StorePath & path, UnkeyedValidPathInfo info)
: UnkeyedValidPathInfo(info) : ValidPathInfo(StorePath{path}, std::move(info))
, path(path) {}; {
}
static ValidPathInfo static ValidPathInfo
makeFromCA(const StoreDirConfig & store, std::string_view name, ContentAddressWithReferences && ca, Hash narHash); makeFromCA(const StoreDirConfig & store, std::string_view name, ContentAddressWithReferences && ca, Hash narHash);
@ -191,3 +195,5 @@ static_assert(std::is_move_constructible_v<ValidPathInfo>);
using ValidPathInfos = std::map<StorePath, ValidPathInfo>; using ValidPathInfos = std::map<StorePath, ValidPathInfo>;
} // namespace nix } // namespace nix
JSON_IMPL(nix::UnkeyedValidPathInfo)

View file

@ -7,7 +7,9 @@
namespace nix { namespace nix {
NarInfo::NarInfo(const StoreDirConfig & store, const std::string & s, const std::string & whence) NarInfo::NarInfo(const StoreDirConfig & store, const std::string & s, const std::string & whence)
: ValidPathInfo(StorePath(StorePath::dummy), Hash(Hash::dummy)) // FIXME: hack : UnkeyedValidPathInfo(Hash::dummy) // FIXME: hack
, ValidPathInfo(StorePath::dummy, static_cast<const UnkeyedValidPathInfo &>(*this)) // FIXME: hack
, UnkeyedNarInfo(static_cast<const UnkeyedValidPathInfo &>(*this))
{ {
unsigned line = 1; unsigned line = 1;
@ -130,11 +132,11 @@ std::string NarInfo::to_string(const StoreDirConfig & store) const
return res; return res;
} }
nlohmann::json NarInfo::toJSON(const StoreDirConfig & store, bool includeImpureInfo, HashFormat hashFormat) const nlohmann::json UnkeyedNarInfo::toJSON(const StoreDirConfig * store, bool includeImpureInfo) const
{ {
using nlohmann::json; using nlohmann::json;
auto jsonObject = ValidPathInfo::toJSON(store, includeImpureInfo, hashFormat); auto jsonObject = UnkeyedValidPathInfo::toJSON(store, includeImpureInfo);
if (includeImpureInfo) { if (includeImpureInfo) {
if (!url.empty()) if (!url.empty())
@ -142,7 +144,7 @@ nlohmann::json NarInfo::toJSON(const StoreDirConfig & store, bool includeImpureI
if (!compression.empty()) if (!compression.empty())
jsonObject["compression"] = compression; jsonObject["compression"] = compression;
if (fileHash) if (fileHash)
jsonObject["downloadHash"] = fileHash->to_string(hashFormat, true); jsonObject["downloadHash"] = *fileHash;
if (fileSize) if (fileSize)
jsonObject["downloadSize"] = fileSize; jsonObject["downloadSize"] = fileSize;
} }
@ -150,30 +152,43 @@ nlohmann::json NarInfo::toJSON(const StoreDirConfig & store, bool includeImpureI
return jsonObject; return jsonObject;
} }
NarInfo NarInfo::fromJSON(const StoreDirConfig & store, const StorePath & path, const nlohmann::json & json) UnkeyedNarInfo UnkeyedNarInfo::fromJSON(const StoreDirConfig * store, const nlohmann::json & json)
{ {
using nlohmann::detail::value_t; using nlohmann::detail::value_t;
NarInfo res{ValidPathInfo{ UnkeyedNarInfo res{UnkeyedValidPathInfo::fromJSON(store, json)};
path,
UnkeyedValidPathInfo::fromJSON(store, json),
}};
auto & obj = getObject(json); auto & obj = getObject(json);
if (json.contains("url")) if (auto * url = get(obj, "url"))
res.url = getString(valueAt(obj, "url")); res.url = getString(*url);
if (json.contains("compression")) if (auto * compression = get(obj, "compression"))
res.compression = getString(valueAt(obj, "compression")); res.compression = getString(*compression);
if (json.contains("downloadHash")) if (auto * downloadHash = get(obj, "downloadHash"))
res.fileHash = Hash::parseAny(getString(valueAt(obj, "downloadHash")), std::nullopt); res.fileHash = *downloadHash;
if (json.contains("downloadSize")) if (auto * downloadSize = get(obj, "downloadSize"))
res.fileSize = getUnsigned(valueAt(obj, "downloadSize")); res.fileSize = getUnsigned(*downloadSize);
return res; return res;
} }
} // namespace nix } // namespace nix
namespace nlohmann {
using namespace nix;
UnkeyedNarInfo adl_serializer<UnkeyedNarInfo>::from_json(const json & json)
{
return UnkeyedNarInfo::fromJSON(nullptr, json);
}
void adl_serializer<UnkeyedNarInfo>::to_json(json & json, const UnkeyedNarInfo & c)
{
json = c.toJSON(nullptr, true);
}
} // namespace nlohmann

View file

@ -149,8 +149,7 @@ ValidPathInfo ValidPathInfo::makeFromCA(
return res; return res;
} }
nlohmann::json nlohmann::json UnkeyedValidPathInfo::toJSON(const StoreDirConfig * store, bool includeImpureInfo) const
UnkeyedValidPathInfo::toJSON(const StoreDirConfig & store, bool includeImpureInfo, HashFormat hashFormat) const
{ {
using nlohmann::json; using nlohmann::json;
@ -158,19 +157,21 @@ UnkeyedValidPathInfo::toJSON(const StoreDirConfig & store, bool includeImpureInf
jsonObject["version"] = 2; jsonObject["version"] = 2;
jsonObject["narHash"] = narHash.to_string(hashFormat, true); jsonObject["narHash"] = narHash;
jsonObject["narSize"] = narSize; jsonObject["narSize"] = narSize;
{ {
auto & jsonRefs = jsonObject["references"] = json::array(); auto & jsonRefs = jsonObject["references"] = json::array();
for (auto & ref : references) for (auto & ref : references)
jsonRefs.emplace_back(store.printStorePath(ref)); jsonRefs.emplace_back(store ? static_cast<json>(store->printStorePath(ref)) : static_cast<json>(ref));
} }
jsonObject["ca"] = ca; jsonObject["ca"] = ca;
if (includeImpureInfo) { if (includeImpureInfo) {
jsonObject["deriver"] = deriver ? (std::optional{store.printStorePath(*deriver)}) : std::nullopt; jsonObject["deriver"] = deriver ? (store ? static_cast<json>(std::optional{store->printStorePath(*deriver)})
: static_cast<json>(std::optional{*deriver}))
: static_cast<json>(std::optional<StorePath>{});
jsonObject["registrationTime"] = registrationTime ? (std::optional{registrationTime}) : std::nullopt; jsonObject["registrationTime"] = registrationTime ? (std::optional{registrationTime}) : std::nullopt;
@ -184,7 +185,7 @@ UnkeyedValidPathInfo::toJSON(const StoreDirConfig & store, bool includeImpureInf
return jsonObject; return jsonObject;
} }
UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(const StoreDirConfig & store, const nlohmann::json & _json) UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(const StoreDirConfig * store, const nlohmann::json & _json)
{ {
UnkeyedValidPathInfo res{ UnkeyedValidPathInfo res{
Hash(Hash::dummy), Hash(Hash::dummy),
@ -192,44 +193,34 @@ UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(const StoreDirConfig & store
auto & json = getObject(_json); auto & json = getObject(_json);
// Check version (optional for backward compatibility) {
nlohmann::json::number_unsigned_t version = 1; auto version = getUnsigned(valueAt(json, "version"));
if (json.contains("version")) { if (version != 2)
version = getUnsigned(valueAt(json, "version")); throw Error("Unsupported path info JSON format version %d, only version 2 is currently supported", version);
if (version != 1 && version != 2) {
throw Error("Unsupported path info JSON format version %d, expected 1 through 2", version);
}
} }
res.narHash = Hash::parseAny(getString(valueAt(json, "narHash")), std::nullopt); res.narHash = valueAt(json, "narHash");
res.narSize = getUnsigned(valueAt(json, "narSize")); res.narSize = getUnsigned(valueAt(json, "narSize"));
try { try {
auto references = getStringList(valueAt(json, "references")); auto references = getStringList(valueAt(json, "references"));
for (auto & input : references) for (auto & input : references)
res.references.insert(store.parseStorePath(static_cast<const std::string &>(input))); res.references.insert(store ? store->parseStorePath(getString(input)) : static_cast<StorePath>(input));
} catch (Error & e) { } catch (Error & e) {
e.addTrace({}, "while reading key 'references'"); e.addTrace({}, "while reading key 'references'");
throw; throw;
} }
// New format as this as nullable but mandatory field; handling try {
// missing is for back-compat. res.ca = ptrToOwned<ContentAddress>(getNullable(valueAt(json, "ca")));
if (auto * rawCa0 = optionalValueAt(json, "ca")) } catch (Error & e) {
if (auto * rawCa = getNullable(*rawCa0)) e.addTrace({}, "while reading key 'ca'");
switch (version) { throw;
case 1: }
// old string format also used in SQLite DB and .narinfo
res.ca = ContentAddress::parse(getString(*rawCa));
break;
case 2 ... std::numeric_limits<decltype(version)>::max():
res.ca = *rawCa;
break;
}
if (auto * rawDeriver0 = optionalValueAt(json, "deriver")) if (auto * rawDeriver0 = optionalValueAt(json, "deriver"))
if (auto * rawDeriver = getNullable(*rawDeriver0)) if (auto * rawDeriver = getNullable(*rawDeriver0))
res.deriver = store.parseStorePath(getString(*rawDeriver)); res.deriver = store ? store->parseStorePath(getString(*rawDeriver)) : static_cast<StorePath>(*rawDeriver);
if (auto * rawRegistrationTime0 = optionalValueAt(json, "registrationTime")) if (auto * rawRegistrationTime0 = optionalValueAt(json, "registrationTime"))
if (auto * rawRegistrationTime = getNullable(*rawRegistrationTime0)) if (auto * rawRegistrationTime = getNullable(*rawRegistrationTime0))
@ -245,3 +236,19 @@ UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(const StoreDirConfig & store
} }
} // namespace nix } // namespace nix
namespace nlohmann {
using namespace nix;
UnkeyedValidPathInfo adl_serializer<UnkeyedValidPathInfo>::from_json(const json & json)
{
return UnkeyedValidPathInfo::fromJSON(nullptr, json);
}
void adl_serializer<UnkeyedValidPathInfo>::to_json(json & json, const UnkeyedValidPathInfo & c)
{
json = c.toJSON(nullptr, true);
}
} // namespace nlohmann

View file

@ -114,4 +114,13 @@ struct adl_serializer<std::optional<T>>
} }
}; };
template<typename T>
static inline std::optional<T> ptrToOwned(const json * ptr)
{
if (ptr)
return std::optional{*ptr};
else
return std::nullopt;
}
} // namespace nlohmann } // namespace nlohmann

View file

@ -51,7 +51,7 @@ static json pathInfoToJSON(Store & store, const StorePathSet & storePaths, bool
// know the name yet until we've read the NAR info. // know the name yet until we've read the NAR info.
printedStorePath = store.printStorePath(info->path); printedStorePath = store.printStorePath(info->path);
jsonObject = info->toJSON(store, true, HashFormat::SRI); jsonObject = info->toJSON(&store, true);
if (showClosureSize) { if (showClosureSize) {
StorePathSet closure; StorePathSet closure;

View file

@ -17,8 +17,16 @@ diff --unified --color=always \
jq --sort-keys 'map_values(.narHash)') \ jq --sort-keys 'map_values(.narHash)') \
<(jq --sort-keys <<-EOF <(jq --sort-keys <<-EOF
{ {
"$foo": "sha256-QvtAMbUl/uvi+LCObmqOhvNOapHdA2raiI4xG5zI5pA=", "$foo": {
"$bar": "sha256-9fhYGu9fqxcQC2Kc81qh2RMo1QcLBUBo8U+pPn+jthQ=", "algorithm": "sha256",
"format": "base64",
"hash": "QvtAMbUl/uvi+LCObmqOhvNOapHdA2raiI4xG5zI5pA="
},
"$bar": {
"algorithm": "sha256",
"format": "base64",
"hash": "9fhYGu9fqxcQC2Kc81qh2RMo1QcLBUBo8U+pPn+jthQ="
},
"$baz": null "$baz": null
} }
EOF EOF