-- | Take configuration, produce 'Travis'.
{-# LANGUAGE NamedFieldPuns    #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards   #-}
{-# OPTIONS_GHC -Wno-unused-matches #-}
module HaskellCI.Travis (
    makeTravis,
    travisHeader,
    ) where

import HaskellCI.Prelude

import qualified Data.Map.Strict                 as M
import qualified Data.Set                        as S
import qualified Distribution.Fields.Pretty      as C
import qualified Distribution.Package            as C
import qualified Distribution.Pretty             as C
import qualified Distribution.Types.VersionRange as C
import qualified Distribution.Version            as C

import Cabal.Project
import HaskellCI.Auxiliary
import HaskellCI.Compiler
import HaskellCI.Config
import HaskellCI.Config.ConstraintSet
import HaskellCI.Config.Doctest
import HaskellCI.Config.Folds
import HaskellCI.Config.HLint
import HaskellCI.Config.Installed
import HaskellCI.Config.Jobs
import HaskellCI.Config.PackageScope
import HaskellCI.Config.Validity
import HaskellCI.HeadHackage
import HaskellCI.Jobs
import HaskellCI.List
import HaskellCI.MonadErr
import HaskellCI.Package
import HaskellCI.Sh
import HaskellCI.ShVersionRange
import HaskellCI.Tools
import HaskellCI.Travis.Yaml
import HaskellCI.VersionInfo

-------------------------------------------------------------------------------
-- Travis header
-------------------------------------------------------------------------------

travisHeader :: Bool -> [String] -> [String]
travisHeader :: Bool -> [[Char]] -> [[Char]]
travisHeader Bool
insertVersion [[Char]]
argv =
    [ [Char]
"This Travis job script has been generated by a script via"
    , [Char]
""
    , [Char]
"  haskell-ci " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> [Char]
unwords [ [Char]
"'" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
a [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'" | [Char]
a <- [[Char]]
argv ]
    , [Char]
""
    , [Char]
"To regenerate the script (for example after adjusting tested-with) run"
    , [Char]
""
    , [Char]
"  haskell-ci regenerate"
    , [Char]
""
    , [Char]
"For more information, see https://github.com/haskell-CI/haskell-ci"
    , [Char]
""
    ] [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++
    if Bool
insertVersion then
    [ [Char]
"version: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
haskellCIVerStr
    , [Char]
""
    ] else []

-------------------------------------------------------------------------------
-- Generate travis configuration
-------------------------------------------------------------------------------

{-
Travis CI–specific notes:

* We use -j2 for parallelism, as Travis' virtual environments use 2 cores, per
  https://docs.travis-ci.com/user/reference/overview/#virtualisation-environment-vs-operating-system.
-}

makeTravis
    :: [String]
    -> Config
    -> Project URI Void Package
    -> JobVersions
    -> Either HsCiError Travis -- TODO: writer
makeTravis :: [[Char]]
-> Config
-> Project URI Void Package
-> JobVersions
-> Either HsCiError Travis
makeTravis [[Char]]
argv config :: Config
config@Config {Bool
Natural
[Char]
[[Char]]
[PrettyField ()]
[PackageName]
[Installed]
[ConstraintSet]
Maybe [Char]
Maybe Version
Maybe Jobs
Set [Char]
Set Fold
Map Version [Char]
Version
VersionRange
Ubuntu
PackageScope
HLintConfig
DoctestConfig
DocspecConfig
CopyFields
Components
TestedWithJobs
cfgCabalInstallVersion :: Maybe Version
cfgJobs :: Maybe Jobs
cfgUbuntu :: Ubuntu
cfgTestedWith :: TestedWithJobs
cfgEnabledJobs :: VersionRange
cfgCopyFields :: CopyFields
cfgLocalGhcOptions :: [[Char]]
cfgSubmodules :: Bool
cfgCache :: Bool
cfgInstallDeps :: Bool
cfgInstalled :: [Installed]
cfgTests :: VersionRange
cfgRunTests :: VersionRange
cfgBenchmarks :: VersionRange
cfgHaddock :: VersionRange
cfgHaddockComponents :: Components
cfgNoTestsNoBench :: VersionRange
cfgUnconstrainted :: VersionRange
cfgHeadHackage :: VersionRange
cfgHeadHackageOverride :: Bool
cfgGhcjsTests :: Bool
cfgGhcjsTools :: [PackageName]
cfgTestOutputDirect :: Bool
cfgCheck :: Bool
cfgOnlyBranches :: [[Char]]
cfgIrcChannels :: [[Char]]
cfgIrcNickname :: Maybe [Char]
cfgIrcPassword :: Maybe [Char]
cfgIrcIfInOriginRepo :: Bool
cfgEmailNotifications :: Bool
cfgProjectName :: Maybe [Char]
cfgFolds :: Set Fold
cfgGhcHead :: Bool
cfgPostgres :: Bool
cfgGoogleChrome :: Bool
cfgEnv :: Map Version [Char]
cfgAllowFailures :: VersionRange
cfgLastInSeries :: Bool
cfgLinuxJobs :: VersionRange
cfgMacosJobs :: VersionRange
cfgGhcupCabal :: Bool
cfgGhcupJobs :: VersionRange
cfgGhcupVersion :: Version
cfgApt :: Set [Char]
cfgTravisPatches :: [[Char]]
cfgGitHubPatches :: [[Char]]
cfgInsertVersion :: Bool
cfgErrorMissingMethods :: PackageScope
cfgDoctest :: DoctestConfig
cfgDocspec :: DocspecConfig
cfgHLint :: HLintConfig
cfgConstraintSets :: [ConstraintSet]
cfgRawProject :: [PrettyField ()]
cfgRawTravis :: [Char]
cfgGitHubActionName :: Maybe [Char]
cfgTimeoutMinutes :: Natural
cfgCabalInstallVersion :: Config -> Maybe Version
cfgJobs :: Config -> Maybe Jobs
cfgUbuntu :: Config -> Ubuntu
cfgTestedWith :: Config -> TestedWithJobs
cfgEnabledJobs :: Config -> VersionRange
cfgCopyFields :: Config -> CopyFields
cfgLocalGhcOptions :: Config -> [[Char]]
cfgSubmodules :: Config -> Bool
cfgCache :: Config -> Bool
cfgInstallDeps :: Config -> Bool
cfgInstalled :: Config -> [Installed]
cfgTests :: Config -> VersionRange
cfgRunTests :: Config -> VersionRange
cfgBenchmarks :: Config -> VersionRange
cfgHaddock :: Config -> VersionRange
cfgHaddockComponents :: Config -> Components
cfgNoTestsNoBench :: Config -> VersionRange
cfgUnconstrainted :: Config -> VersionRange
cfgHeadHackage :: Config -> VersionRange
cfgHeadHackageOverride :: Config -> Bool
cfgGhcjsTests :: Config -> Bool
cfgGhcjsTools :: Config -> [PackageName]
cfgTestOutputDirect :: Config -> Bool
cfgCheck :: Config -> Bool
cfgOnlyBranches :: Config -> [[Char]]
cfgIrcChannels :: Config -> [[Char]]
cfgIrcNickname :: Config -> Maybe [Char]
cfgIrcPassword :: Config -> Maybe [Char]
cfgIrcIfInOriginRepo :: Config -> Bool
cfgEmailNotifications :: Config -> Bool
cfgProjectName :: Config -> Maybe [Char]
cfgFolds :: Config -> Set Fold
cfgGhcHead :: Config -> Bool
cfgPostgres :: Config -> Bool
cfgGoogleChrome :: Config -> Bool
cfgEnv :: Config -> Map Version [Char]
cfgAllowFailures :: Config -> VersionRange
cfgLastInSeries :: Config -> Bool
cfgLinuxJobs :: Config -> VersionRange
cfgMacosJobs :: Config -> VersionRange
cfgGhcupCabal :: Config -> Bool
cfgGhcupJobs :: Config -> VersionRange
cfgGhcupVersion :: Config -> Version
cfgApt :: Config -> Set [Char]
cfgTravisPatches :: Config -> [[Char]]
cfgGitHubPatches :: Config -> [[Char]]
cfgInsertVersion :: Config -> Bool
cfgErrorMissingMethods :: Config -> PackageScope
cfgDoctest :: Config -> DoctestConfig
cfgDocspec :: Config -> DocspecConfig
cfgHLint :: Config -> HLintConfig
cfgConstraintSets :: Config -> [ConstraintSet]
cfgRawProject :: Config -> [PrettyField ()]
cfgRawTravis :: Config -> [Char]
cfgGitHubActionName :: Config -> Maybe [Char]
cfgTimeoutMinutes :: Config -> Natural
..} Project URI Void Package
prj jobs :: JobVersions
jobs@JobVersions {Set CompilerVersion
allVersions :: Set CompilerVersion
linuxVersions :: Set CompilerVersion
macosVersions :: Set CompilerVersion
allVersions :: JobVersions -> Set CompilerVersion
linuxVersions :: JobVersions -> Set CompilerVersion
macosVersions :: JobVersions -> Set CompilerVersion
..} = do
    -- before caching: clear some redundant stuff
    [Sh]
beforeCache <- ShM () -> Either HsCiError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromHsCiError e) =>
ShM () -> m [Sh]
runSh (ShM () -> Either HsCiError [Sh])
-> ShM () -> Either HsCiError [Sh]
forall a b. (a -> b) -> a -> b
$ Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgCache (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
comment [Char]
"remove files that are regenerated by 'cabal update'"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.*" -- legacy
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -fv $CABALHOME/packages/hackage.haskell.org/*.json" -- TUF meta-data
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -rfv $CABALHOME/packages/head.hackage" -- if we cache, it will break builds.

    -- before install: we set up the environment, install GHC/cabal on OSX
    [Sh]
beforeInstall <- ShM () -> Either HsCiError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromHsCiError e) =>
ShM () -> m [Sh]
runSh (ShM () -> Either HsCiError [Sh])
-> ShM () -> Either HsCiError [Sh]
forall a b. (a -> b) -> a -> b
$ do
        -- Validity checks
        Config -> JobVersions -> ShM ()
forall (m :: * -> *).
MonadErr HsCiError m =>
Config -> JobVersions -> m ()
checkConfigValidity Config
config JobVersions
jobs

        -- This have to be first
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
anyGHCJS (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unlines
            [ [Char]
"if echo $CC | grep -q ghcjs; then"
            , [Char]
"    GHCJS=true; GHCJSARITH=1;"
            , [Char]
"else"
            , [Char]
"    GHCJS=false; GHCJSARITH=0;"
            , [Char]
"fi"
            ]

        -- Adjust $HC
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"HC=$(echo \"/opt/$CC/bin/ghc\" | sed 's/-/\\//')"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"WITHCOMPILER=\"-w $HC\""
        CompilerRange -> [Char] -> ShM ()
shForJob CompilerRange
RangeGHCJS [Char]
"HC=${HC}js"
        CompilerRange -> [Char] -> ShM ()
shForJob CompilerRange
RangeGHCJS [Char]
"WITHCOMPILER=\"--ghcjs ${WITHCOMPILER}js\""

        -- Needed to work around haskell/cabal#6214
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"HADDOCK=$(echo \"/opt/$CC/bin/haddock\" | sed 's/-/\\//')"
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Set CompilerVersion -> Bool
forall a. Set a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set CompilerVersion
macosVersions) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"if [ \"$TRAVIS_OS_NAME\" = \"osx\" ]; then HADDOCK=$(echo $HADDOCK | sed \"s:^/opt:$HOME/.ghc-install:\"); fi"

        -- Hack: happy needs ghc. Let's install version matching GHCJS.
        -- At the moment, there is only GHCJS-8.4, so we install GHC-8.4.4
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
anyGHCJS (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            CompilerRange -> [Char] -> ShM ()
shForJob CompilerRange
RangeGHCJS ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"PATH=\"/opt/ghc/8.4.4/bin:$PATH\""

        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"HCPKG=\"$HC-pkg\""
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"unset CC"
        -- cabal
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"CABAL=/opt/ghc/bin/cabal"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"CABALHOME=$HOME/.cabal"
        -- PATH
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"export PATH=\"$CABALHOME/bin:$PATH\""
        -- rootdir is useful for manual script additions
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"TOP=$(pwd)"
        -- macOS installing
        let haskellOnMacos :: [Char]
haskellOnMacos = [Char]
"https://haskell.futurice.com/haskell-on-macos.py"
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Set CompilerVersion -> Bool
forall a. Set a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set CompilerVersion
macosVersions) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"if [ \"$TRAVIS_OS_NAME\" = \"osx\" ]; then curl " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
haskellOnMacos [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" | python3 - --make-dirs --install-dir=$HOME/.ghc-install --cabal-alias=3.2.0.0 install cabal-install-3.2.0.0 ${TRAVIS_COMPILER}; fi"
            [Integer] -> [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Integer] -> [Char] -> m ()
sh' [Integer
2034,Integer
2039] [Char]
"if [ \"$TRAVIS_OS_NAME\" = \"osx\" ]; then HC=$HOME/.ghc-install/ghc/bin/$TRAVIS_COMPILER; WITHCOMPILER=\"-w $HC\"; HCPKG=$HOME/.ghc-install/ghc/bin/${TRAVIS_COMPILER}/ghc/ghc-pkg; CABAL=$HOME/.ghc-install/ghc/bin/cabal; fi"
        -- HCNUMVER, numeric HC version, e.g. ghc 7.8.4 is 70804 and 7.10.3 is 71003
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"echo $HCNUMVER"
        -- verbose in .cabal/config is not respected
        -- https://github.com/haskell/cabal/issues/5956
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"CABAL=\"$CABAL -vnormal+nowrap\""

        -- SC2039: In POSIX sh, set option pipefail is undefined. Travis is bash, so it's fine :)
        [Integer] -> [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Integer] -> [Char] -> m ()
sh' [Integer
2039, Integer
3040] [Char]
"set -o pipefail"

        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"TEST=--enable-tests"
        CompilerRange -> [Char] -> ShM ()
shForJob (CompilerRange -> CompilerRange
invertCompilerRange (CompilerRange -> CompilerRange) -> CompilerRange -> CompilerRange
forall a b. (a -> b) -> a -> b
$ VersionRange -> CompilerRange
Range VersionRange
cfgTests) [Char]
"TEST=--disable-tests"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"BENCH=--enable-benchmarks"
        CompilerRange -> [Char] -> ShM ()
shForJob (CompilerRange -> CompilerRange
invertCompilerRange (CompilerRange -> CompilerRange) -> CompilerRange -> CompilerRange
forall a b. (a -> b) -> a -> b
$ VersionRange -> CompilerRange
Range VersionRange
cfgBenchmarks) [Char]
"BENCH=--disable-benchmarks"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"HEADHACKAGE=false"
        CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range VersionRange
cfgHeadHackage CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
\/ Set CompilerVersion -> CompilerRange
RangePoints (CompilerVersion -> Set CompilerVersion
forall a. a -> Set a
S.singleton CompilerVersion
GHCHead)) [Char]
"HEADHACKAGE=true"

        -- create ~/.cabal/config
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -f $CABALHOME/config"
        [Char] -> [[Char]] -> ShM ()
cat [Char]
"$CABALHOME/config"
            [ [Char]
"verbose: normal +nowrap +markoutput" -- https://github.com/haskell/cabal/issues/5956
            , [Char]
"remote-build-reporting: anonymous"
            , [Char]
"write-ghc-environment-files: never"
            , [Char]
"remote-repo-cache: $CABALHOME/packages"
            , [Char]
"logs-dir:          $CABALHOME/logs"
            , [Char]
"world-file:        $CABALHOME/world"
            , [Char]
"extra-prog-path:   $CABALHOME/bin"
            , [Char]
"symlink-bindir:    $CABALHOME/bin"
            , [Char]
"installdir:        $CABALHOME/bin"
            , [Char]
"build-summary:     $CABALHOME/logs/build.log"
            , [Char]
"store-dir:         $CABALHOME/store"
            , [Char]
"install-dirs user"
            , [Char]
"  prefix: $CABALHOME"
            , [Char]
"repository hackage.haskell.org"
            , [Char]
"  url: http://hackage.haskell.org/"
            ]

        -- Add head.hackage repository to ~/.cabal/config
        -- (locally you want to add it to cabal.project)
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Set CompilerVersion -> Bool
forall a. Set a -> Bool
S.null Set CompilerVersion
headGhcVers) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unlines ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$
            [ [Char]
"if $HEADHACKAGE; then"
            ] [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++
            [Char] -> [[Char]]
lines (Quotes -> [Char] -> [[Char]] -> [Char]
catCmd Quotes
Double [Char]
"$CABALHOME/config" ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ Bool -> [[Char]]
headHackageRepoStanza Bool
cfgHeadHackageOverride) [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++
            [ [Char]
"fi"
            ]

    -- in install step we install tools and dependencies
    [Sh]
install <- ShM () -> Either HsCiError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromHsCiError e) =>
ShM () -> m [Sh]
runSh (ShM () -> Either HsCiError [Sh])
-> ShM () -> Either HsCiError [Sh]
forall a b. (a -> b) -> a -> b
$ do
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"${CABAL} --version"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"echo \"$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]\""
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
anyGHCJS (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"node --version"
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"echo $GHCJS"

        -- Cabal jobs
        Maybe Int -> (Int -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (Maybe Jobs
cfgJobs Maybe Jobs -> (Jobs -> Maybe Int) -> Maybe Int
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Jobs -> Maybe Int
cabalJobs) ((Int -> ShM ()) -> ShM ()) -> (Int -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Int
n ->
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"echo 'jobs: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
n [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"' >> $CABALHOME/config"

        -- GHC jobs + ghc-options
        Maybe Int -> (Int -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (Maybe Jobs
cfgJobs Maybe Jobs -> (Jobs -> Maybe Int) -> Maybe Int
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Jobs -> Maybe Int
ghcJobs) ((Int -> ShM ()) -> ShM ()) -> (Int -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Int
m -> do
            CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range (VersionRange -> CompilerRange) -> VersionRange -> CompilerRange
forall a b. (a -> b) -> a -> b
$ Version -> VersionRange
C.orLaterVersion ([Int] -> Version
C.mkVersion [Int
7,Int
8])) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"GHCJOBS=-j" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
m
        [Char] -> [[Char]] -> ShM ()
cat [Char]
"$CABALHOME/config"
            [ [Char]
"program-default-options"
            , [Char]
"  ghc-options: $GHCJOBS +RTS -M6G -RTS"
            ]

        -- output config for debugging purposes
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"cat $CABALHOME/config"

        -- remove project own cabal.project files
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -fv cabal.project cabal.project.local cabal.project.freeze"

        -- Update hackage index.
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"travis_retry ${CABAL} v2-update -v"

        -- Install doctest
        let doctestVersionConstraint :: [Char]
doctestVersionConstraint
                | VersionRange -> Bool
C.isAnyVersion (DoctestConfig -> VersionRange
cfgDoctestVersion DoctestConfig
cfgDoctest) = [Char]
""
                | Bool
otherwise = [Char]
" --constraint='doctest " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ VersionRange -> [Char]
forall a. Pretty a => a -> [Char]
C.prettyShow (DoctestConfig -> VersionRange
cfgDoctestVersion DoctestConfig
cfgDoctest) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'"
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
doctestEnabled (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
            CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range (DoctestConfig -> VersionRange
cfgDoctestEnabled DoctestConfig
cfgDoctest) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
doctestJobVersionRange) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$
                [Char] -> [Char]
cabal ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char]
"v2-install $WITHCOMPILER --ignore-project -j2 doctest" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
doctestVersionConstraint

        -- Install hlint
        let hlintVersionConstraint :: [Char]
hlintVersionConstraint
                | VersionRange -> Bool
C.isAnyVersion (HLintConfig -> VersionRange
cfgHLintVersion HLintConfig
cfgHLint) = [Char]
""
                | Bool
otherwise = [Char]
" --constraint='hlint " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ VersionRange -> [Char]
forall a. Pretty a => a -> [Char]
C.prettyShow (HLintConfig -> VersionRange
cfgHLintVersion HLintConfig
cfgHLint) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'"
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (HLintConfig -> Bool
cfgHLintEnabled HLintConfig
cfgHLint) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            let forHLint :: [Char] -> ShM ()
forHLint = CompilerRange -> [Char] -> ShM ()
shForJob (Set CompilerVersion -> VersionRange -> HLintJob -> CompilerRange
hlintJobVersionRange Set CompilerVersion
allVersions  VersionRange
cfgHeadHackage (HLintConfig -> HLintJob
cfgHLintJob HLintConfig
cfgHLint))
            if HLintConfig -> Bool
cfgHLintDownload HLintConfig
cfgHLint
            then do
                -- install --dry-run and use perl regex magic to find a hlint version
                -- -v is important
                [Char] -> ShM ()
forHLint ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"HLINTVER=$(cd /tmp && (${CABAL} v2-install -v $WITHCOMPILER --dry-run hlint " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
hlintVersionConstraint [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" |  perl -ne 'if (/\\bhlint-(\\d+(\\.\\d+)*)\\b/) { print \"$1\"; last; }')); echo \"HLint version $HLINTVER\""
                [Char] -> ShM ()
forHLint ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"if [ ! -e $HOME/.hlint/hlint-$HLINTVER/hlint ]; then " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> [Char]
unwords
                    [ [Char]
"echo \"Downloading HLint version $HLINTVER\";"
                    , [Char]
"mkdir -p $HOME/.hlint;"
                    , [Char]
"curl --write-out 'Status Code: %{http_code} Redirects: %{num_redirects} Total time: %{time_total} Total Dsize: %{size_download}\\n' --silent --location --output $HOME/.hlint/hlint-$HLINTVER.tar.gz \"https://github.com/ndmitchell/hlint/releases/download/v$HLINTVER/hlint-$HLINTVER-x86_64-linux.tar.gz\";"
                    , [Char]
"tar -xzv -f $HOME/.hlint/hlint-$HLINTVER.tar.gz -C $HOME/.hlint;"
                    , [Char]
"fi"
                    ]
                [Char] -> ShM ()
forHLint [Char]
"mkdir -p $CABALHOME/bin && ln -sf \"$HOME/.hlint/hlint-$HLINTVER/hlint\" $CABALHOME/bin/hlint"
                [Char] -> ShM ()
forHLint [Char]
"hlint --version"

            else [Char] -> ShM ()
forHLint ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char]
"v2-install $WITHCOMPILER --ignore-project -j2 hlint" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
hlintVersionConstraint

        -- Install cabal-plan (for ghcjs tests)
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
anyGHCJS Bool -> Bool -> Bool
&& Bool
cfgGhcjsTests) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            CompilerRange -> [Char] -> ShM ()
shForJob CompilerRange
RangeGHCJS ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal [Char]
"v2-install -w ghc-8.4.4 --ignore-project -j2 cabal-plan --constraint='cabal-plan ^>=0.6.0.0' --constraint='cabal-plan +exe'"

        -- Install happy
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
anyGHCJS (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ [PackageName] -> (PackageName -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [PackageName]
cfgGhcjsTools ((PackageName -> ShM ()) -> ShM ())
-> (PackageName -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \PackageName
t ->
            CompilerRange -> [Char] -> ShM ()
shForJob CompilerRange
RangeGHCJS ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char]
"v2-install -w ghc-8.4.4 --ignore-project -j2" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ PackageName -> [Char]
forall a. Pretty a => a -> [Char]
C.prettyShow PackageName
t

        -- create cabal.project file
        Bool -> ShM ()
generateCabalProject Bool
False

        -- autoreconf
        [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{[Char]
pkgDir :: [Char]
pkgDir :: Package -> [Char]
pkgDir} ->
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"if [ -f \"" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
pkgDir [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"/configure.ac\" ]; then (cd \"" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
pkgDir [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\" && autoreconf -i); fi"

        -- dump install plan
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal [Char]
"v2-freeze $WITHCOMPILER ${TEST} ${BENCH}"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm  cabal.project.freeze"

        -- Install dependencies
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgInstallDeps (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            -- install dependencies
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabalTW [Char]
"v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all"

            -- install dependencies for no-test-no-bench
            CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range VersionRange
cfgNoTestsNoBench) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabalTW [Char]
"v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all"

    -- Here starts the actual work to be performed for the package under test;
    -- any command which exits with a non-zero exit code causes the build to fail.
    [Sh]
script <- ShM () -> Either HsCiError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromHsCiError e) =>
ShM () -> m [Sh]
runSh (ShM () -> Either HsCiError [Sh])
-> ShM () -> Either HsCiError [Sh]
forall a b. (a -> b) -> a -> b
$ do
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)"

        -- sdist
        Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldSDist [Char]
"Packaging..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal [Char]
"v2-sdist all"

        -- unpack
        Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldUnpack [Char]
"Unpacking..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/"
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"cd ${DISTDIR} || false" -- fail explicitly, makes SC happier
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \\;"
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm       '{}' \\;"

            [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{[Char]
pkgName :: [Char]
pkgName :: Package -> [Char]
pkgName} -> do
                [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
pkgNameDirVariable' [Char]
pkgName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"=\"$(find . -maxdepth 1 -type d -regex '.*/" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
pkgName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"-[0-9.]*')\""

            Bool -> ShM ()
generateCabalProject Bool
True

            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
anyGHCJS Bool -> Bool -> Bool
&& Bool
cfgGhcjsTests) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unlines ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$
                [ [Char]
"pkgdir() {"
                , [Char]
"  case $1 in"
                ] [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++
                [ [Char]
"    " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
pkgName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
") echo " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
pkgNameDirVariable [Char]
pkgName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" ;;"
                | Pkg{[Char]
pkgName :: Package -> [Char]
pkgName :: [Char]
pkgName} <- [Package]
pkgs
                ] [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++
                [ [Char]
"  esac"
                , [Char]
"}"
                ]

        -- build no-tests no-benchmarks
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (VersionRange -> VersionRange -> Bool
equivVersionRanges VersionRange
C.noVersion VersionRange
cfgNoTestsNoBench) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldBuild [Char]
"Building..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
comment [Char]
"this builds all libraries and executables (without tests/benchmarks)"
            CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range VersionRange
cfgNoTestsNoBench) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal [Char]
"v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all"

        -- build everything
        Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldBuildEverything [Char]
"Building with tests and benchmarks..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
comment [Char]
"build & run tests, build benchmarks"
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal [Char]
"v2-build $WITHCOMPILER ${TEST} ${BENCH} all --write-ghc-environment-files=always"

        -- cabal v2-test fails if there are no test-suites.
        Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldTest [Char]
"Testing..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            CompilerRange -> [Char] -> ShM ()
shForJob (CompilerRange
RangeGHC CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ VersionRange -> CompilerRange
Range (VersionRange
cfgTests VersionRange -> VersionRange -> VersionRange
forall a. Lattice a => a -> a -> a
/\ VersionRange
cfgRunTests) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
hasTests) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$
                [Char] -> [Char]
cabal ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char]
"v2-test $WITHCOMPILER ${TEST} ${BENCH} all" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
testShowDetails

            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgGhcjsTests (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ CompilerRange -> [Char] -> ShM ()
shForJob (CompilerRange
RangeGHCJS CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
hasTests) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unwords
                [ [Char]
"cabal-plan list-bins '*:test:*' | while read -r line; do"
                , [Char]
"testpkg=$(echo \"$line\" | perl -pe 's/:.*//');"
                , [Char]
"testexe=$(echo \"$line\" | awk '{ print $2 }');"
                , [Char]
"echo \"testing $textexe in package $textpkg\";"
                , [Char]
"(cd \"$(pkgdir $testpkg)\" && nodejs \"$testexe\".jsexe/all.js);"
                , [Char]
"done"
                ]

        -- doctest
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
doctestEnabled (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldDoctest [Char]
"Doctest..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            let doctestOptions :: [Char]
doctestOptions = [[Char]] -> [Char]
unwords ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ DoctestConfig -> [[Char]]
cfgDoctestOptions DoctestConfig
cfgDoctest
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"$CABAL v2-build $WITHCOMPILER ${TEST} ${BENCH} all --dry-run"
            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([PackageName] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([PackageName] -> Bool) -> [PackageName] -> Bool
forall a b. (a -> b) -> a -> b
$ DoctestConfig -> [PackageName]
cfgDoctestFilterEnvPkgs DoctestConfig
cfgDoctest) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                -- cabal-install mangles unit ids on the OSX,
                -- removing the vowels to make filepaths shorter
                let manglePkgNames :: String -> [String]
                    manglePkgNames :: [Char] -> [[Char]]
manglePkgNames [Char]
n
                        | Set CompilerVersion -> Bool
forall a. Set a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set CompilerVersion
macosVersions = [[Char]
n]
                        | Bool
otherwise          = [[Char]
n, (Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
filter Char -> Bool
notVowel [Char]
n]
                      where
                        notVowel :: Char -> Bool
notVowel Char
c = Char -> [Char] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
notElem Char
c ([Char]
"aeiou" :: String)
                let filterPkgs :: [Char]
filterPkgs = [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"|" ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$ (PackageName -> [[Char]]) -> [PackageName] -> [[Char]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Char] -> [[Char]]
manglePkgNames ([Char] -> [[Char]])
-> (PackageName -> [Char]) -> PackageName -> [[Char]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> [Char]
C.unPackageName) ([PackageName] -> [[Char]]) -> [PackageName] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ DoctestConfig -> [PackageName]
cfgDoctestFilterEnvPkgs DoctestConfig
cfgDoctest
                [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"perl -i -e 'while (<ARGV>) { print unless /package-id\\s+(" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
filterPkgs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")-\\d+(\\.\\d+)*/; }' .ghc.environment.*"
            [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{[Char]
pkgName :: Package -> [Char]
pkgName :: [Char]
pkgName,GenericPackageDescription
pkgGpd :: GenericPackageDescription
pkgGpd :: Package -> GenericPackageDescription
pkgGpd,Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs} ->
                Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([Char] -> PackageName
C.mkPackageName [Char]
pkgName PackageName -> [PackageName] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` DoctestConfig -> [PackageName]
cfgDoctestFilterSrcPkgs DoctestConfig
cfgDoctest) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                    [[[Char]]] -> ([[Char]] -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (GenericPackageDescription -> [[[Char]]]
doctestArgs GenericPackageDescription
pkgGpd) (([[Char]] -> ShM ()) -> ShM ()) -> ([[Char]] -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \[[Char]]
args -> do
                        let args' :: [Char]
args' = [[Char]] -> [Char]
unwords [[Char]]
args
                        let vr :: CompilerRange
vr = VersionRange -> CompilerRange
Range (DoctestConfig -> VersionRange
cfgDoctestEnabled DoctestConfig
cfgDoctest)
                              CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
doctestJobVersionRange
                              CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs
                        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([[Char]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
args) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ CompilerRange -> [Char] -> ShM ()
shForJob  CompilerRange
vr ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$
                            [Char]
"(cd " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
pkgNameDirVariable [Char]
pkgName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" && doctest " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
doctestOptions [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
args' [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"

        -- hlint
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (HLintConfig -> Bool
cfgHLintEnabled HLintConfig
cfgHLint) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldHLint [Char]
"HLint.." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            let [Char]
"" <+> :: [Char] -> [Char] -> [Char]
<+> [Char]
ys = [Char]
ys
                [Char]
xs <+> [Char]
"" = [Char]
xs
                [Char]
xs <+> [Char]
ys = [Char]
xs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
ys

                prependSpace :: [Char] -> [Char]
prependSpace [Char]
"" = [Char]
""
                prependSpace [Char]
xs = [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
xs

            let hlintOptions :: [Char]
hlintOptions = [Char] -> [Char]
prependSpace ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char] -> ([Char] -> [Char]) -> Maybe [Char] -> [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Char]
"" ([Char]
"-h ${TOP}/" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++) (HLintConfig -> Maybe [Char]
cfgHLintYaml HLintConfig
cfgHLint) [Char] -> [Char] -> [Char]
<+> [[Char]] -> [Char]
unwords (HLintConfig -> [[Char]]
cfgHLintOptions HLintConfig
cfgHLint)

            [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{[Char]
pkgName :: Package -> [Char]
pkgName :: [Char]
pkgName,GenericPackageDescription
pkgGpd :: Package -> GenericPackageDescription
pkgGpd :: GenericPackageDescription
pkgGpd,Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs} -> do
                [[[Char]]] -> ([[Char]] -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (GenericPackageDescription -> [[[Char]]]
hlintArgs GenericPackageDescription
pkgGpd) (([[Char]] -> ShM ()) -> ShM ()) -> ([[Char]] -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \[[Char]]
args -> do
                    let args' :: [Char]
args' = [[Char]] -> [Char]
unwords [[Char]]
args
                    Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([[Char]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
args) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                        CompilerRange -> [Char] -> ShM ()
shForJob (Set CompilerVersion -> VersionRange -> HLintJob -> CompilerRange
hlintJobVersionRange Set CompilerVersion
allVersions VersionRange
cfgHeadHackage (HLintConfig -> HLintJob
cfgHLintJob HLintConfig
cfgHLint) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$
                        [Char]
"(cd " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
pkgNameDirVariable [Char]
pkgName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" && hlint" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
hlintOptions [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
args' [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")"

        -- cabal check
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgCheck (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldCheck [Char]
"cabal check..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{[Char]
pkgName :: Package -> [Char]
pkgName :: [Char]
pkgName,Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs} -> CompilerRange -> [Char] -> ShM ()
shForJob (Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$
                [Char]
"(cd " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
pkgNameDirVariable [Char]
pkgName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" && ${CABAL} -vnormal check)"

        -- haddock
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (VersionRange -> VersionRange -> Bool
equivVersionRanges VersionRange
C.noVersion VersionRange
cfgHaddock) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
            Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldHaddock [Char]
"haddock..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                CompilerRange -> [Char] -> ShM ()
shForJob (CompilerRange
RangeGHC CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ VersionRange -> CompilerRange
Range VersionRange
cfgHaddock) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char]
"v2-haddock --haddock-all $WITHCOMPILER " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
withHaddock [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" ${TEST} ${BENCH} all"

        -- unconstained build
        -- Have to build last, as we remove cabal.project.local
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (VersionRange -> VersionRange -> Bool
equivVersionRanges VersionRange
C.noVersion VersionRange
cfgUnconstrainted) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
            Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldBuildInstalled [Char]
"Building without installed constraints for packages in global-db..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range VersionRange
cfgUnconstrainted) [Char]
"rm -f cabal.project.local"
                CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range VersionRange
cfgUnconstrainted) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal [Char]
"v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all"

        -- and now, as we don't have cabal.project.local;
        -- we can test with other constraint sets
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([ConstraintSet] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ConstraintSet]
cfgConstraintSets) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
comment [Char]
"Constraint sets"
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -f cabal.project.local"

            [ConstraintSet] -> (ConstraintSet -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [ConstraintSet]
cfgConstraintSets ((ConstraintSet -> ShM ()) -> ShM ())
-> (ConstraintSet -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \ConstraintSet
cs -> do
                let name :: [Char]
name            = ConstraintSet -> [Char]
csName ConstraintSet
cs
                let shForCs :: [Char] -> ShM ()
shForCs         = CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range (ConstraintSet -> VersionRange
csGhcVersions ConstraintSet
cs))
                let shForCs' :: CompilerRange -> [Char] -> ShM ()
shForCs' CompilerRange
r      = CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range (ConstraintSet -> VersionRange
csGhcVersions ConstraintSet
cs) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
r)
                let testFlag :: [Char]
testFlag        = if ConstraintSet -> Bool
csTests ConstraintSet
cs then [Char]
"--enable-tests" else [Char]
"--disable-tests"
                let benchFlag :: [Char]
benchFlag       = if ConstraintSet -> Bool
csBenchmarks ConstraintSet
cs then [Char]
"--enable-benchmarks" else [Char]
"--disable-benchmarks"
                let constraintFlags :: [[Char]]
constraintFlags = ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (\[Char]
x ->  [Char]
"--constraint='" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
x [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'") (ConstraintSet -> [[Char]]
csConstraints ConstraintSet
cs)
                let allFlags :: [Char]
allFlags        = [[Char]] -> [Char]
unwords ([Char]
testFlag [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: [Char]
benchFlag [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: [[Char]]
constraintFlags)

                Fold -> [Char] -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh' Fold
FoldConstraintSets [Char]
name ([Char]
"Constraint set " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name) Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                    [Char] -> ShM ()
shForCs ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char]
"v2-build $WITHCOMPILER " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
allFlags [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" --dependencies-only -j2 all"
                    [Char] -> ShM ()
shForCs ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char]
"v2-build $WITHCOMPILER " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
allFlags [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" all"
                    Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ConstraintSet -> Bool
csRunTests ConstraintSet
cs) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                        CompilerRange -> [Char] -> ShM ()
shForCs' CompilerRange
hasTests ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char]
"v2-test $WITHCOMPILER " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
allFlags [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" all --test-show-details=direct"
                    Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ConstraintSet -> Bool
csHaddock ConstraintSet
cs) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                        [Char] -> ShM ()
shForCs ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
cabal ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char]
"v2-haddock --haddock-all $WITHCOMPILER " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
withHaddock [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
allFlags [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" all"

        -- At the end, we allow some raw travis scripts
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([Char] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
cfgRawTravis) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
comment [Char]
"Raw travis commands"
            ([Char] -> ShM ()) -> [[Char]] -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh
                [ [Char]
l
                | [Char]
l <- [Char] -> [[Char]]
lines [Char]
cfgRawTravis
                , Bool -> Bool
not ([Char] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
l)
                ]

    -- assemble travis configuration
    Travis -> Either HsCiError Travis
forall a. a -> Either HsCiError a
forall (m :: * -> *) a. Monad m => a -> m a
return Travis
        { travisLanguage :: [Char]
travisLanguage      = [Char]
"c"
        , travisUbuntu :: Ubuntu
travisUbuntu        = Ubuntu
cfgUbuntu
        , travisGit :: TravisGit
travisGit           = TravisGit
            { tgSubmodules :: Bool
tgSubmodules = Bool
cfgSubmodules
            }
        , travisCache :: TravisCache
travisCache         = TravisCache
            { tcDirectories :: [[Char]]
tcDirectories = ListBuilder [Char] () -> [[Char]]
forall x. ListBuilder x () -> [x]
buildList (ListBuilder [Char] () -> [[Char]])
-> ListBuilder [Char] () -> [[Char]]
forall a b. (a -> b) -> a -> b
$ Bool -> ListBuilder [Char] () -> ListBuilder [Char] ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgCache (ListBuilder [Char] () -> ListBuilder [Char] ())
-> ListBuilder [Char] () -> ListBuilder [Char] ()
forall a b. (a -> b) -> a -> b
$ do
                [Char] -> ListBuilder [Char] ()
forall x. x -> ListBuilder x ()
item [Char]
"$HOME/.cabal/packages"
                [Char] -> ListBuilder [Char] ()
forall x. x -> ListBuilder x ()
item [Char]
"$HOME/.cabal/store"
                [Char] -> ListBuilder [Char] ()
forall x. x -> ListBuilder x ()
item [Char]
"$HOME/.hlint"
                -- on OSX ghc is installed in $HOME so we can cache it
                -- independently of linux
                Bool -> ListBuilder [Char] () -> ListBuilder [Char] ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
cfgCache Bool -> Bool -> Bool
&& Bool -> Bool
not (Set CompilerVersion -> Bool
forall a. Set a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set CompilerVersion
macosVersions)) (ListBuilder [Char] () -> ListBuilder [Char] ())
-> ListBuilder [Char] () -> ListBuilder [Char] ()
forall a b. (a -> b) -> a -> b
$ do
                    [Char] -> ListBuilder [Char] ()
forall x. x -> ListBuilder x ()
item [Char]
"$HOME/.ghc-install"
            }
        , travisBranches :: TravisBranches
travisBranches      = TravisBranches
            { tbOnly :: [[Char]]
tbOnly = [[Char]]
cfgOnlyBranches
            }
        , travisNotifications :: TravisNotifications
travisNotifications = TravisNotifications
            { tnIRC :: Maybe TravisIRC
tnIRC = Bool -> TravisIRC -> Maybe TravisIRC
forall {a}. Bool -> a -> Maybe a
justIf (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [[Char]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
cfgIrcChannels) (TravisIRC -> Maybe TravisIRC) -> TravisIRC -> Maybe TravisIRC
forall a b. (a -> b) -> a -> b
$ TravisIRC
                { tiChannels :: [[Char]]
tiChannels = [[Char]]
cfgIrcChannels
                , tiSkipJoin :: Bool
tiSkipJoin = Bool
True
                , tiTemplate :: [[Char]]
tiTemplate =
                    [ [Char]
"\x0313" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
projectName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\x03/\x0306%{branch}\x03 \x0314%{commit}\x03 %{build_url} %{message}"
                    ]
                , tiNick :: Maybe [Char]
tiNick     = Maybe [Char]
cfgIrcNickname
                , tiPassword :: Maybe [Char]
tiPassword = Maybe [Char]
cfgIrcPassword
                }
            , tnEmail :: Bool
tnEmail = Bool
cfgEmailNotifications
            }
        , travisServices :: [[Char]]
travisServices      = ListBuilder [Char] () -> [[Char]]
forall x. ListBuilder x () -> [x]
buildList (ListBuilder [Char] () -> [[Char]])
-> ListBuilder [Char] () -> [[Char]]
forall a b. (a -> b) -> a -> b
$ do
            Bool -> ListBuilder [Char] () -> ListBuilder [Char] ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
cfgPostgres (ListBuilder [Char] () -> ListBuilder [Char] ())
-> ListBuilder [Char] () -> ListBuilder [Char] ()
forall a b. (a -> b) -> a -> b
$ [Char] -> ListBuilder [Char] ()
forall x. x -> ListBuilder x ()
item [Char]
"postgresql"
        , travisAddons :: TravisAddons
travisAddons        = TravisAddons
            { taApt :: TravisApt
taApt          = [[Char]] -> [TravisAptSource] -> TravisApt
TravisApt [] []
            , taPostgres :: Maybe [Char]
taPostgres     = if Bool
cfgPostgres then [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
"10" else Maybe [Char]
forall a. Maybe a
Nothing
            , taGoogleChrome :: Bool
taGoogleChrome = Bool
cfgGoogleChrome
            }
        , travisMatrix :: TravisMatrix
travisMatrix        = TravisMatrix
            { tmInclude :: [TravisJob]
tmInclude = ListBuilder TravisJob () -> [TravisJob]
forall x. ListBuilder x () -> [x]
buildList (ListBuilder TravisJob () -> [TravisJob])
-> ListBuilder TravisJob () -> [TravisJob]
forall a b. (a -> b) -> a -> b
$ do
                let tellJob :: Bool -> CompilerVersion -> ListBuilder TravisJob ()
                    tellJob :: Bool -> CompilerVersion -> ListBuilder TravisJob ()
tellJob Bool
osx CompilerVersion
gv = do
                        let cvs :: [Char]
cvs = Maybe Version -> [Char]
dispCabalVersion (Maybe Version -> [Char]) -> Maybe Version -> [Char]
forall a b. (a -> b) -> a -> b
$ Maybe Version -> CompilerVersion -> Maybe Version
correspondingCabalVersion Maybe Version
cfgCabalInstallVersion CompilerVersion
gv
                        let gvs :: [Char]
gvs = CompilerVersion -> [Char]
dispGhcVersion CompilerVersion
gv

                        -- https://docs.travis-ci.com/user/installing-dependencies/#adding-apt-sources
                        let hvrppa :: TravisAptSource
                            hvrppa :: TravisAptSource
hvrppa = [Char] -> Maybe [Char] -> TravisAptSource
TravisAptSourceLine ([Char]
"deb http://ppa.launchpad.net/hvr/ghc/ubuntu " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Ubuntu -> [Char]
forall a. Pretty a => a -> [Char]
C.prettyShow Ubuntu
cfgUbuntu [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" main") ([Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286")

                        let ghcjsAptSources :: [TravisAptSource]
                            ghcjsAptSources :: [TravisAptSource]
ghcjsAptSources | Bool -> Bool
not (CompilerVersion -> Bool
isGHCJS CompilerVersion
gv) = []
                                            | Bool
otherwise =
                                [ [Char] -> Maybe [Char] -> TravisAptSource
TravisAptSourceLine ([Char]
"deb http://ppa.launchpad.net/hvr/ghcjs/ubuntu " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Ubuntu -> [Char]
forall a. Pretty a => a -> [Char]
C.prettyShow Ubuntu
cfgUbuntu [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" main") Maybe [Char]
forall a. Maybe a
Nothing
                                , [Char] -> Maybe [Char] -> TravisAptSource
TravisAptSourceLine ([Char]
"deb https://deb.nodesource.com/node_10.x " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Ubuntu -> [Char]
forall a. Pretty a => a -> [Char]
C.prettyShow Ubuntu
cfgUbuntu [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" main") ([Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
"https://deb.nodesource.com/gpgkey/nodesource.gpg.key")
                                ]

                        let ghcjsPackages :: [String]
                            ghcjsPackages :: [[Char]]
ghcjsPackages = case CompilerVersion -> Maybe Version
maybeGHCJS CompilerVersion
gv of
                                Just Version
v -> [ [Char]
"ghc-" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Version -> [Char]
forall a. Pretty a => a -> [Char]
C.prettyShow Version
v', [Char]
"nodejs" ] where
                                    -- TODO: partial maximum
                                    v' :: Version
v' = [Version] -> Version
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Version] -> Version) -> [Version] -> Version
forall a b. (a -> b) -> a -> b
$ (Version -> Bool) -> [Version] -> [Version]
forall a. (a -> Bool) -> [a] -> [a]
filter (Version -> VersionRange -> Bool
`C.withinRange` Version -> VersionRange
C.withinVersion Version
v) ([Version] -> [Version]) -> [Version] -> [Version]
forall a b. (a -> b) -> a -> b
$ [Version]
knownGhcVersions
                                Maybe Version
Nothing -> []

                        TravisJob -> ListBuilder TravisJob ()
forall x. x -> ListBuilder x ()
item TravisJob
                            { tjCompiler :: [Char]
tjCompiler = [Char]
gvs
                            , tjOS :: [Char]
tjOS       = if Bool
osx then [Char]
"osx" else [Char]
"linux"
                            , tjEnv :: Maybe [Char]
tjEnv      = case CompilerVersion
gv of
                                GHC Version
v -> Version -> Map Version [Char] -> Maybe [Char]
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Version
v Map Version [Char]
cfgEnv
                                CompilerVersion
_     -> Maybe [Char]
forall a. Maybe a
Nothing
                            , tjAddons :: TravisAddons
tjAddons   = TravisAddons
                                { taApt :: TravisApt
taApt = TravisApt
                                    { taPackages :: [[Char]]
taPackages = [Char]
gvs [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: ([Char]
"cabal-install-" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
cvs) [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: [[Char]]
ghcjsPackages [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ Set [Char] -> [[Char]]
forall a. Set a -> [a]
S.toList Set [Char]
cfgApt
                                    , taSources :: [TravisAptSource]
taSources  = TravisAptSource
hvrppa TravisAptSource -> [TravisAptSource] -> [TravisAptSource]
forall a. a -> [a] -> [a]
: [TravisAptSource]
ghcjsAptSources
                                    }

                                , taPostgres :: Maybe [Char]
taPostgres     = Maybe [Char]
forall a. Maybe a
Nothing
                                , taGoogleChrome :: Bool
taGoogleChrome = Bool
False
                                }
                            }

                [CompilerVersion]
-> (CompilerVersion -> ListBuilder TravisJob ())
-> ListBuilder TravisJob ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ ([CompilerVersion] -> [CompilerVersion]
forall a. [a] -> [a]
reverse ([CompilerVersion] -> [CompilerVersion])
-> [CompilerVersion] -> [CompilerVersion]
forall a b. (a -> b) -> a -> b
$ Set CompilerVersion -> [CompilerVersion]
forall a. Set a -> [a]
S.toList Set CompilerVersion
linuxVersions) ((CompilerVersion -> ListBuilder TravisJob ())
 -> ListBuilder TravisJob ())
-> (CompilerVersion -> ListBuilder TravisJob ())
-> ListBuilder TravisJob ()
forall a b. (a -> b) -> a -> b
$ Bool -> CompilerVersion -> ListBuilder TravisJob ()
tellJob Bool
False
                [CompilerVersion]
-> (CompilerVersion -> ListBuilder TravisJob ())
-> ListBuilder TravisJob ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ ([CompilerVersion] -> [CompilerVersion]
forall a. [a] -> [a]
reverse ([CompilerVersion] -> [CompilerVersion])
-> [CompilerVersion] -> [CompilerVersion]
forall a b. (a -> b) -> a -> b
$ Set CompilerVersion -> [CompilerVersion]
forall a. Set a -> [a]
S.toList Set CompilerVersion
macosVersions) ((CompilerVersion -> ListBuilder TravisJob ())
 -> ListBuilder TravisJob ())
-> (CompilerVersion -> ListBuilder TravisJob ())
-> ListBuilder TravisJob ()
forall a b. (a -> b) -> a -> b
$ Bool -> CompilerVersion -> ListBuilder TravisJob ()
tellJob Bool
True

            , tmAllowFailures :: [TravisAllowFailure]
tmAllowFailures =
                [ [Char] -> TravisAllowFailure
TravisAllowFailure ([Char] -> TravisAllowFailure) -> [Char] -> TravisAllowFailure
forall a b. (a -> b) -> a -> b
$ CompilerVersion -> [Char]
dispGhcVersion CompilerVersion
compiler
                | CompilerVersion
compiler <- Set CompilerVersion -> [CompilerVersion]
forall a. Set a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Set CompilerVersion
allVersions
                , CompilerVersion -> Bool
isGHCHead CompilerVersion
compiler Bool -> Bool -> Bool
|| Bool -> (Version -> Bool) -> CompilerVersion -> Bool
forall a. a -> (Version -> a) -> CompilerVersion -> a
maybeGHC Bool
False (Version -> VersionRange -> Bool
`C.withinRange` VersionRange
cfgAllowFailures) CompilerVersion
compiler
                ]
            }
        , travisBeforeCache :: [Sh]
travisBeforeCache   = [Sh]
beforeCache
        , travisBeforeInstall :: [Sh]
travisBeforeInstall = [Sh]
beforeInstall
        , travisInstall :: [Sh]
travisInstall       = [Sh]
install
        , travisScript :: [Sh]
travisScript        = [Sh]
script
        }
  where
    Auxiliary {Bool
[Char]
[URI]
[Package]
CompilerRange
[Char] -> [PrettyField ()]
doctestEnabled :: Bool
pkgs :: [Package]
hasTests :: CompilerRange
testShowDetails :: [Char]
projectName :: [Char]
uris :: [URI]
docspecEnabled :: Bool
hasLibrary :: Bool
extraCabalProjectFields :: [Char] -> [PrettyField ()]
anyJobUsesHeadHackage :: Bool
anyJobUsesPreviewGHC :: Bool
runHaddock :: Bool
haddockFlags :: [Char]
pkgs :: Auxiliary -> [Package]
uris :: Auxiliary -> [URI]
projectName :: Auxiliary -> [Char]
doctestEnabled :: Auxiliary -> Bool
docspecEnabled :: Auxiliary -> Bool
hasTests :: Auxiliary -> CompilerRange
hasLibrary :: Auxiliary -> Bool
extraCabalProjectFields :: Auxiliary -> [Char] -> [PrettyField ()]
testShowDetails :: Auxiliary -> [Char]
anyJobUsesHeadHackage :: Auxiliary -> Bool
anyJobUsesPreviewGHC :: Auxiliary -> Bool
runHaddock :: Auxiliary -> Bool
haddockFlags :: Auxiliary -> [Char]
..} = Config -> Project URI Void Package -> JobVersions -> Auxiliary
auxiliary Config
config Project URI Void Package
prj JobVersions
jobs

    justIf :: Bool -> a -> Maybe a
justIf Bool
True a
x  = a -> Maybe a
forall a. a -> Maybe a
Just a
x
    justIf Bool
False a
_ = Maybe a
forall a. Maybe a
Nothing

    -- TODO: should this be part of MonadSh ?
    foldedSh :: Fold -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
label = Fold -> [Char] -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh' Fold
label [Char]
""

    anyGHCJS :: Bool
anyGHCJS = (CompilerVersion -> Bool) -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any CompilerVersion -> Bool
isGHCJS Set CompilerVersion
allVersions

    -- https://github.com/travis-ci/docs-travis-ci-com/issues/949#issuecomment-276755003
    -- https://github.com/travis-ci/travis-rubies/blob/9f7962a881c55d32da7c76baefc58b89e3941d91/build.sh#L38-L44
    -- https://github.com/travis-ci/travis-build/blob/91bf066/lib/travis/build/shell/dsl.rb#L58-L63
    foldedSh' :: Fold -> String -> String -> Set Fold -> ShM () -> ShM ()
    foldedSh' :: Fold -> [Char] -> [Char] -> Set Fold -> ShM () -> ShM ()
foldedSh' Fold
label [Char]
sfx [Char]
plabel Set Fold
labels ShM ()
block
        | Fold
label Fold -> Set Fold -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.notMember` Set Fold
labels = [Char] -> ShM () -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m () -> m ()
commentedBlock [Char]
plabel ShM ()
block
        | Bool
otherwise = case ShM () -> Either HsCiError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromHsCiError e) =>
ShM () -> m [Sh]
runSh ShM ()
block of
            Left HsCiError
err  -> HsCiError -> ShM ()
forall a. HsCiError -> ShM a
forall e (m :: * -> *) a. MonadErr e m => e -> m a
throwErr HsCiError
err
            Right [Sh]
shs
                | (Sh -> Bool) -> [Sh] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Sh -> Bool
isComment [Sh]
shs -> () -> ShM ()
forall a. a -> ShM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
                | Bool
otherwise         -> (([Sh] -> [Sh]) -> Either HsCiError ([Sh] -> [Sh], ())) -> ShM ()
forall a.
(([Sh] -> [Sh]) -> Either HsCiError ([Sh] -> [Sh], a)) -> ShM a
ShM ((([Sh] -> [Sh]) -> Either HsCiError ([Sh] -> [Sh], ())) -> ShM ())
-> (([Sh] -> [Sh]) -> Either HsCiError ([Sh] -> [Sh], ()))
-> ShM ()
forall a b. (a -> b) -> a -> b
$ \[Sh] -> [Sh]
shs1 -> ([Sh] -> [Sh], ()) -> Either HsCiError ([Sh] -> [Sh], ())
forall a b. b -> Either a b
Right (([Sh] -> [Sh], ()) -> Either HsCiError ([Sh] -> [Sh], ()))
-> ([Sh] -> [Sh], ()) -> Either HsCiError ([Sh] -> [Sh], ())
forall a b. (a -> b) -> a -> b
$
                    ( [Sh] -> [Sh]
shs1
                    ([Sh] -> [Sh]) -> ([Sh] -> [Sh]) -> [Sh] -> [Sh]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char] -> Sh
Comment [Char]
plabel Sh -> [Sh] -> [Sh]
forall a. a -> [a] -> [a]
:)
                    ([Sh] -> [Sh]) -> ([Sh] -> [Sh]) -> [Sh] -> [Sh]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char] -> Sh
Sh ([Char]
"echo '" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
plabel [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"' && echo -en 'travis_fold:start:" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
label' [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\\\\r'") Sh -> [Sh] -> [Sh]
forall a. a -> [a] -> [a]
:)
                    ([Sh] -> [Sh]) -> ([Sh] -> [Sh]) -> [Sh] -> [Sh]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Sh]
shs [Sh] -> [Sh] -> [Sh]
forall a. [a] -> [a] -> [a]
++)
                    ([Sh] -> [Sh]) -> ([Sh] -> [Sh]) -> [Sh] -> [Sh]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char] -> Sh
Sh ([Char]
"echo -en 'travis_fold:end:" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
label' [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\\\\r'") Sh -> [Sh] -> [Sh]
forall a. a -> [a] -> [a]
:)
                    -- return ()
                    , ()
                    )
      where
        label' :: [Char]
label' | [Char] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
sfx  = Fold -> [Char]
showFold Fold
label
               | Bool
otherwise = Fold -> [Char]
showFold Fold
label [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"-" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
sfx


    -- GHC versions which need head.hackage
    headGhcVers :: Set CompilerVersion
    headGhcVers :: Set CompilerVersion
headGhcVers = (CompilerVersion -> Bool)
-> Set CompilerVersion -> Set CompilerVersion
forall a. (a -> Bool) -> Set a -> Set a
S.filter (VersionRange -> CompilerVersion -> Bool
usesHeadHackage VersionRange
cfgHeadHackage) Set CompilerVersion
allVersions

    cabal :: String -> String
    cabal :: [Char] -> [Char]
cabal [Char]
cmd = [Char]
"${CABAL} " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
cmd

    cabalTW :: String -> String
    cabalTW :: [Char] -> [Char]
cabalTW [Char]
cmd = [Char]
"travis_wait 40 ${CABAL} " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
cmd

    forJob :: CompilerRange -> String -> Maybe String
    forJob :: CompilerRange -> [Char] -> Maybe [Char]
forJob CompilerRange
vr [Char]
cmd
        | (CompilerVersion -> Bool) -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (CompilerVersion -> CompilerRange -> Bool
`compilerWithinRange` CompilerRange
vr) Set CompilerVersion
allVersions       = [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
cmd
        | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (CompilerVersion -> Bool) -> Set CompilerVersion -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (CompilerVersion -> CompilerRange -> Bool
`compilerWithinRange` CompilerRange
vr) Set CompilerVersion
allVersions = Maybe [Char]
forall a. Maybe a
Nothing
        | Bool
otherwise                                        = [Char] -> Maybe [Char]
forall a. a -> Maybe a
Just ([Char] -> Maybe [Char]) -> [Char] -> Maybe [Char]
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unwords
            [ [Char]
"if"
            , Set CompilerVersion -> CompilerRange -> [Char]
compilerVersionPredicate Set CompilerVersion
allVersions CompilerRange
vr
            , [Char]
"; then"
            , [Char]
cmd
            , [Char]
"; fi"
            ]

    shForJob :: CompilerRange -> String -> ShM ()
    shForJob :: CompilerRange -> [Char] -> ShM ()
shForJob CompilerRange
vr [Char]
cmd = ShM () -> ([Char] -> ShM ()) -> Maybe [Char] -> ShM ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> ShM ()
forall a. a -> ShM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh (CompilerRange -> [Char] -> Maybe [Char]
forJob CompilerRange
vr [Char]
cmd)

    -- catForJob vr fp contents = shForJob vr (catCmd Double fp contents)

    generateCabalProject :: Bool -> ShM ()
    generateCabalProject :: Bool -> ShM ()
generateCabalProject Bool
dist = do
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
comment [Char]
"Generate cabal.project"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"rm -rf cabal.project cabal.project.local cabal.project.freeze"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"touch cabal.project"

        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unlines
            [ [Char]
cmd
            | Package
pkg <- [Package]
pkgs
            , let p :: [Char]
p | Bool
dist      = [Char] -> [Char]
pkgNameDirVariable (Package -> [Char]
pkgName Package
pkg)
                    | Bool
otherwise = Package -> [Char]
pkgDir Package
pkg
            , [Char]
cmd <- Maybe [Char] -> [[Char]]
forall a. Maybe a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Maybe [Char] -> [[Char]]) -> Maybe [Char] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ CompilerRange -> [Char] -> Maybe [Char]
forJob (Set CompilerVersion -> CompilerRange
RangePoints (Set CompilerVersion -> CompilerRange)
-> Set CompilerVersion -> CompilerRange
forall a b. (a -> b) -> a -> b
$ Package -> Set CompilerVersion
pkgJobs Package
pkg) ([Char] -> Maybe [Char]) -> [Char] -> Maybe [Char]
forall a b. (a -> b) -> a -> b
$
                [Char]
"echo \"packages: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
p [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"\" >> cabal.project"
            ]

        case PackageScope
cfgErrorMissingMethods of
            PackageScope
PackageScopeNone  -> () -> ShM ()
forall a. a -> ShM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
            PackageScope
PackageScopeLocal -> [Package] -> (Package -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Package]
pkgs ((Package -> ShM ()) -> ShM ()) -> (Package -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \Pkg{[Char]
pkgName :: Package -> [Char]
pkgName :: [Char]
pkgName,Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs} -> do
                CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range (Version -> VersionRange
C.orLaterVersion ([Int] -> Version
C.mkVersion [Int
8,Int
2])) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$
                    [Char]
"echo 'package " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
pkgName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"' >> cabal.project"
                CompilerRange -> [Char] -> ShM ()
shForJob (VersionRange -> CompilerRange
Range (Version -> VersionRange
C.orLaterVersion ([Int] -> Version
C.mkVersion [Int
8,Int
2])) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs) ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$
                    [Char]
"echo '  ghc-options: -Werror=missing-methods' >> cabal.project"
            PackageScope
PackageScopeAll   -> do
                [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"echo 'package *' >> cabal.project"
                [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"echo '  ghc-options: -Werror=missing-methods' >> cabal.project"

        [Char] -> [[Char]] -> ShM ()
cat [Char]
"cabal.project" ([[Char]] -> ShM ()) -> [[Char]] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> [[Char]]
lines ([Char] -> [[Char]]) -> [Char] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ (() -> CommentPosition)
-> (() -> [[Char]] -> [[Char]])
-> Int
-> [PrettyField ()]
-> [Char]
forall ann.
(ann -> CommentPosition)
-> (ann -> [[Char]] -> [[Char]])
-> Int
-> [PrettyField ann]
-> [Char]
C.showFields' (CommentPosition -> () -> CommentPosition
forall a b. a -> b -> a
const CommentPosition
C.NoComment) (([[Char]] -> [[Char]]) -> () -> [[Char]] -> [[Char]]
forall a b. a -> b -> a
const [[Char]] -> [[Char]]
forall a. a -> a
id) Int
2 ([PrettyField ()] -> [Char]) -> [PrettyField ()] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char] -> [PrettyField ()]
extraCabalProjectFields [Char]
""

        -- If using head.hackage, allow building with newer versions of GHC boot libraries.
        -- Note that we put this in a cabal.project file, not ~/.cabal/config, in order to avoid
        -- https://github.com/haskell/cabal/issues/7291.
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Set CompilerVersion -> Bool
forall a. Set a -> Bool
S.null Set CompilerVersion
headGhcVers) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unlines ([[Char]] -> [Char]) -> [[Char]] -> [Char]
forall a b. (a -> b) -> a -> b
$
            [ [Char]
"if $HEADHACKAGE; then"
            , [Char]
"echo \"allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\\1,/g')\" >> $CABALHOME/config"
            , [Char]
"fi"
            ]

        -- also write cabal.project.local file with
        -- @
        -- constraints: base installed
        -- constraints: array installed
        -- ...
        --
        -- omitting any local package names
        case [Installed] -> InstalledNormalised
normaliseInstalled [Installed]
cfgInstalled of
            InstalledDiff Set PackageName
pns -> [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unwords
                [ [Char]
"for pkg in $($HCPKG list --simple-output); do"
                , [Char]
"echo $pkg"
                , [Char]
"| sed 's/-[^-]*$//'"
                , [Char]
"| (grep -vE -- " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
re [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" || true)"
                , [Char]
"| sed 's/^/constraints: /'"
                , [Char]
"| sed 's/$/ installed/'"
                , [Char]
">> cabal.project.local; done"
                ]
              where
                pns' :: Set [Char]
pns' = (PackageName -> [Char]) -> Set PackageName -> Set [Char]
forall b a. Ord b => (a -> b) -> Set a -> Set b
S.map PackageName -> [Char]
C.unPackageName Set PackageName
pns Set [Char] -> Set [Char] -> Set [Char]
forall a. Ord a => Set a -> Set a -> Set a
`S.union` (Package -> Set [Char]) -> [Package] -> Set [Char]
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ([Char] -> Set [Char]
forall a. a -> Set a
S.singleton ([Char] -> Set [Char])
-> (Package -> [Char]) -> Package -> Set [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Package -> [Char]
pkgName) [Package]
pkgs
                re :: [Char]
re = [Char]
"'^(" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"|" (Set [Char] -> [[Char]]
forall a. Set a -> [a]
S.toList Set [Char]
pns') [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
")$'"

            InstalledOnly Set PackageName
pns | Bool -> Bool
not (Set [Char] -> Bool
forall a. Set a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set [Char]
pns') -> [Integer] -> [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Integer] -> [Char] -> m ()
sh' [Integer
2043] ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ [[Char]] -> [Char]
unwords
                [ [Char]
"for pkg in " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [[Char]] -> [Char]
unwords (Set [Char] -> [[Char]]
forall a. Set a -> [a]
S.toList Set [Char]
pns') [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"; do"
                , [Char]
"echo \"constraints: $pkg installed\""
                , [Char]
">> cabal.project.local; done"
                ]
              where
                pns' :: Set [Char]
pns' = (PackageName -> [Char]) -> Set PackageName -> Set [Char]
forall b a. Ord b => (a -> b) -> Set a -> Set b
S.map PackageName -> [Char]
C.unPackageName Set PackageName
pns Set [Char] -> Set [Char] -> Set [Char]
forall a. Ord a => Set a -> Set a -> Set a
`S.difference` (Package -> Set [Char]) -> [Package] -> Set [Char]
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ([Char] -> Set [Char]
forall a. a -> Set a
S.singleton ([Char] -> Set [Char])
-> (Package -> [Char]) -> Package -> Set [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Package -> [Char]
pkgName) [Package]
pkgs

            -- otherwise: nothing
            InstalledNormalised
_ -> () -> ShM ()
forall a. a -> ShM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"cat cabal.project || true"
        [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh [Char]
"cat cabal.project.local || true"

    -- Needed to work around haskell/cabal#6214
    withHaddock :: String
    withHaddock :: [Char]
withHaddock = [Char]
"--with-haddock $HADDOCK"



data Quotes = Single | Double

escape :: Quotes -> String -> String
escape :: Quotes -> [Char] -> [Char]
escape Quotes
Single [Char]
xs = [Char]
"'" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ (Char -> [Char]) -> [Char] -> [Char]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> [Char]
f [Char]
xs [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'" where
    f :: Char -> [Char]
f Char
'\0' = [Char]
""
    f Char
'\'' = [Char]
"'\"'\"'"
    f Char
x    = [Char
x]
escape Quotes
Double [Char]
xs = [Char] -> [Char]
forall a. Show a => a -> [Char]
show [Char]
xs

catCmd :: Quotes -> FilePath -> [String] -> String
catCmd :: Quotes -> [Char] -> [[Char]] -> [Char]
catCmd Quotes
q [Char]
fp [[Char]]
contents = [[Char]] -> [Char]
unlines
    [ [Char]
"echo " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Quotes -> [Char] -> [Char]
escape Quotes
q [Char]
l [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> Char -> [Char]
forall a. Int -> a -> [a]
replicate (Int
maxLength Int -> Int -> Int
forall a. Num a => a -> a -> a
- [Char] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
l) Char
' ' [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" >> " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
fp
    | [Char]
l <- [[Char]]
contents
    ]
  where
    maxLength :: Int
maxLength = (Int -> [Char] -> Int) -> Int -> [[Char]] -> Int
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Int
a [Char]
l -> Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
a ([Char] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
l)) Int
0 [[Char]]
contents
{-
-- https://travis-ci.community/t/multiline-commands-have-two-spaces-in-front-breaks-heredocs/2756
catCmd fp contents = unlines $
    [ "cat >> " ++ fp ++ " << HEREDOC" ] ++
    contents ++
    [ "HEREDOC" ]
-}

cat :: FilePath -> [String] -> ShM ()
cat :: [Char] -> [[Char]] -> ShM ()
cat [Char]
fp [[Char]]
contents = [Char] -> ShM ()
forall (m :: * -> *). MonadSh m => [Char] -> m ()
sh ([Char] -> ShM ()) -> [Char] -> ShM ()
forall a b. (a -> b) -> a -> b
$ Quotes -> [Char] -> [[Char]] -> [Char]
catCmd Quotes
Double [Char]
fp [[Char]]
contents