3
3
{-# language ScopedTypeVariables #-}
4
4
5
5
module System.Nix.Internal.Nar.Streamer
6
- ( streamNarIO
6
+ ( NarSource
7
+ , dumpString
8
+ , dumpPath
9
+ , streamNarIO
7
10
, IsExecutable (.. )
8
11
)
9
12
where
@@ -19,22 +22,43 @@ import System.FilePath ( (</>) )
19
22
import qualified System.Nix.Internal.Nar.Effects as Nar
20
23
21
24
25
+ -- | NarSource
26
+ -- The source to provide nar to the handler `(ByteString -> m ())`.
27
+ -- It is isomorphic to ByteString by Yoneda lemma
28
+ -- if the result is meant to be m ().
29
+ -- It is done in CPS style so IO can be chunks.
30
+ type NarSource m = (ByteString -> m () ) -> m ()
31
+
32
+
33
+ -- | dumpString
34
+ -- dump a string to nar in CPS style. The function takes in a `ByteString`,
35
+ -- and build a `NarSource m`.
36
+ dumpString
37
+ :: forall m . IO. MonadIO m
38
+ => ByteString -- ^ the string you want to dump
39
+ -> NarSource m -- ^ The nar result in CPS style
40
+ dumpString text yield = traverse_ (yield . str)
41
+ [" nix-archive-1" , " (" , " type" , " regular" , " contents" , text, " )" ]
42
+
43
+
44
+ -- | dumpPath
45
+ -- shorthand
46
+ -- build a Source that turn file path to nar using the default narEffectsIO.
47
+ dumpPath
48
+ :: forall m . IO. MonadIO m
49
+ => FilePath -- ^ path for the file you want to dump to nar
50
+ -> NarSource m -- ^ the nar result in CPS style
51
+ dumpPath = streamNarIO Nar. narEffectsIO
52
+
53
+
22
54
-- | This implementation of Nar encoding takes an arbitrary @yield@
23
55
-- function from any streaming library, and repeatedly calls
24
56
-- it while traversing the filesystem object to Nar encode
25
- streamNarIO
26
- :: forall m
27
- . (IO. MonadIO m )
28
- => (ByteString -> m () )
29
- -> Nar. NarEffects IO
30
- -> FilePath
31
- -> m ()
32
- streamNarIO yield effs basePath = do
57
+ streamNarIO :: forall m . IO. MonadIO m => Nar. NarEffects IO -> FilePath -> NarSource m
58
+ streamNarIO effs basePath yield = do
33
59
yield $ str " nix-archive-1"
34
60
parens $ go basePath
35
-
36
61
where
37
-
38
62
go :: FilePath -> m ()
39
63
go path = do
40
64
isDir <- IO. liftIO $ Nar. narIsDir effs path
@@ -65,16 +89,6 @@ streamNarIO yield effs basePath = do
65
89
yield $ strs [" name" , Bytes.Char8. pack f, " node" ]
66
90
parens $ go fullName
67
91
68
- str :: ByteString -> ByteString
69
- str t =
70
- let
71
- len = Bytes. length t
72
- in
73
- int len <> padBS len t
74
-
75
- padBS :: Int -> ByteString -> ByteString
76
- padBS strSize bs = bs <> Bytes. replicate (padLen strSize) 0
77
-
78
92
parens act = do
79
93
yield $ str " ("
80
94
r <- act
@@ -87,13 +101,6 @@ streamNarIO yield effs basePath = do
87
101
mapM_ yield . Bytes.Lazy. toChunks =<< IO. liftIO (Bytes.Lazy. readFile path)
88
102
yield $ Bytes. replicate (padLen $ fromIntegral fsize) 0
89
103
90
- strs :: [ByteString ] -> ByteString
91
- strs xs = Bytes. concat $ str <$> xs
92
-
93
- int :: Integral a => a -> ByteString
94
- int n = Serial. runPut $ Serial. putInt64le $ fromIntegral n
95
-
96
-
97
104
data IsExecutable = NonExecutable | Executable
98
105
deriving (Eq , Show )
99
106
@@ -107,3 +114,19 @@ isExecutable effs fp =
107
114
-- | Distance to the next multiple of 8
108
115
padLen :: Int -> Int
109
116
padLen n = (8 - n) `mod` 8
117
+
118
+ int :: Integral a => a -> ByteString
119
+ int n = Serial. runPut $ Serial. putInt64le $ fromIntegral n
120
+
121
+ str :: ByteString -> ByteString
122
+ str t =
123
+ let
124
+ len = Bytes. length t
125
+ in
126
+ int len <> padBS len t
127
+
128
+ padBS :: Int -> ByteString -> ByteString
129
+ padBS strSize bs = bs <> Bytes. replicate (padLen strSize) 0
130
+
131
+ strs :: [ByteString ] -> ByteString
132
+ strs xs = Bytes. concat $ str <$> xs
0 commit comments