{-# LANGUAGE NoImplicitPrelude     #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NoFieldSelectors      #-}
{-# LANGUAGE OverloadedStrings     #-}

-- | Nix types.

module Stack.Types.Nix
  ( NixOpts (..)
  , NixOptsMonoid (..)
  , nixAddGCRootsArgName
  , nixEnableArgName
  , nixInitFileArgName
  , nixPackagesArgName
  , nixPathArgName
  , nixPureShellArgName
  , nixShellOptsArgName
  ) where

import           Data.Aeson.Types ( FromJSON (..) )
import           Data.Aeson.WarningParser
                   ( WithJSONWarnings, (..:?), withObjectWarnings )
import           Generics.Deriving.Monoid ( mappenddefault, memptydefault )
import           Stack.Prelude

-- | Nix configuration. Parameterize by resolver type to avoid cyclic

-- dependency.

data NixOpts = NixOpts
  { NixOpts -> Bool
enable :: !Bool
  , NixOpts -> Bool
pureShell :: !Bool
  , NixOpts -> [Text]
packages :: ![Text]
    -- ^ The system packages to be installed in the environment before it runs

  , NixOpts -> Maybe FilePath
initFile :: !(Maybe FilePath)
    -- ^ The path of a file containing preconfiguration of the environment

    -- (e.g shell.nix)

  , NixOpts -> [Text]
shellOptions :: ![Text]
    -- ^ Options to be given to the nix-shell command line

  , NixOpts -> Bool
addGCRoots :: !Bool
    -- ^ Should we register gc roots so running nix-collect-garbage doesn't

    -- remove nix dependencies

  }
  deriving Int -> NixOpts -> ShowS
[NixOpts] -> ShowS
NixOpts -> FilePath
(Int -> NixOpts -> ShowS)
-> (NixOpts -> FilePath) -> ([NixOpts] -> ShowS) -> Show NixOpts
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NixOpts -> ShowS
showsPrec :: Int -> NixOpts -> ShowS
$cshow :: NixOpts -> FilePath
show :: NixOpts -> FilePath
$cshowList :: [NixOpts] -> ShowS
showList :: [NixOpts] -> ShowS
Show

-- | An uninterpreted representation of nix options.

-- Configurations may be "cascaded" using mappend (left-biased).

data NixOptsMonoid = NixOptsMonoid
  { NixOptsMonoid -> First Bool
enable :: !(First Bool)
    -- ^ Is using nix-shell enabled?

  , NixOptsMonoid -> First Bool
pureShell :: !(First Bool)
    -- ^ Should the nix-shell be pure

  , NixOptsMonoid -> First [Text]
packages :: !(First [Text])
    -- ^ System packages to use (given to nix-shell)

  , NixOptsMonoid -> First FilePath
initFile :: !(First FilePath)
    -- ^ The path of a file containing preconfiguration of the environment (e.g

    -- shell.nix)

  , NixOptsMonoid -> First [Text]
shellOptions :: !(First [Text])
    -- ^ Options to be given to the nix-shell command line

  , NixOptsMonoid -> First [Text]
path :: !(First [Text])
    -- ^ Override parts of NIX_PATH (notably 'nixpkgs')

  , NixOptsMonoid -> FirstFalse
addGCRoots :: !FirstFalse
    -- ^ Should we register gc roots so running nix-collect-garbage doesn't

    -- remove nix dependencies

  }
  deriving (NixOptsMonoid -> NixOptsMonoid -> Bool
(NixOptsMonoid -> NixOptsMonoid -> Bool)
-> (NixOptsMonoid -> NixOptsMonoid -> Bool) -> Eq NixOptsMonoid
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NixOptsMonoid -> NixOptsMonoid -> Bool
== :: NixOptsMonoid -> NixOptsMonoid -> Bool
$c/= :: NixOptsMonoid -> NixOptsMonoid -> Bool
/= :: NixOptsMonoid -> NixOptsMonoid -> Bool
Eq, (forall x. NixOptsMonoid -> Rep NixOptsMonoid x)
-> (forall x. Rep NixOptsMonoid x -> NixOptsMonoid)
-> Generic NixOptsMonoid
forall x. Rep NixOptsMonoid x -> NixOptsMonoid
forall x. NixOptsMonoid -> Rep NixOptsMonoid x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. NixOptsMonoid -> Rep NixOptsMonoid x
from :: forall x. NixOptsMonoid -> Rep NixOptsMonoid x
$cto :: forall x. Rep NixOptsMonoid x -> NixOptsMonoid
to :: forall x. Rep NixOptsMonoid x -> NixOptsMonoid
Generic, Int -> NixOptsMonoid -> ShowS
[NixOptsMonoid] -> ShowS
NixOptsMonoid -> FilePath
(Int -> NixOptsMonoid -> ShowS)
-> (NixOptsMonoid -> FilePath)
-> ([NixOptsMonoid] -> ShowS)
-> Show NixOptsMonoid
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NixOptsMonoid -> ShowS
showsPrec :: Int -> NixOptsMonoid -> ShowS
$cshow :: NixOptsMonoid -> FilePath
show :: NixOptsMonoid -> FilePath
$cshowList :: [NixOptsMonoid] -> ShowS
showList :: [NixOptsMonoid] -> ShowS
Show)

-- | Decode uninterpreted nix options from JSON/YAML.

instance FromJSON (WithJSONWarnings NixOptsMonoid) where
  parseJSON :: Value -> Parser (WithJSONWarnings NixOptsMonoid)
parseJSON = FilePath
-> (Object -> WarningParser NixOptsMonoid)
-> Value
-> Parser (WithJSONWarnings NixOptsMonoid)
forall a.
FilePath
-> (Object -> WarningParser a)
-> Value
-> Parser (WithJSONWarnings a)
withObjectWarnings FilePath
"NixOptsMonoid" ((Object -> WarningParser NixOptsMonoid)
 -> Value -> Parser (WithJSONWarnings NixOptsMonoid))
-> (Object -> WarningParser NixOptsMonoid)
-> Value
-> Parser (WithJSONWarnings NixOptsMonoid)
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
    First Bool
enable        <- Maybe Bool -> First Bool
forall a. Maybe a -> First a
First (Maybe Bool -> First Bool)
-> WriterT WarningParserMonoid Parser (Maybe Bool)
-> WriterT WarningParserMonoid Parser (First Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> WriterT WarningParserMonoid Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> WarningParser (Maybe a)
..:? Text
nixEnableArgName
    First Bool
pureShell     <- Maybe Bool -> First Bool
forall a. Maybe a -> First a
First (Maybe Bool -> First Bool)
-> WriterT WarningParserMonoid Parser (Maybe Bool)
-> WriterT WarningParserMonoid Parser (First Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> WriterT WarningParserMonoid Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> WarningParser (Maybe a)
..:? Text
nixPureShellArgName
    First [Text]
packages      <- Maybe [Text] -> First [Text]
forall a. Maybe a -> First a
First (Maybe [Text] -> First [Text])
-> WriterT WarningParserMonoid Parser (Maybe [Text])
-> WriterT WarningParserMonoid Parser (First [Text])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> WriterT WarningParserMonoid Parser (Maybe [Text])
forall a. FromJSON a => Object -> Text -> WarningParser (Maybe a)
..:? Text
nixPackagesArgName
    First FilePath
initFile      <- Maybe FilePath -> First FilePath
forall a. Maybe a -> First a
First (Maybe FilePath -> First FilePath)
-> WriterT WarningParserMonoid Parser (Maybe FilePath)
-> WriterT WarningParserMonoid Parser (First FilePath)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object
-> Text -> WriterT WarningParserMonoid Parser (Maybe FilePath)
forall a. FromJSON a => Object -> Text -> WarningParser (Maybe a)
..:? Text
nixInitFileArgName
    First [Text]
shellOptions  <- Maybe [Text] -> First [Text]
forall a. Maybe a -> First a
First (Maybe [Text] -> First [Text])
-> WriterT WarningParserMonoid Parser (Maybe [Text])
-> WriterT WarningParserMonoid Parser (First [Text])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> WriterT WarningParserMonoid Parser (Maybe [Text])
forall a. FromJSON a => Object -> Text -> WarningParser (Maybe a)
..:? Text
nixShellOptsArgName
    First [Text]
path          <- Maybe [Text] -> First [Text]
forall a. Maybe a -> First a
First (Maybe [Text] -> First [Text])
-> WriterT WarningParserMonoid Parser (Maybe [Text])
-> WriterT WarningParserMonoid Parser (First [Text])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> WriterT WarningParserMonoid Parser (Maybe [Text])
forall a. FromJSON a => Object -> Text -> WarningParser (Maybe a)
..:? Text
nixPathArgName
    FirstFalse
addGCRoots    <- Maybe Bool -> FirstFalse
FirstFalse (Maybe Bool -> FirstFalse)
-> WriterT WarningParserMonoid Parser (Maybe Bool)
-> WriterT WarningParserMonoid Parser FirstFalse
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> WriterT WarningParserMonoid Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> WarningParser (Maybe a)
..:? Text
nixAddGCRootsArgName
    NixOptsMonoid -> WarningParser NixOptsMonoid
forall a. a -> WriterT WarningParserMonoid Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure NixOptsMonoid
      { First Bool
$sel:enable:NixOptsMonoid :: First Bool
enable :: First Bool
enable
      , First Bool
$sel:pureShell:NixOptsMonoid :: First Bool
pureShell :: First Bool
pureShell
      , First [Text]
$sel:packages:NixOptsMonoid :: First [Text]
packages :: First [Text]
packages
      , First FilePath
$sel:initFile:NixOptsMonoid :: First FilePath
initFile :: First FilePath
initFile
      , First [Text]
$sel:shellOptions:NixOptsMonoid :: First [Text]
shellOptions :: First [Text]
shellOptions
      , First [Text]
$sel:path:NixOptsMonoid :: First [Text]
path :: First [Text]
path
      , FirstFalse
$sel:addGCRoots:NixOptsMonoid :: FirstFalse
addGCRoots :: FirstFalse
addGCRoots
      }

-- | Left-biased combine Nix options

instance Semigroup NixOptsMonoid where
  <> :: NixOptsMonoid -> NixOptsMonoid -> NixOptsMonoid
(<>) = NixOptsMonoid -> NixOptsMonoid -> NixOptsMonoid
forall a. (Generic a, Monoid' (Rep a)) => a -> a -> a
mappenddefault

-- | Left-biased combine Nix options

instance Monoid NixOptsMonoid where
  mempty :: NixOptsMonoid
mempty = NixOptsMonoid
forall a. (Generic a, Monoid' (Rep a)) => a
memptydefault
  mappend :: NixOptsMonoid -> NixOptsMonoid -> NixOptsMonoid
mappend = NixOptsMonoid -> NixOptsMonoid -> NixOptsMonoid
forall a. Semigroup a => a -> a -> a
(<>)

-- | Nix enable argument name.

nixEnableArgName :: Text
nixEnableArgName :: Text
nixEnableArgName = Text
"enable"

-- | Nix run in pure shell argument name.

nixPureShellArgName :: Text
nixPureShellArgName :: Text
nixPureShellArgName = Text
"pure"

-- | Nix packages (build inputs) argument name.

nixPackagesArgName :: Text
nixPackagesArgName :: Text
nixPackagesArgName = Text
"packages"

-- | shell.nix file path argument name.

nixInitFileArgName :: Text
nixInitFileArgName :: Text
nixInitFileArgName = Text
"shell-file"

-- | Extra options for the nix-shell command argument name.

nixShellOptsArgName :: Text
nixShellOptsArgName :: Text
nixShellOptsArgName = Text
"nix-shell-options"

-- | NIX_PATH override argument name

nixPathArgName :: Text
nixPathArgName :: Text
nixPathArgName = Text
"path"

-- | Add GC roots arg name

nixAddGCRootsArgName :: Text
nixAddGCRootsArgName :: Text
nixAddGCRootsArgName = Text
"add-gc-roots"