{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Stack.Config.Nix
( nixCompiler
, nixCompilerVersion
, nixOptsFromMonoid
) where
import Control.Monad.Extra ( ifM )
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Distribution.System ( OS (..) )
import Stack.Constants ( osIsWindows )
import Stack.Prelude
import Stack.Types.Runner ( HasRunner )
import Stack.Types.Nix ( NixOpts (..), NixOptsMonoid (..) )
import System.Directory ( doesFileExist )
data ConfigNixException
= NixCannotUseShellFileAndPackagesException
| GHCMajorVersionUnspecified
| OnlyGHCSupported
deriving (Int -> ConfigNixException -> ShowS
[ConfigNixException] -> ShowS
ConfigNixException -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ConfigNixException] -> ShowS
$cshowList :: [ConfigNixException] -> ShowS
show :: ConfigNixException -> String
$cshow :: ConfigNixException -> String
showsPrec :: Int -> ConfigNixException -> ShowS
$cshowsPrec :: Int -> ConfigNixException -> ShowS
Show, Typeable)
instance Exception ConfigNixException where
displayException :: ConfigNixException -> String
displayException ConfigNixException
NixCannotUseShellFileAndPackagesException =
String
"Error: [S-2726]\n"
forall a. [a] -> [a] -> [a]
++ String
"You cannot have packages and a shell-file filled at the same time \
\in your nix-shell configuration."
displayException ConfigNixException
GHCMajorVersionUnspecified =
String
"Error: [S-9317]\n"
forall a. [a] -> [a] -> [a]
++ String
"GHC major version not specified."
displayException ConfigNixException
OnlyGHCSupported =
String
"Error: [S-8605]\n"
forall a. [a] -> [a] -> [a]
++ String
"Only GHC is supported by 'stack --nix'."
nixOptsFromMonoid ::
(HasRunner env, HasTerm env)
=> NixOptsMonoid
-> OS
-> RIO env NixOpts
nixOptsFromMonoid :: forall env.
(HasRunner env, HasTerm env) =>
NixOptsMonoid -> OS -> RIO env NixOpts
nixOptsFromMonoid NixOptsMonoid{First Bool
First String
First [Text]
FirstFalse
nixMonoidAddGCRoots :: NixOptsMonoid -> FirstFalse
nixMonoidPath :: NixOptsMonoid -> First [Text]
nixMonoidShellOptions :: NixOptsMonoid -> First [Text]
nixMonoidInitFile :: NixOptsMonoid -> First String
nixMonoidPackages :: NixOptsMonoid -> First [Text]
nixMonoidPureShell :: NixOptsMonoid -> First Bool
nixMonoidEnable :: NixOptsMonoid -> First Bool
nixMonoidAddGCRoots :: FirstFalse
nixMonoidPath :: First [Text]
nixMonoidShellOptions :: First [Text]
nixMonoidInitFile :: First String
nixMonoidPackages :: First [Text]
nixMonoidPureShell :: First Bool
nixMonoidEnable :: First Bool
..} OS
os = do
let defaultPure :: Bool
defaultPure = case OS
os of
OS
OSX -> Bool
False
OS
_ -> Bool
True
nixPureShell :: Bool
nixPureShell = forall a. a -> First a -> a
fromFirst Bool
defaultPure First Bool
nixMonoidPureShell
nixPackages :: [Text]
nixPackages = forall a. a -> First a -> a
fromFirst [] First [Text]
nixMonoidPackages
nixInitFile :: Maybe String
nixInitFile = forall a. First a -> Maybe a
getFirst First String
nixMonoidInitFile
nixShellOptions :: [Text]
nixShellOptions = forall a. a -> First a -> a
fromFirst [] First [Text]
nixMonoidShellOptions
forall a. [a] -> [a] -> [a]
++ forall {t}. t -> [t] -> [t]
prefixAll (String -> Text
T.pack String
"-I") (forall a. a -> First a -> a
fromFirst [] First [Text]
nixMonoidPath)
nixAddGCRoots :: Bool
nixAddGCRoots = FirstFalse -> Bool
fromFirstFalse FirstFalse
nixMonoidAddGCRoots
Bool
osIsNixOS <- forall (m :: * -> *). MonadIO m => m Bool
isNixOS
let nixEnable0 :: Bool
nixEnable0 = forall a. a -> First a -> a
fromFirst Bool
osIsNixOS First Bool
nixMonoidEnable
Bool
nixEnable <-
if Bool
nixEnable0 Bool -> Bool -> Bool
&& Bool
osIsWindows
then do
forall env (m :: * -> *).
(HasCallStack, HasTerm env, MonadReader env m, MonadIO m) =>
String -> m ()
prettyNoteS
String
"Disabling Nix integration, since this is being run in Windows."
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
else forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
nixEnable0
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
nixPackages) Bool -> Bool -> Bool
&& forall a. Maybe a -> Bool
isJust Maybe String
nixInitFile) forall a b. (a -> b) -> a -> b
$
forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
throwIO ConfigNixException
NixCannotUseShellFileAndPackagesException
forall (f :: * -> *) a. Applicative f => a -> f a
pure NixOpts{Bool
[Text]
Maybe String
nixAddGCRoots :: Bool
nixShellOptions :: [Text]
nixInitFile :: Maybe String
nixPackages :: [Text]
nixPureShell :: Bool
nixEnable :: Bool
nixEnable :: Bool
nixAddGCRoots :: Bool
nixShellOptions :: [Text]
nixInitFile :: Maybe String
nixPackages :: [Text]
nixPureShell :: Bool
..}
where
prefixAll :: t -> [t] -> [t]
prefixAll t
p (t
x:[t]
xs) = t
p forall {t}. t -> [t] -> [t]
: t
x forall {t}. t -> [t] -> [t]
: t -> [t] -> [t]
prefixAll t
p [t]
xs
prefixAll t
_ [t]
_ = []
nixCompiler :: WantedCompiler -> Either ConfigNixException T.Text
nixCompiler :: WantedCompiler -> Either ConfigNixException Text
nixCompiler WantedCompiler
compilerVersion =
case WantedCompiler
compilerVersion of
WCGhc Version
version ->
case (Char -> Bool) -> Text -> [Text]
T.split (forall a. Eq a => a -> a -> Bool
== Char
'.') (forall a. IsString a => String -> a
fromString forall a b. (a -> b) -> a -> b
$ Version -> String
versionString Version
version) of
Text
x : Text
y : [Text]
minor ->
forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$
case [Text]
minor of
[] ->
let major :: Text
major = [Text] -> Text
T.concat [Text
x, Text
y] in
Text
"(let compilers = builtins.filter \
\(name: builtins.match \
\\"ghc" forall a. Semigroup a => a -> a -> a
<> Text
major forall a. Semigroup a => a -> a -> a
<> Text
"[[:digit:]]*\" name != null) \
\(lib.attrNames haskell.compiler); in \
\if compilers == [] \
\then abort \"No compiler found for GHC "
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Version -> String
versionString Version
version) forall a. Semigroup a => a -> a -> a
<> Text
"\"\
\else haskell.compiler.${builtins.head compilers})"
[Text]
_ -> Text
"haskell.compiler.ghc" forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
T.concat (Text
x forall {t}. t -> [t] -> [t]
: Text
y forall {t}. t -> [t] -> [t]
: [Text]
minor)
[Text]
_ -> forall a b. a -> Either a b
Left ConfigNixException
GHCMajorVersionUnspecified
WCGhcjs{} -> forall a b. a -> Either a b
Left ConfigNixException
OnlyGHCSupported
WCGhcGit{} -> forall a b. a -> Either a b
Left ConfigNixException
OnlyGHCSupported
nixCompilerVersion :: WantedCompiler -> Either ConfigNixException T.Text
nixCompilerVersion :: WantedCompiler -> Either ConfigNixException Text
nixCompilerVersion WantedCompiler
compilerVersion =
case WantedCompiler
compilerVersion of
WCGhc Version
version ->
case (Char -> Bool) -> Text -> [Text]
T.split (forall a. Eq a => a -> a -> Bool
== Char
'.') (forall a. IsString a => String -> a
fromString forall a b. (a -> b) -> a -> b
$ Version -> String
versionString Version
version) of
Text
x : Text
y : [Text]
minor -> forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ Text
"ghc" forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
T.concat (Text
x forall {t}. t -> [t] -> [t]
: Text
y forall {t}. t -> [t] -> [t]
: [Text]
minor)
[Text]
_ -> forall a b. a -> Either a b
Left ConfigNixException
GHCMajorVersionUnspecified
WCGhcjs{} -> forall a b. a -> Either a b
Left ConfigNixException
OnlyGHCSupported
WCGhcGit{} -> forall a b. a -> Either a b
Left ConfigNixException
OnlyGHCSupported
isNixOS :: MonadIO m => m Bool
isNixOS :: forall (m :: * -> *). MonadIO m => m Bool
isNixOS = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
let fp :: String
fp = String
"/etc/os-release"
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifM (String -> IO Bool
doesFileExist String
fp)
(Text -> Text -> Bool
T.isInfixOf Text
"ID=nixos" forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO Text
TIO.readFile String
fp)
(forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False)