packages feed

hnix-store-core 0.6.1.0 → 0.7.0.0

raw patch · 16 files changed

+256/−99 lines, 16 filesdep +case-insensitivedep ~algebraic-graphsbinary-addedPVP ok

version bump matches the API change (PVP)

Dependencies added: case-insensitive

Dependency ranges changed: algebraic-graphs

API changes (from Hackage documentation)

- System.Nix.Internal.Nar.Parser: instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (System.Nix.Internal.Nar.Effects.NarEffects m) (System.Nix.Internal.Nar.Parser.NarParser m)
- System.Nix.Internal.StorePath: [storePathRoot] :: StorePath -> !FilePath
- System.Nix.StorePath: [storePathRoot] :: StorePath -> !FilePath
+ System.Nix.Internal.Nar.Options: NarOptions :: Bool -> NarOptions
+ System.Nix.Internal.Nar.Options: [optUseCaseHack] :: NarOptions -> Bool
+ System.Nix.Internal.Nar.Options: caseHackSuffix :: Text
+ System.Nix.Internal.Nar.Options: data NarOptions
+ System.Nix.Internal.Nar.Options: defaultNarOptions :: NarOptions
+ System.Nix.Internal.Nar.Parser: instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (System.Nix.Internal.Nar.Parser.ParserEnv m) (System.Nix.Internal.Nar.Parser.NarParser m)
+ System.Nix.Internal.Nar.Parser: runParserWithOptions :: forall m a. (MonadIO m, MonadBaseControl IO m) => NarOptions -> NarEffects m -> NarParser m a -> Handle -> FilePath -> m (Either String a)
+ System.Nix.Internal.Nar.Streamer: streamNarIOWithOptions :: forall m. MonadIO m => NarOptions -> NarEffects IO -> FilePath -> NarSource m
+ System.Nix.Internal.StorePath: StoreDir :: RawFilePath -> StoreDir
+ System.Nix.Internal.StorePath: [unStoreDir] :: StoreDir -> RawFilePath
+ System.Nix.Internal.StorePath: instance Data.Hashable.Class.Hashable System.Nix.Internal.StorePath.StoreDir
+ System.Nix.Internal.StorePath: instance GHC.Classes.Eq System.Nix.Internal.StorePath.StoreDir
+ System.Nix.Internal.StorePath: instance GHC.Classes.Ord System.Nix.Internal.StorePath.StoreDir
+ System.Nix.Internal.StorePath: instance GHC.Show.Show System.Nix.Internal.StorePath.StoreDir
+ System.Nix.Internal.StorePath: instance GHC.Show.Show System.Nix.Internal.StorePath.StorePathName
+ System.Nix.Internal.StorePath: newtype StoreDir
+ System.Nix.Nar: NarOptions :: Bool -> NarOptions
+ System.Nix.Nar: [optUseCaseHack] :: NarOptions -> Bool
+ System.Nix.Nar: data NarOptions
+ System.Nix.Nar: defaultNarOptions :: NarOptions
+ System.Nix.Nar: runParserWithOptions :: forall m a. (MonadIO m, MonadBaseControl IO m) => NarOptions -> NarEffects m -> NarParser m a -> Handle -> FilePath -> m (Either String a)
+ System.Nix.Nar: streamNarIOWithOptions :: forall m. MonadIO m => NarOptions -> NarEffects IO -> FilePath -> NarSource m
+ System.Nix.StorePath: StoreDir :: RawFilePath -> StoreDir
+ System.Nix.StorePath: [unStoreDir] :: StoreDir -> RawFilePath
+ System.Nix.StorePath: newtype StoreDir
- System.Nix.Derivation: buildDerivation :: Derivation StorePath Text -> Builder
+ System.Nix.Derivation: buildDerivation :: StoreDir -> Derivation StorePath Text -> Builder
- System.Nix.Derivation: parseDerivation :: FilePath -> Parser (Derivation StorePath Text)
+ System.Nix.Derivation: parseDerivation :: StoreDir -> Parser (Derivation StorePath Text)
- System.Nix.Internal.Nar.Effects: NarEffects :: (FilePath -> m ByteString) -> (FilePath -> ByteString -> m ()) -> (FilePath -> m (Maybe ByteString) -> m ()) -> (FilePath -> m [FilePath]) -> (FilePath -> m ()) -> (FilePath -> FilePath -> m ()) -> (FilePath -> m Permissions) -> (FilePath -> Permissions -> m ()) -> (FilePath -> m Bool) -> (FilePath -> m Bool) -> (FilePath -> m Int64) -> (FilePath -> m FilePath) -> (FilePath -> m ()) -> (FilePath -> m ()) -> NarEffects (m :: * -> *)
+ System.Nix.Internal.Nar.Effects: NarEffects :: (FilePath -> m ByteString) -> (FilePath -> ByteString -> m ()) -> (FilePath -> m (Maybe ByteString) -> m ()) -> (FilePath -> m [FilePath]) -> (FilePath -> m ()) -> (FilePath -> FilePath -> m ()) -> (FilePath -> m Permissions) -> (FilePath -> Permissions -> m ()) -> (FilePath -> m Bool) -> (FilePath -> m Bool) -> (FilePath -> m Int64) -> (FilePath -> m FilePath) -> (FilePath -> m ()) -> (FilePath -> m ()) -> NarEffects (m :: Type -> Type)
- System.Nix.Internal.Nar.Effects: [narCreateDir] :: NarEffects (m :: * -> *) -> FilePath -> m ()
+ System.Nix.Internal.Nar.Effects: [narCreateDir] :: NarEffects (m :: Type -> Type) -> FilePath -> m ()
- System.Nix.Internal.Nar.Effects: [narCreateLink] :: NarEffects (m :: * -> *) -> FilePath -> FilePath -> m ()
+ System.Nix.Internal.Nar.Effects: [narCreateLink] :: NarEffects (m :: Type -> Type) -> FilePath -> FilePath -> m ()
- System.Nix.Internal.Nar.Effects: [narDeleteDir] :: NarEffects (m :: * -> *) -> FilePath -> m ()
+ System.Nix.Internal.Nar.Effects: [narDeleteDir] :: NarEffects (m :: Type -> Type) -> FilePath -> m ()
- System.Nix.Internal.Nar.Effects: [narDeleteFile] :: NarEffects (m :: * -> *) -> FilePath -> m ()
+ System.Nix.Internal.Nar.Effects: [narDeleteFile] :: NarEffects (m :: Type -> Type) -> FilePath -> m ()
- System.Nix.Internal.Nar.Effects: [narFileSize] :: NarEffects (m :: * -> *) -> FilePath -> m Int64
+ System.Nix.Internal.Nar.Effects: [narFileSize] :: NarEffects (m :: Type -> Type) -> FilePath -> m Int64
- System.Nix.Internal.Nar.Effects: [narGetPerms] :: NarEffects (m :: * -> *) -> FilePath -> m Permissions
+ System.Nix.Internal.Nar.Effects: [narGetPerms] :: NarEffects (m :: Type -> Type) -> FilePath -> m Permissions
- System.Nix.Internal.Nar.Effects: [narIsDir] :: NarEffects (m :: * -> *) -> FilePath -> m Bool
+ System.Nix.Internal.Nar.Effects: [narIsDir] :: NarEffects (m :: Type -> Type) -> FilePath -> m Bool
- System.Nix.Internal.Nar.Effects: [narIsSymLink] :: NarEffects (m :: * -> *) -> FilePath -> m Bool
+ System.Nix.Internal.Nar.Effects: [narIsSymLink] :: NarEffects (m :: Type -> Type) -> FilePath -> m Bool
- System.Nix.Internal.Nar.Effects: [narListDir] :: NarEffects (m :: * -> *) -> FilePath -> m [FilePath]
+ System.Nix.Internal.Nar.Effects: [narListDir] :: NarEffects (m :: Type -> Type) -> FilePath -> m [FilePath]
- System.Nix.Internal.Nar.Effects: [narReadFile] :: NarEffects (m :: * -> *) -> FilePath -> m ByteString
+ System.Nix.Internal.Nar.Effects: [narReadFile] :: NarEffects (m :: Type -> Type) -> FilePath -> m ByteString
- System.Nix.Internal.Nar.Effects: [narReadLink] :: NarEffects (m :: * -> *) -> FilePath -> m FilePath
+ System.Nix.Internal.Nar.Effects: [narReadLink] :: NarEffects (m :: Type -> Type) -> FilePath -> m FilePath
- System.Nix.Internal.Nar.Effects: [narSetPerms] :: NarEffects (m :: * -> *) -> FilePath -> Permissions -> m ()
+ System.Nix.Internal.Nar.Effects: [narSetPerms] :: NarEffects (m :: Type -> Type) -> FilePath -> Permissions -> m ()
- System.Nix.Internal.Nar.Effects: [narStreamFile] :: NarEffects (m :: * -> *) -> FilePath -> m (Maybe ByteString) -> m ()
+ System.Nix.Internal.Nar.Effects: [narStreamFile] :: NarEffects (m :: Type -> Type) -> FilePath -> m (Maybe ByteString) -> m ()
- System.Nix.Internal.Nar.Effects: [narWriteFile] :: NarEffects (m :: * -> *) -> FilePath -> ByteString -> m ()
+ System.Nix.Internal.Nar.Effects: [narWriteFile] :: NarEffects (m :: Type -> Type) -> FilePath -> ByteString -> m ()
- System.Nix.Internal.Nar.Effects: data NarEffects (m :: * -> *)
+ System.Nix.Internal.Nar.Effects: data NarEffects (m :: Type -> Type)
- System.Nix.Internal.StorePath: StorePath :: !StorePathHashPart -> !StorePathName -> !FilePath -> StorePath
+ System.Nix.Internal.StorePath: StorePath :: !StorePathHashPart -> !StorePathName -> StorePath
- System.Nix.Internal.StorePath: parsePath :: FilePath -> ByteString -> Either String StorePath
+ System.Nix.Internal.StorePath: parsePath :: StoreDir -> ByteString -> Either String StorePath
- System.Nix.Internal.StorePath: pathParser :: FilePath -> Parser StorePath
+ System.Nix.Internal.StorePath: pathParser :: StoreDir -> Parser StorePath
- System.Nix.Internal.StorePath: storePathToFilePath :: StorePath -> FilePath
+ System.Nix.Internal.StorePath: storePathToFilePath :: StoreDir -> StorePath -> FilePath
- System.Nix.Internal.StorePath: storePathToRawFilePath :: StorePath -> RawFilePath
+ System.Nix.Internal.StorePath: storePathToRawFilePath :: StoreDir -> StorePath -> RawFilePath
- System.Nix.Internal.StorePath: storePathToText :: StorePath -> Text
+ System.Nix.Internal.StorePath: storePathToText :: StoreDir -> StorePath -> Text
- System.Nix.Nar: NarEffects :: (FilePath -> m ByteString) -> (FilePath -> ByteString -> m ()) -> (FilePath -> m (Maybe ByteString) -> m ()) -> (FilePath -> m [FilePath]) -> (FilePath -> m ()) -> (FilePath -> FilePath -> m ()) -> (FilePath -> m Permissions) -> (FilePath -> Permissions -> m ()) -> (FilePath -> m Bool) -> (FilePath -> m Bool) -> (FilePath -> m Int64) -> (FilePath -> m FilePath) -> (FilePath -> m ()) -> (FilePath -> m ()) -> NarEffects (m :: * -> *)
+ System.Nix.Nar: NarEffects :: (FilePath -> m ByteString) -> (FilePath -> ByteString -> m ()) -> (FilePath -> m (Maybe ByteString) -> m ()) -> (FilePath -> m [FilePath]) -> (FilePath -> m ()) -> (FilePath -> FilePath -> m ()) -> (FilePath -> m Permissions) -> (FilePath -> Permissions -> m ()) -> (FilePath -> m Bool) -> (FilePath -> m Bool) -> (FilePath -> m Int64) -> (FilePath -> m FilePath) -> (FilePath -> m ()) -> (FilePath -> m ()) -> NarEffects (m :: Type -> Type)
- System.Nix.Nar: [narCreateDir] :: NarEffects (m :: * -> *) -> FilePath -> m ()
+ System.Nix.Nar: [narCreateDir] :: NarEffects (m :: Type -> Type) -> FilePath -> m ()
- System.Nix.Nar: [narCreateLink] :: NarEffects (m :: * -> *) -> FilePath -> FilePath -> m ()
+ System.Nix.Nar: [narCreateLink] :: NarEffects (m :: Type -> Type) -> FilePath -> FilePath -> m ()
- System.Nix.Nar: [narDeleteDir] :: NarEffects (m :: * -> *) -> FilePath -> m ()
+ System.Nix.Nar: [narDeleteDir] :: NarEffects (m :: Type -> Type) -> FilePath -> m ()
- System.Nix.Nar: [narDeleteFile] :: NarEffects (m :: * -> *) -> FilePath -> m ()
+ System.Nix.Nar: [narDeleteFile] :: NarEffects (m :: Type -> Type) -> FilePath -> m ()
- System.Nix.Nar: [narFileSize] :: NarEffects (m :: * -> *) -> FilePath -> m Int64
+ System.Nix.Nar: [narFileSize] :: NarEffects (m :: Type -> Type) -> FilePath -> m Int64
- System.Nix.Nar: [narGetPerms] :: NarEffects (m :: * -> *) -> FilePath -> m Permissions
+ System.Nix.Nar: [narGetPerms] :: NarEffects (m :: Type -> Type) -> FilePath -> m Permissions
- System.Nix.Nar: [narIsDir] :: NarEffects (m :: * -> *) -> FilePath -> m Bool
+ System.Nix.Nar: [narIsDir] :: NarEffects (m :: Type -> Type) -> FilePath -> m Bool
- System.Nix.Nar: [narIsSymLink] :: NarEffects (m :: * -> *) -> FilePath -> m Bool
+ System.Nix.Nar: [narIsSymLink] :: NarEffects (m :: Type -> Type) -> FilePath -> m Bool
- System.Nix.Nar: [narListDir] :: NarEffects (m :: * -> *) -> FilePath -> m [FilePath]
+ System.Nix.Nar: [narListDir] :: NarEffects (m :: Type -> Type) -> FilePath -> m [FilePath]
- System.Nix.Nar: [narReadFile] :: NarEffects (m :: * -> *) -> FilePath -> m ByteString
+ System.Nix.Nar: [narReadFile] :: NarEffects (m :: Type -> Type) -> FilePath -> m ByteString
- System.Nix.Nar: [narReadLink] :: NarEffects (m :: * -> *) -> FilePath -> m FilePath
+ System.Nix.Nar: [narReadLink] :: NarEffects (m :: Type -> Type) -> FilePath -> m FilePath
- System.Nix.Nar: [narSetPerms] :: NarEffects (m :: * -> *) -> FilePath -> Permissions -> m ()
+ System.Nix.Nar: [narSetPerms] :: NarEffects (m :: Type -> Type) -> FilePath -> Permissions -> m ()
- System.Nix.Nar: [narStreamFile] :: NarEffects (m :: * -> *) -> FilePath -> m (Maybe ByteString) -> m ()
+ System.Nix.Nar: [narStreamFile] :: NarEffects (m :: Type -> Type) -> FilePath -> m (Maybe ByteString) -> m ()
- System.Nix.Nar: [narWriteFile] :: NarEffects (m :: * -> *) -> FilePath -> ByteString -> m ()
+ System.Nix.Nar: [narWriteFile] :: NarEffects (m :: Type -> Type) -> FilePath -> ByteString -> m ()
- System.Nix.Nar: data NarEffects (m :: * -> *)
+ System.Nix.Nar: data NarEffects (m :: Type -> Type)
- System.Nix.ReadonlyStore: computeStorePathForPath :: StorePathName -> FilePath -> Bool -> (FilePath -> Bool) -> Bool -> IO StorePath
+ System.Nix.ReadonlyStore: computeStorePathForPath :: StoreDir -> StorePathName -> FilePath -> Bool -> (FilePath -> Bool) -> Bool -> IO StorePath
- System.Nix.ReadonlyStore: computeStorePathForText :: FilePath -> StorePathName -> ByteString -> StorePathSet -> StorePath
+ System.Nix.ReadonlyStore: computeStorePathForText :: StoreDir -> StorePathName -> ByteString -> StorePathSet -> StorePath
- System.Nix.ReadonlyStore: makeFixedOutputPath :: forall hashAlgo. NamedAlgo hashAlgo => FilePath -> Bool -> Digest hashAlgo -> StorePathName -> StorePath
+ System.Nix.ReadonlyStore: makeFixedOutputPath :: forall hashAlgo. NamedAlgo hashAlgo => StoreDir -> Bool -> Digest hashAlgo -> StorePathName -> StorePath
- System.Nix.ReadonlyStore: makeStorePath :: forall h. NamedAlgo h => FilePath -> ByteString -> Digest h -> StorePathName -> StorePath
+ System.Nix.ReadonlyStore: makeStorePath :: forall h. NamedAlgo h => StoreDir -> ByteString -> Digest h -> StorePathName -> StorePath
- System.Nix.ReadonlyStore: makeTextPath :: FilePath -> StorePathName -> Digest SHA256 -> StorePathSet -> StorePath
+ System.Nix.ReadonlyStore: makeTextPath :: StoreDir -> StorePathName -> Digest SHA256 -> StorePathSet -> StorePath
- System.Nix.StorePath: StorePath :: !StorePathHashPart -> !StorePathName -> !FilePath -> StorePath
+ System.Nix.StorePath: StorePath :: !StorePathHashPart -> !StorePathName -> StorePath
- System.Nix.StorePath: parsePath :: FilePath -> ByteString -> Either String StorePath
+ System.Nix.StorePath: parsePath :: StoreDir -> ByteString -> Either String StorePath
- System.Nix.StorePath: pathParser :: FilePath -> Parser StorePath
+ System.Nix.StorePath: pathParser :: StoreDir -> Parser StorePath
- System.Nix.StorePath: storePathToFilePath :: StorePath -> FilePath
+ System.Nix.StorePath: storePathToFilePath :: StoreDir -> StorePath -> FilePath
- System.Nix.StorePath: storePathToRawFilePath :: StorePath -> RawFilePath
+ System.Nix.StorePath: storePathToRawFilePath :: StoreDir -> StorePath -> RawFilePath
- System.Nix.StorePath: storePathToText :: StorePath -> Text
+ System.Nix.StorePath: storePathToText :: StoreDir -> StorePath -> Text

Files

ChangeLog.md view
@@ -1,5 +1,19 @@ # ChangeLog +## [0.7.0.0](https://github.com/haskell-nix/hnix-store/compare/core-0.6.1.0...core-0.7.0.0) 2023-11-15++* Breaking:+    * [(link)](https://github.com/haskell-nix/hnix-store/pull/216) `StorePath` no longer carries `storePathRoot` field and we+      have a stand-alone `StoreDir` type instead to be used instead of `FilePath`+      when store root directory is needed as a context.++* Additional:+    * [(link)](https://github.com/haskell-nix/hnix-store/pull/218) NAR encoding and decoding now supports case-insensitive filesystems.+      * The "case hack" replicates the behavior of the `use-case-hack` option in Nix, which adds a suffix to conflicting filenames.+        This feature is enabled by default on macOS (darwin).+      * `data NarOptions` has been added to configure NAR encoding and decoding. The `optUseCaseHack` field can be used to enable or disable the case hack.+      * New `streamNarIOWithOptions` and `runParserWithOptions` functions have been added to `System.Nix.Nar` to support the new configurable options.+ ## [0.6.1.0](https://github.com/haskell-nix/hnix-store/compare/core-0.6.0.0...core-0.6.1.0) 2023-01-02  * Fixed:
hnix-store-core.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                hnix-store-core-version:             0.6.1.0+version:             0.7.0.0 synopsis:            Core effects for interacting with the Nix store. description:   This package contains types and functions needed to describe@@ -19,6 +19,7 @@   , README.md   , tests/samples/example0.drv   , tests/samples/example1.drv+  , tests/fixtures/case-conflict.nar  Common commons   if impl(ghc >= 8.10)@@ -40,6 +41,7 @@     , System.Nix.Internal.Nar.Parser     , System.Nix.Internal.Nar.Streamer     , System.Nix.Internal.Nar.Effects+    , System.Nix.Internal.Nar.Options     , System.Nix.Internal.Signature     , System.Nix.Internal.StorePath     , System.Nix.Nar@@ -51,10 +53,11 @@       base >=4.12 && <5     , relude >= 1.0     , attoparsec-    , algebraic-graphs >= 0.5 && < 0.7+    , algebraic-graphs >= 0.5 && < 0.8     , base16-bytestring     , base64-bytestring     , bytestring+    , case-insensitive     , cereal     , containers     -- Required for cryptonite low-level type convertion
src/System/Nix/Derivation.hs view
@@ -11,19 +11,22 @@                                                 ( Parser ) import           Nix.Derivation                 ( Derivation ) import qualified Nix.Derivation                as Derivation-import           System.Nix.StorePath           ( StorePath )+import           System.Nix.StorePath           ( StoreDir+                                                , StorePath+                                                , storePathToFilePath+                                                ) import qualified System.Nix.StorePath          as StorePath   -parseDerivation :: FilePath -> Text.Lazy.Parser (Derivation StorePath Text)+parseDerivation :: StoreDir -> Text.Lazy.Parser (Derivation StorePath Text) parseDerivation expectedRoot =   Derivation.parseDerivationWith     ("\"" *> StorePath.pathParser expectedRoot <* "\"")     Derivation.textParser -buildDerivation :: Derivation StorePath Text -> Text.Lazy.Builder-buildDerivation =+buildDerivation :: StoreDir -> Derivation StorePath Text -> Text.Lazy.Builder+buildDerivation storeDir =   Derivation.buildDerivationWith-    (show . show)+    (show . storePathToFilePath storeDir)     show
src/System/Nix/Internal/Nar/Effects.hs view
@@ -7,6 +7,7 @@   , narEffectsIO   ) where +import Data.Kind () import qualified Data.ByteString             as Bytes import qualified Data.ByteString.Lazy        as Bytes.Lazy import qualified System.Directory            as Directory@@ -22,7 +23,7 @@ import qualified Control.Exception.Lifted    as Exception.Lifted import qualified Control.Monad.Fail          as MonadFail -data NarEffects (m :: * -> *) = NarEffects {+data NarEffects (m :: Type -> Type) = NarEffects {     narReadFile   :: FilePath -> m Bytes.Lazy.ByteString   , narWriteFile  :: FilePath -> Bytes.Lazy.ByteString -> m ()   , narStreamFile :: FilePath -> m (Maybe Bytes.ByteString) -> m ()
+ src/System/Nix/Internal/Nar/Options.hs view
@@ -0,0 +1,28 @@+module System.Nix.Internal.Nar.Options +  ( NarOptions(..)+  , defaultNarOptions+  , caseHackSuffix+  ) where++import qualified System.Info++-- | Options for configuring how NAR files are encoded and decoded.+data NarOptions = NarOptions {+  optUseCaseHack :: Bool+  -- ^ Whether to enable a case hack to support case-insensitive filesystems.+  -- Equivalent to the 'use-case-hack' option in the Nix client.+  --+  -- The case hack rewrites file names to avoid collisions on case-insensitive file systems, e.g. APFS and HFS+ on macOS.+  -- Enabled by default on macOS (Darwin).+}++defaultNarOptions :: NarOptions+defaultNarOptions = NarOptions {+  optUseCaseHack =+    if System.Info.os == "darwin"+      then True+      else False+}++caseHackSuffix :: Text+caseHackSuffix = "~nix~case~hack~"
src/System/Nix/Internal/Nar/Parser.hs view
@@ -3,9 +3,11 @@ {-# language GeneralizedNewtypeDeriving #-} {-# language ScopedTypeVariables        #-} {-# language TypeFamilies               #-}+{-# language TypeOperators              #-}  module System.Nix.Internal.Nar.Parser   ( runParser+  , runParserWithOptions   , parseNar   , testParser   , testParser'@@ -25,6 +27,8 @@ import qualified Control.Monad.Trans             as Trans import qualified Control.Monad.Trans.Control     as Base import qualified Data.ByteString                 as Bytes+import qualified Data.CaseInsensitive            as CI+import qualified Data.HashMap.Strict             as HashMap import qualified Data.List                       as List import qualified Data.Map                        as Map import qualified Data.Serialize                  as Serialize@@ -34,6 +38,7 @@ import qualified System.IO                       as IO  import qualified System.Nix.Internal.Nar.Effects as Nar+import qualified System.Nix.Internal.Nar.Options as Nar   -- | NarParser is a monad for parsing a Nar file as a byte stream@@ -47,19 +52,34 @@         ParserState         (Except.ExceptT           String-          (Reader.ReaderT-            (Nar.NarEffects m)-            m-          )+          (Reader.ReaderT (ParserEnv m) m)         )         a   }   deriving ( Functor, Applicative, Monad, Fail.MonadFail            , Trans.MonadIO, State.MonadState ParserState            , Except.MonadError String-           , Reader.MonadReader (Nar.NarEffects m)+           , Reader.MonadReader (ParserEnv m)            ) ++data ParserEnv m = ParserEnv+  { envNarEffects :: Nar.NarEffects m+  , envNarOptions :: Nar.NarOptions+  }+++getNarEffects :: Monad m => NarParser m (Nar.NarEffects m)+getNarEffects = fmap envNarEffects ask+++getNarEffect :: Monad m => (Nar.NarEffects m -> a) -> NarParser m a+getNarEffect eff = fmap eff getNarEffects+++getNarOptions :: Monad m => NarParser m Nar.NarOptions+getNarOptions = fmap envNarOptions ask+ -- | Run a @NarParser@ over a byte stream --   This is suitable for testing the top-level NAR parser, or any of the --   smaller utilities parsers, if you have bytes appropriate for them@@ -76,9 +96,26 @@   -> FilePath      -- ^ The root file system object to be created by the NAR   -> m (Either String a)-runParser effs (NarParser action) h target = do+runParser effs parser h target = do+  runParserWithOptions Nar.defaultNarOptions effs parser h target++runParserWithOptions+  :: forall m a+   . (IO.MonadIO m, Base.MonadBaseControl IO m)+  => Nar.NarOptions+  -> Nar.NarEffects m+     -- ^ Provide the effects set, usually @narEffectsIO@+  -> NarParser m a+     -- ^ A parser to run, such as @parseNar@+  -> IO.Handle+     -- ^ A handle the stream containg the NAR. It should already be+     --   open and in @ReadMode@+  -> FilePath+     -- ^ The root file system object to be created by the NAR+  -> m (Either String a)+runParserWithOptions opts effs (NarParser action) h target = do   unpackResult <--    runReaderT (runExceptT $ State.evalStateT action state0) effs+    runReaderT (runExceptT $ State.evalStateT action state0) (ParserEnv effs opts)       `Exception.Lifted.catch` exceptionHandler   when (isLeft unpackResult) cleanup   pure unpackResult@@ -91,6 +128,7 @@       , handle         = h       , directoryStack = [target]       , links          = []+      , filePaths      = HashMap.empty       }    exceptionHandler :: Exception.Lifted.SomeException -> m (Either String a)@@ -125,6 +163,9 @@   , links          :: [LinkInfo]     -- ^ Unlike with files and directories, we collect symlinks     --   from the NAR on+  , filePaths      :: HashMap.HashMap (CI.CI FilePath) Int+    -- ^ A map of case-insensitive files paths to the number of collisions encountered.+    -- See @Nar.NarOptions.optUseCaseHack@ for details.   }  @@ -229,11 +270,11 @@           pure $ Just chunk    target     <- currentFile-  streamFile <- asks Nar.narStreamFile+  streamFile <- getNarEffect Nar.narStreamFile   lift (streamFile target getChunk)    when (s == "executable") $ do-    effs :: Nar.NarEffects m <- ask+    effs :: Nar.NarEffects m <- getNarEffects     lift $ do       p <- Nar.narGetPerms effs target       Nar.narSetPerms effs target (p { Directory.executable = True })@@ -245,37 +286,53 @@ --   handles for target files longer than needed parseDirectory :: (IO.MonadIO m, Fail.MonadFail m) => NarParser m () parseDirectory = do-  createDirectory <- asks Nar.narCreateDir+  createDirectory <- getNarEffect Nar.narCreateDir   target          <- currentFile   lift $ createDirectory target-  parseEntryOrFinish+  parseEntryOrFinish target   where -  parseEntryOrFinish :: (IO.MonadIO m, Fail.MonadFail m) => NarParser m ()-  parseEntryOrFinish =+  parseEntryOrFinish :: (IO.MonadIO m, Fail.MonadFail m) => FilePath -> NarParser m ()+  parseEntryOrFinish path =     -- If we reach a ")", we finished the directory's entries, and we have     -- to put ")" back into the stream, because the outer call to @parens@     -- expects to consume it.     -- Otherwise, parse an entry as a fresh file system object     matchStr       [ ( ")"   , pushStr ")" )-      , ("entry", parseEntry  )+      , ("entry", parseEntry path  )       ] -  parseEntry :: (IO.MonadIO m, Fail.MonadFail m) => NarParser m ()-  parseEntry = do+  parseEntry :: (IO.MonadIO m, Fail.MonadFail m) => FilePath -> NarParser m ()+  parseEntry path = do+    opts <- getNarOptions     parens $ do       expectStr "name"-      fName <- parseStr+      fName <-+        if Nar.optUseCaseHack opts then+          addCaseHack path =<< parseStr+        else+          parseStr       pushFileName (toString fName)       expectStr "node"       parens parseFSO       popFileName-    parseEntryOrFinish+    parseEntryOrFinish path +  addCaseHack :: (IO.MonadIO m, Fail.MonadFail m) => FilePath -> Text -> NarParser m Text+  addCaseHack path fName = do+    let key = path </> Text.unpack fName+    recordFilePath key+    conflictCount <- getFilePathConflictCount key+    pure $+      if conflictCount > 0 then+        fName <> Nar.caseHackSuffix <> show conflictCount+      else+        fName  + ------------------------------------------------------------------------------ -- * Utility parsers @@ -372,7 +429,7 @@ --   (Targets must be created before the links that target them) createLinks :: IO.MonadIO m => NarParser m () createLinks = do-  createLink  <- asks Nar.narCreateLink+  createLink  <- getNarEffect Nar.narCreateLink   allLinks    <- State.gets links   sortedLinks <- IO.liftIO $ sortLinksIO allLinks   forM_ sortedLinks $ \li -> do@@ -421,7 +478,7 @@ consume 0 = pure "" consume n = do   state0   <- State.get-  newBytes <- IO.liftIO $ Bytes.hGetSome (handle state0) (max 0 n)+  newBytes <- IO.liftIO $ Bytes.hGet (handle state0) (max 0 n)   when (Bytes.length newBytes < n) $     Fail.fail $     "consume: Not enough bytes in handle. Wanted "@@ -471,6 +528,16 @@ pushLink :: Monad m => LinkInfo -> NarParser m () pushLink linkInfo = State.modify (\s -> s { links = linkInfo : links s }) ++-- | Add a file path to the collection of encountered file paths+recordFilePath :: Monad m => FilePath -> NarParser m ()+recordFilePath fPath =+  State.modify (\s -> s { filePaths = HashMap.insertWith (\_ v -> v + 1) (CI.mk fPath) 0 (filePaths s) })++getFilePathConflictCount :: Monad m => FilePath -> NarParser m Int+getFilePathConflictCount fPath = do+  fileMap <- State.gets filePaths+  pure $ HashMap.findWithDefault 0 (CI.mk fPath) fileMap  ------------------------------------------------------------------------------ -- * Utilities
src/System/Nix/Internal/Nar/Streamer.hs view
@@ -7,21 +7,22 @@   , dumpString   , dumpPath   , streamNarIO+  , streamNarIOWithOptions   , IsExecutable(..)   ) where  import qualified Control.Monad.IO.Class          as IO import qualified Data.ByteString                 as Bytes-import qualified Data.ByteString.Char8           as Bytes.Char8 import qualified Data.ByteString.Lazy            as Bytes.Lazy import qualified Data.Serialize                  as Serial-import qualified Data.Text                       as T (pack)+import qualified Data.Text                       as T (pack, breakOn) import qualified Data.Text.Encoding              as TE (encodeUtf8) import qualified System.Directory                as Directory import           System.FilePath                 ((</>))  import qualified System.Nix.Internal.Nar.Effects as Nar+import qualified System.Nix.Internal.Nar.Options as Nar   -- | NarSource@@ -57,7 +58,11 @@ --   function from any streaming library, and repeatedly calls --   it while traversing the filesystem object to Nar encode streamNarIO :: forall m . IO.MonadIO m => Nar.NarEffects IO -> FilePath -> NarSource m-streamNarIO effs basePath yield = do+streamNarIO effs basePath yield =+  streamNarIOWithOptions Nar.defaultNarOptions effs basePath yield++streamNarIOWithOptions :: forall m . IO.MonadIO m => Nar.NarOptions -> Nar.NarEffects IO -> FilePath -> NarSource m+streamNarIOWithOptions opts effs basePath yield = do   yield $ str "nix-archive-1"   parens $ go basePath  where@@ -77,7 +82,12 @@             yield $ str "entry"             parens $ do               let fullName = path </> f-              yield $ strs ["name", filePathToBS f, "node"]+              let serializedPath =+                    if Nar.optUseCaseHack opts then+                      filePathToBSWithCaseHack f+                    else+                      filePathToBS f+              yield $ strs ["name", serializedPath, "node"]               parens $ go fullName         else do           isExec <- IO.liftIO $ isExecutable effs path@@ -88,8 +98,6 @@           yield $ int fSize           yieldFile path fSize -  filePathToBS = TE.encodeUtf8 . T.pack-   parens act = do     yield $ str "("     r <- act@@ -99,7 +107,7 @@   -- Read, yield, and pad the file   yieldFile :: FilePath -> Int64 -> m ()   yieldFile path fsize = do-    mapM_ yield . Bytes.Lazy.toChunks =<< IO.liftIO (Bytes.Lazy.readFile path)+    mapM_ yield . Bytes.Lazy.toChunks =<< IO.liftIO (Nar.narReadFile effs path)     yield $ Bytes.replicate (padLen $ fromIntegral fsize) 0  data IsExecutable = NonExecutable | Executable@@ -131,3 +139,12 @@  strs :: [ByteString] -> ByteString strs xs = Bytes.concat $ str <$> xs++filePathToBS :: FilePath -> ByteString+filePathToBS = TE.encodeUtf8 . T.pack++filePathToBSWithCaseHack :: FilePath -> ByteString+filePathToBSWithCaseHack = TE.encodeUtf8 . undoCaseHack . T.pack++undoCaseHack :: Text -> Text+undoCaseHack = fst . T.breakOn Nar.caseHackSuffix
src/System/Nix/Internal/StorePath.hs view
@@ -10,7 +10,8 @@  module System.Nix.Internal.StorePath   ( -- * Basic store path types-    StorePath(..)+    StoreDir(..)+  , StorePath(..)   , StorePathName(..)   , StorePathSet   , mkStorePathHashPart@@ -32,7 +33,6 @@ where  import qualified Relude.Unsafe as Unsafe-import qualified Text.Show import           System.Nix.Internal.Hash import           System.Nix.Internal.Base import qualified System.Nix.Internal.Base32    as Nix.Base32@@ -54,10 +54,9 @@ -- 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.+-- The store directory is *not* included, and must be known from the+-- context. This matches modern C++ Nix, and also represents the fact+-- that store paths for different store directories cannot be mixed. data StorePath = StorePath   { -- | The 160-bit hash digest reflecting the "address" of the name.     -- Currently, this is a truncated SHA256 hash.@@ -66,18 +65,13 @@     -- this is typically the package name and version (e.g.     -- hello-1.2.3).     storePathName :: !StorePathName-  , -- | Root of the store-    storePathRoot :: !FilePath   }-  deriving (Eq, Ord)+  deriving (Eq, Ord, Show)  instance Hashable StorePath where   hashWithSalt s StorePath{..} =     s `hashWithSalt` storePathHash `hashWithSalt` storePathName -instance Show StorePath where-  show p = Bytes.Char8.unpack $ storePathToRawFilePath p- -- | The name portion of a Nix path. -- -- 'unStorePathName' must only contain a-zA-Z0-9+._?=-, can't start@@ -86,7 +80,7 @@ newtype StorePathName = StorePathName   { -- | Extract the contents of the name.     unStorePathName :: Text-  } deriving (Eq, Hashable, Ord)+  } deriving (Eq, Hashable, Ord, Show)  -- | The hash algorithm used for store path hashes. newtype StorePathHashPart = StorePathHashPart ByteString@@ -161,22 +155,29 @@ -- to avoid the dependency. type RawFilePath = ByteString +-- | The path to the store dir+--+-- Many operations need to be parameterized with this, since store paths+-- do not know their own store dir by design.+newtype StoreDir = StoreDir {+    unStoreDir :: RawFilePath+  } deriving (Eq, Hashable, Ord, Show)+ -- | Render a 'StorePath' as a 'RawFilePath'.-storePathToRawFilePath :: StorePath -> RawFilePath-storePathToRawFilePath StorePath{..} =-  root <> "/" <> hashPart <> "-" <> name+storePathToRawFilePath :: StoreDir -> StorePath -> RawFilePath+storePathToRawFilePath storeDir StorePath{..} =+  unStoreDir storeDir <> "/" <> hashPart <> "-" <> name  where-  root     = Bytes.Char8.pack storePathRoot   hashPart = encodeUtf8 $ encodeWith NixBase32 $ coerce storePathHash   name     = encodeUtf8 $ unStorePathName storePathName  -- | Render a 'StorePath' as a 'FilePath'.-storePathToFilePath :: StorePath -> FilePath-storePathToFilePath = Bytes.Char8.unpack . storePathToRawFilePath+storePathToFilePath :: StoreDir -> StorePath -> FilePath+storePathToFilePath storeDir = Bytes.Char8.unpack . storePathToRawFilePath storeDir  -- | Render a 'StorePath' as a 'Text'.-storePathToText :: StorePath -> Text-storePathToText = toText . Bytes.Char8.unpack . storePathToRawFilePath+storePathToText :: StoreDir -> StorePath -> Text+storePathToText storeDir = toText . Bytes.Char8.unpack . storePathToRawFilePath storeDir  -- | Build `narinfo` suffix from `StorePath` which -- can be used to query binary caches.@@ -186,7 +187,7 @@  -- | Parse `StorePath` from `Bytes.Char8.ByteString`, checking -- that store directory matches `expectedRoot`.-parsePath :: FilePath -> Bytes.Char8.ByteString -> Either String StorePath+parsePath :: StoreDir -> Bytes.Char8.ByteString -> Either String StorePath parsePath expectedRoot x =   let     (rootDir, fname) = FilePath.splitFileName . Bytes.Char8.unpack $ x@@ -196,17 +197,20 @@     --rootDir' = dropTrailingPathSeparator rootDir     -- cannot use ^^ as it drops multiple slashes /a/b/// -> /a/b     rootDir' = Unsafe.init rootDir+    expectedRootS = Bytes.Char8.unpack (unStoreDir expectedRoot)     storeDir =-      if expectedRoot == rootDir'+      if expectedRootS == rootDir'         then pure rootDir'-        else Left $ "Root store dir mismatch, expected" <> expectedRoot <> "got" <> rootDir'+        else Left $ "Root store dir mismatch, expected" <> expectedRootS <> "got" <> rootDir'   in-    StorePath <$> coerce storeHash <*> name <*> storeDir+    either Left (pure $ StorePath <$> coerce storeHash <*> name) storeDir -pathParser :: FilePath -> Parser StorePath+pathParser :: StoreDir -> Parser StorePath pathParser expectedRoot = do+  let expectedRootS = Bytes.Char8.unpack (unStoreDir expectedRoot)+   _ <--    Parser.Text.Lazy.string (toText expectedRoot)+    Parser.Text.Lazy.string (toText expectedRootS)       <?> "Store root mismatch" -- e.g. /nix/store    _ <- Parser.Text.Lazy.char '/'@@ -232,4 +236,4 @@   either     fail     pure-    (StorePath <$> coerce digest <*> name <*> pure expectedRoot)+    (StorePath <$> coerce digest <*> name)
src/System/Nix/Nar.hs view
@@ -23,9 +23,14 @@   , Nar.NarEffects(..)   , Nar.narEffectsIO +  , Nar.NarOptions(..)+  , Nar.defaultNarOptions+   -- * Internal   , Nar.streamNarIO+  , Nar.streamNarIOWithOptions   , Nar.runParser+  , Nar.runParserWithOptions   , Nar.dumpString   , Nar.dumpPath @@ -39,6 +44,7 @@ import qualified System.IO                         as IO  import qualified System.Nix.Internal.Nar.Effects   as Nar+import qualified System.Nix.Internal.Nar.Options   as Nar import qualified System.Nix.Internal.Nar.Parser    as Nar import qualified System.Nix.Internal.Nar.Streamer  as Nar 
src/System/Nix/ReadonlyStore.hs view
@@ -4,6 +4,7 @@ module System.Nix.ReadonlyStore where  +import qualified Data.ByteString.Char8         as Bytes.Char8 import qualified Data.ByteString               as BS import qualified Data.HashSet                  as HS import           System.Nix.Hash@@ -23,43 +24,42 @@ makeStorePath   :: forall h    . (NamedAlgo h)-  => FilePath+  => StoreDir   -> ByteString   -> Digest h   -> StorePathName   -> StorePath-makeStorePath fp ty h nm = StorePath (coerce storeHash) nm fp+makeStorePath storeDir ty h nm = StorePath (coerce storeHash) nm  where   storeHash = mkStorePathHash @h s-   s =     BS.intercalate ":" $       ty:fmap encodeUtf8         [ algoName @h         , encodeDigestWith Base16 h-        , toText fp+        , toText . Bytes.Char8.unpack $ unStoreDir storeDir         , coerce nm         ]  makeTextPath-  :: FilePath -> StorePathName -> Digest SHA256 -> StorePathSet -> StorePath-makeTextPath fp nm h refs = makeStorePath fp ty h nm+  :: StoreDir -> StorePathName -> Digest SHA256 -> StorePathSet -> StorePath+makeTextPath storeDir nm h refs = makeStorePath storeDir ty h nm  where   ty =-    BS.intercalate ":" $ "text" : sort (storePathToRawFilePath <$> HS.toList refs)+    BS.intercalate ":" $ "text" : sort (storePathToRawFilePath storeDir <$> HS.toList refs)  makeFixedOutputPath   :: forall hashAlgo   .  NamedAlgo hashAlgo-  => FilePath+  => StoreDir   -> Bool   -> Digest hashAlgo   -> StorePathName   -> StorePath-makeFixedOutputPath fp recursive h =+makeFixedOutputPath storeDir recursive h =   if recursive && (algoName @hashAlgo) == "sha256"-    then makeStorePath fp "source" h-    else makeStorePath fp "output:out" h'+    then makeStorePath storeDir "source" h+    else makeStorePath storeDir "output:out" h'  where   h' =     hash @ByteString @SHA256@@ -70,19 +70,20 @@       <> ":"  computeStorePathForText-  :: FilePath -> StorePathName -> ByteString -> (StorePathSet -> StorePath)-computeStorePathForText fp nm = makeTextPath fp nm . hash+  :: StoreDir -> StorePathName -> ByteString -> (StorePathSet -> StorePath)+computeStorePathForText storeDir nm = makeTextPath storeDir nm . hash  computeStorePathForPath-  :: StorePathName        -- ^ Name part of the newly created `StorePath`+  :: StoreDir+  -> StorePathName        -- ^ Name part of the newly created `StorePath`   -> FilePath             -- ^ Local `FilePath` to add   -> Bool                 -- ^ Add target directory recursively   -> (FilePath -> Bool)   -- ^ Path filter function   -> Bool                 -- ^ Only used by local store backend   -> IO StorePath-computeStorePathForPath name pth recursive _pathFilter _repair = do+computeStorePathForPath storeDir name pth recursive _pathFilter _repair = do   selectedHash <- if recursive then recursiveContentHash else flatContentHash-  pure $ makeFixedOutputPath "/nix/store" recursive selectedHash name+  pure $ makeFixedOutputPath storeDir recursive selectedHash name  where   recursiveContentHash :: IO (Digest SHA256)   recursiveContentHash = hashFinalize <$> execStateT streamNarUpdate (hashInit @SHA256)
src/System/Nix/StorePath.hs view
@@ -3,7 +3,8 @@ -} module System.Nix.StorePath   ( -- * Basic store path types-    StorePath(..)+    StoreDir(..)+  , StorePath(..)   , StorePathName(..)   , StorePathSet   , mkStorePathHashPart
tests/Arbitrary.hs view
@@ -35,23 +35,24 @@ instance Arbitrary (Digest SHA256) where   arbitrary = hash . BSC.pack <$> arbitrary +instance Arbitrary StoreDir where+  arbitrary = StoreDir . ("/" <>) . BSC.pack <$> arbitrary+ newtype NixLike = NixLike {getNixLike :: StorePath}  deriving (Eq, Ord, Show)  instance Arbitrary NixLike where   arbitrary =     NixLike <$>-      liftA3 StorePath+      liftA2 StorePath         arbitraryTruncatedDigest         arbitrary-        (pure "/nix/store")    where     -- 160-bit hash, 20 bytes, 32 chars in base32     arbitraryTruncatedDigest = coerce . BSC.pack <$> replicateM 20 genSafeChar  instance Arbitrary StorePath where   arbitrary =-    liftA3 StorePath+    liftA2 StorePath       arbitrary       arbitrary-      dir
tests/Derivation.hs view
@@ -6,6 +6,7 @@                                                 ) import           Test.Tasty.Golden              ( goldenVsFile ) +import           System.Nix.StorePath           ( StoreDir(..) ) import           System.Nix.Derivation          ( parseDerivation                                                 , buildDerivation                                                 )@@ -23,10 +24,10 @@     (Data.Text.IO.writeFile dest       . toText       . Data.Text.Lazy.Builder.toLazyText-      . buildDerivation+      . buildDerivation (StoreDir "/nix/store")     )     (Data.Attoparsec.Text.parseOnly-      (parseDerivation "/nix/store")+      (parseDerivation $ StoreDir "/nix/store")       contents     ) 
tests/NarFormat.hs view
@@ -5,6 +5,7 @@  import qualified Control.Concurrent               as Concurrent import           Control.Exception                (try)+import           Data.Binary                      (Binary(..), decodeFile) import           Data.Binary.Get                  (Get, getByteString,                                                    getInt64le,                                                    getLazyByteString, runGet)@@ -100,6 +101,10 @@     it "roundtrips directory" $ do       roundTrip "sampleDirectory" (Nar sampleDirectory) +    it "roundtrips case conflicts" $ do+      nar <- decodeFile "tests/fixtures/case-conflict.nar"+      roundTrip "caseConflict" nar+   describe "matches-nix-store fixture" $ do     it "matches regular" $ do       encEqualsNixStore (Nar sampleRegular) sampleRegularBaseline@@ -115,6 +120,7 @@      it "matches directory" $ do       encEqualsNixStore (Nar sampleDirectory) sampleDirectoryBaseline+     it "matches symlink to directory" $ do       encEqualsNixStore (Nar sampleLinkToDirectory) sampleLinkToDirectoryBaseline @@ -578,7 +584,7 @@ filePathPart p = if BSC.any (`elem` ['/', '\NUL']) p then Nothing else Just $ FilePathPart p  newtype Nar = Nar { narFile :: FileSystemObject }-    deriving (Eq, Show)+    deriving (Eq, Show, Generic)  -- | A FileSystemObject (FSO) is an anonymous entity that can be NAR archived data FileSystemObject =@@ -594,6 +600,9 @@ newtype FilePathPart = FilePathPart { unFilePathPart :: BSC.ByteString }   deriving (Eq, Ord, Show) +instance Binary Nar where+  get = getNar+  put = putNar  instance Arbitrary Nar where   arbitrary = Nar <$> resize 10 arbitrary
tests/StorePath.hs view
@@ -1,5 +1,6 @@ {-# language DataKinds           #-} {-# language ScopedTypeVariables #-}+{-# language OverloadedStrings   #-}  module StorePath where @@ -11,19 +12,19 @@ import           Arbitrary  -- | Test that Nix(OS) like paths roundtrip-prop_storePathRoundtrip :: NixLike -> NixLike -> Property-prop_storePathRoundtrip (_ :: NixLike) (NixLike x) =-  parsePath "/nix/store" (storePathToRawFilePath x) === pure x+prop_storePathRoundtrip :: StoreDir -> NixLike -> NixLike -> Property+prop_storePathRoundtrip storeDir (_ :: NixLike) (NixLike x) =+  parsePath storeDir (storePathToRawFilePath storeDir x) === pure x  -- | Test that any `StorePath` roundtrips-prop_storePathRoundtrip' :: StorePath -> Property-prop_storePathRoundtrip' x =-  parsePath (storePathRoot x) (storePathToRawFilePath x) === pure x+prop_storePathRoundtrip' :: StoreDir -> StorePath -> Property+prop_storePathRoundtrip' storeDir x =+  parsePath storeDir (storePathToRawFilePath storeDir x) === pure x -prop_storePathRoundtripParser :: NixLike -> NixLike -> Property-prop_storePathRoundtripParser (_ :: NixLike) (NixLike x) =-  Data.Attoparsec.Text.parseOnly (pathParser $ storePathRoot x) (storePathToText x) === pure x+prop_storePathRoundtripParser :: StoreDir -> NixLike -> NixLike -> Property+prop_storePathRoundtripParser storeDir (_ :: NixLike) (NixLike x) =+  Data.Attoparsec.Text.parseOnly (pathParser storeDir) (storePathToText storeDir x) === pure x -prop_storePathRoundtripParser' :: StorePath -> Property-prop_storePathRoundtripParser' x =-  Data.Attoparsec.Text.parseOnly (pathParser $ storePathRoot x) (storePathToText x) === pure x+prop_storePathRoundtripParser' :: StoreDir -> StorePath -> Property+prop_storePathRoundtripParser' storeDir x =+  Data.Attoparsec.Text.parseOnly (pathParser storeDir) (storePathToText storeDir x) === pure x
+ tests/fixtures/case-conflict.nar view

binary file changed (absent → 1000 bytes)