on ae@static-which-prefetch help sign in
224 lines 6.1 kB history raw
1{-# LANGUAGE AllowAmbiguousTypes #-}
2{-# LANGUAGE ConstraintKinds #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE LambdaCase #-}
5{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE Rank2Types #-}
8{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE TemplateHaskell #-}
10{-# LANGUAGE TypeApplications #-}
11module Obelisk.Command.Nix
12 ( Arg (..)
13 , NixBuildConfig (..)
14 , nixBuildConfig_common
15 , nixBuildConfig_outLink
16 , NixCmd (..)
17 , nixCmdConfig_args
18 , nixCmdConfig_builders
19 , nixCmdConfig_target
20 , NixCommonConfig (..)
21 , NixInstantiateConfig (..)
22 , nixInstantiateConfig_eval
23 , NixShellConfig (..)
24 , nixShellConfig_common
25 , nixShellConfig_pure
26 , nixShellConfig_run
27 , OutLink (..)
28 , Target (..)
29 , target_attr
30 , target_expr
31 , target_path
33 , boolArg
34 , nixCmd
35 , nixCmdProc
36 , nixCmdProc'
37 , rawArg
38 , runNixShellConfig
39 , strArg
40 ) where
42import Control.Monad (guard)
43import Control.Lens
45import Data.Bool (bool)
46import Data.Default
47import Data.List (intercalate)
48import Data.Maybe
49import Data.Monoid ((<>))
50import qualified Data.Text as T
52import Obelisk.App (MonadObelisk)
53import Obelisk.CliApp
55-- | What to build
56data Target = Target
57 { _target_path :: Maybe FilePath
58 , _target_attr :: Maybe String
59 , _target_expr :: Maybe String
60 }
61makeClassy ''Target
63instance Default Target where
64 def = Target
65 { _target_path = Just "."
66 , _target_attr = Nothing
67 , _target_expr = Nothing
68 }
70data Arg
71 = Arg_Str String String
72 | Arg_Expr String String
73 deriving (Eq, Show)
75strArg :: String -> String -> Arg
76strArg = Arg_Str
78rawArg :: String -> String -> Arg
79rawArg = Arg_Expr
81boolArg :: String -> Bool -> Arg
82boolArg k = Arg_Expr k . bool "false" "true"
84cliFromArgs :: [Arg] -> [String]
85cliFromArgs = concatMap $ \case
86 Arg_Str k v -> ["--argstr", k, v]
87 Arg_Expr k v -> ["--arg", k, v]
89data NixCommonConfig = NixCommonConfig
90 { _nixCmdConfig_target :: Target
91 , _nixCmdConfig_args :: [Arg]
92 , _nixCmdConfig_builders :: [String]
93 }
94makeClassy ''NixCommonConfig
96instance Default NixCommonConfig where
97 def = NixCommonConfig def mempty mempty
99runNixCommonConfig :: NixCommonConfig -> [String]
100runNixCommonConfig cfg = mconcat [maybeToList path, attrArg, exprArg, args, buildersArg]
101 where
102 path = _target_path $ _nixCmdConfig_target cfg
103 attr = _target_attr $ _nixCmdConfig_target cfg
104 expr = _target_expr $ _nixCmdConfig_target cfg
105 attrArg = case attr of
106 Nothing -> []
107 Just a -> ["-A", a]
108 exprArg = case expr of
109 Nothing -> []
110 Just a -> ["-E", a]
111 args = cliFromArgs $ _nixCmdConfig_args cfg
112 buildersArg = case _nixCmdConfig_builders cfg of
113 [] -> []
114 builders -> ["--builders", intercalate ";" builders]
116-- | Where to put nix-build output
117data OutLink
118 = OutLink_Default
119 | OutLink_None
120 | OutLink_IndirectRoot FilePath
122instance Default OutLink where
123 def = OutLink_Default
125data NixBuildConfig = NixBuildConfig
126 { _nixBuildConfig_common :: NixCommonConfig
127 , _nixBuildConfig_outLink :: OutLink
128 }
129makeLenses ''NixBuildConfig
131instance HasNixCommonConfig NixBuildConfig where
132 nixCommonConfig = nixBuildConfig_common
134instance Default NixBuildConfig where
135 def = NixBuildConfig def def
137runNixBuildConfig :: NixBuildConfig -> [String]
138runNixBuildConfig cfg = mconcat
139 [ runNixCommonConfig $ cfg ^. nixCommonConfig
140 , case _nixBuildConfig_outLink cfg of
141 OutLink_Default -> []
142 OutLink_None -> ["--no-out-link"]
143 OutLink_IndirectRoot l -> ["--out-link", l]
144 ]
146data NixInstantiateConfig = NixInstantiateConfig
147 { _nixInstantiateConfig_common :: NixCommonConfig
148 , _nixInstantiateConfig_eval :: Bool
149 }
150makeLenses ''NixInstantiateConfig
152instance HasNixCommonConfig NixInstantiateConfig where
153 nixCommonConfig = nixInstantiateConfig_common
155instance Default NixInstantiateConfig where
156 def = NixInstantiateConfig def False
158runNixInstantiateConfig :: NixInstantiateConfig -> [String]
159runNixInstantiateConfig cfg = mconcat
160 [ runNixCommonConfig $ cfg ^. nixCommonConfig
161 , "--eval" <$ guard (_nixInstantiateConfig_eval cfg)
162 ]
164data NixShellConfig = NixShellConfig
165 { _nixShellConfig_common :: NixCommonConfig
166 , _nixShellConfig_pure :: Bool
167 , _nixShellConfig_run :: Maybe String
168 }
170makeLenses ''NixShellConfig
172instance HasNixCommonConfig NixShellConfig where
173 nixCommonConfig = nixShellConfig_common
175instance Default NixShellConfig where
176 def = NixShellConfig def False Nothing
178data NixCmd
179 = NixCmd_Build NixBuildConfig
180 | NixCmd_Instantiate NixInstantiateConfig
182instance Default NixCmd where
183 def = NixCmd_Build def
185runNixShellConfig :: NixShellConfig -> [String]
186runNixShellConfig cfg = mconcat
187 [ runNixCommonConfig $ cfg ^. nixCommonConfig
188 , [ "--pure" | cfg ^. nixShellConfig_pure ]
189 ] ++ mconcat [
190 ["--run", run] | run <- maybeToList $ cfg ^. nixShellConfig_run
191 ]
193nixCmdProc :: NixCmd -> ProcessSpec
194nixCmdProc = fst . nixCmdProc'
196nixCmdProc' :: NixCmd -> (ProcessSpec, T.Text)
197nixCmdProc' cmdCfg = (proc (T.unpack cmd) options, cmd)
198 where
199 (cmd, options) = case cmdCfg of
200 NixCmd_Build cfg' ->
201 ( "nix-build"
202 , runNixBuildConfig cfg'
203 )
204 NixCmd_Instantiate cfg' ->
205 ( "nix-instantiate"
206 , runNixInstantiateConfig cfg'
207 )
209nixCmd :: MonadObelisk m => NixCmd -> m FilePath
210nixCmd cmdCfg = withSpinner' (T.unwords $ "Running" : cmd : desc) (Just $ const $ T.unwords $ "Built" : desc) $ do
211 output <- readProcessAndLogStderr Debug cmdProc
212 -- Remove final newline that Nix appends
213 Just (outPath, '\n') <- pure $ T.unsnoc output
214 pure $ T.unpack outPath
215 where
216 (cmdProc, cmd) = nixCmdProc' cmdCfg
217 commonCfg = case cmdCfg of
218 NixCmd_Build cfg' -> cfg' ^. nixCommonConfig
219 NixCmd_Instantiate cfg' -> cfg' ^. nixCommonConfig
220 path = commonCfg ^. nixCmdConfig_target . target_path
221 desc = concat $ catMaybes
222 [ (\x -> ["on", T.pack x]) <$> path
223 , (\a -> ["[" <> T.pack a <> "]"]) <$> (commonCfg ^. nixCmdConfig_target . target_attr)
224 ]