packages feed

hnix-store-core 0.4.3.0 → 0.5.0.0

raw patch · 17 files changed

+339/−283 lines, 17 filesdep +cryptonitedep +memorydep −cryptohash-md5dep −cryptohash-sha1dep −cryptohash-sha256dep ~attoparsecdep ~basedep ~base16-bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: cryptonite, memory

Dependencies removed: cryptohash-md5, cryptohash-sha1, cryptohash-sha256, cryptohash-sha512

Dependency ranges changed: attoparsec, base, base16-bytestring, base64-bytestring, bytestring, cereal, containers, directory, filepath, hashable, lifted-base, monad-control, mtl, saltine, text, time, unix, unordered-containers, vector

API changes (from Hackage documentation)

- System.Nix.Hash: -- | The incremental state for constructing a hash.
- System.Nix.Hash: Base32 :: BaseEncoding
- System.Nix.Hash: MD5 :: HashAlgorithm
- System.Nix.Hash: SHA1 :: HashAlgorithm
- System.Nix.Hash: SHA256 :: HashAlgorithm
- System.Nix.Hash: SHA512 :: HashAlgorithm
- System.Nix.Hash: Truncated :: Nat -> HashAlgorithm -> HashAlgorithm
- System.Nix.Hash: class ValidAlgo (a :: HashAlgorithm) where {
- System.Nix.Hash: data Digest (a :: HashAlgorithm)
- System.Nix.Hash: data HashAlgorithm
- System.Nix.Hash: decodeBase :: BaseEncoding -> Text -> Either String (Digest a)
- System.Nix.Hash: encodeInBase :: BaseEncoding -> Digest a -> Text
- System.Nix.Hash: finalize :: ValidAlgo a => AlgoCtx a -> Digest a
- System.Nix.Hash: hash :: forall a. ValidAlgo a => ByteString -> Digest a
- System.Nix.Hash: hashLazy :: forall a. ValidAlgo a => ByteString -> Digest a
- System.Nix.Hash: hashSize :: NamedAlgo a => Int
- System.Nix.Hash: initialize :: ValidAlgo a => AlgoCtx a
- System.Nix.Hash: type family AlgoCtx a;
- System.Nix.Hash: update :: ValidAlgo a => AlgoCtx a -> ByteString -> AlgoCtx a
- System.Nix.Hash: }
- System.Nix.Internal.Base32: integerToBS :: Integer -> ByteString
- System.Nix.Internal.Base32: unsafeDecode :: Text -> Either String ByteString
- System.Nix.Internal.Hash: -- | The incremental state for constructing a hash.
- System.Nix.Internal.Hash: Base16 :: BaseEncoding
- System.Nix.Internal.Hash: Base32 :: BaseEncoding
- System.Nix.Internal.Hash: Base64 :: BaseEncoding
- System.Nix.Internal.Hash: Digest :: ByteString -> Digest (a :: HashAlgorithm)
- System.Nix.Internal.Hash: MD5 :: HashAlgorithm
- System.Nix.Internal.Hash: SHA1 :: HashAlgorithm
- System.Nix.Internal.Hash: SHA256 :: HashAlgorithm
- System.Nix.Internal.Hash: SHA512 :: HashAlgorithm
- System.Nix.Internal.Hash: Truncated :: Nat -> HashAlgorithm -> HashAlgorithm
- System.Nix.Internal.Hash: class ValidAlgo (a :: HashAlgorithm) where {
- System.Nix.Internal.Hash: data BaseEncoding
- System.Nix.Internal.Hash: data HashAlgorithm
- System.Nix.Internal.Hash: decodeBase :: BaseEncoding -> Text -> Either String (Digest a)
- System.Nix.Internal.Hash: encodeInBase :: BaseEncoding -> Digest a -> Text
- System.Nix.Internal.Hash: finalize :: ValidAlgo a => AlgoCtx a -> Digest a
- System.Nix.Internal.Hash: hash :: forall a. ValidAlgo a => ByteString -> Digest a
- System.Nix.Internal.Hash: hashLazy :: forall a. ValidAlgo a => ByteString -> Digest a
- System.Nix.Internal.Hash: hashSize :: NamedAlgo a => Int
- System.Nix.Internal.Hash: initialize :: ValidAlgo a => AlgoCtx a
- System.Nix.Internal.Hash: instance (System.Nix.Internal.Hash.ValidAlgo a, GHC.TypeNats.KnownNat n) => System.Nix.Internal.Hash.ValidAlgo ('System.Nix.Internal.Hash.Truncated n a)
- System.Nix.Internal.Hash: instance Data.Hashable.Class.Hashable (System.Nix.Internal.Hash.Digest a)
- System.Nix.Internal.Hash: instance GHC.Classes.Eq (System.Nix.Internal.Hash.Digest a)
- System.Nix.Internal.Hash: instance GHC.Classes.Ord (System.Nix.Internal.Hash.Digest a)
- System.Nix.Internal.Hash: instance GHC.Show.Show (System.Nix.Internal.Hash.Digest a)
- System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.NamedAlgo 'System.Nix.Internal.Hash.MD5
- System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.NamedAlgo 'System.Nix.Internal.Hash.SHA1
- System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.NamedAlgo 'System.Nix.Internal.Hash.SHA256
- System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.NamedAlgo 'System.Nix.Internal.Hash.SHA512
- System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.ValidAlgo 'System.Nix.Internal.Hash.MD5
- System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.ValidAlgo 'System.Nix.Internal.Hash.SHA1
- System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.ValidAlgo 'System.Nix.Internal.Hash.SHA256
- System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.ValidAlgo 'System.Nix.Internal.Hash.SHA512
- System.Nix.Internal.Hash: newtype Digest (a :: HashAlgorithm)
- System.Nix.Internal.Hash: truncateDigest :: forall n a. KnownNat n => Digest a -> Digest ('Truncated n a)
- System.Nix.Internal.Hash: type family AlgoCtx a;
- System.Nix.Internal.Hash: update :: ValidAlgo a => AlgoCtx a -> ByteString -> AlgoCtx a
- System.Nix.Internal.Hash: }
- System.Nix.Internal.Nar.Parser: LinkInfo :: String -> String -> String -> LinkInfo
- System.Nix.Internal.Nar.Parser: NarParser :: StateT ParserState (ExceptT String (ReaderT (NarEffects m) m)) a -> NarParser m a
- System.Nix.Internal.Nar.Parser: ParserState :: ![Text] -> ![String] -> Handle -> [LinkInfo] -> ParserState
- System.Nix.Internal.Nar.Parser: [directoryStack] :: ParserState -> ![String]
- System.Nix.Internal.Nar.Parser: [handle] :: ParserState -> Handle
- System.Nix.Internal.Nar.Parser: [linkFile] :: LinkInfo -> String
- System.Nix.Internal.Nar.Parser: [linkPWD] :: LinkInfo -> String
- System.Nix.Internal.Nar.Parser: [linkTarget] :: LinkInfo -> String
- System.Nix.Internal.Nar.Parser: [links] :: ParserState -> [LinkInfo]
- System.Nix.Internal.Nar.Parser: [runNarParser] :: NarParser m a -> StateT ParserState (ExceptT String (ReaderT (NarEffects m) m)) a
- System.Nix.Internal.Nar.Parser: [tokenStack] :: ParserState -> ![Text]
- System.Nix.Internal.Nar.Parser: consume :: (MonadIO m, MonadFail m) => Int -> NarParser m ByteString
- System.Nix.Internal.Nar.Parser: createLinks :: MonadIO m => NarParser m ()
- System.Nix.Internal.Nar.Parser: currentFile :: Monad m => NarParser m FilePath
- System.Nix.Internal.Nar.Parser: data LinkInfo
- System.Nix.Internal.Nar.Parser: data ParserState
- System.Nix.Internal.Nar.Parser: dbgState :: MonadIO m => NarParser m ()
- System.Nix.Internal.Nar.Parser: expectRawString :: (MonadIO m, MonadFail m) => ByteString -> NarParser m ()
- System.Nix.Internal.Nar.Parser: expectStr :: (MonadIO m, MonadFail m) => Text -> NarParser m ()
- System.Nix.Internal.Nar.Parser: matchStr :: (MonadIO m, MonadFail m) => [(Text, NarParser m a)] -> NarParser m a
- System.Nix.Internal.Nar.Parser: newtype NarParser m a
- System.Nix.Internal.Nar.Parser: padLen :: Int -> Int
- System.Nix.Internal.Nar.Parser: parens :: (MonadIO m, MonadFail m) => NarParser m a -> NarParser m a
- System.Nix.Internal.Nar.Parser: parseDirectory :: (MonadIO m, MonadFail m) => NarParser m ()
- System.Nix.Internal.Nar.Parser: parseFSO :: (MonadIO m, MonadFail m) => NarParser m ()
- System.Nix.Internal.Nar.Parser: parseFile :: forall m. (MonadIO m, MonadFail m) => NarParser m ()
- System.Nix.Internal.Nar.Parser: parseLength :: (MonadIO m, MonadFail m) => NarParser m Int64
- System.Nix.Internal.Nar.Parser: parseStr :: (MonadIO m, MonadFail m) => NarParser m Text
- System.Nix.Internal.Nar.Parser: parseSymlink :: (MonadIO m, MonadFail m) => NarParser m ()
- System.Nix.Internal.Nar.Parser: popFileName :: Monad m => NarParser m ()
- System.Nix.Internal.Nar.Parser: popStr :: Monad m => NarParser m (Maybe Text)
- System.Nix.Internal.Nar.Parser: pushFileName :: Monad m => FilePath -> NarParser m ()
- System.Nix.Internal.Nar.Parser: pushLink :: Monad m => LinkInfo -> NarParser m ()
- System.Nix.Internal.Nar.Parser: pushStr :: Monad m => Text -> NarParser m ()
- System.Nix.Internal.Nar.Streamer: isExecutable :: Functor m => NarEffects m -> FilePath -> m IsExecutable
- System.Nix.Internal.Nar.Streamer: padLen :: Int -> Int
- System.Nix.Internal.Signature: Signature :: ByteString -> Signature
- System.Nix.Internal.Signature: newtype Signature
- System.Nix.Internal.StorePath: reasonInvalid :: Text -> String
- System.Nix.Internal.StorePath: type RawFilePath = ByteString
- System.Nix.Internal.StorePath: type StorePathHashAlgo = 'Truncated 20 'SHA256
- System.Nix.Internal.StorePath: validStorePathNameChar :: Char -> Bool
- System.Nix.StorePath: data StorePathName
- System.Nix.StorePath: type StorePathHashAlgo = 'Truncated 20 'SHA256
- System.Nix.StorePath: unStorePathName :: StorePathName -> Text
+ System.Nix.Hash: NixBase32 :: BaseEncoding
+ System.Nix.Hash: decodeDigestWith :: HashAlgorithm a => BaseEncoding -> Text -> Either String (Digest a)
+ System.Nix.Hash: encodeDigestWith :: BaseEncoding -> Digest a -> Text
+ System.Nix.Hash: mkStorePathHash :: forall a. HashAlgorithm a => ByteString -> ByteString
+ System.Nix.Internal.Base: Base16 :: BaseEncoding
+ System.Nix.Internal.Base: Base64 :: BaseEncoding
+ System.Nix.Internal.Base: NixBase32 :: BaseEncoding
+ System.Nix.Internal.Base: data BaseEncoding
+ System.Nix.Internal.Base: decodeWith :: BaseEncoding -> Text -> Either String ByteString
+ System.Nix.Internal.Base: encodeWith :: BaseEncoding -> ByteString -> Text
+ System.Nix.Internal.Hash: decodeDigestWith :: HashAlgorithm a => BaseEncoding -> Text -> Either String (Digest a)
+ System.Nix.Internal.Hash: encodeDigestWith :: BaseEncoding -> Digest a -> Text
+ System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.NamedAlgo Crypto.Hash.MD5.MD5
+ System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.NamedAlgo Crypto.Hash.SHA1.SHA1
+ System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.NamedAlgo Crypto.Hash.SHA256.SHA256
+ System.Nix.Internal.Hash: instance System.Nix.Internal.Hash.NamedAlgo Crypto.Hash.SHA512.SHA512
+ System.Nix.Internal.Hash: mkStorePathHash :: forall a. HashAlgorithm a => ByteString -> ByteString
+ System.Nix.Internal.Signature: data Signature
+ System.Nix.Internal.StorePath: StorePathHashPart :: ByteString -> StorePathHashPart
+ System.Nix.Internal.StorePath: instance Data.Hashable.Class.Hashable System.Nix.Internal.StorePath.StorePathHashPart
+ System.Nix.Internal.StorePath: instance GHC.Classes.Eq System.Nix.Internal.StorePath.StorePathHashPart
+ System.Nix.Internal.StorePath: instance GHC.Classes.Ord System.Nix.Internal.StorePath.StorePathHashPart
+ System.Nix.Internal.StorePath: instance GHC.Show.Show System.Nix.Internal.StorePath.StorePathHashPart
+ System.Nix.Internal.StorePath: mkStorePathHashPart :: ByteString -> StorePathHashPart
+ System.Nix.Internal.StorePath: newtype StorePathHashPart
+ System.Nix.Internal.Truncation: truncateInNixWay :: Int -> ByteString -> ByteString
+ System.Nix.StorePath: StorePathHashPart :: ByteString -> StorePathHashPart
+ System.Nix.StorePath: StorePathName :: Text -> StorePathName
+ System.Nix.StorePath: [unStorePathName] :: StorePathName -> Text
+ System.Nix.StorePath: mkStorePathHashPart :: ByteString -> StorePathHashPart
+ System.Nix.StorePath: newtype StorePathHashPart
+ System.Nix.StorePath: newtype StorePathName
- System.Nix.Hash: class ValidAlgo a => NamedAlgo (a :: HashAlgorithm)
+ System.Nix.Hash: class HashAlgorithm a => NamedAlgo a
- System.Nix.Internal.Hash: class ValidAlgo a => NamedAlgo (a :: HashAlgorithm)
+ System.Nix.Internal.Hash: class HashAlgorithm a => NamedAlgo a
- System.Nix.Internal.StorePath: StorePath :: !Digest StorePathHashAlgo -> !StorePathName -> !FilePath -> StorePath
+ System.Nix.Internal.StorePath: StorePath :: !StorePathHashPart -> !StorePathName -> !FilePath -> StorePath
- System.Nix.Internal.StorePath: Text :: !Digest 'SHA256 -> ContentAddressableAddress
+ System.Nix.Internal.StorePath: Text :: !Digest SHA256 -> ContentAddressableAddress
- System.Nix.Internal.StorePath: [storePathHash] :: StorePath -> !Digest StorePathHashAlgo
+ System.Nix.Internal.StorePath: [storePathHash] :: StorePath -> !StorePathHashPart
- System.Nix.ReadonlyStore: makeStorePath :: forall hashAlgo. NamedAlgo hashAlgo => FilePath -> ByteString -> Digest hashAlgo -> StorePathName -> StorePath
+ System.Nix.ReadonlyStore: makeStorePath :: forall h. NamedAlgo h => FilePath -> ByteString -> Digest h -> StorePathName -> StorePath
- System.Nix.ReadonlyStore: makeTextPath :: FilePath -> StorePathName -> Digest 'SHA256 -> StorePathSet -> StorePath
+ System.Nix.ReadonlyStore: makeTextPath :: FilePath -> StorePathName -> Digest SHA256 -> StorePathSet -> StorePath
- System.Nix.StorePath: StorePath :: !Digest StorePathHashAlgo -> !StorePathName -> !FilePath -> StorePath
+ System.Nix.StorePath: StorePath :: !StorePathHashPart -> !StorePathName -> !FilePath -> StorePath
- System.Nix.StorePath: Text :: !Digest 'SHA256 -> ContentAddressableAddress
+ System.Nix.StorePath: Text :: !Digest SHA256 -> ContentAddressableAddress
- System.Nix.StorePath: [storePathHash] :: StorePath -> !Digest StorePathHashAlgo
+ System.Nix.StorePath: [storePathHash] :: StorePath -> !StorePathHashPart

Files

ChangeLog.md view
@@ -1,9 +1,44 @@-# Revision history for hnix-store-core+# ChangeLog -## [0.4.3.0](https://github.com/haskell-nix/hnix-store/compare/0.4.2.0...0.4.3.0) 2021-05-30+## [0.5.0.0](https://github.com/haskell-nix/hnix-store/compare/0.4.3.0...core-0.5.0.0) 2021-06-10 +* Breaking:++  * `System.Nix.Hash`:+    * [(link)](https://github.com/haskell-nix/hnix-store/pull/157/commits/97146b41cc87327625e02b81971aeb2fd7d66a3f) Migration from packages `cryptohash-` -> `cryptonite`:+      * rm `newtype Digest` in favour of `cryptonite: newtype Digest`+      * rm `data HashAlgorithm` in favour of `cryptonite: class HashAlgorithm`+      * rm `class ValidAlgo` in favour of `cryptonite: class HashAlgorithm`.+      * `class NamedAlgo` removed `hashSize` in favour of `cryptonite: class HashAlgorithm: hashDigestSize`. Former became a subclass of the latter.+      * rm `hash` in favour of `cryptonite: hash`+      * rm `hashLazy` in favour of `cryptonite: hashlazy`+    * [(link)](https://github.com/haskell-nix/hnix-store/pull/157/commits/2af74986de8aef1a13dbfc955886f9935ca246a3) Base encoding/decoding function for hashes (digests) changed (due to changes in type system & separation of specially truncated Nix Store hasing):+      * `encode(InBase -> DigestWith)`+      * `decode(Base -> DigestWith)`+  * [(link)](https://github.com/haskell-nix/hnix-store/pull/157/commits/2af74986de8aef1a13dbfc955886f9935ca246a3) `System.Nix.StorePath`:+    * rm `type StorePathHashAlgo = 'Truncated 20 'SHA256` in favour of `StorePathHashPart` & `mkStorePathHashPart`.+    * rm `unStorePathName`, please use `GHC: coerce` for `StorePathName <-> Text`, `StorePathName` data constructor is provided.+  * `Internal` modules now have export lists, if something, please contact.++ * Additional: +  * [(link)](https://github.com/haskell-nix/hnix-store/pull/157/commits/97146b41cc87327625e02b81971aeb2fd7d66a3f) Support of GHC 9.0.++  * [(link)](https://github.com/haskell-nix/hnix-store/pull/157/commits/2af74986de8aef1a13dbfc955886f9935ca246a3) `System.Nix.StorePath`:+    * exposed `StorePathName` data constructor to API.+    * added `newtype StorePathHashPart = StorePathHashPart ByteString`.+      * added builder `mkStorePathHashPart :: ByteString -> StorePathHashPart`+  * [(link)](https://github.com/haskell-nix/hnix-store/pull/157/commits/2af74986de8aef1a13dbfc955886f9935ca246a3) `System.Nix.Hash`:+    * Nix store (which are specially truncated) hashes are now handled separately from other hashes:+      * add `mkStorePathHash` - a function to create a content into Nix storepath-style hash:+        `mkStorePathHash :: HashAlgorithm a => ByteString -> ByteString`+        but recommend to at once use `mkStorePathHashPart`.+    ++## [0.4.3.0](https://github.com/haskell-nix/hnix-store/compare/0.4.2.0...0.4.3.0) 2021-05-30++* Additional:   * [(link)](https://github.com/haskell-nix/hnix-store/commit/b85f7c875fe6b0bca939ffbcd8b9bd0ab1598aa0) `System.Nix.ReadonlyStore`: add a readonly `computeStorePathForPath`   * [(link)](https://github.com/haskell-nix/hnix-store/commit/db71ecea3109c0ba270fa98a9041a8556e35217f) `System.Nix.ReadonlyStore`: `computeStorePathForPath`: force SHA256 as it's the only valid choice   * [(link)](https://github.com/haskell-nix/hnix-store/commit/5fddf3c66ba1bcabb72c4d6b6e09fb41a7acd62c): `makeTextPath`: order the references
hnix-store-core.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                hnix-store-core-version:             0.4.3.0+version:             0.5.0.0 synopsis:            Core effects for interacting with the Nix store. description:   This package contains types and functions needed to describe@@ -33,7 +33,9 @@     , System.Nix.Build     , System.Nix.Derivation     , System.Nix.Hash+    , System.Nix.Internal.Base     , System.Nix.Internal.Base32+    , System.Nix.Internal.Truncation     , System.Nix.Internal.Hash     , System.Nix.Internal.Nar.Parser     , System.Nix.Internal.Nar.Streamer@@ -54,10 +56,9 @@     , bytestring     , cereal     , containers-    , cryptohash-md5-    , cryptohash-sha1-    , cryptohash-sha256-    , cryptohash-sha512+    -- Required for cryptonite low-level type convertion+    , memory+    , cryptonite     , directory     , filepath     , hashable@@ -104,6 +105,7 @@     , binary     , bytestring     , containers+    , cryptonite     , directory     , filepath     , process
src/System/Nix/Hash.hs view
@@ -2,21 +2,17 @@ Description : Cryptographic hashes for hnix-store. -} module System.Nix.Hash-  ( Hash.Digest--  , Hash.HashAlgorithm(..)-  , Hash.ValidAlgo(..)+  ( Hash.mkStorePathHash   , Hash.NamedAlgo(..)   , Hash.SomeNamedDigest(..) -  , Hash.hash-  , Hash.hashLazy   , Hash.mkNamedDigest -  , Hash.BaseEncoding(..)-  , Hash.encodeInBase-  , Hash.decodeBase+  , Base.BaseEncoding(..)+  , Hash.encodeDigestWith+  , Hash.decodeDigestWith   ) where  import qualified System.Nix.Internal.Hash      as Hash+import qualified System.Nix.Internal.Base      as Base
+ src/System/Nix/Internal/Base.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE CPP #-}++module System.Nix.Internal.Base+  ( BaseEncoding(Base16,NixBase32,Base64)+  , encodeWith+  , decodeWith+  )+where++import qualified Data.Text              as T+import qualified Data.Text.Encoding     as T+import qualified Data.ByteString        as Bytes+import qualified Data.ByteString.Base16 as Base16+import qualified System.Nix.Base32      as Base32  -- Nix has own Base32 encoding+import qualified Data.ByteString.Base64 as Base64++-- | Constructors to indicate the base encodings+data BaseEncoding+  = NixBase32+  -- | ^ Nix has a special map of Base32 encoding+  -- Placed first, since it determines Haskell optimizations of pattern matches, & NixBase seems be the most widely used in Nix.+  | Base16+  | Base64+++-- | Encode @ByteString@ with @Base@ encoding, produce @Text@.+encodeWith :: BaseEncoding -> Bytes.ByteString -> T.Text+encodeWith Base16 = T.decodeUtf8 . Base16.encode+encodeWith NixBase32 = Base32.encode+encodeWith Base64 = T.decodeUtf8 . Base64.encode++-- | Take the input & @Base@ encoding witness -> decode into @Text@.+decodeWith :: BaseEncoding -> T.Text -> Either String Bytes.ByteString+#if MIN_VERSION_base16_bytestring(1,0,0)+decodeWith Base16 = Base16.decode . T.encodeUtf8+#else+decodeWith Base16 = lDecode  -- this tacit sugar simply makes GHC pleased with number of args+ where+  lDecode t =+    case Base16.decode (T.encodeUtf8 t) of+      (x, "") -> pure $ x+      _       -> Left $ "Unable to decode base16 string" <> T.unpack t+#endif+decodeWith NixBase32 = Base32.decode+decodeWith Base64 = Base64.decode . T.encodeUtf8
src/System/Nix/Internal/Base32.hs view
@@ -1,4 +1,9 @@-module System.Nix.Internal.Base32 where+module System.Nix.Internal.Base32+ ( encode+ , decode+ , digits32+ )+where   import           Data.Bool                      ( bool )@@ -22,7 +27,7 @@  -- | Encode a 'BS.ByteString' in Nix's base32 encoding encode :: ByteString -> Text-encode c = Data.Text.pack $ fmap char32 [nChar - 1, nChar - 2 .. 0]+encode c = Data.Text.pack $ takeCharPosFromDict <$> [nChar - 1, nChar - 2 .. 0]  where   -- Each base32 character gives us 5 bits of information, while   -- each byte gives is 8. Because 'div' rounds down, we need to add@@ -43,8 +48,8 @@       [ fromIntegral (byte j) * (256 ^ j)         | j <- [0 .. Bytes.length c - 1] ] -  char32 :: Integer -> Char-  char32 i = digits32 Vector.! digitInd+  takeCharPosFromDict :: Integer -> Char+  takeCharPosFromDict i = digits32 Vector.! digitInd    where     digitInd =       fromIntegral $@@ -54,7 +59,7 @@ decode :: Text -> Either String ByteString decode what =   bool-    (Left "Invalid Base32 string")+    (Left "Invalid NixBase32 string")     (unsafeDecode what)     (Data.Text.all (`elem` digits32) what) 
src/System/Nix/Internal/Hash.hs view
@@ -12,223 +12,96 @@ {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE CPP #-} -module System.Nix.Internal.Hash where+module System.Nix.Internal.Hash+  ( NamedAlgo(..)+  , SomeNamedDigest(..)+  , mkNamedDigest+  , encodeDigestWith+  , decodeDigestWith+  , mkStorePathHash+  )+where -import qualified Crypto.Hash.MD5        as MD5-import qualified Crypto.Hash.SHA1       as SHA1-import qualified Crypto.Hash.SHA256     as SHA256-import qualified Crypto.Hash.SHA512     as SHA512+import qualified Crypto.Hash            as C import qualified Data.ByteString        as BS-import qualified Data.ByteString.Base16 as Base16-import qualified System.Nix.Base32      as Base32  -- Nix has own Base32 encoding-import qualified Data.ByteString.Base64 as Base64-import           Data.Bits              (xor)-import qualified Data.ByteString.Lazy   as BSL-import qualified Data.Hashable          as DataHashable-import           Data.List              (foldl')-import           Data.Proxy             (Proxy(Proxy)) import           Data.Text              (Text) import qualified Data.Text              as T-import qualified Data.Text.Encoding     as T-import           Data.Word              (Word8)-import           GHC.TypeLits           (Nat, KnownNat, natVal)-import           Data.Coerce            (coerce)---- | Constructors to indicate the base encodings-data BaseEncoding-  = Base16-  | Base32-  -- | ^ Nix has a special map of Base32 encoding-  | Base64---- | The universe of supported hash algorithms.------ Currently only intended for use at the type level.-data HashAlgorithm-  = MD5-  | SHA1-  | SHA256-  | SHA512-  | Truncated Nat HashAlgorithm-    -- ^ The hash algorithm obtained by truncating the result of the-    -- input 'HashAlgorithm' to the given number of bytes. See-    -- 'truncateDigest' for a description of the truncation algorithm.---- | The result of running a 'HashAlgorithm'.-newtype Digest (a :: HashAlgorithm) =-  Digest BS.ByteString deriving (Eq, Ord, DataHashable.Hashable)--instance Show (Digest a) where-  show = ("Digest " <>) . show . encodeInBase Base32---- | The primitive interface for incremental hashing for a given--- 'HashAlgorithm'. Every 'HashAlgorithm' should have an instance.-class ValidAlgo (a :: HashAlgorithm) where-  -- | The incremental state for constructing a hash.-  type AlgoCtx a--  -- | Start building a new hash.-  initialize        :: AlgoCtx a-  -- | Append a 'BS.ByteString' to the overall contents to be hashed.-  update            :: AlgoCtx a -> BS.ByteString -> AlgoCtx a-  -- | Finish hashing and generate the output.-  finalize          :: AlgoCtx a -> Digest a+import           System.Nix.Internal.Base+import           Data.ByteArray+import           System.Nix.Internal.Truncation  -- | A 'HashAlgorithm' with a canonical name, for serialization -- purposes (e.g. SRI hashes)-class ValidAlgo a => NamedAlgo (a :: HashAlgorithm) where+class C.HashAlgorithm a => NamedAlgo a where   algoName :: Text-  hashSize :: Int -instance NamedAlgo 'MD5 where+instance NamedAlgo C.MD5 where   algoName = "md5"-  hashSize = 16 -instance NamedAlgo 'SHA1 where+instance NamedAlgo C.SHA1 where   algoName = "sha1"-  hashSize = 20 -instance NamedAlgo 'SHA256 where+instance NamedAlgo C.SHA256 where   algoName = "sha256"-  hashSize = 32 -instance NamedAlgo 'SHA512 where+instance NamedAlgo C.SHA512 where   algoName = "sha512"-  hashSize = 64  -- | A digest whose 'NamedAlgo' is not known at compile time.-data SomeNamedDigest = forall a . NamedAlgo a => SomeDigest (Digest a)+data SomeNamedDigest = forall a . NamedAlgo a => SomeDigest (C.Digest a)  instance Show SomeNamedDigest where   show sd = case sd of-    SomeDigest (digest :: Digest hashType) -> T.unpack $ "SomeDigest " <> algoName @hashType <> ":" <> encodeInBase Base32 digest+    SomeDigest (digest :: C.Digest hashType) -> T.unpack $ "SomeDigest " <> algoName @hashType <> ":" <> encodeDigestWith NixBase32 digest  mkNamedDigest :: Text -> Text -> Either String SomeNamedDigest mkNamedDigest name sriHash =   let (sriName, h) = T.breakOnEnd "-" sriHash in-    if sriName == "" || sriName == (name <> "-")+    if sriName == "" || sriName == name <> "-"     then mkDigest h     else Left $ T.unpack $ "Sri hash method " <> sriName <> " does not match the required hash type " <> name  where   mkDigest h = case name of-    "md5"    -> SomeDigest <$> decodeGo @'MD5    h-    "sha1"   -> SomeDigest <$> decodeGo @'SHA1   h-    "sha256" -> SomeDigest <$> decodeGo @'SHA256 h-    "sha512" -> SomeDigest <$> decodeGo @'SHA512 h+    "md5"    -> SomeDigest <$> decodeGo C.MD5    h+    "sha1"   -> SomeDigest <$> decodeGo C.SHA1   h+    "sha256" -> SomeDigest <$> decodeGo C.SHA256 h+    "sha512" -> SomeDigest <$> decodeGo C.SHA512 h     _        -> Left $ "Unknown hash name: " <> T.unpack name-  decodeGo :: forall a . (NamedAlgo a, ValidAlgo a) => Text -> Either String (Digest a)-  decodeGo h-    | size == base16Len = decodeBase Base16 h-    | size == base32Len = decodeBase Base32 h-    | size == base64Len = decodeBase Base64 h+  decodeGo :: forall a . NamedAlgo a => a -> Text -> Either String (C.Digest a)+  decodeGo a h+    | size == base16Len = decodeDigestWith Base16 h+    | size == base32Len = decodeDigestWith NixBase32 h+    | size == base64Len = decodeDigestWith Base64 h     | otherwise = Left $ T.unpack sriHash <> " is not a valid " <> T.unpack name <> " hash. Its length (" <> show size <> ") does not match any of " <> show [base16Len, base32Len, base64Len]    where     size = T.length h-    hsize = hashSize @a+    hsize = C.hashDigestSize a     base16Len = hsize * 2     base32Len = ((hsize * 8 - 1) `div` 5) + 1;     base64Len = ((4 * hsize `div` 3) + 3) `div` 4 * 4;  --- | Hash an entire (strict) 'BS.ByteString' as a single call.------   For example:---   > let d = hash "Hello, sha-256!" :: Digest SHA256---   or---   > :set -XTypeApplications---   > let d = hash @SHA256 "Hello, sha-256!"-hash :: forall a.ValidAlgo a => BS.ByteString -> Digest a-hash bs =-  finalize $ update @a (initialize @a) bs---- | Hash an entire (lazy) 'BSL.ByteString' as a single call.------ Use is the same as for 'hash'.  This runs in constant space, but--- forces the entire bytestring.-hashLazy :: forall a.ValidAlgo a => BSL.ByteString -> Digest a-hashLazy bsl =-  finalize $ foldl' (update @a) (initialize @a) (BSL.toChunks bsl)-+mkStorePathHash :: forall a . C.HashAlgorithm a => BS.ByteString -> BS.ByteString+mkStorePathHash bs =+  truncateInNixWay 20 $ convert $ C.hash @BS.ByteString @a bs  -- | Take BaseEncoding type of the output -> take the Digeest as input -> encode Digest-encodeInBase :: BaseEncoding -> Digest a -> T.Text-encodeInBase Base16 = T.decodeUtf8 . Base16.encode . coerce-encodeInBase Base32 = Base32.encode . coerce-encodeInBase Base64 = T.decodeUtf8 . Base64.encode . coerce+encodeDigestWith :: BaseEncoding -> C.Digest a -> T.Text+encodeDigestWith b = encodeWith b . convert   -- | Take BaseEncoding type of the input -> take the input itself -> decodeBase into Digest-decodeBase :: BaseEncoding -> T.Text -> Either String (Digest a)-#if MIN_VERSION_base16_bytestring(1,0,0)-decodeBase Base16 = fmap Digest . Base16.decode . T.encodeUtf8-#else-decodeBase Base16 = lDecode  -- this tacit sugar simply makes GHC pleased with number of args+decodeDigestWith :: C.HashAlgorithm a => BaseEncoding -> T.Text -> Either String (C.Digest a)+decodeDigestWith b x =+  do+    bs <- decodeWith b x+    let+      toEither =+        maybeToRight+          ("Cryptonite was not able to convert '(ByteString -> Digest a)' for: '" <> show bs <>"'.")+    (toEither . C.digestFromByteString) bs  where-  lDecode t = case Base16.decode (T.encodeUtf8 t) of-    (x, "") -> Right $ Digest x-    _       -> Left $ "Unable to decode base16 string" <> T.unpack t-#endif-decodeBase Base32 = fmap Digest . Base32.decode-decodeBase Base64 = fmap Digest . Base64.decode . T.encodeUtf8----- | Uses "Crypto.Hash.MD5" from cryptohash-md5.-instance ValidAlgo 'MD5 where-  type AlgoCtx 'MD5 = MD5.Ctx-  initialize = MD5.init-  update = MD5.update-  finalize = Digest . MD5.finalize---- | Uses "Crypto.Hash.SHA1" from cryptohash-sha1.-instance ValidAlgo 'SHA1 where-  type AlgoCtx 'SHA1 = SHA1.Ctx-  initialize = SHA1.init-  update = SHA1.update-  finalize = Digest . SHA1.finalize---- | Uses "Crypto.Hash.SHA256" from cryptohash-sha256.-instance ValidAlgo 'SHA256 where-  type AlgoCtx 'SHA256 = SHA256.Ctx-  initialize = SHA256.init-  update = SHA256.update-  finalize = Digest . SHA256.finalize---- | Uses "Crypto.Hash.SHA512" from cryptohash-sha512.-instance ValidAlgo 'SHA512 where-  type AlgoCtx 'SHA512 = SHA512.Ctx-  initialize = SHA512.init-  update = SHA512.update-  finalize = Digest . SHA512.finalize---- | Reuses the underlying 'ValidAlgo' instance, but does a--- 'truncateDigest' at the end.-instance (ValidAlgo a, KnownNat n) => ValidAlgo ('Truncated n a) where-  type AlgoCtx ('Truncated n a) = AlgoCtx a-  initialize = initialize @a-  update = update @a-  finalize = truncateDigest @n . finalize @a---- | Bytewise truncation of a 'Digest'.------ When truncation length is greater than the length of the bytestring--- but less than twice the bytestring length, truncation splits the--- bytestring into a head part (truncation length) and tail part--- (leftover part), right-pads the leftovers with 0 to the truncation--- length, and combines the two strings bytewise with 'xor'.-truncateDigest-  :: forall n a.(KnownNat n) => Digest a -> Digest ('Truncated n a)-truncateDigest (Digest c) =-    Digest $ BS.pack $ fmap truncOutputByte [0.. n-1]-  where-    n = fromIntegral $ natVal (Proxy @n)--    truncOutputByte :: Int -> Word8-    truncOutputByte i = foldl' (aux i) 0 [0 .. BS.length c - 1]--    inputByte :: Int -> Word8-    inputByte j = BS.index c (fromIntegral j)--    aux :: Int -> Word8 -> Int -> Word8-    aux i x j = if j `mod` fromIntegral n == fromIntegral i-                then xor x (inputByte $ fromIntegral j)-                else x+  -- To not depend on @extra@+  maybeToRight :: b -> Maybe a -> Either b a+  maybeToRight _ (Just r) = pure r+  maybeToRight y Nothing  = Left y
src/System/Nix/Internal/Nar/Parser.hs view
@@ -7,7 +7,13 @@ {-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-} -module System.Nix.Internal.Nar.Parser where+module System.Nix.Internal.Nar.Parser+  ( runParser+  , parseNar+  , testParser+  , testParser'+  )+where  import qualified Algebra.Graph                   as Graph import qualified Algebra.Graph.ToGraph           as Graph
src/System/Nix/Internal/Nar/Streamer.hs view
@@ -3,7 +3,11 @@ {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE ScopedTypeVariables #-} -module System.Nix.Internal.Nar.Streamer where+module System.Nix.Internal.Nar.Streamer+  ( streamNarIO+  , IsExecutable(..)+  )+where  import           Control.Monad                    ( forM_                                                   , when
src/System/Nix/Internal/Signature.hs view
@@ -4,7 +4,11 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE CPP #-} -module System.Nix.Internal.Signature where+module System.Nix.Internal.Signature+  ( Signature+  , NarSignature(..)+  )+where   import           Data.ByteString                    ( ByteString )
src/System/Nix/Internal/StorePath.hs view
@@ -1,29 +1,40 @@ {-| Description : Representation of Nix store paths. -}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE TypeInType #-} -- Needed for GHC 8.4.4 for some reason--module System.Nix.Internal.StorePath where-import           System.Nix.Hash                ( HashAlgorithm-                                                  ( Truncated-                                                  , SHA256-                                                  )-                                                , Digest-                                                , BaseEncoding(..)-                                                , encodeInBase-                                                , decodeBase-                                                , SomeNamedDigest-                                                )-+{-# LANGUAGE DataKinds #-} +module System.Nix.Internal.StorePath+  ( -- * Basic store path types+    StorePath(..)+  , StorePathName(..)+  , StorePathSet+  , mkStorePathHashPart+  , StorePathHashPart(..)+  , ContentAddressableAddress(..)+  , NarHashMode(..)+  , -- * Manipulating 'StorePathName'+    makeStorePathName+  , validStorePathName+  , -- * Rendering out 'StorePath's+    storePathToFilePath+  , storePathToRawFilePath+  , storePathToText+  , storePathToNarInfo+  , -- * Parsing 'StorePath's+    parsePath+  , pathParser+  )+where+import           System.Nix.Internal.Hash+import           System.Nix.Internal.Base import qualified System.Nix.Internal.Base32    as Nix.Base32-                                                ( digits32 )  import           Data.ByteString                ( ByteString ) import qualified Data.ByteString.Char8         as Bytes.Char8@@ -39,6 +50,10 @@ import qualified System.FilePath               as FilePath import           Data.Hashable                  ( Hashable(..) ) import           Data.HashSet                   ( HashSet )+import           Data.Coerce                    ( coerce )+import           Crypto.Hash                    ( SHA256+                                                , Digest+                                                )  -- | A path in a Nix store. --@@ -52,7 +67,7 @@ data StorePath = StorePath   { -- | The 160-bit hash digest reflecting the "address" of the name.     -- Currently, this is a truncated SHA256 hash.-    storePathHash :: !(Digest StorePathHashAlgo)+    storePathHash :: !StorePathHashPart   , -- | The (typically human readable) name of the path. For packages     -- this is typically the package name and version (e.g.     -- hello-1.2.3).@@ -80,8 +95,12 @@   } deriving (Eq, Hashable, Ord)  -- | The hash algorithm used for store path hashes.-type StorePathHashAlgo = 'Truncated 20 'SHA256+newtype StorePathHashPart = StorePathHashPart ByteString+  deriving (Eq, Hashable, Ord, Show) +mkStorePathHashPart :: ByteString -> StorePathHashPart+mkStorePathHashPart = coerce . mkStorePathHash @SHA256+ -- | A set of 'StorePath's. type StorePathSet = HashSet StorePath @@ -98,7 +117,7 @@   = -- | The path is a plain file added via makeTextPath or     -- addTextToStore. It is addressed according to a sha256sum of the     -- file contents.-    Text !(Digest 'SHA256)+    Text !(Digest SHA256)   | -- | The path was added to the store via makeFixedOutputPath or     -- addToStore. It is addressed according to some hash algorithm     -- applied to the nar serialization via some 'NarHashMode'.@@ -118,7 +137,7 @@ makeStorePathName :: Text -> Either String StorePathName makeStorePathName n =   if validStorePathName n-    then Right $ StorePathName n+    then pure $ StorePathName n     else Left $ reasonInvalid n  reasonInvalid :: Text -> String@@ -154,7 +173,7 @@   root <> "/" <> hashPart <> "-" <> name  where   root     = Bytes.Char8.pack storePathRoot-  hashPart = Text.encodeUtf8 $ encodeInBase Base32 storePathHash+  hashPart = Text.encodeUtf8 $ encodeWith NixBase32 $ coerce storePathHash   name     = Text.encodeUtf8 $ unStorePathName storePathName  -- | Render a 'StorePath' as a 'FilePath'.@@ -169,7 +188,7 @@ -- can be used to query binary caches. storePathToNarInfo :: StorePath -> Bytes.Char8.ByteString storePathToNarInfo StorePath{..} =-  Text.encodeUtf8 $ encodeInBase Base32 storePathHash <> ".narinfo"+  Text.encodeUtf8 $ encodeWith NixBase32 (coerce storePathHash) <> ".narinfo"  -- | Parse `StorePath` from `Bytes.Char8.ByteString`, checking -- that store directory matches `expectedRoot`.@@ -177,8 +196,8 @@ parsePath expectedRoot x =   let     (rootDir, fname) = FilePath.splitFileName . Bytes.Char8.unpack $ x-    (digestPart, namePart) = Text.breakOn "-" $ Text.pack fname-    digest = decodeBase Base32 digestPart+    (storeBasedHashPart, namePart) = Text.breakOn "-" $ Text.pack fname+    storeHash = decodeWith NixBase32 storeBasedHashPart     name = makeStorePathName . Text.drop 1 $ namePart     --rootDir' = dropTrailingPathSeparator rootDir     -- cannot use ^^ as it drops multiple slashes /a/b/// -> /a/b@@ -188,7 +207,7 @@         then Right rootDir'         else Left $ "Root store dir mismatch, expected" <> expectedRoot <> "got" <> rootDir'   in-    StorePath <$> digest <*> name <*> storeDir+    StorePath <$> coerce storeHash <*> name <*> storeDir  pathParser :: FilePath -> Parser StorePath pathParser expectedRoot = do@@ -200,7 +219,7 @@       <?> "Expecting path separator"    digest <--    decodeBase Base32+    decodeWith NixBase32     <$> Parser.Text.Lazy.takeWhile1 (`elem` Nix.Base32.digits32)       <?> "Invalid Base32 part" @@ -219,4 +238,4 @@   either     fail     pure-    (StorePath <$> digest <*> name <*> pure expectedRoot)+    (StorePath <$> coerce digest <*> name <*> pure expectedRoot)
+ src/System/Nix/Internal/Truncation.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE DataKinds           #-}++module System.Nix.Internal.Truncation+  ( truncateInNixWay+  )+where++import qualified Data.ByteString        as Bytes+import           Data.Bits              (xor)+import           Data.List              (foldl')+import           Data.Word              (Word8)+import           Data.Bool                 (bool)++-- | Bytewise truncation of a 'Digest'.+--+-- When truncation length is greater than the length of the bytestring+-- but less than twice the bytestring length, truncation splits the+-- bytestring into a head part (truncation length) and tail part+-- (leftover part), right-pads the leftovers with 0 to the truncation+-- length, and combines the two strings bytewise with 'xor'.+truncateInNixWay+  :: Int -> Bytes.ByteString -> Bytes.ByteString+--  2021-06-07: NOTE: Renamed function, since truncation can be done in a lot of ways, there is no practice of truncting hashes this way, moreover:+-- 1. <https://crypto.stackexchange.com/questions/56337/strength-of-hash-obtained-by-xor-of-parts-of-sha3>+-- 2. <https://www.reddit.com/r/crypto/comments/6olqfm/ways_to_truncated_hash/>+truncateInNixWay n c =+    Bytes.pack $ fmap truncOutputByte [0 .. n-1]+  where++    truncOutputByte :: Int -> Word8+    truncOutputByte i = foldl' (aux i) 0 [0 .. Bytes.length c - 1]++    inputByte :: Int -> Word8+    inputByte j = Bytes.index c j++    aux :: Int -> Word8 -> Int -> Word8+    aux i x j =+      bool+        id+        (`xor` inputByte j)+        (j `mod` n == i)+        x
src/System/Nix/ReadonlyStore.hs view
@@ -16,35 +16,45 @@ import           System.Nix.Nar import           System.Nix.StorePath import           Control.Monad.State.Strict+import           Data.Coerce                    ( coerce )+import           Crypto.Hash                    ( Context+                                                , Digest+                                                , hash+                                                , hashlazy+                                                , hashInit+                                                , hashUpdate+                                                , hashFinalize+                                                , SHA256+                                                )   makeStorePath-  :: forall hashAlgo-   . (NamedAlgo hashAlgo)+  :: forall h+   . (NamedAlgo h)   => FilePath   -> ByteString-  -> Digest hashAlgo+  -> Digest h   -> StorePathName   -> StorePath-makeStorePath fp ty h nm = StorePath storeHash nm fp+makeStorePath fp ty h nm = StorePath (coerce storeHash) nm fp  where-  storeHash = hash s+  storeHash = mkStorePathHash @h s    s =     BS.intercalate ":" $       ty:fmap encodeUtf8-        [ algoName @hashAlgo-        , encodeInBase Base16 h+        [ algoName @h+        , encodeDigestWith Base16 h         , T.pack fp-        , unStorePathName nm+        , coerce nm         ]  makeTextPath-  :: FilePath -> StorePathName -> Digest 'SHA256 -> StorePathSet -> StorePath+  :: FilePath -> StorePathName -> Digest SHA256 -> StorePathSet -> StorePath makeTextPath fp nm h refs = makeStorePath fp ty h nm  where   ty =-    BS.intercalate ":" ("text" : sort (fmap storePathToRawFilePath (HS.toList refs)))+    BS.intercalate ":" $ "text" : sort (storePathToRawFilePath <$> HS.toList refs)  makeFixedOutputPath   :: forall hashAlgo@@ -60,11 +70,11 @@     else makeStorePath fp "output:out" h'  where   h' =-    hash @'SHA256+    hash @ByteString @SHA256       $  "fixed:out:"       <> encodeUtf8 (algoName @hashAlgo)       <> (if recursive then ":r:" else ":")-      <> encodeUtf8 (encodeInBase Base16 h)+      <> encodeUtf8 (encodeDigestWith Base16 h)       <> ":"  computeStorePathForText@@ -82,10 +92,10 @@   selectedHash <- if recursive then recursiveContentHash else flatContentHash   pure $ makeFixedOutputPath "/nix/store" recursive selectedHash name  where-  recursiveContentHash :: IO (Digest 'SHA256)-  recursiveContentHash = finalize <$> execStateT streamNarUpdate (initialize @'SHA256)-  streamNarUpdate :: StateT (AlgoCtx 'SHA256) IO ()-  streamNarUpdate = streamNarIO (modify . flip (update @'SHA256)) narEffectsIO pth+  recursiveContentHash :: IO (Digest SHA256)+  recursiveContentHash = hashFinalize <$> execStateT streamNarUpdate (hashInit @SHA256)+  streamNarUpdate :: StateT (Context SHA256) IO ()+  streamNarUpdate = streamNarIO (modify . flip (hashUpdate @ByteString @SHA256)) narEffectsIO pth -  flatContentHash :: IO (Digest 'SHA256)-  flatContentHash = hashLazy <$> narReadFile narEffectsIO pth+  flatContentHash :: IO (Digest SHA256)+  flatContentHash = hashlazy <$> narReadFile narEffectsIO pth
src/System/Nix/StorePath.hs view
@@ -4,14 +4,14 @@ module System.Nix.StorePath   ( -- * Basic store path types     StorePath(..)-  , StorePathName+  , StorePathName(..)   , StorePathSet-  , StorePathHashAlgo+  , mkStorePathHashPart+  , StorePathHashPart(..)   , ContentAddressableAddress(..)   , NarHashMode(..)   , -- * Manipulating 'StorePathName'     makeStorePathName-  , unStorePathName   , validStorePathName   , -- * Rendering out 'StorePath's     storePathToFilePath
tests/Arbitrary.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE DataKinds            #-} {-# OPTIONS_GHC -Wno-orphans      #-}@@ -10,10 +11,13 @@  import           Test.Tasty.QuickCheck -import           System.Nix.Hash-import           System.Nix.Internal.Hash-import           System.Nix.StorePath import           System.Nix.Internal.StorePath+import           Control.Applicative                ( liftA3 )+import           Data.Coerce                        ( coerce )+import           Crypto.Hash                        ( SHA256+                                                    , Digest+                                                    , hash+                                                    )  genSafeChar :: Gen Char genSafeChar = choose ('\1', '\127') -- ASCII without \NUL@@ -22,7 +26,7 @@ nonEmptyString = listOf1 genSafeChar  dir :: Gen String-dir = ('/':) <$> (listOf1 $ elements $ '/':['a'..'z'])+dir = ('/':) <$> listOf1 (elements $ '/':['a'..'z'])  instance Arbitrary StorePathName where   arbitrary = StorePathName . T.pack <$> ((:) <$> s1 <*> listOf sn)@@ -31,10 +35,10 @@     s1       = elements $ alphanum <> "+-_?="     sn       = elements $ alphanum <> "+-._?=" -instance Arbitrary (Digest StorePathHashAlgo) where-  arbitrary = hash . BSC.pack <$> arbitrary+instance Arbitrary StorePathHashPart where+  arbitrary = mkStorePathHashPart . BSC.pack <$> arbitrary -instance Arbitrary (Digest 'SHA256) where+instance Arbitrary (Digest SHA256) where   arbitrary = hash . BSC.pack <$> arbitrary  newtype NixLike = NixLike {getNixLike :: StorePath}@@ -42,15 +46,19 @@  instance Arbitrary NixLike where   arbitrary =-    NixLike-      <$> (StorePath-         <$> arbitraryTruncatedDigest-         <*> arbitrary-         <*> pure "/nix/store"-        )+    NixLike <$>+      (liftA3 StorePath+        arbitraryTruncatedDigest+        arbitrary+        (pure "/nix/store")+      )    where     -- 160-bit hash, 20 bytes, 32 chars in base32-    arbitraryTruncatedDigest = Digest . BSC.pack <$> replicateM 20 genSafeChar+    arbitraryTruncatedDigest = coerce . BSC.pack <$> replicateM 20 genSafeChar  instance Arbitrary StorePath where-  arbitrary = StorePath <$> arbitrary <*> arbitrary <*> dir+  arbitrary =+    liftA3 StorePath+      arbitrary+      arbitrary+      dir
tests/Derivation.hs view
@@ -20,11 +20,11 @@   contents <- Data.Text.IO.readFile source   either     fail-    (\ drv ->-      Data.Text.IO.writeFile dest-        . Data.Text.Lazy.toStrict-        . Data.Text.Lazy.Builder.toLazyText-        $ buildDerivation drv+    -- It seems to be derivation.+    (Data.Text.IO.writeFile dest+      . Data.Text.Lazy.toStrict+      . Data.Text.Lazy.Builder.toLazyText+      . buildDerivation     )     (Data.Attoparsec.Text.parseOnly       (parseDerivation "/nix/store")
tests/Hash.hs view
@@ -6,13 +6,13 @@  module Hash where -import           Control.Monad               (forM_)+import           Control.Monad               ( forM_ )+import           Data.ByteString             ( ByteString ) import qualified Data.ByteString.Char8       as BSC import qualified Data.ByteString.Base16      as B16 import qualified System.Nix.Base32           as B32 import qualified Data.ByteString.Base64.Lazy as B64 import qualified Data.ByteString.Lazy        as BSL-import           Data.Text                   (Text)  import           Test.Hspec import           Test.Tasty.QuickCheck@@ -20,6 +20,13 @@ import           System.Nix.Hash import           System.Nix.StorePath import           Arbitrary+import           System.Nix.Internal.Base+import           Data.Coerce                ( coerce )+import           Crypto.Hash                ( MD5+                                            , SHA1+                                            , SHA256+                                            , hash+                                            )  spec_hash :: Spec spec_hash = do@@ -27,13 +34,13 @@   describe "hashing parity with nix-store" $ do      it "produces (base32 . sha256) of \"nix-output:foo\" the same as Nix does at the moment for placeholder \"foo\"" $-      shouldBe (encodeInBase Base32 (hash @'SHA256 "nix-output:foo"))+      shouldBe (encodeDigestWith NixBase32 (hash @ByteString @SHA256 "nix-output:foo"))                "1x0ymrsy7yr7i9wdsqy9khmzc1yy7nvxw6rdp72yzn50285s67j5"     it "produces (base16 . md5) of \"Hello World\" the same as the thesis" $-      shouldBe (encodeInBase Base16 (hash @'MD5 "Hello World"))+      shouldBe (encodeDigestWith Base16 (hash @ByteString @MD5 "Hello World"))                "b10a8db164e0754105b7a99be72e3fe5"     it "produces (base32 . sha1) of \"Hello World\" the same as the thesis" $-      shouldBe (encodeInBase Base32 (hash @'SHA1 "Hello World"))+      shouldBe (encodeDigestWith NixBase32 (hash @ByteString @SHA1 "Hello World"))                "s23c9fs0v32pf6bhmcph5rbqsyl5ak8a"      -- The example in question:@@ -42,21 +49,17 @@       let exampleStr =             "source:sha256:2bfef67de873c54551d884fdab3055d84d573e654efa79db3"             <> "c0d7b98883f9ee3:/nix/store:myfile"-      shouldBe (encodeInBase32 @StorePathHashAlgo (hash exampleStr))+      shouldBe (encodeWith NixBase32 $ coerce $ mkStorePathHashPart exampleStr)         "xv2iccirbrvklck36f1g7vldn5v58vck"-   where-    encodeInBase32 :: Digest a -> Text-    encodeInBase32 = encodeInBase Base32  -- | Test that Nix-like base32 encoding roundtrips prop_nixBase32Roundtrip :: Property prop_nixBase32Roundtrip = forAllShrink nonEmptyString genericShrink $-  \x -> Right (BSC.pack x) === (B32.decode . B32.encode . BSC.pack $ x)+  \x -> pure (BSC.pack x) === (B32.decode . B32.encode . BSC.pack $ x)  -- | API variants-prop_nixBase16Roundtrip :: Digest StorePathHashAlgo -> Property-prop_nixBase16Roundtrip =-  \(x :: Digest StorePathHashAlgo) -> Right x === (decodeBase Base16 . encodeInBase Base16 $ x)+prop_nixBase16Roundtrip :: StorePathHashPart -> Property+prop_nixBase16Roundtrip x = pure (coerce x) === decodeWith Base16 (encodeWith Base16 $ coerce x)  -- | Hash encoding conversion ground-truth. -- Similiar to nix/tests/hash.sh
tests/NarFormat.hs view
@@ -26,9 +26,11 @@ import           Data.Maybe                       (fromMaybe) import qualified Data.Text                        as T import qualified Data.Text.Encoding               as E-import           System.Directory                 (doesDirectoryExist, doesPathExist,-                                                   removeDirectoryRecursive,-                                                   removeFile)+import           System.Directory                 ( doesDirectoryExist+                                                  , doesPathExist+                                                  , removeDirectoryRecursive+                                                  , removeFile+                                                  ) import qualified System.Directory                 as Directory import           System.Environment               (getEnv) import           System.FilePath                  ((<.>), (</>))