Skip to content

Commit 523e490

Browse files
committed
remote: port all operations to GADT based ones
1 parent ddfdb89 commit 523e490

File tree

9 files changed

+280
-469
lines changed

9 files changed

+280
-469
lines changed

hnix-store-remote/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ via `nix-daemon`.
1616

1717
import Control.Monad (void)
1818
import Control.Monad.IO.Class (liftIO)
19+
import System.Nix.StorePath (mkStorePathName)
1920
import System.Nix.Store.Remote
2021

2122
main :: IO ()
@@ -25,6 +26,12 @@ main = do
2526
roots <- findRoots
2627
liftIO $ print roots
2728

28-
res <- addTextToStore "hnix-store" "test" mempty RepairMode_DontRepair
29+
res <- case mkStorePathName "hnix-store" of
30+
Left e -> error (show e)
31+
Right name ->
32+
addTextToStore
33+
(StoreText name "Hello World!")
34+
mempty
35+
RepairMode_DontRepair
2936
liftIO $ print res
3037
```

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ executable remote-readme
156156
buildable: False
157157
build-depends:
158158
base >=4.12 && <5
159+
, hnix-store-core
159160
, hnix-store-remote
160161
build-tool-depends:
161162
markdown-unlit:markdown-unlit
@@ -212,6 +213,7 @@ test-suite remote-io
212213
, hnix-store-core
213214
, hnix-store-nar
214215
, hnix-store-remote
216+
, hnix-store-tests
215217
, bytestring
216218
, containers
217219
, crypton
@@ -221,6 +223,7 @@ test-suite remote-io
221223
, hspec-expectations-lifted
222224
, linux-namespaces
223225
, process
226+
, some
224227
, tasty
225228
, tasty-hspec
226229
, temporary
Lines changed: 5 additions & 325 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,6 @@
1-
{-# LANGUAGE AllowAmbiguousTypes #-}
2-
{-# LANGUAGE LiberalTypeSynonyms #-}
3-
{-# LANGUAGE OverloadedStrings #-}
4-
51
module System.Nix.Store.Remote
62
(
7-
-- * Operations
8-
addToStore
9-
, addTextToStore
10-
, addSignatures
11-
, addIndirectRoot
12-
, addTempRoot
13-
, buildPaths
14-
, deleteSpecific
15-
, ensurePath
16-
, findRoots
17-
, isValidPathUncached
18-
, queryValidPaths
19-
, queryAllValidPaths
20-
, querySubstitutablePaths
21-
, queryPathInfoUncached
22-
, queryReferrers
23-
, queryValidDerivers
24-
, queryDerivationOutputs
25-
, queryDerivationOutputNames
26-
, queryPathFromHashPart
27-
, queryMissing
28-
, optimiseStore
29-
, syncWithGC
30-
, verifyStore
31-
, module System.Nix.Store.Types
3+
module System.Nix.Store.Types
324
, module System.Nix.Store.Remote.Client
335
, module System.Nix.Store.Remote.MonadStore
346
, module System.Nix.Store.Remote.Types
@@ -40,44 +12,17 @@ module System.Nix.Store.Remote
4012
, runStoreOptsTCP
4113
) where
4214

43-
import Crypto.Hash (SHA256)
44-
import Data.ByteString (ByteString)
4515
import Data.Default.Class (Default(def))
46-
import Data.Dependent.Sum (DSum((:=>)))
47-
import Data.HashSet (HashSet)
48-
import Data.Map (Map)
49-
import Data.Text (Text)
50-
import Data.Word (Word64)
5116
import Network.Socket (Family, SockAddr(SockAddrUnix))
52-
import System.Nix.Nar (NarSource)
5317
import System.Nix.Store.Types (FileIngestionMethod(..), RepairMode(..))
54-
import System.Nix.Build (BuildMode)
55-
import System.Nix.Hash (NamedAlgo(..), BaseEncoding(Base16), decodeDigestWith)
56-
import System.Nix.StorePath (StoreDir(..), StorePath, StorePathName, StorePathHashPart, InvalidPathError)
57-
import System.Nix.StorePath.Metadata (Metadata(..), StorePathTrust(..))
18+
import System.Nix.StorePath (StoreDir)
19+
import System.Nix.Store.Remote.MonadStore (RemoteStoreT, getStoreDir, RemoteStoreError(RemoteStoreError_GetAddrInfoFailed))
20+
import System.Nix.Store.Remote.Client
21+
import System.Nix.Store.Remote.Types
5822

59-
import qualified Data.Text
6023
import qualified Control.Exception
61-
import qualified Control.Monad
62-
import qualified Data.Attoparsec.Text
63-
import qualified Data.Text.Encoding
64-
import qualified Data.Map.Strict
65-
import qualified Data.Serialize.Put
66-
import qualified Data.Set
6724
import qualified Network.Socket
6825

69-
import qualified System.Nix.ContentAddress
70-
import qualified System.Nix.Hash
71-
import qualified System.Nix.Signature
72-
import qualified System.Nix.StorePath
73-
74-
import System.Nix.Store.Remote.MonadStore (RemoteStoreT, getStoreDir, RemoteStoreError(RemoteStoreError_GetAddrInfoFailed))
75-
import System.Nix.Store.Remote.Client (Run, runStoreSocket, runOp, runOpArgs, runOpArgsIO, simpleOp, simpleOpArgs)
76-
import System.Nix.Store.Remote.Client (buildDerivation)
77-
import System.Nix.Store.Remote.Socket
78-
import System.Nix.Store.Remote.Types
79-
import System.Nix.Store.Remote.Serialize.Prim
80-
8126
-- * Compat
8227

8328
type MonadStore = RemoteStoreT StoreConfig IO
@@ -139,268 +84,3 @@ runStoreOpts' sockFamily sockAddr storeRootDir code =
13984
{ preStoreConfig_socket = soc
14085
, preStoreConfig_dir = storeRootDir
14186
}
142-
143-
-- * Operations
144-
145-
-- | Pack `Nar` and add it to the store.
146-
addToStore
147-
:: forall a
148-
. (NamedAlgo a)
149-
=> StorePathName -- ^ Name part of the newly created `StorePath`
150-
-> NarSource MonadStore -- ^ provide nar stream
151-
-> FileIngestionMethod -- ^ Add target directory recursively
152-
-> RepairMode -- ^ Only used by local store backend
153-
-> MonadStore StorePath
154-
addToStore name source recursive repair = do
155-
Control.Monad.when (repair == RepairMode_DoRepair)
156-
$ error "repairing is not supported when building through the Nix daemon"
157-
158-
runOpArgsIO WorkerOp_AddToStore $ \yield -> do
159-
yield $ Data.Serialize.Put.runPut $ do
160-
putText $ System.Nix.StorePath.unStorePathName name
161-
putBool
162-
$ not
163-
$ System.Nix.Hash.algoName @a == "sha256"
164-
&& recursive == FileIngestionMethod_FileRecursive
165-
putBool (recursive == FileIngestionMethod_FileRecursive)
166-
putText $ System.Nix.Hash.algoName @a
167-
source yield
168-
sockGetPath
169-
170-
-- | Add text to store.
171-
--
172-
-- Reference accepts repair but only uses it
173-
-- to throw error in case of remote talking to nix-daemon.
174-
addTextToStore
175-
:: Text -- ^ Name of the text
176-
-> Text -- ^ Actual text to add
177-
-> HashSet StorePath -- ^ Set of `StorePath`s that the added text references
178-
-> RepairMode -- ^ Repair mode, must be `RepairMode_DontRepair` for remote backend
179-
-- (only valid for local store)
180-
-> MonadStore StorePath
181-
addTextToStore name text references' repair = do
182-
Control.Monad.when (repair == RepairMode_DoRepair)
183-
$ error "repairing is not supported when building through the Nix daemon"
184-
185-
storeDir <- getStoreDir
186-
runOpArgs WorkerOp_AddTextToStore $ do
187-
putText name
188-
putText text
189-
putPaths storeDir references'
190-
sockGetPath
191-
192-
addSignatures :: StorePath -> [ByteString] -> MonadStore ()
193-
addSignatures p signatures = do
194-
storeDir <- getStoreDir
195-
Control.Monad.void $ simpleOpArgs WorkerOp_AddSignatures $ do
196-
putPath storeDir p
197-
putByteStrings signatures
198-
199-
addIndirectRoot :: StorePath -> MonadStore ()
200-
addIndirectRoot pn = do
201-
storeDir <- getStoreDir
202-
Control.Monad.void $ simpleOpArgs WorkerOp_AddIndirectRoot $ putPath storeDir pn
203-
204-
-- | Add temporary garbage collector root.
205-
--
206-
-- This root is removed as soon as the client exits.
207-
addTempRoot :: StorePath -> MonadStore ()
208-
addTempRoot pn = do
209-
storeDir <- getStoreDir
210-
Control.Monad.void $ simpleOpArgs WorkerOp_AddTempRoot $ putPath storeDir pn
211-
212-
-- | Build paths if they are an actual derivations.
213-
--
214-
-- If derivation output paths are already valid, do nothing.
215-
buildPaths :: HashSet StorePath -> BuildMode -> MonadStore ()
216-
buildPaths ps bm = do
217-
storeDir <- getStoreDir
218-
Control.Monad.void $ simpleOpArgs WorkerOp_BuildPaths $ do
219-
putPaths storeDir ps
220-
putInt $ fromEnum bm
221-
222-
-- | Delete store paths
223-
deleteSpecific
224-
:: HashSet StorePath -- ^ Paths to delete
225-
-> MonadStore GCResult
226-
deleteSpecific paths = do
227-
storeDir <- getStoreDir
228-
runOpArgs WorkerOp_CollectGarbage $ do
229-
putEnum GCAction_DeleteSpecific
230-
putPaths storeDir paths
231-
putBool False -- ignoreLiveness
232-
putInt (maxBound :: Word64) -- maxFreedBytes
233-
putInt (0::Int)
234-
putInt (0::Int)
235-
putInt (0::Int)
236-
getSocketIncremental $ do
237-
gcResultDeletedPaths <- getPathsOrFail storeDir
238-
gcResultBytesFreed <- getInt
239-
-- TODO: obsolete
240-
_ :: Int <- getInt
241-
pure GCResult{..}
242-
243-
ensurePath :: StorePath -> MonadStore ()
244-
ensurePath pn = do
245-
storeDir <- getStoreDir
246-
Control.Monad.void
247-
$ simpleOpArgs WorkerOp_EnsurePath
248-
$ putPath storeDir pn
249-
250-
-- | Find garbage collector roots.
251-
findRoots :: MonadStore (Map ByteString StorePath)
252-
findRoots = do
253-
runOp WorkerOp_FindRoots
254-
sd <- getStoreDir
255-
res <-
256-
getSocketIncremental
257-
$ getMany
258-
$ (,)
259-
<$> getByteString
260-
<*> getPath sd
261-
262-
r <- catRights res
263-
pure $ Data.Map.Strict.fromList r
264-
where
265-
catRights :: [(a, Either InvalidPathError b)] -> MonadStore [(a, b)]
266-
catRights = mapM ex
267-
268-
ex :: (a, Either InvalidPathError b) -> MonadStore (a, b)
269-
ex (x , Right y) = pure (x, y)
270-
ex (_x, Left e ) = error $ "Unable to decode root: " <> show e
271-
272-
isValidPathUncached :: StorePath -> MonadStore Bool
273-
isValidPathUncached p = do
274-
storeDir <- getStoreDir
275-
simpleOpArgs WorkerOp_IsValidPath $ putPath storeDir p
276-
277-
-- | Query valid paths from set, optionally try to use substitutes.
278-
queryValidPaths
279-
:: HashSet StorePath -- ^ Set of `StorePath`s to query
280-
-> SubstituteMode -- ^ Try substituting missing paths when `True`
281-
-> MonadStore (HashSet StorePath)
282-
queryValidPaths ps substitute = do
283-
storeDir <- getStoreDir
284-
runOpArgs WorkerOp_QueryValidPaths $ do
285-
putPaths storeDir ps
286-
putBool $ substitute == SubstituteMode_DoSubstitute
287-
sockGetPaths
288-
289-
queryAllValidPaths :: MonadStore (HashSet StorePath)
290-
queryAllValidPaths = do
291-
runOp WorkerOp_QueryAllValidPaths
292-
sockGetPaths
293-
294-
querySubstitutablePaths :: HashSet StorePath -> MonadStore (HashSet StorePath)
295-
querySubstitutablePaths ps = do
296-
storeDir <- getStoreDir
297-
runOpArgs WorkerOp_QuerySubstitutablePaths $ putPaths storeDir ps
298-
sockGetPaths
299-
300-
queryPathInfoUncached :: StorePath -> MonadStore (Metadata StorePath)
301-
queryPathInfoUncached path = do
302-
storeDir <- getStoreDir
303-
runOpArgs WorkerOp_QueryPathInfo $ do
304-
putPath storeDir path
305-
306-
valid <- sockGetBool
307-
Control.Monad.unless valid $ error "Path is not valid"
308-
309-
metadataDeriverPath <- sockGetPathMay
310-
311-
narHashText <- Data.Text.Encoding.decodeUtf8 <$> sockGetStr
312-
let
313-
metadataNarHash =
314-
case
315-
decodeDigestWith @SHA256 Base16 narHashText
316-
of
317-
Left e -> error e
318-
Right d -> System.Nix.Hash.HashAlgo_SHA256 :=> d
319-
320-
metadataReferences <- sockGetPaths
321-
metadataRegistrationTime <- sockGet getTime
322-
metadataNarBytes <- Just <$> sockGetInt
323-
ultimate <- sockGetBool
324-
325-
sigStrings <- fmap Data.Text.Encoding.decodeUtf8 <$> sockGetStrings
326-
caString <- Data.Text.Encoding.decodeUtf8 <$> sockGetStr
327-
328-
let
329-
metadataSigs = case
330-
Data.Set.fromList
331-
<$> mapM System.Nix.Signature.parseNarSignature sigStrings
332-
of
333-
Left e -> error e
334-
Right x -> x
335-
336-
metadataContentAddress =
337-
if Data.Text.null caString then Nothing else
338-
case
339-
Data.Attoparsec.Text.parseOnly
340-
System.Nix.ContentAddress.contentAddressParser
341-
caString
342-
of
343-
Left e -> error e
344-
Right x -> Just x
345-
346-
metadataTrust = if ultimate then BuiltLocally else BuiltElsewhere
347-
348-
pure $ Metadata{..}
349-
350-
queryReferrers :: StorePath -> MonadStore (HashSet StorePath)
351-
queryReferrers p = do
352-
storeDir <- getStoreDir
353-
runOpArgs WorkerOp_QueryReferrers $ putPath storeDir p
354-
sockGetPaths
355-
356-
queryValidDerivers :: StorePath -> MonadStore (HashSet StorePath)
357-
queryValidDerivers p = do
358-
storeDir <- getStoreDir
359-
runOpArgs WorkerOp_QueryValidDerivers $ putPath storeDir p
360-
sockGetPaths
361-
362-
queryDerivationOutputs :: StorePath -> MonadStore (HashSet StorePath)
363-
queryDerivationOutputs p = do
364-
storeDir <- getStoreDir
365-
runOpArgs WorkerOp_QueryDerivationOutputs $ putPath storeDir p
366-
sockGetPaths
367-
368-
queryDerivationOutputNames :: StorePath -> MonadStore (HashSet StorePath)
369-
queryDerivationOutputNames p = do
370-
storeDir <- getStoreDir
371-
runOpArgs WorkerOp_QueryDerivationOutputNames $ putPath storeDir p
372-
sockGetPaths
373-
374-
queryPathFromHashPart :: StorePathHashPart -> MonadStore StorePath
375-
queryPathFromHashPart storePathHash = do
376-
runOpArgs WorkerOp_QueryPathFromHashPart
377-
$ putText
378-
$ System.Nix.StorePath.storePathHashPartToText storePathHash
379-
sockGetPath
380-
381-
queryMissing
382-
:: (HashSet StorePath)
383-
-> MonadStore Missing
384-
queryMissing ps = do
385-
storeDir <- getStoreDir
386-
runOpArgs WorkerOp_QueryMissing $ putPaths storeDir ps
387-
388-
missingWillBuild <- sockGetPaths
389-
missingWillSubstitute <- sockGetPaths
390-
missingUnknownPaths <- sockGetPaths
391-
missingDownloadSize <- sockGetInt
392-
missingNarSize <- sockGetInt
393-
394-
pure Missing{..}
395-
396-
optimiseStore :: MonadStore ()
397-
optimiseStore = Control.Monad.void $ simpleOp WorkerOp_OptimiseStore
398-
399-
syncWithGC :: MonadStore ()
400-
syncWithGC = Control.Monad.void $ simpleOp WorkerOp_SyncWithGC
401-
402-
-- returns True on errors
403-
verifyStore :: CheckMode -> RepairMode -> MonadStore Bool
404-
verifyStore check repair = simpleOpArgs WorkerOp_VerifyStore $ do
405-
putBool $ check == CheckMode_DoCheck
406-
putBool $ repair == RepairMode_DoRepair

0 commit comments

Comments
 (0)