Skip to content

Commit df62048

Browse files
committed
remote: use proper paths, add nix-derivation support, add tests
1 parent 1fe1237 commit df62048

File tree

6 files changed

+318
-108
lines changed

6 files changed

+318
-108
lines changed

hnix-store-remote/hnix-store-remote.cabal

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,14 @@ library
2727
, bytestring
2828
, containers
2929
, text
30+
, time
3031
, unix
3132
, network
3233
, mtl
34+
, nix-derivation
35+
, system-filepath
3336
, unordered-containers
34-
-- , pretty-simple
35-
-- , base16-bytestring
36-
-- , base32-bytestring
37+
, vector
3738
, hnix-store-core
3839
hs-source-dirs: src
3940
default-language: Haskell2010
@@ -48,4 +49,42 @@ executable hnix-store-temporary-live-test
4849
, hnix-store-core
4950
, hnix-store-remote
5051
, unordered-containers
52+
, nix-derivation
53+
, attoparsec
54+
, text
5155
, pretty-simple
56+
57+
test-suite hnix-store-remote-tests
58+
ghc-options: -rtsopts -fprof-auto
59+
type: exitcode-stdio-1.0
60+
main-is: Driver.hs
61+
other-modules:
62+
NixDaemon
63+
hs-source-dirs: tests
64+
build-depends:
65+
attoparsec
66+
, nix-derivation
67+
, hnix-store-core
68+
, hnix-store-remote
69+
, base
70+
, base64-bytestring
71+
, binary
72+
, bytestring
73+
, containers
74+
, directory
75+
, process
76+
, system-filepath
77+
, hspec-expectations-lifted
78+
, tasty
79+
, tasty-discover
80+
, tasty-hspec
81+
, tasty-hunit
82+
, tasty-quickcheck
83+
, linux-namespaces
84+
, temporary
85+
, text
86+
, time
87+
, unix
88+
, unordered-containers
89+
, vector
90+
default-language: Haskell2010

hnix-store-remote/src/System/Nix/Store/Remote.hs

Lines changed: 116 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
{-# LANGUAGE OverloadedStrings #-}
55
{-# LANGUAGE RankNTypes #-}
66
{-# LANGUAGE ScopedTypeVariables #-}
7+
{-# LANGUAGE DataKinds #-}
78
{-# LANGUAGE TypeApplications #-}
9+
{-# LANGUAGE RecordWildCards #-}
810
module System.Nix.Store.Remote (
911
runStore
1012
, isValidPathUncached
@@ -43,17 +45,20 @@ import Data.Maybe
4345
import qualified Data.ByteString.Lazy as LBS
4446
import qualified Data.Map.Strict as M
4547
import Data.Proxy (Proxy(Proxy))
48+
import Data.Text (Text)
4649
import qualified Data.Text.Lazy as T
4750
import qualified Data.Text.Lazy.Encoding as T
4851

4952
import qualified System.Nix.Build as Build
50-
import qualified System.Nix.Derivation as Drv
53+
import qualified Nix.Derivation as Drv
54+
5155
import qualified System.Nix.GC as GC
5256
import System.Nix.Hash (Digest, HashAlgorithm)
5357
import System.Nix.Path
5458
import System.Nix.Hash
55-
import System.Nix.Nar (localPackNar, putNar, narEffectsIO)
59+
import System.Nix.Nar (localPackNar, putNar, narEffectsIO, Nar)
5660
import System.Nix.Util
61+
import System.Nix.ValidPath
5762

5863
import System.Nix.Store.Remote.Types
5964
import System.Nix.Store.Remote.Protocol
@@ -70,12 +75,15 @@ type SubstituteFlag = Bool
7075
--setOptions :: StoreSetting -> MonadStore ()
7176

7277
isValidPathUncached :: Path -> MonadStore Bool
73-
isValidPathUncached p = simpleOpArgs IsValidPath $ putPath p
78+
isValidPathUncached p = do
79+
sd <- getStoreDir
80+
simpleOpArgs IsValidPath $ putPath sd p
7481

7582
queryValidPaths :: PathSet -> SubstituteFlag -> MonadStore PathSet
7683
queryValidPaths ps substitute = do
84+
sd <- getStoreDir
7785
runOpArgs QueryValidPaths $ do
78-
putPaths ps
86+
putPaths sd ps
7987
putBool substitute
8088
sockGetPaths
8189

@@ -86,14 +94,16 @@ queryAllValidPaths = do
8694

8795
querySubstitutablePaths :: PathSet -> MonadStore PathSet
8896
querySubstitutablePaths ps = do
97+
sd <- getStoreDir
8998
runOpArgs QuerySubstitutablePaths $ do
90-
putPaths ps
99+
putPaths sd ps
91100
sockGetPaths
92101

93102
querySubstitutablePathInfos :: PathSet -> MonadStore [SubstitutablePathInfo]
94103
querySubstitutablePathInfos ps = do
104+
sd <- getStoreDir
95105
runOpArgs QuerySubstitutablePathInfos $ do
96-
putPaths ps
106+
putPaths sd ps
97107

98108
cnt <- sockGetInt
99109
forM (take cnt $ cycle [(0 :: Int)]) $ pure $ do
@@ -109,71 +119,80 @@ querySubstitutablePathInfos ps = do
109119
, narSize = narSize'
110120
}
111121

112-
queryPathInfoUncached :: Path -> MonadStore ValidPathInfo
113-
queryPathInfoUncached p = do
122+
queryPathInfoUncached :: Path -> MonadStore ValidPath
123+
queryPathInfoUncached path = do
124+
sd <- getStoreDir
114125
runOpArgs QueryPathInfo $ do
115-
putPath p
126+
putPath sd path
116127

117128
valid <- sockGetBool
118129
unless valid $ error "Path is not valid"
119130

120-
drv <- sockGetStr
121-
hash' <- lBSToText <$> sockGetStr
122-
refs <- sockGetPaths
123-
regTime <- sockGetInt
124-
size <- sockGetInt
125-
ulti <- sockGetBool
126-
sigs' <- map lBSToText <$> sockGetStrings
127-
ca' <- lBSToText <$> sockGetStr
128-
return $ ValidPathInfo {
129-
path = p
130-
, deriverVP = mkPath drv
131-
, narHash = hash'
132-
, referencesVP = refs
133-
, registrationTime = regTime
134-
, narSizeVP = size
135-
, ultimate = ulti
136-
, sigs = sigs'
137-
, ca = ca'
138-
}
131+
deriver <- mkPath <$> sockGetStr
132+
narHash <- lBSToText <$> sockGetStr
133+
references <- sockGetPaths
134+
registrationTime <- sockGet getTime
135+
narSize <- sockGetInt
136+
ultimate <- sockGetBool
137+
sigs <- map lBSToText <$> sockGetStrings
138+
ca <- lBSToText <$> sockGetStr
139+
return $ ValidPath {..}
139140

140141
queryReferrers :: Path -> MonadStore PathSet
141142
queryReferrers p = do
143+
sd <- getStoreDir
142144
runOpArgs QueryReferrers $ do
143-
putPath p
145+
putPath sd p
144146
sockGetPaths
145147

146148
queryValidDerivers :: Path -> MonadStore PathSet
147149
queryValidDerivers p = do
150+
sd <- getStoreDir
148151
runOpArgs QueryValidDerivers $ do
149-
putPath p
152+
putPath sd p
150153
sockGetPaths
151154

152155
queryDerivationOutputs :: Path -> MonadStore PathSet
153156
queryDerivationOutputs p = do
157+
sd <- getStoreDir
154158
runOpArgs QueryDerivationOutputs $
155-
putPath p
159+
putPath sd p
156160
sockGetPaths
157161

158162
queryDerivationOutputNames :: Path -> MonadStore PathSet
159163
queryDerivationOutputNames p = do
164+
sd <- getStoreDir
160165
runOpArgs QueryDerivationOutputNames $
161-
putPath p
166+
putPath sd p
162167
sockGetPaths
163168

164-
-- XXX: this is broken as I don't know how to get hashes from paths (fix mkPath)
165169
queryPathFromHashPart :: Digest PathHashAlgo -> MonadStore (Maybe Path)
166-
queryPathFromHashPart d = do
170+
queryPathFromHashPart digest = do
167171
runOpArgs QueryPathFromHashPart $
168-
-- TODO: replace `undefined` with digest encoding function when
169-
-- [issue 24](https://github.com/haskell-nix/hnix-store/issues/24) is
170-
-- closed
171-
putByteStringLen $ LBS.fromStrict $ undefined d
172+
putText $ printAsBase32 @PathHashAlgo digest
172173
sockGetPath
173174

174-
type Source = () -- abstract binary source
175-
addToStoreNar :: ValidPathInfo -> Source -> RepairFlag -> CheckSigsFlag -> MonadStore ()
176-
addToStoreNar = undefined -- XXX
175+
addToStoreNar :: ValidPath -> Nar -> RepairFlag -> CheckSigsFlag -> MonadStore ()
176+
addToStoreNar ValidPath{..} nar repair checkSigs = do
177+
sd <- getStoreDir
178+
void $ runOpArgs AddToStoreNar $ do
179+
putPath sd path
180+
maybe (return ()) (putPath sd) deriver
181+
putText narHash -- info.narHash.to_string(Base16, false)
182+
putPaths sd references
183+
putTime registrationTime
184+
putInt narSize
185+
putBool ultimate
186+
putTexts sigs
187+
putText ca
188+
189+
-- << repair << !checkSigs;
190+
putBool repair
191+
putBool (not checkSigs)
192+
193+
-- reference uses copyNAR here to just parse & dump existing NAR from path
194+
-- TUNNEL
195+
-- putNar nar
177196

178197
printHashType :: HashAlgorithm' Integer -> T.Text
179198
printHashType MD5 = "MD5"
@@ -212,31 +231,50 @@ addToStore name pth recursive algoProxy pfilter repair = do
212231

213232
fmap (fromMaybe $ error "TODO: Error") sockGetPath
214233

215-
216-
addTextToStore :: LBS.ByteString -> LBS.ByteString -> PathSet -> RepairFlag -> MonadStore (Maybe Path)
234+
-- reference accepts repair but only uses it to throw error in case of nix daemon
235+
addTextToStore :: Text -> Text -> PathSet -> RepairFlag -> MonadStore (Maybe Path)
217236
addTextToStore name text references' repair = do
237+
when repair $ error "repairing is not supported when building through the Nix daemon"
238+
sd <- getStoreDir
218239
runOpArgs AddTextToStore $ do
219-
putByteStringLen name
220-
putByteStringLen text
221-
putPaths references'
240+
putText name
241+
putText text
242+
putPaths sd references'
222243
sockGetPath
223244

224245
buildPaths :: PathSet -> Build.BuildMode -> MonadStore ()
225-
buildPaths ps bm = void $ simpleOpArgs EnsurePath $ do
226-
putPaths ps
227-
putInt $ fromEnum bm
228-
229-
buildDerivation :: PathName -> Drv.Derivation -> Build.BuildMode -> MonadStore Build.BuildResult
230-
buildDerivation = undefined -- XXX
246+
buildPaths ps bm = do
247+
sd <- getStoreDir
248+
void $ simpleOpArgs BuildPaths $ do
249+
putPaths sd ps
250+
putInt $ fromEnum bm
251+
252+
buildDerivation :: Path -> Drv.Derivation -> Build.BuildMode -> MonadStore Build.BuildResult
253+
buildDerivation p drv buildMode = do
254+
sd <- getStoreDir
255+
runOpArgs BuildDerivation $ do
256+
putPath sd p
257+
putDerivation drv
258+
putEnum buildMode
259+
putInt 0 -- ??????
260+
261+
res <- getSocketIncremental $ getBuildResult
262+
return res
231263

232264
ensurePath :: Path -> MonadStore ()
233-
ensurePath pn = void $ simpleOpArgs EnsurePath $ putPath pn
265+
ensurePath pn = do
266+
sd <- getStoreDir
267+
void $ simpleOpArgs EnsurePath $ putPath sd pn
234268

235269
addTempRoot :: Path -> MonadStore ()
236-
addTempRoot pn = void $ simpleOpArgs AddTempRoot $ putPath pn
270+
addTempRoot pn = do
271+
sd <- getStoreDir
272+
void $ simpleOpArgs AddTempRoot $ putPath sd pn
237273

238274
addIndirectRoot :: Path -> MonadStore ()
239-
addIndirectRoot pn = void $ simpleOpArgs AddIndirectRoot $ putPath pn
275+
addIndirectRoot pn = do
276+
sd <- getStoreDir
277+
void $ simpleOpArgs AddIndirectRoot $ putPath sd pn
240278

241279
syncWithGC :: MonadStore ()
242280
syncWithGC = void $ simpleOp SyncWithGC
@@ -257,12 +295,15 @@ findRoots = do
257295

258296
collectGarbage :: GC.Options -> MonadStore GC.Result
259297
collectGarbage opts = do
298+
sd <- getStoreDir
260299
runOpArgs CollectGarbage $ do
261300
putInt $ fromEnum $ GC.operation opts
262-
putPaths $ GC.pathsToDelete opts
301+
putPaths sd $ GC.pathsToDelete opts
263302
putBool $ GC.ignoreLiveness opts
264303
putInt $ GC.maxFreed opts
265-
forM_ [(0 :: Int)..2] $ pure $ putInt (0 :: Int) -- removed options
304+
-- removed options
305+
-- drop when collectGarbage drops these from nix/src/libstore/remote-store.cc
306+
forM_ [(0 :: Int)..2] $ pure $ putInt (0 :: Int)
266307

267308
paths <- sockGetPaths
268309
freed <- sockGetInt
@@ -273,19 +314,28 @@ collectGarbage opts = do
273314
optimiseStore :: MonadStore ()
274315
optimiseStore = void $ simpleOp OptimiseStore
275316

317+
queryMissing :: PathSet -> MonadStore (PathSet, PathSet, PathSet, Integer, Integer)
318+
queryMissing ps = do
319+
sd <- getStoreDir
320+
runOpArgs QueryMissing $ do
321+
putPaths sd ps
322+
323+
willBuild <- sockGetPaths
324+
willSubstitute <- sockGetPaths
325+
unknown <- sockGetPaths
326+
downloadSize' <- sockGetInt
327+
narSize' <- sockGetInt
328+
return (willBuild, willSubstitute, unknown, downloadSize', narSize')
329+
276330
-- returns True on errors
277331
verifyStore :: CheckFlag -> RepairFlag -> MonadStore Bool
278332
verifyStore check repair = simpleOpArgs VerifyStore $ do
279333
putBool check
280334
putBool repair
281335

282336
addSignatures :: Path -> [LBS.ByteString] -> MonadStore ()
283-
addSignatures p signatures = void $ simpleOpArgs AddSignatures $ do
284-
putPath p
285-
putByteStrings signatures
286-
287-
-- TODO:
288-
queryMissing :: PathSet -> MonadStore (PathSet, PathSet, PathSet, Integer, Integer)
289-
queryMissing ps = undefined -- willBuild willSubstitute unknown downloadSize narSize
290-
291-
337+
addSignatures p signatures = do
338+
sd <- getStoreDir
339+
void $ simpleOpArgs AddSignatures $ do
340+
putPath sd p
341+
putByteStrings signatures

0 commit comments

Comments
 (0)