Skip to content

Commit 37c030c

Browse files
committed
remote: add remaining Serializers
* storePathHashPart * storePathName * pathMetadata * someHashAlgo * digest
1 parent 76e2a41 commit 37c030c

File tree

3 files changed

+198
-4
lines changed

3 files changed

+198
-4
lines changed

hnix-store-remote/hnix-store-remote.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ test-suite remote
162162
, hnix-store-remote
163163
, hnix-store-tests
164164
, cereal
165+
, crypton
166+
, dependent-sum > 0.7 && < 1
165167
, some > 1.0.5 && < 2
166168
, text
167169
, time

hnix-store-remote/src/System/Nix/Store/Remote/Serializer.hs

Lines changed: 162 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ module System.Nix.Store.Remote.Serializer
3333
, protoVersion
3434
-- * StorePath
3535
, storePath
36+
, storePathHashPart
37+
, storePathName
38+
-- * Metadata
39+
, pathMetadata
40+
-- * Some HashAlgo
41+
, someHashAlgo
42+
-- * Digest
43+
, digest
3644
-- * Derivation
3745
, derivation
3846
-- * Derivation
@@ -59,12 +67,15 @@ import Control.Monad.Reader (MonadReader)
5967
import Control.Monad.Trans (MonadTrans, lift)
6068
import Control.Monad.Trans.Reader (ReaderT, runReaderT)
6169
import Control.Monad.Trans.Except (ExceptT, runExceptT)
70+
import Crypto.Hash (Digest, HashAlgorithm, SHA256)
6271
import Data.ByteString (ByteString)
72+
import Data.Dependent.Sum (DSum((:=>)))
6373
import Data.Fixed (Uni)
6474
import Data.Hashable (Hashable)
6575
import Data.HashSet (HashSet)
6676
import Data.Map (Map)
6777
import Data.Set (Set)
78+
import Data.Some (Some)
6879
import Data.Text (Text)
6980
import Data.Time (NominalDiffTime, UTCTime)
7081
import Data.Vector (Vector)
@@ -86,13 +97,23 @@ import qualified Data.Time.Clock.POSIX
8697
import qualified Data.Vector
8798

8899
import Data.Serializer
100+
import System.Nix.Base (BaseEncoding(NixBase32))
89101
import System.Nix.Build (BuildMode, BuildResult(..))
102+
import System.Nix.ContentAddress (ContentAddress)
90103
import System.Nix.Derivation (Derivation(..), DerivationOutput(..))
91104
import System.Nix.DerivedPath (DerivedPath, ParseOutputsError)
92-
import System.Nix.StorePath (HasStoreDir(..), InvalidPathError, StorePath)
105+
import System.Nix.Hash (HashAlgo)
106+
import System.Nix.StorePath (HasStoreDir(..), InvalidPathError, StorePath, StorePathHashPart, StorePathName)
107+
import System.Nix.StorePath.Metadata (Metadata(..), StorePathTrust(..))
93108
import System.Nix.Store.Remote.Types
94109

110+
import qualified Data.Coerce
111+
import qualified Data.Bifunctor
112+
import qualified Data.Some
113+
import qualified System.Nix.Base
114+
import qualified System.Nix.ContentAddress
95115
import qualified System.Nix.DerivedPath
116+
import qualified System.Nix.Hash
96117
import qualified System.Nix.StorePath
97118

98119
-- | Transformer for @Serializer@
@@ -144,10 +165,15 @@ data PrimError
144165
, badPaddingLen :: Int
145166
, badPaddingPads :: [Word8]
146167
}
168+
| PrimError_ContentAddress String
147169
| PrimError_DerivedPath ParseOutputsError
170+
| PrimError_Digest String
148171
| PrimError_EnumOutOfMinBound Int
149172
| PrimError_EnumOutOfMaxBound Int
173+
| PrimError_HashAlgo String
150174
| PrimError_IllegalBool Word64
175+
| PrimError_InvalidNixBase32
176+
| PrimError_NarHashMustBeSHA256
151177
| PrimError_NotYetImplemented String (ForPV ProtoVersion)
152178
| PrimError_Path InvalidPathError
153179
deriving (Eq, Ord, Generic, Show)
@@ -260,7 +286,7 @@ maybeText = mapIsoSerializer
260286
t | Data.Text.null t -> Nothing
261287
t | otherwise -> Just t
262288
)
263-
(Prelude.maybe mempty id)
289+
(maybe mempty id)
264290
text
265291

266292
-- * UTCTime
@@ -379,6 +405,140 @@ storePath = Serializer
379405
$ System.Nix.StorePath.storePathToRawFilePath sd p
380406
}
381407

408+
storePathHashPart :: NixSerializer r PrimError StorePathHashPart
409+
storePathHashPart =
410+
mapIsoSerializer
411+
System.Nix.StorePath.unsafeMakeStorePathHashPart
412+
System.Nix.StorePath.unStorePathHashPart
413+
$ mapPrismSerializer
414+
(Data.Bifunctor.first (pure PrimError_InvalidNixBase32)
415+
. System.Nix.Base.decodeWith NixBase32)
416+
(System.Nix.Base.encodeWith NixBase32)
417+
text
418+
419+
storePathName :: NixSerializer r PrimError StorePathName
420+
storePathName =
421+
mapPrismSerializer
422+
(Data.Bifunctor.first PrimError_Path
423+
. System.Nix.StorePath.makeStorePathName)
424+
System.Nix.StorePath.unStorePathName
425+
text
426+
427+
pathMetadata
428+
:: HasStoreDir r
429+
=> NixSerializer r PrimError (Metadata StorePath)
430+
pathMetadata = Serializer
431+
{ getS = do
432+
deriverPath <- getS maybePath
433+
434+
digest' <- getS $ digest NixBase32
435+
let narHash = System.Nix.Hash.HashAlgo_SHA256 :=> digest'
436+
437+
references <- getS $ hashSet storePath
438+
registrationTime <- getS time
439+
narBytes <- (\case
440+
0 -> Nothing
441+
size -> Just size) <$> getS int
442+
trust <- getS storePathTrust
443+
444+
_sigStrings <- getS $ list text
445+
contentAddress <- getS maybeContentAddress
446+
447+
let
448+
-- XXX: signatures need pubkey from config
449+
sigs = mempty
450+
pure $ Metadata{..}
451+
452+
, putS = \Metadata{..} -> do
453+
putS maybePath deriverPath
454+
455+
let putNarHash
456+
:: DSum HashAlgo Digest
457+
-> SerialT r PrimError PutM ()
458+
putNarHash = \case
459+
System.Nix.Hash.HashAlgo_SHA256 :=> d
460+
-> putS (digest @SHA256 NixBase32) d
461+
_ -> throwError PrimError_NarHashMustBeSHA256
462+
463+
putNarHash narHash
464+
465+
putS (hashSet storePath) references
466+
putS time registrationTime
467+
putS int $ Prelude.maybe 0 id $ narBytes
468+
putS storePathTrust trust
469+
putS (hashSet text) mempty
470+
putS maybeContentAddress contentAddress
471+
}
472+
where
473+
maybeContentAddress
474+
:: NixSerializer r PrimError (Maybe ContentAddress)
475+
maybeContentAddress =
476+
mapPrismSerializer
477+
(maybe
478+
(pure Nothing)
479+
$ Data.Bifunctor.bimap
480+
PrimError_ContentAddress
481+
Just
482+
. System.Nix.ContentAddress.parseContentAddress
483+
)
484+
(fmap System.Nix.ContentAddress.buildContentAddress)
485+
maybeText
486+
487+
maybePath
488+
:: HasStoreDir r
489+
=> NixSerializer r PrimError (Maybe StorePath)
490+
maybePath = Serializer
491+
{ getS = do
492+
getS maybeText >>= \case
493+
Nothing -> pure Nothing
494+
Just t -> do
495+
sd <- Control.Monad.Reader.asks hasStoreDir
496+
either
497+
(throwError . PrimError_Path)
498+
(pure . pure)
499+
$ System.Nix.StorePath.parsePathFromText sd t
500+
501+
, putS = \case
502+
Nothing -> putS maybeText Nothing
503+
Just p -> do
504+
sd <- Control.Monad.Reader.asks hasStoreDir
505+
putS text $ System.Nix.StorePath.storePathToText sd p
506+
}
507+
508+
storePathTrust =
509+
mapIsoSerializer
510+
(\case False -> BuiltElsewhere; True -> BuiltLocally)
511+
(\case BuiltElsewhere -> False; BuiltLocally -> True)
512+
bool
513+
514+
515+
-- * Some HashAlgo
516+
517+
someHashAlgo :: NixSerializer r PrimError (Some HashAlgo)
518+
someHashAlgo =
519+
mapPrismSerializer
520+
(Data.Bifunctor.first PrimError_HashAlgo
521+
. System.Nix.Hash.textToAlgo)
522+
(Data.Some.foldSome System.Nix.Hash.algoToText)
523+
text
524+
525+
-- * Digest
526+
527+
digest
528+
:: forall a r
529+
. HashAlgorithm a
530+
=> BaseEncoding
531+
-> NixSerializer r PrimError (Digest a)
532+
digest base =
533+
mapIsoSerializer
534+
Data.Coerce.coerce
535+
Data.Coerce.coerce
536+
$ mapPrismSerializer
537+
(Data.Bifunctor.first PrimError_Digest
538+
. System.Nix.Hash.decodeDigestWith @a base)
539+
(System.Nix.Hash.encodeDigestWith base)
540+
$ text
541+
382542
derivationOutput
383543
:: HasStoreDir r
384544
=> NixSerializer r PrimError (DerivationOutput StorePath Text)

hnix-store-remote/tests/NixSerializerSpec.hs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
module NixSerializerSpec (spec) where
44

5+
import Crypto.Hash (MD5, SHA1, SHA256, SHA512)
6+
import Data.Dependent.Sum (DSum((:=>)))
57
import Data.Fixed (Uni)
68
import Data.Time (NominalDiffTime)
79
import Test.Hspec (Expectation, Spec, describe, parallel, shouldBe)
@@ -12,11 +14,13 @@ import Test.QuickCheck.Instances ()
1214
import qualified Data.Time.Clock.POSIX
1315
import qualified Data.Serializer
1416
import qualified System.Nix.Build
17+
import qualified System.Nix.Hash
1518

1619
import System.Nix.Arbitrary ()
1720
import System.Nix.Build (BuildResult)
1821
import System.Nix.Derivation (Derivation(inputDrvs))
1922
import System.Nix.StorePath (StoreDir)
23+
import System.Nix.StorePath.Metadata (Metadata(..))
2024
import System.Nix.Store.Remote.Arbitrary ()
2125
import System.Nix.Store.Remote.Serializer
2226
import System.Nix.Store.Remote.Types (ErrorInfo(..), Logger(..), ProtoVersion(..), Trace(..))
@@ -89,8 +93,36 @@ spec = parallel $ do
8993
, System.Nix.Build.stopTime = Data.Time.Clock.POSIX.posixSecondsToUTCTime 0
9094
}
9195

92-
prop "StorePath" $ \sd ->
93-
roundtripSReader @StoreDir storePath sd
96+
prop "StorePath" $
97+
roundtripSReader @StoreDir storePath
98+
99+
prop "StorePathHashPart" $
100+
roundtripS storePathHashPart
101+
102+
prop "StorePathName" $
103+
roundtripS storePathName
104+
105+
let narHashIsSHA256 Metadata{..} =
106+
case narHash of
107+
(System.Nix.Hash.HashAlgo_SHA256 :=> _) -> True
108+
_ -> False
109+
110+
prop "Metadata (StorePath)"
111+
$ \sd -> forAll (arbitrary `suchThat` (\m -> narHashIsSHA256 m && narBytes m /= Just 0))
112+
$ roundtripSReader @StoreDir pathMetadata sd
113+
. (\m -> m
114+
{ registrationTime = Data.Time.Clock.POSIX.posixSecondsToUTCTime 0
115+
, sigs = mempty
116+
})
117+
118+
prop "Some HashAlgo" $
119+
roundtripS someHashAlgo
120+
121+
describe "Digest" $ do
122+
prop "MD5" $ roundtripS . digest @MD5
123+
prop "SHA1" $ roundtripS . digest @SHA1
124+
prop "SHA256" $ roundtripS . digest @SHA256
125+
prop "SHA512" $ roundtripS . digest @SHA512
94126

95127
prop "Derivation" $ \sd ->
96128
roundtripSReader @StoreDir derivation sd

0 commit comments

Comments
 (0)