diff --git a/doc/manual/rl-next/json-format-changes.md b/doc/manual/rl-next/json-format-changes.md index c5518ee1b..bd7e11243 100644 --- a/doc/manual/rl-next/json-format-changes.md +++ b/doc/manual/rl-next/json-format-changes.md @@ -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..."}}` - 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` diff --git a/doc/manual/source/protocols/json/schema/store-object-info-v2.yaml b/doc/manual/source/protocols/json/schema/store-object-info-v2.yaml index 4f442e0c3..44d9e5eae 100644 --- a/doc/manual/source/protocols/json/schema/store-object-info-v2.yaml +++ b/doc/manual/source/protocols/json/schema/store-object-info-v2.yaml @@ -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. narHash: - type: string + "$ref": "./hash-v1.yaml" title: NAR Hash 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). @@ -229,7 +229,7 @@ $defs: > This is an impure "`.narinfo`" field that may not be included in certain contexts. downloadHash: - type: string + "$ref": "./hash-v1.yaml" title: Download Hash description: | A digest for the compressed archive itself, as opposed to the data contained within. diff --git a/src/libstore-test-support/include/nix/store/tests/protocol.hh b/src/libstore-test-support/include/nix/store/tests/protocol.hh index 5b57c6585..0f774df0e 100644 --- a/src/libstore-test-support/include/nix/store/tests/protocol.hh +++ b/src/libstore-test-support/include/nix/store/tests/protocol.hh @@ -6,6 +6,7 @@ #include "nix/store/tests/libstore.hh" #include "nix/util/tests/characterization.hh" +#include "nix/util/tests/json-characterization.hh" namespace nix { @@ -16,12 +17,30 @@ class ProtoTest : public CharacterizationTest std::filesystem::path goldenMaster(std::string_view testStem) const override { - return unitTestData / (std::string{testStem + ".bin"}); + return unitTestData / testStem; } public: Path storeDir = "/nix/store"; StoreDirConfig store{storeDir}; + + /** + * Golden test for `T` JSON reading + */ + template + void readJsonTest(PathView testStem, const T & expected) + { + nix::readJsonTest(*this, testStem, expected); + } + + /** + * Golden test for `T` JSON write + */ + template + void writeJsonTest(PathView testStem, const T & decoded) + { + nix::writeJsonTest(*this, testStem, decoded); + } }; template @@ -34,7 +53,7 @@ public: template void readProtoTest(PathView testStem, typename Proto::Version version, T expected) { - CharacterizationTest::readTest(testStem, [&](const auto & encoded) { + CharacterizationTest::readTest(std::string{testStem + ".bin"}, [&](const auto & encoded) { T got = ({ StringSource from{encoded}; Proto::template Serialise::read( @@ -55,7 +74,7 @@ public: template void writeProtoTest(PathView testStem, typename Proto::Version version, const T & decoded) { - CharacterizationTest::writeTest(testStem, [&]() { + CharacterizationTest::writeTest(std::string{testStem + ".bin"}, [&]() { StringSink to; Proto::template Serialise::write( this->store, @@ -69,14 +88,25 @@ public: } }; -#define VERSIONED_CHARACTERIZATION_TEST(FIXTURE, NAME, STEM, VERSION, VALUE) \ - TEST_F(FIXTURE, NAME##_read) \ - { \ - readProtoTest(STEM, VERSION, VALUE); \ - } \ - TEST_F(FIXTURE, NAME##_write) \ - { \ - writeProtoTest(STEM, VERSION, VALUE); \ +#define VERSIONED_CHARACTERIZATION_TEST_NO_JSON(FIXTURE, NAME, STEM, VERSION, VALUE) \ + TEST_F(FIXTURE, NAME##_read) \ + { \ + readProtoTest(STEM, VERSION, VALUE); \ + } \ + TEST_F(FIXTURE, NAME##_write) \ + { \ + writeProtoTest(STEM, VERSION, VALUE); \ + } + +#define VERSIONED_CHARACTERIZATION_TEST(FIXTURE, NAME, STEM, VERSION, VALUE) \ + VERSIONED_CHARACTERIZATION_TEST_NO_JSON(FIXTURE, NAME, STEM, VERSION, VALUE) \ + TEST_F(FIXTURE, NAME##_json_read) \ + { \ + readJsonTest(STEM, VALUE); \ + } \ + TEST_F(FIXTURE, NAME##_json_write) \ + { \ + writeJsonTest(STEM, VALUE); \ } } // namespace nix diff --git a/src/libstore-tests/common-protocol.cc b/src/libstore-tests/common-protocol.cc index 7c40e8cdb..fa676eb7f 100644 --- a/src/libstore-tests/common-protocol.cc +++ b/src/libstore-tests/common-protocol.cc @@ -3,6 +3,7 @@ #include #include +#include "nix/util/json-utils.hh" #include "nix/store/common-protocol.hh" #include "nix/store/common-protocol-impl.hh" #include "nix/store/build-result.hh" @@ -22,7 +23,7 @@ public: template void readProtoTest(PathView testStem, const T & expected) { - CharacterizationTest::readTest(testStem, [&](const auto & encoded) { + CharacterizationTest::readTest(std::string{testStem + ".bin"}, [&](const auto & encoded) { T got = ({ StringSource from{encoded}; CommonProto::Serialise::read(store, CommonProto::ReadConn{.from = from}); @@ -38,7 +39,7 @@ public: template void writeProtoTest(PathView testStem, const T & decoded) { - CharacterizationTest::writeTest(testStem, [&]() -> std::string { + CharacterizationTest::writeTest(std::string{testStem + ".bin"}, [&]() -> std::string { StringSink to; CommonProto::Serialise::write(store, CommonProto::WriteConn{.to = to}, decoded); return to.s; @@ -54,6 +55,14 @@ public: TEST_F(CommonProtoTest, NAME##_write) \ { \ writeProtoTest(STEM, VALUE); \ + } \ + TEST_F(CommonProtoTest, NAME##_json_read) \ + { \ + readJsonTest(STEM, VALUE); \ + } \ + TEST_F(CommonProtoTest, NAME##_json_write) \ + { \ + writeJsonTest(STEM, VALUE); \ } CHARACTERIZATION_TEST( diff --git a/src/libstore-tests/data/common-protocol/content-address.json b/src/libstore-tests/data/common-protocol/content-address.json new file mode 100644 index 000000000..9a0d57154 --- /dev/null +++ b/src/libstore-tests/data/common-protocol/content-address.json @@ -0,0 +1,26 @@ +[ + { + "hash": { + "algorithm": "sha256", + "format": "base64", + "hash": "+Xc9Ll6mcPltwaewrk/BAQ56Y3G5T//wzhKUc0zrYu0=" + }, + "method": "text" + }, + { + "hash": { + "algorithm": "sha1", + "format": "base64", + "hash": "gGemBoenViNZM3hiwqns/Fgzqwo=" + }, + "method": "flat" + }, + { + "hash": { + "algorithm": "sha256", + "format": "base64", + "hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=" + }, + "method": "nar" + } +] diff --git a/src/libstore-tests/data/common-protocol/drv-output.json b/src/libstore-tests/data/common-protocol/drv-output.json new file mode 100644 index 000000000..2668d70c9 --- /dev/null +++ b/src/libstore-tests/data/common-protocol/drv-output.json @@ -0,0 +1,4 @@ +[ + "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!quux" +] diff --git a/src/libstore-tests/data/common-protocol/optional-content-address.json b/src/libstore-tests/data/common-protocol/optional-content-address.json new file mode 100644 index 000000000..6cdaa59a5 --- /dev/null +++ b/src/libstore-tests/data/common-protocol/optional-content-address.json @@ -0,0 +1,11 @@ +[ + null, + { + "hash": { + "algorithm": "sha1", + "format": "base64", + "hash": "gGemBoenViNZM3hiwqns/Fgzqwo=" + }, + "method": "flat" + } +] diff --git a/src/libstore-tests/data/common-protocol/optional-store-path.json b/src/libstore-tests/data/common-protocol/optional-store-path.json new file mode 100644 index 000000000..58519a4d2 --- /dev/null +++ b/src/libstore-tests/data/common-protocol/optional-store-path.json @@ -0,0 +1,4 @@ +[ + null, + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" +] diff --git a/src/libstore-tests/data/common-protocol/realisation-with-deps.json b/src/libstore-tests/data/common-protocol/realisation-with-deps.json new file mode 100644 index 000000000..77148d14c --- /dev/null +++ b/src/libstore-tests/data/common-protocol/realisation-with-deps.json @@ -0,0 +1,13 @@ +[ + { + "dependentRealisations": { + "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!quux": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" + }, + "id": "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [ + "asdf", + "qwer" + ] + } +] diff --git a/src/libstore-tests/data/common-protocol/realisation.json b/src/libstore-tests/data/common-protocol/realisation.json new file mode 100644 index 000000000..f9ff09dbb --- /dev/null +++ b/src/libstore-tests/data/common-protocol/realisation.json @@ -0,0 +1,17 @@ +[ + { + "dependentRealisations": {}, + "id": "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [] + }, + { + "dependentRealisations": {}, + "id": "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [ + "asdf", + "qwer" + ] + } +] diff --git a/src/libstore-tests/data/common-protocol/set.json b/src/libstore-tests/data/common-protocol/set.json new file mode 100644 index 000000000..acd123082 --- /dev/null +++ b/src/libstore-tests/data/common-protocol/set.json @@ -0,0 +1,22 @@ +[ + [], + [ + "" + ], + [ + "", + "bar", + "foo" + ], + [ + [], + [ + "" + ], + [ + "", + "1", + "2" + ] + ] +] diff --git a/src/libstore-tests/data/common-protocol/store-path.json b/src/libstore-tests/data/common-protocol/store-path.json new file mode 100644 index 000000000..16459245b --- /dev/null +++ b/src/libstore-tests/data/common-protocol/store-path.json @@ -0,0 +1,4 @@ +[ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" +] diff --git a/src/libstore-tests/data/common-protocol/string.json b/src/libstore-tests/data/common-protocol/string.json new file mode 100644 index 000000000..d3db4f3b4 --- /dev/null +++ b/src/libstore-tests/data/common-protocol/string.json @@ -0,0 +1,7 @@ +[ + "", + "hi", + "white rabbit", + "大白兔", + "oh no " +] diff --git a/src/libstore-tests/data/common-protocol/vector.json b/src/libstore-tests/data/common-protocol/vector.json new file mode 100644 index 000000000..2b8cc1b3a --- /dev/null +++ b/src/libstore-tests/data/common-protocol/vector.json @@ -0,0 +1,22 @@ +[ + [], + [ + "" + ], + [ + "", + "foo", + "bar" + ], + [ + [], + [ + "" + ], + [ + "", + "1", + "2" + ] + ] +] diff --git a/src/libstore-tests/data/nar-info/impure.json b/src/libstore-tests/data/nar-info/impure.json index f35ff990b..13cfa8639 100644 --- a/src/libstore-tests/data/nar-info/impure.json +++ b/src/libstore-tests/data/nar-info/impure.json @@ -9,9 +9,17 @@ }, "compression": "xz", "deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", - "downloadHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", + "downloadHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, "downloadSize": 4029176, - "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, "narSize": 34878, "references": [ "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", diff --git a/src/libstore-tests/data/nar-info/pure.json b/src/libstore-tests/data/nar-info/pure.json index 2c5cb3bde..470f92da9 100644 --- a/src/libstore-tests/data/nar-info/pure.json +++ b/src/libstore-tests/data/nar-info/pure.json @@ -7,7 +7,11 @@ }, "method": "nar" }, - "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, "narSize": 34878, "references": [ "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", diff --git a/src/libstore-tests/data/path-info/empty_impure.json b/src/libstore-tests/data/path-info/empty_impure.json index 381acaa03..2fcd2078c 100644 --- a/src/libstore-tests/data/path-info/empty_impure.json +++ b/src/libstore-tests/data/path-info/empty_impure.json @@ -1,7 +1,11 @@ { "ca": null, "deriver": null, - "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, "narSize": 0, "references": [], "registrationTime": null, diff --git a/src/libstore-tests/data/path-info/empty_pure.json b/src/libstore-tests/data/path-info/empty_pure.json index 6d3fa646b..365e2f646 100644 --- a/src/libstore-tests/data/path-info/empty_pure.json +++ b/src/libstore-tests/data/path-info/empty_pure.json @@ -1,6 +1,10 @@ { "ca": null, - "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, "narSize": 0, "references": [], "version": 2 diff --git a/src/libstore-tests/data/path-info/impure.json b/src/libstore-tests/data/path-info/impure.json index 141b38a16..5e9944e5a 100644 --- a/src/libstore-tests/data/path-info/impure.json +++ b/src/libstore-tests/data/path-info/impure.json @@ -8,7 +8,11 @@ "method": "nar" }, "deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", - "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, "narSize": 34878, "references": [ "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", diff --git a/src/libstore-tests/data/path-info/pure.json b/src/libstore-tests/data/path-info/pure.json index 2c5cb3bde..470f92da9 100644 --- a/src/libstore-tests/data/path-info/pure.json +++ b/src/libstore-tests/data/path-info/pure.json @@ -7,7 +7,11 @@ }, "method": "nar" }, - "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, "narSize": 34878, "references": [ "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", diff --git a/src/libstore-tests/data/serve-protocol/build-result-2.2.json b/src/libstore-tests/data/serve-protocol/build-result-2.2.json new file mode 100644 index 000000000..029bcb5a8 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/build-result-2.2.json @@ -0,0 +1,28 @@ +[ + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "startTime": 0, + "status": "OutputRejected", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "startTime": 0, + "status": "NotDeterministic", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "builtOutputs": {}, + "startTime": 0, + "status": "Built", + "stopTime": 0, + "success": true, + "timesBuilt": 0 + } +] diff --git a/src/libstore-tests/data/serve-protocol/build-result-2.3.json b/src/libstore-tests/data/serve-protocol/build-result-2.3.json new file mode 100644 index 000000000..be14b0947 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/build-result-2.3.json @@ -0,0 +1,28 @@ +[ + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "startTime": 0, + "status": "OutputRejected", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "errorMsg": "no idea why", + "isNonDeterministic": true, + "startTime": 30, + "status": "NotDeterministic", + "stopTime": 50, + "success": false, + "timesBuilt": 3 + }, + { + "builtOutputs": {}, + "startTime": 30, + "status": "Built", + "stopTime": 50, + "success": true, + "timesBuilt": 0 + } +] diff --git a/src/libstore-tests/data/serve-protocol/build-result-2.6.json b/src/libstore-tests/data/serve-protocol/build-result-2.6.json new file mode 100644 index 000000000..30a8e82e9 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/build-result-2.6.json @@ -0,0 +1,41 @@ +[ + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "startTime": 0, + "status": "OutputRejected", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "errorMsg": "no idea why", + "isNonDeterministic": true, + "startTime": 30, + "status": "NotDeterministic", + "stopTime": 50, + "success": false, + "timesBuilt": 3 + }, + { + "builtOutputs": { + "bar": { + "dependentRealisations": {}, + "id": "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!bar", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "signatures": [] + }, + "foo": { + "dependentRealisations": {}, + "id": "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!foo", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [] + } + }, + "startTime": 30, + "status": "Built", + "stopTime": 50, + "success": true, + "timesBuilt": 1 + } +] diff --git a/src/libstore-tests/data/serve-protocol/content-address.json b/src/libstore-tests/data/serve-protocol/content-address.json new file mode 100644 index 000000000..9a0d57154 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/content-address.json @@ -0,0 +1,26 @@ +[ + { + "hash": { + "algorithm": "sha256", + "format": "base64", + "hash": "+Xc9Ll6mcPltwaewrk/BAQ56Y3G5T//wzhKUc0zrYu0=" + }, + "method": "text" + }, + { + "hash": { + "algorithm": "sha1", + "format": "base64", + "hash": "gGemBoenViNZM3hiwqns/Fgzqwo=" + }, + "method": "flat" + }, + { + "hash": { + "algorithm": "sha256", + "format": "base64", + "hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=" + }, + "method": "nar" + } +] diff --git a/src/libstore-tests/data/serve-protocol/drv-output.json b/src/libstore-tests/data/serve-protocol/drv-output.json new file mode 100644 index 000000000..2668d70c9 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/drv-output.json @@ -0,0 +1,4 @@ +[ + "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!quux" +] diff --git a/src/libstore-tests/data/serve-protocol/optional-content-address.json b/src/libstore-tests/data/serve-protocol/optional-content-address.json new file mode 100644 index 000000000..6cdaa59a5 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/optional-content-address.json @@ -0,0 +1,11 @@ +[ + null, + { + "hash": { + "algorithm": "sha1", + "format": "base64", + "hash": "gGemBoenViNZM3hiwqns/Fgzqwo=" + }, + "method": "flat" + } +] diff --git a/src/libstore-tests/data/serve-protocol/optional-store-path.json b/src/libstore-tests/data/serve-protocol/optional-store-path.json new file mode 100644 index 000000000..58519a4d2 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/optional-store-path.json @@ -0,0 +1,4 @@ +[ + null, + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" +] diff --git a/src/libstore-tests/data/serve-protocol/realisation-with-deps.json b/src/libstore-tests/data/serve-protocol/realisation-with-deps.json new file mode 100644 index 000000000..77148d14c --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/realisation-with-deps.json @@ -0,0 +1,13 @@ +[ + { + "dependentRealisations": { + "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!quux": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" + }, + "id": "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [ + "asdf", + "qwer" + ] + } +] diff --git a/src/libstore-tests/data/serve-protocol/realisation.json b/src/libstore-tests/data/serve-protocol/realisation.json new file mode 100644 index 000000000..f9ff09dbb --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/realisation.json @@ -0,0 +1,17 @@ +[ + { + "dependentRealisations": {}, + "id": "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [] + }, + { + "dependentRealisations": {}, + "id": "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [ + "asdf", + "qwer" + ] + } +] diff --git a/src/libstore-tests/data/serve-protocol/set.json b/src/libstore-tests/data/serve-protocol/set.json new file mode 100644 index 000000000..acd123082 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/set.json @@ -0,0 +1,22 @@ +[ + [], + [ + "" + ], + [ + "", + "bar", + "foo" + ], + [ + [], + [ + "" + ], + [ + "", + "1", + "2" + ] + ] +] diff --git a/src/libstore-tests/data/serve-protocol/store-path.json b/src/libstore-tests/data/serve-protocol/store-path.json new file mode 100644 index 000000000..16459245b --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/store-path.json @@ -0,0 +1,4 @@ +[ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" +] diff --git a/src/libstore-tests/data/serve-protocol/string.json b/src/libstore-tests/data/serve-protocol/string.json new file mode 100644 index 000000000..d3db4f3b4 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/string.json @@ -0,0 +1,7 @@ +[ + "", + "hi", + "white rabbit", + "大白兔", + "oh no " +] diff --git a/src/libstore-tests/data/serve-protocol/unkeyed-valid-path-info-2.3.json b/src/libstore-tests/data/serve-protocol/unkeyed-valid-path-info-2.3.json new file mode 100644 index 000000000..b8d914380 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/unkeyed-valid-path-info-2.3.json @@ -0,0 +1,34 @@ +[ + { + "ca": null, + "deriver": null, + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" + }, + "narSize": 34878, + "references": [], + "registrationTime": null, + "signatures": [], + "ultimate": false, + "version": 2 + }, + { + "ca": null, + "deriver": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" + }, + "narSize": 34878, + "references": [ + "g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo.drv" + ], + "registrationTime": null, + "signatures": [], + "ultimate": false, + "version": 2 + } +] diff --git a/src/libstore-tests/data/serve-protocol/unkeyed-valid-path-info-2.4.json b/src/libstore-tests/data/serve-protocol/unkeyed-valid-path-info-2.4.json new file mode 100644 index 000000000..725880590 --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/unkeyed-valid-path-info-2.4.json @@ -0,0 +1,47 @@ +[ + { + "ca": null, + "deriver": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, + "narSize": 34878, + "references": [ + "g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo.drv" + ], + "registrationTime": null, + "signatures": [], + "ultimate": false, + "version": 2 + }, + { + "ca": { + "hash": { + "algorithm": "sha256", + "format": "base64", + "hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=" + }, + "method": "nar" + }, + "deriver": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, + "narSize": 34878, + "references": [ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "n5wkd9frr45pa74if5gpz9j7mifg27fh-foo" + ], + "registrationTime": null, + "signatures": [ + "fake-sig-1", + "fake-sig-2" + ], + "ultimate": false, + "version": 2 + } +] diff --git a/src/libstore-tests/data/serve-protocol/vector.json b/src/libstore-tests/data/serve-protocol/vector.json new file mode 100644 index 000000000..2b8cc1b3a --- /dev/null +++ b/src/libstore-tests/data/serve-protocol/vector.json @@ -0,0 +1,22 @@ +[ + [], + [ + "" + ], + [ + "", + "foo", + "bar" + ], + [ + [], + [ + "" + ], + [ + "", + "1", + "2" + ] + ] +] diff --git a/src/libstore-tests/data/worker-protocol/build-mode.json b/src/libstore-tests/data/worker-protocol/build-mode.json new file mode 100644 index 000000000..2ef158f87 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/build-mode.json @@ -0,0 +1,5 @@ +[ + 0, + 1, + 2 +] diff --git a/src/libstore-tests/data/worker-protocol/build-result-1.27.json b/src/libstore-tests/data/worker-protocol/build-result-1.27.json new file mode 100644 index 000000000..029bcb5a8 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/build-result-1.27.json @@ -0,0 +1,28 @@ +[ + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "startTime": 0, + "status": "OutputRejected", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "startTime": 0, + "status": "NotDeterministic", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "builtOutputs": {}, + "startTime": 0, + "status": "Built", + "stopTime": 0, + "success": true, + "timesBuilt": 0 + } +] diff --git a/src/libstore-tests/data/worker-protocol/build-result-1.28.json b/src/libstore-tests/data/worker-protocol/build-result-1.28.json new file mode 100644 index 000000000..d02845b7f --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/build-result-1.28.json @@ -0,0 +1,41 @@ +[ + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "startTime": 0, + "status": "OutputRejected", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "startTime": 0, + "status": "NotDeterministic", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "builtOutputs": { + "bar": { + "dependentRealisations": {}, + "id": "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!bar", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "signatures": [] + }, + "foo": { + "dependentRealisations": {}, + "id": "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!foo", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [] + } + }, + "startTime": 0, + "status": "Built", + "stopTime": 0, + "success": true, + "timesBuilt": 0 + } +] diff --git a/src/libstore-tests/data/worker-protocol/build-result-1.29.json b/src/libstore-tests/data/worker-protocol/build-result-1.29.json new file mode 100644 index 000000000..30a8e82e9 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/build-result-1.29.json @@ -0,0 +1,41 @@ +[ + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "startTime": 0, + "status": "OutputRejected", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "errorMsg": "no idea why", + "isNonDeterministic": true, + "startTime": 30, + "status": "NotDeterministic", + "stopTime": 50, + "success": false, + "timesBuilt": 3 + }, + { + "builtOutputs": { + "bar": { + "dependentRealisations": {}, + "id": "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!bar", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "signatures": [] + }, + "foo": { + "dependentRealisations": {}, + "id": "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!foo", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [] + } + }, + "startTime": 30, + "status": "Built", + "stopTime": 50, + "success": true, + "timesBuilt": 1 + } +] diff --git a/src/libstore-tests/data/worker-protocol/build-result-1.37.json b/src/libstore-tests/data/worker-protocol/build-result-1.37.json new file mode 100644 index 000000000..61cddd2ca --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/build-result-1.37.json @@ -0,0 +1,43 @@ +[ + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "startTime": 0, + "status": "OutputRejected", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "errorMsg": "no idea why", + "isNonDeterministic": true, + "startTime": 30, + "status": "NotDeterministic", + "stopTime": 50, + "success": false, + "timesBuilt": 3 + }, + { + "builtOutputs": { + "bar": { + "dependentRealisations": {}, + "id": "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!bar", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "signatures": [] + }, + "foo": { + "dependentRealisations": {}, + "id": "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!foo", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [] + } + }, + "cpuSystem": 604000000, + "cpuUser": 500000000, + "startTime": 30, + "status": "Built", + "stopTime": 50, + "success": true, + "timesBuilt": 1 + } +] diff --git a/src/libstore-tests/data/worker-protocol/content-address.json b/src/libstore-tests/data/worker-protocol/content-address.json new file mode 100644 index 000000000..9a0d57154 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/content-address.json @@ -0,0 +1,26 @@ +[ + { + "hash": { + "algorithm": "sha256", + "format": "base64", + "hash": "+Xc9Ll6mcPltwaewrk/BAQ56Y3G5T//wzhKUc0zrYu0=" + }, + "method": "text" + }, + { + "hash": { + "algorithm": "sha1", + "format": "base64", + "hash": "gGemBoenViNZM3hiwqns/Fgzqwo=" + }, + "method": "flat" + }, + { + "hash": { + "algorithm": "sha256", + "format": "base64", + "hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=" + }, + "method": "nar" + } +] diff --git a/src/libstore-tests/data/worker-protocol/derived-path-1.29.json b/src/libstore-tests/data/worker-protocol/derived-path-1.29.json new file mode 100644 index 000000000..f0efe4a35 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/derived-path-1.29.json @@ -0,0 +1,16 @@ +[ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + { + "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "outputs": [ + "*" + ] + }, + { + "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "outputs": [ + "x", + "y" + ] + } +] diff --git a/src/libstore-tests/data/worker-protocol/derived-path-1.30.json b/src/libstore-tests/data/worker-protocol/derived-path-1.30.json new file mode 100644 index 000000000..7a67e4761 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/derived-path-1.30.json @@ -0,0 +1,17 @@ +[ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv", + { + "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "outputs": [ + "*" + ] + }, + { + "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "outputs": [ + "x", + "y" + ] + } +] diff --git a/src/libstore-tests/data/worker-protocol/drv-output.json b/src/libstore-tests/data/worker-protocol/drv-output.json new file mode 100644 index 000000000..2668d70c9 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/drv-output.json @@ -0,0 +1,4 @@ +[ + "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!quux" +] diff --git a/src/libstore-tests/data/worker-protocol/keyed-build-result-1.29.json b/src/libstore-tests/data/worker-protocol/keyed-build-result-1.29.json new file mode 100644 index 000000000..c15d47aa3 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/keyed-build-result-1.29.json @@ -0,0 +1,27 @@ +[ + { + "errorMsg": "no idea why", + "isNonDeterministic": false, + "path": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-xxx", + "startTime": 0, + "status": "OutputRejected", + "stopTime": 0, + "success": false, + "timesBuilt": 0 + }, + { + "errorMsg": "no idea why", + "isNonDeterministic": true, + "path": { + "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "outputs": [ + "out" + ] + }, + "startTime": 30, + "status": "NotDeterministic", + "stopTime": 50, + "success": false, + "timesBuilt": 3 + } +] diff --git a/src/libstore-tests/data/worker-protocol/optional-content-address.json b/src/libstore-tests/data/worker-protocol/optional-content-address.json new file mode 100644 index 000000000..6cdaa59a5 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/optional-content-address.json @@ -0,0 +1,11 @@ +[ + null, + { + "hash": { + "algorithm": "sha1", + "format": "base64", + "hash": "gGemBoenViNZM3hiwqns/Fgzqwo=" + }, + "method": "flat" + } +] diff --git a/src/libstore-tests/data/worker-protocol/optional-store-path.json b/src/libstore-tests/data/worker-protocol/optional-store-path.json new file mode 100644 index 000000000..58519a4d2 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/optional-store-path.json @@ -0,0 +1,4 @@ +[ + null, + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" +] diff --git a/src/libstore-tests/data/worker-protocol/optional-trusted-flag.json b/src/libstore-tests/data/worker-protocol/optional-trusted-flag.json new file mode 100644 index 000000000..2f3c092f8 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/optional-trusted-flag.json @@ -0,0 +1,5 @@ +[ + null, + true, + false +] diff --git a/src/libstore-tests/data/worker-protocol/realisation-with-deps.json b/src/libstore-tests/data/worker-protocol/realisation-with-deps.json new file mode 100644 index 000000000..77148d14c --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/realisation-with-deps.json @@ -0,0 +1,13 @@ +[ + { + "dependentRealisations": { + "sha256:6f869f9ea2823bda165e06076fd0de4366dead2c0e8d2dbbad277d4f15c373f5!quux": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" + }, + "id": "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [ + "asdf", + "qwer" + ] + } +] diff --git a/src/libstore-tests/data/worker-protocol/realisation.json b/src/libstore-tests/data/worker-protocol/realisation.json new file mode 100644 index 000000000..f9ff09dbb --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/realisation.json @@ -0,0 +1,17 @@ +[ + { + "dependentRealisations": {}, + "id": "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [] + }, + { + "dependentRealisations": {}, + "id": "sha256:15e3c560894cbb27085cf65b5a2ecb18488c999497f4531b6907a7581ce6d527!baz", + "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "signatures": [ + "asdf", + "qwer" + ] + } +] diff --git a/src/libstore-tests/data/worker-protocol/set.json b/src/libstore-tests/data/worker-protocol/set.json new file mode 100644 index 000000000..acd123082 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/set.json @@ -0,0 +1,22 @@ +[ + [], + [ + "" + ], + [ + "", + "bar", + "foo" + ], + [ + [], + [ + "" + ], + [ + "", + "1", + "2" + ] + ] +] diff --git a/src/libstore-tests/data/worker-protocol/store-path.json b/src/libstore-tests/data/worker-protocol/store-path.json new file mode 100644 index 000000000..16459245b --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/store-path.json @@ -0,0 +1,4 @@ +[ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo", + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" +] diff --git a/src/libstore-tests/data/worker-protocol/string.json b/src/libstore-tests/data/worker-protocol/string.json new file mode 100644 index 000000000..d3db4f3b4 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/string.json @@ -0,0 +1,7 @@ +[ + "", + "hi", + "white rabbit", + "大白兔", + "oh no " +] diff --git a/src/libstore-tests/data/worker-protocol/unkeyed-valid-path-info-1.15.json b/src/libstore-tests/data/worker-protocol/unkeyed-valid-path-info-1.15.json new file mode 100644 index 000000000..0d78d3875 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/unkeyed-valid-path-info-1.15.json @@ -0,0 +1,34 @@ +[ + { + "ca": null, + "deriver": null, + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, + "narSize": 34878, + "references": [], + "registrationTime": 23423, + "signatures": [], + "ultimate": false, + "version": 2 + }, + { + "ca": null, + "deriver": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, + "narSize": 34878, + "references": [ + "g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo.drv" + ], + "registrationTime": 23423, + "signatures": [], + "ultimate": false, + "version": 2 + } +] diff --git a/src/libstore-tests/data/worker-protocol/valid-path-info-1.15.json b/src/libstore-tests/data/worker-protocol/valid-path-info-1.15.json new file mode 100644 index 000000000..6d153ee1c --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/valid-path-info-1.15.json @@ -0,0 +1,37 @@ +[ + { + "ca": null, + "deriver": null, + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, + "narSize": 34878, + "path": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "references": [], + "registrationTime": 23423, + "signatures": [], + "ultimate": false, + "version": 2 + }, + { + "ca": null, + "deriver": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, + "narSize": 34878, + "path": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "references": [ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo" + ], + "registrationTime": 23423, + "signatures": [], + "ultimate": false, + "version": 2 + } +] diff --git a/src/libstore-tests/data/worker-protocol/valid-path-info-1.16.json b/src/libstore-tests/data/worker-protocol/valid-path-info-1.16.json new file mode 100644 index 000000000..9e2806824 --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/valid-path-info-1.16.json @@ -0,0 +1,66 @@ +[ + { + "ca": null, + "deriver": null, + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, + "narSize": 34878, + "path": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "references": [], + "registrationTime": 23423, + "signatures": [], + "ultimate": true, + "version": 2 + }, + { + "ca": null, + "deriver": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv", + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, + "narSize": 34878, + "path": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "references": [ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo" + ], + "registrationTime": 23423, + "signatures": [ + "fake-sig-1", + "fake-sig-2" + ], + "ultimate": false, + "version": 2 + }, + { + "ca": { + "hash": { + "algorithm": "sha256", + "format": "base64", + "hash": "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=" + }, + "method": "nar" + }, + "deriver": null, + "narHash": { + "algorithm": "sha256", + "format": "base64", + "hash": "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=" + }, + "narSize": 34878, + "path": "n5wkd9frr45pa74if5gpz9j7mifg27fh-foo", + "references": [ + "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar", + "n5wkd9frr45pa74if5gpz9j7mifg27fh-foo" + ], + "registrationTime": 23423, + "signatures": [], + "ultimate": false, + "version": 2 + } +] diff --git a/src/libstore-tests/data/worker-protocol/vector.json b/src/libstore-tests/data/worker-protocol/vector.json new file mode 100644 index 000000000..2b8cc1b3a --- /dev/null +++ b/src/libstore-tests/data/worker-protocol/vector.json @@ -0,0 +1,22 @@ +[ + [], + [ + "" + ], + [ + "", + "foo", + "bar" + ], + [ + [], + [ + "" + ], + [ + "", + "1", + "2" + ] + ] +] diff --git a/src/libstore-tests/nar-info.cc b/src/libstore-tests/nar-info.cc index 751c5e305..1add98053 100644 --- a/src/libstore-tests/nar-info.cc +++ b/src/libstore-tests/nar-info.cc @@ -59,24 +59,24 @@ static NarInfo makeNarInfo(const Store & store, bool includeImpureInfo) return info; } -#define JSON_TEST(STEM, PURE) \ - TEST_F(NarInfoTest, NarInfo_##STEM##_from_json) \ - { \ - readTest(#STEM, [&](const auto & encoded_) { \ - auto encoded = json::parse(encoded_); \ - auto expected = makeNarInfo(*store, PURE); \ - NarInfo got = NarInfo::fromJSON(*store, expected.path, encoded); \ - ASSERT_EQ(got, expected); \ - }); \ - } \ - \ - TEST_F(NarInfoTest, NarInfo_##STEM##_to_json) \ - { \ - writeTest( \ - #STEM, \ - [&]() -> json { return makeNarInfo(*store, PURE).toJSON(*store, PURE, HashFormat::SRI); }, \ - [](const auto & file) { return json::parse(readFile(file)); }, \ - [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ +#define JSON_TEST(STEM, PURE) \ + TEST_F(NarInfoTest, NarInfo_##STEM##_from_json) \ + { \ + readTest(#STEM, [&](const auto & encoded_) { \ + auto encoded = json::parse(encoded_); \ + auto expected = makeNarInfo(*store, PURE); \ + auto got = UnkeyedNarInfo::fromJSON(&*store, encoded); \ + ASSERT_EQ(got, expected); \ + }); \ + } \ + \ + TEST_F(NarInfoTest, NarInfo_##STEM##_to_json) \ + { \ + writeTest( \ + #STEM, \ + [&]() -> json { return makeNarInfo(*store, PURE).toJSON(&*store, PURE); }, \ + [](const auto & file) { return json::parse(readFile(file)); }, \ + [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ } JSON_TEST(pure, false) diff --git a/src/libstore-tests/path-info.cc b/src/libstore-tests/path-info.cc index 63310c1c3..8c02bf403 100644 --- a/src/libstore-tests/path-info.cc +++ b/src/libstore-tests/path-info.cc @@ -70,7 +70,7 @@ static UnkeyedValidPathInfo makeFull(const Store & store, bool includeImpureInfo { \ readTest(#STEM, [&](const auto & encoded_) { \ auto encoded = json::parse(encoded_); \ - UnkeyedValidPathInfo got = UnkeyedValidPathInfo::fromJSON(*store, encoded); \ + UnkeyedValidPathInfo got = UnkeyedValidPathInfo::fromJSON(&*store, encoded); \ auto expected = OBJ; \ ASSERT_EQ(got, expected); \ }); \ @@ -80,7 +80,7 @@ static UnkeyedValidPathInfo makeFull(const Store & store, bool includeImpureInfo { \ writeTest( \ #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, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ } diff --git a/src/libstore-tests/serve-protocol.cc b/src/libstore-tests/serve-protocol.cc index a7b69821c..e04d89e3d 100644 --- a/src/libstore-tests/serve-protocol.cc +++ b/src/libstore-tests/serve-protocol.cc @@ -4,6 +4,7 @@ #include #include +#include "nix/util/json-utils.hh" #include "nix/store/serve-protocol.hh" #include "nix/store/serve-protocol-impl.hh" #include "nix/store/serve-protocol-connection.hh" @@ -334,7 +335,7 @@ VERSIONED_CHARACTERIZATION_TEST( }), })) -VERSIONED_CHARACTERIZATION_TEST( +VERSIONED_CHARACTERIZATION_TEST_NO_JSON( ServeProtoTest, build_options_2_1, "build-options-2.1", @@ -344,7 +345,7 @@ VERSIONED_CHARACTERIZATION_TEST( .buildTimeout = 6, })) -VERSIONED_CHARACTERIZATION_TEST( +VERSIONED_CHARACTERIZATION_TEST_NO_JSON( ServeProtoTest, build_options_2_2, "build-options-2.2", @@ -355,7 +356,7 @@ VERSIONED_CHARACTERIZATION_TEST( .maxLogSize = 7, })) -VERSIONED_CHARACTERIZATION_TEST( +VERSIONED_CHARACTERIZATION_TEST_NO_JSON( ServeProtoTest, build_options_2_3, "build-options-2.3", @@ -368,7 +369,7 @@ VERSIONED_CHARACTERIZATION_TEST( .enforceDeterminism = true, })) -VERSIONED_CHARACTERIZATION_TEST( +VERSIONED_CHARACTERIZATION_TEST_NO_JSON( ServeProtoTest, build_options_2_7, "build-options-2.7", @@ -439,7 +440,7 @@ VERSIONED_CHARACTERIZATION_TEST( TEST_F(ServeProtoTest, handshake_log) { - CharacterizationTest::writeTest("handshake-to-client", [&]() -> std::string { + CharacterizationTest::writeTest("handshake-to-client.bin", [&]() -> std::string { StringSink toClientLog; Pipe toClient, toServer; @@ -475,7 +476,7 @@ struct NullBufferedSink : BufferedSink TEST_F(ServeProtoTest, handshake_client_replay) { - CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) { + CharacterizationTest::readTest("handshake-to-client.bin", [&](std::string toClientLog) { NullBufferedSink nullSink; StringSource in{toClientLog}; @@ -487,7 +488,7 @@ TEST_F(ServeProtoTest, handshake_client_replay) TEST_F(ServeProtoTest, handshake_client_truncated_replay_throws) { - CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) { + CharacterizationTest::readTest("handshake-to-client.bin", [&](std::string toClientLog) { for (size_t len = 0; len < toClientLog.size(); ++len) { NullBufferedSink nullSink; auto substring = toClientLog.substr(0, len); @@ -505,7 +506,7 @@ TEST_F(ServeProtoTest, handshake_client_truncated_replay_throws) TEST_F(ServeProtoTest, handshake_client_corrupted_throws) { - CharacterizationTest::readTest("handshake-to-client", [&](const std::string toClientLog) { + CharacterizationTest::readTest("handshake-to-client.bin", [&](const std::string toClientLog) { for (size_t idx = 0; idx < toClientLog.size(); ++idx) { // corrupt a copy std::string toClientLogCorrupt = toClientLog; diff --git a/src/libstore-tests/worker-protocol.cc b/src/libstore-tests/worker-protocol.cc index 8f70e937b..1e0ede81c 100644 --- a/src/libstore-tests/worker-protocol.cc +++ b/src/libstore-tests/worker-protocol.cc @@ -4,6 +4,7 @@ #include #include +#include "nix/util/json-utils.hh" #include "nix/store/worker-protocol.hh" #include "nix/store/worker-protocol-connection.hh" #include "nix/store/worker-protocol-impl.hh" @@ -649,7 +650,7 @@ VERSIONED_CHARACTERIZATION_TEST( }, })) -VERSIONED_CHARACTERIZATION_TEST( +VERSIONED_CHARACTERIZATION_TEST_NO_JSON( WorkerProtoTest, clientHandshakeInfo_1_30, "client-handshake-info_1_30", @@ -658,7 +659,7 @@ VERSIONED_CHARACTERIZATION_TEST( {}, })) -VERSIONED_CHARACTERIZATION_TEST( +VERSIONED_CHARACTERIZATION_TEST_NO_JSON( WorkerProtoTest, clientHandshakeInfo_1_33, "client-handshake-info_1_33", @@ -672,7 +673,7 @@ VERSIONED_CHARACTERIZATION_TEST( }, })) -VERSIONED_CHARACTERIZATION_TEST( +VERSIONED_CHARACTERIZATION_TEST_NO_JSON( WorkerProtoTest, clientHandshakeInfo_1_35, "client-handshake-info_1_35", @@ -690,7 +691,7 @@ VERSIONED_CHARACTERIZATION_TEST( TEST_F(WorkerProtoTest, handshake_log) { - CharacterizationTest::writeTest("handshake-to-client", [&]() -> std::string { + CharacterizationTest::writeTest("handshake-to-client.bin", [&]() -> std::string { StringSink toClientLog; Pipe toClient, toServer; @@ -751,7 +752,7 @@ struct NullBufferedSink : BufferedSink TEST_F(WorkerProtoTest, handshake_client_replay) { - CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) { + CharacterizationTest::readTest("handshake-to-client.bin", [&](std::string toClientLog) { NullBufferedSink nullSink; StringSource in{toClientLog}; @@ -764,7 +765,7 @@ TEST_F(WorkerProtoTest, handshake_client_replay) TEST_F(WorkerProtoTest, handshake_client_truncated_replay_throws) { - CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) { + CharacterizationTest::readTest("handshake-to-client.bin", [&](std::string toClientLog) { for (size_t len = 0; len < toClientLog.size(); ++len) { NullBufferedSink nullSink; auto substring = toClientLog.substr(0, len); @@ -782,7 +783,7 @@ TEST_F(WorkerProtoTest, handshake_client_truncated_replay_throws) TEST_F(WorkerProtoTest, handshake_client_corrupted_throws) { - CharacterizationTest::readTest("handshake-to-client", [&](const std::string toClientLog) { + CharacterizationTest::readTest("handshake-to-client.bin", [&](const std::string toClientLog) { for (size_t idx = 0; idx < toClientLog.size(); ++idx) { // corrupt a copy std::string toClientLogCorrupt = toClientLog; diff --git a/src/libstore/build-result.cc b/src/libstore/build-result.cc index e3d9e9085..f4bc8ab33 100644 --- a/src/libstore/build-result.cc +++ b/src/libstore/build-result.cc @@ -153,4 +153,20 @@ BuildResult adl_serializer::from_json(const json & _json) return br; } +KeyedBuildResult adl_serializer::from_json(const json & json0) +{ + auto json = getObject(json0); + + return KeyedBuildResult{ + adl_serializer::from_json(json0), + valueAt(json, "path"), + }; +} + +void adl_serializer::to_json(json & json, const KeyedBuildResult & kbr) +{ + adl_serializer::to_json(json, kbr); + json["path"] = kbr.path; +} + } // namespace nlohmann diff --git a/src/libstore/derivation-options.cc b/src/libstore/derivation-options.cc index 75313841c..265f28e80 100644 --- a/src/libstore/derivation-options.cc +++ b/src/libstore/derivation-options.cc @@ -423,15 +423,6 @@ void adl_serializer::to_json(json & json, const DerivationOpt json["allowSubstitutes"] = o.allowSubstitutes; } -template -static inline std::optional ptrToOwned(const json * ptr) -{ - if (ptr) - return std::optional{*ptr}; - else - return std::nullopt; -} - DerivationOptions::OutputChecks adl_serializer::from_json(const json & json_) { auto & json = getObject(json_); diff --git a/src/libstore/include/nix/store/build-result.hh b/src/libstore/include/nix/store/build-result.hh index 4739232f8..96134791b 100644 --- a/src/libstore/include/nix/store/build-result.hh +++ b/src/libstore/include/nix/store/build-result.hh @@ -178,3 +178,4 @@ struct KeyedBuildResult : BuildResult } // namespace nix JSON_IMPL(nix::BuildResult) +JSON_IMPL(nix::KeyedBuildResult) diff --git a/src/libstore/include/nix/store/nar-info.hh b/src/libstore/include/nix/store/nar-info.hh index 1684837c6..92af0b7d5 100644 --- a/src/libstore/include/nix/store/nar-info.hh +++ b/src/libstore/include/nix/store/nar-info.hh @@ -9,17 +9,38 @@ namespace nix { struct StoreDirConfig; -struct NarInfo : ValidPathInfo +struct UnkeyedNarInfo : virtual UnkeyedValidPathInfo { std::string url; std::string compression; std::optional fileHash; 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(ValidPathInfo info) - : ValidPathInfo{std::move(info)} + : UnkeyedValidPathInfo(std::move(static_cast(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); 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; - - 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 + +JSON_IMPL(nix::UnkeyedNarInfo) diff --git a/src/libstore/include/nix/store/path-info.hh b/src/libstore/include/nix/store/path-info.hh index cbc5abdb4..a64e8458d 100644 --- a/src/libstore/include/nix/store/path-info.hh +++ b/src/libstore/include/nix/store/path-info.hh @@ -117,11 +117,11 @@ struct UnkeyedValidPathInfo * @param includeImpureInfo If true, variable elements such as the * registration time are included. */ - virtual nlohmann::json toJSON(const StoreDirConfig & store, bool includeImpureInfo, HashFormat hashFormat) const; - static UnkeyedValidPathInfo fromJSON(const StoreDirConfig & store, const nlohmann::json & json); + virtual nlohmann::json toJSON(const StoreDirConfig * store, bool includeImpureInfo) const; + static UnkeyedValidPathInfo fromJSON(const StoreDirConfig * store, const nlohmann::json & json); }; -struct ValidPathInfo : UnkeyedValidPathInfo +struct ValidPathInfo : virtual UnkeyedValidPathInfo { StorePath path; @@ -174,10 +174,14 @@ struct ValidPathInfo : UnkeyedValidPathInfo ValidPathInfo(StorePath && path, UnkeyedValidPathInfo info) : UnkeyedValidPathInfo(info) - , path(std::move(path)) {}; + , path(std::move(path)) + { + } + ValidPathInfo(const StorePath & path, UnkeyedValidPathInfo info) - : UnkeyedValidPathInfo(info) - , path(path) {}; + : ValidPathInfo(StorePath{path}, std::move(info)) + { + } static ValidPathInfo makeFromCA(const StoreDirConfig & store, std::string_view name, ContentAddressWithReferences && ca, Hash narHash); @@ -191,3 +195,6 @@ static_assert(std::is_move_constructible_v); using ValidPathInfos = std::map; } // namespace nix + +JSON_IMPL(nix::UnkeyedValidPathInfo) +JSON_IMPL(nix::ValidPathInfo) diff --git a/src/libstore/include/nix/store/realisation.hh b/src/libstore/include/nix/store/realisation.hh index e8a71862e..af0e4aefd 100644 --- a/src/libstore/include/nix/store/realisation.hh +++ b/src/libstore/include/nix/store/realisation.hh @@ -182,5 +182,6 @@ public: } // namespace nix +JSON_IMPL(nix::DrvOutput) JSON_IMPL(nix::UnkeyedRealisation) JSON_IMPL(nix::Realisation) diff --git a/src/libstore/include/nix/store/store-api.hh b/src/libstore/include/nix/store/store-api.hh index c57eff1f0..4c0b156fa 100644 --- a/src/libstore/include/nix/store/store-api.hh +++ b/src/libstore/include/nix/store/store-api.hh @@ -1004,4 +1004,10 @@ const ContentAddress * getDerivationCA(const BasicDerivation & drv); std::map drvOutputReferences(Store & store, const Derivation & drv, const StorePath & outputPath, Store * evalStore = nullptr); +template<> +struct json_avoids_null : std::true_type +{}; + } // namespace nix + +JSON_IMPL(nix::TrustedFlag) diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index 8b2a7287e..ea0c8a3c2 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -10,6 +10,7 @@ #include "nix/util/closure.hh" #include "nix/store/filetransfer.hh" #include "nix/util/strings.hh" +#include "nix/util/json-utils.hh" #include @@ -479,3 +480,19 @@ OutputPathMap resolveDerivedPath(Store & store, const DerivedPath::Built & bfd) } } // namespace nix + +namespace nlohmann { + +using namespace nix; + +TrustedFlag adl_serializer::from_json(const json & json) +{ + return getBoolean(json) ? TrustedFlag::Trusted : TrustedFlag::NotTrusted; +} + +void adl_serializer::to_json(json & json, const TrustedFlag & trustedFlag) +{ + json = static_cast(trustedFlag); +} + +} // namespace nlohmann diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc index 6f1abb273..2dbcee325 100644 --- a/src/libstore/nar-info.cc +++ b/src/libstore/nar-info.cc @@ -7,7 +7,9 @@ namespace nix { 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(*this)) // FIXME: hack + , UnkeyedNarInfo(static_cast(*this)) { unsigned line = 1; @@ -130,11 +132,11 @@ std::string NarInfo::to_string(const StoreDirConfig & store) const 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; - auto jsonObject = ValidPathInfo::toJSON(store, includeImpureInfo, hashFormat); + auto jsonObject = UnkeyedValidPathInfo::toJSON(store, includeImpureInfo); if (includeImpureInfo) { if (!url.empty()) @@ -142,7 +144,7 @@ nlohmann::json NarInfo::toJSON(const StoreDirConfig & store, bool includeImpureI if (!compression.empty()) jsonObject["compression"] = compression; if (fileHash) - jsonObject["downloadHash"] = fileHash->to_string(hashFormat, true); + jsonObject["downloadHash"] = *fileHash; if (fileSize) jsonObject["downloadSize"] = fileSize; } @@ -150,30 +152,43 @@ nlohmann::json NarInfo::toJSON(const StoreDirConfig & store, bool includeImpureI 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; - NarInfo res{ValidPathInfo{ - path, - UnkeyedValidPathInfo::fromJSON(store, json), - }}; + UnkeyedNarInfo res{UnkeyedValidPathInfo::fromJSON(store, json)}; auto & obj = getObject(json); - if (json.contains("url")) - res.url = getString(valueAt(obj, "url")); + if (auto * url = get(obj, "url")) + res.url = getString(*url); - if (json.contains("compression")) - res.compression = getString(valueAt(obj, "compression")); + if (auto * compression = get(obj, "compression")) + res.compression = getString(*compression); - if (json.contains("downloadHash")) - res.fileHash = Hash::parseAny(getString(valueAt(obj, "downloadHash")), std::nullopt); + if (auto * downloadHash = get(obj, "downloadHash")) + res.fileHash = *downloadHash; - if (json.contains("downloadSize")) - res.fileSize = getUnsigned(valueAt(obj, "downloadSize")); + if (auto * downloadSize = get(obj, "downloadSize")) + res.fileSize = getUnsigned(*downloadSize); return res; } } // namespace nix + +namespace nlohmann { + +using namespace nix; + +UnkeyedNarInfo adl_serializer::from_json(const json & json) +{ + return UnkeyedNarInfo::fromJSON(nullptr, json); +} + +void adl_serializer::to_json(json & json, const UnkeyedNarInfo & c) +{ + json = c.toJSON(nullptr, true); +} + +} // namespace nlohmann diff --git a/src/libstore/path-info.cc b/src/libstore/path-info.cc index c535d08f4..6b7469e33 100644 --- a/src/libstore/path-info.cc +++ b/src/libstore/path-info.cc @@ -149,8 +149,7 @@ ValidPathInfo ValidPathInfo::makeFromCA( return res; } -nlohmann::json -UnkeyedValidPathInfo::toJSON(const StoreDirConfig & store, bool includeImpureInfo, HashFormat hashFormat) const +nlohmann::json UnkeyedValidPathInfo::toJSON(const StoreDirConfig * store, bool includeImpureInfo) const { using nlohmann::json; @@ -158,19 +157,21 @@ UnkeyedValidPathInfo::toJSON(const StoreDirConfig & store, bool includeImpureInf jsonObject["version"] = 2; - jsonObject["narHash"] = narHash.to_string(hashFormat, true); + jsonObject["narHash"] = narHash; jsonObject["narSize"] = narSize; { auto & jsonRefs = jsonObject["references"] = json::array(); for (auto & ref : references) - jsonRefs.emplace_back(store.printStorePath(ref)); + jsonRefs.emplace_back(store ? static_cast(store->printStorePath(ref)) : static_cast(ref)); } jsonObject["ca"] = ca; if (includeImpureInfo) { - jsonObject["deriver"] = deriver ? (std::optional{store.printStorePath(*deriver)}) : std::nullopt; + jsonObject["deriver"] = deriver ? (store ? static_cast(std::optional{store->printStorePath(*deriver)}) + : static_cast(std::optional{*deriver})) + : static_cast(std::optional{}); jsonObject["registrationTime"] = registrationTime ? (std::optional{registrationTime}) : std::nullopt; @@ -184,7 +185,7 @@ UnkeyedValidPathInfo::toJSON(const StoreDirConfig & store, bool includeImpureInf return jsonObject; } -UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(const StoreDirConfig & store, const nlohmann::json & _json) +UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(const StoreDirConfig * store, const nlohmann::json & _json) { UnkeyedValidPathInfo res{ Hash(Hash::dummy), @@ -192,44 +193,34 @@ UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(const StoreDirConfig & store auto & json = getObject(_json); - // Check version (optional for backward compatibility) - nlohmann::json::number_unsigned_t version = 1; - if (json.contains("version")) { - version = getUnsigned(valueAt(json, "version")); - if (version != 1 && version != 2) { - throw Error("Unsupported path info JSON format version %d, expected 1 through 2", version); - } + { + auto version = getUnsigned(valueAt(json, "version")); + if (version != 2) + throw Error("Unsupported path info JSON format version %d, only version 2 is currently supported", version); } - res.narHash = Hash::parseAny(getString(valueAt(json, "narHash")), std::nullopt); + res.narHash = valueAt(json, "narHash"); res.narSize = getUnsigned(valueAt(json, "narSize")); try { auto references = getStringList(valueAt(json, "references")); for (auto & input : references) - res.references.insert(store.parseStorePath(static_cast(input))); + res.references.insert(store ? store->parseStorePath(getString(input)) : static_cast(input)); } catch (Error & e) { e.addTrace({}, "while reading key 'references'"); throw; } - // New format as this as nullable but mandatory field; handling - // missing is for back-compat. - if (auto * rawCa0 = optionalValueAt(json, "ca")) - if (auto * rawCa = getNullable(*rawCa0)) - switch (version) { - case 1: - // old string format also used in SQLite DB and .narinfo - res.ca = ContentAddress::parse(getString(*rawCa)); - break; - case 2 ... std::numeric_limits::max(): - res.ca = *rawCa; - break; - } + try { + res.ca = ptrToOwned(getNullable(valueAt(json, "ca"))); + } catch (Error & e) { + e.addTrace({}, "while reading key 'ca'"); + throw; + } if (auto * rawDeriver0 = optionalValueAt(json, "deriver")) if (auto * rawDeriver = getNullable(*rawDeriver0)) - res.deriver = store.parseStorePath(getString(*rawDeriver)); + res.deriver = store ? store->parseStorePath(getString(*rawDeriver)) : static_cast(*rawDeriver); if (auto * rawRegistrationTime0 = optionalValueAt(json, "registrationTime")) if (auto * rawRegistrationTime = getNullable(*rawRegistrationTime0)) @@ -245,3 +236,35 @@ UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(const StoreDirConfig & store } } // namespace nix + +namespace nlohmann { + +using namespace nix; + +UnkeyedValidPathInfo adl_serializer::from_json(const json & json) +{ + return UnkeyedValidPathInfo::fromJSON(nullptr, json); +} + +void adl_serializer::to_json(json & json, const UnkeyedValidPathInfo & c) +{ + json = c.toJSON(nullptr, true); +} + +ValidPathInfo adl_serializer::from_json(const json & json0) +{ + auto json = getObject(json0); + + return ValidPathInfo{ + valueAt(json, "path"), + adl_serializer::from_json(json0), + }; +} + +void adl_serializer::to_json(json & json, const ValidPathInfo & v) +{ + adl_serializer::to_json(json, v); + json["path"] = v.path; +} + +} // namespace nlohmann diff --git a/src/libstore/realisation.cc b/src/libstore/realisation.cc index a7f3b98d6..4aeb05874 100644 --- a/src/libstore/realisation.cc +++ b/src/libstore/realisation.cc @@ -144,6 +144,16 @@ namespace nlohmann { using namespace nix; +DrvOutput adl_serializer::from_json(const json & json) +{ + return DrvOutput::parse(getString(json)); +} + +void adl_serializer::to_json(json & json, const DrvOutput & drvOutput) +{ + json = drvOutput.to_string(); +} + UnkeyedRealisation adl_serializer::from_json(const json & json0) { auto json = getObject(json0); @@ -182,14 +192,14 @@ Realisation adl_serializer::from_json(const json & json0) return Realisation{ static_cast(json0), - DrvOutput::parse(valueAt(json, "id")), + valueAt(json, "id"), }; } void adl_serializer::to_json(json & json, const Realisation & r) { json = static_cast(r); - json["id"] = r.id.to_string(); + json["id"] = r.id; } } // namespace nlohmann diff --git a/src/libutil-test-support/include/nix/util/tests/json-characterization.hh b/src/libutil-test-support/include/nix/util/tests/json-characterization.hh index d713c615b..0ee6fd2fd 100644 --- a/src/libutil-test-support/include/nix/util/tests/json-characterization.hh +++ b/src/libutil-test-support/include/nix/util/tests/json-characterization.hh @@ -11,6 +11,34 @@ namespace nix { +/** + * Golden test for JSON reading + */ +template +void readJsonTest(CharacterizationTest & test, PathView testStem, const T & expected, auto... args) +{ + using namespace nlohmann; + test.readTest(Path{testStem} + ".json", [&](const auto & encodedRaw) { + auto encoded = json::parse(encodedRaw); + T decoded = adl_serializer::from_json(encoded, args...); + ASSERT_EQ(decoded, expected); + }); +} + +/** + * Golden test for JSON writing + */ +template +void writeJsonTest(CharacterizationTest & test, PathView testStem, const T & value) +{ + using namespace nlohmann; + test.writeTest( + Path{testStem} + ".json", + [&]() -> json { return static_cast(value); }, + [](const auto & file) { return json::parse(readFile(file)); }, + [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); +} + /** * Mixin class for writing characterization tests for `nlohmann::json` * conversions for a given type. @@ -26,12 +54,7 @@ struct JsonCharacterizationTest : virtual CharacterizationTest */ void readJsonTest(PathView testStem, const T & expected, auto... args) { - using namespace nlohmann; - readTest(Path{testStem} + ".json", [&](const auto & encodedRaw) { - auto encoded = json::parse(encodedRaw); - T decoded = adl_serializer::from_json(encoded, args...); - ASSERT_EQ(decoded, expected); - }); + nix::readJsonTest(*this, testStem, expected, args...); } /** @@ -42,12 +65,7 @@ struct JsonCharacterizationTest : virtual CharacterizationTest */ void writeJsonTest(PathView testStem, const T & value) { - using namespace nlohmann; - writeTest( - Path{testStem} + ".json", - [&]() -> json { return static_cast(value); }, - [](const auto & file) { return json::parse(readFile(file)); }, - [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); + nix::writeJsonTest(*this, testStem, value); } }; diff --git a/src/libutil/include/nix/util/json-utils.hh b/src/libutil/include/nix/util/json-utils.hh index 7a3fe4f36..ec513ca25 100644 --- a/src/libutil/include/nix/util/json-utils.hh +++ b/src/libutil/include/nix/util/json-utils.hh @@ -114,4 +114,13 @@ struct adl_serializer> } }; +template +static inline std::optional ptrToOwned(const json * ptr) +{ + if (ptr) + return std::optional{*ptr}; + else + return std::nullopt; +} + } // namespace nlohmann diff --git a/src/nix/path-info.cc b/src/nix/path-info.cc index 146b775e5..74921126b 100644 --- a/src/nix/path-info.cc +++ b/src/nix/path-info.cc @@ -51,7 +51,7 @@ static json pathInfoToJSON(Store & store, const StorePathSet & storePaths, bool // know the name yet until we've read the NAR info. printedStorePath = store.printStorePath(info->path); - jsonObject = info->toJSON(store, true, HashFormat::SRI); + jsonObject = info->toJSON(&store, true); if (showClosureSize) { StorePathSet closure; diff --git a/tests/functional/path-info.sh b/tests/functional/path-info.sh index 463ac6214..70ad1a7aa 100755 --- a/tests/functional/path-info.sh +++ b/tests/functional/path-info.sh @@ -17,8 +17,16 @@ diff --unified --color=always \ jq --sort-keys 'map_values(.narHash)') \ <(jq --sort-keys <<-EOF { - "$foo": "sha256-QvtAMbUl/uvi+LCObmqOhvNOapHdA2raiI4xG5zI5pA=", - "$bar": "sha256-9fhYGu9fqxcQC2Kc81qh2RMo1QcLBUBo8U+pPn+jthQ=", + "$foo": { + "algorithm": "sha256", + "format": "base64", + "hash": "QvtAMbUl/uvi+LCObmqOhvNOapHdA2raiI4xG5zI5pA=" + }, + "$bar": { + "algorithm": "sha256", + "format": "base64", + "hash": "9fhYGu9fqxcQC2Kc81qh2RMo1QcLBUBo8U+pPn+jthQ=" + }, "$baz": null } EOF