@@ -6,10 +6,19 @@
66{-# LANGUAGE OverloadedStrings #-}
77{-# LANGUAGE Rank2Types #-}
88{-# LANGUAGE ScopedTypeVariables #-}
9+{-# LANGUAGE TemplateHaskell #-}
910{-# LANGUAGE TypeApplications #-}
1011module Obelisk.Command.Nix
11− ( nixBuild
12+ ( nixCmd
13+ , NixCmd (..)
14+ , nixCmdConfig_target
15+ , nixCmdConfig_args
16+ , nixCmdConfig_builders
1217 , NixBuildConfig (..)
18+ , nixBuildConfig_outLink
19+ , NixInstantiateConfig (..)
20+ , nixInstantiateConfig_eval
21+ , NixCommonConfig (..)
1322 , Target (..)
1423 , OutLink (..)
1524 , Arg (..)
@@ -18,6 +27,9 @@ module Obelisk.Command.Nix
1827 , strArg
1928 ) where
2029
30+import Control.Monad (guard)
31+import Control.Lens
32+
2133import Data.Bool (bool)
2234import Data.Default
2335import Data.List (intercalate)
@@ -28,20 +40,12 @@ import System.Process (proc)
2840import Obelisk.App (MonadObelisk)
2941import Obelisk.CliApp
3042
31−-- | Where to put nix-build output
32−data OutLink
33− = OutLink_Default
34− | OutLink_None
35− | OutLink_IndirectRoot FilePath
36−
37−instance Default OutLink where
38− def = OutLink_Default
39−
4043-- | What to build
4144data Target = Target
4245 { _target_path :: FilePath
4346 , _target_attr :: Maybe String
4447 }
48+makeClassy ''Target
4549
4650instance Default Target where
4751 def = Target
@@ -68,36 +72,103 @@ cliFromArgs = concatMap $ \case
6872 Arg_Str k v -> ["--argstr", k, v]
6973 Arg_Expr k v -> ["--arg", k, v]
7074
71−data NixBuildConfig = NixBuildConfig
72− { _nixBuildConfig_target :: Target
73− , _nixBuildConfig_outLink :: OutLink
74− , _nixBuildConfig_args :: [Arg]
75− , _nixBuildConfig_builders :: [String]
75+data NixCommonConfig = NixCommonConfig
76+ { _nixCmdConfig_target :: Target
77+ , _nixCmdConfig_args :: [Arg]
78+ , _nixCmdConfig_builders :: [String]
7679 }
80+makeClassy ''NixCommonConfig
7781
78−instance Default NixBuildConfig where
79− def = NixBuildConfig def def mempty mempty
82+instance Default NixCommonConfig where
83+ def = NixCommonConfig def mempty mempty
8084
81−nixBuild :: MonadObelisk m => NixBuildConfig -> m FilePath
82−nixBuild cfg = withSpinner' ("Running nix-build on " <> desc) (Just $ const $ "Built " <> desc) $ do
83− output <- readProcessAndLogStderr Debug $ proc "nix-build" $ mconcat
84− [[path], attrArg, args, outLink, buildersArg]
85− -- Remove final newline that Nix appends
86− Just (outPath, '\n') <- pure $ T.unsnoc output
87− pure $ T.unpack outPath
85+runNixCommonConfig :: NixCommonConfig -> [FilePath]
86+runNixCommonConfig cfg = mconcat [[path], attrArg, args, buildersArg]
8887 where
89− path = _target_path $ _nixBuildConfig_target cfg
90− attr = _target_attr $ _nixBuildConfig_target cfg
88+ path = _target_path $ _nixCmdConfig_target cfg
89+ attr = _target_attr $ _nixCmdConfig_target cfg
9190 attrArg = case attr of
9291 Nothing -> []
9392 Just a -> ["-A", a]
94− args = cliFromArgs $ _nixBuildConfig_args cfg
95− outLink = case _nixBuildConfig_outLink cfg of
93+ args = cliFromArgs $ _nixCmdConfig_args cfg
94+ buildersArg = case _nixCmdConfig_builders cfg of
95+ [] -> []
96+ builders -> ["--builders", intercalate ";" builders]
97+
98+-- | Where to put nix-build output
99+data OutLink
100+ = OutLink_Default
101+ | OutLink_None
102+ | OutLink_IndirectRoot FilePath
103+
104+instance Default OutLink where
105+ def = OutLink_Default
106+
107+data NixBuildConfig = NixBuildConfig
108+ { _nixBuildConfig_common :: NixCommonConfig
109+ , _nixBuildConfig_outLink :: OutLink
110+ }
111+makeLenses ''NixBuildConfig
112+
113+instance HasNixCommonConfig NixBuildConfig where
114+ nixCommonConfig = nixBuildConfig_common
115+
116+instance Default NixBuildConfig where
117+ def = NixBuildConfig def def
118+
119+runNixBuildConfig :: NixBuildConfig -> [FilePath]
120+runNixBuildConfig cfg = mconcat
121+ [ runNixCommonConfig $ cfg ^. nixCommonConfig
122+ , case _nixBuildConfig_outLink cfg of
96123 OutLink_Default -> []
97124 OutLink_None -> ["--no-out-link"]
98125 OutLink_IndirectRoot l -> ["--out-link", l]
99− desc = T.pack $ path <> maybe "" (\a -> " [" <> a <> "]") attr
100− buildersArg = case _nixBuildConfig_builders cfg of
101− [] -> []
102− builders -> ["--builders", intercalate ";" builders]
126+ ]
103127
128+data NixInstantiateConfig = NixInstantiateConfig
129+ { _nixInstantiateConfig_common :: NixCommonConfig
130+ , _nixInstantiateConfig_eval :: Bool
131+ }
132+makeLenses ''NixInstantiateConfig
133+
134+instance HasNixCommonConfig NixInstantiateConfig where
135+ nixCommonConfig = nixInstantiateConfig_common
136+
137+instance Default NixInstantiateConfig where
138+ def = NixInstantiateConfig def False
139+
140+runNixInstantiateConfig :: NixInstantiateConfig -> [FilePath]
141+runNixInstantiateConfig cfg = mconcat
142+ [ runNixCommonConfig $ cfg ^. nixCommonConfig
143+ , "--eval" <$ guard (_nixInstantiateConfig_eval cfg)
144+ ]
145+
146+data NixCmd
147+ = NixCmd_Build NixBuildConfig
148+ | NixCmd_Instantiate NixInstantiateConfig
149+
150+instance Default NixCmd where
151+ def = NixCmd_Build def
152+
153+nixCmd :: MonadObelisk m => NixCmd -> m FilePath
154+nixCmd cmdCfg = withSpinner' ("Running " <> cmd <> " on " <> desc) (Just $ const $ "Built " <> desc) $ do
155+ output <- readProcessAndLogStderr Debug $ proc (T.unpack cmd) $ options
156+ -- Remove final newline that Nix appends
157+ Just (outPath, '\n') <- pure $ T.unsnoc output
158+ pure $ T.unpack outPath
159+ where
160+ (cmd, options, commonCfg) = case cmdCfg of
161+ NixCmd_Build cfg' ->
162+ ( "nix-build"
163+ , runNixBuildConfig cfg'
164+ , cfg' ^. nixCommonConfig
165+ )
166+ NixCmd_Instantiate cfg' ->
167+ ( "nix-instantiate"
168+ , runNixInstantiateConfig cfg'
169+ , cfg' ^. nixCommonConfig
170+ )
171+ path = commonCfg ^. nixCmdConfig_target . target_path
172+ desc = T.pack $ path <> maybe ""
173+ (\a -> " [" <> a <> "]")
174+ (commonCfg ^. nixCmdConfig_target . target_attr)