Skip to content

Commit d117cf5

Browse files
committed
Heavy lifting
This refactors the store to make it composable with arbitrary mtl monad stacks, with the added constraint that `addToStore` takes a filtering fucntion `FilePath -> PathFilter -> m Bool` which is not MonadBaseControl compatible, and cannot be lifted (the monad is in a negative/contravariant position). The solution involves a RemoteStoreT transformer, a MonadRemoteStore monad and still lacks a proper generic MonadStore which I would like to make generic across all the store implementations (in-memeory / read-only / remote daemon / etc.)
1 parent aaba7f5 commit d117cf5

File tree

12 files changed

+211
-136
lines changed

12 files changed

+211
-136
lines changed

hnix-store-core/src/System/Nix/Internal/Nar/Effects.hs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
module System.Nix.Internal.Nar.Effects
77
( NarEffects(..)
8+
, PathType(..)
89
, narEffectsIO
910
) where
1011

@@ -18,9 +19,16 @@ import Data.Int (Int64)
1819
import qualified System.Directory as Directory
1920
import qualified System.Directory as Directory
2021
import qualified System.IO as IO
21-
import System.Posix.Files (createSymbolicLink, fileSize,
22-
getFileStatus, isDirectory,
23-
readSymbolicLink)
22+
import System.Posix.Files (createSymbolicLink, fileSize, readSymbolicLink,
23+
getSymbolicLinkStatus, isRegularFile, isDirectory, isSymbolicLink)
24+
25+
data PathType = Regular | Directory | Symlink | Unknown deriving Show
26+
27+
pathTypeFromPosix status
28+
| isRegularFile status = Regular
29+
| isDirectory status = Directory
30+
| isSymbolicLink status = Symlink
31+
| otherwise = Unknown
2432

2533
data NarEffects (m :: * -> *) = NarEffects {
2634
narReadFile :: FilePath -> m BSL.ByteString
@@ -31,8 +39,7 @@ data NarEffects (m :: * -> *) = NarEffects {
3139
, narCreateLink :: FilePath -> FilePath -> m ()
3240
, narGetPerms :: FilePath -> m Directory.Permissions
3341
, narSetPerms :: FilePath -> Directory.Permissions -> m ()
34-
, narIsDir :: FilePath -> m Bool
35-
, narIsSymLink :: FilePath -> m Bool
42+
, narPathType :: FilePath -> m PathType
3643
, narFileSize :: FilePath -> m Int64
3744
, narReadLink :: FilePath -> m FilePath
3845
, narDeleteDir :: FilePath -> m ()
@@ -57,9 +64,8 @@ narEffectsIO = NarEffects {
5764
, narCreateLink = \f t -> IO.liftIO $ createSymbolicLink f t
5865
, narGetPerms = IO.liftIO . Directory.getPermissions
5966
, narSetPerms = \f p -> IO.liftIO $ Directory.setPermissions f p
60-
, narIsDir = \d -> fmap isDirectory $ IO.liftIO (getFileStatus d)
61-
, narIsSymLink = IO.liftIO . Directory.pathIsSymbolicLink
62-
, narFileSize = \n -> fmap (fromIntegral . fileSize) $ IO.liftIO (getFileStatus n)
67+
, narPathType = \f -> fmap pathTypeFromPosix $ IO.liftIO (getSymbolicLinkStatus f)
68+
, narFileSize = \n -> fmap (fromIntegral . fileSize) $ IO.liftIO (getSymbolicLinkStatus n)
6369
, narReadLink = IO.liftIO . readSymbolicLink
6470
, narDeleteDir = IO.liftIO . Directory.removeDirectoryRecursive
6571
, narDeleteFile = IO.liftIO . Directory.removeFile

hnix-store-core/src/System/Nix/Internal/Nar/Parser.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ runParser effs (NarParser action) h target = do
9191

9292
cleanup :: m ()
9393
cleanup = do
94-
isDir <- Nar.narIsDir effs target
95-
if isDir
96-
then Nar.narDeleteDir effs target
97-
else Nar.narDeleteFile effs target
94+
pathType <- Nar.narPathType effs target
95+
case pathType of
96+
Nar.Directory -> Nar.narDeleteDir effs target
97+
_ -> Nar.narDeleteFile effs target
9898

9999

100100
instance Trans.MonadTrans NarParser where

hnix-store-core/src/System/Nix/Internal/Nar/Streamer.hs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
{-# LANGUAGE RankNTypes #-}
55
{-# LANGUAGE ScopedTypeVariables #-}
66
{-# LANGUAGE TypeFamilies #-}
7+
{-# LANGUAGE LambdaCase #-}
78

89
module System.Nix.Internal.Nar.Streamer where
910

@@ -28,26 +29,24 @@ import qualified System.Nix.Internal.Nar.Effects as Nar
2829
streamNarIO
2930
:: forall m.(IO.MonadIO m)
3031
=> (BS.ByteString -> m ())
32+
-> (FilePath -> Nar.PathType -> m Bool)
3133
-> Nar.NarEffects IO
3234
-> FilePath
3335
-> m ()
34-
streamNarIO yield effs basePath = do
36+
streamNarIO yield filter effs basePath = do
3537
yield (str "nix-archive-1")
36-
parens (go basePath)
38+
basePathType <- IO.liftIO $ Nar.narPathType effs basePath
39+
parens (go basePath basePathType)
3740
where
3841

39-
go :: FilePath -> m ()
40-
go path = do
41-
isDir <- IO.liftIO $ Nar.narIsDir effs path
42-
isSymLink <- IO.liftIO $ Nar.narIsSymLink effs path
43-
let isRegular = not (isDir || isSymLink)
44-
45-
when isSymLink $ do
42+
go :: FilePath -> Nar.PathType -> m ()
43+
go path = \case
44+
Nar.Symlink -> do
4645
target <- IO.liftIO $ Nar.narReadLink effs path
4746
yield $
4847
strs ["type", "symlink", "target", BSC.pack target]
4948

50-
when isRegular $ do
49+
Nar.Regular -> do
5150
isExec <- IO.liftIO $ isExecutable effs path
5251
yield $ strs ["type","regular"]
5352
when (isExec == Executable) (yield $ strs ["executable", ""])
@@ -56,15 +55,21 @@ streamNarIO yield effs basePath = do
5655
yield $ int fSize
5756
yieldFile path fSize
5857

59-
when isDir $ do
58+
Nar.Directory -> do
6059
fs <- IO.liftIO (Nar.narListDir effs path)
6160
yield $ strs ["type", "directory"]
6261
forM_ (List.sort fs) $ \f -> do
63-
yield $ str "entry"
64-
parens $ do
65-
let fullName = path </> f
66-
yield (strs ["name", BSC.pack f, "node"])
67-
parens (go fullName)
62+
let fullName = path </> f
63+
pathType <- IO.liftIO $ Nar.narPathType effs fullName
64+
keep <- filter fullName pathType
65+
when keep $ do
66+
yield $ str "entry"
67+
parens $ do
68+
yield (strs ["name", BSC.pack f, "node"])
69+
parens (go fullName pathType)
70+
71+
Nar.Unknown -> do
72+
IO.liftIO $ fail $ "Cannot serialise path " ++ path
6873

6974
str :: BS.ByteString -> BS.ByteString
7075
str t = let len = BS.length t

hnix-store-core/src/System/Nix/Nar.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module System.Nix.Nar (
1818
-- * Encoding and Decoding NAR archives
1919
buildNarIO
2020
, unpackNarIO
21+
, Nar.PathType (..)
2122

2223
-- * Experimental
2324
, Nar.parseNar
@@ -67,7 +68,7 @@ buildNarIO
6768
-> IO.Handle
6869
-> IO ()
6970
buildNarIO effs basePath outHandle = do
70-
Nar.streamNarIO (\chunk -> BS.hPut outHandle chunk >> Concurrent.threadDelay 10) effs basePath
71+
Nar.streamNarIO (\chunk -> BS.hPut outHandle chunk >> Concurrent.threadDelay 10) (\p pt -> pure True) effs basePath
7172

7273

7374
-- | Read NAR formatted bytes from the @IO.Handle@ and unpack them into

hnix-store-core/tests/NarFormat.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import qualified Text.Printf as Printf
5454
import Text.Read (readMaybe)
5555

5656
import qualified System.Nix.Internal.Nar.Streamer as Nar
57-
import System.Nix.Nar
57+
import System.Nix.Nar hiding (PathType(..))
5858

5959

6060

0 commit comments

Comments
 (0)