Skip to content

Commit 3bba554

Browse files
layusAnton-Latukha
authored andcommitted
Implement derivationStrict primOp
1 parent 9bcfbbe commit 3bba554

File tree

6 files changed

+453
-80
lines changed

6 files changed

+453
-80
lines changed

hnix.cabal

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ library
341341
Nix.Convert
342342
Nix.Effects
343343
Nix.Effects.Basic
344+
Nix.Effects.Derivation
344345
Nix.Eval
345346
Nix.Exec
346347
Nix.Expr
@@ -401,8 +402,9 @@ library
401402
, gitrev >= 1.1.0 && < 1.4
402403
, hashable >= 1.2.5 && < 1.4
403404
, hashing >= 0.1.0 && < 0.2
404-
, hnix-store-core >= 0.1.0 && < 0.3
405-
, http-client >= 0.5.14 && < 0.6 || >= 0.6.4 && < 0.8
405+
, hnix-store-core >= 0.3.0 && < 0.4
406+
, hnix-store-remote >= 0.2.0 && < 0.3
407+
, http-client >= 0.5.14 && < 0.6 || >= 0.6.4 && < 0.7
406408
, http-client-tls >= 0.3.5 && < 0.4
407409
, http-types >= 0.12.2 && < 0.13
408410
, lens-family >= 1.2.2 && < 2.2

src/Nix/Effects.hs

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
{-# LANGUAGE MultiParamTypeClasses #-}
88
{-# LANGUAGE OverloadedStrings #-}
99
{-# LANGUAGE TypeFamilies #-}
10+
{-# LANGUAGE DataKinds #-}
11+
{-# LANGUAGE TypeApplications #-}
1012

1113
module Nix.Effects where
1214

@@ -17,24 +19,31 @@ import Prelude hiding ( putStr
1719
import qualified Prelude
1820

1921
import Control.Monad.Trans
22+
import qualified Data.HashSet as HS
2023
import Data.Text ( Text )
2124
import qualified Data.Text as T
22-
import Network.HTTP.Client hiding ( path )
25+
import qualified Data.Text.Encoding as T
26+
import Network.HTTP.Client hiding ( path, Proxy )
2327
import Network.HTTP.Client.TLS
2428
import Network.HTTP.Types
2529
import Nix.Expr
26-
import Nix.Frames
30+
import Nix.Frames hiding ( Proxy )
2731
import Nix.Parser
2832
import Nix.Render
2933
import Nix.Utils
3034
import Nix.Value
3135
import qualified Paths_hnix
32-
import qualified System.Directory as S
3336
import System.Environment
3437
import System.Exit
38+
import System.FilePath ( takeFileName )
3539
import qualified System.Info
3640
import System.Process
3741

42+
import qualified System.Nix.Hash as Store
43+
import qualified System.Nix.Store.Remote as Store
44+
import qualified System.Nix.Store.Remote.Types as Store
45+
import qualified System.Nix.StorePath as Store
46+
3847
-- | A path into the nix store
3948
newtype StorePath = StorePath { unStorePath :: FilePath }
4049

@@ -226,36 +235,54 @@ print = putStrLn . show
226235
instance MonadPutStr IO where
227236
putStr = Prelude.putStr
228237

238+
239+
type RecursiveFlag = Bool
240+
type RepairFlag = Bool
241+
type StorePathName = Text
242+
type FilePathFilter m = FilePath -> m Bool
243+
type StorePathSet = HS.HashSet StorePath
244+
229245
class Monad m => MonadStore m where
230-
-- | Import a path into the nix store, and return the resulting path
231-
addPath' :: FilePath -> m (Either ErrorCall StorePath)
232246

233-
-- | Add a file with the given name and contents to the nix store
234-
toFile_' :: FilePath -> String -> m (Either ErrorCall StorePath)
247+
-- | Add a path to the store, with bells and whistles
248+
addToStore :: StorePathName -> FilePath -> RecursiveFlag -> RepairFlag -> m (Either ErrorCall StorePath)
249+
default addToStore :: (MonadTrans t, MonadStore m', m ~ t m') => StorePathName -> FilePath -> RecursiveFlag -> RepairFlag -> m (Either ErrorCall StorePath)
250+
addToStore a b c d = lift $ addToStore a b c d
251+
252+
-- | Add a nar (action) to the store
253+
-- addToStore' :: StorePathName -> IO Nar -> RecursiveFlag -> RepairFlag -> m (Either ErrorCall StorePath)
254+
255+
addTextToStore' :: StorePathName -> Text -> Store.StorePathSet -> RepairFlag -> m (Either ErrorCall StorePath)
256+
default addTextToStore' :: (MonadTrans t, MonadStore m', m ~ t m') => StorePathName -> Text -> Store.StorePathSet -> RepairFlag -> m (Either ErrorCall StorePath)
257+
addTextToStore' a b c d = lift $ addTextToStore' a b c d
258+
259+
parseStoreResult :: Monad m => String -> (Either String a, [Store.Logger]) -> m (Either ErrorCall a)
260+
parseStoreResult name res = case res of
261+
(Left msg, logs) -> return $ Left $ ErrorCall $ "Failed to execute '" ++ name ++ "': " ++ msg ++ "\n" ++ show logs
262+
(Right result, _) -> return $ Right result
235263

236264
instance MonadStore IO where
237-
addPath' path = do
238-
(exitCode, out, _) <- readProcessWithExitCode "nix-store" ["--add", path] ""
239-
case exitCode of
240-
ExitSuccess -> do
241-
let dropTrailingLinefeed p = take (length p - 1) p
242-
pure $ Right $ StorePath $ dropTrailingLinefeed out
243-
_ ->
244-
pure
245-
$ Left
246-
$ ErrorCall
247-
$ "addPath: failed: nix-store --add "
248-
++ show path
249265

250-
--TODO: Use a temp directory so we don't overwrite anything important
251-
toFile_' filepath content = do
252-
writeFile filepath content
253-
storepath <- addPath' filepath
254-
S.removeFile filepath
255-
pure storepath
266+
addToStore name path recursive repair = case Store.makeStorePathName name of
267+
Left err -> return $ Left $ ErrorCall $ "String '" ++ show name ++ "' is not a valid path name: " ++ err
268+
Right pathName -> do
269+
-- TODO: redesign the filter parameter
270+
res <- Store.runStore $ Store.addToStore @'Store.SHA256 pathName path recursive (const False) repair
271+
parseStoreResult "addToStore" res >>= \case
272+
Left err -> return $ Left err
273+
Right storePath -> return $ Right $ StorePath $ T.unpack $ T.decodeUtf8 $ Store.storePathToRawFilePath storePath
274+
275+
addTextToStore' name text references repair = do
276+
res <- Store.runStore $ Store.addTextToStore name text references repair
277+
parseStoreResult "addTextToStore" res >>= \case
278+
Left err -> return $ Left err
279+
Right path -> return $ Right $ StorePath $ T.unpack $ T.decodeUtf8 $ Store.storePathToRawFilePath path
280+
281+
addTextToStore :: (Framed e m, MonadStore m) => StorePathName -> Text -> Store.StorePathSet -> RepairFlag -> m StorePath
282+
addTextToStore a b c d = either throwError return =<< addTextToStore' a b c d
256283

257284
addPath :: (Framed e m, MonadStore m) => FilePath -> m StorePath
258-
addPath p = either throwError pure =<< addPath' p
285+
addPath p = either throwError return =<< addToStore (T.pack $ takeFileName p) p True False
259286

260287
toFile_ :: (Framed e m, MonadStore m) => FilePath -> String -> m StorePath
261-
toFile_ p contents = either throwError pure =<< toFile_' p contents
288+
toFile_ p contents = addTextToStore (T.pack p) (T.pack contents) HS.empty False

src/Nix/Effects/Basic.hs

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88
{-# LANGUAGE TypeApplications #-}
99
{-# LANGUAGE ViewPatterns #-}
1010

11-
{-# OPTIONS_GHC -Wno-missing-signatures #-}
12-
{-# OPTIONS_GHC -Wno-orphans #-}
13-
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
14-
1511
module Nix.Effects.Basic where
1612

1713
import Control.Monad
@@ -20,30 +16,24 @@ import Data.HashMap.Lazy ( HashMap )
2016
import qualified Data.HashMap.Lazy as M
2117
import Data.List
2218
import Data.List.Split
23-
import Data.Maybe ( maybeToList )
2419
import Data.Text ( Text )
2520
import qualified Data.Text as Text
26-
import Nix.Atoms
21+
import Data.Text.Prettyprint.Doc
2722
import Nix.Convert
2823
import Nix.Effects
2924
import Nix.Exec ( MonadNix
30-
, callFunc
3125
, evalExprLoc
3226
, nixInstantiateExpr
3327
)
3428
import Nix.Expr
3529
import Nix.Frames
36-
import Nix.Normal
3730
import Nix.Parser
38-
import Nix.Pretty
3931
import Nix.Render
4032
import Nix.Scope
4133
import Nix.String
42-
import Nix.String.Coerce
4334
import Nix.Utils
4435
import Nix.Value
4536
import Nix.Value.Monad
46-
import Prettyprinter
4737
import System.FilePath
4838

4939
#ifdef MIN_VERSION_ghc_datasize
@@ -126,8 +116,8 @@ findPathBy
126116
-> [NValue t f m]
127117
-> FilePath
128118
-> m FilePath
129-
findPathBy finder l name = do
130-
mpath <- foldM go Nothing l
119+
findPathBy finder ls name = do
120+
mpath <- foldM go Nothing ls
131121
case mpath of
132122
Nothing ->
133123
throwError
@@ -264,38 +254,5 @@ pathToDefaultNixFile p = do
264254
isDir <- doesDirectoryExist p
265255
pure $ if isDir then p </> "default.nix" else p
266256

267-
defaultDerivationStrict
268-
:: forall e t f m . MonadNix e t f m => NValue t f m -> m (NValue t f m)
269-
defaultDerivationStrict = fromValue @(AttrSet (NValue t f m)) >=> \s -> do
270-
nn <- maybe (pure False) (demand ?? fromValue) (M.lookup "__ignoreNulls" s)
271-
s' <- M.fromList <$> mapMaybeM (handleEntry nn) (M.toList s)
272-
v' <- normalForm =<< toValue @(AttrSet (NValue t f m)) @_ @(NValue t f m) s'
273-
nixInstantiateExpr $ "derivationStrict " ++ show (prettyNValue v')
274-
where
275-
mapMaybeM :: (a -> m (Maybe b)) -> [a] -> m [b]
276-
mapMaybeM op = foldr f (pure [])
277-
where f x xs = op x >>= (<$> xs) . (++) . maybeToList
278-
279-
handleEntry :: Bool -> (Text, NValue t f m) -> m (Maybe (Text, NValue t f m))
280-
handleEntry ignoreNulls (k, v) = fmap (k, ) <$> case k of
281-
-- The `args' attribute is special: it supplies the command-line
282-
-- arguments to the builder.
283-
-- TODO This use of coerceToString is probably not right and may
284-
-- not have the right arguments.
285-
"args" -> demand v $ fmap Just . coerceNixList
286-
"__ignoreNulls" -> pure Nothing
287-
_ -> demand v $ \case
288-
NVConstant NNull | ignoreNulls -> pure Nothing
289-
v' -> Just <$> coerceNix v'
290-
where
291-
coerceNix :: NValue t f m -> m (NValue t f m)
292-
coerceNix = toValue <=< coerceToString callFunc CopyToStore CoerceAny
293-
294-
coerceNixList :: NValue t f m -> m (NValue t f m)
295-
coerceNixList v = do
296-
xs <- fromValue @[NValue t f m] v
297-
ys <- traverse (`demand` coerceNix) xs
298-
toValue @[NValue t f m] ys
299-
300257
defaultTraceEffect :: MonadPutStr m => String -> m ()
301258
defaultTraceEffect = Nix.Effects.putStrLn

0 commit comments

Comments
 (0)