packages feed

hnix-store-json 0.1.0.0 → 0.2.0.0

raw patch · 48 files changed

+1445/−187 lines, 48 filesdep +bytestringdep +cryptondep +dependent-sumdep −data-default-classdep −deriving-aesonPVP ok

version bump matches the API change (PVP)

Dependencies added: bytestring, crypton, dependent-sum, monoidal-containers, some, these, time, unordered-containers, vector

Dependencies removed: data-default-class, deriving-aeson

API changes (from Hackage documentation)

- System.Nix.JSON: data LowerLeading
- System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON (System.Nix.Realisation.DerivationOutput System.Nix.OutputName.OutputName)
- System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSONKey (System.Nix.Realisation.DerivationOutput System.Nix.OutputName.OutputName)
- System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON (System.Nix.Realisation.DerivationOutput System.Nix.OutputName.OutputName)
- System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSONKey (System.Nix.Realisation.DerivationOutput System.Nix.OutputName.OutputName)
- System.Nix.JSON: instance Deriving.Aeson.StringModifier System.Nix.JSON.LowerLeading
+ System.Nix.JSON: HashJSON :: DSum HashAlgo Digest -> HashJSON
+ System.Nix.JSON: [unHashJSON] :: HashJSON -> DSum HashAlgo Digest
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON (System.Nix.StorePath.Metadata.Metadata System.Nix.StorePath.StorePath)
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Build.BuildFailureStatus
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Build.BuildResult
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Build.BuildSuccessStatus
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.ContentAddress.ContentAddress
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Derivation.ChildNode
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Derivation.ContentAddressedDerivationOutput
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Derivation.Derivation
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Derivation.DerivedPathMap
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Derivation.FixedDerivationOutput
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Derivation.InputAddressedDerivationOutput
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.DerivedPath.DerivedPath
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.DerivedPath.OutputsSpec
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.DerivedPath.SingleDerivedPath
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.JSON.HashJSON
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.OutputName.OutputName
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Realisation.BuildTraceKey
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSON System.Nix.Signature.NamedSignature
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSONKey System.Nix.OutputName.OutputName
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSONKey System.Nix.StorePath.StorePath
+ System.Nix.JSON: instance Data.Aeson.Types.FromJSON.FromJSONKey System.Nix.StorePath.StorePathName
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON (System.Nix.StorePath.Metadata.Metadata System.Nix.StorePath.StorePath)
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Build.BuildFailureStatus
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Build.BuildResult
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Build.BuildSuccessStatus
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.ContentAddress.ContentAddress
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Derivation.ChildNode
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Derivation.ContentAddressedDerivationOutput
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Derivation.Derivation
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Derivation.DerivedPathMap
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Derivation.FixedDerivationOutput
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Derivation.InputAddressedDerivationOutput
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.DerivedPath.DerivedPath
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.DerivedPath.OutputsSpec
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.DerivedPath.SingleDerivedPath
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.JSON.HashJSON
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.OutputName.OutputName
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Realisation.BuildTraceKey
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSON System.Nix.Signature.NamedSignature
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSONKey System.Nix.OutputName.OutputName
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSONKey System.Nix.StorePath.StorePath
+ System.Nix.JSON: instance Data.Aeson.Types.ToJSON.ToJSONKey System.Nix.StorePath.StorePathName
+ System.Nix.JSON: instance GHC.Classes.Eq System.Nix.JSON.HashJSON
+ System.Nix.JSON: instance GHC.Show.Show System.Nix.JSON.HashJSON
+ System.Nix.JSON: newtype HashJSON

Files

CHANGELOG.md view
@@ -1,3 +1,28 @@+# [0.2.0.0](https://github.com/haskell-nix/hnix-store/compare/json-0.1.0.0...json-0.2.0.0) 2026-10-21++The test suite is now much more comprenesive, uses test data from upstream Nix to make sure the JSON formats match.++* JSON instance for `StorePath` now doesn't include the store dir, matching upstream.+  (This keeps it canonical.)++* Removed `deriving-aeson` and `constraints-extras` dependencies; all JSON instances are now hand-written.++* New JSON instances for:+  * `Hash`+  * `ContentAddress`+  * `OutputsSpec`+  * `SingleDerivedPath`+  * `DerivedPath`+  * `Derivation`+  * `Signature`+  * `NamedSignature`+  * `BuildTraceKey`+  * `Realisation`+  * `RealisationWithId`+  * `BuildSuccessStatus`, `BuildFailureStatus`+  * `BuildResult`+  * `Metadata StorePath` (path-info version 3 format)+ # 0.1.0.0 2024-07-31  * Initial release
hnix-store-json.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                hnix-store-json-version:             0.1.0.0+version:             0.2.0.0 synopsis:            JSON serialization for core types description:   Aeson instances for core types, required for remote store protocol@@ -16,6 +16,40 @@     CHANGELOG.md extra-source-files:     README.md+data-files:+    upstream-libstore-data/content-address/nar.json+    upstream-libstore-data/content-address/text.json+    upstream-libstore-data/derived-path/multi_built_built.json+    upstream-libstore-data/derived-path/multi_built_built_wildcard.json+    upstream-libstore-data/derived-path/multi_opaque.json+    upstream-libstore-data/derived-path/mutli_built.json+    upstream-libstore-data/derived-path/single_built_built.json+    upstream-libstore-data/derived-path/single_built.json+    upstream-libstore-data/derived-path/single_opaque.json+    upstream-libstore-data/derivation/dyn-dep-derivation.json+    upstream-libstore-data/derivation/output-caFixedFlat.json+    upstream-libstore-data/derivation/output-caFixedNAR.json+    upstream-libstore-data/derivation/output-caFixedText.json+    upstream-libstore-data/derivation/output-caFloating.json+    upstream-libstore-data/derivation/output-inputAddressed.json+    upstream-libstore-data/derivation/simple-derivation.json+    upstream-libstore-data/outputs-spec/all.json+    upstream-libstore-data/outputs-spec/name.json+    upstream-libstore-data/outputs-spec/names.json+    upstream-libstore-data/realisation/simple.json+    upstream-libstore-data/realisation/unkeyed-simple.json+    upstream-libstore-data/realisation/unkeyed-with-signature.json+    upstream-libstore-data/realisation/with-signature.json+    upstream-libstore-data/build-result/not-deterministic.json+    upstream-libstore-data/build-result/output-rejected.json+    upstream-libstore-data/build-result/success.json+    upstream-libstore-data/store-path/simple.json+    upstream-libstore-data/path-info/json-3/empty_impure.json+    upstream-libstore-data/path-info/json-3/empty_pure.json+    upstream-libstore-data/path-info/json-3/impure.json+    upstream-libstore-data/path-info/json-3/pure.json+    upstream-libutil-data/hash/sha256.json+    upstream-libutil-data/hash/sha512.json  common commons   ghc-options:  -Wall@@ -25,6 +59,7 @@     , DeriveGeneric     , DerivingVia     , FlexibleInstances+    , ImportQualifiedPost     , LambdaCase     , RecordWildCards     , StandaloneDeriving@@ -38,10 +73,16 @@   build-depends:       base >=4.12 && <5     , hnix-store-core >= 0.8+     , aeson >= 2.0 && < 3.0     , attoparsec-    , deriving-aeson >= 0.2+    , containers+    , crypton+    , dependent-sum+    , monoidal-containers     , text+    , these+    , time   hs-source-dirs:      src  test-suite json@@ -49,7 +90,21 @@   type: exitcode-stdio-1.0   main-is: Spec.hs   other-modules:+    BuildResultSpec+    ContentAddressSpec+    DerivationSpec+    DerivedPathSpec+    HashSpec     JSONSpec+    OutputsSpecSpec+    PathInfoSpec+    RealisationSpec+    SingleDerivedPathSpec+    StorePathSpec+    UpstreamData+    Paths_hnix_store_json+  autogen-modules:+    Paths_hnix_store_json   hs-source-dirs:     tests   build-tool-depends:@@ -59,7 +114,16 @@     , hnix-store-core     , hnix-store-json     , hnix-store-tests+     , aeson+    , bytestring     , containers-    , data-default-class+    , crypton+    , dependent-sum     , hspec+    , monoidal-containers+    , some+    , these+    , time+    , unordered-containers+    , vector
src/System/Nix/JSON.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MonoLocalBinds #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {-| Description : JSON serialization@@ -7,28 +9,45 @@ providing (From|To)JSON for Realisation type which is required for `-remote`. -}-module System.Nix.JSON where+module System.Nix.JSON+  ( HashJSON(..)+  ) where +import Control.Applicative ((<|>))+import Crypto.Hash (Digest) import Data.Aeson-import Deriving.Aeson-import System.Nix.Base (BaseEncoding(NixBase32))-import System.Nix.OutputName (OutputName)-import System.Nix.Realisation (DerivationOutput, Realisation, RealisationWithId(..))-import System.Nix.Signature (Signature)-import System.Nix.StorePath (StoreDir(..), StorePath, StorePathName, StorePathHashPart)--import qualified Data.Aeson.KeyMap-import qualified Data.Aeson.Types-import qualified Data.Attoparsec.Text-import qualified Data.Char-import qualified Data.Text-import qualified Data.Text.Lazy-import qualified Data.Text.Lazy.Builder-import qualified System.Nix.Base-import qualified System.Nix.OutputName-import qualified System.Nix.Realisation-import qualified System.Nix.Signature-import qualified System.Nix.StorePath+import Data.Aeson.Key qualified+import Data.Aeson.KeyMap qualified+import Data.Aeson.Types (Parser)+import Data.Aeson.Types qualified+import Data.Attoparsec.Text qualified+import Data.Dependent.Sum+import Data.Foldable (toList)+import Data.Map.Monoidal qualified+import Data.Map.Strict qualified+import Data.Maybe (fromMaybe, maybeToList)+import Data.Set qualified+import Data.Some+import Data.Text (Text)+import Data.Text qualified+import Data.These+import Data.These.Combinators+import Data.Time (diffUTCTime)+import Data.Time.Clock.POSIX (posixSecondsToUTCTime)+import System.Nix.Base qualified+import System.Nix.Build (BuildResult(..), BuildSuccess(..), BuildFailure(..), BuildSuccessStatus(..), BuildFailureStatus(..))+import System.Nix.ContentAddress+import System.Nix.Derivation+import System.Nix.DerivedPath (DerivedPath(..), OutputsSpec(..), SingleDerivedPath(..))+import System.Nix.Hash+import System.Nix.OutputName (OutputName, mkOutputName)+import System.Nix.OutputName qualified+import System.Nix.Realisation (BuildTraceKey(..), Realisation(..), RealisationWithId(..))+import System.Nix.Signature (Signature, NamedSignature(..))+import System.Nix.Signature qualified+import System.Nix.StorePath (StorePath, StorePathName, StorePathHashPart, mkStorePathName, unStorePathName, parseBasePathFromText)+import System.Nix.StorePath qualified+import System.Nix.StorePath.Metadata (Metadata(..), StorePathTrust(..))  instance ToJSON StorePathName where   toJSON = toJSON . System.Nix.StorePath.unStorePathName@@ -54,18 +73,8 @@     )  instance ToJSON StorePath where-  toJSON =-    toJSON-    -- TODO: hacky, we need to stop requiring StoreDir for-    -- StorePath rendering and have a distinct-    -- types for rooted|unrooted paths-    . Data.Text.drop 1-    . System.Nix.StorePath.storePathToText (StoreDir mempty)--  toEncoding =-    toEncoding-    . Data.Text.drop 1-    . System.Nix.StorePath.storePathToText (StoreDir mempty)+  toJSON = toJSON . System.Nix.StorePath.storePathBaseToText+  toEncoding = toEncoding . System.Nix.StorePath.storePathBaseToText  instance FromJSON StorePath where   parseJSON =@@ -73,53 +82,174 @@     ( either         (fail . show)         pure-    . System.Nix.StorePath.parsePathFromText (StoreDir mempty)-    . Data.Text.cons '/'+    . parseBasePathFromText     ) -instance ToJSON (DerivationOutput OutputName) where-  toJSON =-    toJSON-    . Data.Text.Lazy.toStrict-    . Data.Text.Lazy.Builder.toLazyText-    . System.Nix.Realisation.derivationOutputBuilder-        System.Nix.OutputName.unOutputName+instance ToJSONKey StorePath where+  toJSONKey = Data.Aeson.Types.toJSONKeyText System.Nix.StorePath.storePathBaseToText -  toEncoding =-    toEncoding-    . Data.Text.Lazy.toStrict-    . Data.Text.Lazy.Builder.toLazyText-    . System.Nix.Realisation.derivationOutputBuilder-        System.Nix.OutputName.unOutputName+instance FromJSONKey StorePath where+  fromJSONKey = FromJSONKeyTextParser $+    either (fail . show) pure . parseBasePathFromText -instance ToJSONKey (DerivationOutput OutputName) where-  toJSONKey =-    Data.Aeson.Types.toJSONKeyText-    $ Data.Text.Lazy.toStrict-    . Data.Text.Lazy.Builder.toLazyText-    . System.Nix.Realisation.derivationOutputBuilder-        System.Nix.OutputName.unOutputName+deriving newtype instance FromJSON DerivedPathMap+deriving newtype instance ToJSON DerivedPathMap -instance FromJSON (DerivationOutput OutputName) where-  parseJSON =-    withText "DerivationOutput OutputName"-    ( either-        (fail . show)-        pure-    . System.Nix.Realisation.derivationOutputParser-        System.Nix.OutputName.mkOutputName-    )+instance FromJSON ChildNode where+  parseJSON = withObject "ChildNode" $ \obj -> do+    outputs <- obj .: "outputs"+    dynamicOutputs <- obj .: "dynamicOutputs"+    ChildNode <$> case (Data.Set.null outputs, Data.Map.Monoidal.null dynamicOutputs) of+      (False, True) -> pure $ This outputs+      (True, False) -> pure $ That dynamicOutputs+      (False, False) -> pure $ These outputs dynamicOutputs+      (True, True) -> fail "outputs and dynamic outputs cannot both be empty" -instance FromJSONKey (DerivationOutput OutputName) where-  fromJSONKey =-    FromJSONKeyTextParser-    ( either-        (fail . show)-        pure-    . System.Nix.Realisation.derivationOutputParser-        System.Nix.OutputName.mkOutputName-    )+instance ToJSON ChildNode where+  toJSON (ChildNode cn) = object+    [ "outputs" .= fromMaybe Data.Set.empty (justHere cn)+    , "dynamicOutputs" .= fromMaybe Data.Map.Monoidal.empty (justThere cn)+    ] +-- | Input-addressed derivation output JSON instance+instance FromJSON InputAddressedDerivationOutput where+  parseJSON = withObject "InputAddressedDerivationOutput" $ \obj ->+    InputAddressedDerivationOutput <$> obj .: "path"++instance ToJSON InputAddressedDerivationOutput where+  toJSON (InputAddressedDerivationOutput path) =+    object ["path" .= path]++-- | Fixed derivation output JSON instance+instance FromJSON FixedDerivationOutput where+  parseJSON = withObject "FixedDerivationOutput" $ \obj -> do+    method <- obj .: "method" >>= either fail pure . textToMethod+    HashJSON hash <- obj .: "hash"+    pure $ FixedDerivationOutput method hash++instance ToJSON FixedDerivationOutput where+  toJSON (FixedDerivationOutput method hash) =+    object+      [ "method" .= methodToText method+      , "hash" .= HashJSON hash+      ]++-- | Content-addressed derivation output JSON instance+instance FromJSON ContentAddressedDerivationOutput where+  parseJSON = withObject "ContentAddressedDerivationOutput" $ \obj -> do+    method <- obj .: "method" >>= either fail pure . textToMethod+    hashAlgo <- obj .: "hashAlgo" >>= either fail pure . textToAlgo+    pure $ ContentAddressedDerivationOutput method hashAlgo++instance ToJSON ContentAddressedDerivationOutput where+  toJSON (ContentAddressedDerivationOutput method (Some hashAlgo)) =+    object+      [ "method" .= methodToText method+      , "hashAlgo" .= algoToText hashAlgo+      ]++-- Helper to parse DerivationOutputs from JSON+parseDerivationOutputs :: Object -> Parser DerivationOutputs+parseDerivationOutputs obj = do+  let outputPairs = Data.Aeson.KeyMap.toList obj+  case outputPairs of+    [] -> pure $ DerivationType_InputAddressing :=> mempty+    (_, firstVal) : _ -> do+      -- Parse the first output to determine the derivation type+      withObject "first output" (\first -> do+        -- Determine type by checking which fields are present+        let hasPath = Data.Aeson.KeyMap.member "path" first+            hasMethod = Data.Aeson.KeyMap.member "method" first+            hasHash = Data.Aeson.KeyMap.member "hash" first+            hasHashAlgo = Data.Aeson.KeyMap.member "hashAlgo" first++        case (hasPath, hasMethod, hasHash, hasHashAlgo) of+          (True, False, False, False) -> do+            -- Input-addressed+            outputs <- Data.Map.Strict.fromList <$> mapM (\(k, v) -> do+              outputName <- either (fail . show) pure $ mkOutputName $ Data.Aeson.Key.toText k+              output <- parseJSON v+              pure (outputName, output)) outputPairs+            pure $ DerivationType_InputAddressing :=> outputs+          (False, True, True, False) -> do+            -- Fixed+            outputs <- Data.Map.Strict.fromList <$> mapM (\(k, v) -> do+              outputName <- either (fail . show) pure $ mkOutputName $ Data.Aeson.Key.toText k+              output <- parseJSON v+              pure (outputName, output)) outputPairs+            pure $ DerivationType_Fixed :=> outputs+          (False, True, False, True) -> do+            -- Content-addressed+            outputs <- Data.Map.Strict.fromList <$> mapM (\(k, v) -> do+              outputName <- either (fail . show) pure $ mkOutputName $ Data.Aeson.Key.toText k+              output <- parseJSON v+              pure (outputName, output)) outputPairs+            pure $ DerivationType_ContentAddressing :=> outputs+          _ -> fail $ "Invalid output format: " <> show (hasPath, hasMethod, hasHash, hasHashAlgo)+        ) firstVal++-- Helper to serialize DerivationOutputs to JSON+derivationOutputsToJSON :: DerivationOutputs -> Value+derivationOutputsToJSON (ty :=> outputs) = case ty of+  DerivationType_InputAddressing -> toJSON outputs+  DerivationType_Fixed -> toJSON outputs+  DerivationType_ContentAddressing -> toJSON outputs++instance FromJSONKey StorePathName where+  fromJSONKey = FromJSONKeyTextParser $ either (fail . show) pure . mkStorePathName++instance ToJSONKey StorePathName where+  toJSONKey = Data.Aeson.Types.toJSONKeyText unStorePathName++deriving newtype instance FromJSON OutputName+deriving newtype instance ToJSON OutputName+deriving newtype instance FromJSONKey OutputName+deriving newtype instance ToJSONKey OutputName++-- | TODO: hacky, we need to stop assuming StoreDir for+-- StorePath to and from JSON+instance FromJSON Derivation where+  parseJSON = withObject "Derivation" $ \v -> do+    name <- v .: "name"+    inputs <- v .: "inputs" >>= \inputsObj -> DerivationInputs+      <$> inputsObj .: "srcs"+      <*> inputsObj .: "drvs"+    outputs <- v .: "outputs" >>= parseDerivationOutputs+    Derivation name outputs+      <$> pure inputs+      <*> v .: "system"+      <*> v .: "builder"+      <*> v .: "args"+      <*> v .: "env"++instance ToJSON Derivation where+  toJSON (Derivation name outputs (DerivationInputs inputSrcs inputDrvs) system builder args env) =+    object [ "version" .= (4 :: Int)+           , "name" .= name+           , "outputs" .= derivationOutputsToJSON outputs+           , "inputs" .= object+              [ "srcs" .= inputSrcs+              , "drvs" .= inputDrvs+              ]+           , "system" .= system+           , "builder" .= builder+           , "args" .= args+           , "env" .= env+           ]++instance ToJSON BuildTraceKey where+  toJSON btk =+    object+      [ "drvPath" .= buildTraceKeyDrvPath btk+      , "outputName" .= buildTraceKeyOutput btk+      ]++instance FromJSON BuildTraceKey where+  parseJSON = withObject "BuildTraceKey" $ \o ->+    BuildTraceKey+      <$> o .: "drvPath"+      <*> o .: "outputName"+ instance ToJSON Signature where   toJSON = toJSON . System.Nix.Signature.signatureToText   toEncoding = toEncoding . System.Nix.Signature.signatureToText@@ -134,43 +264,273 @@         System.Nix.Signature.signatureParser     ) -data LowerLeading-instance StringModifier LowerLeading where-  getStringModifier "" = ""-  getStringModifier (c:xs) = Data.Char.toLower c : xs+instance ToJSON NamedSignature where+  toJSON ns =+    object+      [ "keyName" .= publicKey ns+      , "sig" .= sig ns+      ] -deriving-  via CustomJSON-    '[FieldLabelModifier-       '[ StripPrefix "realisation"-        , LowerLeading-        , Rename "dependencies" "dependentRealisations"-        ]-     ] Realisation-  instance ToJSON Realisation-deriving-  via CustomJSON-    '[FieldLabelModifier-       '[ StripPrefix "realisation"-        , LowerLeading-        , Rename "dependencies" "dependentRealisations"-        ]-     ] Realisation-  instance FromJSON Realisation+instance FromJSON NamedSignature where+  parseJSON = withObject "NamedSignature" $ \o -> do+    keyName <- o .: "keyName"+    sigVal <- o .: "sig"+    pure $ NamedSignature { publicKey = keyName, sig = sigVal } +-- | Needed to avoid overlapping instances+newtype HashJSON = HashJSON { unHashJSON :: DSum HashAlgo Digest }+  deriving (Eq, Show)++instance ToJSON HashJSON where+  toJSON (HashJSON (algo :=> digest)) =+    -- SRI format: "algo-base64hash"+    toJSON $ algoToText algo <> "-" <> encodeDigestWith Base64 digest++instance FromJSON HashJSON where+  parseJSON = withText "HashJSON" $ \t -> do+    -- SRI format: "algo-base64hash"+    let (algoText, rest) = Data.Text.breakOn "-" t+    case Data.Text.uncons rest of+      Nothing -> fail "HashJSON: missing '-' separator"+      Just ('-', _hashText) ->+        either fail (pure . HashJSON) $ mkNamedDigest algoText t+      _ -> fail "HashJSON: missing '-' separator"++instance ToJSON ContentAddress where+  toJSON (ContentAddress method digest) =+    object+      [ "hash" .= HashJSON digest+      , "method" .= methodToText method+      ]++instance FromJSON ContentAddress where+  parseJSON = withObject "ContentAddress" $ \obj -> do+    HashJSON digest <- obj .: "hash"+    methodText <- obj .: "method"+    method <- either fail pure $ textToMethod methodText+    pure $ ContentAddress method digest++-- | OutputsSpec encodes as an array. The wildcard "*" is a singleton+-- array ["*"] to match upstream Nix JSON format.+instance ToJSON OutputsSpec where+  toJSON OutputsSpec_All = toJSON ["*" :: Text]+  toJSON (OutputsSpec_Names names) = toJSON $ Data.Set.toList names++instance FromJSON OutputsSpec where+  parseJSON = withArray "OutputsSpec" $ \arr -> do+    outputs <- mapM parseJSON (toList arr)+    if outputs == ["*" :: Text]+      then pure OutputsSpec_All+      else do+        names <- mapM (either (fail . show) pure . System.Nix.OutputName.mkOutputName) outputs+        pure $ OutputsSpec_Names (Data.Set.fromList names)++instance ToJSON SingleDerivedPath where+  toJSON (SingleDerivedPath_Opaque path) = toJSON path+  toJSON (SingleDerivedPath_Built drvPath output) =+    object+      [ "drvPath" .= toJSON drvPath+      , "output" .= output+      ]++instance FromJSON SingleDerivedPath where+  parseJSON v = parseOpaque v <|> parseBuilt v+    where+      parseOpaque = fmap SingleDerivedPath_Opaque . parseJSON+      parseBuilt = withObject "SingleDerivedPath_Built" $ \obj ->+        SingleDerivedPath_Built+          <$> obj .: "drvPath"+          <*> obj .: "output"++instance ToJSON DerivedPath where+  toJSON (DerivedPath_Opaque path) = toJSON path+  toJSON (DerivedPath_Built drvPath outputs) =+    object+      [ "drvPath" .= toJSON drvPath+      , "outputs" .= outputs+      ]++instance FromJSON DerivedPath where+  parseJSON v = parseOpaque v <|> parseBuilt v+    where+      parseOpaque = fmap DerivedPath_Opaque . parseJSON+      parseBuilt = withObject "DerivedPath_Built" $ \obj ->+        DerivedPath_Built+          <$> obj .: "drvPath"+          <*> obj .: "outputs"++instance ToJSON Realisation where+  toJSON r =+    object+      [ "outPath" .= realisationOutPath r+      , "signatures" .= realisationSignatures r+      ]++instance FromJSON Realisation where+  parseJSON = withObject "Realisation" $ \o ->+    Realisation+      <$> o .: "outPath"+      <*> o .:? "signatures" .!= mempty+ -- For a keyed version of Realisation--- we use RealisationWithId (DerivationOutput OutputName, Realisation)--- instead of Realisation.id :: (DerivationOutput OutputName)+-- we use RealisationWithId (BuildTraceKey, Realisation)+-- instead of Realisation.id :: BuildTraceKey -- field. instance ToJSON RealisationWithId where   toJSON (RealisationWithId (drvOut, r)) =-    case toJSON r of-      Object o -> Object $ Data.Aeson.KeyMap.insert "id" (toJSON drvOut) o-      _ -> error "absurd"+    object+      [ "key" .= drvOut+      , "value" .= r+      ]  instance FromJSON RealisationWithId where-  parseJSON v@(Object o) = do-    r <- parseJSON @Realisation v-    drvOut <- o .: "id"+  parseJSON = withObject "RealisationWithId" $ \o -> do+    drvOut <- o .: "key"+    r <- o .: "value"     pure (RealisationWithId (drvOut, r))-  parseJSON x = fail $ "Expected Object but got " ++ show x++-- BuildSuccessStatus enum to/from JSON as strings+instance ToJSON BuildSuccessStatus where+  toJSON BuildSuccessStatus_Built = String "Built"+  toJSON BuildSuccessStatus_Substituted = String "Substituted"+  toJSON BuildSuccessStatus_AlreadyValid = String "AlreadyValid"+  toJSON BuildSuccessStatus_ResolvesToAlreadyValid = String "ResolvesToAlreadyValid"++instance FromJSON BuildSuccessStatus where+  parseJSON = withText "BuildSuccessStatus" $ \case+    "Built" -> pure BuildSuccessStatus_Built+    "Substituted" -> pure BuildSuccessStatus_Substituted+    "AlreadyValid" -> pure BuildSuccessStatus_AlreadyValid+    "ResolvesToAlreadyValid" -> pure BuildSuccessStatus_ResolvesToAlreadyValid+    other -> fail $ "Unknown BuildSuccessStatus: " ++ Data.Text.unpack other++-- BuildFailureStatus enum to/from JSON as strings+instance ToJSON BuildFailureStatus where+  toJSON BuildFailureStatus_PermanentFailure = String "PermanentFailure"+  toJSON BuildFailureStatus_InputRejected = String "InputRejected"+  toJSON BuildFailureStatus_OutputRejected = String "OutputRejected"+  toJSON BuildFailureStatus_TransientFailure = String "TransientFailure"+  toJSON BuildFailureStatus_CachedFailure = String "CachedFailure"+  toJSON BuildFailureStatus_TimedOut = String "TimedOut"+  toJSON BuildFailureStatus_MiscFailure = String "MiscFailure"+  toJSON BuildFailureStatus_DependencyFailed = String "DependencyFailed"+  toJSON BuildFailureStatus_LogLimitExceeded = String "LogLimitExceeded"+  toJSON BuildFailureStatus_NotDeterministic = String "NotDeterministic"+  toJSON BuildFailureStatus_NoSubstituters = String "NoSubstituters"+  toJSON BuildFailureStatus_HashMismatch = String "HashMismatch"++instance FromJSON BuildFailureStatus where+  parseJSON = withText "BuildFailureStatus" $ \case+    "PermanentFailure" -> pure BuildFailureStatus_PermanentFailure+    "InputRejected" -> pure BuildFailureStatus_InputRejected+    "OutputRejected" -> pure BuildFailureStatus_OutputRejected+    "TransientFailure" -> pure BuildFailureStatus_TransientFailure+    "CachedFailure" -> pure BuildFailureStatus_CachedFailure+    "TimedOut" -> pure BuildFailureStatus_TimedOut+    "MiscFailure" -> pure BuildFailureStatus_MiscFailure+    "DependencyFailed" -> pure BuildFailureStatus_DependencyFailed+    "LogLimitExceeded" -> pure BuildFailureStatus_LogLimitExceeded+    "NotDeterministic" -> pure BuildFailureStatus_NotDeterministic+    "NoSubstituters" -> pure BuildFailureStatus_NoSubstituters+    "HashMismatch" -> pure BuildFailureStatus_HashMismatch+    other -> fail $ "Unknown BuildFailureStatus: " ++ Data.Text.unpack other++-- BuildResult JSON instances+instance ToJSON BuildResult where+  toJSON (BuildResult status timesBuilt startTime stopTime cpuUser cpuSystem) =+    case status of+      Right (BuildSuccess successStatus builtOutputs) ->+        object $ concat+          [ [ "success" .= True+            , "status" .= successStatus+            , "builtOutputs" .= builtOutputs+            , "timesBuilt" .= timesBuilt+            , "startTime" .= (floor (realToFrac (diffUTCTime startTime (posixSecondsToUTCTime 0)) :: Double) :: Integer)+            , "stopTime" .= (floor (realToFrac (diffUTCTime stopTime (posixSecondsToUTCTime 0)) :: Double) :: Integer)+            ]+          , maybeToList $ ("cpuUser" .=) <$> cpuUser+          , maybeToList $ ("cpuSystem" .=) <$> cpuSystem+          ]+      Left (BuildFailure failureStatus errorMsg isNonDeterministic) ->+        object+          [ "success" .= False+          , "status" .= failureStatus+          , "errorMsg" .= errorMsg+          , "isNonDeterministic" .= isNonDeterministic+          , "timesBuilt" .= timesBuilt+          , "startTime" .= (floor (realToFrac (diffUTCTime startTime (posixSecondsToUTCTime 0)) :: Double) :: Integer)+          , "stopTime" .= (floor (realToFrac (diffUTCTime stopTime (posixSecondsToUTCTime 0)) :: Double) :: Integer)+          ]++instance FromJSON BuildResult where+  parseJSON = withObject "BuildResult" $ \obj -> do+    success <- obj .: "success"+    timesBuilt <- obj .: "timesBuilt"+    startTimeSeconds <- obj .: "startTime"+    stopTimeSeconds <- obj .: "stopTime"+    let startTime = posixSecondsToUTCTime (fromInteger startTimeSeconds)+        stopTime = posixSecondsToUTCTime (fromInteger stopTimeSeconds)++    buildResultStatus <- if success+      then do+        successStatus <- obj .: "status"+        builtOutputs <- obj .:? "builtOutputs" .!= mempty+        pure $ Right (BuildSuccess successStatus builtOutputs)+      else do+        failureStatus <- obj .: "status"+        errorMsg <- obj .: "errorMsg"+        isNonDeterministic <- obj .: "isNonDeterministic"+        pure $ Left (BuildFailure failureStatus errorMsg isNonDeterministic)++    buildResultCpuUser <- obj .:? "cpuUser"+    buildResultCpuSystem <- obj .:? "cpuSystem"++    pure BuildResult+      { buildResultStatus = buildResultStatus+      , buildResultTimesBuilt = timesBuilt+      , buildResultStartTime = startTime+      , buildResultStopTime = stopTime+      , buildResultCpuUser = buildResultCpuUser+      , buildResultCpuSystem = buildResultCpuSystem+      }++-- | Metadata (path-info) JSON, version 3 format+instance ToJSON (Metadata StorePath) where+  toJSON m = object+    [ "version" .= (3 :: Int)+    , "storeDir" .= ("/nix/store" :: Text)+    , "narHash" .= HashJSON (metadataNarHash m)+    , "narSize" .= fromMaybe 0 (metadataNarBytes m)+    , "references" .= metadataReferences m+    , "ca" .= metadataContentAddress m+    , "deriver" .= metadataDeriverPath m+    , "registrationTime" .=+        let t = metadataRegistrationTime m+        in if t == posixSecondsToUTCTime 0+           then Nothing @Integer+           else Just (floor (realToFrac (diffUTCTime t (posixSecondsToUTCTime 0)) :: Double) :: Integer)+    , "signatures" .= metadataSigs m+    , "ultimate" .= (metadataTrust m == BuiltLocally)+    ]++instance FromJSON (Metadata StorePath) where+  parseJSON = withObject "Metadata" $ \o -> do+    HashJSON narHash <- o .: "narHash"+    narSize <- o .: "narSize"+    references <- o .:? "references" .!= mempty+    ca <- o .:? "ca"+    deriver <- o .:? "deriver"+    regTime <- o .:? "registrationTime"+    sigs <- o .:? "signatures" .!= mempty+    ultimate <- o .:? "ultimate" .!= False+    pure Metadata+      { metadataDeriverPath = deriver+      , metadataNarHash = narHash+      , metadataReferences = references+      , metadataRegistrationTime =+          maybe (posixSecondsToUTCTime 0) (posixSecondsToUTCTime . fromInteger) regTime+      , metadataNarBytes = if narSize == (0 :: Int) then Nothing else Just (fromIntegral narSize)+      , metadataTrust = if ultimate then BuiltLocally else BuiltElsewhere+      , metadataSigs = sigs+      , metadataContentAddress = ca+      }
+ tests/BuildResultSpec.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module BuildResultSpec where++import Data.Aeson (eitherDecode)+import Data.ByteString.Lazy qualified as BSL+import Paths_hnix_store_json (getDataFileName)+import Test.Hspec (Spec, describe, it, shouldSatisfy)++import System.Nix.Build (BuildResult(..), BuildFailure(..), BuildFailureStatus(..))+import System.Nix.JSON ()++-- For success.json, we'll just check that it parses successfully+-- The exact BuildTraceKey values are derived from the hash in the JSON++-- We just check that the failures parse correctly since they don't have complex nested structures++spec :: Spec+spec = do+  describe "upstream Nix test data" $ do+    it "parses success.json" $ do+      path <- getDataFileName "upstream-libstore-data/build-result/success.json"+      json <- BSL.readFile path+      let result = eitherDecode json :: Either String BuildResult+      result `shouldSatisfy` \case+        Right (BuildResult (Right _) 3 _ _ (Just 500000000) (Just 604000000)) -> True+        _ -> False++    it "parses not-deterministic.json" $ do+      path <- getDataFileName "upstream-libstore-data/build-result/not-deterministic.json"+      json <- BSL.readFile path+      let result = eitherDecode json :: Either String BuildResult+      result `shouldSatisfy` \case+        Right (BuildResult (Left (BuildFailure BuildFailureStatus_NotDeterministic "no idea why" False)) 1 _ _ Nothing Nothing) -> True+        _ -> False++    it "parses output-rejected.json" $ do+      path <- getDataFileName "upstream-libstore-data/build-result/output-rejected.json"+      json <- BSL.readFile path+      let result = eitherDecode json :: Either String BuildResult+      result `shouldSatisfy` \case+        Right (BuildResult (Left (BuildFailure BuildFailureStatus_OutputRejected "no idea why" False)) 3 _ _ Nothing Nothing) -> True+        _ -> False
+ tests/ContentAddressSpec.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module ContentAddressSpec where++import Test.Hspec (Spec, describe)+import Test.Hspec.Nix (forceRight)+import UpstreamData (parsesUpstream)++import System.Nix.ContentAddress (ContentAddress(..), ContentAddressMethod(..))+import System.Nix.Hash (mkNamedDigest)+import System.Nix.JSON ()++spec :: Spec+spec = do+  describe "upstream Nix test data" $ do+    parsesUpstream "upstream-libstore-data/content-address" "nar.json" $+      ContentAddress+        ContentAddressMethod_NixArchive+        (forceRight $ mkNamedDigest "sha256" "9vLqj0XYoFfJVmoz+ZR02i5camYE1zYSFlDicwxvsKM=")++    parsesUpstream "upstream-libstore-data/content-address" "text.json" $+      ContentAddress+        ContentAddressMethod_Text+        (forceRight $ mkNamedDigest "sha256" "8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts=")
+ tests/DerivationSpec.hs view
@@ -0,0 +1,151 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}+module DerivationSpec where++import Crypto.Hash (SHA256)+import Data.Aeson (eitherDecode)+import Data.ByteString.Lazy qualified as BSL+import Data.Dependent.Sum (DSum(..))+import Data.Map.Monoidal qualified as MonoidalMap+import Data.Map.Strict qualified as Map+import Data.Set qualified as Set+import Data.Some (Some(..))+import Data.These (These(..))+import Data.Vector qualified as Vector+import Paths_hnix_store_json (getDataFileName)+import Test.Hspec (Spec, describe, it, shouldBe)+import Test.Hspec.Nix (forceRight)++import System.Nix.Base (BaseEncoding(..))+import System.Nix.ContentAddress (ContentAddressMethod(..))+import System.Nix.Derivation+  ( ChildNode(..)+  , Derivation+  , Derivation'(..)+  , DerivationInputs(..)+  , DerivedPathMap(..)+  , DerivationType(..)+  , InputAddressedDerivationOutput(..)+  , FixedDerivationOutput(..)+  , ContentAddressedDerivationOutput(..)+  )+import System.Nix.Hash (HashAlgo(..), decodeDigestWith)+import System.Nix.JSON ()+import System.Nix.OutputName qualified+import System.Nix.StorePath (mkStorePathName, parseBasePathFromText)++simpleDerivation :: Derivation+simpleDerivation = Derivation+  { name = forceRight $ mkStorePathName "simple-derivation"+  , outputs = DerivationType_InputAddressing :=> mempty+  , inputs = DerivationInputs+      { srcs = Set.singleton $ forceRight $ parseBasePathFromText "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"+      , drvs = DerivedPathMap $ MonoidalMap.singleton+          (forceRight $ parseBasePathFromText "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv")+          (ChildNode $ This $ Set.fromList+            [ forceRight $ System.Nix.OutputName.mkOutputName "cat"+            , forceRight $ System.Nix.OutputName.mkOutputName "dog"+            ])+      }+  , platform = "wasm-sel4"+  , builder = "foo"+  , args = Vector.fromList ["bar", "baz"]+  , env = Map.fromList [("BIG_BAD", "WOLF")]+  }++dynDepDerivation :: Derivation+dynDepDerivation = Derivation+  { name = forceRight $ mkStorePathName "dyn-dep-derivation"+  , outputs = DerivationType_InputAddressing :=> mempty+  , inputs = DerivationInputs+      { srcs = Set.singleton $ forceRight $ parseBasePathFromText "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"+      , drvs = DerivedPathMap $ MonoidalMap.singleton+          (forceRight $ parseBasePathFromText "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv")+          (ChildNode $ These+            (Set.fromList+              [ forceRight $ System.Nix.OutputName.mkOutputName "cat"+              , forceRight $ System.Nix.OutputName.mkOutputName "dog"+              ])+            (MonoidalMap.fromList+              [ ( forceRight $ System.Nix.OutputName.mkOutputName "cat"+                , ChildNode $ This $ Set.singleton $ forceRight $ System.Nix.OutputName.mkOutputName "kitten"+                )+              , ( forceRight $ System.Nix.OutputName.mkOutputName "goose"+                , ChildNode $ This $ Set.singleton $ forceRight $ System.Nix.OutputName.mkOutputName "gosling"+                )+              ])+          )+      }+  , platform = "wasm-sel4"+  , builder = "foo"+  , args = Vector.fromList ["bar", "baz"]+  , env = Map.fromList [("BIG_BAD", "WOLF")]+  }++spec :: Spec+spec = do+  describe "upstream Nix test data" $ do+    describe "full derivations" $ do+      it "parses simple-derivation.json" $ do+        path <- getDataFileName "upstream-libstore-data/derivation/simple-derivation.json"+        json <- BSL.readFile path+        eitherDecode json `shouldBe` Right simpleDerivation++      it "parses dyn-dep-derivation.json" $ do+        path <- getDataFileName "upstream-libstore-data/derivation/dyn-dep-derivation.json"+        json <- BSL.readFile path+        eitherDecode json `shouldBe` Right dynDepDerivation++    describe "output types" $ do+      it "parses output-inputAddressed.json" $ do+        path <- getDataFileName "upstream-libstore-data/derivation/output-inputAddressed.json"+        json <- BSL.readFile path+        output <- case eitherDecode json of+          Right output -> pure output+          Left err -> fail err++        let expectedPath = forceRight $ parseBasePathFromText "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"++        output `shouldBe` InputAddressedDerivationOutput expectedPath++      it "parses output-caFixedFlat.json" $ do+        path <- getDataFileName "upstream-libstore-data/derivation/output-caFixedFlat.json"+        json <- BSL.readFile path+        output <- case eitherDecode json of+          Right output -> pure output+          Left err -> fail err++        let expectedHash = either error id $ decodeDigestWith @SHA256 Base64 "iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="++        output `shouldBe` FixedDerivationOutput ContentAddressMethod_Flat (HashAlgo_SHA256 :=> expectedHash)++      it "parses output-caFixedNAR.json" $ do+        path <- getDataFileName "upstream-libstore-data/derivation/output-caFixedNAR.json"+        json <- BSL.readFile path+        output <- case eitherDecode json of+          Right output -> pure output+          Left err -> fail err++        let expectedHash = either error id $ decodeDigestWith @SHA256 Base64 "iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="++        output `shouldBe` FixedDerivationOutput ContentAddressMethod_NixArchive (HashAlgo_SHA256 :=> expectedHash)++      it "parses output-caFixedText.json" $ do+        path <- getDataFileName "upstream-libstore-data/derivation/output-caFixedText.json"+        json <- BSL.readFile path+        output <- case eitherDecode json of+          Right output -> pure output+          Left err -> fail err++        let expectedHash = either error id $ decodeDigestWith @SHA256 Base64 "iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="++        output `shouldBe` FixedDerivationOutput ContentAddressMethod_Text (HashAlgo_SHA256 :=> expectedHash)++      it "parses output-caFloating.json" $ do+        path <- getDataFileName "upstream-libstore-data/derivation/output-caFloating.json"+        json <- BSL.readFile path+        output <- case eitherDecode json of+          Right output -> pure output+          Left err -> fail err++        output `shouldBe` ContentAddressedDerivationOutput ContentAddressMethod_NixArchive (Some HashAlgo_SHA256)
+ tests/DerivedPathSpec.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module DerivedPathSpec where++import Data.Set qualified+import Test.Hspec (Spec, describe)+import Test.Hspec.Nix (forceRight)+import UpstreamData (parsesUpstream)++import System.Nix.DerivedPath (DerivedPath(..), OutputsSpec(..), SingleDerivedPath(..))+import System.Nix.JSON ()+import System.Nix.OutputName qualified+import System.Nix.StorePath (parseBasePathFromText)++-- upstream-nix/src/libstore-tests/data/derived-path/multi_opaque.json+upstreamMultiOpaque :: DerivedPath+upstreamMultiOpaque = DerivedPath_Opaque $+  forceRight $ parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"++-- upstream-nix/src/libstore-tests/data/derived-path/mutli_built.json+upstreamMultiBuilt :: DerivedPath+upstreamMultiBuilt = DerivedPath_Built+  (SingleDerivedPath_Opaque $ forceRight $ parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv")+  (OutputsSpec_Names $ Data.Set.fromList+    [ forceRight $ System.Nix.OutputName.mkOutputName "bar"+    , forceRight $ System.Nix.OutputName.mkOutputName "baz"+    ])++-- upstream-nix/src/libstore-tests/data/derived-path/multi_built_built.json+upstreamMultiBuiltBuilt :: DerivedPath+upstreamMultiBuiltBuilt = DerivedPath_Built+  (SingleDerivedPath_Built+    (SingleDerivedPath_Opaque $ forceRight $ parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv")+    (forceRight $ System.Nix.OutputName.mkOutputName "bar"))+  (OutputsSpec_Names $ Data.Set.fromList+    [ forceRight $ System.Nix.OutputName.mkOutputName "baz"+    , forceRight $ System.Nix.OutputName.mkOutputName "quux"+    ])++-- upstream-nix/src/libstore-tests/data/derived-path/multi_built_built_wildcard.json+upstreamMultiBuiltBuiltWildcard :: DerivedPath+upstreamMultiBuiltBuiltWildcard = DerivedPath_Built+  (SingleDerivedPath_Built+    (SingleDerivedPath_Opaque $ forceRight $ parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv")+    (forceRight $ System.Nix.OutputName.mkOutputName "bar"))+  OutputsSpec_All++spec :: Spec+spec = do+  let dir = "upstream-libstore-data/derived-path"+  describe "upstream Nix test data" $ do+    parsesUpstream dir "multi_opaque.json" upstreamMultiOpaque+    parsesUpstream dir "mutli_built.json" upstreamMultiBuilt+    parsesUpstream dir "multi_built_built.json" upstreamMultiBuiltBuilt+    parsesUpstream dir "multi_built_built_wildcard.json" upstreamMultiBuiltBuiltWildcard
+ tests/HashSpec.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module HashSpec where++import Test.Hspec (Spec, describe)+import Test.Hspec.Nix (forceRight)+import UpstreamData (parsesUpstream)++import System.Nix.Hash (mkNamedDigest)+import System.Nix.JSON (HashJSON(..))++-- upstream-nix/src/libutil-tests/data/hash/sha256.json+upstreamSHA256 :: HashJSON+upstreamSHA256 = HashJSON $ forceRight $ mkNamedDigest "sha256" "8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts="++-- upstream-nix/src/libutil-tests/data/hash/sha512.json+-- Note: sha512.json also contains a sha256 SRI hash (same test value as sha256.json)+upstreamSHA512 :: HashJSON+upstreamSHA512 = HashJSON $ forceRight $ mkNamedDigest "sha256" "8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts="++spec :: Spec+spec = do+  let dir = "upstream-libutil-data/hash"+  describe "upstream Nix test data" $ do+    parsesUpstream dir "sha256.json" upstreamSHA256+    parsesUpstream dir "sha512.json" upstreamSHA512
tests/JSONSpec.hs view
@@ -1,26 +1,21 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-} module JSONSpec where -import Data.Aeson (ToJSON, FromJSON, decode, encode)-import Data.Default.Class (Default(def))-import Test.Hspec (Expectation, Spec, describe, it, shouldBe)+import Data.Aeson (ToJSON, FromJSON, eitherDecode, encode)+import Test.Hspec (Expectation, Spec, describe)+import Test.Hspec.Nix (roundtrips) import Test.Hspec.QuickCheck (prop)-import Test.Hspec.Nix (forceRight, roundtrips)  import System.Nix.Arbitrary ()+import System.Nix.ContentAddress (ContentAddress)+import System.Nix.Derivation (Derivation)+import System.Nix.DerivedPath (DerivedPath, OutputsSpec, SingleDerivedPath) import System.Nix.JSON ()-import System.Nix.OutputName (OutputName)-import System.Nix.Realisation (DerivationOutput(..), Realisation(..))-import System.Nix.Signature (Signature)+import System.Nix.Realisation (BuildTraceKey, Realisation)+import System.Nix.Signature (Signature, NamedSignature) import System.Nix.StorePath (StorePath, StorePathName, StorePathHashPart) -import qualified Data.Map-import qualified Data.Set-import qualified System.Nix.Hash-import qualified System.Nix.OutputName-import qualified System.Nix.Signature-import qualified System.Nix.StorePath- roundtripsJSON   :: ( Eq a      , Show a@@ -29,73 +24,20 @@      )   => a   -> Expectation-roundtripsJSON = roundtrips encode decode--sampleDerivationOutput :: DerivationOutput OutputName-sampleDerivationOutput = DerivationOutput-  { derivationOutputHash =-      forceRight-      $ System.Nix.Hash.mkNamedDigest-          "sha256"-          "1b4sb93wp679q4zx9k1ignby1yna3z7c4c2ri3wphylbc2dwsys0"-  , derivationOutputOutput =-      forceRight-      $ System.Nix.OutputName.mkOutputName "foo"-  }--sampleRealisation0 :: Realisation-sampleRealisation0 = Realisation-  { realisationOutPath =-      forceRight-      $ System.Nix.StorePath.parsePath-          def-          "/nix/store/cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"-  , realisationSignatures = mempty-  , realisationDependencies = mempty-  }--sampleRealisation1 :: Realisation-sampleRealisation1 = Realisation-  { realisationOutPath =-      forceRight-      $ System.Nix.StorePath.parsePath-          def-          "/nix/store/5rwxzi7pal3qhpsyfc16gzkh939q1np6-curl-7.82.0.drv"-  , realisationSignatures =-      Data.Set.fromList-      $ forceRight-      . System.Nix.Signature.parseSignature-      <$> [ "fW3iEMfyx6IZzGNswD54BjclfkXiYzh0xRXddrXfJ1rp1l8p1xTi9/0g2EibbwLFb6p83cwIJv5KtTGksC54CQ=="-          , "SMjnB3mPgXYjXacU+xN24BdzXlAgGAuFnYwPddU3bhjfHBeQus/OimdIPMgR/JMKFPHXORrk7pbjv68vecTEBA=="-          ]-  , realisationDependencies =-      Data.Map.fromList-      [ ( sampleDerivationOutput-        , forceRight-          $ System.Nix.StorePath.parsePathFromText-              def-              "/nix/store/9472ijanf79nlkb5n1yh57s7867p1930-testFixed"-        )-      ]-  }+roundtripsJSON = roundtrips encode eitherDecode  spec :: Spec spec = do-  describe "JSON" $ do-    describe "roundtrips" $ do-      prop "StorePathName" $ roundtripsJSON @StorePathName-      prop "StorePathHashPart" $ roundtripsJSON @StorePathHashPart-      prop "StorePath" $ roundtripsJSON @StorePath-      prop "DerivationOutput OutputName" $ roundtripsJSON @(DerivationOutput OutputName)-      prop "Signature" $ roundtripsJSON @Signature-      prop "Realisation" $ roundtripsJSON @Realisation--    describe "ground truth" $ do-      it "sampleDerivationOutput matches preimage" $-        encode sampleDerivationOutput `shouldBe` "\"sha256:1b4sb93wp679q4zx9k1ignby1yna3z7c4c2ri3wphylbc2dwsys0!foo\""--      it "sampleRealisation0 matches preimage" $-        encode sampleRealisation0 `shouldBe` "{\"outPath\":\"cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh\",\"signatures\":[],\"dependentRealisations\":{}}"--      it "sampleRealisation1 matches preimage" $-        encode sampleRealisation1 `shouldBe` "{\"outPath\":\"5rwxzi7pal3qhpsyfc16gzkh939q1np6-curl-7.82.0.drv\",\"signatures\":[\"SMjnB3mPgXYjXacU+xN24BdzXlAgGAuFnYwPddU3bhjfHBeQus/OimdIPMgR/JMKFPHXORrk7pbjv68vecTEBA==\",\"fW3iEMfyx6IZzGNswD54BjclfkXiYzh0xRXddrXfJ1rp1l8p1xTi9/0g2EibbwLFb6p83cwIJv5KtTGksC54CQ==\"],\"dependentRealisations\":{\"sha256:1b4sb93wp679q4zx9k1ignby1yna3z7c4c2ri3wphylbc2dwsys0!foo\":\"9472ijanf79nlkb5n1yh57s7867p1930-testFixed\"}}"+  describe "roundtrips" $ do+    prop "StorePathName" $ roundtripsJSON @StorePathName+    prop "StorePathHashPart" $ roundtripsJSON @StorePathHashPart+    prop "StorePath" $ roundtripsJSON @StorePath+    prop "ContentAddress" $ roundtripsJSON @ContentAddress+    prop "OutputsSpec" $ roundtripsJSON @OutputsSpec+    prop "SingleDerivedPath" $ roundtripsJSON @SingleDerivedPath+    prop "DerivedPath" $ roundtripsJSON @DerivedPath+    prop "Derivation" $ roundtripsJSON @Derivation+    prop "BuildTraceKey" $ roundtripsJSON @BuildTraceKey+    prop "Signature" $ roundtripsJSON @Signature+    prop "NamedSignature" $ roundtripsJSON @NamedSignature+    prop "Realisation" $ roundtripsJSON @Realisation
+ tests/OutputsSpecSpec.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module OutputsSpecSpec where++import Data.Set qualified+import Test.Hspec (Spec, describe)+import Test.Hspec.Nix (forceRight)+import UpstreamData (parsesUpstream)++import System.Nix.DerivedPath (OutputsSpec(..))+import System.Nix.JSON ()+import System.Nix.OutputName qualified++-- upstream-nix/src/libstore-tests/data/outputs-spec/all.json+upstreamAll :: OutputsSpec+upstreamAll = OutputsSpec_All++-- upstream-nix/src/libstore-tests/data/outputs-spec/name.json+upstreamName :: OutputsSpec+upstreamName = OutputsSpec_Names $+  Data.Set.singleton $ forceRight $ System.Nix.OutputName.mkOutputName "a"++-- upstream-nix/src/libstore-tests/data/outputs-spec/names.json+upstreamNames :: OutputsSpec+upstreamNames = OutputsSpec_Names $ Data.Set.fromList+  [ forceRight $ System.Nix.OutputName.mkOutputName "a"+  , forceRight $ System.Nix.OutputName.mkOutputName "b"+  ]++spec :: Spec+spec = do+  let dir = "upstream-libstore-data/outputs-spec"+  describe "upstream Nix test data" $ do+    parsesUpstream dir "all.json" upstreamAll+    parsesUpstream dir "name.json" upstreamName+    parsesUpstream dir "names.json" upstreamNames
+ tests/PathInfoSpec.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module PathInfoSpec where++import Test.Hspec (Spec, describe)+import Test.Hspec.Nix (forceRight)+import UpstreamData (parsesUpstream)++import Data.HashSet qualified+import Data.Set qualified+import Data.Time.Clock.POSIX (posixSecondsToUTCTime)++import Crypto.Hash (Digest)+import Data.Dependent.Sum (DSum)++import System.Nix.ContentAddress (ContentAddress(..), ContentAddressMethod(..))+import System.Nix.Hash (HashAlgo, mkNamedDigest)+import System.Nix.JSON ()+import System.Nix.Signature (NamedSignature(..))+import System.Nix.Signature qualified+import System.Nix.StorePath (StorePath)+import System.Nix.StorePath qualified+import System.Nix.StorePath.Metadata (Metadata(..), StorePathTrust(..))++barPath :: StorePath+barPath = forceRight $ System.Nix.StorePath.parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar"++barDrvPath :: StorePath+barDrvPath = forceRight $ System.Nix.StorePath.parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv"++fooPath :: StorePath+fooPath = forceRight $ System.Nix.StorePath.parseBasePathFromText "n5wkd9frr45pa74if5gpz9j7mifg27fh-foo"++sig1 :: NamedSignature+sig1 = NamedSignature+  { publicKey = "asdf"+  , sig = forceRight $ System.Nix.Signature.parseSignature "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="+  }++sig2 :: NamedSignature+sig2 = NamedSignature+  { publicKey = "qwer"+  , sig = forceRight $ System.Nix.Signature.parseSignature "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="+  }++theNarHash :: DSum HashAlgo Digest+theNarHash = forceRight $ mkNamedDigest "sha256" "FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="++theCa :: ContentAddress+theCa = ContentAddress+  ContentAddressMethod_NixArchive+  (forceRight $ mkNamedDigest "sha256" "EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=")++spec :: Spec+spec = do+  let dir = "upstream-libstore-data/path-info/json-3"++  describe "upstream Nix test data (path-info json-3)" $ do+    parsesUpstream dir "pure.json" Metadata+      { metadataDeriverPath = Nothing+      , metadataNarHash = theNarHash+      , metadataReferences = Data.HashSet.fromList [barPath, fooPath]+      , metadataRegistrationTime = posixSecondsToUTCTime 0+      , metadataNarBytes = Just 34878+      , metadataTrust = BuiltElsewhere+      , metadataSigs = mempty+      , metadataContentAddress = Just theCa+      }++    parsesUpstream dir "impure.json" Metadata+      { metadataDeriverPath = Just barDrvPath+      , metadataNarHash = theNarHash+      , metadataReferences = Data.HashSet.fromList [barPath, fooPath]+      , metadataRegistrationTime = posixSecondsToUTCTime 23423+      , metadataNarBytes = Just 34878+      , metadataTrust = BuiltLocally+      , metadataSigs = Data.Set.fromList [sig1, sig2]+      , metadataContentAddress = Just theCa+      }++    parsesUpstream dir "empty_pure.json" emptyMetadata++    parsesUpstream dir "empty_impure.json" emptyMetadata++emptyMetadata :: Metadata StorePath+emptyMetadata = Metadata+  { metadataDeriverPath = Nothing+  , metadataNarHash = theNarHash+  , metadataReferences = mempty+  , metadataRegistrationTime = posixSecondsToUTCTime 0+  , metadataNarBytes = Nothing+  , metadataTrust = BuiltElsewhere+  , metadataSigs = mempty+  , metadataContentAddress = Nothing+  }
+ tests/RealisationSpec.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module RealisationSpec where++import Data.Aeson (eitherDecode, encode)+import Data.ByteString.Lazy qualified as BSL+import Paths_hnix_store_json (getDataFileName)+import Test.Hspec (Spec, describe, it, shouldBe, shouldSatisfy)+import Test.Hspec.Nix (forceRight)+import UpstreamData (parsesUpstream)++import System.Nix.JSON ()+import System.Nix.OutputName qualified+import System.Nix.Realisation (BuildTraceKey(..), Realisation(..), RealisationWithId(..))+import System.Nix.StorePath qualified++sampleRealisation0 :: Realisation+sampleRealisation0 = Realisation+  { realisationOutPath =+      forceRight+      $ System.Nix.StorePath.parseBasePath+          "cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh"+  , realisationSignatures = mempty+  }++-- upstream-nix/src/libstore-tests/data/realisation/simple.json+upstreamSimpleRealisation :: RealisationWithId+upstreamSimpleRealisation = RealisationWithId+  ( BuildTraceKey+      { buildTraceKeyDrvPath =+          forceRight+          $ System.Nix.StorePath.parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv"+      , buildTraceKeyOutput =+          forceRight+          $ System.Nix.OutputName.mkOutputName "foo"+      }+  , Realisation+      { realisationOutPath =+          forceRight+          $ System.Nix.StorePath.parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"+      , realisationSignatures = mempty+      }+  )++-- upstream-nix/src/libstore-tests/data/realisation/unkeyed-simple.json+upstreamUnkeyedSimple :: Realisation+upstreamUnkeyedSimple = Realisation+  { realisationOutPath =+      forceRight+      $ System.Nix.StorePath.parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo"+  , realisationSignatures = mempty+  }++spec :: Spec+spec = do+  describe "ground truth" $ do+    it "sampleRealisation0 matches preimage (relative paths)" $+      encode sampleRealisation0 `shouldBe` "{\"outPath\":\"cdips4lakfk1qbf1x68fq18wnn3r5r14-builder.sh\",\"signatures\":[]}"++  let dir = "upstream-libstore-data/realisation"+  describe "upstream Nix test data" $ do+    parsesUpstream dir "simple.json" upstreamSimpleRealisation+    parsesUpstream dir "unkeyed-simple.json" upstreamUnkeyedSimple++    it "parses with-signature.json" $ do+      path <- getDataFileName "upstream-libstore-data/realisation/with-signature.json"+      json <- BSL.readFile path+      let result = eitherDecode json :: Either String RealisationWithId+      result `shouldSatisfy` \case+        Right _ -> True+        Left _ -> False++    it "parses unkeyed-with-signature.json" $ do+      path <- getDataFileName "upstream-libstore-data/realisation/unkeyed-with-signature.json"+      json <- BSL.readFile path+      let result = eitherDecode json :: Either String Realisation+      result `shouldSatisfy` \case+        Right _ -> True+        Left _ -> False
+ tests/SingleDerivedPathSpec.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module SingleDerivedPathSpec where++import Test.Hspec (Spec, describe)+import Test.Hspec.Nix (forceRight)+import UpstreamData (parsesUpstream)++import System.Nix.DerivedPath (SingleDerivedPath(..))+import System.Nix.JSON ()+import System.Nix.OutputName qualified+import System.Nix.StorePath (parseBasePathFromText)++-- upstream-nix/src/libstore-tests/data/derived-path/single_opaque.json+upstreamSingleOpaque :: SingleDerivedPath+upstreamSingleOpaque = SingleDerivedPath_Opaque $+  forceRight $ parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"++-- upstream-nix/src/libstore-tests/data/derived-path/single_built.json+upstreamSingleBuilt :: SingleDerivedPath+upstreamSingleBuilt = SingleDerivedPath_Built+  (SingleDerivedPath_Opaque $ forceRight $ parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv")+  (forceRight $ System.Nix.OutputName.mkOutputName "bar")++-- upstream-nix/src/libstore-tests/data/derived-path/single_built_built.json+upstreamSingleBuiltBuilt :: SingleDerivedPath+upstreamSingleBuiltBuilt = SingleDerivedPath_Built+  (SingleDerivedPath_Built+    (SingleDerivedPath_Opaque $ forceRight $ parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv")+    (forceRight $ System.Nix.OutputName.mkOutputName "bar"))+  (forceRight $ System.Nix.OutputName.mkOutputName "baz")++spec :: Spec+spec = do+  let dir = "upstream-libstore-data/derived-path"+  describe "upstream Nix test data" $ do+    parsesUpstream dir "single_opaque.json" upstreamSingleOpaque+    parsesUpstream dir "single_built.json" upstreamSingleBuilt+    parsesUpstream dir "single_built_built.json" upstreamSingleBuiltBuilt
+ tests/StorePathSpec.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module StorePathSpec where++import Test.Hspec (Spec, describe)+import Test.Hspec.Nix (forceRight)+import UpstreamData (parsesUpstream)++import System.Nix.JSON ()+import System.Nix.StorePath (StorePath, parseBasePathFromText)++-- upstream-nix/src/libstore-tests/data/store-path/simple.json+upstreamSimple :: StorePath+upstreamSimple = forceRight $ parseBasePathFromText "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"++spec :: Spec+spec = do+  describe "upstream Nix test data" $ do+    parsesUpstream "upstream-libstore-data/store-path" "simple.json" upstreamSimple
+ tests/UpstreamData.hs view
@@ -0,0 +1,16 @@+module UpstreamData+  ( parsesUpstream+  ) where++import Data.Aeson (FromJSON, eitherDecode)+import Data.ByteString.Lazy qualified as BSL+import Paths_hnix_store_json (getDataFileName)+import Test.Hspec (Spec, it, shouldBe)++-- | Helper to test parsing upstream Nix test data files.+parsesUpstream :: (Eq a, Show a, FromJSON a) => FilePath -> FilePath -> a -> Spec+parsesUpstream dir filename expected =+  it ("parses " <> filename) $ do+    path <- getDataFileName (dir ++ "/" ++ filename)+    json <- BSL.readFile path+    eitherDecode json `shouldBe` Right expected
+ upstream-libstore-data/build-result/not-deterministic.json view
@@ -0,0 +1,9 @@+{+  "errorMsg": "no idea why",+  "isNonDeterministic": false,+  "startTime": 0,+  "status": "NotDeterministic",+  "stopTime": 0,+  "success": false,+  "timesBuilt": 1+}
+ upstream-libstore-data/build-result/output-rejected.json view
@@ -0,0 +1,9 @@+{+  "errorMsg": "no idea why",+  "isNonDeterministic": false,+  "startTime": 30,+  "status": "OutputRejected",+  "stopTime": 50,+  "success": false,+  "timesBuilt": 3+}
+ upstream-libstore-data/build-result/success.json view
@@ -0,0 +1,19 @@+{+  "builtOutputs": {+    "bar": {+      "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",+      "signatures": []+    },+    "foo": {+      "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo",+      "signatures": []+    }+  },+  "cpuSystem": 604000000,+  "cpuUser": 500000000,+  "startTime": 30,+  "status": "Built",+  "stopTime": 50,+  "success": true,+  "timesBuilt": 3+}
+ upstream-libstore-data/content-address/nar.json view
@@ -0,0 +1,4 @@+{+  "hash": "sha256-9vLqj0XYoFfJVmoz+ZR02i5camYE1zYSFlDicwxvsKM=",+  "method": "nar"+}
+ upstream-libstore-data/content-address/text.json view
@@ -0,0 +1,4 @@+{+  "hash": "sha256-8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts=",+  "method": "text"+}
+ upstream-libstore-data/derivation/dyn-dep-derivation.json view
@@ -0,0 +1,41 @@+{+  "args": [+    "bar",+    "baz"+  ],+  "builder": "foo",+  "env": {+    "BIG_BAD": "WOLF"+  },+  "inputs": {+    "drvs": {+      "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": {+        "dynamicOutputs": {+          "cat": {+            "dynamicOutputs": {},+            "outputs": [+              "kitten"+            ]+          },+          "goose": {+            "dynamicOutputs": {},+            "outputs": [+              "gosling"+            ]+          }+        },+        "outputs": [+          "cat",+          "dog"+        ]+      }+    },+    "srcs": [+      "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"+    ]+  },+  "name": "dyn-dep-derivation",+  "outputs": {},+  "system": "wasm-sel4",+  "version": 4+}
+ upstream-libstore-data/derivation/output-caFixedFlat.json view
@@ -0,0 +1,4 @@+{+  "hash": "sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8=",+  "method": "flat"+}
+ upstream-libstore-data/derivation/output-caFixedNAR.json view
@@ -0,0 +1,4 @@+{+  "hash": "sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8=",+  "method": "nar"+}
+ upstream-libstore-data/derivation/output-caFixedText.json view
@@ -0,0 +1,4 @@+{+  "hash": "sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8=",+  "method": "text"+}
+ upstream-libstore-data/derivation/output-caFloating.json view
@@ -0,0 +1,4 @@+{+  "hashAlgo": "sha256",+  "method": "nar"+}
+ upstream-libstore-data/derivation/output-inputAddressed.json view
@@ -0,0 +1,3 @@+{+  "path": "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"+}
+ upstream-libstore-data/derivation/simple-derivation.json view
@@ -0,0 +1,28 @@+{+  "args": [+    "bar",+    "baz"+  ],+  "builder": "foo",+  "env": {+    "BIG_BAD": "WOLF"+  },+  "inputs": {+    "drvs": {+      "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": {+        "dynamicOutputs": {},+        "outputs": [+          "cat",+          "dog"+        ]+      }+    },+    "srcs": [+      "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"+    ]+  },+  "name": "simple-derivation",+  "outputs": {},+  "system": "wasm-sel4",+  "version": 4+}
+ upstream-libstore-data/derived-path/multi_built_built.json view
@@ -0,0 +1,10 @@+{+  "drvPath": {+    "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv",+    "output": "bar"+  },+  "outputs": [+    "baz",+    "quux"+  ]+}
+ upstream-libstore-data/derived-path/multi_built_built_wildcard.json view
@@ -0,0 +1,9 @@+{+  "drvPath": {+    "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv",+    "output": "bar"+  },+  "outputs": [+    "*"+  ]+}
+ upstream-libstore-data/derived-path/multi_opaque.json view
@@ -0,0 +1,1 @@+"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"
+ upstream-libstore-data/derived-path/mutli_built.json view
@@ -0,0 +1,7 @@+{+  "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv",+  "outputs": [+    "bar",+    "baz"+  ]+}
+ upstream-libstore-data/derived-path/single_built.json view
@@ -0,0 +1,4 @@+{+  "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv",+  "output": "bar"+}
+ upstream-libstore-data/derived-path/single_built_built.json view
@@ -0,0 +1,7 @@+{+  "drvPath": {+    "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv",+    "output": "bar"+  },+  "output": "baz"+}
+ upstream-libstore-data/derived-path/single_opaque.json view
@@ -0,0 +1,1 @@+"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"
+ upstream-libstore-data/outputs-spec/all.json view
@@ -0,0 +1,3 @@+[+  "*"+]
+ upstream-libstore-data/outputs-spec/name.json view
@@ -0,0 +1,3 @@+[+  "a"+]
+ upstream-libstore-data/outputs-spec/names.json view
@@ -0,0 +1,4 @@+[+  "a",+  "b"+]
+ upstream-libstore-data/path-info/json-3/empty_impure.json view
@@ -0,0 +1,12 @@+{+  "ca": null,+  "deriver": null,+  "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",+  "narSize": 0,+  "references": [],+  "registrationTime": null,+  "signatures": [],+  "storeDir": "/nix/store",+  "ultimate": false,+  "version": 3+}
+ upstream-libstore-data/path-info/json-3/empty_pure.json view
@@ -0,0 +1,8 @@+{+  "ca": null,+  "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",+  "narSize": 0,+  "references": [],+  "storeDir": "/nix/store",+  "version": 3+}
+ upstream-libstore-data/path-info/json-3/impure.json view
@@ -0,0 +1,27 @@+{+  "ca": {+    "hash": "sha256-EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=",+    "method": "nar"+  },+  "deriver": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",+  "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",+  "narSize": 34878,+  "references": [+    "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",+    "n5wkd9frr45pa74if5gpz9j7mifg27fh-foo"+  ],+  "registrationTime": 23423,+  "signatures": [+    {+      "keyName": "asdf",+      "sig": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="+    },+    {+      "keyName": "qwer",+      "sig": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="+    }+  ],+  "storeDir": "/nix/store",+  "ultimate": true,+  "version": 3+}
+ upstream-libstore-data/path-info/json-3/pure.json view
@@ -0,0 +1,14 @@+{+  "ca": {+    "hash": "sha256-EMIJ+giQ/gLIWoxmPKjno3zHZrxbGymgzGGyZvZBIdM=",+    "method": "nar"+  },+  "narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",+  "narSize": 34878,+  "references": [+    "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",+    "n5wkd9frr45pa74if5gpz9j7mifg27fh-foo"+  ],+  "storeDir": "/nix/store",+  "version": 3+}
+ upstream-libstore-data/realisation/simple.json view
@@ -0,0 +1,10 @@+{+  "key": {+    "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",+    "outputName": "foo"+  },+  "value": {+    "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo",+    "signatures": []+  }+}
+ upstream-libstore-data/realisation/unkeyed-simple.json view
@@ -0,0 +1,4 @@+{+  "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo",+  "signatures": []+}
+ upstream-libstore-data/realisation/unkeyed-with-signature.json view
@@ -0,0 +1,9 @@+{+  "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv",+  "signatures": [+    {+      "keyName": "asdf",+      "sig": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="+    }+  ]+}
+ upstream-libstore-data/realisation/with-signature.json view
@@ -0,0 +1,15 @@+{+  "key": {+    "drvPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",+    "outputName": "foo"+  },+  "value": {+    "outPath": "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv",+    "signatures": [+      {+        "keyName": "asdf",+        "sig": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="+      }+    ]+  }+}
+ upstream-libstore-data/store-path/simple.json view
@@ -0,0 +1,1 @@+"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"
+ upstream-libutil-data/hash/sha256.json view
@@ -0,0 +1,1 @@+"sha256-8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts="
+ upstream-libutil-data/hash/sha512.json view
@@ -0,0 +1,1 @@+"sha256-8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts="