packages feed

hnix-store-core 0.1.0.0 → 0.2.0.0

raw patch · 18 files changed

+377/−363 lines, 18 filesdep +regex-tdfadep +saltinedep +timedep −regex-tdfa-textnew-uploader

Dependencies added: regex-tdfa, saltine, time

Dependencies removed: regex-tdfa-text

Files

hnix-store-core.cabal view
@@ -1,5 +1,5 @@ name:                hnix-store-core-version:             0.1.0.0+version:             0.2.0.0 synopsis:            Core effects for interacting with the Nix store. description:         This package contains types and functions needed to describe@@ -18,15 +18,15 @@  library   exposed-modules:     System.Nix.Base32-                     , System.Nix.Build-                     , System.Nix.Derivation-                     , System.Nix.GC                      , System.Nix.Hash                      , System.Nix.Internal.Hash+                     , System.Nix.Internal.Signature+                     , System.Nix.Internal.StorePath                      , System.Nix.Nar-                     , System.Nix.Path                      , System.Nix.ReadonlyStore-                     , System.Nix.Store+                     , System.Nix.Signature+                     , System.Nix.StorePath+                     , System.Nix.StorePathMetadata                      , System.Nix.Util   build-depends:       base >=4.10 && <5                      , base16-bytestring@@ -42,7 +42,9 @@                      , hashable                      , mtl                      , regex-base-                     , regex-tdfa-text+                     , regex-tdfa >= 1.3.1.0+                     , saltine+                     , time                      , text                      , unix                      , unordered-containers
src/System/Nix/Base32.hs view
@@ -9,23 +9,31 @@  -- | Encode a 'BS.ByteString' in Nix's base32 encoding encode :: BS.ByteString -> T.Text-encode c = T.pack $ concatMap char32 [nChar - 1, nChar - 2 .. 0]+encode c = T.pack $ map char32 [nChar - 1, nChar - 2 .. 0]   where     digits32 = V.fromList "0123456789abcdfghijklmnpqrsvwxyz"-    -- The base32 encoding is 8/5's as long as the base256 digest.  This `+ 1`-    -- `- 1` business is a bit odd, but has always been used in C++ since the-    -- base32 truncation was added in was first added in-    -- d58a11e019813902b6c4547ca61a127938b2cc20.+    -- Each base32 character gives us 5 bits of information, while+    -- each byte gives is 8. Because 'div' rounds down, we need to add+    -- one extra character to the result, and because of that extra 1+    -- we need to subtract one from the number of bits in the+    -- bytestring to cover for the case where the number of bits is+    -- already a factor of 5. Thus, the + 1 outside of the 'div' and+    -- the - 1 inside of it.     nChar = fromIntegral $ ((BS.length c * 8 - 1) `div` 5) + 1 -    char32 :: Integer -> [Char]-    char32 i = [digits32 V.! digitInd]+    byte = BS.index c . fromIntegral++    -- May need to switch to a more efficient calculation at some+    -- point.+    bAsInteger :: Integer+    bAsInteger = sum [fromIntegral (byte j) * (256 ^ j)+                     | j <- [0 .. BS.length c - 1]+                     ]++    char32 :: Integer -> Char+    char32 i = digits32 V.! digitInd       where-        byte j   = BS.index c (fromIntegral j)-        fromIntegral' :: Num b => Integer -> b-        fromIntegral' = fromIntegral-        digitInd = fromIntegral' $-                   sum [fromIntegral (byte j) * (256^j)-                       | j <- [0 .. BS.length c - 1]]+        digitInd = fromIntegral $+                   bAsInteger                    `div` (32^i)                    `mod` 32
− src/System/Nix/Build.hs
@@ -1,50 +0,0 @@-{-# LANGUAGE RecordWildCards #-}-{-|-Description : Build related types-Maintainer  : srk <srk@48.io>-|-}-module System.Nix.Build (-    BuildMode(..)-  , BuildStatus(..)-  , BuildResult(..)-  , buildSuccess-  ) where--import           Data.Text                 (Text)-import           Data.HashSet              (HashSet)-import           System.Nix.Path           (Path)--data BuildMode = Normal | Repair | Check-  deriving (Eq, Ord, Enum, Show)--data BuildStatus =-    Built-  | Substituted-  | AlreadyValid-  | PermanentFailure-  | InputRejected-  | OutputRejected-  | TransientFailure -- possibly transient-  | CachedFailure    -- no longer used-  | TimedOut-  | MiscFailure-  | DependencyFailed-  | LogLimitExceeded-  | NotDeterministic-  deriving (Eq, Ord, Enum, Show)----- | Result of the build-data BuildResult = BuildResult-  { -- | build status, MiscFailure should be default-    status             :: !BuildStatus-  , -- | possible build error message-    error              :: !(Maybe Text)-  , -- | How many times this build was performed-    timesBuilt         :: !Integer-  , -- | If timesBuilt > 1, whether some builds did not produce the same result-    isNonDeterministic :: !Bool-    -- XXX: | startTime stopTime time_t-  } deriving (Eq, Ord, Show)--buildSuccess BuildResult{..} = status == Built || status == Substituted || status == AlreadyValid
− src/System/Nix/Derivation.hs
@@ -1,30 +0,0 @@-{-|-Description : Derivation types-Maintainer  : srk <srk@48.io>-|-}--module System.Nix.Derivation where---import Data.Text (Text)-import Data.HashMap.Strict (HashMap)-import Data.HashSet (HashSet)-import System.Nix.Path--type OutputName = Text--newtype DerivationInputs = DerivationInputs-  { _unDerivationInputs :: HashMap Path (HashSet OutputName)-  } deriving (Eq, Ord, Show)--data Derivation = Derivation-  { _derivationInputs    :: DerivationInputs-  , _derivationOutputs   :: !(HashMap OutputName Path)-    -- | Inputs that are sources-  , _derivationInputSrcs :: !PathSet-  , _derivationPlatform  :: !Text-    -- | Path to builder-  , _derivationBuilder   :: !Path-  , _derivationArgs      :: ![Text]-  , _derivationEnv       :: ![HashMap Text Text]-  } deriving (Eq, Ord, Show)
− src/System/Nix/GC.hs
@@ -1,47 +0,0 @@-{-|-Description : Garbage collection actions / options-Maintainer  : srk <srk@48.io>-|-}-module System.Nix.GC (-    Action(..)-  , Options(..)-  , Result(..)-  ) where--import           System.Nix.Path           (PathSet)--{- Garbage collector operation:-     - ReturnLive: return the set of paths reachable from-       (i.e. in the closure of) the roots.-     - ReturnDead: return the set of paths not reachable from-       the roots.-     - DeleteDead: actually delete the latter set.-     - DeleteSpecific: delete the paths listed in-        `pathsToDelete', insofar as they are not reachable.--}--data Action = ReturnLive | ReturnDead | DeleteDead | DeleteSpecific-  deriving (Eq, Ord, Enum, Show)---- | Garbage collector operation options-data Options = Options-  { -- | operation-    operation      :: !Action-    -- | If `ignoreLiveness' is set, then reachability from the roots is-    -- ignored (dangerous!).  However, the paths must still be-    -- unreferenced *within* the store (i.e., there can be no other-    -- store paths that depend on them).-  , ignoreLiveness :: !Bool-    -- | For DeleteSpecific, the paths to delete-  , pathsToDelete  :: !PathSet-  , -- | Stop after at least `maxFreed` bytes have been freed-    maxFreed       :: !Integer-  } deriving (Eq, Ord, Show)--data Result = Result- { -- | Depending on the action, the GC roots, or the paths that would be or have been deleted-   paths      :: !PathSet- , -- |  For ReturnDead, DeleteDead and DeleteSpecific, the number of bytes that would be or was freed-   bytesFreed :: !Integer- } deriving (Eq, Ord, Show)-
src/System/Nix/Hash.hs view
@@ -7,6 +7,7 @@   , HNix.HashAlgorithm(..)   , HNix.ValidAlgo(..)   , HNix.NamedAlgo(..)+  , HNix.SomeNamedDigest(..)   , HNix.hash   , HNix.hashLazy 
src/System/Nix/Internal/Hash.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE TypeApplications    #-} {-# LANGUAGE DataKinds           #-} {-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ExistentialQuantification #-}  module System.Nix.Internal.Hash where @@ -71,6 +72,9 @@  instance NamedAlgo 'SHA256 where   algoName = "sha256"++-- | A digest whose 'NamedAlgo' is not known at compile time.+data SomeNamedDigest = forall a . NamedAlgo a => SomeDigest (Digest a)  -- | Hash an entire (strict) 'BS.ByteString' as a single call. --
+ src/System/Nix/Internal/Signature.hs view
@@ -0,0 +1,29 @@+{-|+Description : Nix-relevant interfaces to NaCl signatures.+-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module System.Nix.Internal.Signature where++import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import Data.Coerce (coerce)+import Crypto.Saltine.Core.Sign (PublicKey)+import Crypto.Saltine.Class (IsEncoding(..))+import qualified Crypto.Saltine.Internal.ByteSizes as NaClSizes++-- | A NaCl signature.+newtype Signature = Signature ByteString deriving (Eq, Ord)++instance IsEncoding Signature where+  decode s+    | BS.length s == NaClSizes.sign = Just (Signature s)+    | otherwise = Nothing+  encode = coerce++-- | A detached NaCl signature attesting to a nix archive's validity.+data NarSignature = NarSignature+  { -- | The public key used to sign the archive.+    publicKey :: PublicKey+  , -- | The archive's signature.+    sig :: Signature+  } deriving (Eq, Ord)
+ src/System/Nix/Internal/StorePath.hs view
@@ -0,0 +1,201 @@+{-|+Description : Representation of Nix store paths.+-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# 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+  , encodeBase32+  , SomeNamedDigest+  )+import Text.Regex.Base.RegexLike (makeRegex, matchTest)+import Text.Regex.TDFA.Text (Regex)+import Data.Text (Text)+import Data.Text.Encoding (encodeUtf8)+import GHC.TypeLits (Symbol, KnownSymbol, symbolVal)+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BC+import Data.Hashable (Hashable(..))+import Data.HashSet (HashSet)+import Data.Proxy (Proxy(..))++-- | A path in a Nix store.+--+-- From the Nix thesis: A store path is the full path of a store+-- object. It has the following anatomy: storeDir/hashPart-name.+--+-- @storeDir@: The root of the Nix store (e.g. \/nix\/store).+--+-- See the 'StoreDir' haddocks for details on why we represent this at+-- the type level.+data StorePath (storeDir :: StoreDir) = StorePath+  { -- | The 160-bit hash digest reflecting the "address" of the name.+    -- Currently, this is a truncated SHA256 hash.+    storePathHash :: !(Digest StorePathHashAlgo)+  , -- | The (typically human readable) name of the path. For packages+    -- this is typically the package name and version (e.g.+    -- hello-1.2.3).+    storePathName :: !StorePathName+  } deriving (Eq, Ord)++instance Hashable (StorePath storeDir) where+  hashWithSalt s (StorePath {..}) =+    s `hashWithSalt` storePathHash `hashWithSalt` storePathName++-- | The name portion of a Nix path.+--+-- 'unStorePathName' must only contain a-zA-Z0-9+._?=-, can't start+-- with a -, and must have at least one character (i.e. it must match+-- 'storePathNameRegex').+newtype StorePathName = StorePathName+  { -- | Extract the contents of the name.+    unStorePathName :: Text+  } deriving (Eq, Hashable, Ord)++-- | The hash algorithm used for store path hashes.+type StorePathHashAlgo = 'Truncated 20 'SHA256++-- | A set of 'StorePath's.+type StorePathSet storeDir = HashSet (StorePath storeDir)++-- | An address for a content-addressable store path, i.e. one whose+-- store path hash is purely a function of its contents (as opposed to+-- paths that are derivation outputs, whose hashes are a function of+-- the contents of the derivation file instead).+--+-- For backwards-compatibility reasons, the same information is+-- encodable in multiple ways, depending on the method used to add the+-- path to the store. These unfortunately result in separate store+-- paths.+data ContentAddressableAddress+  = -- | 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)+  | -- | 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'.+    Fixed !NarHashMode !SomeNamedDigest++-- | Schemes for hashing a nix archive.+--+-- For backwards-compatibility reasons, there are two different modes+-- here, even though 'Recursive' should be able to cover both.+data NarHashMode+  = -- | Require the nar to represent a non-executable regular file.+    RegularFile+  | -- | Hash an arbitrary nar, including a non-executable regular+    -- file if so desired.+    Recursive++-- | A type-level representation of the root directory of a Nix store.+--+-- The extra complexity of type indices requires justification.+-- Fundamentally, this boils down to the fact that there is little+-- meaningful sense in which 'StorePath's rooted at different+-- directories are of the same type, i.e. there are few if any+-- non-trivial non-contrived functions or data types that could+-- equally well accept 'StorePath's from different stores. In current+-- practice, any real application dealing with Nix stores (including,+-- in particular, the Nix expression language) only operates over one+-- store root and only cares about 'StorePath's belonging to that+-- root. One could imagine a use case that cares about multiple store+-- roots at once (e.g. the normal \/nix\/store along with some private+-- store at \/root\/nix\/store to contain secrets), but in that case+-- distinguishing 'StorePath's that belong to one store or the other+-- is even /more/ critical: Most operations will only be correct over+-- one of the stores or another, and it would be an error to mix and+-- match (e.g. a 'StorePath' in one store could not legitimately refer+-- to one in another).+--+-- As of @5886bc5996537fbf00d1fcfbb29595b8ccc9743e@, the C++ Nix+-- codebase contains 30 separate places where we assert that a given+-- store dir is, in fact, in the store we care about; those run-time+-- assertions could be completely removed if we had stronger types+-- there. Moreover, there are dozens of other cases where input coming+-- from the user, from serializations, etc. is parsed and then+-- required to be in the appropriate store; this case is the+-- equivalent of an existentially quantified version of 'StorePath'+-- and, notably, requiring at runtime that the index matches the+-- ambient store directory we're working in. In every case where a+-- path is treated as a store path, there is exactly one legitimate+-- candidate for the store directory it belongs to.+--+-- It may be instructive to consider the example of "chroot stores".+-- Since Nix 2.0, it has been possible to have a store actually live+-- at one directory (say, $HOME\/nix\/store) with a different+-- effective store directory (say, \/nix\/store). Nix can build into+-- a chroot store by running the builds in a mount namespace where the+-- store is at the effective store directory, can download from a+-- binary cache containing paths for the effective store directory,+-- and can run programs in the store that expect to be living at the+-- effective store directory (via nix run). When viewed as store paths+-- (rather than random files in the filesystem), paths in a chroot+-- store have nothing in common with paths in a non-chroot store that+-- lives in the same directory, and a lot in common with paths in a+-- non-chroot store that lives in the effective store directory of the+-- store in question. Store paths in stores with the same effective+-- store directory share the same hashing scheme, can be copied+-- between each other, etc. Store paths in stores with different+-- effective store directories have no relationship to each other that+-- they don't have to arbitrary other files.+type StoreDir = Symbol++-- | Smart constructor for 'StorePathName' that ensures the underlying+-- content invariant is met.+makeStorePathName :: Text -> Maybe StorePathName+makeStorePathName n = case matchTest storePathNameRegex n of+  True  -> Just $ StorePathName n+  False -> Nothing++-- | Regular expression to match valid store path names.+storePathNameRegex :: Regex+storePathNameRegex = makeRegex r+  where+    r :: String+    r = "[a-zA-Z0-9\\+\\-\\_\\?\\=][a-zA-Z0-9\\+\\-\\.\\_\\?\\=]*"++-- | Copied from @RawFilePath@ in the @unix@ package, duplicated here+-- to avoid the dependency.+type RawFilePath = ByteString++-- | Render a 'StorePath' as a 'RawFilePath'.+storePathToRawFilePath+  :: forall storeDir . (KnownStoreDir storeDir)+  => StorePath storeDir+  -> RawFilePath+storePathToRawFilePath (StorePath {..}) = BS.concat+    [ root+    , "/"+    , hashPart+    , "-"+    , name+    ]+  where+    root = storeDirVal @storeDir+    hashPart = encodeUtf8 $ encodeBase32 storePathHash+    name = encodeUtf8 $ unStorePathName storePathName++-- | Get a value-level representation of a 'KnownStoreDir'+storeDirVal :: forall storeDir . (KnownStoreDir storeDir)+            => ByteString+storeDirVal = BC.pack $ symbolVal @storeDir Proxy++-- | A 'StoreDir' whose value is known at compile time.+--+-- A valid instance of 'KnownStoreDir' should represent a valid path,+-- i.e. all "characters" fit into bytes (as determined by the logic of+-- 'BC.pack') and there are no 0 "characters". Currently this is not+-- enforced, but it should be.+type KnownStoreDir = KnownSymbol
src/System/Nix/Nar.hs view
@@ -18,6 +18,8 @@   , localUnpackNar   , narEffectsIO   , putNar+  , FilePathPart(..)+  , filePathPart   ) where  import           Control.Applicative@@ -42,7 +44,6 @@ import           System.Posix.Files         (createSymbolicLink, fileSize, getFileStatus,                                              isDirectory, readSymbolicLink) -import           System.Nix.Path  data NarEffects (m :: * -> *) = NarEffects {     narReadFile   :: FilePath -> m BSL.ByteString@@ -64,6 +65,17 @@  data Nar = Nar { narFile :: FileSystemObject }     deriving (Eq, Show)++-- | A valid filename or directory name+newtype FilePathPart = FilePathPart { unFilePathPart :: BSC.ByteString }+  deriving (Eq, Ord, Show)++-- | Construct FilePathPart from Text by checking that there+--   are no '/' or '\\NUL' characters+filePathPart :: BSC.ByteString -> Maybe FilePathPart+filePathPart p = case BSC.any (`elem` ['/', '\NUL']) p of+  False -> Just $ FilePathPart p+  True  -> Nothing  -- | A FileSystemObject (FSO) is an anonymous entity that can be NAR archived data FileSystemObject =
− src/System/Nix/Path.hs
@@ -1,128 +0,0 @@-{-|-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(..)-  , PathName(..)-  , filePathPart-  , pathName-  , Roots-  ) where--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)-import           Text.Regex.Base.RegexLike (makeRegex, matchTest)-import           Text.Regex.TDFA.Text      (Regex)---- | The hash algorithm used for store path hashes.-type PathHashAlgo = Truncated 20 SHA256----- | The name portion of a Nix path.------ Must be composed of a-z, A-Z, 0-9, +, -, ., _, ?, and =, can't--- start with a ., and must have at least one character.-newtype PathName = PathName-  { pathNameContents :: Text -- ^ The contents of the path name-  } deriving (Eq, Ord, Show, Hashable)---- | A regular expression for matching a valid 'PathName'-nameRegex :: Regex-nameRegex =-  makeRegex ("[a-zA-Z0-9\\+\\-\\_\\?\\=][a-zA-Z0-9\\+\\-\\.\\_\\?\\=]*" :: String)---- | Construct a 'PathName', assuming the provided contents are valid.-pathName :: Text -> Maybe PathName-pathName n = case matchTest nameRegex n of-  True  -> Just $ PathName n-  False -> Nothing---- | A path in a store.-data Path = Path !(Digest PathHashAlgo) !PathName-  deriving (Eq, Ord, Show)--pathToText :: Text -> Path -> Text-pathToText storeDir (Path h nm) = storeDir <> "/" <> encodeBase32 h <> "-" <> pathNameContents nm--type PathSet = HashSet Path---- | Information about substitutes for a 'Path'.-data SubstitutablePathInfo = SubstitutablePathInfo-  { -- | The .drv which led to this 'Path'.-    deriver      :: !(Maybe Path)-  , -- | The references of the 'Path'-    references   :: !PathSet-  , -- | The (likely compressed) size of the download of this 'Path'.-    downloadSize :: !Integer-  , -- | The size of the uncompressed NAR serialization of this-    -- 'Path'.-    narSize      :: !Integer-  } deriving (Eq, Ord, Show)---- | Information about @Path@-data ValidPathInfo = ValidPathInfo-  { -- | Path itself-    path             :: !Path-  , -- | The .drv which led to this 'Path'.-    deriverVP        :: !(Maybe Path)-  , -- | NAR hash-    narHash          :: !Text-  , -- | The references of the 'Path'-    referencesVP     :: !PathSet-  , -- | Registration time should be time_t-    registrationTime :: !Integer-  , -- | The size of the uncompressed NAR serialization of this-    -- 'Path'.-    narSizeVP        :: !Integer-  , -- | Whether the path is ultimately trusted, that is, it's a-    -- derivation output that was built locally.-    ultimate         :: !Bool-  , -- | Signatures-    sigs             :: ![Text]-  , -- | Content-addressed-    -- Store path is computed from a cryptographic hash-    -- of the contents of the path, plus some other bits of data like-    -- the "name" part of the path.-    ---    -- ‘ca’ has one of the following forms:-    -- * ‘text:sha256:<sha256 hash of file contents>’ (paths by makeTextPath() / addTextToStore())-    -- * ‘fixed:<r?>:<ht>:<h>’ (paths by makeFixedOutputPath() / addToStore())-    ca               :: !Text-  } deriving (Eq, Ord, Show)---- | A valid filename or directory name-newtype FilePathPart = FilePathPart { unFilePathPart :: BSC.ByteString }-  deriving (Eq, Ord, Show)---- | Construct FilePathPart from Text by checking that there---   are no '/' or '\\NUL' characters-filePathPart :: BSC.ByteString -> Maybe FilePathPart-filePathPart p = case BSC.any (`elem` ['/', '\NUL']) p of-  False -> Just $ FilePathPart p-  True  -> Nothing--type Roots = Map Path Path--instance Hashable Path where-  hashWithSalt s (Path hash name) = s `hashWithSalt` hash `hashWithSalt` name
src/System/Nix/ReadonlyStore.hs view
@@ -1,34 +1,32 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeApplications #-}-+{-# LANGUAGE ScopedTypeVariables #-} module System.Nix.ReadonlyStore where  import           Data.ByteString (ByteString)-import           Data.ByteString.Base16 as Base16+import qualified Data.ByteString as BS import qualified Data.HashSet as HS-import           Data.Text (Text)-import qualified Data.Text as T import           Data.Text.Encoding import           System.Nix.Hash-import           System.Nix.Path+import           System.Nix.StorePath -makeStorePath :: Text -> Text -> Digest 'SHA256 -> Text -> Path-makeStorePath storeDir ty h nm = Path storeHash (PathName nm)+makeStorePath :: forall storeDir hashAlgo . (KnownStoreDir storeDir, NamedAlgo hashAlgo) => ByteString -> Digest hashAlgo -> StorePathName -> StorePath storeDir+makeStorePath ty h nm = StorePath storeHash nm   where-    s = T.intercalate ":"+    s = BS.intercalate ":"       [ ty-      , algoName @'SHA256-      , encodeBase16 h-      , storeDir-      , nm+      , encodeUtf8 $ algoName @hashAlgo+      , encodeUtf8 $ encodeBase16 h+      , storeDirVal @storeDir+      , encodeUtf8 $ unStorePathName nm       ]-    storeHash = hash $ encodeUtf8 s+    storeHash = hash s -makeTextPath :: Text -> Text -> Digest 'SHA256 -> PathSet -> Path-makeTextPath storeDir nm h refs = makeStorePath storeDir ty h nm+makeTextPath :: (KnownStoreDir storeDir) => StorePathName -> Digest 'SHA256 -> StorePathSet storeDir -> StorePath storeDir+makeTextPath nm h refs = makeStorePath ty h nm   where-    ty = T.intercalate ":" ("text" : map (pathToText storeDir) (HS.toList refs))+    ty = BS.intercalate ":" ("text" : map storePathToRawFilePath (HS.toList refs)) -computeStorePathForText :: Text -> Text -> ByteString -> PathSet -> Path-computeStorePathForText storeDir nm s refs = makeTextPath storeDir nm (hash s) refs+computeStorePathForText :: (KnownStoreDir storeDir) => StorePathName -> ByteString -> StorePathSet storeDir -> StorePath storeDir+computeStorePathForText nm s refs = makeTextPath nm (hash s) refs
+ src/System/Nix/Signature.hs view
@@ -0,0 +1,9 @@+{-|+Description : Nix-relevant interfaces to NaCl signatures.+-}+module System.Nix.Signature+  ( Signature+  , NarSignature(..)+  ) where++import System.Nix.Internal.Signature
− src/System/Nix/Store.hs
@@ -1,66 +0,0 @@-{-|-Description : Types and effects for interacting with the Nix store.-Maintainer  : Shea Levy <shea@shealevy.com>--}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-module System.Nix.Store-  ( PathName, pathNameContents, pathName-  , PathHashAlgo, Path(..)-  , StoreEffects(..)-  , SubstitutablePathInfo(..)-  ) where--import qualified Data.ByteString.Lazy as BS-import Data.Text (Text)-import Text.Regex.Base.RegexLike (makeRegex, matchTest)-import Text.Regex.TDFA.Text (Regex)-import Data.Hashable (Hashable(..), hashPtrWithSalt)-import Data.HashSet (HashSet)-import Data.HashMap.Strict (HashMap)-import System.IO.Unsafe (unsafeDupablePerformIO)--import System.Nix.Hash (Digest)-import System.Nix.Path-import System.Nix.Nar----- | Interactions with the Nix store.------ @rootedPath@: A path plus a witness to the fact that the path is--- reachable from a root whose liftime is at least as long as the--- @rootedPath@ reference itself, when the implementation supports--- this.------ @validPath@: A @rootedPath@ plus a witness to the fact that the--- path is valid. On implementations that support temporary roots,--- this implies that the path will remain valid so long as the--- reference is held.------ @m@: The monad the effects operate in.-data StoreEffects rootedPath validPath m =-  StoreEffects-    { -- | Project out the underlying 'Path' from a 'rootedPath'-      fromRootedPath :: !(rootedPath -> Path)-    , -- | Project out the underlying 'rootedPath' from a 'validPath'-      fromValidPath :: !(validPath -> rootedPath)-    , -- | Which of the given paths are valid?-      validPaths :: !(HashSet rootedPath -> m (HashSet validPath))-    , -- | Get the paths that refer to a given path.-      referrers :: !(validPath -> m (HashSet Path))-    , -- | Get a root to the 'Path'.-      rootedPath :: !(Path -> m rootedPath)-    , -- | Get information about substituters of a set of 'Path's-      substitutablePathInfos ::-        !(HashSet Path -> m (HashMap Path SubstitutablePathInfo))-    , -- | Get the currently valid derivers of a 'Path'.-      validDerivers :: !(Path -> m (HashSet Path))-    , -- | Get the outputs of the derivation at a 'Path'.-      derivationOutputs :: !(validPath -> m (HashSet Path))-    , -- | Get the output names of the derivation at a 'Path'.-      derivationOutputNames :: !(validPath -> m (HashSet Text))-    , -- | Get a full 'Path' corresponding to a given 'Digest'.-      pathFromHashPart :: !(Digest PathHashAlgo -> m Path)-    , -- | Add a non-nar file to the store-      addFile :: !(BS.ByteString -> m validPath)-    }
+ src/System/Nix/StorePath.hs view
@@ -0,0 +1,23 @@+{-|+Description : Representation of Nix store paths.+-}+module System.Nix.StorePath+  ( -- * Basic store path types+    StorePath(..)+  , StorePathName+  , StorePathSet+  , StorePathHashAlgo+  , StoreDir+  , ContentAddressableAddress(..)+  , NarHashMode(..)+  , -- * Manipulating 'StorePathName'+    makeStorePathName+  , unStorePathName+  , storePathNameRegex+  , -- * Rendering out 'StorePath's+    storePathToRawFilePath+  , storeDirVal+  , KnownStoreDir+  ) where++import System.Nix.Internal.StorePath
+ src/System/Nix/StorePathMetadata.hs view
@@ -0,0 +1,49 @@+{-|+Description : Metadata about Nix store paths.+-}+module System.Nix.StorePathMetadata where++import System.Nix.StorePath (StorePath, StorePathSet, ContentAddressableAddress)+import System.Nix.Hash (SomeNamedDigest)+import Data.Set (Set)+import Data.Time (UTCTime)+import Data.Word (Word64)+import System.Nix.Signature (NarSignature)++-- | Metadata about a 'StorePath' in @storeDir@.+data StorePathMetadata storeDir = StorePathMetadata+  { -- | The path this metadata is about+    path :: !(StorePath storeDir)+  , -- | The path to the derivation file that built this path, if any+    -- and known.+    deriverPath :: !(Maybe (StorePath storeDir))+  , -- TODO should this be optional?+    -- | The hash of the nar serialization of the path.+    narHash :: !SomeNamedDigest+  , -- | The paths that this path directly references+    references :: !(StorePathSet storeDir)+  , -- | When was this path registered valid in the store?+    registrationTime :: !UTCTime+  , -- | The size of the nar serialization of the path, in bytes.+    narBytes :: !(Maybe Word64)+  , -- | How much we trust this path.+    trust :: !StorePathTrust+  , -- | A set of cryptographic attestations of this path's validity.+    --+    -- There is no guarantee from this type alone that these+    -- signatures are valid.+    sigs :: !(Set NarSignature)+  , -- | Whether and how this store path is content-addressable.+    --+    -- There is no guarantee from this type alone that this address+    -- is actually correct for this store path.+    contentAddressableAddress :: !(Maybe ContentAddressableAddress)+  }++-- | How much do we trust the path, based on its provenance?+data StorePathTrust+  = -- | It was built locally and thus ultimately trusted+    BuiltLocally+  | -- | It was built elsewhere (and substituted or similar) and so+    -- is less trusted+    BuiltElsewhere
tests/Hash.hs view
@@ -23,7 +23,7 @@ import           Text.Read                   (readMaybe)  import           System.Nix.Hash-import           System.Nix.Path+import           System.Nix.StorePath import           NarFormat -- TODO: Move the fixtures into a common module  spec_hash :: Spec@@ -45,5 +45,5 @@       let exampleStr =             "source:sha256:2bfef67de873c54551d884fdab3055d84d573e654efa79db3"             <> "c0d7b98883f9ee3:/nix/store:myfile"-      shouldBe (encodeBase32 @PathHashAlgo (hash exampleStr))+      shouldBe (encodeBase32 @StorePathHashAlgo (hash exampleStr))         "xv2iccirbrvklck36f1g7vldn5v58vck"
tests/NarFormat.hs view
@@ -33,7 +33,6 @@ import           Text.Read                   (readMaybe)  import           System.Nix.Nar-import           System.Nix.Path