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

-- | Configuration options for building from the command line only.

module Stack.Types.BuildOptsCLI
  ( BuildOptsCLI (..)
  , defaultBuildOptsCLI
  , ApplyCLIFlag (..)
  , BuildSubset (..)
  , FileWatchOpts (..)
  , BuildCommand (..)
  , boptsCLIAllProgOptions
  , boptsCLIFlagsByName
  ) where

import qualified Data.Map.Strict as Map
import qualified Data.Text as T
import           Stack.Prelude

-- | Build options that may only be specified from the CLI

data BuildOptsCLI = BuildOptsCLI
  { BuildOptsCLI -> [Text]
targetsCLI :: ![Text]
  , BuildOptsCLI -> Bool
dryrun :: !Bool
  , BuildOptsCLI -> [Text]
ghcOptions :: ![Text]
  , BuildOptsCLI -> [(Text, [Text])]
progsOptions :: ![(Text, [Text])]
  , BuildOptsCLI -> Map ApplyCLIFlag (Map FlagName Bool)
flags :: !(Map ApplyCLIFlag (Map FlagName Bool))
  , BuildOptsCLI -> BuildSubset
buildSubset :: !BuildSubset
  , BuildOptsCLI -> FileWatchOpts
fileWatch :: !FileWatchOpts
  , BuildOptsCLI -> Bool
watchAll :: !Bool
  , BuildOptsCLI -> [(String, [String])]
exec :: ![(String, [String])]
  , BuildOptsCLI -> Bool
onlyConfigure :: !Bool
  , BuildOptsCLI -> BuildCommand
command :: !BuildCommand
  , BuildOptsCLI -> Bool
initialBuildSteps :: !Bool
  }
  deriving Int -> BuildOptsCLI -> ShowS
[BuildOptsCLI] -> ShowS
BuildOptsCLI -> String
(Int -> BuildOptsCLI -> ShowS)
-> (BuildOptsCLI -> String)
-> ([BuildOptsCLI] -> ShowS)
-> Show BuildOptsCLI
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BuildOptsCLI -> ShowS
showsPrec :: Int -> BuildOptsCLI -> ShowS
$cshow :: BuildOptsCLI -> String
show :: BuildOptsCLI -> String
$cshowList :: [BuildOptsCLI] -> ShowS
showList :: [BuildOptsCLI] -> ShowS
Show

defaultBuildOptsCLI ::BuildOptsCLI
defaultBuildOptsCLI :: BuildOptsCLI
defaultBuildOptsCLI = BuildOptsCLI
  { $sel:targetsCLI:BuildOptsCLI :: [Text]
targetsCLI = []
  , $sel:dryrun:BuildOptsCLI :: Bool
dryrun = Bool
False
  , $sel:flags:BuildOptsCLI :: Map ApplyCLIFlag (Map FlagName Bool)
flags = Map ApplyCLIFlag (Map FlagName Bool)
forall k a. Map k a
Map.empty
  , $sel:ghcOptions:BuildOptsCLI :: [Text]
ghcOptions = []
  , $sel:progsOptions:BuildOptsCLI :: [(Text, [Text])]
progsOptions = []
  , $sel:buildSubset:BuildOptsCLI :: BuildSubset
buildSubset = BuildSubset
BSAll
  , $sel:fileWatch:BuildOptsCLI :: FileWatchOpts
fileWatch = FileWatchOpts
NoFileWatch
  , $sel:watchAll:BuildOptsCLI :: Bool
watchAll = Bool
False
  , $sel:exec:BuildOptsCLI :: [(String, [String])]
exec = []
  , $sel:onlyConfigure:BuildOptsCLI :: Bool
onlyConfigure = Bool
False
  , $sel:command:BuildOptsCLI :: BuildCommand
command = BuildCommand
Build
  , $sel:initialBuildSteps:BuildOptsCLI :: Bool
initialBuildSteps = Bool
False
  }

-- | How to apply a CLI flag

data ApplyCLIFlag
  = ACFAllProjectPackages
    -- ^ Apply to all project packages which have such a flag name available.

  | ACFByName !PackageName
    -- ^ Apply to the specified package only.

  deriving (ApplyCLIFlag -> ApplyCLIFlag -> Bool
(ApplyCLIFlag -> ApplyCLIFlag -> Bool)
-> (ApplyCLIFlag -> ApplyCLIFlag -> Bool) -> Eq ApplyCLIFlag
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
== :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
$c/= :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
/= :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
Eq, Eq ApplyCLIFlag
Eq ApplyCLIFlag =>
(ApplyCLIFlag -> ApplyCLIFlag -> Ordering)
-> (ApplyCLIFlag -> ApplyCLIFlag -> Bool)
-> (ApplyCLIFlag -> ApplyCLIFlag -> Bool)
-> (ApplyCLIFlag -> ApplyCLIFlag -> Bool)
-> (ApplyCLIFlag -> ApplyCLIFlag -> Bool)
-> (ApplyCLIFlag -> ApplyCLIFlag -> ApplyCLIFlag)
-> (ApplyCLIFlag -> ApplyCLIFlag -> ApplyCLIFlag)
-> Ord ApplyCLIFlag
ApplyCLIFlag -> ApplyCLIFlag -> Bool
ApplyCLIFlag -> ApplyCLIFlag -> Ordering
ApplyCLIFlag -> ApplyCLIFlag -> ApplyCLIFlag
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ApplyCLIFlag -> ApplyCLIFlag -> Ordering
compare :: ApplyCLIFlag -> ApplyCLIFlag -> Ordering
$c< :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
< :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
$c<= :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
<= :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
$c> :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
> :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
$c>= :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
>= :: ApplyCLIFlag -> ApplyCLIFlag -> Bool
$cmax :: ApplyCLIFlag -> ApplyCLIFlag -> ApplyCLIFlag
max :: ApplyCLIFlag -> ApplyCLIFlag -> ApplyCLIFlag
$cmin :: ApplyCLIFlag -> ApplyCLIFlag -> ApplyCLIFlag
min :: ApplyCLIFlag -> ApplyCLIFlag -> ApplyCLIFlag
Ord, Int -> ApplyCLIFlag -> ShowS
[ApplyCLIFlag] -> ShowS
ApplyCLIFlag -> String
(Int -> ApplyCLIFlag -> ShowS)
-> (ApplyCLIFlag -> String)
-> ([ApplyCLIFlag] -> ShowS)
-> Show ApplyCLIFlag
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ApplyCLIFlag -> ShowS
showsPrec :: Int -> ApplyCLIFlag -> ShowS
$cshow :: ApplyCLIFlag -> String
show :: ApplyCLIFlag -> String
$cshowList :: [ApplyCLIFlag] -> ShowS
showList :: [ApplyCLIFlag] -> ShowS
Show)

-- | Which subset of packages to build

data BuildSubset
  = BSAll
  | BSOnlySnapshot
    -- ^ Only install packages in the snapshot database, skipping

    -- packages intended for the local database.

  | BSOnlyDependencies
  | BSOnlyLocals
    -- ^ Refuse to build anything in the snapshot database, see

    -- https://github.com/commercialhaskell/stack/issues/5272

  deriving (Int -> BuildSubset -> ShowS
[BuildSubset] -> ShowS
BuildSubset -> String
(Int -> BuildSubset -> ShowS)
-> (BuildSubset -> String)
-> ([BuildSubset] -> ShowS)
-> Show BuildSubset
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BuildSubset -> ShowS
showsPrec :: Int -> BuildSubset -> ShowS
$cshow :: BuildSubset -> String
show :: BuildSubset -> String
$cshowList :: [BuildSubset] -> ShowS
showList :: [BuildSubset] -> ShowS
Show, BuildSubset -> BuildSubset -> Bool
(BuildSubset -> BuildSubset -> Bool)
-> (BuildSubset -> BuildSubset -> Bool) -> Eq BuildSubset
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BuildSubset -> BuildSubset -> Bool
== :: BuildSubset -> BuildSubset -> Bool
$c/= :: BuildSubset -> BuildSubset -> Bool
/= :: BuildSubset -> BuildSubset -> Bool
Eq)

data FileWatchOpts
  = NoFileWatch
  | FileWatch
  | FileWatchPoll
  deriving (Int -> FileWatchOpts -> ShowS
[FileWatchOpts] -> ShowS
FileWatchOpts -> String
(Int -> FileWatchOpts -> ShowS)
-> (FileWatchOpts -> String)
-> ([FileWatchOpts] -> ShowS)
-> Show FileWatchOpts
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FileWatchOpts -> ShowS
showsPrec :: Int -> FileWatchOpts -> ShowS
$cshow :: FileWatchOpts -> String
show :: FileWatchOpts -> String
$cshowList :: [FileWatchOpts] -> ShowS
showList :: [FileWatchOpts] -> ShowS
Show, FileWatchOpts -> FileWatchOpts -> Bool
(FileWatchOpts -> FileWatchOpts -> Bool)
-> (FileWatchOpts -> FileWatchOpts -> Bool) -> Eq FileWatchOpts
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileWatchOpts -> FileWatchOpts -> Bool
== :: FileWatchOpts -> FileWatchOpts -> Bool
$c/= :: FileWatchOpts -> FileWatchOpts -> Bool
/= :: FileWatchOpts -> FileWatchOpts -> Bool
Eq)

-- | Command sum type for conditional arguments.

data BuildCommand
  = Build
  | Test
  | Haddock
  | Bench
  | Install
  deriving (BuildCommand -> BuildCommand -> Bool
(BuildCommand -> BuildCommand -> Bool)
-> (BuildCommand -> BuildCommand -> Bool) -> Eq BuildCommand
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BuildCommand -> BuildCommand -> Bool
== :: BuildCommand -> BuildCommand -> Bool
$c/= :: BuildCommand -> BuildCommand -> Bool
/= :: BuildCommand -> BuildCommand -> Bool
Eq, Int -> BuildCommand -> ShowS
[BuildCommand] -> ShowS
BuildCommand -> String
(Int -> BuildCommand -> ShowS)
-> (BuildCommand -> String)
-> ([BuildCommand] -> ShowS)
-> Show BuildCommand
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BuildCommand -> ShowS
showsPrec :: Int -> BuildCommand -> ShowS
$cshow :: BuildCommand -> String
show :: BuildCommand -> String
$cshowList :: [BuildCommand] -> ShowS
showList :: [BuildCommand] -> ShowS
Show)

-- | Generate a list of --PROG-option="<argument>" arguments for all PROGs.

boptsCLIAllProgOptions :: BuildOptsCLI -> [Text]
boptsCLIAllProgOptions :: BuildOptsCLI -> [Text]
boptsCLIAllProgOptions BuildOptsCLI
boptsCLI =
  ((Text, [Text]) -> [Text]) -> [(Text, [Text])] -> [Text]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Text, [Text]) -> [Text]
progOptionArgs BuildOptsCLI
boptsCLI.progsOptions
 where
  -- Generate a list of --PROG-option="<argument>" arguments for a PROG.

  progOptionArgs :: (Text, [Text]) -> [Text]
  progOptionArgs :: (Text, [Text]) -> [Text]
progOptionArgs (Text
prog, [Text]
opts) = (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
progOptionArg [Text]
opts
   where
    -- Generate a --PROG-option="<argument>" argument for a PROG and option.

    progOptionArg :: Text -> Text
    progOptionArg :: Text -> Text
progOptionArg Text
opt = [Text] -> Text
T.concat
      [ Text
"--"
      , Text
prog
      , Text
"-option=\""
      , Text
opt
      , Text
"\""
      ]

-- | Only flags set via 'ACFByName'

boptsCLIFlagsByName :: BuildOptsCLI -> Map PackageName (Map FlagName Bool)
boptsCLIFlagsByName :: BuildOptsCLI -> Map PackageName (Map FlagName Bool)
boptsCLIFlagsByName = [(PackageName, Map FlagName Bool)]
-> Map PackageName (Map FlagName Bool)
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(PackageName, Map FlagName Bool)]
 -> Map PackageName (Map FlagName Bool))
-> (BuildOptsCLI -> [(PackageName, Map FlagName Bool)])
-> BuildOptsCLI
-> Map PackageName (Map FlagName Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((ApplyCLIFlag, Map FlagName Bool)
 -> Maybe (PackageName, Map FlagName Bool))
-> [(ApplyCLIFlag, Map FlagName Bool)]
-> [(PackageName, Map FlagName Bool)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (ApplyCLIFlag, Map FlagName Bool)
-> Maybe (PackageName, Map FlagName Bool)
forall {b}. (ApplyCLIFlag, b) -> Maybe (PackageName, b)
go ([(ApplyCLIFlag, Map FlagName Bool)]
 -> [(PackageName, Map FlagName Bool)])
-> (BuildOptsCLI -> [(ApplyCLIFlag, Map FlagName Bool)])
-> BuildOptsCLI
-> [(PackageName, Map FlagName Bool)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map ApplyCLIFlag (Map FlagName Bool)
-> [(ApplyCLIFlag, Map FlagName Bool)]
forall k a. Map k a -> [(k, a)]
Map.toList (Map ApplyCLIFlag (Map FlagName Bool)
 -> [(ApplyCLIFlag, Map FlagName Bool)])
-> (BuildOptsCLI -> Map ApplyCLIFlag (Map FlagName Bool))
-> BuildOptsCLI
-> [(ApplyCLIFlag, Map FlagName Bool)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.flags)
 where
  go :: (ApplyCLIFlag, b) -> Maybe (PackageName, b)
go (ApplyCLIFlag
ACFAllProjectPackages, b
_) = Maybe (PackageName, b)
forall a. Maybe a
Nothing
  go (ACFByName PackageName
name, b
flags) = (PackageName, b) -> Maybe (PackageName, b)
forall a. a -> Maybe a
Just (PackageName
name, b
flags)