hascar 0.2.0.2 → 0.2.1.0
raw patch · 3 files changed
+35/−21 lines, 3 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Codec.Archive.SAPCAR: instance GHC.Show.Show Codec.Archive.SAPCAR.CarEntry
- Codec.Archive.SAPCAR: instance GHC.Show.Show Codec.Archive.SAPCAR.SapCarHeader
- Codec.Archive.SAPCAR: type SapCar m a = StateT SapCarFile m a
+ Codec.Archive.SAPCAR: data SapCar s m a
+ Codec.Archive.SAPCAR: instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Codec.Archive.SAPCAR.SapCar s m)
+ Codec.Archive.SAPCAR: instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Codec.Archive.SAPCAR.SapCar s m)
+ Codec.Archive.SAPCAR: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Codec.Archive.SAPCAR.SapCar s m)
+ Codec.Archive.SAPCAR: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Codec.Archive.SAPCAR.SapCar s m)
+ Codec.Archive.SAPCAR: instance GHC.Base.Functor m => GHC.Base.Functor (Codec.Archive.SAPCAR.SapCar s m)
+ Codec.Archive.SAPCAR: instance GHC.Base.Monad m => GHC.Base.Applicative (Codec.Archive.SAPCAR.SapCar s m)
+ Codec.Archive.SAPCAR: instance GHC.Base.Monad m => GHC.Base.Monad (Codec.Archive.SAPCAR.SapCar s m)
+ Codec.Archive.SAPCAR: instance GHC.Show.Show (Codec.Archive.SAPCAR.CarEntry s)
+ Codec.Archive.SAPCAR: instance GHC.Show.Show (Codec.Archive.SAPCAR.SapCarHeader s)
- Codec.Archive.SAPCAR: CarEntry :: !CarFileType -> !Word32 -> !Word32 -> !Word32 -> !Text -> !Int64 -> !Int64 -> CarEntry
+ Codec.Archive.SAPCAR: CarEntry :: !CarFileType -> !Word32 -> !Word32 -> !Word32 -> !Text -> !Int64 -> !Int64 -> CarEntry s
- Codec.Archive.SAPCAR: [cfFileName] :: CarEntry -> !Text
+ Codec.Archive.SAPCAR: [cfFileName] :: CarEntry s -> !Text
- Codec.Archive.SAPCAR: [cfFileOffset] :: CarEntry -> !Int64
+ Codec.Archive.SAPCAR: [cfFileOffset] :: CarEntry s -> !Int64
- Codec.Archive.SAPCAR: [cfFileType] :: CarEntry -> !CarFileType
+ Codec.Archive.SAPCAR: [cfFileType] :: CarEntry s -> !CarFileType
- Codec.Archive.SAPCAR: [cfLength] :: CarEntry -> !Word32
+ Codec.Archive.SAPCAR: [cfLength] :: CarEntry s -> !Word32
- Codec.Archive.SAPCAR: [cfPayloadOffset] :: CarEntry -> !Int64
+ Codec.Archive.SAPCAR: [cfPayloadOffset] :: CarEntry s -> !Int64
- Codec.Archive.SAPCAR: [cfPermissions] :: CarEntry -> !Word32
+ Codec.Archive.SAPCAR: [cfPermissions] :: CarEntry s -> !Word32
- Codec.Archive.SAPCAR: [cfTimestamp] :: CarEntry -> !Word32
+ Codec.Archive.SAPCAR: [cfTimestamp] :: CarEntry s -> !Word32
- Codec.Archive.SAPCAR: carEntryFilename :: CarEntry -> Text
+ Codec.Archive.SAPCAR: carEntryFilename :: CarEntry s -> Text
- Codec.Archive.SAPCAR: data CarEntry
+ Codec.Archive.SAPCAR: data CarEntry s
- Codec.Archive.SAPCAR: getEntries :: MonadIO m => SapCar m [CarEntry]
+ Codec.Archive.SAPCAR: getEntries :: MonadIO m => SapCar s m [CarEntry s]
- Codec.Archive.SAPCAR: sourceEntry :: MonadIO m => CarEntry -> Sink ByteString IO a -> SapCar m a
+ Codec.Archive.SAPCAR: sourceEntry :: MonadIO m => CarEntry s -> Sink ByteString IO a -> SapCar s m a
- Codec.Archive.SAPCAR: withSapCarFile :: (MonadIO m, MonadThrow m, MonadMask m) => FilePath -> SapCar m a -> m a
+ Codec.Archive.SAPCAR: withSapCarFile :: (MonadIO m, MonadThrow m, MonadMask m) => FilePath -> (forall s. SapCar s m a) -> m a
- Codec.Archive.SAPCAR: withSapCarHandle :: (MonadIO m, MonadThrow m, MonadMask m) => SapCar m a -> Handle -> m a
+ Codec.Archive.SAPCAR: withSapCarHandle :: (MonadIO m, MonadThrow m, MonadMask m) => (forall s. SapCar s m a) -> Handle -> m a
- Codec.Archive.SAPCAR: withSapCarPath :: (MonadIO m, MonadThrow m, MonadMask m) => Path b File -> SapCar m a -> m a
+ Codec.Archive.SAPCAR: withSapCarPath :: (MonadIO m, MonadThrow m, MonadMask m) => Path b File -> (forall s. SapCar s m a) -> m a
- Codec.Archive.SAPCAR: writeToFile :: (MonadIO m, MonadMask m, MonadThrow m) => CarEntry -> Path b File -> SapCar m ()
+ Codec.Archive.SAPCAR: writeToFile :: (MonadIO m, MonadMask m, MonadThrow m) => CarEntry s -> Path b File -> SapCar s m ()
- Codec.Archive.SAPCAR: writeToHandle :: (MonadIO m, MonadMask m, MonadThrow m) => CarEntry -> Handle -> SapCar m ()
+ Codec.Archive.SAPCAR: writeToHandle :: (MonadIO m, MonadMask m, MonadThrow m) => CarEntry s -> Handle -> SapCar s m ()
Files
- changelog.md +6/−0
- hascar.cabal +1/−1
- src/Codec/Archive/SAPCAR.hs +28/−20
changelog.md view
@@ -1,3 +1,9 @@+0.2.1.0+-------++- Make "SapCar" a real type instead of a type synonym+- Use the type system to prevent "CarEntry"s to escape the monad+ 0.2.0.0 -------
hascar.cabal view
@@ -1,5 +1,5 @@ name: hascar-version: 0.2.0.2+version: 0.2.1.0 synopsis: Decompress SAPCAR archives description: Decompress SAPCAR archives homepage: https://github.com/VirtualForgeGmbH/hascar
src/Codec/Archive/SAPCAR.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE OverloadedStrings, DeriveFunctor, GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ExistentialQuantification, ImpredicativeTypes #-} -- | -- (De-)compress SAPCAR files --@@ -58,7 +58,15 @@ -- | The SAPCAR monad. All operations on SAPCAR files -- should happen inside this monad.-type SapCar m a = StateT SapCarFile m a+newtype SapCar s m a = SapCar+ { unSapCar :: StateT SapCarFile m a }+ deriving ( Functor+ , Applicative+ , Monad+ , MonadIO+ , MonadThrow+ , MonadCatch+ , MonadMask ) -- | The state during operations inside the SAPCAR monad. data SapCarFile = SapCarFile@@ -67,11 +75,11 @@ } -- | The SAPCAR file header-data SapCarHeader = SapCarHeader+data SapCarHeader s = SapCarHeader { -- | The version string of the SAPCAR archive scVersion :: !Text , -- | Meta information on all files and directories in an archive- scFiles :: ![CarEntry]+ scFiles :: ![CarEntry s] } deriving (Show) -- | The type of an entry in the SAPCAR file@@ -95,7 +103,7 @@ -- | Meta information about a single file or directory -- in a SAPCAR archive-data CarEntry = CarEntry+data CarEntry s = CarEntry { -- | The type of the entry cfFileType :: !CarFileType , -- | The unix style permissions of the entry@@ -112,7 +120,7 @@ cfPayloadOffset :: !Int64 } -instance Show CarEntry where+instance Show (CarEntry s) where show ce = printf "%s%s 0 root root %d\t%s 00:00 %s" (case cfFileType ce of CarFile -> "-" :: Text@@ -150,7 +158,7 @@ perm False w = "-" -- | Get the filename of a car entry-carEntryFilename :: CarEntry -> Text+carEntryFilename :: CarEntry s -> Text carEntryFilename = cfFileName -- | The compression algorithm used@@ -184,7 +192,7 @@ withSapCarPath :: (MonadIO m, MonadThrow m, MonadMask m) => Path b File- -> SapCar m a+ -> (forall s. SapCar s m a) -> m a withSapCarPath sarfile = bracket open close . withSapCarHandle where@@ -195,7 +203,7 @@ withSapCarFile :: (MonadIO m, MonadThrow m, MonadMask m) => FilePath- -> SapCar m a+ -> (forall s. SapCar s m a) -> m a withSapCarFile sarfile = bracket open close . withSapCarHandle where@@ -205,16 +213,16 @@ -- | Run all actions in the SapCar monad. withSapCarHandle :: (MonadIO m, MonadThrow m, MonadMask m)- => SapCar m a+ => (forall s. SapCar s m a) -> Handle -> m a-withSapCarHandle a = evalStateT a . SapCarFile+withSapCarHandle a = evalStateT (unSapCar a) . SapCarFile -- let res = runGet (parseFileHdr >> parseSAPCARFile []) c -- | Get all entries contained inside the SapCar file.-getEntries :: MonadIO m => SapCar m [CarEntry]-getEntries = do+getEntries :: MonadIO m => SapCar s m [CarEntry s]+getEntries = SapCar $ do fh <- sarFileH <$> get let entryParser = runGetIncremental (parseFileHdr >> parseSAPCARFile []) res <- liftIO $ feedChunks entryParser fh@@ -223,8 +231,8 @@ -- | Stream the contents of the given SapCar entry to -- the specified conduit sink.-sourceEntry :: MonadIO m => CarEntry -> Sink S.ByteString IO a -> SapCar m a-sourceEntry entry sink = do+sourceEntry :: MonadIO m => CarEntry s -> Sink S.ByteString IO a -> SapCar s m a+sourceEntry entry sink = SapCar $ do fh <- sarFileH <$> get case cfLength entry of 0 -> liftIO $ emptySource $$ sink@@ -244,7 +252,7 @@ else feedChunks (pushChunk d chunk) h -- | Parse all SAPCAR entries. (tail recursive)-parseSAPCARFile :: [CarEntry] -> Get [CarEntry]+parseSAPCARFile :: [CarEntry s] -> Get [CarEntry s] parseSAPCARFile acc = do empty <- isEmpty if empty@@ -254,7 +262,7 @@ parseSAPCARFile $ entry:acc -- | Write a SapCar entry to the specified file.-writeToFile :: (MonadIO m, MonadMask m, MonadThrow m) => CarEntry -> Path b File -> SapCar m ()+writeToFile :: (MonadIO m, MonadMask m, MonadThrow m) => CarEntry s -> Path b File -> SapCar s m () writeToFile entry path = bracket open close w where open = liftIO $ openBinaryFile (toFilePath path) WriteMode@@ -262,7 +270,7 @@ w = sourceEntry entry . writer -- | Write a SapCar entry to the specified handle.-writeToHandle :: (MonadIO m, MonadMask m, MonadThrow m) => CarEntry -> Handle -> SapCar m ()+writeToHandle :: (MonadIO m, MonadMask m, MonadThrow m) => CarEntry s -> Handle -> SapCar s m () writeToHandle entry = sourceEntry entry . writer -- | Provide a conduit sink, write everything that arrives there to the given handle.@@ -288,7 +296,7 @@ return $ CompHdr len alg' magic spe -- | Parse one SAPCAR entry's metadata, ignoring its contents.-parseEntry :: Get CarEntry+parseEntry :: Get (CarEntry s) parseEntry = do fileOffset <- bytesRead ftype <- getType