mirror of
https://github.com/haskell-nix/hnix-store.git
synced 2025-01-05 19:00:24 +03:00
Merge pull request #32 from haskell-nix/readonly-store-hash
Implement readonly store path hashing
This commit is contained in:
commit
8965dc85bf
@ -24,9 +24,11 @@ library
|
||||
, System.Nix.Internal.Hash
|
||||
, System.Nix.Nar
|
||||
, System.Nix.Path
|
||||
, System.Nix.ReadonlyStore
|
||||
, System.Nix.Store
|
||||
, System.Nix.Util
|
||||
build-depends: base >=4.10 && <4.12
|
||||
, base16-bytestring
|
||||
, bytestring
|
||||
, binary
|
||||
, bytestring
|
||||
@ -61,7 +63,7 @@ test-suite format-tests
|
||||
NarFormat
|
||||
Hash
|
||||
hs-source-dirs:
|
||||
tests
|
||||
tests
|
||||
build-depends:
|
||||
hnix-store-core
|
||||
, base
|
||||
|
@ -12,25 +12,29 @@ Maintainer : Greg Hale <imalsogreg@gmail.com>
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# LANGUAGE TypeInType #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module System.Nix.Internal.Hash where
|
||||
|
||||
import qualified Crypto.Hash.MD5 as MD5
|
||||
import qualified Crypto.Hash.SHA1 as SHA1
|
||||
import qualified Crypto.Hash.SHA256 as SHA256
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Char8 as BSC
|
||||
import Data.Bits (xor)
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Lazy as BSL
|
||||
import qualified Data.Hashable as DataHashable
|
||||
import Data.Kind (Type)
|
||||
import Data.List (foldl')
|
||||
import Data.Proxy (Proxy(Proxy))
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as T
|
||||
import qualified Data.Vector as V
|
||||
import Data.Word (Word8)
|
||||
import qualified Crypto.Hash.MD5 as MD5
|
||||
import qualified Crypto.Hash.SHA1 as SHA1
|
||||
import qualified Crypto.Hash.SHA256 as SHA256
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Base16 as Base16
|
||||
import qualified Data.ByteString.Char8 as BSC
|
||||
import Data.Bits (xor)
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Lazy as BSL
|
||||
import qualified Data.Hashable as DataHashable
|
||||
import Data.Kind (Type)
|
||||
import Data.List (foldl')
|
||||
import Data.Monoid
|
||||
import Data.Proxy (Proxy(Proxy))
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as T
|
||||
import qualified Data.Vector as V
|
||||
import Data.Word (Word8)
|
||||
import GHC.TypeLits
|
||||
|
||||
-- | A tag for different hashing algorithms
|
||||
@ -45,6 +49,18 @@ data HashAlgorithm' n
|
||||
| Truncated n (HashAlgorithm' n)
|
||||
deriving (Eq, Show)
|
||||
|
||||
class HashAlgoText a where
|
||||
algoString :: Proxy a -> Text
|
||||
|
||||
instance HashAlgoText 'MD5 where
|
||||
algoString (Proxy :: Proxy 'MD5) = "md5"
|
||||
|
||||
instance HashAlgoText 'SHA1 where
|
||||
algoString (Proxy :: Proxy 'SHA1) = "sha1"
|
||||
|
||||
instance HashAlgoText 'SHA256 where
|
||||
algoString (Proxy :: Proxy 'SHA256) = "sha256"
|
||||
|
||||
type HashAlgorithm = HashAlgorithm' Nat
|
||||
|
||||
-- | Types with kind @HashAlgorithm@ may be a @HasDigest@ instance
|
||||
@ -80,8 +96,11 @@ hashLazy :: forall a.HasDigest a => BSL.ByteString -> Digest a
|
||||
hashLazy bsl =
|
||||
finalize $ foldl' (update @a) (initialize @a) (BSL.toChunks bsl)
|
||||
|
||||
digestText32 :: forall a. HashAlgoText a => Digest a -> T.Text
|
||||
digestText32 d = algoString (Proxy :: Proxy a) <> ":" <> printAsBase32 d
|
||||
|
||||
|
||||
digestText16 :: forall a. HashAlgoText a => Digest a -> T.Text
|
||||
digestText16 (Digest bs) = algoString (Proxy :: Proxy a) <> ":" <> T.decodeUtf8 (Base16.encode bs)
|
||||
|
||||
-- | Convert any Digest to a base32-encoded string.
|
||||
-- This is not used in producing store path hashes
|
||||
|
@ -3,11 +3,13 @@ Description : Types and effects for interacting with the Nix store.
|
||||
Maintainer : Shea Levy <shea@shealevy.com>
|
||||
-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
module System.Nix.Path
|
||||
( FilePathPart(..)
|
||||
, PathHashAlgo
|
||||
, Path(..)
|
||||
, pathToText
|
||||
, PathSet
|
||||
, SubstitutablePathInfo(..)
|
||||
, ValidPathInfo(..)
|
||||
@ -19,12 +21,14 @@ module System.Nix.Path
|
||||
|
||||
import System.Nix.Hash (Digest(..),
|
||||
HashAlgorithm'(Truncated, SHA256))
|
||||
import System.Nix.Internal.Hash
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.ByteString.Char8 as BSC
|
||||
import Data.Hashable (Hashable (..), hashPtrWithSalt)
|
||||
import Data.HashMap.Strict (HashMap)
|
||||
import Data.HashSet (HashSet)
|
||||
import Data.Map.Strict (Map)
|
||||
import Data.Monoid
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import System.IO.Unsafe (unsafeDupablePerformIO)
|
||||
@ -46,7 +50,7 @@ newtype PathName = PathName
|
||||
-- | A regular expression for matching a valid 'PathName'
|
||||
nameRegex :: Regex
|
||||
nameRegex =
|
||||
makeRegex "[a-zA-Z0-9\\+\\-\\_\\?\\=][a-zA-Z0-9\\+\\-\\.\\_\\?\\=]*"
|
||||
makeRegex ("[a-zA-Z0-9\\+\\-\\_\\?\\=][a-zA-Z0-9\\+\\-\\.\\_\\?\\=]*" :: String)
|
||||
|
||||
-- | Construct a 'PathName', assuming the provided contents are valid.
|
||||
pathName :: Text -> Maybe PathName
|
||||
@ -58,6 +62,9 @@ pathName n = case matchTest nameRegex n of
|
||||
data Path = Path !(Digest PathHashAlgo) !PathName
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
pathToText :: Text -> Path -> Text
|
||||
pathToText storeDir (Path h nm) = storeDir <> "/" <> printAsBase32 h <> "-" <> pathNameContents nm
|
||||
|
||||
type PathSet = HashSet Path
|
||||
|
||||
-- | Information about substitutes for a 'Path'.
|
||||
|
33
hnix-store-core/src/System/Nix/ReadonlyStore.hs
Normal file
33
hnix-store-core/src/System/Nix/ReadonlyStore.hs
Normal file
@ -0,0 +1,33 @@
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
|
||||
module System.Nix.ReadonlyStore where
|
||||
|
||||
import Data.ByteString (ByteString)
|
||||
import Data.ByteString.Base16 as Base16
|
||||
import qualified Data.HashSet as HS
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import Data.Text.Encoding
|
||||
import System.Nix.Internal.Hash
|
||||
import System.Nix.Path
|
||||
|
||||
makeStorePath :: Text -> Text -> Digest 'SHA256 -> Text -> Path
|
||||
makeStorePath storeDir ty h nm = Path storeHash (PathName nm)
|
||||
where
|
||||
s = T.intercalate ":"
|
||||
[ ty
|
||||
, digestText16 h
|
||||
, storeDir
|
||||
, nm
|
||||
]
|
||||
storeHash = truncateDigest $ hash $ encodeUtf8 s
|
||||
|
||||
makeTextPath :: Text -> Text -> Digest 'SHA256 -> PathSet -> Path
|
||||
makeTextPath storeDir nm h refs = makeStorePath storeDir ty h nm
|
||||
where
|
||||
ty = T.intercalate ":" ("text" : map (pathToText storeDir) (HS.toList refs))
|
||||
|
||||
computeStorePathForText :: Text -> Text -> ByteString -> PathSet -> Path
|
||||
computeStorePathForText storeDir nm s refs = makeTextPath storeDir nm (hash s) refs
|
Loading…
Reference in New Issue
Block a user