mirror of
https://github.com/haskell-nix/hnix-store.git
synced 2025-01-07 11:51:26 +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.Internal.Hash
|
||||||
, System.Nix.Nar
|
, System.Nix.Nar
|
||||||
, System.Nix.Path
|
, System.Nix.Path
|
||||||
|
, System.Nix.ReadonlyStore
|
||||||
, System.Nix.Store
|
, System.Nix.Store
|
||||||
, System.Nix.Util
|
, System.Nix.Util
|
||||||
build-depends: base >=4.10 && <4.12
|
build-depends: base >=4.10 && <4.12
|
||||||
|
, base16-bytestring
|
||||||
, bytestring
|
, bytestring
|
||||||
, binary
|
, binary
|
||||||
, bytestring
|
, bytestring
|
||||||
@ -61,7 +63,7 @@ test-suite format-tests
|
|||||||
NarFormat
|
NarFormat
|
||||||
Hash
|
Hash
|
||||||
hs-source-dirs:
|
hs-source-dirs:
|
||||||
tests
|
tests
|
||||||
build-depends:
|
build-depends:
|
||||||
hnix-store-core
|
hnix-store-core
|
||||||
, base
|
, base
|
||||||
|
@ -12,25 +12,29 @@ Maintainer : Greg Hale <imalsogreg@gmail.com>
|
|||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
{-# LANGUAGE TypeInType #-}
|
{-# LANGUAGE TypeInType #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
module System.Nix.Internal.Hash where
|
module System.Nix.Internal.Hash where
|
||||||
|
|
||||||
import qualified Crypto.Hash.MD5 as MD5
|
import qualified Crypto.Hash.MD5 as MD5
|
||||||
import qualified Crypto.Hash.SHA1 as SHA1
|
import qualified Crypto.Hash.SHA1 as SHA1
|
||||||
import qualified Crypto.Hash.SHA256 as SHA256
|
import qualified Crypto.Hash.SHA256 as SHA256
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.ByteString.Char8 as BSC
|
import qualified Data.ByteString.Base16 as Base16
|
||||||
import Data.Bits (xor)
|
import qualified Data.ByteString.Char8 as BSC
|
||||||
import qualified Data.ByteString as BS
|
import Data.Bits (xor)
|
||||||
import qualified Data.ByteString.Lazy as BSL
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.Hashable as DataHashable
|
import qualified Data.ByteString.Lazy as BSL
|
||||||
import Data.Kind (Type)
|
import qualified Data.Hashable as DataHashable
|
||||||
import Data.List (foldl')
|
import Data.Kind (Type)
|
||||||
import Data.Proxy (Proxy(Proxy))
|
import Data.List (foldl')
|
||||||
import qualified Data.Text as T
|
import Data.Monoid
|
||||||
import qualified Data.Text.Encoding as T
|
import Data.Proxy (Proxy(Proxy))
|
||||||
import qualified Data.Vector as V
|
import Data.Text (Text)
|
||||||
import Data.Word (Word8)
|
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
|
import GHC.TypeLits
|
||||||
|
|
||||||
-- | A tag for different hashing algorithms
|
-- | A tag for different hashing algorithms
|
||||||
@ -45,6 +49,18 @@ data HashAlgorithm' n
|
|||||||
| Truncated n (HashAlgorithm' n)
|
| Truncated n (HashAlgorithm' n)
|
||||||
deriving (Eq, Show)
|
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
|
type HashAlgorithm = HashAlgorithm' Nat
|
||||||
|
|
||||||
-- | Types with kind @HashAlgorithm@ may be a @HasDigest@ instance
|
-- | Types with kind @HashAlgorithm@ may be a @HasDigest@ instance
|
||||||
@ -80,8 +96,11 @@ hashLazy :: forall a.HasDigest a => BSL.ByteString -> Digest a
|
|||||||
hashLazy bsl =
|
hashLazy bsl =
|
||||||
finalize $ foldl' (update @a) (initialize @a) (BSL.toChunks 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.
|
-- | Convert any Digest to a base32-encoded string.
|
||||||
-- This is not used in producing store path hashes
|
-- 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>
|
Maintainer : Shea Levy <shea@shealevy.com>
|
||||||
-}
|
-}
|
||||||
{-# LANGUAGE DataKinds #-}
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
module System.Nix.Path
|
module System.Nix.Path
|
||||||
( FilePathPart(..)
|
( FilePathPart(..)
|
||||||
, PathHashAlgo
|
, PathHashAlgo
|
||||||
, Path(..)
|
, Path(..)
|
||||||
|
, pathToText
|
||||||
, PathSet
|
, PathSet
|
||||||
, SubstitutablePathInfo(..)
|
, SubstitutablePathInfo(..)
|
||||||
, ValidPathInfo(..)
|
, ValidPathInfo(..)
|
||||||
@ -19,12 +21,14 @@ module System.Nix.Path
|
|||||||
|
|
||||||
import System.Nix.Hash (Digest(..),
|
import System.Nix.Hash (Digest(..),
|
||||||
HashAlgorithm'(Truncated, SHA256))
|
HashAlgorithm'(Truncated, SHA256))
|
||||||
|
import System.Nix.Internal.Hash
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import qualified Data.ByteString.Char8 as BSC
|
import qualified Data.ByteString.Char8 as BSC
|
||||||
import Data.Hashable (Hashable (..), hashPtrWithSalt)
|
import Data.Hashable (Hashable (..), hashPtrWithSalt)
|
||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
import Data.HashSet (HashSet)
|
import Data.HashSet (HashSet)
|
||||||
import Data.Map.Strict (Map)
|
import Data.Map.Strict (Map)
|
||||||
|
import Data.Monoid
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import System.IO.Unsafe (unsafeDupablePerformIO)
|
import System.IO.Unsafe (unsafeDupablePerformIO)
|
||||||
@ -46,7 +50,7 @@ newtype PathName = PathName
|
|||||||
-- | A regular expression for matching a valid 'PathName'
|
-- | A regular expression for matching a valid 'PathName'
|
||||||
nameRegex :: Regex
|
nameRegex :: Regex
|
||||||
nameRegex =
|
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.
|
-- | Construct a 'PathName', assuming the provided contents are valid.
|
||||||
pathName :: Text -> Maybe PathName
|
pathName :: Text -> Maybe PathName
|
||||||
@ -58,6 +62,9 @@ pathName n = case matchTest nameRegex n of
|
|||||||
data Path = Path !(Digest PathHashAlgo) !PathName
|
data Path = Path !(Digest PathHashAlgo) !PathName
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
pathToText :: Text -> Path -> Text
|
||||||
|
pathToText storeDir (Path h nm) = storeDir <> "/" <> printAsBase32 h <> "-" <> pathNameContents nm
|
||||||
|
|
||||||
type PathSet = HashSet Path
|
type PathSet = HashSet Path
|
||||||
|
|
||||||
-- | Information about substitutes for a '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