-- | 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.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 -> [String] -> [String]
travisHeader Bool
insertVersion [String]
argv =
    [ String
"This Travis job script has been generated by a script via"
    , String
""
    , String
"  haskell-ci " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [ String
"'" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
a String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"'" | String
a <- [String]
argv ]
    , String
""
    , String
"To regenerate the script (for example after adjusting tested-with) run"
    , String
""
    , String
"  haskell-ci regenerate"
    , String
""
    , String
"For more information, see https://github.com/haskell-CI/haskell-ci"
    , String
""
    ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
    if Bool
insertVersion then
    [ String
"version: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
haskellCIVerStr
    , String
""
    ] 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 ShError Travis -- TODO: writer
makeTravis :: [String]
-> Config
-> Project URI Void Package
-> JobVersions
-> Either ShError Travis
makeTravis [String]
argv config :: Config
config@Config {Bool
String
[String]
[PrettyField ()]
[PackageName]
[Installed]
[ConstraintSet]
Maybe String
Maybe Version
Maybe Jobs
VersionRange
Set String
Set Version
Set Fold
Map Version String
Ubuntu
PackageScope
HLintConfig
DoctestConfig
DocspecConfig
CopyFields
TestedWithJobs
cfgGitHubActionName :: Config -> Maybe String
cfgRawTravis :: Config -> String
cfgRawProject :: Config -> [PrettyField ()]
cfgConstraintSets :: Config -> [ConstraintSet]
cfgHLint :: Config -> HLintConfig
cfgDocspec :: Config -> DocspecConfig
cfgDoctest :: Config -> DoctestConfig
cfgErrorMissingMethods :: Config -> PackageScope
cfgInsertVersion :: Config -> Bool
cfgGitHubPatches :: Config -> [String]
cfgTravisPatches :: Config -> [String]
cfgApt :: Config -> Set String
cfgOsx :: Config -> Set Version
cfgLastInSeries :: Config -> Bool
cfgAllowFailures :: Config -> VersionRange
cfgEnv :: Config -> Map Version String
cfgGoogleChrome :: Config -> Bool
cfgPostgres :: Config -> Bool
cfgGhcHead :: Config -> Bool
cfgFolds :: Config -> Set Fold
cfgProjectName :: Config -> Maybe String
cfgEmailNotifications :: Config -> Bool
cfgIrcIfInOriginRepo :: Config -> Bool
cfgIrcChannels :: Config -> [String]
cfgOnlyBranches :: Config -> [String]
cfgCheck :: Config -> Bool
cfgTestOutputDirect :: Config -> Bool
cfgGhcjsTools :: Config -> [PackageName]
cfgGhcjsTests :: Config -> Bool
cfgHeadHackage :: Config -> VersionRange
cfgUnconstrainted :: Config -> VersionRange
cfgNoTestsNoBench :: Config -> VersionRange
cfgHaddock :: Config -> VersionRange
cfgBenchmarks :: Config -> VersionRange
cfgRunTests :: Config -> VersionRange
cfgTests :: Config -> VersionRange
cfgInstalled :: Config -> [Installed]
cfgInstallDeps :: Config -> Bool
cfgCache :: Config -> Bool
cfgSubmodules :: Config -> Bool
cfgLocalGhcOptions :: Config -> [String]
cfgCopyFields :: Config -> CopyFields
cfgTestedWith :: Config -> TestedWithJobs
cfgUbuntu :: Config -> Ubuntu
cfgJobs :: Config -> Maybe Jobs
cfgCabalInstallVersion :: Config -> Maybe Version
cfgGitHubActionName :: Maybe String
cfgRawTravis :: String
cfgRawProject :: [PrettyField ()]
cfgConstraintSets :: [ConstraintSet]
cfgHLint :: HLintConfig
cfgDocspec :: DocspecConfig
cfgDoctest :: DoctestConfig
cfgErrorMissingMethods :: PackageScope
cfgInsertVersion :: Bool
cfgGitHubPatches :: [String]
cfgTravisPatches :: [String]
cfgApt :: Set String
cfgOsx :: Set Version
cfgLastInSeries :: Bool
cfgAllowFailures :: VersionRange
cfgEnv :: Map Version String
cfgGoogleChrome :: Bool
cfgPostgres :: Bool
cfgGhcHead :: Bool
cfgFolds :: Set Fold
cfgProjectName :: Maybe String
cfgEmailNotifications :: Bool
cfgIrcIfInOriginRepo :: Bool
cfgIrcChannels :: [String]
cfgOnlyBranches :: [String]
cfgCheck :: Bool
cfgTestOutputDirect :: Bool
cfgGhcjsTools :: [PackageName]
cfgGhcjsTests :: Bool
cfgHeadHackage :: VersionRange
cfgUnconstrainted :: VersionRange
cfgNoTestsNoBench :: VersionRange
cfgHaddock :: VersionRange
cfgBenchmarks :: VersionRange
cfgRunTests :: VersionRange
cfgTests :: VersionRange
cfgInstalled :: [Installed]
cfgInstallDeps :: Bool
cfgCache :: Bool
cfgSubmodules :: Bool
cfgLocalGhcOptions :: [String]
cfgCopyFields :: CopyFields
cfgTestedWith :: TestedWithJobs
cfgUbuntu :: Ubuntu
cfgJobs :: Maybe Jobs
cfgCabalInstallVersion :: Maybe Version
..} Project URI Void Package
prj jobs :: JobVersions
jobs@JobVersions {Set Version
Set CompilerVersion
omittedOsxVersions :: JobVersions -> Set Version
osxVersions :: JobVersions -> Set Version
versions :: JobVersions -> Set CompilerVersion
omittedOsxVersions :: Set Version
osxVersions :: Set Version
versions :: Set CompilerVersion
..} = do
    -- before caching: clear some redundant stuff
    [Sh]
beforeCache <- ShM () -> Either ShError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromShError e) =>
ShM () -> m [Sh]
runSh (ShM () -> Either ShError [Sh]) -> ShM () -> Either ShError [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
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
comment String
"remove files that are regenerated by 'cabal update'"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.*" -- legacy
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -fv $CABALHOME/packages/hackage.haskell.org/*.json" -- TUF meta-data
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"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 ShError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromShError e) =>
ShM () -> m [Sh]
runSh (ShM () -> Either ShError [Sh]) -> ShM () -> Either ShError [Sh]
forall a b. (a -> b) -> a -> b
$ do
        -- 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
$ String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
            [ String
"if echo $CC | grep -q ghcjs; then"
            , String
"    GHCJS=true; GHCJSARITH=1;"
            , String
"else"
            , String
"    GHCJS=false; GHCJSARITH=0;"
            , String
"fi"
            ]

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

        -- Needed to work around haskell/cabal#6214
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"HADDOCK=$(echo \"/opt/$CC/bin/haddock\" | sed 's/-/\\//')"
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Set Version -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set Version
cfgOsx) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"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 -> String -> ShM ()
shForJob CompilerRange
RangeGHCJS (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"PATH=\"/opt/ghc/8.4.4/bin:$PATH\""

        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"HCPKG=\"$HC-pkg\""
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"unset CC"
        -- cabal
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"CABAL=/opt/ghc/bin/cabal"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"CABALHOME=$HOME/.cabal"
        -- PATH
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"export PATH=\"$CABALHOME/bin:$PATH\""
        -- rootdir is useful for manual script additions
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"TOP=$(pwd)"
        -- macOS installing
        let haskellOnMacos :: String
haskellOnMacos = String
"https://haskell.futurice.com/haskell-on-macos.py"
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Set Version -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set Version
cfgOsx) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"if [ \"$TRAVIS_OS_NAME\" = \"osx\" ]; then curl " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
haskellOnMacos String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" | 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] -> String -> ShM ()
forall (m :: * -> *). MonadSh m => [Integer] -> String -> m ()
sh' [Integer
2034,Integer
2039] String
"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
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"echo $HCNUMVER"
        -- verbose in .cabal/config is not respected
        -- https://github.com/haskell/cabal/issues/5956
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"CABAL=\"$CABAL -vnormal+nowrap\""

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

        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"TEST=--enable-tests"
        CompilerRange -> String -> ShM ()
shForJob (CompilerRange -> CompilerRange
invertCompilerRange (CompilerRange -> CompilerRange) -> CompilerRange -> CompilerRange
forall a b. (a -> b) -> a -> b
$ VersionRange -> CompilerRange
Range VersionRange
cfgTests) String
"TEST=--disable-tests"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"BENCH=--enable-benchmarks"
        CompilerRange -> String -> ShM ()
shForJob (CompilerRange -> CompilerRange
invertCompilerRange (CompilerRange -> CompilerRange) -> CompilerRange -> CompilerRange
forall a b. (a -> b) -> a -> b
$ VersionRange -> CompilerRange
Range VersionRange
cfgBenchmarks) String
"BENCH=--disable-benchmarks"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"HEADHACKAGE=false"
        CompilerRange -> String -> 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)) String
"HEADHACKAGE=true"

        -- create ~/.cabal/config
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"rm -f $CABALHOME/config"
        String -> [String] -> ShM ()
cat String
"$CABALHOME/config"
            [ String
"verbose: normal +nowrap +markoutput" -- https://github.com/haskell/cabal/issues/5956
            , String
"remote-build-reporting: anonymous"
            , String
"write-ghc-environment-files: never"
            , String
"remote-repo-cache: $CABALHOME/packages"
            , String
"logs-dir:          $CABALHOME/logs"
            , String
"world-file:        $CABALHOME/world"
            , String
"extra-prog-path:   $CABALHOME/bin"
            , String
"symlink-bindir:    $CABALHOME/bin"
            , String
"installdir:        $CABALHOME/bin"
            , String
"build-summary:     $CABALHOME/logs/build.log"
            , String
"store-dir:         $CABALHOME/store"
            , String
"install-dirs user"
            , String
"  prefix: $CABALHOME"
            , String
"repository hackage.haskell.org"
            , String
"  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
$ String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
            [ String
"if $HEADHACKAGE; then"
            ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
            String -> [String]
lines (Quotes -> String -> [String] -> String
catCmd Quotes
Double String
"$CABALHOME/config" [String]
headHackageRepoStanza) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
            [ String
"fi"
            ]

    -- in install step we install tools and dependencies
    [Sh]
install <- ShM () -> Either ShError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromShError e) =>
ShM () -> m [Sh]
runSh (ShM () -> Either ShError [Sh]) -> ShM () -> Either ShError [Sh]
forall a b. (a -> b) -> a -> b
$ do
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"${CABAL} --version"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"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
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"node --version"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"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 (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 ->
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"echo 'jobs: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"' >> $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 (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 -> String -> 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])) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"GHCJOBS=-j" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
m
        String -> [String] -> ShM ()
cat String
"$CABALHOME/config"
            [ String
"program-default-options"
            , String
"  ghc-options: $GHCJOBS +RTS -M6G -RTS"
            ]

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

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

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

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

        -- Install hlint
        let hlintVersionConstraint :: String
hlintVersionConstraint
                | VersionRange -> Bool
C.isAnyVersion (HLintConfig -> VersionRange
cfgHLintVersion HLintConfig
cfgHLint) = String
""
                | Bool
otherwise = String
" --constraint='hlint " String -> String -> String
forall a. [a] -> [a] -> [a]
++ VersionRange -> String
forall a. Pretty a => a -> String
C.prettyShow (HLintConfig -> VersionRange
cfgHLintVersion HLintConfig
cfgHLint) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"'"
        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 :: String -> ShM ()
forHLint = CompilerRange -> String -> ShM ()
shForJob (Set CompilerVersion -> VersionRange -> HLintJob -> CompilerRange
hlintJobVersionRange Set CompilerVersion
versions 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
                String -> ShM ()
forHLint (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"HLINTVER=$(cd /tmp && (${CABAL} v2-install -v $WITHCOMPILER --dry-run hlint " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
hlintVersionConstraint String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" |  perl -ne 'if (/\\bhlint-(\\d+(\\.\\d+)*)\\b/) { print \"$1\"; last; }')); echo \"HLint version $HLINTVER\""
                String -> ShM ()
forHLint (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"if [ ! -e $HOME/.hlint/hlint-$HLINTVER/hlint ]; then " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords
                    [ String
"echo \"Downloading HLint version $HLINTVER\";"
                    , String
"mkdir -p $HOME/.hlint;"
                    , String
"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\";"
                    , String
"tar -xzv -f $HOME/.hlint/hlint-$HLINTVER.tar.gz -C $HOME/.hlint;"
                    , String
"fi"
                    ]
                String -> ShM ()
forHLint String
"mkdir -p $CABALHOME/bin && ln -sf \"$HOME/.hlint/hlint-$HLINTVER/hlint\" $CABALHOME/bin/hlint"
                String -> ShM ()
forHLint String
"hlint --version"

            else String -> ShM ()
forHLint (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabal (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
"v2-install $WITHCOMPILER --ignore-project -j2 hlint" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
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 -> String -> ShM ()
shForJob CompilerRange
RangeGHCJS (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabal String
"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 -> String -> ShM ()
shForJob CompilerRange
RangeGHCJS (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabal (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
"v2-install -w ghc-8.4.4 --ignore-project -j2" String -> String -> String
forall a. [a] -> [a] -> [a]
++ PackageName -> String
forall a. Pretty a => a -> String
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{String
pkgDir :: Package -> String
pkgDir :: String
pkgDir} ->
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"if [ -f \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
pkgDir String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/configure.ac\" ]; then (cd \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
pkgDir String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\" && autoreconf -i); fi"

        -- dump install plan
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabal String
"v2-freeze $WITHCOMPILER ${TEST} ${BENCH}"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"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
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabalTW String
"v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all"

            -- install dependencies for no-test-no-bench
            CompilerRange -> String -> ShM ()
shForJob (VersionRange -> CompilerRange
Range VersionRange
cfgNoTestsNoBench) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabalTW String
"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 ShError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromShError e) =>
ShM () -> m [Sh]
runSh (ShM () -> Either ShError [Sh]) -> ShM () -> Either ShError [Sh]
forall a b. (a -> b) -> a -> b
$ do
        String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)"

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

        -- unpack
        Fold -> String -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldUnpack String
"Unpacking..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"cd ${DISTDIR} || false" -- fail explicitly, makes SC happier
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \\;"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"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{String
pkgName :: Package -> String
pkgName :: String
pkgName} -> do
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
pkgNameDirVariable' String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"=\"$(find . -maxdepth 1 -type d -regex '.*/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-[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
$ String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
                [ String
"pkgdir() {"
                , String
"  case $1 in"
                ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
                [ String
"    " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") echo " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
pkgNameDirVariable String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" ;;"
                | Pkg{String
pkgName :: String
pkgName :: Package -> String
pkgName} <- [Package]
pkgs
                ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
                [ String
"  esac"
                , String
"}"
                ]

        -- 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 -> String -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldBuild String
"Building..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
comment String
"this builds all libraries and executables (without tests/benchmarks)"
            CompilerRange -> String -> ShM ()
shForJob (VersionRange -> CompilerRange
Range VersionRange
cfgNoTestsNoBench) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabal String
"v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all"

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

        -- cabal v2-test fails if there are no test-suites.
        Fold -> String -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldTest String
"Testing..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            CompilerRange -> String -> 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) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$
                String -> String
cabal (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
"v2-test $WITHCOMPILER ${TEST} ${BENCH} all" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
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 -> String -> ShM ()
shForJob (CompilerRange
RangeGHCJS CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
hasTests) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords
                [ String
"cabal-plan list-bins '*:test:*' | while read -r line; do"
                , String
"testpkg=$(echo \"$line\" | perl -pe 's/:.*//');"
                , String
"testexe=$(echo \"$line\" | awk '{ print $2 }');"
                , String
"echo \"testing $textexe in package $textpkg\";"
                , String
"(cd \"$(pkgdir $testpkg)\" && nodejs \"$testexe\".jsexe/all.js);"
                , String
"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 -> String -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldDoctest String
"Doctest..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            let doctestOptions :: String
doctestOptions = [String] -> String
unwords ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ DoctestConfig -> [String]
cfgDoctestOptions DoctestConfig
cfgDoctest
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"$CABAL v2-build $WITHCOMPILER ${TEST} ${BENCH} all --dry-run"
            Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([PackageName] -> 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 :: String -> [String]
manglePkgNames String
n
                        | Set Version -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Set Version
cfgOsx = [String
n]
                        | Bool
otherwise   = [String
n, (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter Char -> Bool
notVowel String
n]
                      where
                        notVowel :: Char -> Bool
notVowel Char
c = Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
notElem Char
c (String
"aeiou" :: String)
                let filterPkgs :: String
filterPkgs = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"|" ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (PackageName -> [String]) -> [PackageName] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> [String]
manglePkgNames (String -> [String])
-> (PackageName -> String) -> PackageName -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> String
C.unPackageName) ([PackageName] -> [String]) -> [PackageName] -> [String]
forall a b. (a -> b) -> a -> b
$ DoctestConfig -> [PackageName]
cfgDoctestFilterEnvPkgs DoctestConfig
cfgDoctest
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String
"perl -i -e 'while (<ARGV>) { print unless /package-id\\s+(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
filterPkgs String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")-\\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{String
pkgName :: String
pkgName :: Package -> String
pkgName,GenericPackageDescription
pkgGpd :: Package -> GenericPackageDescription
pkgGpd :: GenericPackageDescription
pkgGpd,Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs} ->
                Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (String -> PackageName
C.mkPackageName String
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
                    [[String]] -> ([String] -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (GenericPackageDescription -> [[String]]
doctestArgs GenericPackageDescription
pkgGpd) (([String] -> ShM ()) -> ShM ()) -> ([String] -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \[String]
args -> do
                        let args' :: String
args' = [String] -> String
unwords [String]
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 ([String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
args) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ CompilerRange -> String -> ShM ()
shForJob  CompilerRange
vr (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$
                            String
"(cd " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
pkgNameDirVariable String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" && doctest " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
doctestOptions String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
args' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"

        -- 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 -> String -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldHLint String
"HLint.." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            let String
"" <+> :: String -> String -> String
<+> String
ys = String
ys
                String
xs <+> String
"" = String
xs
                String
xs <+> String
ys = String
xs String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ys

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

            let hlintOptions :: String
hlintOptions = String -> String
prependSpace (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> (String -> String) -> Maybe String -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"" (String
"-h ${TOP}/" String -> String -> String
forall a. [a] -> [a] -> [a]
++) (HLintConfig -> Maybe String
cfgHLintYaml HLintConfig
cfgHLint) String -> String -> String
<+> [String] -> String
unwords (HLintConfig -> [String]
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{String
pkgName :: String
pkgName :: Package -> String
pkgName,GenericPackageDescription
pkgGpd :: GenericPackageDescription
pkgGpd :: Package -> GenericPackageDescription
pkgGpd,Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs} -> do
                [[String]] -> ([String] -> ShM ()) -> ShM ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (GenericPackageDescription -> [[String]]
hlintArgs GenericPackageDescription
pkgGpd) (([String] -> ShM ()) -> ShM ()) -> ([String] -> ShM ()) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \[String]
args -> do
                    let args' :: String
args' = [String] -> String
unwords [String]
args
                    Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
args) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                        CompilerRange -> String -> ShM ()
shForJob (Set CompilerVersion -> VersionRange -> HLintJob -> CompilerRange
hlintJobVersionRange Set CompilerVersion
versions VersionRange
cfgHeadHackage (HLintConfig -> HLintJob
cfgHLintJob HLintConfig
cfgHLint) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$
                        String
"(cd " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
pkgNameDirVariable String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" && hlint" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
hlintOptions String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
args' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"

        -- 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 -> String -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldCheck String
"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{String
pkgName :: String
pkgName :: Package -> String
pkgName,Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs} -> CompilerRange -> String -> ShM ()
shForJob (Set CompilerVersion -> CompilerRange
RangePoints Set CompilerVersion
pkgJobs) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$
                String
"(cd " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
pkgNameDirVariable String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" && ${CABAL} -vnormal check)"

        -- haddock
        Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
hasLibrary Bool -> Bool -> Bool
&& Bool -> Bool
not (VersionRange -> VersionRange -> Bool
equivVersionRanges VersionRange
C.noVersion VersionRange
cfgHaddock)) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
            Fold -> String -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldHaddock String
"haddock..." Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                CompilerRange -> String -> ShM ()
shForJob (CompilerRange
RangeGHC CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ VersionRange -> CompilerRange
Range VersionRange
cfgHaddock) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabal (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
"v2-haddock $WITHCOMPILER " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
withHaddock String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" ${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 -> String -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
FoldBuildInstalled String
"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 -> String -> ShM ()
shForJob (VersionRange -> CompilerRange
Range VersionRange
cfgUnconstrainted) String
"rm -f cabal.project.local"
                CompilerRange -> String -> ShM ()
shForJob (VersionRange -> CompilerRange
Range VersionRange
cfgUnconstrainted) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabal String
"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 (t :: * -> *) a. Foldable t => t a -> Bool
null [ConstraintSet]
cfgConstraintSets) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
comment String
"Constraint sets"
            String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"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 :: String
name            = ConstraintSet -> String
csName ConstraintSet
cs
                let shForCs :: String -> ShM ()
shForCs         = CompilerRange -> String -> ShM ()
shForJob (VersionRange -> CompilerRange
Range (ConstraintSet -> VersionRange
csGhcVersions ConstraintSet
cs))
                let shForCs' :: CompilerRange -> String -> ShM ()
shForCs' CompilerRange
r      = CompilerRange -> String -> ShM ()
shForJob (VersionRange -> CompilerRange
Range (ConstraintSet -> VersionRange
csGhcVersions ConstraintSet
cs) CompilerRange -> CompilerRange -> CompilerRange
forall a. Lattice a => a -> a -> a
/\ CompilerRange
r)
                let testFlag :: String
testFlag        = if ConstraintSet -> Bool
csTests ConstraintSet
cs then String
"--enable-tests" else String
"--disable-tests"
                let benchFlag :: String
benchFlag       = if ConstraintSet -> Bool
csBenchmarks ConstraintSet
cs then String
"--enable-benchmarks" else String
"--disable-benchmarks"
                let constraintFlags :: [String]
constraintFlags = (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (\String
x ->  String
"--constraint='" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"'") (ConstraintSet -> [String]
csConstraints ConstraintSet
cs)
                let allFlags :: String
allFlags        = [String] -> String
unwords (String
testFlag String -> [String] -> [String]
forall a. a -> [a] -> [a]
: String
benchFlag String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
constraintFlags)

                Fold -> String -> String -> Set Fold -> ShM () -> ShM ()
foldedSh' Fold
FoldConstraintSets String
name (String
"Constraint set " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name) Set Fold
cfgFolds (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$ do
                    String -> ShM ()
shForCs (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabal (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
"v2-build $WITHCOMPILER " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
allFlags String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" 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 -> String -> ShM ()
shForCs' CompilerRange
hasTests (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabal (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
"v2-test $WITHCOMPILER " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
allFlags String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" all --test-show-details=direct"
                    Bool -> ShM () -> ShM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
hasLibrary Bool -> Bool -> Bool
&& ConstraintSet -> Bool
csHaddock ConstraintSet
cs) (ShM () -> ShM ()) -> ShM () -> ShM ()
forall a b. (a -> b) -> a -> b
$
                        String -> ShM ()
shForCs (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ String -> String
cabal (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
"v2-haddock $WITHCOMPILER " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
withHaddock String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
allFlags String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" all"

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

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

                        -- https://docs.travis-ci.com/user/installing-dependencies/#adding-apt-sources
                        let hvrppa :: TravisAptSource
                            hvrppa :: TravisAptSource
hvrppa = String -> Maybe String -> TravisAptSource
TravisAptSourceLine (String
"deb http://ppa.launchpad.net/hvr/ghc/ubuntu " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Ubuntu -> String
forall a. Pretty a => a -> String
C.prettyShow Ubuntu
cfgUbuntu String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" main") (String -> Maybe String
forall a. a -> Maybe a
Just String
"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 =
                                [ String -> Maybe String -> TravisAptSource
TravisAptSourceLine (String
"deb http://ppa.launchpad.net/hvr/ghcjs/ubuntu " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Ubuntu -> String
forall a. Pretty a => a -> String
C.prettyShow Ubuntu
cfgUbuntu String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" main") Maybe String
forall a. Maybe a
Nothing
                                , String -> Maybe String -> TravisAptSource
TravisAptSourceLine (String
"deb https://deb.nodesource.com/node_10.x " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Ubuntu -> String
forall a. Pretty a => a -> String
C.prettyShow Ubuntu
cfgUbuntu String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" main") (String -> Maybe String
forall a. a -> Maybe a
Just String
"https://deb.nodesource.com/gpgkey/nodesource.gpg.key")
                                ]

                        let ghcjsPackages :: [String]
                            ghcjsPackages :: [String]
ghcjsPackages = case CompilerVersion -> Maybe Version
maybeGHCJS CompilerVersion
gv of
                                Just Version
v -> [ String
"ghc-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Version -> String
forall a. Pretty a => a -> String
C.prettyShow Version
v', String
"nodejs" ] where
                                    -- TODO: partial maximum
                                    v' :: Version
v' = [Version] -> Version
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 :: String -> Maybe String -> TravisAddons -> String -> TravisJob
TravisJob
                            { tjCompiler :: String
tjCompiler = String
gvs
                            , tjOS :: String
tjOS       = if Bool
osx then String
"osx" else String
"linux"
                            , tjEnv :: Maybe String
tjEnv      = case CompilerVersion
gv of
                                GHC Version
v -> Version -> Map Version String -> Maybe String
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Version
v Map Version String
cfgEnv
                                CompilerVersion
_     -> Maybe String
forall a. Maybe a
Nothing
                            , tjAddons :: TravisAddons
tjAddons   = TravisAddons :: TravisApt -> Maybe String -> Bool -> TravisAddons
TravisAddons
                                { taApt :: TravisApt
taApt = TravisApt :: [String] -> [TravisAptSource] -> TravisApt
TravisApt
                                    { taPackages :: [String]
taPackages = String
gvs String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (String
"cabal-install-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cvs) String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
ghcjsPackages [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ Set String -> [String]
forall a. Set a -> [a]
S.toList Set String
cfgApt
                                    , taSources :: [TravisAptSource]
taSources  = TravisAptSource
hvrppa TravisAptSource -> [TravisAptSource] -> [TravisAptSource]
forall a. a -> [a] -> [a]
: [TravisAptSource]
ghcjsAptSources
                                    }

                                , taPostgres :: Maybe String
taPostgres     = Maybe String
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
versions) ((CompilerVersion -> ListBuilder TravisJob ())
 -> ListBuilder TravisJob ())
-> (CompilerVersion -> ListBuilder TravisJob ())
-> ListBuilder TravisJob ()
forall a b. (a -> b) -> a -> b
$ Bool -> CompilerVersion -> ListBuilder TravisJob ()
tellJob Bool
False
                [Version]
-> (Version -> ListBuilder TravisJob ())
-> ListBuilder TravisJob ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ ([Version] -> [Version]
forall a. [a] -> [a]
reverse ([Version] -> [Version]) -> [Version] -> [Version]
forall a b. (a -> b) -> a -> b
$ Set Version -> [Version]
forall a. Set a -> [a]
S.toList Set Version
osxVersions) ((Version -> ListBuilder TravisJob ()) -> ListBuilder TravisJob ())
-> (Version -> ListBuilder TravisJob ())
-> ListBuilder TravisJob ()
forall a b. (a -> b) -> a -> b
$ Bool -> CompilerVersion -> ListBuilder TravisJob ()
tellJob Bool
True (CompilerVersion -> ListBuilder TravisJob ())
-> (Version -> CompilerVersion)
-> Version
-> ListBuilder TravisJob ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Version -> CompilerVersion
GHC

            , tmAllowFailures :: [TravisAllowFailure]
tmAllowFailures =
                [ String -> TravisAllowFailure
TravisAllowFailure (String -> TravisAllowFailure) -> String -> TravisAllowFailure
forall a b. (a -> b) -> a -> b
$ CompilerVersion -> String
dispGhcVersion CompilerVersion
compiler
                | CompilerVersion
compiler <- Set CompilerVersion -> [CompilerVersion]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Set CompilerVersion
versions
                , VersionRange -> CompilerVersion -> Bool
previewGHC VersionRange
cfgHeadHackage 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
String
[PrettyField ()]
[URI]
[Package]
CompilerRange
testShowDetails :: Auxiliary -> String
extraCabalProjectFields :: Auxiliary -> [PrettyField ()]
hasLibrary :: Auxiliary -> Bool
hasTests :: Auxiliary -> CompilerRange
docspecEnabled :: Auxiliary -> Bool
doctestEnabled :: Auxiliary -> Bool
projectName :: Auxiliary -> String
uris :: Auxiliary -> [URI]
pkgs :: Auxiliary -> [Package]
extraCabalProjectFields :: [PrettyField ()]
docspecEnabled :: Bool
uris :: [URI]
projectName :: String
hasLibrary :: Bool
testShowDetails :: String
hasTests :: CompilerRange
pkgs :: [Package]
doctestEnabled :: Bool
..} = 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 -> String -> Set Fold -> ShM () -> ShM ()
foldedSh Fold
label = Fold -> String -> String -> Set Fold -> ShM () -> ShM ()
foldedSh' Fold
label String
""

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

    -- 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 -> String -> String -> Set Fold -> ShM () -> ShM ()
foldedSh' Fold
label String
sfx String
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 = String -> ShM () -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m () -> m ()
commentedBlock String
plabel ShM ()
block
        | Bool
otherwise = case ShM () -> Either ShError [Sh]
forall e (m :: * -> *).
(MonadErr e m, FromShError e) =>
ShM () -> m [Sh]
runSh ShM ()
block of
            Left ShError
err  -> ShError -> ShM ()
forall e (m :: * -> *) a. MonadErr e m => e -> m a
throwErr ShError
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 (f :: * -> *) a. Applicative f => a -> f a
pure ()
                | Bool
otherwise         -> (([Sh] -> [Sh]) -> Either ShError ([Sh] -> [Sh], ())) -> ShM ()
forall a.
(([Sh] -> [Sh]) -> Either ShError ([Sh] -> [Sh], a)) -> ShM a
ShM ((([Sh] -> [Sh]) -> Either ShError ([Sh] -> [Sh], ())) -> ShM ())
-> (([Sh] -> [Sh]) -> Either ShError ([Sh] -> [Sh], ())) -> ShM ()
forall a b. (a -> b) -> a -> b
$ \[Sh] -> [Sh]
shs1 -> ([Sh] -> [Sh], ()) -> Either ShError ([Sh] -> [Sh], ())
forall a b. b -> Either a b
Right (([Sh] -> [Sh], ()) -> Either ShError ([Sh] -> [Sh], ()))
-> ([Sh] -> [Sh], ()) -> Either ShError ([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
. (String -> Sh
Comment String
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
. (String -> Sh
Sh (String
"echo '" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
plabel String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"' && echo -en 'travis_fold:start:" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
label' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\\\\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
. (String -> Sh
Sh (String
"echo -en 'travis_fold:end:" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
label' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\\\\r'") Sh -> [Sh] -> [Sh]
forall a. a -> [a] -> [a]
:)
                    -- return ()
                    , ()
                    )
      where
        label' :: String
label' | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
sfx  = Fold -> String
showFold Fold
label
               | Bool
otherwise = Fold -> String
showFold Fold
label String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
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
previewGHC VersionRange
cfgHeadHackage) Set CompilerVersion
versions

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

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

    forJob :: CompilerRange -> String -> Maybe String
    forJob :: CompilerRange -> String -> Maybe String
forJob CompilerRange
vr String
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
versions       = String -> Maybe String
forall a. a -> Maybe a
Just String
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
versions = Maybe String
forall a. Maybe a
Nothing
        | Bool
otherwise                                     = String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords
            [ String
"if"
            , Set CompilerVersion -> CompilerRange -> String
compilerVersionPredicate Set CompilerVersion
versions CompilerRange
vr
            , String
"; then"
            , String
cmd
            , String
"; fi"
            ]

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

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

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

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

        case PackageScope
cfgErrorMissingMethods of
            PackageScope
PackageScopeNone  -> () -> ShM ()
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{String
pkgName :: String
pkgName :: Package -> String
pkgName,Set CompilerVersion
pkgJobs :: Set CompilerVersion
pkgJobs :: Package -> Set CompilerVersion
pkgJobs} -> do
                CompilerRange -> String -> 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) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$
                    String
"echo 'package " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
pkgName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"' >> cabal.project"
                CompilerRange -> String -> 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) (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$
                    String
"echo '  ghc-options: -Werror=missing-methods' >> cabal.project"
            PackageScope
PackageScopeAll   -> do
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"echo 'package *' >> cabal.project"
                String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh String
"echo '  ghc-options: -Werror=missing-methods' >> cabal.project"

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

        -- 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
$ String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
            [ String
"if $HEADHACKAGE; then"
            , String
"echo \"allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\\1,/g')\" >> $CABALHOME/config"
            , String
"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 -> String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords
                [ String
"for pkg in $($HCPKG list --simple-output); do"
                , String
"echo $pkg"
                , String
"| sed 's/-[^-]*$//'"
                , String
"| (grep -vE -- " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
re String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" || true)"
                , String
"| sed 's/^/constraints: /'"
                , String
"| sed 's/$/ installed/'"
                , String
">> cabal.project.local; done"
                ]
              where
                pns' :: Set String
pns' = (PackageName -> String) -> Set PackageName -> Set String
forall b a. Ord b => (a -> b) -> Set a -> Set b
S.map PackageName -> String
C.unPackageName Set PackageName
pns Set String -> Set String -> Set String
forall a. Ord a => Set a -> Set a -> Set a
`S.union` (Package -> Set String) -> [Package] -> Set String
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (String -> Set String
forall a. a -> Set a
S.singleton (String -> Set String)
-> (Package -> String) -> Package -> Set String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Package -> String
pkgName) [Package]
pkgs
                re :: String
re = String
"'^(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"|" (Set String -> [String]
forall a. Set a -> [a]
S.toList Set String
pns') String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")$'"

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

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

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

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



data Quotes = Single | Double

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

catCmd :: Quotes -> FilePath -> [String] -> String
catCmd :: Quotes -> String -> [String] -> String
catCmd Quotes
q String
fp [String]
contents = [String] -> String
unlines
    [ String
"echo " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Quotes -> String -> String
escape Quotes
q String
l String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
maxLength Int -> Int -> Int
forall a. Num a => a -> a -> a
- String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
l) Char
' ' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" >> " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
fp
    | String
l <- [String]
contents
    ]
  where
    maxLength :: Int
maxLength = (Int -> String -> Int) -> Int -> [String] -> Int
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Int
a String
l -> Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
a (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
l)) Int
0 [String]
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 :: String -> [String] -> ShM ()
cat String
fp [String]
contents = String -> ShM ()
forall (m :: * -> *). MonadSh m => String -> m ()
sh (String -> ShM ()) -> String -> ShM ()
forall a b. (a -> b) -> a -> b
$ Quotes -> String -> [String] -> String
catCmd Quotes
Double String
fp [String]
contents