{-# LANGUAGE CPP #-}
module HaskellCI.Bash.Template (
    -- * Input
    Z (..),
    defaultZ,
    -- * Rendering
    renderIO,
    render,
) where

import HaskellCI.Prelude

import Control.Monad (forM_)

import qualified Zinza

data Z = Z
    { Z -> [String]
zJobs      :: [String]
    , Z -> String
zRegendata :: String
    , Z -> [String]
zBlocks    :: [String]
    , Z -> String
zTestsCond :: String
    , Z -> String
zBenchCond :: String
    , Z -> [String]
zApt       :: [String]
    , Z -> [String] -> Bool
zNotNull   :: [String] -> Bool
    , Z -> [String] -> String
zUnwords   :: [String] -> String
    }
  deriving ((forall x. Z -> Rep Z x) -> (forall x. Rep Z x -> Z) -> Generic Z
forall x. Rep Z x -> Z
forall x. Z -> Rep Z x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Z -> Rep Z x
from :: forall x. Z -> Rep Z x
$cto :: forall x. Rep Z x -> Z
to :: forall x. Rep Z x -> Z
Generic)

defaultZ :: Z
defaultZ :: Z
defaultZ = Z
    { zJobs :: [String]
zJobs      = []
    , zRegendata :: String
zRegendata = String
"[]"
    , zBlocks :: [String]
zBlocks    = []
    , zTestsCond :: String
zTestsCond = String
"1"
    , zBenchCond :: String
zBenchCond = String
"1"
    , zApt :: [String]
zApt       = []
    , zNotNull :: [String] -> Bool
zNotNull   = Bool -> Bool
not (Bool -> Bool) -> ([String] -> Bool) -> [String] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null
    , zUnwords :: [String] -> String
zUnwords   = [String] -> String
unwords
    }

instance Zinza.Zinza Z where
    toType :: Proxy Z -> Ty
toType    = Proxy Z -> Ty
forall a.
(Generic a, GZinzaType (Rep a), GFieldNames (Rep a)) =>
Proxy a -> Ty
Zinza.genericToTypeSFP
    toValue :: Z -> Value
toValue   = Z -> Value
forall a.
(Generic a, GZinzaValue (Rep a), GFieldNames (Rep a)) =>
a -> Value
Zinza.genericToValueSFP
    fromValue :: Loc -> Value -> Either RuntimeError Z
fromValue = Loc -> Value -> Either RuntimeError Z
forall a.
(Generic a, GZinzaFrom (Rep a), GFieldNames (Rep a)) =>
Loc -> Value -> Either RuntimeError a
Zinza.genericFromValueSFP

-------------------------------------------------------------------------------
-- Development
-------------------------------------------------------------------------------

-- #define DEVELOPMENT 1

#ifdef DEVELOPMENT

renderIO :: Z -> IO String
renderIO z = do
    template <- Zinza.parseAndCompileTemplateIO "haskell-ci.sh.zinza"
    template z

#endif

-------------------------------------------------------------------------------
-- Production
-------------------------------------------------------------------------------

#ifndef DEVELOPMENT
renderIO :: Z -> IO String
renderIO :: Z -> IO String
renderIO = String -> IO String
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> IO String) -> (Z -> String) -> Z -> IO String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Z -> String
render
#endif

type Writer a = (String, a)
tell :: String -> Writer (); tell :: String -> Writer ()
tell String
x = (String
x, ())
execWriter :: Writer a -> String; execWriter :: forall a. Writer a -> String
execWriter = (String, a) -> String
forall a b. (a, b) -> a
fst

-- To generate:
--
-- :m *HaskellCI.Bash.Template
-- Zinza.parseAndCompileModuleIO (Zinza.simpleConfig "Module" [] :: Zinza.ModuleConfig Z) "haskell-ci.sh.zinza" >>= putStr

render :: Z -> String
render :: Z -> String
render Z
z_root = Writer () -> String
forall a. Writer a -> String
execWriter (Writer () -> String) -> Writer () -> String
forall a b. (a -> b) -> a -> b
$ do
  String -> Writer ()
tell String
"#!/bin/bash\n"
  String -> Writer ()
tell String
"# shellcheck disable=SC2086,SC2016,SC2046\n"
  String -> Writer ()
tell String
"# REGENDATA "
  String -> Writer ()
tell (Z -> String
zRegendata Z
z_root)
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"set -o pipefail\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Mode\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"if [ \"$1\" = \"indocker\" ]; then\n"
  String -> Writer ()
tell String
"    INDOCKER=true\n"
  String -> Writer ()
tell String
"    shift\n"
  String -> Writer ()
tell String
"else\n"
  String -> Writer ()
tell String
"    INDOCKER=false\n"
  String -> Writer ()
tell String
"fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Run configuration\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"CFG_CABAL_STORE_CACHE=\"\"\n"
  String -> Writer ()
tell String
"CFG_CABAL_REPO_CACHE=\"\"\n"
  String -> Writer ()
tell String
"CFG_JOBS=\""
  String -> Writer ()
tell (Z -> [String] -> String
zUnwords Z
z_root (Z -> [String]
zJobs Z
z_root))
  String -> Writer ()
tell String
"\"\n"
  String -> Writer ()
tell String
"CFG_CABAL_UPDATE=false\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"SCRIPT_NAME=$(basename \"$0\")\n"
  String -> Writer ()
tell String
"START_TIME=\"$(date +'%s')\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Job configuration\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"GHC_VERSION=\"non-existing\"\n"
  String -> Writer ()
tell String
"CABAL_VERSION=3.2\n"
  String -> Writer ()
tell String
"HEADHACKAGE=false\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Locale\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"export LC_ALL=C.UTF-8\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Utilities\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"SGR_RED='\\033[1;31m'\n"
  String -> Writer ()
tell String
"SGR_GREEN='\\033[1;32m'\n"
  String -> Writer ()
tell String
"SGR_BLUE='\\033[1;34m'\n"
  String -> Writer ()
tell String
"SGR_CYAN='\\033[1;96m'\n"
  String -> Writer ()
tell String
"SGR_RESET='\\033[0m' # No Color\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"put_info() {\n"
  String -> Writer ()
tell String
"    printf \"$SGR_CYAN%s$SGR_RESET\\n\" \"### $*\"\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"put_error() {\n"
  String -> Writer ()
tell String
"    printf \"$SGR_RED%s$SGR_RESET\\n\" \"!!! $*\"\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"run_cmd() {\n"
  String -> Writer ()
tell String
"    local PRETTYCMD=\"$*\"\n"
  String -> Writer ()
tell String
"    local PROMPT\n"
  String -> Writer ()
tell String
"    if $INDOCKER; then\n"
  String -> Writer ()
tell String
"        PROMPT=\"$(pwd) >>>\"\n"
  String -> Writer ()
tell String
"    else\n"
  String -> Writer ()
tell String
"        PROMPT=\">>>\"\n"
  String -> Writer ()
tell String
"    fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    printf \"$SGR_BLUE%s %s$SGR_RESET\\n\" \"$PROMPT\" \"$PRETTYCMD\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    local start_time end_time cmd_duration total_duration\n"
  String -> Writer ()
tell String
"    start_time=$(date +'%s')\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    \"$@\"\n"
  String -> Writer ()
tell String
"    local RET=$?\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    end_time=$(date +'%s')\n"
  String -> Writer ()
tell String
"    cmd_duration=$((end_time - start_time))\n"
  String -> Writer ()
tell String
"    total_duration=$((end_time - START_TIME))\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    cmd_min=$((cmd_duration / 60))\n"
  String -> Writer ()
tell String
"    cmd_sec=$((cmd_duration % 60))\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    total_min=$((total_duration / 60))\n"
  String -> Writer ()
tell String
"    total_sec=$((total_duration % 60))\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    if [ $RET -eq 0 ]; then\n"
  String -> Writer ()
tell String
"        printf \"$SGR_GREEN%s$SGR_RESET (%dm%02ds; %dm%02ds)\\n\" \"<<< $PRETTYCMD\" \"$cmd_min\" \"$cmd_sec\" \"$total_min\" \"$total_sec\"\n"
  String -> Writer ()
tell String
"    else\n"
  String -> Writer ()
tell String
"        printf \"$SGR_RED%s$SGR_RESET\\n\" \"!!! $PRETTYCMD\"\n"
  String -> Writer ()
tell String
"        exit 1\n"
  String -> Writer ()
tell String
"    fi\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"run_cmd_if() {\n"
  String -> Writer ()
tell String
"    local COND=$1\n"
  String -> Writer ()
tell String
"    shift\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    if [ $COND -eq 1 ]; then\n"
  String -> Writer ()
tell String
"        run_cmd \"$@\"\n"
  String -> Writer ()
tell String
"    else\n"
  String -> Writer ()
tell String
"        local PRETTYCMD=\"$*\"\n"
  String -> Writer ()
tell String
"        local PROMPT\n"
  String -> Writer ()
tell String
"        PROMPT=\"$(pwd) (skipping) >>>\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"        printf \"$SGR_BLUE%s %s$SGR_RESET\\n\" \"$PROMPT\" \"$PRETTYCMD\"\n"
  String -> Writer ()
tell String
"    fi\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"run_cmd_unchecked() {\n"
  String -> Writer ()
tell String
"    local PRETTYCMD=\"$*\"\n"
  String -> Writer ()
tell String
"    local PROMPT\n"
  String -> Writer ()
tell String
"    if $INDOCKER; then\n"
  String -> Writer ()
tell String
"        PROMPT=\"$(pwd) >>>\"\n"
  String -> Writer ()
tell String
"    else\n"
  String -> Writer ()
tell String
"        PROMPT=\">>>\"\n"
  String -> Writer ()
tell String
"    fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    printf \"$SGR_BLUE%s %s$SGR_RESET\\n\" \"$PROMPT\" \"$PRETTYCMD\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    local start_time end_time cmd_duration total_duration cmd_min cmd_sec total_min total_sec\n"
  String -> Writer ()
tell String
"    start_time=$(date +'%s')\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    \"$@\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    end_time=$(date +'%s')\n"
  String -> Writer ()
tell String
"    cmd_duration=$((end_time - start_time))\n"
  String -> Writer ()
tell String
"    total_duration=$((end_time - START_TIME))\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    cmd_min=$((cmd_duration / 60))\n"
  String -> Writer ()
tell String
"    cmd_sec=$((cmd_duration % 60))\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    total_min=$((total_duration / 60))\n"
  String -> Writer ()
tell String
"    total_sec=$((total_duration % 60))\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    printf \"$SGR_GREEN%s$SGR_RESET (%dm%02ds; %dm%02ds)\\n\" \"<<< $PRETTYCMD\" \"$cmd_min\" \"$cmd_sec\" \"$total_min\" \"$total_sec\"\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"change_dir() {\n"
  String -> Writer ()
tell String
"    local DIR=$1\n"
  String -> Writer ()
tell String
"    if [ -d \"$DIR\" ]; then\n"
  String -> Writer ()
tell String
"        printf \"$SGR_BLUE%s$SGR_RESET\\n\" \"change directory to $DIR\"\n"
  String -> Writer ()
tell String
"        cd \"$DIR\" || exit 1\n"
  String -> Writer ()
tell String
"    else\n"
  String -> Writer ()
tell String
"        printf \"$SGR_RED%s$SGR_RESET\\n\" \"!!! cd $DIR\"\n"
  String -> Writer ()
tell String
"        exit 1\n"
  String -> Writer ()
tell String
"    fi\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"change_dir_if() {\n"
  String -> Writer ()
tell String
"    local COND=$1\n"
  String -> Writer ()
tell String
"    local DIR=$2\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    if [ $COND -ne 0 ]; then\n"
  String -> Writer ()
tell String
"        change_dir \"$DIR\"\n"
  String -> Writer ()
tell String
"    fi\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"echo_to() {\n"
  String -> Writer ()
tell String
"    local DEST=$1\n"
  String -> Writer ()
tell String
"    local CONTENTS=$2\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    echo \"$CONTENTS\" >> \"$DEST\"\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"echo_if_to() {\n"
  String -> Writer ()
tell String
"    local COND=$1\n"
  String -> Writer ()
tell String
"    local DEST=$2\n"
  String -> Writer ()
tell String
"    local CONTENTS=$3\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    if [ $COND -ne 0 ]; then\n"
  String -> Writer ()
tell String
"        echo_to \"$DEST\" \"$CONTENTS\"\n"
  String -> Writer ()
tell String
"    fi\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"install_cabalplan() {\n"
  String -> Writer ()
tell String
"    put_info \"installing cabal-plan\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    if [ ! -e $CABAL_REPOCACHE/downloads/cabal-plan ]; then\n"
  String -> Writer ()
tell String
"        curl -L https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > /tmp/cabal-plan.xz || exit 1\n"
  String -> Writer ()
tell String
"        (cd /tmp && echo \"de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc  cabal-plan.xz\" | sha256sum -c -)|| exit 1\n"
  String -> Writer ()
tell String
"        mkdir -p $CABAL_REPOCACHE/downloads\n"
  String -> Writer ()
tell String
"        xz -d < /tmp/cabal-plan.xz > $CABAL_REPOCACHE/downloads/cabal-plan || exit 1\n"
  String -> Writer ()
tell String
"        chmod a+x $CABAL_REPOCACHE/downloads/cabal-plan || exit 1\n"
  String -> Writer ()
tell String
"    fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    mkdir -p $CABAL_DIR/bin || exit 1\n"
  String -> Writer ()
tell String
"    ln -s $CABAL_REPOCACHE/downloads/cabal-plan $CABAL_DIR/bin/cabal-plan || exit 1\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Help\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"show_usage() {\n"
  String -> Writer ()
tell String
"cat <<EOF\n"
  String -> Writer ()
tell String
"./haskell-ci.sh - build & test\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"Usage: ./haskell-ci.sh [options]\n"
  String -> Writer ()
tell String
"  A script to run automated checks locally (using Docker)\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"Available options:\n"
  String -> Writer ()
tell String
"  --jobs JOBS               Jobs to run (default: $CFG_JOBS)\n"
  String -> Writer ()
tell String
"  --cabal-store-cache PATH  Directory to use for cabal-store-cache\n"
  String -> Writer ()
tell String
"  --cabal-repo-cache PATH   Directory to use for cabal-repo-cache\n"
  String -> Writer ()
tell String
"  --skip-cabal-update       Skip cabal update (useful with --cabal-repo-cache)\n"
  String -> Writer ()
tell String
"  --no-skip-cabal-update\n"
  String -> Writer ()
tell String
"  --help                    Print this message\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"EOF\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# getopt\n"
  String -> Writer ()
tell String
"#######################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"process_cli_options() {\n"
  String -> Writer ()
tell String
"    while [ $# -gt 0 ]; do\n"
  String -> Writer ()
tell String
"        arg=$1\n"
  String -> Writer ()
tell String
"        case $arg in\n"
  String -> Writer ()
tell String
"            --help)\n"
  String -> Writer ()
tell String
"                show_usage\n"
  String -> Writer ()
tell String
"                exit\n"
  String -> Writer ()
tell String
"                ;;\n"
  String -> Writer ()
tell String
"            --jobs)\n"
  String -> Writer ()
tell String
"                CFG_JOBS=$2\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                ;;\n"
  String -> Writer ()
tell String
"            --cabal-store-cache)\n"
  String -> Writer ()
tell String
"                CFG_CABAL_STORE_CACHE=$2\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                ;;\n"
  String -> Writer ()
tell String
"            --cabal-repo-cache)\n"
  String -> Writer ()
tell String
"                CFG_CABAL_REPO_CACHE=$2\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                ;;\n"
  String -> Writer ()
tell String
"            --skip-cabal-update)\n"
  String -> Writer ()
tell String
"                CFG_CABAL_UPDATE=false\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                ;;\n"
  String -> Writer ()
tell String
"            --no-skip-cabal-update)\n"
  String -> Writer ()
tell String
"                CFG_CABAL_UPDATE=true\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                ;;\n"
  String -> Writer ()
tell String
"            *)\n"
  String -> Writer ()
tell String
"                echo \"Unknown option $arg\"\n"
  String -> Writer ()
tell String
"                exit 1\n"
  String -> Writer ()
tell String
"        esac\n"
  String -> Writer ()
tell String
"    done\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"process_indocker_options () {\n"
  String -> Writer ()
tell String
"    while [ $# -gt 0 ]; do\n"
  String -> Writer ()
tell String
"        arg=$1\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"        case $arg in\n"
  String -> Writer ()
tell String
"            --ghc-version)\n"
  String -> Writer ()
tell String
"                GHC_VERSION=$2\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                ;;\n"
  String -> Writer ()
tell String
"            --cabal-version)\n"
  String -> Writer ()
tell String
"                CABAL_VERSION=$2\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                ;;\n"
  String -> Writer ()
tell String
"            --start-time)\n"
  String -> Writer ()
tell String
"                START_TIME=$2\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                ;;\n"
  String -> Writer ()
tell String
"            --cabal-update)\n"
  String -> Writer ()
tell String
"                CABAL_UPDATE=$2\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                shift\n"
  String -> Writer ()
tell String
"                ;;\n"
  String -> Writer ()
tell String
"            *)\n"
  String -> Writer ()
tell String
"                echo \"Unknown option $arg\"\n"
  String -> Writer ()
tell String
"                exit 1\n"
  String -> Writer ()
tell String
"        esac\n"
  String -> Writer ()
tell String
"    done\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"if $INDOCKER; then\n"
  String -> Writer ()
tell String
"    process_indocker_options \"$@\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"else\n"
  String -> Writer ()
tell String
"    if [ -f \"$XDG_CONFIG_HOME/haskell-ci/bash.config\" ]; then\n"
  String -> Writer ()
tell String
"        process_cli_options $(cat \"$XDG_CONFIG_HOME/haskell-ci/bash.config\")\n"
  String -> Writer ()
tell String
"    fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    process_cli_options \"$@\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    put_info \"jobs:              $CFG_JOBS\"\n"
  String -> Writer ()
tell String
"    put_info \"cabal-store-cache: $CFG_CABAL_STORE_CACHE\"\n"
  String -> Writer ()
tell String
"    put_info \"cabal-repo-cache:  $CFG_CABAL_REPO_CACHE\"\n"
  String -> Writer ()
tell String
"    put_info \"cabal-update:      $CFG_CABAL_UPDATE\"\n"
  String -> Writer ()
tell String
"fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Constants\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"SRCDIR=/hsci/src\n"
  String -> Writer ()
tell String
"BUILDDIR=/hsci/build\n"
  String -> Writer ()
tell String
"CABAL_DIR=\"$BUILDDIR/cabal\"\n"
  String -> Writer ()
tell String
"CABAL_REPOCACHE=/hsci/cabal-repocache\n"
  String -> Writer ()
tell String
"CABAL_STOREDIR=/hsci/store\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Docker invoke\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# if cache directory is specified, use it.\n"
  String -> Writer ()
tell String
"# Otherwise use another tmpfs host\n"
  String -> Writer ()
tell String
"if [ -z \"$CFG_CABAL_STORE_CACHE\" ]; then\n"
  String -> Writer ()
tell String
"    CABALSTOREARG=\"--tmpfs $CABAL_STOREDIR:exec\"\n"
  String -> Writer ()
tell String
"else\n"
  String -> Writer ()
tell String
"    CABALSTOREARG=\"--volume $CFG_CABAL_STORE_CACHE:$CABAL_STOREDIR\"\n"
  String -> Writer ()
tell String
"fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"if [ -z \"$CFG_CABAL_REPO_CACHE\" ]; then\n"
  String -> Writer ()
tell String
"    CABALREPOARG=\"--tmpfs $CABAL_REPOCACHE:exec\"\n"
  String -> Writer ()
tell String
"else\n"
  String -> Writer ()
tell String
"    CABALREPOARG=\"--volume $CFG_CABAL_REPO_CACHE:$CABAL_REPOCACHE\"\n"
  String -> Writer ()
tell String
"fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"echo_docker_cmd() {\n"
  String -> Writer ()
tell String
"    local GHCVER=$1\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    # TODO: mount /hsci/src:ro (readonly)\n"
  String -> Writer ()
tell String
"    echo docker run \\\n"
  String -> Writer ()
tell String
"        --tty \\\n"
  String -> Writer ()
tell String
"        --interactive \\\n"
  String -> Writer ()
tell String
"        --rm \\\n"
  String -> Writer ()
tell String
"        --label haskell-ci \\\n"
  String -> Writer ()
tell String
"        --volume \"$(pwd):/hsci/src\" \\\n"
  String -> Writer ()
tell String
"        $CABALSTOREARG \\\n"
  String -> Writer ()
tell String
"        $CABALREPOARG \\\n"
  String -> Writer ()
tell String
"        --tmpfs /tmp:exec \\\n"
  String -> Writer ()
tell String
"        --tmpfs /hsci/build:exec \\\n"
  String -> Writer ()
tell String
"        --workdir /hsci/build \\\n"
  String -> Writer ()
tell String
"        \"phadej/ghc:$GHCVER-bionic\" \\\n"
  String -> Writer ()
tell String
"        \"/bin/bash\" \"/hsci/src/$SCRIPT_NAME\" indocker \\\n"
  String -> Writer ()
tell String
"        --ghc-version \"$GHCVER\" \\\n"
  String -> Writer ()
tell String
"        --cabal-update \"$CFG_CABAL_UPDATE\" \\\n"
  String -> Writer ()
tell String
"        --start-time \"$START_TIME\"\n"
  String -> Writer ()
tell String
"}\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# if we are not in docker, loop through jobs\n"
  String -> Writer ()
tell String
"if ! $INDOCKER; then\n"
  String -> Writer ()
tell String
"    for JOB in $CFG_JOBS; do\n"
  String -> Writer ()
tell String
"        put_info \"Running in docker: $JOB\"\n"
  String -> Writer ()
tell String
"        run_cmd $(echo_docker_cmd \"$JOB\")\n"
  String -> Writer ()
tell String
"    done\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"    run_cmd echo \"ALL OK\"\n"
  String -> Writer ()
tell String
"    exit 0\n"
  String -> Writer ()
tell String
"fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Otherwise we are in docker, and the rest of script executes\n"
  String -> Writer ()
tell String
"put_info \"In docker\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Environment\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"GHCDIR=/opt/ghc/$GHC_VERSION\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"HC=$GHCDIR/bin/ghc\n"
  String -> Writer ()
tell String
"HCPKG=$GHCDIR/bin/ghc-pkg\n"
  String -> Writer ()
tell String
"HADDOCK=$GHCDIR/bin/haddock\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"CABAL=/opt/cabal/$CABAL_VERSION/bin/cabal\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"CABAL=\"$CABAL -vnormal+nowrap\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"export CABAL_DIR\n"
  String -> Writer ()
tell String
"export CABAL_CONFIG=\"$BUILDDIR/cabal/config\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"PATH=\"$CABAL_DIR/bin:$PATH\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# HCNUMVER\n"
  String -> Writer ()
tell String
"HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')\n"
  String -> Writer ()
tell String
"GHCJSARITH=0\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"put_info \"HCNUMVER: $HCNUMVER\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Args for shorter/nicer commands\n"
  String -> Writer ()
tell String
"if [ "
  String -> Writer ()
tell (Z -> String
zTestsCond Z
z_root)
  String -> Writer ()
tell String
" -ne 0 ] ; then ARG_TESTS=--enable-tests; else ARG_TESTS=--disable-tests; fi\n"
  String -> Writer ()
tell String
"if [ "
  String -> Writer ()
tell (Z -> String
zBenchCond Z
z_root)
  String -> Writer ()
tell String
" -ne 0 ] ; then ARG_BENCH=--enable-benchmarks; else ARG_BENCH=--disable-benchmarks; fi\n"
  String -> Writer ()
tell String
"ARG_COMPILER=\"--ghc --with-compiler=$HC\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"put_info \"tests/benchmarks: $ARG_TESTS $ARG_BENCH\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Apt dependencies\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  if (Z -> [String] -> Bool
zNotNull Z
z_root (Z -> [String]
zApt Z
z_root))
  then do
    String -> Writer ()
tell String
"run_cmd apt-get update\n"
    String -> Writer ()
tell String
"run_cmd apt-get install -y --no-install-recommends "
    String -> Writer ()
tell (Z -> [String] -> String
zUnwords Z
z_root (Z -> [String]
zApt Z
z_root))
    String -> Writer ()
tell String
"\n"
    () -> Writer ()
forall a. a -> (String, a)
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  else do
    () -> Writer ()
forall a. a -> (String, a)
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Cabal config\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"mkdir -p $BUILDDIR/cabal\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"cat > $BUILDDIR/cabal/config <<EOF\n"
  String -> Writer ()
tell String
"remote-build-reporting: anonymous\n"
  String -> Writer ()
tell String
"write-ghc-environment-files: always\n"
  String -> Writer ()
tell String
"remote-repo-cache: $CABAL_REPOCACHE\n"
  String -> Writer ()
tell String
"logs-dir:          $CABAL_DIR/logs\n"
  String -> Writer ()
tell String
"world-file:        $CABAL_DIR/world\n"
  String -> Writer ()
tell String
"extra-prog-path:   $CABAL_DIR/bin\n"
  String -> Writer ()
tell String
"symlink-bindir:    $CABAL_DIR/bin\n"
  String -> Writer ()
tell String
"installdir:        $CABAL_DIR/bin\n"
  String -> Writer ()
tell String
"build-summary:     $CABAL_DIR/logs/build.log\n"
  String -> Writer ()
tell String
"store-dir:         $CABAL_STOREDIR\n"
  String -> Writer ()
tell String
"install-dirs user\n"
  String -> Writer ()
tell String
"  prefix: $CABAL_DIR\n"
  String -> Writer ()
tell String
"repository hackage.haskell.org\n"
  String -> Writer ()
tell String
"  url: http://hackage.haskell.org/\n"
  String -> Writer ()
tell String
"EOF\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"if $HEADHACKAGE; then\n"
  String -> Writer ()
tell String
"    put_error \"head.hackage is not implemented\"\n"
  String -> Writer ()
tell String
"    exit 1\n"
  String -> Writer ()
tell String
"fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"run_cmd cat \"$BUILDDIR/cabal/config\"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Version\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"put_info \"Versions\"\n"
  String -> Writer ()
tell String
"run_cmd $HC --version\n"
  String -> Writer ()
tell String
"run_cmd_unchecked $HC --print-project-git-commit-id\n"
  String -> Writer ()
tell String
"run_cmd $CABAL --version\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Build script\n"
  String -> Writer ()
tell String
"##############################################################################\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# update cabal index\n"
  String -> Writer ()
tell String
"if $CABAL_UPDATE; then\n"
  String -> Writer ()
tell String
"    put_info \"Updating Hackage index\"\n"
  String -> Writer ()
tell String
"    run_cmd $CABAL v2-update -v\n"
  String -> Writer ()
tell String
"fi\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# install cabal-plan\n"
  String -> Writer ()
tell String
"install_cabalplan\n"
  String -> Writer ()
tell String
"run_cmd cabal-plan --version\n"
  String -> Writer ()
tell String
"\n"
  [String] -> (String -> Writer ()) -> Writer ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Z -> [String]
zBlocks Z
z_root) ((String -> Writer ()) -> Writer ())
-> (String -> Writer ()) -> Writer ()
forall a b. (a -> b) -> a -> b
$ \String
z_var0_block -> do
    String -> Writer ()
tell String
z_var0_block
    String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"\n"
  String -> Writer ()
tell String
"# Done\n"
  String -> Writer ()
tell String
"run_cmd echo OK\n"