packages feed

haskell-ci 0.2.1 → 0.4

raw patch · 63 files changed

+4757/−2540 lines, 63 filesdep +aesondep +bifunctorsdep +exceptionsdep ~Cabaldep ~ShellCheckdep ~ansi-terminalPVP ok

version bump matches the API change (PVP)

Dependencies added: aeson, bifunctors, exceptions, lattices, mtl, process, temporary, unordered-containers

Dependency ranges changed: Cabal, ShellCheck, ansi-terminal, base, tasty

API changes (from Hackage documentation)

- HaskellCI: Error :: String -> Diagnostic
- HaskellCI: Failure :: [e] -> Result e a
- HaskellCI: Info :: String -> Diagnostic
- HaskellCI: Success :: [e] -> a -> Result e a
- HaskellCI: Warn :: String -> Diagnostic
- HaskellCI: [optCollections] :: Options -> [String]
- HaskellCI: data Diagnostic
- HaskellCI: data Result e a
- HaskellCI: formatDiagnostic :: Diagnostic -> String
- HaskellCI: formatDiagnostics :: [Diagnostic] -> String
- HaskellCI: type MakeTravisOutput = Result Diagnostic [String]
- HaskellCI.Cli: [optCollections] :: Options -> [String]
- HaskellCI.Config: [cfgNoise] :: Config -> !Bool
- HaskellCI.Config: instance Distribution.Compat.Newtype.Newtype HaskellCI.Config.Env (Data.Map.Internal.Map Distribution.Types.Version.Version GHC.Base.String)
- HaskellCI.Config: instance Distribution.Parsec.Class.Parsec HaskellCI.Config.Env
- HaskellCI.Config: instance GHC.Show.Show HaskellCI.Config.Config
- HaskellCI.Config.CopyFields: instance Distribution.Parsec.Class.Parsec HaskellCI.Config.CopyFields.CopyFields
- HaskellCI.Config.Folds: instance Distribution.Compat.Newtype.Newtype HaskellCI.Config.Folds.Folds (Data.Set.Internal.Set HaskellCI.Config.Folds.Fold)
- HaskellCI.Config.Folds: instance Distribution.Parsec.Class.Parsec HaskellCI.Config.Folds.Folds
- HaskellCI.Config.HLint: instance Distribution.Parsec.Class.Parsec HaskellCI.Config.HLint.HLintJob
- HaskellCI.Config.Installed: instance Distribution.Parsec.Class.Parsec HaskellCI.Config.Installed.Installed
- HaskellCI.Config.Jobs: instance Distribution.Parsec.Class.Parsec HaskellCI.Config.Jobs.Jobs
- HaskellCI.Extras: afterInfix :: Eq a => [a] -> [a] -> Maybe [a]
- HaskellCI.Extras: afterPrefix :: Eq a => [a] -> [a] -> Maybe [a]
- HaskellCI.Extras: findMaybe :: (a -> Maybe b) -> [a] -> Maybe b
- HaskellCI.GHC: dispGhcVersion :: Maybe Version -> String
- HaskellCI.GHC: ghcAlpha :: Maybe Version
- HaskellCI.GHC: ghcMajVer :: Version -> (Int, Int)
- HaskellCI.GHC: knownGhcVersions :: [Version]
- HaskellCI.GHC: previewGHC :: Maybe Version -> Bool
- HaskellCI.MakeTravisOutput: Error :: String -> Diagnostic
- HaskellCI.MakeTravisOutput: Failure :: [e] -> Result e a
- HaskellCI.MakeTravisOutput: Info :: String -> Diagnostic
- HaskellCI.MakeTravisOutput: Row :: String -> Row
- HaskellCI.MakeTravisOutput: RowErr :: String -> Row
- HaskellCI.MakeTravisOutput: RowSkip :: Row
- HaskellCI.MakeTravisOutput: Success :: [e] -> a -> Result e a
- HaskellCI.MakeTravisOutput: Warn :: String -> Diagnostic
- HaskellCI.MakeTravisOutput: blank :: Row
- HaskellCI.MakeTravisOutput: comment :: String -> Row
- HaskellCI.MakeTravisOutput: data Diagnostic
- HaskellCI.MakeTravisOutput: data Result e a
- HaskellCI.MakeTravisOutput: data Row
- HaskellCI.MakeTravisOutput: foldedTellStrLns :: Monad m => Fold -> String -> Set Fold -> YamlWriter m () -> YamlWriter m ()
- HaskellCI.MakeTravisOutput: foldedTellStrLns' :: Monad m => Fold -> String -> String -> Set Fold -> YamlWriter m () -> YamlWriter m ()
- HaskellCI.MakeTravisOutput: formatDiagnostic :: Diagnostic -> String
- HaskellCI.MakeTravisOutput: formatDiagnostics :: [Diagnostic] -> String
- HaskellCI.MakeTravisOutput: instance (GHC.Classes.Eq e, GHC.Classes.Eq a) => GHC.Classes.Eq (HaskellCI.MakeTravisOutput.Result e a)
- HaskellCI.MakeTravisOutput: instance (GHC.Show.Show e, GHC.Show.Show a) => GHC.Show.Show (HaskellCI.MakeTravisOutput.Result e a)
- HaskellCI.MakeTravisOutput: instance Data.String.IsString HaskellCI.MakeTravisOutput.Row
- HaskellCI.MakeTravisOutput: instance GHC.Base.Functor (HaskellCI.MakeTravisOutput.Result e)
- HaskellCI.MakeTravisOutput: instance GHC.Base.Monoid a => GHC.Base.Monoid (HaskellCI.MakeTravisOutput.Result e a)
- HaskellCI.MakeTravisOutput: instance GHC.Base.Monoid a => GHC.Base.Semigroup (HaskellCI.MakeTravisOutput.Result e a)
- HaskellCI.MakeTravisOutput: instance GHC.Classes.Eq HaskellCI.MakeTravisOutput.Diagnostic
- HaskellCI.MakeTravisOutput: instance GHC.Show.Show HaskellCI.MakeTravisOutput.Diagnostic
- HaskellCI.MakeTravisOutput: putStrLnErr :: Monad m => String -> YamlWriter m a
- HaskellCI.MakeTravisOutput: putStrLnErrs :: Monad m => [String] -> YamlWriter m ()
- HaskellCI.MakeTravisOutput: putStrLnInfo :: Monad m => String -> YamlWriter m ()
- HaskellCI.MakeTravisOutput: putStrLnWarn :: Monad m => String -> YamlWriter m ()
- HaskellCI.MakeTravisOutput: rawRow :: String -> Row
- HaskellCI.MakeTravisOutput: sequenceRows :: [Row] -> Either String [String]
- HaskellCI.MakeTravisOutput: sh :: String -> Row
- HaskellCI.MakeTravisOutput: sh' :: [Integer] -> String -> Row
- HaskellCI.MakeTravisOutput: shForJob :: Set Version -> VersionRange -> String -> Row
- HaskellCI.MakeTravisOutput: shImpl :: String -> String
- HaskellCI.MakeTravisOutput: success :: a -> Result e a
- HaskellCI.MakeTravisOutput: tellStrLn :: Monad m => String -> YamlWriter m ()
- HaskellCI.MakeTravisOutput: tellStrLns :: Monad m => [Row] -> YamlWriter m ()
- HaskellCI.MakeTravisOutput: tellStrLnsRaw :: Monad m => [String] -> YamlWriter m ()
- HaskellCI.MakeTravisOutput: type MakeTravisOutput = Result Diagnostic [String]
- HaskellCI.MakeTravisOutput: type YamlWriter m a = MaybeT (WriterT MakeTravisOutput m) a
- HaskellCI.Newtypes: class Sep sep
- HaskellCI.Newtypes: instance (Distribution.Compat.Newtype.Newtype b a, GHC.Classes.Ord a, HaskellCI.Newtypes.Sep sep, Distribution.Parsec.Class.Parsec b) => Distribution.Parsec.Class.Parsec (HaskellCI.Newtypes.AlaSet sep b a)
- HaskellCI.Newtypes: instance (Distribution.Compat.Newtype.Newtype b a, HaskellCI.Newtypes.Sep sep, Distribution.Pretty.Pretty b) => Distribution.Pretty.Pretty (HaskellCI.Newtypes.AlaSet sep b a)
- HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype (HaskellCI.Newtypes.AlaSet sep wrapper a) (Data.Set.Internal.Set a)
- HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype HaskellCI.Newtypes.HeadVersion (GHC.Maybe.Maybe Distribution.Types.Version.Version)
- HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype HaskellCI.Newtypes.Int' GHC.Types.Int
- HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype HaskellCI.Newtypes.NoCommas [GHC.Types.Char]
- HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype HaskellCI.Newtypes.PackageLocation [GHC.Types.Char]
- HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype HaskellCI.Newtypes.Range Distribution.Types.VersionRange.VersionRange
- HaskellCI.Newtypes: instance Distribution.Parsec.Class.Parsec HaskellCI.Newtypes.HeadVersion
- HaskellCI.Newtypes: instance Distribution.Parsec.Class.Parsec HaskellCI.Newtypes.Int'
- HaskellCI.Newtypes: instance Distribution.Parsec.Class.Parsec HaskellCI.Newtypes.NoCommas
- HaskellCI.Newtypes: instance Distribution.Parsec.Class.Parsec HaskellCI.Newtypes.PackageLocation
- HaskellCI.Newtypes: instance Distribution.Parsec.Class.Parsec HaskellCI.Newtypes.Range
- HaskellCI.Newtypes: instance HaskellCI.Newtypes.Sep Distribution.Parsec.Newtypes.CommaFSep
- HaskellCI.Newtypes: instance HaskellCI.Newtypes.Sep Distribution.Parsec.Newtypes.CommaVCat
- HaskellCI.Newtypes: instance HaskellCI.Newtypes.Sep Distribution.Parsec.Newtypes.NoCommaFSep
- HaskellCI.Newtypes: parseSep :: (Sep sep, CabalParsing m) => Proxy sep -> m a -> m [a]
- HaskellCI.Newtypes: prettySep :: Sep sep => Proxy sep -> [Doc] -> Doc
- HaskellCI.Optimization: instance Distribution.Parsec.Class.Parsec HaskellCI.Optimization.Optimization
- HaskellCI.Project: instance Data.Foldable.Foldable HaskellCI.Project.Project
- HaskellCI.Project: instance Data.Traversable.Traversable HaskellCI.Project.Project
- HaskellCI.Project: instance GHC.Base.Functor HaskellCI.Project.Project
- HaskellCI.Project: instance GHC.Generics.Generic (HaskellCI.Project.Project a)
- HaskellCI.Project: instance GHC.Show.Show a => GHC.Show.Show (HaskellCI.Project.Project a)
- HaskellCI.TestedWith: instance Distribution.Parsec.Class.Parsec HaskellCI.TestedWith.TestedWithJobs
- HaskellCI.Version: equivVersionRanges :: VersionRange -> VersionRange -> Bool
- HaskellCI.Version: ghcVersionPredicate :: VersionRange -> String
- HaskellCI.Version: ghcVersionToString :: Version -> String
+ HaskellCI.Cli: OutputFile :: FilePath -> Output
+ HaskellCI.Cli: OutputStdout :: Output
+ HaskellCI.Cli: data Output
+ HaskellCI.Cli: haskellCIVerStr :: String
+ HaskellCI.Cli: optionsWithOutputFile :: FilePath -> Options
+ HaskellCI.Cli: outputP :: Parser Output
+ HaskellCI.Cli: versionP :: Parser (a -> a)
+ HaskellCI.Compiler: GHC :: Version -> CompilerVersion
+ HaskellCI.Compiler: GHCHead :: CompilerVersion
+ HaskellCI.Compiler: GHCJS :: Version -> CompilerVersion
+ HaskellCI.Compiler: Range :: VersionRange -> CompilerRange
+ HaskellCI.Compiler: RangeGHC :: CompilerRange
+ HaskellCI.Compiler: RangeGHCJS :: CompilerRange
+ HaskellCI.Compiler: RangeInter :: CompilerRange -> CompilerRange -> CompilerRange
+ HaskellCI.Compiler: RangePoints :: Set CompilerVersion -> CompilerRange
+ HaskellCI.Compiler: RangeUnion :: CompilerRange -> CompilerRange -> CompilerRange
+ HaskellCI.Compiler: compilerWithinRange :: CompilerVersion -> CompilerRange -> Bool
+ HaskellCI.Compiler: correspondingCabalVersion :: Maybe Version -> CompilerVersion -> Maybe Version
+ HaskellCI.Compiler: data CompilerRange
+ HaskellCI.Compiler: data CompilerVersion
+ HaskellCI.Compiler: dispCabalVersion :: Maybe Version -> String
+ HaskellCI.Compiler: dispGhcVersion :: CompilerVersion -> String
+ HaskellCI.Compiler: dispGhcVersionShort :: CompilerVersion -> String
+ HaskellCI.Compiler: ghcMajVer :: Version -> (Int, Int)
+ HaskellCI.Compiler: instance Algebra.Lattice.BoundedJoinSemiLattice HaskellCI.Compiler.CompilerRange
+ HaskellCI.Compiler: instance Algebra.Lattice.BoundedMeetSemiLattice HaskellCI.Compiler.CompilerRange
+ HaskellCI.Compiler: instance Algebra.Lattice.Lattice HaskellCI.Compiler.CompilerRange
+ HaskellCI.Compiler: instance GHC.Classes.Eq HaskellCI.Compiler.CompilerVersion
+ HaskellCI.Compiler: instance GHC.Classes.Ord HaskellCI.Compiler.CompilerVersion
+ HaskellCI.Compiler: instance GHC.Show.Show HaskellCI.Compiler.CompilerRange
+ HaskellCI.Compiler: instance GHC.Show.Show HaskellCI.Compiler.CompilerVersion
+ HaskellCI.Compiler: invertCompilerRange :: CompilerRange -> CompilerRange
+ HaskellCI.Compiler: isGHCJS :: CompilerVersion -> Bool
+ HaskellCI.Compiler: knownGhcVersions :: [Version]
+ HaskellCI.Compiler: knownGhcjsVersions :: [Version]
+ HaskellCI.Compiler: maybeGHC :: a -> (Version -> a) -> CompilerVersion -> a
+ HaskellCI.Compiler: previewGHC :: VersionRange -> CompilerVersion -> Bool
+ HaskellCI.Config: [cfgColor] :: Config -> !Bool
+ HaskellCI.Config: [cfgGhcjsTests] :: Config -> !Bool
+ HaskellCI.Config: [cfgHeadHackage] :: Config -> !VersionRange
+ HaskellCI.Config: [cfgInsertVersion] :: Config -> !Bool
+ HaskellCI.Config: [cfgRunTests] :: Config -> !VersionRange
+ HaskellCI.Config: [cfgSubmodules] :: Config -> !Bool
+ HaskellCI.Config: [cfgTravisPatches] :: Config -> [FilePath]
+ HaskellCI.Config: [cfgUbuntu] :: Config -> !Ubuntu
+ HaskellCI.Config: defaultHeadHackage :: VersionRange
+ HaskellCI.Config: instance Distribution.Compat.Newtype.Newtype (Data.Map.Internal.Map Distribution.Types.Version.Version GHC.Base.String) HaskellCI.Config.Env
+ HaskellCI.Config: instance Distribution.Parsec.Parsec HaskellCI.Config.Env
+ HaskellCI.Config.ConstraintSet: [csBenchmarks] :: ConstraintSet -> Bool
+ HaskellCI.Config.ConstraintSet: [csHaddock] :: ConstraintSet -> Bool
+ HaskellCI.Config.ConstraintSet: [csTests] :: ConstraintSet -> Bool
+ HaskellCI.Config.CopyFields: instance Distribution.Parsec.Parsec HaskellCI.Config.CopyFields.CopyFields
+ HaskellCI.Config.Doctest: [cfgDoctestFilterPkgs] :: DoctestConfig -> ![PackageName]
+ HaskellCI.Config.Folds: instance Distribution.Compat.Newtype.Newtype (Data.Set.Internal.Set HaskellCI.Config.Folds.Fold) HaskellCI.Config.Folds.Folds
+ HaskellCI.Config.Folds: instance Distribution.Parsec.Parsec HaskellCI.Config.Folds.Folds
+ HaskellCI.Config.HLint: instance Distribution.Parsec.Parsec HaskellCI.Config.HLint.HLintJob
+ HaskellCI.Config.Installed: instance Distribution.Parsec.Parsec HaskellCI.Config.Installed.Installed
+ HaskellCI.Config.Jobs: instance Distribution.Parsec.Parsec HaskellCI.Config.Jobs.Jobs
+ HaskellCI.Config.Ubuntu: Bionic :: Ubuntu
+ HaskellCI.Config.Ubuntu: Xenial :: Ubuntu
+ HaskellCI.Config.Ubuntu: data Ubuntu
+ HaskellCI.Config.Ubuntu: instance Distribution.Parsec.Parsec HaskellCI.Config.Ubuntu.Ubuntu
+ HaskellCI.Config.Ubuntu: instance Distribution.Pretty.Pretty HaskellCI.Config.Ubuntu.Ubuntu
+ HaskellCI.Config.Ubuntu: instance GHC.Classes.Eq HaskellCI.Config.Ubuntu.Ubuntu
+ HaskellCI.Config.Ubuntu: instance GHC.Classes.Ord HaskellCI.Config.Ubuntu.Ubuntu
+ HaskellCI.Config.Ubuntu: instance GHC.Show.Show HaskellCI.Config.Ubuntu.Ubuntu
+ HaskellCI.Config.Ubuntu: showUbuntu :: Ubuntu -> String
+ HaskellCI.Diagnostics: Diagnostics :: MaybeT (WriterT [String] m) a -> DiagnosticsT m a
+ HaskellCI.Diagnostics: [unDiagnostics] :: DiagnosticsT m a -> MaybeT (WriterT [String] m) a
+ HaskellCI.Diagnostics: class Monad m => MonadDiagnostics m
+ HaskellCI.Diagnostics: instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (HaskellCI.Diagnostics.DiagnosticsT m)
+ HaskellCI.Diagnostics: instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (HaskellCI.Diagnostics.DiagnosticsT m)
+ HaskellCI.Diagnostics: instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (HaskellCI.Diagnostics.DiagnosticsT m)
+ HaskellCI.Diagnostics: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (HaskellCI.Diagnostics.DiagnosticsT m)
+ HaskellCI.Diagnostics: instance GHC.Base.Functor m => GHC.Base.Functor (HaskellCI.Diagnostics.DiagnosticsT m)
+ HaskellCI.Diagnostics: instance GHC.Base.Monad m => GHC.Base.Applicative (HaskellCI.Diagnostics.DiagnosticsT m)
+ HaskellCI.Diagnostics: instance GHC.Base.Monad m => GHC.Base.Monad (HaskellCI.Diagnostics.DiagnosticsT m)
+ HaskellCI.Diagnostics: instance GHC.Base.Monad m => HaskellCI.Diagnostics.MonadDiagnostics (HaskellCI.Diagnostics.DiagnosticsT m)
+ HaskellCI.Diagnostics: instance HaskellCI.Diagnostics.MonadDiagnostics GHC.Types.IO
+ HaskellCI.Diagnostics: newtype DiagnosticsT m a
+ HaskellCI.Diagnostics: putStrLnErr :: MonadDiagnostics m => String -> m a
+ HaskellCI.Diagnostics: putStrLnErrs :: MonadDiagnostics m => NonEmpty String -> m a
+ HaskellCI.Diagnostics: putStrLnInfo :: MonadDiagnostics m => String -> m ()
+ HaskellCI.Diagnostics: putStrLnWarn :: MonadDiagnostics m => String -> m ()
+ HaskellCI.Diagnostics: runDiagnosticsT :: DiagnosticsT m a -> m (Maybe a, [String])
+ HaskellCI.Jobs: JobVersions :: Set CompilerVersion -> Set Version -> Set Version -> JobVersions
+ HaskellCI.Jobs: [omittedOsxVersions] :: JobVersions -> Set Version
+ HaskellCI.Jobs: [osxVersions] :: JobVersions -> Set Version
+ HaskellCI.Jobs: [versions] :: JobVersions -> Set CompilerVersion
+ HaskellCI.Jobs: data JobVersions
+ HaskellCI.Jobs: describeJobs :: MonadDiagnostics m => TestedWithJobs -> JobVersions -> [Package] -> m ()
+ HaskellCI.Jobs: makeJobVersions :: Config -> Set CompilerVersion -> JobVersions
+ HaskellCI.List: buildList :: ListBuilder x () -> [x]
+ HaskellCI.List: data ListBuilder x a
+ HaskellCI.List: instance GHC.Base.Applicative (HaskellCI.List.ListBuilder x)
+ HaskellCI.List: instance GHC.Base.Functor (HaskellCI.List.ListBuilder x)
+ HaskellCI.List: instance GHC.Base.Monad (HaskellCI.List.ListBuilder x)
+ HaskellCI.List: item :: x -> ListBuilder x ()
+ HaskellCI.MonadErr: class Monad m => MonadErr e m | m -> e
+ HaskellCI.MonadErr: instance HaskellCI.MonadErr.MonadErr e (Data.Either.Either e)
+ HaskellCI.MonadErr: throwErr :: MonadErr e m => e -> m a
+ HaskellCI.Newtypes: hack :: Proxy a -> proxy a
+ HaskellCI.Newtypes: instance (Distribution.Compat.Newtype.Newtype a b, Distribution.Parsec.Newtypes.Sep sep, Distribution.Pretty.Pretty b) => Distribution.Pretty.Pretty (HaskellCI.Newtypes.AlaSet sep b a)
+ HaskellCI.Newtypes: instance (Distribution.Compat.Newtype.Newtype a b, GHC.Classes.Ord a, Distribution.Parsec.Newtypes.Sep sep, Distribution.Parsec.Parsec b) => Distribution.Parsec.Parsec (HaskellCI.Newtypes.AlaSet sep b a)
+ HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype (Data.Set.Internal.Set a) (HaskellCI.Newtypes.AlaSet sep b a)
+ HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype (GHC.Maybe.Maybe Distribution.Types.Version.Version) HaskellCI.Newtypes.HeadVersion
+ HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype Distribution.Types.VersionRange.Internal.VersionRange HaskellCI.Newtypes.Range
+ HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype GHC.Base.String HaskellCI.Newtypes.NoCommas
+ HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype GHC.Base.String HaskellCI.Newtypes.PackageLocation
+ HaskellCI.Newtypes: instance Distribution.Compat.Newtype.Newtype GHC.Types.Int HaskellCI.Newtypes.Int'
+ HaskellCI.Newtypes: instance Distribution.Parsec.Parsec HaskellCI.Newtypes.HeadVersion
+ HaskellCI.Newtypes: instance Distribution.Parsec.Parsec HaskellCI.Newtypes.Int'
+ HaskellCI.Newtypes: instance Distribution.Parsec.Parsec HaskellCI.Newtypes.NoCommas
+ HaskellCI.Newtypes: instance Distribution.Parsec.Parsec HaskellCI.Newtypes.PackageLocation
+ HaskellCI.Newtypes: instance Distribution.Parsec.Parsec HaskellCI.Newtypes.Range
+ HaskellCI.Optimization: instance Distribution.Parsec.Parsec HaskellCI.Optimization.Optimization
+ HaskellCI.Package: instance GHC.Generics.Generic HaskellCI.Package.Package
+ HaskellCI.Prelude: (!!) :: () => [a] -> Int -> a
+ HaskellCI.Prelude: ($!) :: () => (a -> b) -> a -> b
+ HaskellCI.Prelude: ($) :: () => (a -> b) -> a -> b
+ HaskellCI.Prelude: (&&) :: Bool -> Bool -> Bool
+ HaskellCI.Prelude: (&) :: () => a -> (a -> b) -> b
+ HaskellCI.Prelude: (*) :: Num a => a -> a -> a
+ HaskellCI.Prelude: (**) :: Floating a => a -> a -> a
+ HaskellCI.Prelude: (*>) :: Applicative f => f a -> f b -> f b
+ HaskellCI.Prelude: (+) :: Num a => a -> a -> a
+ HaskellCI.Prelude: (++) :: () => [a] -> [a] -> [a]
+ HaskellCI.Prelude: (-) :: Num a => a -> a -> a
+ HaskellCI.Prelude: (.) :: () => (b -> c) -> (a -> b) -> a -> c
+ HaskellCI.Prelude: (.~) :: () => ASetter s t a b -> b -> s -> t
+ HaskellCI.Prelude: (/) :: Fractional a => a -> a -> a
+ HaskellCI.Prelude: (/=) :: Eq a => a -> a -> Bool
+ HaskellCI.Prelude: (/\) :: Lattice a => a -> a -> a
+ HaskellCI.Prelude: (:|) :: a -> [a] -> NonEmpty a
+ HaskellCI.Prelude: (<$) :: Functor f => a -> f b -> f a
+ HaskellCI.Prelude: (<$>) :: Functor f => (a -> b) -> f a -> f b
+ HaskellCI.Prelude: (<&>) :: Functor f => f a -> (a -> b) -> f b
+ HaskellCI.Prelude: (<) :: Ord a => a -> a -> Bool
+ HaskellCI.Prelude: (<*) :: Applicative f => f a -> f b -> f a
+ HaskellCI.Prelude: (<*>) :: Applicative f => f (a -> b) -> f a -> f b
+ HaskellCI.Prelude: (<=) :: Ord a => a -> a -> Bool
+ HaskellCI.Prelude: (<>) :: Semigroup a => a -> a -> a
+ HaskellCI.Prelude: (<|>) :: Alternative f => f a -> f a -> f a
+ HaskellCI.Prelude: (=<<) :: Monad m => (a -> m b) -> m a -> m b
+ HaskellCI.Prelude: (==) :: Eq a => a -> a -> Bool
+ HaskellCI.Prelude: (>) :: Ord a => a -> a -> Bool
+ HaskellCI.Prelude: (>=) :: Ord a => a -> a -> Bool
+ HaskellCI.Prelude: (>>) :: Monad m => m a -> m b -> m b
+ HaskellCI.Prelude: (>>=) :: Monad m => m a -> (a -> m b) -> m b
+ HaskellCI.Prelude: (\/) :: Lattice a => a -> a -> a
+ HaskellCI.Prelude: (^) :: (Num a, Integral b) => a -> b -> a
+ HaskellCI.Prelude: (^.) :: () => s -> Getting a s a -> a
+ HaskellCI.Prelude: (^..) :: () => s -> Getting (Endo [a]) s a -> [a]
+ HaskellCI.Prelude: (^^) :: (Fractional a, Integral b) => a -> b -> a
+ HaskellCI.Prelude: (||) :: Bool -> Bool -> Bool
+ HaskellCI.Prelude: EQ :: Ordering
+ HaskellCI.Prelude: False :: Bool
+ HaskellCI.Prelude: GT :: Ordering
+ HaskellCI.Prelude: Identity :: a -> Identity a
+ HaskellCI.Prelude: Just :: a -> Maybe a
+ HaskellCI.Prelude: LT :: Ordering
+ HaskellCI.Prelude: Left :: a -> Either a b
+ HaskellCI.Prelude: Nothing :: Maybe a
+ HaskellCI.Prelude: Proxy :: Proxy
+ HaskellCI.Prelude: Right :: b -> Either a b
+ HaskellCI.Prelude: True :: Bool
+ HaskellCI.Prelude: [runIdentity] :: Identity a -> a
+ HaskellCI.Prelude: abs :: Num a => a -> a
+ HaskellCI.Prelude: acos :: Floating a => a -> a
+ HaskellCI.Prelude: acosh :: Floating a => a -> a
+ HaskellCI.Prelude: afterInfix :: Eq a => [a] -> [a] -> Maybe [a]
+ HaskellCI.Prelude: afterPrefix :: Eq a => [a] -> [a] -> Maybe [a]
+ HaskellCI.Prelude: all :: Foldable t => (a -> Bool) -> t a -> Bool
+ HaskellCI.Prelude: and :: Foldable t => t Bool -> Bool
+ HaskellCI.Prelude: any :: Foldable t => (a -> Bool) -> t a -> Bool
+ HaskellCI.Prelude: anyVersion :: VersionRange
+ HaskellCI.Prelude: ap :: Monad m => m (a -> b) -> m a -> m b
+ HaskellCI.Prelude: appendFile :: FilePath -> String -> IO ()
+ HaskellCI.Prelude: asTypeOf :: () => a -> a -> a
+ HaskellCI.Prelude: asin :: Floating a => a -> a
+ HaskellCI.Prelude: asinh :: Floating a => a -> a
+ HaskellCI.Prelude: atan :: Floating a => a -> a
+ HaskellCI.Prelude: atan2 :: RealFloat a => a -> a -> a
+ HaskellCI.Prelude: atanh :: Floating a => a -> a
+ HaskellCI.Prelude: bifold :: (Bifoldable p, Monoid m) => p m m -> m
+ HaskellCI.Prelude: bifoldMap :: (Bifoldable p, Monoid m) => (a -> m) -> (b -> m) -> p a b -> m
+ HaskellCI.Prelude: bifoldMapDefault :: (Bitraversable t, Monoid m) => (a -> m) -> (b -> m) -> t a b -> m
+ HaskellCI.Prelude: bifoldl :: Bifoldable p => (c -> a -> c) -> (c -> b -> c) -> c -> p a b -> c
+ HaskellCI.Prelude: bifoldr :: Bifoldable p => (a -> c -> c) -> (b -> c -> c) -> c -> p a b -> c
+ HaskellCI.Prelude: bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
+ HaskellCI.Prelude: bimapDefault :: Bitraversable t => (a -> b) -> (c -> d) -> t a c -> t b d
+ HaskellCI.Prelude: bitraverse :: (Bitraversable t, Applicative f) => (a -> f c) -> (b -> f d) -> t a b -> f (t c d)
+ HaskellCI.Prelude: bottom :: BoundedJoinSemiLattice a => a
+ HaskellCI.Prelude: break :: () => (a -> Bool) -> [a] -> ([a], [a])
+ HaskellCI.Prelude: ceiling :: (RealFrac a, Integral b) => a -> b
+ HaskellCI.Prelude: class Functor f => Applicative (f :: Type -> Type)
+ HaskellCI.Prelude: class Bifoldable (p :: Type -> Type -> Type)
+ HaskellCI.Prelude: class Bifunctor (p :: Type -> Type -> Type)
+ HaskellCI.Prelude: class (Bifunctor t, Bifoldable t) => Bitraversable (t :: Type -> Type -> Type)
+ HaskellCI.Prelude: class Bounded a
+ HaskellCI.Prelude: class Lattice a => BoundedJoinSemiLattice a
+ HaskellCI.Prelude: class Lattice a => BoundedMeetSemiLattice a
+ HaskellCI.Prelude: class Enum a
+ HaskellCI.Prelude: class Eq a
+ HaskellCI.Prelude: class (Typeable e, Show e) => Exception e
+ HaskellCI.Prelude: class Fractional a => Floating a
+ HaskellCI.Prelude: class Foldable (t :: Type -> Type)
+ HaskellCI.Prelude: class Num a => Fractional a
+ HaskellCI.Prelude: class Functor (f :: Type -> Type)
+ HaskellCI.Prelude: class Generic a
+ HaskellCI.Prelude: class (Real a, Enum a) => Integral a
+ HaskellCI.Prelude: class IsString a
+ HaskellCI.Prelude: class Lattice a
+ HaskellCI.Prelude: class Applicative m => Monad (m :: Type -> Type)
+ HaskellCI.Prelude: class MonadThrow m => MonadCatch (m :: Type -> Type)
+ HaskellCI.Prelude: class Monad m => MonadIO (m :: Type -> Type)
+ HaskellCI.Prelude: class MonadCatch m => MonadMask (m :: Type -> Type)
+ HaskellCI.Prelude: class Monad m => MonadThrow (m :: Type -> Type)
+ HaskellCI.Prelude: class Semigroup a => Monoid a
+ HaskellCI.Prelude: class Num a
+ HaskellCI.Prelude: class Eq a => Ord a
+ HaskellCI.Prelude: class Read a
+ HaskellCI.Prelude: class (Num a, Ord a) => Real a
+ HaskellCI.Prelude: class (RealFrac a, Floating a) => RealFloat a
+ HaskellCI.Prelude: class (Real a, Fractional a) => RealFrac a
+ HaskellCI.Prelude: class Semigroup a
+ HaskellCI.Prelude: class Show a
+ HaskellCI.Prelude: class (Functor t, Foldable t) => Traversable (t :: Type -> Type)
+ HaskellCI.Prelude: coerce :: Coercible a b => a -> b
+ HaskellCI.Prelude: compare :: Ord a => a -> a -> Ordering
+ HaskellCI.Prelude: concat :: Foldable t => t [a] -> [a]
+ HaskellCI.Prelude: concatMap :: Foldable t => (a -> [b]) -> t a -> [b]
+ HaskellCI.Prelude: const :: () => a -> b -> a
+ HaskellCI.Prelude: cos :: Floating a => a -> a
+ HaskellCI.Prelude: cosh :: Floating a => a -> a
+ HaskellCI.Prelude: curry :: () => ((a, b) -> c) -> a -> b -> c
+ HaskellCI.Prelude: cycle :: () => [a] -> [a]
+ HaskellCI.Prelude: data Bool
+ HaskellCI.Prelude: data ByteString
+ HaskellCI.Prelude: data Char
+ HaskellCI.Prelude: data Double
+ HaskellCI.Prelude: data Either a b
+ HaskellCI.Prelude: data Float
+ HaskellCI.Prelude: data IO a
+ HaskellCI.Prelude: data Int
+ HaskellCI.Prelude: data Integer
+ HaskellCI.Prelude: data Maybe a
+ HaskellCI.Prelude: data NonEmpty a
+ HaskellCI.Prelude: data Ordering
+ HaskellCI.Prelude: data Set a
+ HaskellCI.Prelude: data Version
+ HaskellCI.Prelude: data VersionRange
+ HaskellCI.Prelude: data Void
+ HaskellCI.Prelude: data Word
+ HaskellCI.Prelude: data Proxy (t :: k) :: forall k. () => k -> Type
+ HaskellCI.Prelude: decodeFloat :: RealFloat a => a -> (Integer, Int)
+ HaskellCI.Prelude: displayException :: Exception e => e -> String
+ HaskellCI.Prelude: div :: Integral a => a -> a -> a
+ HaskellCI.Prelude: divMod :: Integral a => a -> a -> (a, a)
+ HaskellCI.Prelude: drop :: () => Int -> [a] -> [a]
+ HaskellCI.Prelude: dropWhile :: () => (a -> Bool) -> [a] -> [a]
+ HaskellCI.Prelude: either :: () => (a -> c) -> (b -> c) -> Either a b -> c
+ HaskellCI.Prelude: elem :: (Foldable t, Eq a) => a -> t a -> Bool
+ HaskellCI.Prelude: encodeFloat :: RealFloat a => Integer -> Int -> a
+ HaskellCI.Prelude: enumFrom :: Enum a => a -> [a]
+ HaskellCI.Prelude: enumFromThen :: Enum a => a -> a -> [a]
+ HaskellCI.Prelude: enumFromThenTo :: Enum a => a -> a -> a -> [a]
+ HaskellCI.Prelude: enumFromTo :: Enum a => a -> a -> [a]
+ HaskellCI.Prelude: equivVersionRanges :: VersionRange -> VersionRange -> Bool
+ HaskellCI.Prelude: error :: HasCallStack => [Char] -> a
+ HaskellCI.Prelude: errorWithoutStackTrace :: () => [Char] -> a
+ HaskellCI.Prelude: even :: Integral a => a -> Bool
+ HaskellCI.Prelude: exp :: Floating a => a -> a
+ HaskellCI.Prelude: exponent :: RealFloat a => a -> Int
+ HaskellCI.Prelude: fail :: Monad m => String -> m a
+ HaskellCI.Prelude: filter :: () => (a -> Bool) -> [a] -> [a]
+ HaskellCI.Prelude: findMaybe :: (a -> Maybe b) -> [a] -> Maybe b
+ HaskellCI.Prelude: first :: Bifunctor p => (a -> b) -> p a c -> p b c
+ HaskellCI.Prelude: flip :: () => (a -> b -> c) -> b -> a -> c
+ HaskellCI.Prelude: floatDigits :: RealFloat a => a -> Int
+ HaskellCI.Prelude: floatRadix :: RealFloat a => a -> Integer
+ HaskellCI.Prelude: floatRange :: RealFloat a => a -> (Int, Int)
+ HaskellCI.Prelude: floor :: (RealFrac a, Integral b) => a -> b
+ HaskellCI.Prelude: fmap :: Functor f => (a -> b) -> f a -> f b
+ HaskellCI.Prelude: foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
+ HaskellCI.Prelude: foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
+ HaskellCI.Prelude: foldl' :: Foldable t => (b -> a -> b) -> b -> t a -> b
+ HaskellCI.Prelude: foldl1 :: Foldable t => (a -> a -> a) -> t a -> a
+ HaskellCI.Prelude: foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
+ HaskellCI.Prelude: foldr1 :: Foldable t => (a -> a -> a) -> t a -> a
+ HaskellCI.Prelude: for_ :: (Foldable t, Applicative f) => t a -> (a -> f b) -> f ()
+ HaskellCI.Prelude: fromEnum :: Enum a => a -> Int
+ HaskellCI.Prelude: fromException :: Exception e => SomeException -> Maybe e
+ HaskellCI.Prelude: fromInteger :: Num a => Integer -> a
+ HaskellCI.Prelude: fromIntegral :: (Integral a, Num b) => a -> b
+ HaskellCI.Prelude: fromMaybe :: () => a -> Maybe a -> a
+ HaskellCI.Prelude: fromRational :: Fractional a => Rational -> a
+ HaskellCI.Prelude: fromString :: IsString a => String -> a
+ HaskellCI.Prelude: fst :: () => (a, b) -> a
+ HaskellCI.Prelude: gcd :: Integral a => a -> a -> a
+ HaskellCI.Prelude: getChar :: IO Char
+ HaskellCI.Prelude: getContents :: IO String
+ HaskellCI.Prelude: getLine :: IO String
+ HaskellCI.Prelude: groupBy :: Foldable f => (a -> a -> Bool) -> f a -> [NonEmpty a]
+ HaskellCI.Prelude: head :: NonEmpty a -> a
+ HaskellCI.Prelude: id :: () => a -> a
+ HaskellCI.Prelude: infix 4 `notElem`
+ HaskellCI.Prelude: infixl 0 `on`
+ HaskellCI.Prelude: infixl 1 <&>
+ HaskellCI.Prelude: infixl 3 <|>
+ HaskellCI.Prelude: infixl 4 <$>
+ HaskellCI.Prelude: infixl 6 +
+ HaskellCI.Prelude: infixl 7 *
+ HaskellCI.Prelude: infixl 8 ^.
+ HaskellCI.Prelude: infixl 9 !!
+ HaskellCI.Prelude: infixr 0 $!
+ HaskellCI.Prelude: infixr 1 =<<
+ HaskellCI.Prelude: infixr 2 ||
+ HaskellCI.Prelude: infixr 3 &&
+ HaskellCI.Prelude: infixr 4 .~
+ HaskellCI.Prelude: infixr 5 \/
+ HaskellCI.Prelude: infixr 6 /\
+ HaskellCI.Prelude: infixr 8 ^^
+ HaskellCI.Prelude: infixr 9 .
+ HaskellCI.Prelude: init :: () => [a] -> [a]
+ HaskellCI.Prelude: instance Algebra.Lattice.Lattice Distribution.Types.VersionRange.Internal.VersionRange
+ HaskellCI.Prelude: interact :: (String -> String) -> IO ()
+ HaskellCI.Prelude: intercalate :: () => [a] -> [[a]] -> [a]
+ HaskellCI.Prelude: ioError :: () => IOError -> IO a
+ HaskellCI.Prelude: isDenormalized :: RealFloat a => a -> Bool
+ HaskellCI.Prelude: isIEEE :: RealFloat a => a -> Bool
+ HaskellCI.Prelude: isInfinite :: RealFloat a => a -> Bool
+ HaskellCI.Prelude: isJust :: () => Maybe a -> Bool
+ HaskellCI.Prelude: isNaN :: RealFloat a => a -> Bool
+ HaskellCI.Prelude: isNegativeZero :: RealFloat a => a -> Bool
+ HaskellCI.Prelude: isNothing :: () => Maybe a -> Bool
+ HaskellCI.Prelude: isPrefixOf :: Eq a => [a] -> [a] -> Bool
+ HaskellCI.Prelude: isSpace :: Char -> Bool
+ HaskellCI.Prelude: isUpper :: Char -> Bool
+ HaskellCI.Prelude: iterate :: () => (a -> a) -> a -> [a]
+ HaskellCI.Prelude: last :: () => [a] -> a
+ HaskellCI.Prelude: lcm :: Integral a => a -> a -> a
+ HaskellCI.Prelude: length :: Foldable t => t a -> Int
+ HaskellCI.Prelude: lex :: ReadS String
+ HaskellCI.Prelude: liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
+ HaskellCI.Prelude: liftIO :: MonadIO m => IO a -> m a
+ HaskellCI.Prelude: lines :: String -> [String]
+ HaskellCI.Prelude: log :: Floating a => a -> a
+ HaskellCI.Prelude: logBase :: Floating a => a -> a -> a
+ HaskellCI.Prelude: lookup :: Eq a => a -> [(a, b)] -> Maybe b
+ HaskellCI.Prelude: map :: () => (a -> b) -> [a] -> [b]
+ HaskellCI.Prelude: mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
+ HaskellCI.Prelude: mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
+ HaskellCI.Prelude: mapMaybe :: () => (a -> Maybe b) -> [a] -> [b]
+ HaskellCI.Prelude: mapped :: Functor f => ASetter (f a) (f b) a b
+ HaskellCI.Prelude: mappend :: Monoid a => a -> a -> a
+ HaskellCI.Prelude: max :: Ord a => a -> a -> a
+ HaskellCI.Prelude: maxBound :: Bounded a => a
+ HaskellCI.Prelude: maximum :: (Foldable t, Ord a) => t a -> a
+ HaskellCI.Prelude: maybe :: () => b -> (a -> b) -> Maybe a -> b
+ HaskellCI.Prelude: mconcat :: Monoid a => [a] -> a
+ HaskellCI.Prelude: mempty :: Monoid a => a
+ HaskellCI.Prelude: min :: Ord a => a -> a -> a
+ HaskellCI.Prelude: minBound :: Bounded a => a
+ HaskellCI.Prelude: minimum :: (Foldable t, Ord a) => t a -> a
+ HaskellCI.Prelude: mkVersion :: [Int] -> Version
+ HaskellCI.Prelude: mod :: Integral a => a -> a -> a
+ HaskellCI.Prelude: negate :: Num a => a -> a
+ HaskellCI.Prelude: newtype Identity a
+ HaskellCI.Prelude: noVersion :: VersionRange
+ HaskellCI.Prelude: not :: Bool -> Bool
+ HaskellCI.Prelude: notElem :: (Foldable t, Eq a) => a -> t a -> Bool
+ HaskellCI.Prelude: nub :: Eq a => [a] -> [a]
+ HaskellCI.Prelude: null :: Foldable t => t a -> Bool
+ HaskellCI.Prelude: odd :: Integral a => a -> Bool
+ HaskellCI.Prelude: on :: () => (b -> b -> c) -> (a -> b) -> a -> a -> c
+ HaskellCI.Prelude: or :: Foldable t => t Bool -> Bool
+ HaskellCI.Prelude: otherwise :: Bool
+ HaskellCI.Prelude: over :: () => ASetter s t a b -> (a -> b) -> s -> t
+ HaskellCI.Prelude: pi :: Floating a => a
+ HaskellCI.Prelude: pred :: Enum a => a -> a
+ HaskellCI.Prelude: print :: Show a => a -> IO ()
+ HaskellCI.Prelude: product :: (Foldable t, Num a) => t a -> a
+ HaskellCI.Prelude: properFraction :: (RealFrac a, Integral b) => a -> (b, a)
+ HaskellCI.Prelude: pure :: Applicative f => a -> f a
+ HaskellCI.Prelude: putChar :: Char -> IO ()
+ HaskellCI.Prelude: putStr :: String -> IO ()
+ HaskellCI.Prelude: putStrLn :: String -> IO ()
+ HaskellCI.Prelude: quot :: Integral a => a -> a -> a
+ HaskellCI.Prelude: quotRem :: Integral a => a -> a -> (a, a)
+ HaskellCI.Prelude: read :: Read a => String -> a
+ HaskellCI.Prelude: readFile :: FilePath -> IO String
+ HaskellCI.Prelude: readIO :: Read a => String -> IO a
+ HaskellCI.Prelude: readList :: Read a => ReadS [a]
+ HaskellCI.Prelude: readLn :: Read a => IO a
+ HaskellCI.Prelude: readMaybe :: Read a => String -> Maybe a
+ HaskellCI.Prelude: readParen :: () => Bool -> ReadS a -> ReadS a
+ HaskellCI.Prelude: reads :: Read a => ReadS a
+ HaskellCI.Prelude: readsPrec :: Read a => Int -> ReadS a
+ HaskellCI.Prelude: realToFrac :: (Real a, Fractional b) => a -> b
+ HaskellCI.Prelude: recip :: Fractional a => a -> a
+ HaskellCI.Prelude: rem :: Integral a => a -> a -> a
+ HaskellCI.Prelude: repeat :: () => a -> [a]
+ HaskellCI.Prelude: replicate :: () => Int -> a -> [a]
+ HaskellCI.Prelude: return :: Monad m => a -> m a
+ HaskellCI.Prelude: reverse :: () => [a] -> [a]
+ HaskellCI.Prelude: round :: (RealFrac a, Integral b) => a -> b
+ HaskellCI.Prelude: scaleFloat :: RealFloat a => Int -> a -> a
+ HaskellCI.Prelude: scanl :: () => (b -> a -> b) -> b -> [a] -> [b]
+ HaskellCI.Prelude: scanl1 :: () => (a -> a -> a) -> [a] -> [a]
+ HaskellCI.Prelude: scanr :: () => (a -> b -> b) -> b -> [a] -> [b]
+ HaskellCI.Prelude: scanr1 :: () => (a -> a -> a) -> [a] -> [a]
+ HaskellCI.Prelude: second :: Bifunctor p => (b -> c) -> p a b -> p a c
+ HaskellCI.Prelude: seq :: () => a -> b -> b
+ HaskellCI.Prelude: sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
+ HaskellCI.Prelude: sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
+ HaskellCI.Prelude: sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
+ HaskellCI.Prelude: show :: Show a => a -> String
+ HaskellCI.Prelude: showChar :: Char -> ShowS
+ HaskellCI.Prelude: showList :: Show a => [a] -> ShowS
+ HaskellCI.Prelude: showParen :: Bool -> ShowS -> ShowS
+ HaskellCI.Prelude: showString :: String -> ShowS
+ HaskellCI.Prelude: shows :: Show a => a -> ShowS
+ HaskellCI.Prelude: showsPrec :: Show a => Int -> a -> ShowS
+ HaskellCI.Prelude: significand :: RealFloat a => a -> a
+ HaskellCI.Prelude: signum :: Num a => a -> a
+ HaskellCI.Prelude: sin :: Floating a => a -> a
+ HaskellCI.Prelude: sinh :: Floating a => a -> a
+ HaskellCI.Prelude: snd :: () => (a, b) -> b
+ HaskellCI.Prelude: span :: () => (a -> Bool) -> [a] -> ([a], [a])
+ HaskellCI.Prelude: splitAt :: () => Int -> [a] -> ([a], [a])
+ HaskellCI.Prelude: sqrt :: Floating a => a -> a
+ HaskellCI.Prelude: stripPrefix :: Eq a => [a] -> [a] -> Maybe [a]
+ HaskellCI.Prelude: subtract :: Num a => a -> a -> a
+ HaskellCI.Prelude: succ :: Enum a => a -> a
+ HaskellCI.Prelude: sum :: (Foldable t, Num a) => t a -> a
+ HaskellCI.Prelude: tails :: () => [a] -> [[a]]
+ HaskellCI.Prelude: take :: () => Int -> [a] -> [a]
+ HaskellCI.Prelude: takeWhile :: () => (a -> Bool) -> [a] -> [a]
+ HaskellCI.Prelude: tan :: Floating a => a -> a
+ HaskellCI.Prelude: tanh :: Floating a => a -> a
+ HaskellCI.Prelude: toEnum :: Enum a => Int -> a
+ HaskellCI.Prelude: toException :: Exception e => e -> SomeException
+ HaskellCI.Prelude: toInteger :: Integral a => a -> Integer
+ HaskellCI.Prelude: toList :: Foldable t => t a -> [a]
+ HaskellCI.Prelude: toLower :: Char -> Char
+ HaskellCI.Prelude: toRational :: Real a => a -> Rational
+ HaskellCI.Prelude: top :: BoundedMeetSemiLattice a => a
+ HaskellCI.Prelude: traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
+ HaskellCI.Prelude: traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()
+ HaskellCI.Prelude: truncate :: (RealFrac a, Integral b) => a -> b
+ HaskellCI.Prelude: type BoundedLattice a = (BoundedMeetSemiLattice a, BoundedJoinSemiLattice a)
+ HaskellCI.Prelude: type FilePath = String
+ HaskellCI.Prelude: type IOError = IOException
+ HaskellCI.Prelude: type Rational = Ratio Integer
+ HaskellCI.Prelude: type ReadS a = String -> [(a, String)]
+ HaskellCI.Prelude: type ShowS = String -> String
+ HaskellCI.Prelude: type String = [Char]
+ HaskellCI.Prelude: uncurry :: () => (a -> b -> c) -> (a, b) -> c
+ HaskellCI.Prelude: undefined :: HasCallStack => a
+ HaskellCI.Prelude: unless :: Applicative f => Bool -> f () -> f ()
+ HaskellCI.Prelude: unlines :: [String] -> String
+ HaskellCI.Prelude: until :: () => (a -> Bool) -> (a -> a) -> a -> a
+ HaskellCI.Prelude: unwords :: [String] -> String
+ HaskellCI.Prelude: unzip :: () => [(a, b)] -> ([a], [b])
+ HaskellCI.Prelude: unzip3 :: () => [(a, b, c)] -> ([a], [b], [c])
+ HaskellCI.Prelude: userError :: String -> IOError
+ HaskellCI.Prelude: void :: Functor f => f a -> f ()
+ HaskellCI.Prelude: when :: Applicative f => Bool -> f () -> f ()
+ HaskellCI.Prelude: words :: String -> [String]
+ HaskellCI.Prelude: writeFile :: FilePath -> String -> IO ()
+ HaskellCI.Prelude: zip :: () => [a] -> [b] -> [(a, b)]
+ HaskellCI.Prelude: zip3 :: () => [a] -> [b] -> [c] -> [(a, b, c)]
+ HaskellCI.Prelude: zipWith :: () => (a -> b -> c) -> [a] -> [b] -> [c]
+ HaskellCI.Prelude: zipWith3 :: () => (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
+ HaskellCI.Project: [prjOptPackages] :: Project b a -> [b]
+ HaskellCI.Project: instance Data.Bifoldable.Bifoldable HaskellCI.Project.Project
+ HaskellCI.Project: instance Data.Bifunctor.Bifunctor HaskellCI.Project.Project
+ HaskellCI.Project: instance Data.Bitraversable.Bitraversable HaskellCI.Project.Project
+ HaskellCI.Project: instance Data.Foldable.Foldable (HaskellCI.Project.Project b)
+ HaskellCI.Project: instance Data.Traversable.Traversable (HaskellCI.Project.Project b)
+ HaskellCI.Project: instance GHC.Base.Functor (HaskellCI.Project.Project b)
+ HaskellCI.Project: instance GHC.Generics.Generic (HaskellCI.Project.Project b a)
+ HaskellCI.Sh: Comment :: String -> Sh
+ HaskellCI.Sh: Sh :: String -> Sh
+ HaskellCI.Sh: ShError :: String -> ShError
+ HaskellCI.Sh: ShM :: (([Sh] -> [Sh]) -> Either ShError ([Sh] -> [Sh], a)) -> ShM a
+ HaskellCI.Sh: ShellCheckError :: String -> ShError
+ HaskellCI.Sh: [unShM] :: ShM a -> ([Sh] -> [Sh]) -> Either ShError ([Sh] -> [Sh], a)
+ HaskellCI.Sh: class FromShError e
+ HaskellCI.Sh: class Monad m => MonadSh m
+ HaskellCI.Sh: comment :: MonadSh m => String -> m ()
+ HaskellCI.Sh: commentedBlock :: MonadSh m => String -> m () -> m ()
+ HaskellCI.Sh: data Sh
+ HaskellCI.Sh: data ShError
+ HaskellCI.Sh: fromShError :: FromShError e => ShError -> e
+ HaskellCI.Sh: instance Control.Monad.Fail.MonadFail HaskellCI.Sh.ShM
+ HaskellCI.Sh: instance GHC.Base.Applicative HaskellCI.Sh.ShM
+ HaskellCI.Sh: instance GHC.Base.Functor HaskellCI.Sh.ShM
+ HaskellCI.Sh: instance GHC.Base.Monad HaskellCI.Sh.ShM
+ HaskellCI.Sh: instance GHC.Exception.Type.Exception HaskellCI.Sh.ShError
+ HaskellCI.Sh: instance GHC.Show.Show HaskellCI.Sh.Sh
+ HaskellCI.Sh: instance GHC.Show.Show HaskellCI.Sh.ShError
+ HaskellCI.Sh: instance HaskellCI.MonadErr.MonadErr HaskellCI.Sh.ShError HaskellCI.Sh.ShM
+ HaskellCI.Sh: instance HaskellCI.Sh.FromShError HaskellCI.Sh.ShError
+ HaskellCI.Sh: instance HaskellCI.Sh.MonadSh HaskellCI.Sh.ShM
+ HaskellCI.Sh: isComment :: Sh -> Bool
+ HaskellCI.Sh: newtype ShM a
+ HaskellCI.Sh: runSh :: (MonadErr e m, FromShError e) => ShM () -> m [Sh]
+ HaskellCI.Sh: sh :: MonadSh m => String -> m ()
+ HaskellCI.Sh: sh' :: MonadSh m => [Integer] -> String -> m ()
+ HaskellCI.ShVersionRange: compilerVersionPredicate :: Set CompilerVersion -> CompilerRange -> String
+ HaskellCI.ShVersionRange: instance GHC.Show.Show a => GHC.Show.Show (HaskellCI.ShVersionRange.R a)
+ HaskellCI.TestedWith: instance Distribution.Parsec.Parsec HaskellCI.TestedWith.TestedWithJobs
+ HaskellCI.Tools: doctestArgs :: GenericPackageDescription -> [[String]]
+ HaskellCI.Tools: doctestJobVersionRange :: CompilerRange
+ HaskellCI.Tools: hlintArgs :: GenericPackageDescription -> [[String]]
+ HaskellCI.Tools: hlintJobVersionRange :: Set CompilerVersion -> VersionRange -> HLintJob -> CompilerRange
+ HaskellCI.Travis: makeTravis :: [String] -> Config -> Project Void Package -> JobVersions -> Either ShError Travis
+ HaskellCI.Travis: travisHeader :: Bool -> [String] -> [String]
+ HaskellCI.Travis.Yaml: (^^^) :: ([String], String, Yaml [String]) -> String -> ([String], String, Yaml [String])
+ HaskellCI.Travis.Yaml: (~>) :: String -> Yaml [String] -> ([String], String, Yaml [String])
+ HaskellCI.Travis.Yaml: Travis :: !Ubuntu -> !String -> !TravisGit -> !TravisCache -> !TravisBranches -> !TravisNotifications -> ![String] -> !TravisAddons -> !TravisMatrix -> ![Sh] -> ![Sh] -> ![Sh] -> ![Sh] -> Travis
+ HaskellCI.Travis.Yaml: TravisAddons :: TravisApt -> Maybe String -> TravisAddons
+ HaskellCI.Travis.Yaml: TravisAllowFailure :: String -> TravisAllowFailure
+ HaskellCI.Travis.Yaml: TravisApt :: [String] -> [String] -> TravisApt
+ HaskellCI.Travis.Yaml: TravisBranches :: [String] -> TravisBranches
+ HaskellCI.Travis.Yaml: TravisCache :: [FilePath] -> TravisCache
+ HaskellCI.Travis.Yaml: TravisGit :: Bool -> TravisGit
+ HaskellCI.Travis.Yaml: TravisIRC :: [String] -> Bool -> [String] -> TravisIRC
+ HaskellCI.Travis.Yaml: TravisJob :: String -> Maybe String -> TravisAddons -> String -> TravisJob
+ HaskellCI.Travis.Yaml: TravisMatrix :: [TravisJob] -> [TravisAllowFailure] -> TravisMatrix
+ HaskellCI.Travis.Yaml: TravisNotifications :: Maybe TravisIRC -> TravisNotifications
+ HaskellCI.Travis.Yaml: [taApt] :: TravisAddons -> TravisApt
+ HaskellCI.Travis.Yaml: [taPackages] :: TravisApt -> [String]
+ HaskellCI.Travis.Yaml: [taPostgres] :: TravisAddons -> Maybe String
+ HaskellCI.Travis.Yaml: [taSources] :: TravisApt -> [String]
+ HaskellCI.Travis.Yaml: [tafCompiler] :: TravisAllowFailure -> String
+ HaskellCI.Travis.Yaml: [tbOnly] :: TravisBranches -> [String]
+ HaskellCI.Travis.Yaml: [tcDirectories] :: TravisCache -> [FilePath]
+ HaskellCI.Travis.Yaml: [tgSubmodules] :: TravisGit -> Bool
+ HaskellCI.Travis.Yaml: [tiChannels] :: TravisIRC -> [String]
+ HaskellCI.Travis.Yaml: [tiSkipJoin] :: TravisIRC -> Bool
+ HaskellCI.Travis.Yaml: [tiTemplate] :: TravisIRC -> [String]
+ HaskellCI.Travis.Yaml: [tjAddons] :: TravisJob -> TravisAddons
+ HaskellCI.Travis.Yaml: [tjCompiler] :: TravisJob -> String
+ HaskellCI.Travis.Yaml: [tjEnv] :: TravisJob -> Maybe String
+ HaskellCI.Travis.Yaml: [tjOS] :: TravisJob -> String
+ HaskellCI.Travis.Yaml: [tmAllowFailures] :: TravisMatrix -> [TravisAllowFailure]
+ HaskellCI.Travis.Yaml: [tmInclude] :: TravisMatrix -> [TravisJob]
+ HaskellCI.Travis.Yaml: [tnIRC] :: TravisNotifications -> Maybe TravisIRC
+ HaskellCI.Travis.Yaml: [travisAddons] :: Travis -> !TravisAddons
+ HaskellCI.Travis.Yaml: [travisBeforeCache] :: Travis -> ![Sh]
+ HaskellCI.Travis.Yaml: [travisBeforeInstall] :: Travis -> ![Sh]
+ HaskellCI.Travis.Yaml: [travisBranches] :: Travis -> !TravisBranches
+ HaskellCI.Travis.Yaml: [travisCache] :: Travis -> !TravisCache
+ HaskellCI.Travis.Yaml: [travisGit] :: Travis -> !TravisGit
+ HaskellCI.Travis.Yaml: [travisInstall] :: Travis -> ![Sh]
+ HaskellCI.Travis.Yaml: [travisLanguage] :: Travis -> !String
+ HaskellCI.Travis.Yaml: [travisMatrix] :: Travis -> !TravisMatrix
+ HaskellCI.Travis.Yaml: [travisNotifications] :: Travis -> !TravisNotifications
+ HaskellCI.Travis.Yaml: [travisScript] :: Travis -> ![Sh]
+ HaskellCI.Travis.Yaml: [travisServices] :: Travis -> ![String]
+ HaskellCI.Travis.Yaml: [travisUbuntu] :: Travis -> !Ubuntu
+ HaskellCI.Travis.Yaml: data Travis
+ HaskellCI.Travis.Yaml: data TravisAddons
+ HaskellCI.Travis.Yaml: data TravisApt
+ HaskellCI.Travis.Yaml: data TravisIRC
+ HaskellCI.Travis.Yaml: data TravisJob
+ HaskellCI.Travis.Yaml: data TravisMatrix
+ HaskellCI.Travis.Yaml: instance Data.Aeson.Types.ToJSON.ToJSON HaskellCI.Travis.Yaml.TravisAddons
+ HaskellCI.Travis.Yaml: instance Data.Aeson.Types.ToJSON.ToJSON HaskellCI.Travis.Yaml.TravisApt
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.Travis
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.TravisAddons
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.TravisAllowFailure
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.TravisApt
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.TravisBranches
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.TravisCache
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.TravisGit
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.TravisIRC
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.TravisJob
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.TravisMatrix
+ HaskellCI.Travis.Yaml: instance GHC.Show.Show HaskellCI.Travis.Yaml.TravisNotifications
+ HaskellCI.Travis.Yaml: instance HaskellCI.YamlSyntax.ToYaml HaskellCI.Travis.Yaml.Travis
+ HaskellCI.Travis.Yaml: instance HaskellCI.YamlSyntax.ToYaml HaskellCI.Travis.Yaml.TravisAddons
+ HaskellCI.Travis.Yaml: instance HaskellCI.YamlSyntax.ToYaml HaskellCI.Travis.Yaml.TravisAllowFailure
+ HaskellCI.Travis.Yaml: instance HaskellCI.YamlSyntax.ToYaml HaskellCI.Travis.Yaml.TravisBranches
+ HaskellCI.Travis.Yaml: instance HaskellCI.YamlSyntax.ToYaml HaskellCI.Travis.Yaml.TravisCache
+ HaskellCI.Travis.Yaml: instance HaskellCI.YamlSyntax.ToYaml HaskellCI.Travis.Yaml.TravisGit
+ HaskellCI.Travis.Yaml: instance HaskellCI.YamlSyntax.ToYaml HaskellCI.Travis.Yaml.TravisIRC
+ HaskellCI.Travis.Yaml: instance HaskellCI.YamlSyntax.ToYaml HaskellCI.Travis.Yaml.TravisJob
+ HaskellCI.Travis.Yaml: instance HaskellCI.YamlSyntax.ToYaml HaskellCI.Travis.Yaml.TravisMatrix
+ HaskellCI.Travis.Yaml: instance HaskellCI.YamlSyntax.ToYaml HaskellCI.Travis.Yaml.TravisNotifications
+ HaskellCI.Travis.Yaml: isEmpty :: Yaml ann -> Bool
+ HaskellCI.Travis.Yaml: newtype TravisAllowFailure
+ HaskellCI.Travis.Yaml: newtype TravisBranches
+ HaskellCI.Travis.Yaml: newtype TravisCache
+ HaskellCI.Travis.Yaml: newtype TravisGit
+ HaskellCI.Travis.Yaml: newtype TravisNotifications
+ HaskellCI.Travis.Yaml: shListToYaml :: [Sh] -> Yaml [String]
+ HaskellCI.Travis.Yaml: ykeyValuesFilt :: ann -> [(ann, String, Yaml ann)] -> Yaml ann
+ HaskellCI.Travis.Yaml: ylistFilt :: ann -> [Yaml ann] -> Yaml ann
+ HaskellCI.YamlSyntax: YBool :: ann -> Bool -> Yaml ann
+ HaskellCI.YamlSyntax: YKeyValues :: ann -> [(ann, String, Yaml ann)] -> Yaml ann
+ HaskellCI.YamlSyntax: YList :: ann -> [Yaml ann] -> Yaml ann
+ HaskellCI.YamlSyntax: YString :: ann -> String -> Yaml ann
+ HaskellCI.YamlSyntax: YValue :: ann -> Value -> Yaml ann
+ HaskellCI.YamlSyntax: class ToYaml a
+ HaskellCI.YamlSyntax: data Yaml ann
+ HaskellCI.YamlSyntax: instance (ann Data.Type.Equality.~ [GHC.Base.String]) => HaskellCI.YamlSyntax.ToYaml (HaskellCI.YamlSyntax.Yaml ann)
+ HaskellCI.YamlSyntax: instance Data.Foldable.Foldable HaskellCI.YamlSyntax.Yaml
+ HaskellCI.YamlSyntax: instance Data.Traversable.Traversable HaskellCI.YamlSyntax.Yaml
+ HaskellCI.YamlSyntax: instance GHC.Base.Functor HaskellCI.YamlSyntax.Yaml
+ HaskellCI.YamlSyntax: instance GHC.Base.Monoid ann => Data.String.IsString (HaskellCI.YamlSyntax.Yaml ann)
+ HaskellCI.YamlSyntax: instance GHC.Classes.Eq ann => GHC.Classes.Eq (HaskellCI.YamlSyntax.Yaml ann)
+ HaskellCI.YamlSyntax: instance GHC.Show.Show ann => GHC.Show.Show (HaskellCI.YamlSyntax.Yaml ann)
+ HaskellCI.YamlSyntax: instance HaskellCI.YamlSyntax.ToYaml Data.Aeson.Types.Internal.Value
+ HaskellCI.YamlSyntax: instance HaskellCI.YamlSyntax.ToYaml GHC.Types.Bool
+ HaskellCI.YamlSyntax: instance HaskellCI.YamlSyntax.ToYaml a => HaskellCI.YamlSyntax.ToYaml [a]
+ HaskellCI.YamlSyntax: prettyYaml :: forall ann. (ann -> [String]) -> Yaml ann -> String
+ HaskellCI.YamlSyntax: reann :: (ann -> ann) -> Yaml ann -> Yaml ann
+ HaskellCI.YamlSyntax: toYaml :: ToYaml a => a -> Yaml [String]
- HaskellCI: Options :: [String] -> Maybe FilePath -> Maybe FilePath -> (Config -> Config) -> Options
+ HaskellCI: Options :: Maybe Output -> Maybe FilePath -> (Config -> Config) -> Options
- HaskellCI: [optOutput] :: Options -> Maybe FilePath
+ HaskellCI: [optOutput] :: Options -> Maybe Output
- HaskellCI: travisFromConfigFile :: MonadIO m => [String] -> Options -> FilePath -> YamlWriter m ()
+ HaskellCI: travisFromConfigFile :: forall m. (MonadIO m, MonadDiagnostics m, MonadMask m) => [String] -> Options -> FilePath -> m [String]
- HaskellCI.Cli: Options :: [String] -> Maybe FilePath -> Maybe FilePath -> (Config -> Config) -> Options
+ HaskellCI.Cli: Options :: Maybe Output -> Maybe FilePath -> (Config -> Config) -> Options
- HaskellCI.Cli: [optOutput] :: Options -> Maybe FilePath
+ HaskellCI.Cli: [optOutput] :: Options -> Maybe Output
- HaskellCI.Config: Config :: Maybe Version -> Maybe Jobs -> !TestedWithJobs -> !CopyFields -> [String] -> !Bool -> !Bool -> !Bool -> [Installed] -> !VersionRange -> !VersionRange -> !VersionRange -> !VersionRange -> !VersionRange -> !Bool -> [String] -> [String] -> Maybe String -> Set Fold -> !Bool -> !Bool -> Map Version String -> !VersionRange -> !Bool -> Set Version -> Set String -> !DoctestConfig -> !HLintConfig -> [ConstraintSet] -> [PrettyField] -> Config
+ HaskellCI.Config: Config :: Maybe Version -> Maybe Jobs -> !Ubuntu -> !TestedWithJobs -> !CopyFields -> [String] -> !Bool -> !Bool -> !Bool -> [Installed] -> !VersionRange -> !VersionRange -> !VersionRange -> !VersionRange -> !VersionRange -> !VersionRange -> !VersionRange -> !Bool -> !Bool -> [String] -> [String] -> Maybe String -> Set Fold -> !Bool -> !Bool -> Map Version String -> !VersionRange -> !Bool -> Set Version -> Set String -> [FilePath] -> !Bool -> !Bool -> !DoctestConfig -> !HLintConfig -> [ConstraintSet] -> [PrettyField ()] -> Config
- HaskellCI.Config: [cfgRawProject] :: Config -> [PrettyField]
+ HaskellCI.Config: [cfgRawProject] :: Config -> [PrettyField ()]
- HaskellCI.Config.ConstraintSet: ConstraintSet :: String -> VersionRange -> [String] -> Bool -> ConstraintSet
+ HaskellCI.Config.ConstraintSet: ConstraintSet :: String -> VersionRange -> [String] -> Bool -> Bool -> Bool -> Bool -> ConstraintSet
- HaskellCI.Config.Doctest: DoctestConfig :: !Bool -> [String] -> !VersionRange -> DoctestConfig
+ HaskellCI.Config.Doctest: DoctestConfig :: !VersionRange -> [String] -> !VersionRange -> ![PackageName] -> DoctestConfig
- HaskellCI.Config.Doctest: [cfgDoctestEnabled] :: DoctestConfig -> !Bool
+ HaskellCI.Config.Doctest: [cfgDoctestEnabled] :: DoctestConfig -> !VersionRange
- HaskellCI.Glob: parseFilePathGlobRel :: ReadP r FilePathGlobRel
+ HaskellCI.Glob: parseFilePathGlobRel :: ReadP FilePathGlobRel
- HaskellCI.Glob: parseGlob :: ReadP r Glob
+ HaskellCI.Glob: parseGlob :: ReadP Glob
- HaskellCI.Package: Pkg :: String -> VersionRange -> FilePath -> GenericPackageDescription -> Package
+ HaskellCI.Package: Pkg :: String -> Set CompilerVersion -> FilePath -> GenericPackageDescription -> Package
- HaskellCI.Package: [pkgJobs] :: Package -> VersionRange
+ HaskellCI.Package: [pkgJobs] :: Package -> Set CompilerVersion
- HaskellCI.Project: Project :: [a] -> [String] -> [String] -> Bool -> Maybe Int -> Optimization -> [SourceRepo] -> [PrettyField] -> Project a
+ HaskellCI.Project: Project :: [a] -> [b] -> [String] -> [String] -> Bool -> Maybe Int -> Optimization -> [SourceRepo] -> [PrettyField ()] -> Project b a
- HaskellCI.Project: [prjAllowNewer] :: Project a -> [String]
+ HaskellCI.Project: [prjAllowNewer] :: Project b a -> [String]
- HaskellCI.Project: [prjConstraints] :: Project a -> [String]
+ HaskellCI.Project: [prjConstraints] :: Project b a -> [String]
- HaskellCI.Project: [prjMaxBackjumps] :: Project a -> Maybe Int
+ HaskellCI.Project: [prjMaxBackjumps] :: Project b a -> Maybe Int
- HaskellCI.Project: [prjOptimization] :: Project a -> Optimization
+ HaskellCI.Project: [prjOptimization] :: Project b a -> Optimization
- HaskellCI.Project: [prjOrigFields] :: Project a -> [PrettyField]
+ HaskellCI.Project: [prjOrigFields] :: Project b a -> [PrettyField ()]
- HaskellCI.Project: [prjPackages] :: Project a -> [a]
+ HaskellCI.Project: [prjPackages] :: Project b a -> [a]
- HaskellCI.Project: [prjReorderGoals] :: Project a -> Bool
+ HaskellCI.Project: [prjReorderGoals] :: Project b a -> Bool
- HaskellCI.Project: [prjSourceRepos] :: Project a -> [SourceRepo]
+ HaskellCI.Project: [prjSourceRepos] :: Project b a -> [SourceRepo]
- HaskellCI.Project: data Project a
+ HaskellCI.Project: data Project b a
- HaskellCI.Project: emptyProject :: Project [a]
+ HaskellCI.Project: emptyProject :: Project b a
- HaskellCI.Project: parseProjectFile :: FilePath -> ByteString -> Either String (Project String)
+ HaskellCI.Project: parseProjectFile :: FilePath -> ByteString -> Either String (Project String String)
- HaskellCI.TestedWith: checkVersions :: TestedWithJobs -> Project (Package, Set Version) -> Either [String] (Set Version, Project Package)
+ HaskellCI.TestedWith: checkVersions :: TestedWithJobs -> Project Void Package -> Either [String] (Set CompilerVersion, Project Void Package)

Files

CHANGELOG.md view
@@ -1,3 +1,11 @@+## 0.4++* Make default `--output` to be `.travis.yml`; use `--stdout` to output to standard output.+* Add GHC-8.8 support+* Use cabal-install-3.0 by default+* Experimental support for GHCJS jobs+* A lot of new configuration options+ ## 0.2.1  * `local-ghc-options` are always applied (independent of `copy-fields` value)
LICENSE view
@@ -1,31 +1,674 @@-Copyright (c) 2017-2018, Herbert Valerio Riedel-              2017-2018, Oleg Grenrus+                    GNU GENERAL PUBLIC LICENSE+                       Version 3, 29 June 2007 -All rights reserved.+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed. -Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:+                            Preamble -    * Redistributions of source code must retain the above copyright-      notice, this list of conditions and the following disclaimer.+  The GNU General Public License is a free, copyleft license for+software and other kinds of works. -    * Redistributions in binary form must reproduce the above-      copyright notice, this list of conditions and the following-      disclaimer in the documentation and/or other materials provided-      with the distribution.+  The licenses for most software and other practical works are designed+to take away your freedom to share and change the works.  By contrast,+the GNU General Public License is intended to guarantee your freedom to+share and change all versions of a program--to make sure it remains free+software for all its users.  We, the Free Software Foundation, use the+GNU General Public License for most of our software; it applies also to+any other work released this way by its authors.  You can apply it to+your programs, too. -    * Neither the name of Herbert Valerio Riedel nor the names of other-      contributors may be used to endorse or promote products derived-      from this software without specific prior written permission.+  When we speak of free software, we are referring to freedom, not+price.  Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+them if you wish), that you receive source code or can get it if you+want it, that you can change the software or use pieces of it in new+free programs, and that you know you can do these things. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+  To protect your rights, we need to prevent others from denying you+these rights or asking you to surrender the rights.  Therefore, you have+certain responsibilities if you distribute copies of the software, or if+you modify it: responsibilities to respect the freedom of others.++  For example, if you distribute copies of such a program, whether+gratis or for a fee, you must pass on to the recipients the same+freedoms that you received.  You must make sure that they, too, receive+or can get the source code.  And you must show them these terms so they+know their rights.++  Developers that use the GNU GPL protect your rights with two steps:+(1) assert copyright on the software, and (2) offer you this License+giving you legal permission to copy, distribute and/or modify it.++  For the developers' and authors' protection, the GPL clearly explains+that there is no warranty for this free software.  For both users' and+authors' sake, the GPL requires that modified versions be marked as+changed, so that their problems will not be attributed erroneously to+authors of previous versions.++  Some devices are designed to deny users access to install or run+modified versions of the software inside them, although the manufacturer+can do so.  This is fundamentally incompatible with the aim of+protecting users' freedom to change the software.  The systematic+pattern of such abuse occurs in the area of products for individuals to+use, which is precisely where it is most unacceptable.  Therefore, we+have designed this version of the GPL to prohibit the practice for those+products.  If such problems arise substantially in other domains, we+stand ready to extend this provision to those domains in future versions+of the GPL, as needed to protect the freedom of users.++  Finally, every program is threatened constantly by software patents.+States should not allow patents to restrict development and use of+software on general-purpose computers, but in those that do, we wish to+avoid the special danger that patents applied to a free program could+make it effectively proprietary.  To prevent this, the GPL assures that+patents cannot be used to render the program non-free.++  The precise terms and conditions for copying, distribution and+modification follow.++                       TERMS AND CONDITIONS++  0. Definitions.++  "This License" refers to version 3 of the GNU General Public License.++  "Copyright" also means copyright-like laws that apply to other kinds of+works, such as semiconductor masks.++  "The Program" refers to any copyrightable work licensed under this+License.  Each licensee is addressed as "you".  "Licensees" and+"recipients" may be individuals or organizations.++  To "modify" a work means to copy from or adapt all or part of the work+in a fashion requiring copyright permission, other than the making of an+exact copy.  The resulting work is called a "modified version" of the+earlier work or a work "based on" the earlier work.++  A "covered work" means either the unmodified Program or a work based+on the Program.++  To "propagate" a work means to do anything with it that, without+permission, would make you directly or secondarily liable for+infringement under applicable copyright law, except executing it on a+computer or modifying a private copy.  Propagation includes copying,+distribution (with or without modification), making available to the+public, and in some countries other activities as well.++  To "convey" a work means any kind of propagation that enables other+parties to make or receive copies.  Mere interaction with a user through+a computer network, with no transfer of a copy, is not conveying.++  An interactive user interface displays "Appropriate Legal Notices"+to the extent that it includes a convenient and prominently visible+feature that (1) displays an appropriate copyright notice, and (2)+tells the user that there is no warranty for the work (except to the+extent that warranties are provided), that licensees may convey the+work under this License, and how to view a copy of this License.  If+the interface presents a list of user commands or options, such as a+menu, a prominent item in the list meets this criterion.++  1. Source Code.++  The "source code" for a work means the preferred form of the work+for making modifications to it.  "Object code" means any non-source+form of a work.++  A "Standard Interface" means an interface that either is an official+standard defined by a recognized standards body, or, in the case of+interfaces specified for a particular programming language, one that+is widely used among developers working in that language.++  The "System Libraries" of an executable work include anything, other+than the work as a whole, that (a) is included in the normal form of+packaging a Major Component, but which is not part of that Major+Component, and (b) serves only to enable use of the work with that+Major Component, or to implement a Standard Interface for which an+implementation is available to the public in source code form.  A+"Major Component", in this context, means a major essential component+(kernel, window system, and so on) of the specific operating system+(if any) on which the executable work runs, or a compiler used to+produce the work, or an object code interpreter used to run it.++  The "Corresponding Source" for a work in object code form means all+the source code needed to generate, install, and (for an executable+work) run the object code and to modify the work, including scripts to+control those activities.  However, it does not include the work's+System Libraries, or general-purpose tools or generally available free+programs which are used unmodified in performing those activities but+which are not part of the work.  For example, Corresponding Source+includes interface definition files associated with source files for+the work, and the source code for shared libraries and dynamically+linked subprograms that the work is specifically designed to require,+such as by intimate data communication or control flow between those+subprograms and other parts of the work.++  The Corresponding Source need not include anything that users+can regenerate automatically from other parts of the Corresponding+Source.++  The Corresponding Source for a work in source code form is that+same work.++  2. Basic Permissions.++  All rights granted under this License are granted for the term of+copyright on the Program, and are irrevocable provided the stated+conditions are met.  This License explicitly affirms your unlimited+permission to run the unmodified Program.  The output from running a+covered work is covered by this License only if the output, given its+content, constitutes a covered work.  This License acknowledges your+rights of fair use or other equivalent, as provided by copyright law.++  You may make, run and propagate covered works that you do not+convey, without conditions so long as your license otherwise remains+in force.  You may convey covered works to others for the sole purpose+of having them make modifications exclusively for you, or provide you+with facilities for running those works, provided that you comply with+the terms of this License in conveying all material for which you do+not control copyright.  Those thus making or running the covered works+for you must do so exclusively on your behalf, under your direction+and control, on terms that prohibit them from making any copies of+your copyrighted material outside their relationship with you.++  Conveying under any other circumstances is permitted solely under+the conditions stated below.  Sublicensing is not allowed; section 10+makes it unnecessary.++  3. Protecting Users' Legal Rights From Anti-Circumvention Law.++  No covered work shall be deemed part of an effective technological+measure under any applicable law fulfilling obligations under article+11 of the WIPO copyright treaty adopted on 20 December 1996, or+similar laws prohibiting or restricting circumvention of such+measures.++  When you convey a covered work, you waive any legal power to forbid+circumvention of technological measures to the extent such circumvention+is effected by exercising rights under this License with respect to+the covered work, and you disclaim any intention to limit operation or+modification of the work as a means of enforcing, against the work's+users, your or third parties' legal rights to forbid circumvention of+technological measures.++  4. Conveying Verbatim Copies.++  You may convey verbatim copies of the Program's source code as you+receive it, in any medium, provided that you conspicuously and+appropriately publish on each copy an appropriate copyright notice;+keep intact all notices stating that this License and any+non-permissive terms added in accord with section 7 apply to the code;+keep intact all notices of the absence of any warranty; and give all+recipients a copy of this License along with the Program.++  You may charge any price or no price for each copy that you convey,+and you may offer support or warranty protection for a fee.++  5. Conveying Modified Source Versions.++  You may convey a work based on the Program, or the modifications to+produce it from the Program, in the form of source code under the+terms of section 4, provided that you also meet all of these conditions:++    a) The work must carry prominent notices stating that you modified+    it, and giving a relevant date.++    b) The work must carry prominent notices stating that it is+    released under this License and any conditions added under section+    7.  This requirement modifies the requirement in section 4 to+    "keep intact all notices".++    c) You must license the entire work, as a whole, under this+    License to anyone who comes into possession of a copy.  This+    License will therefore apply, along with any applicable section 7+    additional terms, to the whole of the work, and all its parts,+    regardless of how they are packaged.  This License gives no+    permission to license the work in any other way, but it does not+    invalidate such permission if you have separately received it.++    d) If the work has interactive user interfaces, each must display+    Appropriate Legal Notices; however, if the Program has interactive+    interfaces that do not display Appropriate Legal Notices, your+    work need not make them do so.++  A compilation of a covered work with other separate and independent+works, which are not by their nature extensions of the covered work,+and which are not combined with it such as to form a larger program,+in or on a volume of a storage or distribution medium, is called an+"aggregate" if the compilation and its resulting copyright are not+used to limit the access or legal rights of the compilation's users+beyond what the individual works permit.  Inclusion of a covered work+in an aggregate does not cause this License to apply to the other+parts of the aggregate.++  6. Conveying Non-Source Forms.++  You may convey a covered work in object code form under the terms+of sections 4 and 5, provided that you also convey the+machine-readable Corresponding Source under the terms of this License,+in one of these ways:++    a) Convey the object code in, or embodied in, a physical product+    (including a physical distribution medium), accompanied by the+    Corresponding Source fixed on a durable physical medium+    customarily used for software interchange.++    b) Convey the object code in, or embodied in, a physical product+    (including a physical distribution medium), accompanied by a+    written offer, valid for at least three years and valid for as+    long as you offer spare parts or customer support for that product+    model, to give anyone who possesses the object code either (1) a+    copy of the Corresponding Source for all the software in the+    product that is covered by this License, on a durable physical+    medium customarily used for software interchange, for a price no+    more than your reasonable cost of physically performing this+    conveying of source, or (2) access to copy the+    Corresponding Source from a network server at no charge.++    c) Convey individual copies of the object code with a copy of the+    written offer to provide the Corresponding Source.  This+    alternative is allowed only occasionally and noncommercially, and+    only if you received the object code with such an offer, in accord+    with subsection 6b.++    d) Convey the object code by offering access from a designated+    place (gratis or for a charge), and offer equivalent access to the+    Corresponding Source in the same way through the same place at no+    further charge.  You need not require recipients to copy the+    Corresponding Source along with the object code.  If the place to+    copy the object code is a network server, the Corresponding Source+    may be on a different server (operated by you or a third party)+    that supports equivalent copying facilities, provided you maintain+    clear directions next to the object code saying where to find the+    Corresponding Source.  Regardless of what server hosts the+    Corresponding Source, you remain obligated to ensure that it is+    available for as long as needed to satisfy these requirements.++    e) Convey the object code using peer-to-peer transmission, provided+    you inform other peers where the object code and Corresponding+    Source of the work are being offered to the general public at no+    charge under subsection 6d.++  A separable portion of the object code, whose source code is excluded+from the Corresponding Source as a System Library, need not be+included in conveying the object code work.++  A "User Product" is either (1) a "consumer product", which means any+tangible personal property which is normally used for personal, family,+or household purposes, or (2) anything designed or sold for incorporation+into a dwelling.  In determining whether a product is a consumer product,+doubtful cases shall be resolved in favor of coverage.  For a particular+product received by a particular user, "normally used" refers to a+typical or common use of that class of product, regardless of the status+of the particular user or of the way in which the particular user+actually uses, or expects or is expected to use, the product.  A product+is a consumer product regardless of whether the product has substantial+commercial, industrial or non-consumer uses, unless such uses represent+the only significant mode of use of the product.++  "Installation Information" for a User Product means any methods,+procedures, authorization keys, or other information required to install+and execute modified versions of a covered work in that User Product from+a modified version of its Corresponding Source.  The information must+suffice to ensure that the continued functioning of the modified object+code is in no case prevented or interfered with solely because+modification has been made.++  If you convey an object code work under this section in, or with, or+specifically for use in, a User Product, and the conveying occurs as+part of a transaction in which the right of possession and use of the+User Product is transferred to the recipient in perpetuity or for a+fixed term (regardless of how the transaction is characterized), the+Corresponding Source conveyed under this section must be accompanied+by the Installation Information.  But this requirement does not apply+if neither you nor any third party retains the ability to install+modified object code on the User Product (for example, the work has+been installed in ROM).++  The requirement to provide Installation Information does not include a+requirement to continue to provide support service, warranty, or updates+for a work that has been modified or installed by the recipient, or for+the User Product in which it has been modified or installed.  Access to a+network may be denied when the modification itself materially and+adversely affects the operation of the network or violates the rules and+protocols for communication across the network.++  Corresponding Source conveyed, and Installation Information provided,+in accord with this section must be in a format that is publicly+documented (and with an implementation available to the public in+source code form), and must require no special password or key for+unpacking, reading or copying.++  7. Additional Terms.++  "Additional permissions" are terms that supplement the terms of this+License by making exceptions from one or more of its conditions.+Additional permissions that are applicable to the entire Program shall+be treated as though they were included in this License, to the extent+that they are valid under applicable law.  If additional permissions+apply only to part of the Program, that part may be used separately+under those permissions, but the entire Program remains governed by+this License without regard to the additional permissions.++  When you convey a copy of a covered work, you may at your option+remove any additional permissions from that copy, or from any part of+it.  (Additional permissions may be written to require their own+removal in certain cases when you modify the work.)  You may place+additional permissions on material, added by you to a covered work,+for which you have or can give appropriate copyright permission.++  Notwithstanding any other provision of this License, for material you+add to a covered work, you may (if authorized by the copyright holders of+that material) supplement the terms of this License with terms:++    a) Disclaiming warranty or limiting liability differently from the+    terms of sections 15 and 16 of this License; or++    b) Requiring preservation of specified reasonable legal notices or+    author attributions in that material or in the Appropriate Legal+    Notices displayed by works containing it; or++    c) Prohibiting misrepresentation of the origin of that material, or+    requiring that modified versions of such material be marked in+    reasonable ways as different from the original version; or++    d) Limiting the use for publicity purposes of names of licensors or+    authors of the material; or++    e) Declining to grant rights under trademark law for use of some+    trade names, trademarks, or service marks; or++    f) Requiring indemnification of licensors and authors of that+    material by anyone who conveys the material (or modified versions of+    it) with contractual assumptions of liability to the recipient, for+    any liability that these contractual assumptions directly impose on+    those licensors and authors.++  All other non-permissive additional terms are considered "further+restrictions" within the meaning of section 10.  If the Program as you+received it, or any part of it, contains a notice stating that it is+governed by this License along with a term that is a further+restriction, you may remove that term.  If a license document contains+a further restriction but permits relicensing or conveying under this+License, you may add to a covered work material governed by the terms+of that license document, provided that the further restriction does+not survive such relicensing or conveying.++  If you add terms to a covered work in accord with this section, you+must place, in the relevant source files, a statement of the+additional terms that apply to those files, or a notice indicating+where to find the applicable terms.++  Additional terms, permissive or non-permissive, may be stated in the+form of a separately written license, or stated as exceptions;+the above requirements apply either way.++  8. Termination.++  You may not propagate or modify a covered work except as expressly+provided under this License.  Any attempt otherwise to propagate or+modify it is void, and will automatically terminate your rights under+this License (including any patent licenses granted under the third+paragraph of section 11).++  However, if you cease all violation of this License, then your+license from a particular copyright holder is reinstated (a)+provisionally, unless and until the copyright holder explicitly and+finally terminates your license, and (b) permanently, if the copyright+holder fails to notify you of the violation by some reasonable means+prior to 60 days after the cessation.++  Moreover, your license from a particular copyright holder is+reinstated permanently if the copyright holder notifies you of the+violation by some reasonable means, this is the first time you have+received notice of violation of this License (for any work) from that+copyright holder, and you cure the violation prior to 30 days after+your receipt of the notice.++  Termination of your rights under this section does not terminate the+licenses of parties who have received copies or rights from you under+this License.  If your rights have been terminated and not permanently+reinstated, you do not qualify to receive new licenses for the same+material under section 10.++  9. Acceptance Not Required for Having Copies.++  You are not required to accept this License in order to receive or+run a copy of the Program.  Ancillary propagation of a covered work+occurring solely as a consequence of using peer-to-peer transmission+to receive a copy likewise does not require acceptance.  However,+nothing other than this License grants you permission to propagate or+modify any covered work.  These actions infringe copyright if you do+not accept this License.  Therefore, by modifying or propagating a+covered work, you indicate your acceptance of this License to do so.++  10. Automatic Licensing of Downstream Recipients.++  Each time you convey a covered work, the recipient automatically+receives a license from the original licensors, to run, modify and+propagate that work, subject to this License.  You are not responsible+for enforcing compliance by third parties with this License.++  An "entity transaction" is a transaction transferring control of an+organization, or substantially all assets of one, or subdividing an+organization, or merging organizations.  If propagation of a covered+work results from an entity transaction, each party to that+transaction who receives a copy of the work also receives whatever+licenses to the work the party's predecessor in interest had or could+give under the previous paragraph, plus a right to possession of the+Corresponding Source of the work from the predecessor in interest, if+the predecessor has it or can get it with reasonable efforts.++  You may not impose any further restrictions on the exercise of the+rights granted or affirmed under this License.  For example, you may+not impose a license fee, royalty, or other charge for exercise of+rights granted under this License, and you may not initiate litigation+(including a cross-claim or counterclaim in a lawsuit) alleging that+any patent claim is infringed by making, using, selling, offering for+sale, or importing the Program or any portion of it.++  11. Patents.++  A "contributor" is a copyright holder who authorizes use under this+License of the Program or a work on which the Program is based.  The+work thus licensed is called the contributor's "contributor version".++  A contributor's "essential patent claims" are all patent claims+owned or controlled by the contributor, whether already acquired or+hereafter acquired, that would be infringed by some manner, permitted+by this License, of making, using, or selling its contributor version,+but do not include claims that would be infringed only as a+consequence of further modification of the contributor version.  For+purposes of this definition, "control" includes the right to grant+patent sublicenses in a manner consistent with the requirements of+this License.++  Each contributor grants you a non-exclusive, worldwide, royalty-free+patent license under the contributor's essential patent claims, to+make, use, sell, offer for sale, import and otherwise run, modify and+propagate the contents of its contributor version.++  In the following three paragraphs, a "patent license" is any express+agreement or commitment, however denominated, not to enforce a patent+(such as an express permission to practice a patent or covenant not to+sue for patent infringement).  To "grant" such a patent license to a+party means to make such an agreement or commitment not to enforce a+patent against the party.++  If you convey a covered work, knowingly relying on a patent license,+and the Corresponding Source of the work is not available for anyone+to copy, free of charge and under the terms of this License, through a+publicly available network server or other readily accessible means,+then you must either (1) cause the Corresponding Source to be so+available, or (2) arrange to deprive yourself of the benefit of the+patent license for this particular work, or (3) arrange, in a manner+consistent with the requirements of this License, to extend the patent+license to downstream recipients.  "Knowingly relying" means you have+actual knowledge that, but for the patent license, your conveying the+covered work in a country, or your recipient's use of the covered work+in a country, would infringe one or more identifiable patents in that+country that you have reason to believe are valid.++  If, pursuant to or in connection with a single transaction or+arrangement, you convey, or propagate by procuring conveyance of, a+covered work, and grant a patent license to some of the parties+receiving the covered work authorizing them to use, propagate, modify+or convey a specific copy of the covered work, then the patent license+you grant is automatically extended to all recipients of the covered+work and works based on it.++  A patent license is "discriminatory" if it does not include within+the scope of its coverage, prohibits the exercise of, or is+conditioned on the non-exercise of one or more of the rights that are+specifically granted under this License.  You may not convey a covered+work if you are a party to an arrangement with a third party that is+in the business of distributing software, under which you make payment+to the third party based on the extent of your activity of conveying+the work, and under which the third party grants, to any of the+parties who would receive the covered work from you, a discriminatory+patent license (a) in connection with copies of the covered work+conveyed by you (or copies made from those copies), or (b) primarily+for and in connection with specific products or compilations that+contain the covered work, unless you entered into that arrangement,+or that patent license was granted, prior to 28 March 2007.++  Nothing in this License shall be construed as excluding or limiting+any implied license or other defenses to infringement that may+otherwise be available to you under applicable patent law.++  12. No Surrender of Others' Freedom.++  If conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License.  If you cannot convey a+covered work so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you may+not convey it at all.  For example, if you agree to terms that obligate you+to collect a royalty for further conveying from those to whom you convey+the Program, the only way you could satisfy both those terms and this+License would be to refrain entirely from conveying the Program.++  13. Use with the GNU Affero General Public License.++  Notwithstanding any other provision of this License, you have+permission to link or combine any covered work with a work licensed+under version 3 of the GNU Affero General Public License into a single+combined work, and to convey the resulting work.  The terms of this+License will continue to apply to the part which is the covered work,+but the special requirements of the GNU Affero General Public License,+section 13, concerning interaction through a network will apply to the+combination as such.++  14. Revised Versions of this License.++  The Free Software Foundation may publish revised and/or new versions of+the GNU General Public License from time to time.  Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++  Each version is given a distinguishing version number.  If the+Program specifies that a certain numbered version of the GNU General+Public License "or any later version" applies to it, you have the+option of following the terms and conditions either of that numbered+version or of any later version published by the Free Software+Foundation.  If the Program does not specify a version number of the+GNU General Public License, you may choose any version ever published+by the Free Software Foundation.++  If the Program specifies that a proxy can decide which future+versions of the GNU General Public License can be used, that proxy's+public statement of acceptance of a version permanently authorizes you+to choose that version for the Program.++  Later license versions may give you additional or different+permissions.  However, no additional obligations are imposed on any+author or copyright holder as a result of your choosing to follow a+later version.++  15. Disclaimer of Warranty.++  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.++  16. Limitation of Liability.++  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF+SUCH DAMAGES.++  17. Interpretation of Sections 15 and 16.++  If the disclaimer of warranty and limitation of liability provided+above cannot be given local legal effect according to their terms,+reviewing courts shall apply local law that most closely approximates+an absolute waiver of all civil liability in connection with the+Program, unless a warranty or assumption of liability accompanies a+copy of the Program in return for a fee.++                     END OF TERMS AND CONDITIONS++            How to Apply These Terms to Your New Programs++  If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++  To do so, attach the following notices to the program.  It is safest+to attach them to the start of each source file to most effectively+state the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++    <one line to give the program's name and a brief idea of what it does.>+    Copyright (C) <year>  <name of author>++    This program is free software: you can redistribute it and/or modify+    it under the terms of the GNU General Public License as published by+    the Free Software Foundation, either version 3 of the License, or+    (at your option) any later version.++    This program is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+    GNU General Public License for more details.++    You should have received a copy of the GNU General Public License+    along with this program.  If not, see <https://www.gnu.org/licenses/>.++Also add information on how to contact you by electronic and paper mail.++  If the program does terminal interaction, make it output a short+notice like this when it starts in an interactive mode:++    <program>  Copyright (C) <year>  <name of author>+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+    This is free software, and you are welcome to redistribute it+    under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License.  Of course, your program's commands+might be different; for a GUI interface, you would use an "about box".++  You should also get your employer (if you work as a programmer) or school,+if any, to sign a "copyright disclaimer" for the program, if necessary.+For more information on this, and how to apply and follow the GNU GPL, see+<https://www.gnu.org/licenses/>.++  The GNU General Public License does not permit incorporating your program+into proprietary programs.  If your program is a subroutine library, you+may consider it more useful to permit linking proprietary applications with+the library.  If this is what you want to do, use the GNU Lesser General+Public License instead of this License.  But first, please read+<https://www.gnu.org/licenses/why-not-lgpl.html>.
fixtures/cabal.haskell-ci view
@@ -1,6 +1,10 @@ -- Most settings can be given as command line arguments -- Config file is convenient if you maintain large amount of packages +-- Supported: xenial and bionic;+-- though bionic doesn't seem to be officially supported by Travis+distribution: xenial+ jobs: 2:2  -- Add GHC head job@@ -12,6 +16,19 @@ -- remove cabal noise from test output -- cabal-noise: False +-- Build tests. In addition to True and False you may specify+-- a version range, e.g. >= 8.0 to build tests only in some jobs.+tests: True++-- Run tests. Note that only built tests are run. Accepts booleans or version range.+run-tests: True++-- Build benchmarks. There are no way to run benchmarks. Accepts booleans or version range.+benchmarks: True++-- Build haddocks. Accepts booleans or version range.+haddock: True+ -- Run cabal check -- cabal-check: True @@ -51,8 +68,12 @@ -- doctest-version: ==0.13.*  -- macOS job-osx: 8.4.4+osx: 8.4.4 8.6.5 +-- Define per-job environment variables+-- env: 8.4.4:FOO=bar,+--      8.6.4:FOO=baz+ -- Constraint sets -- Package will be build with different constraints. -- This is useful to check compatibility with older versions of dependencies.@@ -60,7 +81,18 @@ constraint-set deepseq-1.4   ghc: (>= 7.8 && <7.10) || == 8.2.2   constraints: deepseq ==1.4.*+  constraints: binary installed +  -- Constraint sets accept booleans for few steps, as the main script+  -- Defaults are False.+  -- These fields don't accept version ranges: you should rather create+  -- another constraint set.++  -- tests: False+  -- run-tests: False+  -- benchmarks: False+  haddock: True+ -- Copy over additional properties specified in a cabal.project file. -- Possible values are: --   none: Do not copy any properties from the cabal.project file.@@ -75,6 +107,28 @@ --         * source-repository-package --   all: Copy every property from the cabal.project file. copy-fields: some++-- Configure haskell-ci's behavior when presented multiple packages (e.g., a+-- cabal.project file that specifies multiple .cabal files), each of which+-- having its own range of GHC versions in its tested-with stanza.+-- Possible values are:+--   uniform: Every package must have the same range of versions in its+--            tested-with stanza. (Default)+--   any:     Take the union of all packages' version ranges. This implies+--            that different packages' version ranges can be disjoint.+jobs-selection: uniform++-- Controls whether the haskell-ci version should be inserted into the+-- generated Travis YAML file. (Default: True)+--+-- We set this option to False here only to prevent version number churn in+-- the commit history, as version numbers for haskell-ci HEAD change extremely+-- frequently.+insert-version: False++-- Controls whether the output of `cabal` invocations should be highlighted+-- using special colors in the Travis output.+color: True  -- Include these fields "as is" in generated cabal.project raw-project
fixtures/cabal.project.copy-fields.all.stderr view
@@ -1,1 +1,1 @@-*INFO* Generating Travis-CI config for testing for GHC versions: 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4+*INFO* Generating Travis-CI config for testing for GHC versions: 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4 8.6.5 8.8.1
fixtures/cabal.project.copy-fields.all.travis.yml view
@@ -1,22 +1,18 @@ # This Travis job script has been generated by a script via #-#   haskell-ci '-o' 'cabal.project.empty-line.travis.yml' '--copy-fields=all' 'cabal.project.empty-line'+#   haskell-ci '-o' 'cabal.project.empty-line.travis.yml' '--config=cabal.project.haskell-ci' '--copy-fields=all' 'cabal.project.empty-line' # # For more information, see https://github.com/haskell-CI/haskell-ci #-# version: 0.2.1-# language: c dist: xenial- git:-  submodules: false  # whether to recursively clone submodules-+  # whether to recursively clone submodules+  submodules: false cache:   directories:     - $HOME/.cabal/packages     - $HOME/.cabal/store- before_cache:   - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log   # remove files that are regenerated by 'cabal update'@@ -25,142 +21,184 @@   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx-   - rm -rfv $CABALHOME/packages/head.hackage- matrix:   include:-    - compiler: "ghc-8.6.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.4], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.3], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.4], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.3], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.1], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.3], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.2], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.1], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.4], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.3], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.2], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.1], sources: [hvr-ghc]}}-+    - compiler: ghc-8.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.8.1","cabal-install-3.0"]}}+    - compiler: ghc-8.6.5+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-3.0"]}}+    - compiler: ghc-8.6.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.4","cabal-install-3.0"]}}+    - compiler: ghc-8.6.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.3","cabal-install-3.0"]}}+    - compiler: ghc-8.6.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.2","cabal-install-3.0"]}}+    - compiler: ghc-8.6.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.1","cabal-install-3.0"]}}+    - compiler: ghc-8.4.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-3.0"]}}+    - compiler: ghc-8.4.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.3","cabal-install-3.0"]}}+    - compiler: ghc-8.4.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.2","cabal-install-3.0"]}}+    - compiler: ghc-8.4.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.1","cabal-install-3.0"]}}+    - compiler: ghc-8.2.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-3.0"]}}+    - compiler: ghc-8.2.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.1","cabal-install-3.0"]}}+    - compiler: ghc-8.0.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-3.0"]}}+    - compiler: ghc-8.0.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.1","cabal-install-3.0"]}}+    - compiler: ghc-7.10.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.3","cabal-install-3.0"]}}+    - compiler: ghc-7.10.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.2","cabal-install-3.0"]}}+    - compiler: ghc-7.10.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.1","cabal-install-3.0"]}}+    - compiler: ghc-7.8.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.4","cabal-install-3.0"]}}+    - compiler: ghc-7.8.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.3","cabal-install-3.0"]}}+    - compiler: ghc-7.8.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.2","cabal-install-3.0"]}}+    - compiler: ghc-7.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.1","cabal-install-3.0"]}} before_install:-  - HC=/opt/ghc/bin/${CC}-  - HCPKG=${HC/ghc/ghc-pkg}+  - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')+  - WITHCOMPILER="-w $HC"+  - HCPKG="$HC-pkg"   - unset CC   - CABAL=/opt/ghc/bin/cabal   - CABALHOME=$HOME/.cabal   - export PATH="$CABALHOME/bin:$PATH"-  - ROOTDIR=$(pwd)-  - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))+  - TOP=$(pwd)+  - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"   - echo $HCNUMVER-+  - CABAL="$CABAL -vnormal+nowrap+markoutput"+  - set -o pipefail+  - |+    echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }'           >> .colorful.awk+    echo 'BEGIN { state = "output"; }'                                     >> .colorful.awk+    echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }'            >> .colorful.awk+    echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }'             >> .colorful.awk+    echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk+    echo '  if (state == "cabal") {'                                       >> .colorful.awk+    echo '    print blue($0)'                                              >> .colorful.awk+    echo '  } else {'                                                      >> .colorful.awk+    echo '    print $0'                                                    >> .colorful.awk+    echo '  }'                                                             >> .colorful.awk+    echo '}'                                                               >> .colorful.awk+  - cat .colorful.awk+  - |+    color_cabal_output () {+      awk -f $TOP/.colorful.awk+    }+  - echo text | color_cabal_output install:   - ${CABAL} --version   - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"   - TEST=--enable-tests   - BENCH=--enable-benchmarks-  - GHCHEAD=${GHCHEAD-false}-  - travis_retry ${CABAL} update -v-  - sed -i.bak 's/^jobs:/-- jobs:/' $CABALHOME/config-  - rm -fv cabal.project cabal.project.local-  - grep -Ev -- '^\s*--' $CABALHOME/config | grep -Ev '^\s*$'-  - rm -f cabal.project+  - HEADHACKAGE=false+  - rm -f $CABALHOME/config+  - |+    echo "verbose: normal +nowrap +markoutput"          >> $CABALHOME/config+    echo "remote-build-reporting: anonymous"            >> $CABALHOME/config+    echo "write-ghc-environment-files: always"          >> $CABALHOME/config+    echo "remote-repo-cache: $CABALHOME/packages"       >> $CABALHOME/config+    echo "logs-dir:          $CABALHOME/logs"           >> $CABALHOME/config+    echo "world-file:        $CABALHOME/world"          >> $CABALHOME/config+    echo "extra-prog-path:   $CABALHOME/bin"            >> $CABALHOME/config+    echo "symlink-bindir:    $CABALHOME/bin"            >> $CABALHOME/config+    echo "installdir:        $CABALHOME/bin"            >> $CABALHOME/config+    echo "build-summary:     $CABALHOME/logs/build.log" >> $CABALHOME/config+    echo "store-dir:         $CABALHOME/store"          >> $CABALHOME/config+    echo "install-dirs user"                            >> $CABALHOME/config+    echo "  prefix: $CABALHOME"                         >> $CABALHOME/config+    echo "repository hackage.haskell.org"               >> $CABALHOME/config+    echo "  url: http://hackage.haskell.org/"           >> $CABALHOME/config+  - cat $CABALHOME/config+  - rm -fv cabal.project cabal.project.local cabal.project.freeze+  - travis_retry ${CABAL} v2-update -v+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"servant\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-client\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-docs\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-server\"\\n' >> cabal.project"-  - echo 'package servant' >> cabal.project-  - "echo '  tests: False' >> cabal.project"-  - "echo 'constraints: foundation >= 0.14' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant-foreign' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - |+    echo "packages: servant" >> cabal.project+    echo "packages: servant-client" >> cabal.project+    echo "packages: servant-docs" >> cabal.project+    echo "packages: servant-server" >> cabal.project+  - |+    echo "package servant"                         >> cabal.project+    echo "  tests: False"                          >> cabal.project+    echo ""                                        >> cabal.project+    echo "constraints: foundation >= 0.14"         >> cabal.project+    echo "allow-newer: servant-js:servant"         >> cabal.project+    echo "allow-newer: servant-js:servant-foreign" >> cabal.project+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true   - if [ -f "servant/configure.ac" ]; then (cd "servant" && autoreconf -i); fi   - if [ -f "servant-client/configure.ac" ]; then (cd "servant-client" && autoreconf -i); fi   - if [ -f "servant-docs/configure.ac" ]; then (cd "servant-docs" && autoreconf -i); fi   - if [ -f "servant-server/configure.ac" ]; then (cd "servant-server" && autoreconf -i); fi-  - rm -f cabal.project.freeze-  - ${CABAL} new-freeze -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project.copy-fields.all" --dry-  - "cat \"cabal.project.copy-fields.all.freeze\" | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"-  - rm  "cabal.project.copy-fields.all.freeze"-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project.copy-fields.all" --dep -j2 all-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks --project-file="cabal.project.copy-fields.all" --dep -j2 all-  - rm -rf .ghc.environment.* "servant"/dist "servant-client"/dist "servant-docs"/dist "servant-server"/dist-  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)--# 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.+  - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output+  - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"+  - rm  cabal.project.freeze+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all | color_cabal_output+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output script:-  # test that source-distributions can be generated-  - ${CABAL} new-sdist all+  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)+  # Packaging...+  - ${CABAL} v2-sdist all | color_cabal_output+  # Unpacking...   - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/   - cd ${DISTDIR} || false-  - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;-  - rm -f cabal.project+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm       '{}' \;+  - PKGDIR_servant="$(find . -maxdepth 1 -type d -regex '.*/servant-[0-9.]*')"+  - PKGDIR_servant_client="$(find . -maxdepth 1 -type d -regex '.*/servant-client-[0-9.]*')"+  - PKGDIR_servant_docs="$(find . -maxdepth 1 -type d -regex '.*/servant-docs-[0-9.]*')"+  - PKGDIR_servant_server="$(find . -maxdepth 1 -type d -regex '.*/servant-server-[0-9.]*')"+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"servant-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-client-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-docs-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-server-*/*.cabal\"\\n' >> cabal.project"-  - echo 'package servant' >> cabal.project-  - "echo '  tests: False' >> cabal.project"-  - "echo 'constraints: foundation >= 0.14' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant-foreign' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - |+    echo "packages: ${PKGDIR_servant}" >> cabal.project+    echo "packages: ${PKGDIR_servant_client}" >> cabal.project+    echo "packages: ${PKGDIR_servant_docs}" >> cabal.project+    echo "packages: ${PKGDIR_servant_server}" >> cabal.project+  - |+    echo "package servant"                         >> cabal.project+    echo "  tests: False"                          >> cabal.project+    echo ""                                        >> cabal.project+    echo "constraints: foundation >= 0.14"         >> cabal.project+    echo "allow-newer: servant-js:servant"         >> cabal.project+    echo "allow-newer: servant-js:servant-foreign" >> cabal.project+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true+  # Building...   # this builds all libraries and executables (without tests/benchmarks)-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all-+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output+  # Building with tests and benchmarks...   # build & run tests, build benchmarks-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} all-  - if [ "x$TEST" = "x--enable-tests" ]; then ${CABAL} new-test -w ${HC} ${TEST} ${BENCH} all; fi--  # cabal check-  - (cd servant-* && ${CABAL} check)-  - (cd servant-client-* && ${CABAL} check)-  - (cd servant-docs-* && ${CABAL} check)-  - (cd servant-server-* && ${CABAL} check)--  # haddock-  - ${CABAL} new-haddock -w ${HC} ${TEST} ${BENCH} all--  # Build without installed constraints for packages in global-db-  - rm -f cabal.project.local; ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all;+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Testing...+  - ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # cabal check...+  - (cd ${PKGDIR_servant} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_client} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_docs} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_server} && ${CABAL} -vnormal check)+  # haddock...+  - ${CABAL} v2-haddock $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Building without installed constraints for packages in global-db...+  - rm -f cabal.project.local+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output -# REGENDATA ["-o","cabal.project.empty-line.travis.yml","--copy-fields=all","cabal.project.empty-line"]+# REGENDATA ["-o","cabal.project.empty-line.travis.yml","--config=cabal.project.haskell-ci","--copy-fields=all","cabal.project.empty-line"] # EOF
fixtures/cabal.project.copy-fields.none.stderr view
@@ -1,1 +1,1 @@-*INFO* Generating Travis-CI config for testing for GHC versions: 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4+*INFO* Generating Travis-CI config for testing for GHC versions: 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4 8.6.5 8.8.1
fixtures/cabal.project.copy-fields.none.travis.yml view
@@ -1,22 +1,18 @@ # This Travis job script has been generated by a script via #-#   haskell-ci '-o' 'cabal.project.empty-line.travis.yml' '--copy-fields=none' 'cabal.project.empty-line'+#   haskell-ci '-o' 'cabal.project.empty-line.travis.yml' '--config=cabal.project.haskell-ci' '--copy-fields=none' 'cabal.project.empty-line' # # For more information, see https://github.com/haskell-CI/haskell-ci #-# version: 0.2.1-# language: c dist: xenial- git:-  submodules: false  # whether to recursively clone submodules-+  # whether to recursively clone submodules+  submodules: false cache:   directories:     - $HOME/.cabal/packages     - $HOME/.cabal/store- before_cache:   - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log   # remove files that are regenerated by 'cabal update'@@ -25,132 +21,172 @@   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx-   - rm -rfv $CABALHOME/packages/head.hackage- matrix:   include:-    - compiler: "ghc-8.6.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.4], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.3], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.4], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.3], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.1], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.3], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.2], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.1], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.4], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.3], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.2], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.1], sources: [hvr-ghc]}}-+    - compiler: ghc-8.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.8.1","cabal-install-3.0"]}}+    - compiler: ghc-8.6.5+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-3.0"]}}+    - compiler: ghc-8.6.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.4","cabal-install-3.0"]}}+    - compiler: ghc-8.6.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.3","cabal-install-3.0"]}}+    - compiler: ghc-8.6.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.2","cabal-install-3.0"]}}+    - compiler: ghc-8.6.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.1","cabal-install-3.0"]}}+    - compiler: ghc-8.4.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-3.0"]}}+    - compiler: ghc-8.4.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.3","cabal-install-3.0"]}}+    - compiler: ghc-8.4.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.2","cabal-install-3.0"]}}+    - compiler: ghc-8.4.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.1","cabal-install-3.0"]}}+    - compiler: ghc-8.2.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-3.0"]}}+    - compiler: ghc-8.2.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.1","cabal-install-3.0"]}}+    - compiler: ghc-8.0.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-3.0"]}}+    - compiler: ghc-8.0.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.1","cabal-install-3.0"]}}+    - compiler: ghc-7.10.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.3","cabal-install-3.0"]}}+    - compiler: ghc-7.10.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.2","cabal-install-3.0"]}}+    - compiler: ghc-7.10.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.1","cabal-install-3.0"]}}+    - compiler: ghc-7.8.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.4","cabal-install-3.0"]}}+    - compiler: ghc-7.8.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.3","cabal-install-3.0"]}}+    - compiler: ghc-7.8.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.2","cabal-install-3.0"]}}+    - compiler: ghc-7.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.1","cabal-install-3.0"]}} before_install:-  - HC=/opt/ghc/bin/${CC}-  - HCPKG=${HC/ghc/ghc-pkg}+  - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')+  - WITHCOMPILER="-w $HC"+  - HCPKG="$HC-pkg"   - unset CC   - CABAL=/opt/ghc/bin/cabal   - CABALHOME=$HOME/.cabal   - export PATH="$CABALHOME/bin:$PATH"-  - ROOTDIR=$(pwd)-  - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))+  - TOP=$(pwd)+  - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"   - echo $HCNUMVER-+  - CABAL="$CABAL -vnormal+nowrap+markoutput"+  - set -o pipefail+  - |+    echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }'           >> .colorful.awk+    echo 'BEGIN { state = "output"; }'                                     >> .colorful.awk+    echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }'            >> .colorful.awk+    echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }'             >> .colorful.awk+    echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk+    echo '  if (state == "cabal") {'                                       >> .colorful.awk+    echo '    print blue($0)'                                              >> .colorful.awk+    echo '  } else {'                                                      >> .colorful.awk+    echo '    print $0'                                                    >> .colorful.awk+    echo '  }'                                                             >> .colorful.awk+    echo '}'                                                               >> .colorful.awk+  - cat .colorful.awk+  - |+    color_cabal_output () {+      awk -f $TOP/.colorful.awk+    }+  - echo text | color_cabal_output install:   - ${CABAL} --version   - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"   - TEST=--enable-tests   - BENCH=--enable-benchmarks-  - GHCHEAD=${GHCHEAD-false}-  - travis_retry ${CABAL} update -v-  - sed -i.bak 's/^jobs:/-- jobs:/' $CABALHOME/config-  - rm -fv cabal.project cabal.project.local-  - grep -Ev -- '^\s*--' $CABALHOME/config | grep -Ev '^\s*$'-  - rm -f cabal.project+  - HEADHACKAGE=false+  - rm -f $CABALHOME/config+  - |+    echo "verbose: normal +nowrap +markoutput"          >> $CABALHOME/config+    echo "remote-build-reporting: anonymous"            >> $CABALHOME/config+    echo "write-ghc-environment-files: always"          >> $CABALHOME/config+    echo "remote-repo-cache: $CABALHOME/packages"       >> $CABALHOME/config+    echo "logs-dir:          $CABALHOME/logs"           >> $CABALHOME/config+    echo "world-file:        $CABALHOME/world"          >> $CABALHOME/config+    echo "extra-prog-path:   $CABALHOME/bin"            >> $CABALHOME/config+    echo "symlink-bindir:    $CABALHOME/bin"            >> $CABALHOME/config+    echo "installdir:        $CABALHOME/bin"            >> $CABALHOME/config+    echo "build-summary:     $CABALHOME/logs/build.log" >> $CABALHOME/config+    echo "store-dir:         $CABALHOME/store"          >> $CABALHOME/config+    echo "install-dirs user"                            >> $CABALHOME/config+    echo "  prefix: $CABALHOME"                         >> $CABALHOME/config+    echo "repository hackage.haskell.org"               >> $CABALHOME/config+    echo "  url: http://hackage.haskell.org/"           >> $CABALHOME/config+  - cat $CABALHOME/config+  - rm -fv cabal.project cabal.project.local cabal.project.freeze+  - travis_retry ${CABAL} v2-update -v+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"servant\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-client\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-docs\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-server\"\\n' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - |+    echo "packages: servant" >> cabal.project+    echo "packages: servant-client" >> cabal.project+    echo "packages: servant-docs" >> cabal.project+    echo "packages: servant-server" >> cabal.project+  - |+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true   - if [ -f "servant/configure.ac" ]; then (cd "servant" && autoreconf -i); fi   - if [ -f "servant-client/configure.ac" ]; then (cd "servant-client" && autoreconf -i); fi   - if [ -f "servant-docs/configure.ac" ]; then (cd "servant-docs" && autoreconf -i); fi   - if [ -f "servant-server/configure.ac" ]; then (cd "servant-server" && autoreconf -i); fi-  - rm -f cabal.project.freeze-  - ${CABAL} new-freeze -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project.copy-fields.none" --dry-  - "cat \"cabal.project.copy-fields.none.freeze\" | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"-  - rm  "cabal.project.copy-fields.none.freeze"-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project.copy-fields.none" --dep -j2 all-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks --project-file="cabal.project.copy-fields.none" --dep -j2 all-  - rm -rf .ghc.environment.* "servant"/dist "servant-client"/dist "servant-docs"/dist "servant-server"/dist-  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)--# 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.+  - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output+  - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"+  - rm  cabal.project.freeze+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all | color_cabal_output+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output script:-  # test that source-distributions can be generated-  - ${CABAL} new-sdist all+  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)+  # Packaging...+  - ${CABAL} v2-sdist all | color_cabal_output+  # Unpacking...   - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/   - cd ${DISTDIR} || false-  - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;-  - rm -f cabal.project+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm       '{}' \;+  - PKGDIR_servant="$(find . -maxdepth 1 -type d -regex '.*/servant-[0-9.]*')"+  - PKGDIR_servant_client="$(find . -maxdepth 1 -type d -regex '.*/servant-client-[0-9.]*')"+  - PKGDIR_servant_docs="$(find . -maxdepth 1 -type d -regex '.*/servant-docs-[0-9.]*')"+  - PKGDIR_servant_server="$(find . -maxdepth 1 -type d -regex '.*/servant-server-[0-9.]*')"+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"servant-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-client-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-docs-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-server-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - |+    echo "packages: ${PKGDIR_servant}" >> cabal.project+    echo "packages: ${PKGDIR_servant_client}" >> cabal.project+    echo "packages: ${PKGDIR_servant_docs}" >> cabal.project+    echo "packages: ${PKGDIR_servant_server}" >> cabal.project+  - |+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true+  # Building...   # this builds all libraries and executables (without tests/benchmarks)-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all-+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output+  # Building with tests and benchmarks...   # build & run tests, build benchmarks-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} all-  - if [ "x$TEST" = "x--enable-tests" ]; then ${CABAL} new-test -w ${HC} ${TEST} ${BENCH} all; fi--  # cabal check-  - (cd servant-* && ${CABAL} check)-  - (cd servant-client-* && ${CABAL} check)-  - (cd servant-docs-* && ${CABAL} check)-  - (cd servant-server-* && ${CABAL} check)--  # haddock-  - ${CABAL} new-haddock -w ${HC} ${TEST} ${BENCH} all--  # Build without installed constraints for packages in global-db-  - rm -f cabal.project.local; ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all;+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Testing...+  - ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # cabal check...+  - (cd ${PKGDIR_servant} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_client} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_docs} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_server} && ${CABAL} -vnormal check)+  # haddock...+  - ${CABAL} v2-haddock $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Building without installed constraints for packages in global-db...+  - rm -f cabal.project.local+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output -# REGENDATA ["-o","cabal.project.empty-line.travis.yml","--copy-fields=none","cabal.project.empty-line"]+# REGENDATA ["-o","cabal.project.empty-line.travis.yml","--config=cabal.project.haskell-ci","--copy-fields=none","cabal.project.empty-line"] # EOF
fixtures/cabal.project.copy-fields.some.stderr view
@@ -1,1 +1,1 @@-*INFO* Generating Travis-CI config for testing for GHC versions: 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4+*INFO* Generating Travis-CI config for testing for GHC versions: 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4 8.6.5 8.8.1
fixtures/cabal.project.copy-fields.some.travis.yml view
@@ -1,22 +1,18 @@ # This Travis job script has been generated by a script via #-#   haskell-ci '-o' 'cabal.project.empty-line.travis.yml' '--copy-fields=some' 'cabal.project.empty-line'+#   haskell-ci '-o' 'cabal.project.empty-line.travis.yml' '--config=cabal.project.haskell-ci' '--copy-fields=some' 'cabal.project.empty-line' # # For more information, see https://github.com/haskell-CI/haskell-ci #-# version: 0.2.1-# language: c dist: xenial- git:-  submodules: false  # whether to recursively clone submodules-+  # whether to recursively clone submodules+  submodules: false cache:   directories:     - $HOME/.cabal/packages     - $HOME/.cabal/store- before_cache:   - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log   # remove files that are regenerated by 'cabal update'@@ -25,138 +21,178 @@   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx-   - rm -rfv $CABALHOME/packages/head.hackage- matrix:   include:-    - compiler: "ghc-8.6.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.4], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.3], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.4], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.3], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.1], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.3], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.2], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.1], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.4], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.3], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.2], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.1], sources: [hvr-ghc]}}-+    - compiler: ghc-8.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.8.1","cabal-install-3.0"]}}+    - compiler: ghc-8.6.5+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-3.0"]}}+    - compiler: ghc-8.6.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.4","cabal-install-3.0"]}}+    - compiler: ghc-8.6.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.3","cabal-install-3.0"]}}+    - compiler: ghc-8.6.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.2","cabal-install-3.0"]}}+    - compiler: ghc-8.6.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.1","cabal-install-3.0"]}}+    - compiler: ghc-8.4.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-3.0"]}}+    - compiler: ghc-8.4.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.3","cabal-install-3.0"]}}+    - compiler: ghc-8.4.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.2","cabal-install-3.0"]}}+    - compiler: ghc-8.4.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.1","cabal-install-3.0"]}}+    - compiler: ghc-8.2.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-3.0"]}}+    - compiler: ghc-8.2.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.1","cabal-install-3.0"]}}+    - compiler: ghc-8.0.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-3.0"]}}+    - compiler: ghc-8.0.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.1","cabal-install-3.0"]}}+    - compiler: ghc-7.10.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.3","cabal-install-3.0"]}}+    - compiler: ghc-7.10.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.2","cabal-install-3.0"]}}+    - compiler: ghc-7.10.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.1","cabal-install-3.0"]}}+    - compiler: ghc-7.8.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.4","cabal-install-3.0"]}}+    - compiler: ghc-7.8.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.3","cabal-install-3.0"]}}+    - compiler: ghc-7.8.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.2","cabal-install-3.0"]}}+    - compiler: ghc-7.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.1","cabal-install-3.0"]}} before_install:-  - HC=/opt/ghc/bin/${CC}-  - HCPKG=${HC/ghc/ghc-pkg}+  - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')+  - WITHCOMPILER="-w $HC"+  - HCPKG="$HC-pkg"   - unset CC   - CABAL=/opt/ghc/bin/cabal   - CABALHOME=$HOME/.cabal   - export PATH="$CABALHOME/bin:$PATH"-  - ROOTDIR=$(pwd)-  - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))+  - TOP=$(pwd)+  - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"   - echo $HCNUMVER-+  - CABAL="$CABAL -vnormal+nowrap+markoutput"+  - set -o pipefail+  - |+    echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }'           >> .colorful.awk+    echo 'BEGIN { state = "output"; }'                                     >> .colorful.awk+    echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }'            >> .colorful.awk+    echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }'             >> .colorful.awk+    echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk+    echo '  if (state == "cabal") {'                                       >> .colorful.awk+    echo '    print blue($0)'                                              >> .colorful.awk+    echo '  } else {'                                                      >> .colorful.awk+    echo '    print $0'                                                    >> .colorful.awk+    echo '  }'                                                             >> .colorful.awk+    echo '}'                                                               >> .colorful.awk+  - cat .colorful.awk+  - |+    color_cabal_output () {+      awk -f $TOP/.colorful.awk+    }+  - echo text | color_cabal_output install:   - ${CABAL} --version   - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"   - TEST=--enable-tests   - BENCH=--enable-benchmarks-  - GHCHEAD=${GHCHEAD-false}-  - travis_retry ${CABAL} update -v-  - sed -i.bak 's/^jobs:/-- jobs:/' $CABALHOME/config-  - rm -fv cabal.project cabal.project.local-  - grep -Ev -- '^\s*--' $CABALHOME/config | grep -Ev '^\s*$'-  - rm -f cabal.project+  - HEADHACKAGE=false+  - rm -f $CABALHOME/config+  - |+    echo "verbose: normal +nowrap +markoutput"          >> $CABALHOME/config+    echo "remote-build-reporting: anonymous"            >> $CABALHOME/config+    echo "write-ghc-environment-files: always"          >> $CABALHOME/config+    echo "remote-repo-cache: $CABALHOME/packages"       >> $CABALHOME/config+    echo "logs-dir:          $CABALHOME/logs"           >> $CABALHOME/config+    echo "world-file:        $CABALHOME/world"          >> $CABALHOME/config+    echo "extra-prog-path:   $CABALHOME/bin"            >> $CABALHOME/config+    echo "symlink-bindir:    $CABALHOME/bin"            >> $CABALHOME/config+    echo "installdir:        $CABALHOME/bin"            >> $CABALHOME/config+    echo "build-summary:     $CABALHOME/logs/build.log" >> $CABALHOME/config+    echo "store-dir:         $CABALHOME/store"          >> $CABALHOME/config+    echo "install-dirs user"                            >> $CABALHOME/config+    echo "  prefix: $CABALHOME"                         >> $CABALHOME/config+    echo "repository hackage.haskell.org"               >> $CABALHOME/config+    echo "  url: http://hackage.haskell.org/"           >> $CABALHOME/config+  - cat $CABALHOME/config+  - rm -fv cabal.project cabal.project.local cabal.project.freeze+  - travis_retry ${CABAL} v2-update -v+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"servant\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-client\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-docs\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-server\"\\n' >> cabal.project"-  - "echo 'constraints: foundation >= 0.14' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant-foreign' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - |+    echo "packages: servant" >> cabal.project+    echo "packages: servant-client" >> cabal.project+    echo "packages: servant-docs" >> cabal.project+    echo "packages: servant-server" >> cabal.project+  - |+    echo "constraints: foundation >= 0.14"         >> cabal.project+    echo "allow-newer: servant-js:servant"         >> cabal.project+    echo "allow-newer: servant-js:servant-foreign" >> cabal.project+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true   - if [ -f "servant/configure.ac" ]; then (cd "servant" && autoreconf -i); fi   - if [ -f "servant-client/configure.ac" ]; then (cd "servant-client" && autoreconf -i); fi   - if [ -f "servant-docs/configure.ac" ]; then (cd "servant-docs" && autoreconf -i); fi   - if [ -f "servant-server/configure.ac" ]; then (cd "servant-server" && autoreconf -i); fi-  - rm -f cabal.project.freeze-  - ${CABAL} new-freeze -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project.copy-fields.some" --dry-  - "cat \"cabal.project.copy-fields.some.freeze\" | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"-  - rm  "cabal.project.copy-fields.some.freeze"-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project.copy-fields.some" --dep -j2 all-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks --project-file="cabal.project.copy-fields.some" --dep -j2 all-  - rm -rf .ghc.environment.* "servant"/dist "servant-client"/dist "servant-docs"/dist "servant-server"/dist-  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)--# 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.+  - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output+  - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"+  - rm  cabal.project.freeze+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all | color_cabal_output+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output script:-  # test that source-distributions can be generated-  - ${CABAL} new-sdist all+  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)+  # Packaging...+  - ${CABAL} v2-sdist all | color_cabal_output+  # Unpacking...   - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/   - cd ${DISTDIR} || false-  - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;-  - rm -f cabal.project+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm       '{}' \;+  - PKGDIR_servant="$(find . -maxdepth 1 -type d -regex '.*/servant-[0-9.]*')"+  - PKGDIR_servant_client="$(find . -maxdepth 1 -type d -regex '.*/servant-client-[0-9.]*')"+  - PKGDIR_servant_docs="$(find . -maxdepth 1 -type d -regex '.*/servant-docs-[0-9.]*')"+  - PKGDIR_servant_server="$(find . -maxdepth 1 -type d -regex '.*/servant-server-[0-9.]*')"+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"servant-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-client-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-docs-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-server-*/*.cabal\"\\n' >> cabal.project"-  - "echo 'constraints: foundation >= 0.14' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant-foreign' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - |+    echo "packages: ${PKGDIR_servant}" >> cabal.project+    echo "packages: ${PKGDIR_servant_client}" >> cabal.project+    echo "packages: ${PKGDIR_servant_docs}" >> cabal.project+    echo "packages: ${PKGDIR_servant_server}" >> cabal.project+  - |+    echo "constraints: foundation >= 0.14"         >> cabal.project+    echo "allow-newer: servant-js:servant"         >> cabal.project+    echo "allow-newer: servant-js:servant-foreign" >> cabal.project+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true+  # Building...   # this builds all libraries and executables (without tests/benchmarks)-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all-+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output+  # Building with tests and benchmarks...   # build & run tests, build benchmarks-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} all-  - if [ "x$TEST" = "x--enable-tests" ]; then ${CABAL} new-test -w ${HC} ${TEST} ${BENCH} all; fi--  # cabal check-  - (cd servant-* && ${CABAL} check)-  - (cd servant-client-* && ${CABAL} check)-  - (cd servant-docs-* && ${CABAL} check)-  - (cd servant-server-* && ${CABAL} check)--  # haddock-  - ${CABAL} new-haddock -w ${HC} ${TEST} ${BENCH} all--  # Build without installed constraints for packages in global-db-  - rm -f cabal.project.local; ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all;+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Testing...+  - ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # cabal check...+  - (cd ${PKGDIR_servant} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_client} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_docs} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_server} && ${CABAL} -vnormal check)+  # haddock...+  - ${CABAL} v2-haddock $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Building without installed constraints for packages in global-db...+  - rm -f cabal.project.local+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output -# REGENDATA ["-o","cabal.project.empty-line.travis.yml","--copy-fields=some","cabal.project.empty-line"]+# REGENDATA ["-o","cabal.project.empty-line.travis.yml","--config=cabal.project.haskell-ci","--copy-fields=some","cabal.project.empty-line"] # EOF
fixtures/cabal.project.empty-line.stderr view
@@ -1,1 +1,1 @@-*INFO* Generating Travis-CI config for testing for GHC versions: head 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4+*INFO* Generating Travis-CI config for testing for GHC versions: ghc-head 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4 8.6.5 8.8.1
fixtures/cabal.project.empty-line.travis.yml view
@@ -1,22 +1,18 @@ # This Travis job script has been generated by a script via #-#   haskell-ci '-o' 'cabal.project.empty-line.travis.yml' '--ghc-head' 'cabal.project.empty-line'+#   haskell-ci '-o' 'cabal.project.empty-line.travis.yml' '--config=cabal.project.haskell-ci' '--ghc-head' 'cabal.project.empty-line' # # For more information, see https://github.com/haskell-CI/haskell-ci #-# version: 0.2.1-# language: c dist: xenial- git:-  submodules: false  # whether to recursively clone submodules-+  # whether to recursively clone submodules+  submodules: false cache:   directories:     - $HOME/.cabal/packages     - $HOME/.cabal/store- before_cache:   - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log   # remove files that are regenerated by 'cabal update'@@ -25,162 +21,194 @@   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx-   - rm -rfv $CABALHOME/packages/head.hackage- matrix:   include:-    - compiler: "ghc-8.6.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.4], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.3], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.4], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.3], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.1], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.1], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.3], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.2], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.1], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.4], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.3], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.2], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.1], sources: [hvr-ghc]}}-    - compiler: "ghc-head"-      env: GHCHEAD=true-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-head], sources: [hvr-ghc]}}-+    - compiler: ghc-8.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.8.1","cabal-install-3.0"]}}+    - compiler: ghc-8.6.5+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-3.0"]}}+    - compiler: ghc-8.6.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.4","cabal-install-3.0"]}}+    - compiler: ghc-8.6.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.3","cabal-install-3.0"]}}+    - compiler: ghc-8.6.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.2","cabal-install-3.0"]}}+    - compiler: ghc-8.6.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.1","cabal-install-3.0"]}}+    - compiler: ghc-8.4.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-3.0"]}}+    - compiler: ghc-8.4.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.3","cabal-install-3.0"]}}+    - compiler: ghc-8.4.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.2","cabal-install-3.0"]}}+    - compiler: ghc-8.4.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.1","cabal-install-3.0"]}}+    - compiler: ghc-8.2.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-3.0"]}}+    - compiler: ghc-8.2.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.1","cabal-install-3.0"]}}+    - compiler: ghc-8.0.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-3.0"]}}+    - compiler: ghc-8.0.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.1","cabal-install-3.0"]}}+    - compiler: ghc-7.10.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.3","cabal-install-3.0"]}}+    - compiler: ghc-7.10.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.2","cabal-install-3.0"]}}+    - compiler: ghc-7.10.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.1","cabal-install-3.0"]}}+    - compiler: ghc-7.8.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.4","cabal-install-3.0"]}}+    - compiler: ghc-7.8.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.3","cabal-install-3.0"]}}+    - compiler: ghc-7.8.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.2","cabal-install-3.0"]}}+    - compiler: ghc-7.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.1","cabal-install-3.0"]}}+    - compiler: ghc-head+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-head","cabal-install-head"]}}   allow_failures:-    - compiler: "ghc-head"-+    - compiler: ghc-head before_install:-  - HC=/opt/ghc/bin/${CC}-  - HCPKG=${HC/ghc/ghc-pkg}+  - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')+  - WITHCOMPILER="-w $HC"+  - HCPKG="$HC-pkg"   - unset CC   - CABAL=/opt/ghc/bin/cabal   - CABALHOME=$HOME/.cabal   - export PATH="$CABALHOME/bin:$PATH"-  - ROOTDIR=$(pwd)-  - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))+  - TOP=$(pwd)+  - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"   - echo $HCNUMVER-+  - CABAL="$CABAL -vnormal+nowrap+markoutput"+  - set -o pipefail+  - |+    echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }'           >> .colorful.awk+    echo 'BEGIN { state = "output"; }'                                     >> .colorful.awk+    echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }'            >> .colorful.awk+    echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }'             >> .colorful.awk+    echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk+    echo '  if (state == "cabal") {'                                       >> .colorful.awk+    echo '    print blue($0)'                                              >> .colorful.awk+    echo '  } else {'                                                      >> .colorful.awk+    echo '    print $0'                                                    >> .colorful.awk+    echo '  }'                                                             >> .colorful.awk+    echo '}'                                                               >> .colorful.awk+  - cat .colorful.awk+  - |+    color_cabal_output () {+      awk -f $TOP/.colorful.awk+    }+  - echo text | color_cabal_output install:   - ${CABAL} --version   - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"   - TEST=--enable-tests   - BENCH=--enable-benchmarks-  - GHCHEAD=${GHCHEAD-false}-  - travis_retry ${CABAL} update -v-  - sed -i.bak 's/^jobs:/-- jobs:/' $CABALHOME/config-  - rm -fv cabal.project cabal.project.local-  # Overlay Hackage Package Index for GHC HEAD: https://github.com/hvr/head.hackage+  - HEADHACKAGE=false+  - if [ $HCNUMVER -gt 80801 ] ; then HEADHACKAGE=true ; fi+  - rm -f $CABALHOME/config   - |-    if $GHCHEAD; then-      sed -i 's/-- allow-newer: .*/allow-newer: *:base/' $CABALHOME/config-      for pkg in $($HCPKG list --simple-output); do pkg=$(echo $pkg | sed 's/-[^-]*$//'); sed -i "s/allow-newer: /allow-newer: *:$pkg, /" $CABALHOME/config; done--      echo 'repository head.hackage'                                                        >> $CABALHOME/config-      echo '   url: http://head.hackage.haskell.org/'                                       >> $CABALHOME/config-      echo '   secure: True'                                                                >> $CABALHOME/config-      echo '   root-keys: 07c59cb65787dedfaef5bd5f987ceb5f7e5ebf88b904bbd4c5cbdeb2ff71b740' >> $CABALHOME/config-      echo '              2e8555dde16ebd8df076f1a8ef13b8f14c66bad8eafefd7d9e37d0ed711821fb' >> $CABALHOME/config-      echo '              8f79fd2389ab2967354407ec852cbe73f2e8635793ac446d09461ffb99527f6e' >> $CABALHOME/config-      echo '   key-threshold: 3'                                                            >> $CABALHOME.config--      grep -Ev -- '^\s*--' $CABALHOME/config | grep -Ev '^\s*$'--      ${CABAL} new-update head.hackage -v+    echo "verbose: normal +nowrap +markoutput"          >> $CABALHOME/config+    echo "remote-build-reporting: anonymous"            >> $CABALHOME/config+    echo "write-ghc-environment-files: always"          >> $CABALHOME/config+    echo "remote-repo-cache: $CABALHOME/packages"       >> $CABALHOME/config+    echo "logs-dir:          $CABALHOME/logs"           >> $CABALHOME/config+    echo "world-file:        $CABALHOME/world"          >> $CABALHOME/config+    echo "extra-prog-path:   $CABALHOME/bin"            >> $CABALHOME/config+    echo "symlink-bindir:    $CABALHOME/bin"            >> $CABALHOME/config+    echo "installdir:        $CABALHOME/bin"            >> $CABALHOME/config+    echo "build-summary:     $CABALHOME/logs/build.log" >> $CABALHOME/config+    echo "store-dir:         $CABALHOME/store"          >> $CABALHOME/config+    echo "install-dirs user"                            >> $CABALHOME/config+    echo "  prefix: $CABALHOME"                         >> $CABALHOME/config+    echo "repository hackage.haskell.org"               >> $CABALHOME/config+    echo "  url: http://hackage.haskell.org/"           >> $CABALHOME/config+  - |+    if $HEADHACKAGE; then+    echo "allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\1/g')" >> $CABALHOME/config+    echo "repository head.hackage.ghc.haskell.org"                                        >> $CABALHOME/config+    echo "   url: https://ghc.gitlab.haskell.org/head.hackage/"                           >> $CABALHOME/config+    echo "   secure: True"                                                                >> $CABALHOME/config+    echo "   root-keys: 7541f32a4ccca4f97aea3b22f5e593ba2c0267546016b992dfadcd2fe944e55d" >> $CABALHOME/config+    echo "              26021a13b401500c8eb2761ca95c61f2d625bfef951b939a8124ed12ecf07329" >> $CABALHOME/config+    echo "              f76d08be13e9a61a377a85e2fb63f4c5435d40f8feb3e12eb05905edb8cdea89" >> $CABALHOME/config+    echo "   key-threshold: 3"                                                            >> $CABALHOME/config     fi-  - grep -Ev -- '^\s*--' $CABALHOME/config | grep -Ev '^\s*$'-  - rm -f cabal.project+  - cat $CABALHOME/config+  - rm -fv cabal.project cabal.project.local cabal.project.freeze+  - travis_retry ${CABAL} v2-update -v+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"servant\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-client\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-docs\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-server\"\\n' >> cabal.project"-  - "echo 'constraints: foundatiion >= 0.14' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant-foreign' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - |+    echo "packages: servant" >> cabal.project+    echo "packages: servant-client" >> cabal.project+    echo "packages: servant-docs" >> cabal.project+    echo "packages: servant-server" >> cabal.project+  - |+    echo "constraints: foundatiion >= 0.14"        >> cabal.project+    echo "allow-newer: servant-js:servant"         >> cabal.project+    echo "allow-newer: servant-js:servant-foreign" >> cabal.project+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true   - if [ -f "servant/configure.ac" ]; then (cd "servant" && autoreconf -i); fi   - if [ -f "servant-client/configure.ac" ]; then (cd "servant-client" && autoreconf -i); fi   - if [ -f "servant-docs/configure.ac" ]; then (cd "servant-docs" && autoreconf -i); fi   - if [ -f "servant-server/configure.ac" ]; then (cd "servant-server" && autoreconf -i); fi-  - rm -f cabal.project.freeze-  - ${CABAL} new-freeze -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project.empty-line" --dry-  - "cat \"cabal.project.empty-line.freeze\" | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"-  - rm  "cabal.project.empty-line.freeze"-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project.empty-line" --dep -j2 all-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks --project-file="cabal.project.empty-line" --dep -j2 all-  - rm -rf .ghc.environment.* "servant"/dist "servant-client"/dist "servant-docs"/dist "servant-server"/dist-  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)--# 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.+  - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output+  - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"+  - rm  cabal.project.freeze+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all | color_cabal_output+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output script:-  # test that source-distributions can be generated-  - ${CABAL} new-sdist all+  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)+  # Packaging...+  - ${CABAL} v2-sdist all | color_cabal_output+  # Unpacking...   - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/   - cd ${DISTDIR} || false-  - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;-  - rm -f cabal.project+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm       '{}' \;+  - PKGDIR_servant="$(find . -maxdepth 1 -type d -regex '.*/servant-[0-9.]*')"+  - PKGDIR_servant_client="$(find . -maxdepth 1 -type d -regex '.*/servant-client-[0-9.]*')"+  - PKGDIR_servant_docs="$(find . -maxdepth 1 -type d -regex '.*/servant-docs-[0-9.]*')"+  - PKGDIR_servant_server="$(find . -maxdepth 1 -type d -regex '.*/servant-server-[0-9.]*')"+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"servant-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-client-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-docs-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-server-*/*.cabal\"\\n' >> cabal.project"-  - "echo 'constraints: foundatiion >= 0.14' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant' >> cabal.project"-  - "echo 'allow-newer: servant-js:servant-foreign' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - |+    echo "packages: ${PKGDIR_servant}" >> cabal.project+    echo "packages: ${PKGDIR_servant_client}" >> cabal.project+    echo "packages: ${PKGDIR_servant_docs}" >> cabal.project+    echo "packages: ${PKGDIR_servant_server}" >> cabal.project+  - |+    echo "constraints: foundatiion >= 0.14"        >> cabal.project+    echo "allow-newer: servant-js:servant"         >> cabal.project+    echo "allow-newer: servant-js:servant-foreign" >> cabal.project+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(servant|servant-client|servant-docs|servant-server)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true+  # Building...   # this builds all libraries and executables (without tests/benchmarks)-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all-+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output+  # Building with tests and benchmarks...   # build & run tests, build benchmarks-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} all-  - if [ "x$TEST" = "x--enable-tests" ]; then ${CABAL} new-test -w ${HC} ${TEST} ${BENCH} all; fi--  # cabal check-  - (cd servant-* && ${CABAL} check)-  - (cd servant-client-* && ${CABAL} check)-  - (cd servant-docs-* && ${CABAL} check)-  - (cd servant-server-* && ${CABAL} check)--  # haddock-  - ${CABAL} new-haddock -w ${HC} ${TEST} ${BENCH} all--  # Build without installed constraints for packages in global-db-  - rm -f cabal.project.local; ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all;+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Testing...+  - ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # cabal check...+  - (cd ${PKGDIR_servant} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_client} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_docs} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_server} && ${CABAL} -vnormal check)+  # haddock...+  - ${CABAL} v2-haddock $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Building without installed constraints for packages in global-db...+  - rm -f cabal.project.local+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output -# REGENDATA ["-o","cabal.project.empty-line.travis.yml","--ghc-head","cabal.project.empty-line"]+# REGENDATA ["-o","cabal.project.empty-line.travis.yml","--config=cabal.project.haskell-ci","--ghc-head","cabal.project.empty-line"] # EOF
fixtures/cabal.project.fail-versions.stderr view
@@ -1,3 +1,3 @@-*ERROR* servant-client-core is missing tested-with annotations for: 7.8.1,7.8.2,7.8.3,7.8.4-*ERROR* servant-foreign is missing tested-with annotations for: 7.8.1,7.8.2,7.8.3,7.8.4-*ERROR* tutorial is missing tested-with annotations for: 7.8.1,7.8.2,7.8.3,7.8.4+*ERROR* servant-client-core is missing tested-with annotations for: ghc-7.8.1,ghc-7.8.2,ghc-7.8.3,ghc-7.8.4+*ERROR* servant-foreign is missing tested-with annotations for: ghc-7.8.1,ghc-7.8.2,ghc-7.8.3,ghc-7.8.4+*ERROR* tutorial is missing tested-with annotations for: ghc-7.8.1,ghc-7.8.2,ghc-7.8.3,ghc-7.8.4
+ fixtures/cabal.project.haskell-ci view
@@ -0,0 +1,2 @@+-- Common configuration options for .travis.yml files in fixtures/+insert-version: False
fixtures/cabal.project.messy.stderr view
@@ -1,1 +1,1 @@-*INFO* Generating Travis-CI config for testing for GHC versions: head 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4+*INFO* Generating Travis-CI config for testing for GHC versions: ghc-head 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4 8.6.5 8.8.1
fixtures/cabal.project.messy.travis.yml view
@@ -1,22 +1,18 @@ # This Travis job script has been generated by a script via #-#   haskell-ci '-o' 'cabal.project.messy.travis.yml' '--ghc-head' '--apt=fftw3-dev' '--installed=-all +deepseq' 'cabal.project.messy'+#   haskell-ci '-o' 'cabal.project.messy.travis.yml' '--config=cabal.project.haskell-ci' '--ghc-head' '--apt=fftw3-dev' '--installed=-all +deepseq' 'cabal.project.messy' # # For more information, see https://github.com/haskell-CI/haskell-ci #-# version: 0.2.1-# language: c dist: xenial- git:-  submodules: false  # whether to recursively clone submodules-+  # whether to recursively clone submodules+  submodules: false cache:   directories:     - $HOME/.cabal/packages     - $HOME/.cabal/store- before_cache:   - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log   # remove files that are regenerated by 'cabal update'@@ -25,156 +21,188 @@   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx-   - rm -rfv $CABALHOME/packages/head.hackage- matrix:   include:-    - compiler: "ghc-8.6.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.4,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.3,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.2,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.6.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.1,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.4,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.3,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.2,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.1,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.2,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.1,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.2,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.1,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.3,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.2,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-7.10.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.10.1,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.4,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.3"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.3,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.2,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-7.8.1"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-7.8.1,fftw3-dev], sources: [hvr-ghc]}}-    - compiler: "ghc-head"-      env: GHCHEAD=true-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-head,fftw3-dev], sources: [hvr-ghc]}}-+    - compiler: ghc-8.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.8.1","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.6.5+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.6.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.4","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.6.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.3","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.6.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.2","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.6.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.1","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.4.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.4.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.3","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.4.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.2","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.4.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.1","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.2.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.2.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.1","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.0.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-8.0.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.1","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-7.10.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.3","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-7.10.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.2","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-7.10.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.1","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-7.8.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.4","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-7.8.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.3","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-7.8.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.2","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-7.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.1","cabal-install-3.0","fftw3-dev"]}}+    - compiler: ghc-head+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-head","cabal-install-head","fftw3-dev"]}}   allow_failures:-    - compiler: "ghc-head"-+    - compiler: ghc-head before_install:-  - HC=/opt/ghc/bin/${CC}-  - HCPKG=${HC/ghc/ghc-pkg}+  - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')+  - WITHCOMPILER="-w $HC"+  - HCPKG="$HC-pkg"   - unset CC   - CABAL=/opt/ghc/bin/cabal   - CABALHOME=$HOME/.cabal   - export PATH="$CABALHOME/bin:$PATH"-  - ROOTDIR=$(pwd)-  - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))+  - TOP=$(pwd)+  - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"   - echo $HCNUMVER-+  - CABAL="$CABAL -vnormal+nowrap+markoutput"+  - set -o pipefail+  - |+    echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }'           >> .colorful.awk+    echo 'BEGIN { state = "output"; }'                                     >> .colorful.awk+    echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }'            >> .colorful.awk+    echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }'             >> .colorful.awk+    echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk+    echo '  if (state == "cabal") {'                                       >> .colorful.awk+    echo '    print blue($0)'                                              >> .colorful.awk+    echo '  } else {'                                                      >> .colorful.awk+    echo '    print $0'                                                    >> .colorful.awk+    echo '  }'                                                             >> .colorful.awk+    echo '}'                                                               >> .colorful.awk+  - cat .colorful.awk+  - |+    color_cabal_output () {+      awk -f $TOP/.colorful.awk+    }+  - echo text | color_cabal_output install:   - ${CABAL} --version   - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"   - TEST=--enable-tests   - BENCH=--enable-benchmarks-  - GHCHEAD=${GHCHEAD-false}-  - travis_retry ${CABAL} update -v-  - sed -i.bak 's/^jobs:/-- jobs:/' $CABALHOME/config-  - rm -fv cabal.project cabal.project.local-  # Overlay Hackage Package Index for GHC HEAD: https://github.com/hvr/head.hackage+  - HEADHACKAGE=false+  - if [ $HCNUMVER -gt 80801 ] ; then HEADHACKAGE=true ; fi+  - rm -f $CABALHOME/config   - |-    if $GHCHEAD; then-      sed -i 's/-- allow-newer: .*/allow-newer: *:base/' $CABALHOME/config-      for pkg in $($HCPKG list --simple-output); do pkg=$(echo $pkg | sed 's/-[^-]*$//'); sed -i "s/allow-newer: /allow-newer: *:$pkg, /" $CABALHOME/config; done--      echo 'repository head.hackage'                                                        >> $CABALHOME/config-      echo '   url: http://head.hackage.haskell.org/'                                       >> $CABALHOME/config-      echo '   secure: True'                                                                >> $CABALHOME/config-      echo '   root-keys: 07c59cb65787dedfaef5bd5f987ceb5f7e5ebf88b904bbd4c5cbdeb2ff71b740' >> $CABALHOME/config-      echo '              2e8555dde16ebd8df076f1a8ef13b8f14c66bad8eafefd7d9e37d0ed711821fb' >> $CABALHOME/config-      echo '              8f79fd2389ab2967354407ec852cbe73f2e8635793ac446d09461ffb99527f6e' >> $CABALHOME/config-      echo '   key-threshold: 3'                                                            >> $CABALHOME.config--      grep -Ev -- '^\s*--' $CABALHOME/config | grep -Ev '^\s*$'--      ${CABAL} new-update head.hackage -v+    echo "verbose: normal +nowrap +markoutput"          >> $CABALHOME/config+    echo "remote-build-reporting: anonymous"            >> $CABALHOME/config+    echo "write-ghc-environment-files: always"          >> $CABALHOME/config+    echo "remote-repo-cache: $CABALHOME/packages"       >> $CABALHOME/config+    echo "logs-dir:          $CABALHOME/logs"           >> $CABALHOME/config+    echo "world-file:        $CABALHOME/world"          >> $CABALHOME/config+    echo "extra-prog-path:   $CABALHOME/bin"            >> $CABALHOME/config+    echo "symlink-bindir:    $CABALHOME/bin"            >> $CABALHOME/config+    echo "installdir:        $CABALHOME/bin"            >> $CABALHOME/config+    echo "build-summary:     $CABALHOME/logs/build.log" >> $CABALHOME/config+    echo "store-dir:         $CABALHOME/store"          >> $CABALHOME/config+    echo "install-dirs user"                            >> $CABALHOME/config+    echo "  prefix: $CABALHOME"                         >> $CABALHOME/config+    echo "repository hackage.haskell.org"               >> $CABALHOME/config+    echo "  url: http://hackage.haskell.org/"           >> $CABALHOME/config+  - |+    if $HEADHACKAGE; then+    echo "allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\1/g')" >> $CABALHOME/config+    echo "repository head.hackage.ghc.haskell.org"                                        >> $CABALHOME/config+    echo "   url: https://ghc.gitlab.haskell.org/head.hackage/"                           >> $CABALHOME/config+    echo "   secure: True"                                                                >> $CABALHOME/config+    echo "   root-keys: 7541f32a4ccca4f97aea3b22f5e593ba2c0267546016b992dfadcd2fe944e55d" >> $CABALHOME/config+    echo "              26021a13b401500c8eb2761ca95c61f2d625bfef951b939a8124ed12ecf07329" >> $CABALHOME/config+    echo "              f76d08be13e9a61a377a85e2fb63f4c5435d40f8feb3e12eb05905edb8cdea89" >> $CABALHOME/config+    echo "   key-threshold: 3"                                                            >> $CABALHOME/config     fi-  - grep -Ev -- '^\s*--' $CABALHOME/config | grep -Ev '^\s*$'-  - rm -f cabal.project+  - cat $CABALHOME/config+  - rm -fv cabal.project cabal.project.local cabal.project.freeze+  - travis_retry ${CABAL} v2-update -v+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"servant\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-client\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-docs\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-server\"\\n' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in deepseq; do echo \"constraints: $pkg installed\" >> cabal.project >> cabal.project.local; done"+  - |+    echo "packages: servant" >> cabal.project+    echo "packages: servant-client" >> cabal.project+    echo "packages: servant-docs" >> cabal.project+    echo "packages: servant-server" >> cabal.project+  - |+  - "for pkg in deepseq; do echo \"constraints: $pkg installed\" >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true   - if [ -f "servant/configure.ac" ]; then (cd "servant" && autoreconf -i); fi   - if [ -f "servant-client/configure.ac" ]; then (cd "servant-client" && autoreconf -i); fi   - if [ -f "servant-docs/configure.ac" ]; then (cd "servant-docs" && autoreconf -i); fi   - if [ -f "servant-server/configure.ac" ]; then (cd "servant-server" && autoreconf -i); fi-  - rm -f cabal.project.freeze-  - ${CABAL} new-freeze -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project.messy" --dry-  - "cat \"cabal.project.messy.freeze\" | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"-  - rm  "cabal.project.messy.freeze"-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project.messy" --dep -j2 all-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks --project-file="cabal.project.messy" --dep -j2 all-  - rm -rf .ghc.environment.* "servant"/dist "servant-client"/dist "servant-docs"/dist "servant-server"/dist-  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)--# 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.+  - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output+  - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"+  - rm  cabal.project.freeze+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all | color_cabal_output+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output script:-  # test that source-distributions can be generated-  - ${CABAL} new-sdist all+  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)+  # Packaging...+  - ${CABAL} v2-sdist all | color_cabal_output+  # Unpacking...   - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/   - cd ${DISTDIR} || false-  - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;-  - rm -f cabal.project+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm       '{}' \;+  - PKGDIR_servant="$(find . -maxdepth 1 -type d -regex '.*/servant-[0-9.]*')"+  - PKGDIR_servant_client="$(find . -maxdepth 1 -type d -regex '.*/servant-client-[0-9.]*')"+  - PKGDIR_servant_docs="$(find . -maxdepth 1 -type d -regex '.*/servant-docs-[0-9.]*')"+  - PKGDIR_servant_server="$(find . -maxdepth 1 -type d -regex '.*/servant-server-[0-9.]*')"+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"servant-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-client-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-docs-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'packages: \"servant-server-*/*.cabal\"\\n' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in deepseq; do echo \"constraints: $pkg installed\" >> cabal.project >> cabal.project.local; done"+  - |+    echo "packages: ${PKGDIR_servant}" >> cabal.project+    echo "packages: ${PKGDIR_servant_client}" >> cabal.project+    echo "packages: ${PKGDIR_servant_docs}" >> cabal.project+    echo "packages: ${PKGDIR_servant_server}" >> cabal.project+  - |+  - "for pkg in deepseq; do echo \"constraints: $pkg installed\" >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true+  # Building...   # this builds all libraries and executables (without tests/benchmarks)-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all-+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output+  # Building with tests and benchmarks...   # build & run tests, build benchmarks-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} all-  - if [ "x$TEST" = "x--enable-tests" ]; then ${CABAL} new-test -w ${HC} ${TEST} ${BENCH} all; fi--  # cabal check-  - (cd servant-* && ${CABAL} check)-  - (cd servant-client-* && ${CABAL} check)-  - (cd servant-docs-* && ${CABAL} check)-  - (cd servant-server-* && ${CABAL} check)--  # haddock-  - ${CABAL} new-haddock -w ${HC} ${TEST} ${BENCH} all--  # Build without installed constraints for packages in global-db-  - rm -f cabal.project.local; ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all;+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Testing...+  - ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # cabal check...+  - (cd ${PKGDIR_servant} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_client} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_docs} && ${CABAL} -vnormal check)+  - (cd ${PKGDIR_servant_server} && ${CABAL} -vnormal check)+  # haddock...+  - ${CABAL} v2-haddock $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Building without installed constraints for packages in global-db...+  - rm -f cabal.project.local+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output -# REGENDATA ["-o","cabal.project.messy.travis.yml","--ghc-head","--apt=fftw3-dev","--installed=-all +deepseq","cabal.project.messy"]+# REGENDATA ["-o","cabal.project.messy.travis.yml","--config=cabal.project.haskell-ci","--ghc-head","--apt=fftw3-dev","--installed=-all +deepseq","cabal.project.messy"] # EOF
+ fixtures/cabal.project.travis-patch view
@@ -0,0 +1,1 @@+packages: servant
+ fixtures/cabal.project.travis-patch.patch view
@@ -0,0 +1,13 @@+diff --git a/fixtures/cabal.project.travis-patch.travis.yml b/fixtures/cabal.project.travis-patch.travis.yml+index 9a725c1..0554fed 100644+--- a/fixtures/cabal.project.travis-patch.travis.yml++++ b/fixtures/cabal.project.travis-patch.travis.yml+@@ -8,7 +8,7 @@+ #+ language: c+ dist: xenial+-git:++ git:+   # whether to recursively clone submodules+   submodules: false+ cache:
+ fixtures/cabal.project.travis-patch.stderr view
@@ -0,0 +1,1 @@+*INFO* Generating Travis-CI config for testing for GHC versions: 7.8.1 7.8.2 7.8.3 7.8.4 7.10.1 7.10.2 7.10.3 8.0.1 8.0.2 8.2.1 8.2.2 8.4.1 8.4.2 8.4.3 8.4.4 8.6.1 8.6.2 8.6.3 8.6.4 8.6.5 8.8.1
+ fixtures/cabal.project.travis-patch.travis.yml view
@@ -0,0 +1,177 @@+# This Travis job script has been generated by a script via+#+#   haskell-ci '--config=cabal.project.haskell-ci' '--travis-patches=cabal.project.travis-patch.patch' 'cabal.project.travis-patch'+#+# For more information, see https://github.com/haskell-CI/haskell-ci+#+language: c+dist: xenial+ git:+  # whether to recursively clone submodules+  submodules: false+cache:+  directories:+    - $HOME/.cabal/packages+    - $HOME/.cabal/store+before_cache:+  - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log+  # remove files that are regenerated by 'cabal update'+  - rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.*+  - rm -fv $CABALHOME/packages/hackage.haskell.org/*.json+  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache+  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar+  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx+  - rm -rfv $CABALHOME/packages/head.hackage+matrix:+  include:+    - compiler: ghc-8.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.8.1","cabal-install-3.0"]}}+    - compiler: ghc-8.6.5+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-3.0"]}}+    - compiler: ghc-8.6.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.4","cabal-install-3.0"]}}+    - compiler: ghc-8.6.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.3","cabal-install-3.0"]}}+    - compiler: ghc-8.6.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.2","cabal-install-3.0"]}}+    - compiler: ghc-8.6.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.1","cabal-install-3.0"]}}+    - compiler: ghc-8.4.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-3.0"]}}+    - compiler: ghc-8.4.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.3","cabal-install-3.0"]}}+    - compiler: ghc-8.4.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.2","cabal-install-3.0"]}}+    - compiler: ghc-8.4.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.1","cabal-install-3.0"]}}+    - compiler: ghc-8.2.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-3.0"]}}+    - compiler: ghc-8.2.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.1","cabal-install-3.0"]}}+    - compiler: ghc-8.0.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-3.0"]}}+    - compiler: ghc-8.0.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.1","cabal-install-3.0"]}}+    - compiler: ghc-7.10.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.3","cabal-install-3.0"]}}+    - compiler: ghc-7.10.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.2","cabal-install-3.0"]}}+    - compiler: ghc-7.10.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.1","cabal-install-3.0"]}}+    - compiler: ghc-7.8.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.4","cabal-install-3.0"]}}+    - compiler: ghc-7.8.3+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.3","cabal-install-3.0"]}}+    - compiler: ghc-7.8.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.2","cabal-install-3.0"]}}+    - compiler: ghc-7.8.1+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.1","cabal-install-3.0"]}}+before_install:+  - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')+  - WITHCOMPILER="-w $HC"+  - HCPKG="$HC-pkg"+  - unset CC+  - CABAL=/opt/ghc/bin/cabal+  - CABALHOME=$HOME/.cabal+  - export PATH="$CABALHOME/bin:$PATH"+  - TOP=$(pwd)+  - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"+  - echo $HCNUMVER+  - CABAL="$CABAL -vnormal+nowrap+markoutput"+  - set -o pipefail+  - |+    echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }'           >> .colorful.awk+    echo 'BEGIN { state = "output"; }'                                     >> .colorful.awk+    echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }'            >> .colorful.awk+    echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }'             >> .colorful.awk+    echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk+    echo '  if (state == "cabal") {'                                       >> .colorful.awk+    echo '    print blue($0)'                                              >> .colorful.awk+    echo '  } else {'                                                      >> .colorful.awk+    echo '    print $0'                                                    >> .colorful.awk+    echo '  }'                                                             >> .colorful.awk+    echo '}'                                                               >> .colorful.awk+  - cat .colorful.awk+  - |+    color_cabal_output () {+      awk -f $TOP/.colorful.awk+    }+  - echo text | color_cabal_output+install:+  - ${CABAL} --version+  - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"+  - TEST=--enable-tests+  - BENCH=--enable-benchmarks+  - HEADHACKAGE=false+  - rm -f $CABALHOME/config+  - |+    echo "verbose: normal +nowrap +markoutput"          >> $CABALHOME/config+    echo "remote-build-reporting: anonymous"            >> $CABALHOME/config+    echo "write-ghc-environment-files: always"          >> $CABALHOME/config+    echo "remote-repo-cache: $CABALHOME/packages"       >> $CABALHOME/config+    echo "logs-dir:          $CABALHOME/logs"           >> $CABALHOME/config+    echo "world-file:        $CABALHOME/world"          >> $CABALHOME/config+    echo "extra-prog-path:   $CABALHOME/bin"            >> $CABALHOME/config+    echo "symlink-bindir:    $CABALHOME/bin"            >> $CABALHOME/config+    echo "installdir:        $CABALHOME/bin"            >> $CABALHOME/config+    echo "build-summary:     $CABALHOME/logs/build.log" >> $CABALHOME/config+    echo "store-dir:         $CABALHOME/store"          >> $CABALHOME/config+    echo "install-dirs user"                            >> $CABALHOME/config+    echo "  prefix: $CABALHOME"                         >> $CABALHOME/config+    echo "repository hackage.haskell.org"               >> $CABALHOME/config+    echo "  url: http://hackage.haskell.org/"           >> $CABALHOME/config+  - cat $CABALHOME/config+  - rm -fv cabal.project cabal.project.local cabal.project.freeze+  - travis_retry ${CABAL} v2-update -v+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze+  - touch cabal.project+  - |+    echo "packages: servant" >> cabal.project+  - |+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(servant)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - cat cabal.project || true+  - cat cabal.project.local || true+  - if [ -f "servant/configure.ac" ]; then (cd "servant" && autoreconf -i); fi+  - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output+  - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"+  - rm  cabal.project.freeze+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all | color_cabal_output+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output+script:+  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)+  # Packaging...+  - ${CABAL} v2-sdist all | color_cabal_output+  # Unpacking...+  - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/+  - cd ${DISTDIR} || false+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm       '{}' \;+  - PKGDIR_servant="$(find . -maxdepth 1 -type d -regex '.*/servant-[0-9.]*')"+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze+  - touch cabal.project+  - |+    echo "packages: ${PKGDIR_servant}" >> cabal.project+  - |+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(servant)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - cat cabal.project || true+  - cat cabal.project.local || true+  # Building...+  # this builds all libraries and executables (without tests/benchmarks)+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output+  # Building with tests and benchmarks...+  # build & run tests, build benchmarks+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Testing...+  - ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # cabal check...+  - (cd ${PKGDIR_servant} && ${CABAL} -vnormal check)+  # haddock...+  - ${CABAL} v2-haddock $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Building without installed constraints for packages in global-db...+  - rm -f cabal.project.local+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output++# REGENDATA ["--config=cabal.project.haskell-ci","--travis-patches=cabal.project.travis-patch.patch","cabal.project.travis-patch"]+# EOF
fixtures/haskell-ci.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               haskell-ci-version:            0.2.1+version:            0.4 synopsis:           Cabal package script generator for Travis-CI description:   Script generator (@haskell-ci@) for [Travis-CI](https://travis-ci.org/) for continuous-integration testing of Haskell Cabal packages.@@ -13,6 +13,7 @@   * Runs tests and builds benchmarks   * Generates Haddocks   * macOS (OSX) support+  * GHCJS support   * building with specific constraints   .   === Quick Start Guide@@ -23,16 +24,17 @@  homepage:           https://haskell-ci.rtfd.org/ bug-reports:        https://github.com/haskell-CI/haskell-ci/issues-license:            BSD-3-Clause+license:            GPL-3.0-or-later license-file:       LICENSE author:             Herbert Valerio Riedel, Oleg Grenrus maintainer:         hvr@gnu.org category:           Development build-type:         Simple-tested-with:        GHC ==8.6.4 || ==8.4.4 || ==8.2.2 || ==8.0.2+tested-with:        GHC ==8.6.5 || ==8.4.4 || ==8.2.2 extra-source-files:   CHANGELOG.md   fixtures/cabal.haskell-ci+  fixtures/cabal.project.haskell-ci   fixtures/cabal.project.fail-versions   fixtures/cabal.project.fail-versions.stderr   fixtures/haskell-ci.cabal@@ -53,6 +55,10 @@   fixtures/cabal.project.copy-fields.all.travis.yml   fixtures/cabal.project.copy-fields.some.travis.yml   fixtures/cabal.project.copy-fields.none.travis.yml+  fixtures/cabal.project.travis-patch+  fixtures/cabal.project.travis-patch.patch+  fixtures/cabal.project.travis-patch.stderr+  fixtures/cabal.project.travis-patch.travis.yml   fixtures/servant-client-core/*.cabal   fixtures/servant-client/*.cabal   fixtures/servant-docs/*.cabal@@ -73,6 +79,7 @@   exposed-modules:     HaskellCI     HaskellCI.Cli+    HaskellCI.Compiler     HaskellCI.Config     HaskellCI.Config.ConstraintSet     HaskellCI.Config.CopyFields@@ -82,10 +89,12 @@     HaskellCI.Config.HLint     HaskellCI.Config.Installed     HaskellCI.Config.Jobs-    HaskellCI.Extras-    HaskellCI.GHC+    HaskellCI.Config.Ubuntu+    HaskellCI.Diagnostics     HaskellCI.Glob-    HaskellCI.MakeTravisOutput+    HaskellCI.Jobs+    HaskellCI.List+    HaskellCI.MonadErr     HaskellCI.Newtypes     HaskellCI.Optimization     HaskellCI.OptionsGrammar@@ -93,22 +102,32 @@     HaskellCI.Package     HaskellCI.ParsecError     HaskellCI.ParsecUtils+    HaskellCI.Prelude     HaskellCI.Project+    HaskellCI.Sh+    HaskellCI.ShVersionRange     HaskellCI.TestedWith-    HaskellCI.Version+    HaskellCI.Tools+    HaskellCI.Travis+    HaskellCI.Travis.Yaml+    HaskellCI.YamlSyntax -  -- vendored from Cabal development version-  other-modules:      Distribution.Fields.Pretty   ghc-options:     -Wall -Wcompat -Wnoncanonical-monad-instances     -Wnoncanonical-monadfail-instances    hs-source-dirs:     src   default-extensions:+    BangPatterns+    NoImplicitPrelude+    DeriveAnyClass     DeriveFoldable     DeriveFunctor     DeriveGeneric     DeriveTraversable+    DerivingStrategies+    GeneralizedNewtypeDeriving+    ScopedTypeVariables    other-extensions:     CPP@@ -117,35 +136,44 @@     ViewPatterns    build-depends:-    , base          >=4.9      && <4.13+    , base          >=4.10     && <4.13     , bytestring    ^>=0.10.8.1-    , Cabal         ^>=2.4+    , Cabal         ^>=3.0     , containers    ^>=0.5.7.1 || ^>=0.6.0.1     , deepseq       ^>=1.4.2.0     , directory     ^>=1.3.0.0     , filepath      ^>=1.4.1.1+    , mtl           >=2.2.2     , parsec        ^>=3.1.13.0     , pretty        ^>=1.1.3.3+    , process       ^>=1.4.3.0 || ^>=1.6.1.0     , text          ^>=1.2.3.0     , transformers  ^>=0.5.2.0 +  if !impl(ghc >=8.2)+    build-depends: bifunctors ^>=5.5.4+   -- other dependencies   build-depends:+    , aeson                 ^>=1.4.2.0     , base-compat           ^>=0.10.5+    , exceptions            ^>=0.10.0     , generic-lens          ^>=1.1.0.0     , HsYAML                ^>=0.1.1.3+    , lattices              ^>=2     , microlens             ^>=0.4.10     , optparse-applicative  ^>=0.14.3.0+    , temporary             ^>=1.3+    , unordered-containers  ^>=0.2.10.0    default-language:   Haskell2010    -- ShellCheck. Would need newer transformers for older GHC   if (flag(shellcheck) && impl(ghc >=7.10 && <8.7))-    build-depends: ShellCheck ==0.6.0+    build-depends: ShellCheck ==0.7.0  executable haskell-ci   main-is:          Main.hs-  ghc-options:      -Wall   hs-source-dirs:   cli   build-depends:     , base@@ -158,14 +186,14 @@   main-is:          Tests.hs   hs-source-dirs:   test   build-depends:-    , ansi-terminal        ^>=0.8.0.2+    , ansi-terminal        ^>=0.8.0.2 || ^>=0.9.1     , base     , bytestring     , Diff                 ^>=0.3.4     , directory     , filepath     , haskell-ci-internal-    , tasty                >=1.0     && <1.2+    , tasty                >=1.0     && <1.3     , tasty-golden         ^>=2.3.1.1     , transformers 
fixtures/haskell-ci.cabal.stderr view
@@ -1,2 +1,2 @@-*INFO* Generating Travis-CI config for testing for GHC versions: head 8.0.2 8.2.2 8.4.4 8.6.4-*INFO* Also OSX jobs for: 8.4.4+*INFO* Generating Travis-CI config for testing for GHC versions: ghc-head 8.2.2 8.4.4 8.6.5+*INFO* Also OSX jobs for: 8.4.4 8.6.5
fixtures/haskell-ci.cabal.travis.yml view
@@ -1,27 +1,22 @@ # This Travis job script has been generated by a script via #-#   haskell-ci '--output=.travis.yml' '--config=cabal.haskell-ci' 'haskell-ci.cabal'+#   haskell-ci '--config=cabal.haskell-ci' 'cabal.project' # # For more information, see https://github.com/haskell-CI/haskell-ci #-# version: 0.2.1-# language: c dist: xenial- git:-  submodules: false  # whether to recursively clone submodules-+  # whether to recursively clone submodules+  submodules: false branches:   only:     - master- cache:   directories:     - $HOME/.cabal/packages     - $HOME/.cabal/store     - $HOME/.ghc-install- before_cache:   - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log   # remove files that are regenerated by 'cabal update'@@ -30,146 +25,175 @@   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar   - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx-   - rm -rfv $CABALHOME/packages/head.hackage- matrix:   include:-    - compiler: "ghc-8.6.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.6.4], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.4], sources: [hvr-ghc]}}-    - compiler: "ghc-8.2.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.2.2], sources: [hvr-ghc]}}-    - compiler: "ghc-8.0.2"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.0.2], sources: [hvr-ghc]}}-    - compiler: "ghc-head"-      env: GHCHEAD=true-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-head], sources: [hvr-ghc]}}-    - compiler: "ghc-8.4.4"-      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.4,ghc-8.4.4], sources: [hvr-ghc]}}+    - compiler: ghc-8.6.5+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-3.0"]}}+    - compiler: ghc-8.4.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-3.0"]}}+    - compiler: ghc-8.2.2+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-3.0"]}}+    - compiler: ghc-head+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-head","cabal-install-head"]}}+    - compiler: ghc-8.6.5+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-3.0"]}}       os: osx-+    - compiler: ghc-8.4.4+      addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-3.0"]}}+      os: osx   allow_failures:-    - compiler: "ghc-head"-+    - compiler: ghc-head before_install:-  - HC=/opt/ghc/bin/${CC}-  - HCPKG=${HC/ghc/ghc-pkg}+  - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')+  - WITHCOMPILER="-w $HC"+  - HCPKG="$HC-pkg"   - unset CC   - CABAL=/opt/ghc/bin/cabal   - CABALHOME=$HOME/.cabal   - export PATH="$CABALHOME/bin:$PATH"-  - ROOTDIR=$(pwd)+  - TOP=$(pwd)   - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; brew upgrade python@3; curl https://haskell.futurice.com/haskell-on-macos.py | python3 - --make-dirs --install-dir=$HOME/.ghc-install --cabal-alias=head install cabal-install-head ${TRAVIS_COMPILER}; fi-  - if [ "$TRAVIS_OS_NAME" = "osx" ]; then HC=$HOME/.ghc-install/ghc/bin/$TRAVIS_COMPILER; HCPKG=${HC/ghc/ghc-pkg}; CABAL=$HOME/.ghc-install/ghc/bin/cabal; fi-  - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))+  - if [ "$TRAVIS_OS_NAME" = "osx" ]; then HC=$HOME/.ghc-install/ghc/bin/$TRAVIS_COMPILER; WITHCOMPILER="-w $HC"; HCPKG=${HC/ghc/ghc-pkg}; CABAL=$HOME/.ghc-install/ghc/bin/cabal; fi+  - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"   - echo $HCNUMVER-+  - CABAL="$CABAL -vnormal+nowrap+markoutput"+  - set -o pipefail+  - |+    echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }'           >> .colorful.awk+    echo 'BEGIN { state = "output"; }'                                     >> .colorful.awk+    echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }'            >> .colorful.awk+    echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }'             >> .colorful.awk+    echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk+    echo '  if (state == "cabal") {'                                       >> .colorful.awk+    echo '    print blue($0)'                                              >> .colorful.awk+    echo '  } else {'                                                      >> .colorful.awk+    echo '    print $0'                                                    >> .colorful.awk+    echo '  }'                                                             >> .colorful.awk+    echo '}'                                                               >> .colorful.awk+  - cat .colorful.awk+  - |+    color_cabal_output () {+      awk -f $TOP/.colorful.awk+    }+  - echo text | color_cabal_output install:   - ${CABAL} --version   - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"   - TEST=--enable-tests   - BENCH=--enable-benchmarks-  - GHCHEAD=${GHCHEAD-false}-  - travis_retry ${CABAL} update -v-  - sed -i.bak 's/^jobs:/-- jobs:/' $CABALHOME/config-  - rm -fv cabal.project cabal.project.local-  - "sed -i.bak 's/^-- jobs:.*/jobs: 2/' $CABALHOME/config"-  - "sed -i.bak 's/-- ghc-options:.*/ghc-options: -j2/' $CABALHOME/config"-  # Overlay Hackage Package Index for GHC HEAD: https://github.com/hvr/head.hackage+  - HEADHACKAGE=false+  - if [ $HCNUMVER -gt 80605 ] ; then HEADHACKAGE=true ; fi+  - rm -f $CABALHOME/config   - |-    if $GHCHEAD; then-      sed -i 's/-- allow-newer: .*/allow-newer: *:base/' $CABALHOME/config-      for pkg in $($HCPKG list --simple-output); do pkg=$(echo $pkg | sed 's/-[^-]*$//'); sed -i "s/allow-newer: /allow-newer: *:$pkg, /" $CABALHOME/config; done--      echo 'repository head.hackage'                                                        >> $CABALHOME/config-      echo '   url: http://head.hackage.haskell.org/'                                       >> $CABALHOME/config-      echo '   secure: True'                                                                >> $CABALHOME/config-      echo '   root-keys: 07c59cb65787dedfaef5bd5f987ceb5f7e5ebf88b904bbd4c5cbdeb2ff71b740' >> $CABALHOME/config-      echo '              2e8555dde16ebd8df076f1a8ef13b8f14c66bad8eafefd7d9e37d0ed711821fb' >> $CABALHOME/config-      echo '              8f79fd2389ab2967354407ec852cbe73f2e8635793ac446d09461ffb99527f6e' >> $CABALHOME/config-      echo '   key-threshold: 3'                                                            >> $CABALHOME.config--      grep -Ev -- '^\s*--' $CABALHOME/config | grep -Ev '^\s*$'--      ${CABAL} new-update head.hackage -v+    echo "verbose: normal +nowrap +markoutput"          >> $CABALHOME/config+    echo "remote-build-reporting: anonymous"            >> $CABALHOME/config+    echo "write-ghc-environment-files: always"          >> $CABALHOME/config+    echo "remote-repo-cache: $CABALHOME/packages"       >> $CABALHOME/config+    echo "logs-dir:          $CABALHOME/logs"           >> $CABALHOME/config+    echo "world-file:        $CABALHOME/world"          >> $CABALHOME/config+    echo "extra-prog-path:   $CABALHOME/bin"            >> $CABALHOME/config+    echo "symlink-bindir:    $CABALHOME/bin"            >> $CABALHOME/config+    echo "installdir:        $CABALHOME/bin"            >> $CABALHOME/config+    echo "build-summary:     $CABALHOME/logs/build.log" >> $CABALHOME/config+    echo "store-dir:         $CABALHOME/store"          >> $CABALHOME/config+    echo "install-dirs user"                            >> $CABALHOME/config+    echo "  prefix: $CABALHOME"                         >> $CABALHOME/config+    echo "repository hackage.haskell.org"               >> $CABALHOME/config+    echo "  url: http://hackage.haskell.org/"           >> $CABALHOME/config+  - |+    if $HEADHACKAGE; then+    echo "allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\1/g')" >> $CABALHOME/config+    echo "repository head.hackage.ghc.haskell.org"                                        >> $CABALHOME/config+    echo "   url: https://ghc.gitlab.haskell.org/head.hackage/"                           >> $CABALHOME/config+    echo "   secure: True"                                                                >> $CABALHOME/config+    echo "   root-keys: 7541f32a4ccca4f97aea3b22f5e593ba2c0267546016b992dfadcd2fe944e55d" >> $CABALHOME/config+    echo "              26021a13b401500c8eb2761ca95c61f2d625bfef951b939a8124ed12ecf07329" >> $CABALHOME/config+    echo "              f76d08be13e9a61a377a85e2fb63f4c5435d40f8feb3e12eb05905edb8cdea89" >> $CABALHOME/config+    echo "   key-threshold: 3"                                                            >> $CABALHOME/config     fi-  - grep -Ev -- '^\s*--' $CABALHOME/config | grep -Ev '^\s*$'-  - ${CABAL} new-install -w ${HC} -j2 doctest --constraint='doctest ==0.16.*'-  - if [ $HCNUMVER -eq 80604 ] ; then ${CABAL} new-install -w ${HC} -j2 hlint --constraint='hlint ==2.1.*' ; fi-  - rm -f cabal.project+  - "echo 'jobs: 2' >> $CABALHOME/config"+  - |+    echo "program-default-options" >> $CABALHOME/config+    echo "  ghc-options: -j2"      >> $CABALHOME/config+  - cat $CABALHOME/config+  - rm -fv cabal.project cabal.project.local cabal.project.freeze+  - travis_retry ${CABAL} v2-update -v+  - (cd /tmp && ${CABAL} v2-install $WITHCOMPILER -j2 doctest --constraint='doctest ==0.16.*' | color_cabal_output)+  - if [ $HCNUMVER -ge 80600 ] && [ $HCNUMVER -lt 80606 ] ; then (cd /tmp && ${CABAL} v2-install $WITHCOMPILER -j2 hlint --constraint='hlint ==2.1.*' | color_cabal_output) ; fi+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \".\"\\n' >> cabal.project"-  - echo 'package haskell-ci' >> cabal.project-  - "echo '  ghc-options: -Werror' >> cabal.project"-  - "echo 'keep-going: False' >> cabal.project"-  - echo 'package bytestring' >> cabal.project-  - "echo '  tests: False' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(Cabal|haskell-ci)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - |+    echo "packages: ." >> cabal.project+  - |+    echo "package haskell-ci"     >> cabal.project+    echo "  ghc-options: -Werror" >> cabal.project+    echo ""                       >> cabal.project+    echo "keep-going: False"      >> cabal.project+    echo ""                       >> cabal.project+    echo "package bytestring"     >> cabal.project+    echo "  tests: False"         >> cabal.project+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(Cabal|haskell-ci)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true   - if [ -f "./configure.ac" ]; then (cd "." && autoreconf -i); fi-  - rm -f cabal.project.freeze-  - ${CABAL} new-freeze -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project" --dry-  - "cat \"cabal.project.freeze\" | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"-  - rm  "cabal.project.freeze"-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project" --dep -j2 all-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks --project-file="cabal.project" --dep -j2 all-  - rm -rf .ghc.environment.* "."/dist-  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)--# 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.+  - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output+  - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"+  - rm  cabal.project.freeze+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all | color_cabal_output+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output script:-  # test that source-distributions can be generated-  - ${CABAL} new-sdist all+  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)+  # Packaging...+  - ${CABAL} v2-sdist all | color_cabal_output+  # Unpacking...   - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/   - cd ${DISTDIR} || false-  - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;-  - rm -f cabal.project+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;+  - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm       '{}' \;+  - PKGDIR_haskell_ci="$(find . -maxdepth 1 -type d -regex '.*/haskell-ci-[0-9.]*')"+  # Generate cabal.project+  - rm -rf cabal.project cabal.project.local cabal.project.freeze   - touch cabal.project-  - "printf 'packages: \"haskell-ci-*/*.cabal\"\\n' >> cabal.project"-  - echo 'package haskell-ci' >> cabal.project-  - "echo '  ghc-options: -Werror' >> cabal.project"-  - "echo 'keep-going: False' >> cabal.project"-  - echo 'package bytestring' >> cabal.project-  - "echo '  tests: False' >> cabal.project"-  - "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-  - touch cabal.project.local-  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(Cabal|haskell-ci)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"+  - |+    echo "packages: ${PKGDIR_haskell_ci}" >> cabal.project+  - |+    echo "package haskell-ci"     >> cabal.project+    echo "  ghc-options: -Werror" >> cabal.project+    echo ""                       >> cabal.project+    echo "keep-going: False"      >> cabal.project+    echo ""                       >> cabal.project+    echo "package bytestring"     >> cabal.project+    echo "  tests: False"         >> cabal.project+  - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(Cabal|haskell-ci)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"   - cat cabal.project || true   - cat cabal.project.local || true+  # Building...   # this builds all libraries and executables (without tests/benchmarks)-  - ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all-+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output+  # Building with tests and benchmarks...   # build & run tests, build benchmarks-  - ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} all-  - if [ "x$TEST" = "x--enable-tests" ]; then ${CABAL} new-test -w ${HC} ${TEST} ${BENCH} all; fi--  # doctest-  - (cd haskell-ci-* && doctest --fast -XDeriveFoldable -XDeriveFunctor -XDeriveGeneric -XDeriveTraversable src)--  # hlint-  - if [ $HCNUMVER -eq 80604 ] ; then (cd haskell-ci-* && hlint -h ${ROOTDIR}/.hlint.yaml -XDeriveFoldable -XDeriveFunctor -XDeriveGeneric -XDeriveTraversable src) ; fi-  - if [ $HCNUMVER -eq 80604 ] ; then (cd haskell-ci-* && hlint -h ${ROOTDIR}/.hlint.yaml cli) ; fi--  # cabal check-  - (cd haskell-ci-* && ${CABAL} check)--  # Build without installed constraints for packages in global-db-  - rm -f cabal.project.local; ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all;-+  - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Testing...+  - ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output+  # Doctest...+  - (cd ${PKGDIR_haskell_ci} && doctest --fast -XBangPatterns -XNoImplicitPrelude -XDeriveAnyClass -XDeriveFoldable -XDeriveFunctor -XDeriveGeneric -XDeriveTraversable -XDerivingStrategies -XGeneralizedNewtypeDeriving -XScopedTypeVariables src)+  # HLint..+  - if [ $HCNUMVER -ge 80600 ] && [ $HCNUMVER -lt 80606 ] ; then (cd ${PKGDIR_haskell_ci} && hlint -h ${TOP}/.hlint.yaml -XBangPatterns -XNoImplicitPrelude -XDeriveAnyClass -XDeriveFoldable -XDeriveFunctor -XDeriveGeneric -XDeriveTraversable -XDerivingStrategies -XGeneralizedNewtypeDeriving -XScopedTypeVariables src) ; fi+  - if [ $HCNUMVER -ge 80600 ] && [ $HCNUMVER -lt 80606 ] ; then (cd ${PKGDIR_haskell_ci} && hlint -h ${TOP}/.hlint.yaml cli) ; fi+  # cabal check...+  - (cd ${PKGDIR_haskell_ci} && ${CABAL} -vnormal check)+  # Building without installed constraints for packages in global-db...+  - rm -f cabal.project.local+  - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output   # Constraint sets   - rm -rf cabal.project.local-   # Constraint set deepseq-1.4-  - echo Constraint set deepseq-1.4 && echo -en 'travis_fold:start:constraint-sets-deepseq-1.4\\r'-  - if [ $HCNUMVER -ge 70800 ] && [ $HCNUMVER -lt 71000 ]  ||  [ $HCNUMVER -eq 80202 ] ; then ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks  --constraint='deepseq ==1.4.*' all ; fi-+  - echo 'Constraint set deepseq-1.4' && echo -en 'travis_fold:start:constraint-sets-deepseq-1.4\\r'+  - if [ $HCNUMVER -lt 80400 ] ; then ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --constraint='deepseq ==1.4.*' --constraint='binary installed' all | color_cabal_output ; fi+  - if [ $HCNUMVER -lt 80400 ] ; then ${CABAL} v2-haddock $WITHCOMPILER --disable-tests --disable-benchmarks --constraint='deepseq ==1.4.*' --constraint='binary installed' all | color_cabal_output ; fi   - echo -en 'travis_fold:end:constraint-sets-deepseq-1.4\\r' -# REGENDATA ["--output=.travis.yml","--config=cabal.haskell-ci","haskell-ci.cabal"]+# REGENDATA ["--config=cabal.haskell-ci","cabal.project"] # EOF
haskell-ci.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               haskell-ci-version:            0.2.1+version:            0.4 synopsis:           Cabal package script generator for Travis-CI description:   Script generator (@haskell-ci@) for [Travis-CI](https://travis-ci.org/) for continuous-integration testing of Haskell Cabal packages.@@ -13,6 +13,7 @@   * Runs tests and builds benchmarks   * Generates Haddocks   * macOS (OSX) support+  * GHCJS support   * building with specific constraints   .   === Quick Start Guide@@ -23,16 +24,17 @@  homepage:           https://haskell-ci.rtfd.org/ bug-reports:        https://github.com/haskell-CI/haskell-ci/issues-license:            BSD-3-Clause+license:            GPL-3.0-or-later license-file:       LICENSE author:             Herbert Valerio Riedel, Oleg Grenrus maintainer:         hvr@gnu.org category:           Development build-type:         Simple-tested-with:        GHC ==8.6.4 || ==8.4.4 || ==8.2.2 || ==8.0.2+tested-with:        GHC ==8.6.5 || ==8.4.4 || ==8.2.2 extra-source-files:   CHANGELOG.md   fixtures/cabal.haskell-ci+  fixtures/cabal.project.haskell-ci   fixtures/cabal.project.fail-versions   fixtures/cabal.project.fail-versions.stderr   fixtures/haskell-ci.cabal@@ -53,6 +55,10 @@   fixtures/cabal.project.copy-fields.all.travis.yml   fixtures/cabal.project.copy-fields.some.travis.yml   fixtures/cabal.project.copy-fields.none.travis.yml+  fixtures/cabal.project.travis-patch+  fixtures/cabal.project.travis-patch.patch+  fixtures/cabal.project.travis-patch.stderr+  fixtures/cabal.project.travis-patch.travis.yml   fixtures/servant-client-core/*.cabal   fixtures/servant-client/*.cabal   fixtures/servant-docs/*.cabal@@ -73,6 +79,7 @@   exposed-modules:     HaskellCI     HaskellCI.Cli+    HaskellCI.Compiler     HaskellCI.Config     HaskellCI.Config.ConstraintSet     HaskellCI.Config.CopyFields@@ -82,10 +89,12 @@     HaskellCI.Config.HLint     HaskellCI.Config.Installed     HaskellCI.Config.Jobs-    HaskellCI.Extras-    HaskellCI.GHC+    HaskellCI.Config.Ubuntu+    HaskellCI.Diagnostics     HaskellCI.Glob-    HaskellCI.MakeTravisOutput+    HaskellCI.Jobs+    HaskellCI.List+    HaskellCI.MonadErr     HaskellCI.Newtypes     HaskellCI.Optimization     HaskellCI.OptionsGrammar@@ -93,22 +102,32 @@     HaskellCI.Package     HaskellCI.ParsecError     HaskellCI.ParsecUtils+    HaskellCI.Prelude     HaskellCI.Project+    HaskellCI.Sh+    HaskellCI.ShVersionRange     HaskellCI.TestedWith-    HaskellCI.Version+    HaskellCI.Tools+    HaskellCI.Travis+    HaskellCI.Travis.Yaml+    HaskellCI.YamlSyntax -  -- vendored from Cabal development version-  other-modules:      Distribution.Fields.Pretty   ghc-options:     -Wall -Wcompat -Wnoncanonical-monad-instances     -Wnoncanonical-monadfail-instances    hs-source-dirs:     src   default-extensions:+    BangPatterns+    NoImplicitPrelude+    DeriveAnyClass     DeriveFoldable     DeriveFunctor     DeriveGeneric     DeriveTraversable+    DerivingStrategies+    GeneralizedNewtypeDeriving+    ScopedTypeVariables    other-extensions:     CPP@@ -117,35 +136,44 @@     ViewPatterns    build-depends:-    , base          >=4.9      && <4.13+    , base          >=4.10     && <4.13     , bytestring    ^>=0.10.8.1-    , Cabal         ^>=2.4+    , Cabal         ^>=3.0     , containers    ^>=0.5.7.1 || ^>=0.6.0.1     , deepseq       ^>=1.4.2.0     , directory     ^>=1.3.0.0     , filepath      ^>=1.4.1.1+    , mtl           >=2.2.2     , parsec        ^>=3.1.13.0     , pretty        ^>=1.1.3.3+    , process       ^>=1.4.3.0 || ^>=1.6.1.0     , text          ^>=1.2.3.0     , transformers  ^>=0.5.2.0 +  if !impl(ghc >=8.2)+    build-depends: bifunctors ^>=5.5.4+   -- other dependencies   build-depends:+    , aeson                 ^>=1.4.2.0     , base-compat           ^>=0.10.5+    , exceptions            ^>=0.10.0     , generic-lens          ^>=1.1.0.0     , HsYAML                ^>=0.1.1.3+    , lattices              ^>=2     , microlens             ^>=0.4.10     , optparse-applicative  ^>=0.14.3.0+    , temporary             ^>=1.3+    , unordered-containers  ^>=0.2.10.0    default-language:   Haskell2010    -- ShellCheck. Would need newer transformers for older GHC   if (flag(shellcheck) && impl(ghc >=7.10 && <8.7))-    build-depends: ShellCheck ==0.6.0+    build-depends: ShellCheck ==0.7.0  executable haskell-ci   main-is:          Main.hs-  ghc-options:      -Wall   hs-source-dirs:   cli   build-depends:     , base@@ -158,14 +186,14 @@   main-is:          Tests.hs   hs-source-dirs:   test   build-depends:-    , ansi-terminal        ^>=0.8.0.2+    , ansi-terminal        ^>=0.8.0.2 || ^>=0.9.1     , base     , bytestring     , Diff                 ^>=0.3.4     , directory     , filepath     , haskell-ci-internal-    , tasty                >=1.0     && <1.2+    , tasty                >=1.0     && <1.3     , tasty-golden         ^>=2.3.1.1     , transformers 
− src/Distribution/Fields/Pretty.hs
@@ -1,134 +0,0 @@-{-# LANGUAGE BangPatterns #-}--- | Cabal-like file AST types: 'Field', 'Section' etc,------ This (intermediate) data type is used for pretty-printing.------ @since 3.0.0.0----module Distribution.Fields.Pretty (-    -- * Fields-    PrettyField (..),-    showFields,-    showFields',-    -- * Transformation from 'P.Field'-    fromParsecFields,-    genericFromParsecFields,-    prettyFieldLines,-    prettySectionArgs,-    ) where--import Data.Functor.Identity       (Identity (..))-import Distribution.Pretty         (showToken)--import Distribution.Parsec.Field (FieldName)-import Distribution.Simple.Utils (fromUTF8BS)--import qualified Distribution.Parsec.Parser as P--import qualified Data.ByteString  as BS-import qualified Text.PrettyPrint as PP--data PrettyField-    = PrettyField FieldName PP.Doc-    | PrettySection FieldName [PP.Doc] [PrettyField]-  deriving Show---- | Prettyprint a list of fields.-showFields :: [PrettyField] -> String-showFields = showFields' 4---- | 'showFields' with user specified indentation.-showFields' :: Int -> [PrettyField] -> String-showFields' n = unlines . renderFields indent where-    -- few hardcoded, "unrolled"  variants.-    indent | n == 4    = indent4-           | n == 2    = indent2-           | otherwise = (replicate (max n 1) ' ' ++)--    indent4 :: String -> String-    indent4 [] = []-    indent4 xs = ' ' : ' ' : ' ' : ' ' : xs--    indent2 :: String -> String-    indent2 [] = []-    indent2 xs = ' ' : ' ' : xs--renderFields :: (String -> String) -> [PrettyField] -> [String]-renderFields indent fields = flattenBlocks $ map (renderField indent len) fields-  where-    len = maxNameLength 0 fields--    maxNameLength !acc []                          = acc-    maxNameLength !acc (PrettyField name _ : rest) = maxNameLength (max acc (BS.length name)) rest-    maxNameLength !acc (PrettySection {}   : rest) = maxNameLength acc rest---- | Block of lines,--- Boolean parameter tells whether block should be surrounded by empty lines-data Block = Block Bool [String]--flattenBlocks :: [Block] -> [String]-flattenBlocks = go0 where-    go0 [] = []-    go0 (Block surr strs : blocks) = strs ++ go surr blocks--    go _surr' [] = []-    go  surr' (Block surr strs : blocks) = ins $ strs ++ go surr blocks where-        ins | surr' || surr = ("" :)-            | otherwise     = id--renderField :: (String -> String) -> Int -> PrettyField -> Block-renderField indent fw (PrettyField name doc) = Block False $ case lines narrow of-    []           -> [ name' ++ ":" ]-    [singleLine] | length singleLine < 60-                 -> [ name' ++ ": " ++ replicate (fw - length name') ' ' ++ narrow ]-    _            -> (name' ++ ":") : map indent (lines (PP.render doc))-  where-    name' = fromUTF8BS name-    narrow = PP.renderStyle narrowStyle doc--    narrowStyle :: PP.Style-    narrowStyle = PP.style { PP.lineLength = PP.lineLength PP.style - fw }--renderField indent _ (PrettySection name args fields) = Block True $-    PP.render (PP.hsep $ PP.text (fromUTF8BS name) : args)-    :-    map indent (renderFields indent fields)------------------------------------------------------------------------------------ Transform from Parsec.Field----------------------------------------------------------------------------------genericFromParsecFields-    :: Applicative f-    => (FieldName -> [P.FieldLine ann] -> f PP.Doc)     -- ^ transform field contents-    -> (FieldName -> [P.SectionArg ann] -> f [PP.Doc])  -- ^ transform section arguments-    -> [P.Field ann]-    -> f [PrettyField]-genericFromParsecFields f g = goMany where-    goMany = traverse go--    go (P.Field (P.Name _ann name) fls)          = PrettyField name <$> f name fls-    go (P.Section (P.Name _ann name) secargs fs) = PrettySection name <$> g name secargs <*> goMany fs---- | Used in 'fromParsecFields'.-prettyFieldLines :: FieldName -> [P.FieldLine ann] -> PP.Doc-prettyFieldLines _ fls = PP.vcat-    [ PP.text $ fromUTF8BS bs-    | P.FieldLine _ bs <- fls-    ]---- | Used in 'fromParsecFields'.-prettySectionArgs :: FieldName -> [P.SectionArg ann] -> [PP.Doc]-prettySectionArgs _ = map $ \sa -> case sa of-    P.SecArgName _ bs  -> showToken $ fromUTF8BS bs-    P.SecArgStr _ bs   -> showToken $ fromUTF8BS bs-    P.SecArgOther _ bs -> PP.text $ fromUTF8BS bs---- | Simple variant of 'genericFromParsecField'-fromParsecFields :: [P.Field ann] -> [PrettyField]-fromParsecFields = runIdentity . genericFromParsecFields-    (Identity .: prettyFieldLines)-    (Identity .: prettySectionArgs)-  where-    (.:) :: (a -> b) -> (c -> d -> a) -> (c -> d -> b)-    (f .: g) x y = f (g x y)
src/HaskellCI.hs view
@@ -1,1033 +1,353 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE OverloadedLabels #-}---- | New-style @.travis.yml@ script generator using cabal 1.24's nix-style--- tech-preview facilities.------ See also <https://github.com/haskell-CI/haskell-ci>------ NB: This code deliberately avoids relying on non-standard packages and---     is expected to compile/work with at least GHC 7.0 through GHC 8.0-module HaskellCI (-    main,-    -- * for tests-    Result (..),-    Diagnostic (..),-    parseTravis,-    formatDiagnostic, formatDiagnostics,-    travisFromConfigFile, MakeTravisOutput, Options (..), defaultOptions,-    ) where--import Prelude ()-import Prelude.Compat--import Control.DeepSeq (force)-import Control.Exception (evaluate)-import Control.Monad (when, unless, liftM, forM_, mzero)-import qualified Data.ByteString as BS-import qualified Data.Foldable as F-import qualified Data.Traversable as T-import Data.Function-import Data.List-import Data.Maybe-import Data.Set (Set)-import qualified Data.Set as S-import qualified Data.Map as M-import System.Directory (doesDirectoryExist, doesFileExist)-import System.Exit-import System.FilePath.Posix ((</>), takeDirectory, takeFileName, takeExtension)-import System.IO-import Control.Monad.IO.Class-import Control.Monad.Trans.Maybe-import System.Environment (getArgs)-import Control.Monad.Trans.Writer-import Text.Read (readMaybe)-import Distribution.Compat.ReadP (readP_to_S)---import qualified Options.Applicative         as O--import Distribution.Compiler (CompilerFlavor(..))-import Distribution.Package hiding (Package, pkgName)-import qualified Distribution.Package as Pkg-import Distribution.PackageDescription (GenericPackageDescription,packageDescription, testedWith, package, condLibrary, condTestSuites)-import Distribution.PackageDescription.Configuration (flattenPackageDescription)-import qualified Distribution.PackageDescription as PD-import qualified Distribution.ParseUtils as PU-import Distribution.Text-import Distribution.Version-#if MIN_VERSION_Cabal(2,2,0)-import Distribution.PackageDescription.Parsec (readGenericPackageDescription)-#elif MIN_VERSION_Cabal(2,0,0)-import Distribution.PackageDescription.Parse (readGenericPackageDescription)-#else-import Distribution.PackageDescription.Parse (readPackageDescription)-import Distribution.Verbosity (Verbosity)-#endif--import qualified Distribution.FieldGrammar                    as C-import qualified Distribution.Fields.Pretty                   as C-import qualified Distribution.PackageDescription.FieldGrammar as C-import qualified Distribution.Types.SourceRepo                as C-import qualified Distribution.Types.VersionRange              as C-import qualified Text.PrettyPrint                             as PP----#if MIN_VERSION_base(4,9,0)-import Data.Semigroup (Semigroup (..))-#else-import Data.Monoid ((<>))-#endif---- lens-import Lens.Micro-import Data.Generics.Labels () -- IsLabel (->) ...--import qualified Distribution.Types.BuildInfo.Lens          as L-import qualified Distribution.Types.PackageDescription.Lens as L--import HaskellCI.Cli-import HaskellCI.Config-import HaskellCI.Config.CopyFields-import HaskellCI.Config.ConstraintSet-import HaskellCI.Config.Doctest-import HaskellCI.Config.Dump-import HaskellCI.Config.Folds-import HaskellCI.Config.HLint-import HaskellCI.Config.Installed-import HaskellCI.Config.Jobs-import HaskellCI.Extras-import HaskellCI.GHC-import HaskellCI.Glob-import HaskellCI.MakeTravisOutput-import HaskellCI.Optimization-import HaskellCI.Package-import HaskellCI.Project-import HaskellCI.TestedWith-import HaskellCI.Version--#ifndef CURRENT_PACKAGE_VERSION-#define CURRENT_PACKAGE_VERSION "???"-#endif------------------------------------------------------------------------------------ Main----------------------------------------------------------------------------------main :: IO ()-main = do-    argv0 <- getArgs-    (cmd, opts) <- O.execParser cliParserInfo-    case cmd of-        CommandListGHC -> do-            putStrLn $ "Supported GHC versions:"-            forM_ groupedVersions $ \(v, vs) -> do-                putStr $ prettyMajVersion v ++ ": "-                putStrLn $ intercalate ", " (map display vs)-        CommandDumpConfig -> do-            putStr $ unlines $ runDG configGrammar--        CommandRegenerate -> do-            let fp = ".travis.yml" -- make configurable?-            contents <- readFile fp-            case findArgv (lines contents) of-                Nothing     -> do-                    hPutStrLn stderr $ "Error: expected REGENDATA line in " ++ fp-                    exitFailure-                Just argv   -> do-                    (f, opts') <- parseTravis argv-                    doTravis argv f (opts' <> opts)-        CommandTravis f -> doTravis argv0 f opts-  where-    findArgv :: [String] -> Maybe [String]-    findArgv ls = do-        l <- findMaybe (afterInfix "REGENDATA") ls-        readMaybe l--    groupedVersions :: [(Version, [Version])]-    groupedVersions = map ((\vs -> (head vs, vs)) . sortBy (flip compare))-                    . groupBy ((==) `on` ghcMajVer)-                    $ sort knownGhcVersions--    prettyMajVersion :: Version -> String-    prettyMajVersion v-        | Just v == ghcAlpha = "alpha"-        | otherwise = case ghcMajVer v of (x,y) -> show x ++ "." ++ show y--doTravis :: [String] -> FilePath -> Options -> IO ()-doTravis args path opts = do-    runYamlWriter (optOutput opts) $ travisFromConfigFile args opts path--runYamlWriter :: Maybe FilePath -> YamlWriter IO () -> IO ()-runYamlWriter mfp m = do-    result <- execWriterT (runMaybeT m)-    case result of-        Failure (formatDiagnostics -> errors) -> hPutStr stderr errors >> exitFailure-        Success (formatDiagnostics -> warnings) (unlines -> contents) -> do-            contents' <- evaluate (force contents)-            hPutStr stderr warnings-            case mfp of-                Nothing -> putStr contents'-                Just fp -> writeFile fp contents'--travisFromConfigFile-    :: MonadIO m-    => [String]-    -> Options-    -> FilePath-    -> YamlWriter m ()-travisFromConfigFile args opts path = do-    cabalFiles <- getCabalFiles-    config' <- maybe (return emptyConfig) readConfigFile (optConfig opts)-    let config = optConfigMorphism opts config'-    pkgs <- T.mapM (configFromCabalFile config opts) cabalFiles-    (ghcs, prj) <- case checkVersions (cfgTestedWith config) pkgs of-        Right x     -> return x-        Left errors -> putStrLnErrs errors >> mzero-    genTravisFromConfigs args opts isCabalProject config prj ghcs-  where-    isCabalProject :: Maybe FilePath-    isCabalProject-        | "cabal.project" `isPrefixOf` takeFileName path = Just path-        | otherwise = Nothing--    getCabalFiles :: MonadIO m => YamlWriter m (Project FilePath)-    getCabalFiles-        | isNothing isCabalProject = return $ emptyProject & #prjPackages .~ [path]-        | otherwise = do-            contents <- liftIO $ BS.readFile path-            pkgs <- either putStrLnErr return $ parseProjectFile path contents-            over #prjPackages concat `liftM` T.mapM findProjectPackage pkgs--    rootdir = takeDirectory path--    -- See findProjectPackages in cabal-install codebase-    -- this is simple variant.-    findProjectPackage :: MonadIO m => String -> YamlWriter m [FilePath]-    findProjectPackage pkglocstr = do-        mfp <- checkisFileGlobPackage pkglocstr `mplusMaybeT`-               checkIsSingleFilePackage pkglocstr-        maybe (putStrLnErr $ "bad package location: " ++ pkglocstr) return mfp--    checkIsSingleFilePackage pkglocstr = do-        let abspath = rootdir </> pkglocstr-        isFile <- liftIO $ doesFileExist abspath-        isDir  <- liftIO $ doesDirectoryExist abspath-        if | isFile && takeExtension pkglocstr == ".cabal" -> return (Just [abspath])-           | isDir -> checkisFileGlobPackage (pkglocstr </> "*.cabal")-           | otherwise -> return Nothing--    -- if it looks like glob, glob-    checkisFileGlobPackage pkglocstr =-        case filter (null . snd) $ readP_to_S parseFilePathGlobRel pkglocstr of-            [(g, "")] -> do-                files <- liftIO $ expandRelGlob rootdir g-                let files' = filter ((== ".cabal") . takeExtension) files-                -- if nothing is matched, skip.-                if null files' then return Nothing else return (Just files')-            _         -> return Nothing--    mplusMaybeT :: Monad m => m (Maybe a) -> m (Maybe a) -> m (Maybe a)-    mplusMaybeT ma mb = do-        mx <- ma-        case mx of-            Nothing -> mb-            Just x  -> return (Just x)--configFromCabalFile-    :: MonadIO m => Config ->  Options -> FilePath -> YamlWriter m (Package, Set Version)-configFromCabalFile cfg opts cabalFile = do-    gpd <- liftIO $ readGenericPackageDescription maxBound cabalFile--    let compilers = testedWith $ packageDescription gpd-        pkgNameStr = display $ Pkg.pkgName $ package $ packageDescription gpd--    let unknownComps = nub [ c | (c,_) <- compilers, c /= GHC ]-        ghcVerConstrs = [ vc | (GHC,vc) <- compilers ]-        ghcVerConstrs' = simplifyVersionRange $ foldr unionVersionRanges noVersion ghcVerConstrs-        twoDigitGhcVerConstrs = mapMaybe isTwoDigitGhcVersion ghcVerConstrs :: [Version]-        specificGhcVers = nub $ mapMaybe isSpecificVersion ghcVerConstrs--    unless (null twoDigitGhcVerConstrs) $ do-        putStrLnWarn $ "'tested-with:' uses two digit GHC versions (which don't match any existing GHC version): " ++ intercalate ", " (map display twoDigitGhcVerConstrs)-        putStrLnInfo $ "Either use wild-card format, for example 'tested-with: GHC ==7.10.*' or a specific existing version 'tested-with: GHC ==7.10.3'"--    when (null compilers) $ do-        putStrLnErr (unlines $-                     [ "empty or missing top-level 'tested-with:' definition in " ++ cabalFile ++ " file; example definition:"-                     , ""-                     , "tested-with: " ++ intercalate ", " [ "GHC==" ++ display v | v <- lastStableGhcVers ]-                     ])--    unless (null unknownComps) $ do-        putStrLnWarn $ "ignoring unsupported compilers mentioned in tested-with: " ++ show unknownComps--    when (null ghcVerConstrs) $ do-        putStrLnErr "'tested-with:' doesn't mention any 'GHC' version"--    when (isNoVersion ghcVerConstrs') $ do-        putStrLnErr "'tested-with:' describes an empty version range for 'GHC'"--    when (isAnyVersion ghcVerConstrs') $ do-        putStrLnErr "'tested-with:' allows /any/ 'GHC' version"--    let unknownGhcVers = sort $ specificGhcVers \\ knownGhcVersions--    unless (null unknownGhcVers) $ do-        putStrLnErr ("'tested-with:' specifically refers to unknown 'GHC' versions: "-                     ++ intercalate ", " (map display unknownGhcVers) ++ "\n"-                     ++ "Known GHC versions: " ++ intercalate ", " (map display knownGhcVersions))--    let knownGhcVersions'-            | cfgLastInSeries cfg = filterLastMajor knownGhcVersions-            | otherwise           = knownGhcVersions--    let testedGhcVersions = filter (`withinRange` ghcVerConstrs') knownGhcVersions'--    when (null testedGhcVersions) $ do-        putStrLnErr "no known GHC version is allowed by the 'tested-with' specification"--    forM_ (optCollections opts) $ \c -> do-        let v = collToGhcVer c-        unless (v `elem` testedGhcVersions) $-            putStrLnErr $ unlines-               [ "collection " ++ c ++ " requires GHC " ++ display v-               , "add 'tested-width: GHC == " ++ display v ++ "' to your .cabal file"-               ]--    let pkg = Pkg pkgNameStr anyVersion (takeDirectory cabalFile) gpd--    return (pkg, S.fromList testedGhcVersions)-  where-    lastStableGhcVers-        = nubBy ((==) `on` ghcMajVer)-        $ sortBy (flip compare)-        $ filter (not . previewGHC . Just)-        $ knownGhcVersions--    isTwoDigitGhcVersion :: VersionRange -> Maybe Version-    isTwoDigitGhcVersion vr = isSpecificVersion vr >>= t-      where-        t v | [_,_] <- versionNumbers v = Just v-        t _                             = Nothing--    filterLastMajor = map maximum . groupBy ((==) `on` ghcMajVer)--genTravisFromConfigs-    :: Monad m-    => [String]-    -> Options-    -> Maybe FilePath-    -> Config-    -> Project Package-    -> Set Version-    -> YamlWriter m ()-genTravisFromConfigs argv opts isCabalProject config prj@Project { prjPackages = pkgs } versions' = do-    let folds = cfgFolds config--    putStrLnInfo $-        "Generating Travis-CI config for testing for GHC versions: " ++ ghcVersions--    unless (null $ cfgOsx config) $  do-        putStrLnInfo $ "Also OSX jobs for: " ++ ghcOsxVersions-        unless (S.null omittedOsxVersions) $-            putStrLnWarn $ "Not all GHC versions specified with --osx are generated: " ++ ghcOmittedOsxVersions--    ----------------------------------------------------------------------------    -- travis.yml generation starts here--    tellStrLns-        [ "# This Travis job script has been generated by a script via"-        , "#"-        , rawRow $ "#   haskell-ci " ++ unwords [ "'" ++ a ++ "'" | a <- argv ]-        , "#"-        , "# For more information, see https://github.com/haskell-CI/haskell-ci"-        , "#"-        , rawRow $ "# version: " ++ CURRENT_PACKAGE_VERSION-        , "#"-        , "language: c"-        , "dist: xenial"-        , ""-        , "git:"-        , "  submodules: false  # whether to recursively clone submodules"-        , ""-        ]--    let projectName = fromMaybe (pkgName $ head pkgs) (cfgProjectName config)-    unless (null $ cfgIrcChannels config) $ tellStrLnsRaw $-        [ "notifications:"-        , "  irc:"-        , "    channels:"-        ] ++-        [ "      - \"" ++ chan ++ "\"" | chan <- cfgIrcChannels config ] ++-        [ "    skip_join: true"-        , "    template:"-        , "      - \"\\x0313" ++ projectName ++ "\\x03/\\x0306%{branch}\\x03 \\x0314%{commit}\\x03 %{build_url} %{message}\""-        , ""-        ]--    unless (null $ cfgOnlyBranches config) $ tellStrLnsRaw $-        [ "branches:"-        , "  only:"-        ] ++-        [ "    - " ++ branch-        | branch <- cfgOnlyBranches config-        ] ++-        [ ""-        ]--    -- cache directories-    when (cfgCache config) $ tellStrLns-        [ "cache:"-        , "  directories:"-        , "    - $HOME/.cabal/packages"-        , "    - $HOME/.cabal/store"-        ]---    -- on OSX ghc is installed in $HOME so we can cache it-    -- independently of linux-    when (cfgCache config && not (null (cfgOsx config))) $ tellStrLns-        [ "    - $HOME/.ghc-install"-        ]--    tellStrLn ""--    -- postgresql-    when (cfgPostgres config) $ tellStrLns-        [ "services:"-        , "- postgresql"-        , "addons:"-        , "  postgresql: '10'"-        , ""-        ]--    -- before caching: clear some redundant stuff-    when (cfgCache config) $ tellStrLns-        [ "before_cache:"-        , "  - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log"-        , "  # remove files that are regenerated by 'cabal update'"-        , "  - rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.*" -- legacy-        , "  - rm -fv $CABALHOME/packages/hackage.haskell.org/*.json" -- TUF meta-data-        , "  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache"-        , "  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar"-        , "  - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx"-        , ""-        , "  - rm -rfv $CABALHOME/packages/head.hackage" -- if we cache, it will break builds.-        , ""-        ]--    tellStrLn "matrix:"-    tellStrLn "  include:"--    let colls = [ (collToGhcVer cid,cid) | cid <- reverse $ optCollections opts ]--    let tellJob :: Monad m => Bool -> Maybe Version -> YamlWriter m ()-        tellJob osx gv = do-            let cvs = dispGhcVersion $ gv >> cfgCabalInstallVersion config-                gvs = dispGhcVersion gv--                xpkgs' = concatMap (',':) (S.toList $ cfgApt config)--                colls' = [ cid | (v,cid) <- colls, Just v == gv ]--            tellStrLnsRaw $ catMaybes-                [ Just $ "    - compiler: \"ghc-" <> gvs <> "\""-                , if | Just e <- gv >>= \v -> M.lookup v (cfgEnv config)-                                     -> Just $ "      env: " ++ e-                     | previewGHC gv -> Just $ "      env: GHCHEAD=true"-                     | null colls'   -> Nothing-                     | otherwise     -> Just $ "      env: 'COLLECTIONS=" ++ intercalate "," colls' ++ "'"-                , Just $ "      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-" <> cvs <> ",ghc-" <> gvs <> xpkgs' <> "], sources: [hvr-ghc]}}"-                ]--            when osx $ tellStrLnsRaw-                [ "      os: osx"-                ]--    -- newer GHC first, -head last (which is great).-    -- Alpha release would go first though.-    F.forM_ (reverse $ S.toList versions) $ tellJob False-    F.forM_ (reverse $ S.toList osxVersions) $ tellJob True . Just--    let allowFailures = headGhcVers `S.union` S.map Just (S.filter (`C.withinRange` cfgAllowFailures config) versions')-    unless (S.null allowFailures) $ do-        tellStrLn ""-        tellStrLn "  allow_failures:"--        F.forM_ allowFailures $ \gv -> do-            let gvs = dispGhcVersion gv-            tellStrLn $ concat [ "    - compiler: \"ghc-", gvs, "\"" ]--    tellStrLns-        [ ""-        , "before_install:"-        , sh "HC=/opt/ghc/bin/${CC}"-        , sh' [2034,2039] "HCPKG=${HC/ghc/ghc-pkg}" -- SC2039. In POSIX sh, string replacement is undefined.-        , sh "unset CC"-        -- cabal-        , sh "CABAL=/opt/ghc/bin/cabal"-        , sh "CABALHOME=$HOME/.cabal"-        -- PATH-        , sh "export PATH=\"$CABALHOME/bin:$PATH\""-        -- rootdir is useful for manual script additions-        , sh "ROOTDIR=$(pwd)"-        ]--    -- macOS installing-    let haskellOnMacos = "https://haskell.futurice.com/haskell-on-macos.py"-    unless (null (cfgOsx config)) $ tellStrLns-        [ sh $ "if [ \"$TRAVIS_OS_NAME\" = \"osx\" ]; then brew update; brew upgrade python@3; curl " ++ haskellOnMacos ++ " | python3 - --make-dirs --install-dir=$HOME/.ghc-install --cabal-alias=head install cabal-install-head ${TRAVIS_COMPILER}; fi"-        , sh' [2034,2039] "if [ \"$TRAVIS_OS_NAME\" = \"osx\" ]; then HC=$HOME/.ghc-install/ghc/bin/$TRAVIS_COMPILER; HCPKG=${HC/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-    tellStrLns-        [ sh $ "HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\\.([0-9]+)\\.([0-9]+).*/\\1 * 10000 + \\2 * 100 + \\3/') ))"-        , sh "echo $HCNUMVER"-        ]--    unless (null colls) $-       tellStrLn " - IFS=', ' read -a COLLS <<< \"$COLLECTIONS\""--    tellStrLns-        [ ""-        , "install:"-        , sh "${CABAL} --version"-        , sh "echo \"$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]\""-        , sh "TEST=--enable-tests"-        , shForJob versions' (invertVersionRange $ cfgTests config) "TEST=--disable-tests"-        , sh "BENCH=--enable-benchmarks"-        , shForJob versions' (invertVersionRange $ cfgBenchmarks config) "BENCH=--disable-benchmarks"-        , sh "GHCHEAD=${GHCHEAD-false}"-        ]--    -- Update hackage index. Side-effect: ~/.cabal.config is created.-    tellStrLns-        [ sh "travis_retry ${CABAL} update -v"-        , sh "sed -i.bak 's/^jobs:/-- jobs:/' $CABALHOME/config"-        , sh "rm -fv cabal.project cabal.project.local"-        ]--    -- Cabal jobs-    case cfgJobs config >>= cabalJobs of-        Just n -> tellStrLns-            [ sh $ "sed -i.bak 's/^-- jobs:.*/jobs: " ++ show n ++ "/' $CABALHOME/config"-            ]-        _ -> return ()--    -- GHC jobs-    case cfgJobs config >>= ghcJobs of-        Just m -> tellStrLns-            [ shForJob versions' (orLaterVersion (mkVersion [7,8])) $-              "sed -i.bak 's/-- ghc-options:.*/ghc-options: -j" ++ show m ++ "/' $CABALHOME/config"-            ]-        _ -> return ()--    -- Add head.hackage repository to ~/.cabal/config-    -- (locally you want to add it to cabal.project)-    unless (S.null headGhcVers) $ tellStrLns-        [ "  # Overlay Hackage Package Index for GHC HEAD: https://github.com/hvr/head.hackage"-        , "  - |"-        , "    if $GHCHEAD; then"-        , "      sed -i 's/-- allow-newer: .*/allow-newer: *:base/' $CABALHOME/config"-        , "      for pkg in $($HCPKG list --simple-output); do pkg=$(echo $pkg | sed 's/-[^-]*$//'); sed -i \"s/allow-newer: /allow-newer: *:$pkg, /\" $CABALHOME/config; done"-        , ""-        , "      echo 'repository head.hackage'                                                        >> $CABALHOME/config"-        , "      echo '   url: http://head.hackage.haskell.org/'                                       >> $CABALHOME/config"-        , "      echo '   secure: True'                                                                >> $CABALHOME/config"-        , "      echo '   root-keys: 07c59cb65787dedfaef5bd5f987ceb5f7e5ebf88b904bbd4c5cbdeb2ff71b740' >> $CABALHOME/config"-        , "      echo '              2e8555dde16ebd8df076f1a8ef13b8f14c66bad8eafefd7d9e37d0ed711821fb' >> $CABALHOME/config"-        , "      echo '              8f79fd2389ab2967354407ec852cbe73f2e8635793ac446d09461ffb99527f6e' >> $CABALHOME/config"-        , "      echo '   key-threshold: 3'                                                            >> $CABALHOME.config"-        , ""-        , "      grep -Ev -- '^\\s*--' $CABALHOME/config | grep -Ev '^\\s*$'"-        , ""-        , "      ${CABAL} new-update head.hackage -v"-        , "    fi"-        ]--    -- Output cabal.config-    tellStrLns-        [ sh "grep -Ev -- '^\\s*--' $CABALHOME/config | grep -Ev '^\\s*$'"-        ]--    -- Install doctest-    let doctestVersionConstraint-            | isAnyVersion (cfgDoctestVersion doctestConfig) = ""-            | otherwise = " --constraint='doctest " ++ display (cfgDoctestVersion doctestConfig) ++ "'"-    when (cfgDoctestEnabled doctestConfig) $ tellStrLns-        [ shForJob versions' doctestJobVersionRange $ "${CABAL} new-install -w ${HC} -j2 doctest" ++ doctestVersionConstraint-        ]--    -- Install hlint-    let hlintVersionConstraint-            | isAnyVersion (cfgHLintVersion hlintConfig) = ""-            | otherwise = " --constraint='hlint " ++ display (cfgHLintVersion hlintConfig) ++ "'"-    when (cfgHLintEnabled hlintConfig) $ tellStrLns-        [ shForJob versions' (hlintJobVersionRange versions (cfgHLintJob hlintConfig)) $-          "${CABAL} new-install -w ${HC} -j2 hlint" ++ hlintVersionConstraint-        ]--    -- create cabal.project file-    generateCabalProject False--    let pkgFilter = intercalate " | " $ map (wrap.pkgName) pkgs-        wrap s = "grep -Fv \"" ++ s ++ " ==\""-    unless (null colls) $ tellStrLnsRaw-        [ "  - for COLL in \"${COLLS[@]}\"; do"-        , "      echo \"== collection $COLL ==\";"-        , "      ghc-travis collection ${COLL} > /dev/null || break;"-        , "      ghc-travis collection ${COLL} | " ++ pkgFilter ++ " > cabal.project.freeze;"-        , "      grep ' collection-id' cabal.project.freeze;"-        , "      rm -rf dist-newstyle/;"-        , "      $(CABAL} new-build -w ${HC} ${TEST} ${BENCH} --project-file=\"" ++ projectFile ++ "\" --dep -j2 all;"-        , "    done"-        , ""-        ]--    forM_ pkgs $ \Pkg{pkgDir} -> tellStrLns-        [ sh $ "if [ -f \"" ++ pkgDir ++ "/configure.ac\" ]; then (cd \"" ++ pkgDir ++ "\" && autoreconf -i); fi"-        ]--    let quotedRmPaths =-          ".ghc.environment.*"-          ++ " " ++-          unwords (quotedPaths (\Pkg{pkgDir} -> pkgDir ++ "/dist"))--    tellStrLns-        [ sh $ "rm -f cabal.project.freeze"-        ]--    -- Install dependencies-    when (cfgInstallDeps config) $ do-        tellStrLns-            -- dump install plan-            [ sh $ "${CABAL} new-freeze -w ${HC} ${TEST} ${BENCH} --project-file=\"" ++ projectFile ++"\" --dry"-            , sh $ "cat \"" ++ projectFile ++ ".freeze\" | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"-            , sh $ "rm  \"" ++ projectFile ++ ".freeze\""--            -- install dependencies-            , sh $ "${CABAL} new-build -w ${HC} ${TEST} ${BENCH} --project-file=\"" ++ projectFile ++"\" --dep -j2 all"-            ]-        tellStrLns-            [ shForJob versions' (cfgNoTestsNoBench config) $ "${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks --project-file=\"" ++ projectFile ++ "\" --dep -j2 all"-            ]--    tellStrLns-        [ sh $ "rm -rf " ++ quotedRmPaths-        , sh $  "DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)"-        ]--    tellStrLns-        [ ""-        , "# 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."-        , "script:"-        , "  # test that source-distributions can be generated"-        ]--    foldedTellStrLns FoldSDist "Packaging..." folds $ do-        tellStrLns-            [ sh $ "${CABAL} new-sdist all"-            ]--    let tarFiles = "dist-newstyle" </> "sdist" </> "*.tar.gz"---    foldedTellStrLns FoldUnpack "Unpacking..." folds $ do-        tellStrLns-            [ sh $ "mv " ++ tarFiles ++ " ${DISTDIR}/"-            , sh $ "cd ${DISTDIR} || false" -- fail explicitly, makes SC happier-            , sh $ "find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \\;"-            ]-        generateCabalProject True--    unless (equivVersionRanges noVersion $ cfgNoTestsNoBench config) $ foldedTellStrLns FoldBuild "Building..." folds $ tellStrLns-        [ comment "this builds all libraries and executables (without tests/benchmarks)"-        , shForJob versions' (cfgNoTestsNoBench config) $ "${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all"-        ]--    tellStrLns [""]---    foldedTellStrLns FoldBuildEverything-        "Building with tests and benchmarks..." folds $ tellStrLns-        [ comment "build & run tests, build benchmarks"-        , sh "${CABAL} new-build -w ${HC} ${TEST} ${BENCH} all"-        ]--    -- cabal new-test fails if there are no test-suites.-    when hasTests $-        foldedTellStrLns FoldTest "Testing..." folds $ tellStrLns-            [ sh $ mconcat-                [ "if [ \"x$TEST\" = \"x--enable-tests\" ]; then "-                , if cfgNoise config-                     then "${CABAL} "-                     else "(set -o pipefail; ${CABAL} -vnormal+nowrap+markoutput "-                , "new-test -w ${HC} ${TEST} ${BENCH} all"-                , if cfgNoise config-                     then ""-                     else " 2>&1 | sed '/^-----BEGIN CABAL OUTPUT-----$/,/^-----END CABAL OUTPUT-----$/d' )"-                , "; fi"-                ]-            ]--    tellStrLns [""]--    when (cfgDoctestEnabled doctestConfig) $ do-        let doctestOptions = unwords $ cfgDoctestOptions doctestConfig-        tellStrLns [ comment "doctest" ]-        foldedTellStrLns FoldDoctest "Doctest..." folds $ do-            forM_ pkgs $ \Pkg{pkgName,pkgGpd,pkgJobs} -> do-                forM_ (doctestArgs pkgGpd) $ \args -> do-                    let args' = unwords args-                    unless (null args) $ tellStrLns-                        [ shForJob versions' (doctestJobVersionRange `intersectVersionRanges` pkgJobs) $-                          "(cd " ++ pkgName ++ "-* && doctest " ++ doctestOptions ++ " " ++ args' ++ ")"-                        ]-        tellStrLns [ "" ]--    when (cfgHLintEnabled hlintConfig) $ do-        let "" <+> ys = ys-            xs <+> "" = xs-            xs <+> ys = xs ++ " " ++ ys--            prependSpace "" = ""-            prependSpace xs = " " ++ xs--        let hlintOptions = prependSpace $ maybe "" ("-h ${ROOTDIR}/" ++) (cfgHLintYaml hlintConfig) <+> unwords (cfgHLintOptions hlintConfig)--        tellStrLns [ comment "hlint" ]-        foldedTellStrLns FoldHLint "HLint.." folds $ do-            forM_ pkgs $ \Pkg{pkgName,pkgGpd,pkgJobs} -> do-                -- note: similar arguments work so far for doctest and hlint-                forM_ (hlintArgs pkgGpd) $ \args -> do-                    let args' = unwords args-                    unless (null args) $ tellStrLns-                        [ shForJob versions' (hlintJobVersionRange versions (cfgHLintJob hlintConfig) `intersectVersionRanges` pkgJobs) $-                          "(cd " ++ pkgName ++ "-* && hlint" ++ hlintOptions ++ " " ++ args' ++ ")"-                        ]-        tellStrLns [ "" ]--    when (cfgCheck config) $-        foldedTellStrLns FoldCheck "cabal check..." folds $ do-            tellStrLns [ comment "cabal check" ]-            forM_ pkgs $ \Pkg{pkgName,pkgJobs} -> tellStrLns-                [ shForJob versions' pkgJobs $-                  "(cd " ++ pkgName ++ "-* && ${CABAL} check)"-                ]-            tellStrLns [ "" ]--    when (hasLibrary && not (equivVersionRanges noVersion $ cfgHaddock config)) $-        foldedTellStrLns FoldHaddock "Haddock..." folds $ tellStrLns-            [ comment "haddock"-            , shForJob versions' (cfgHaddock config) "${CABAL} new-haddock -w ${HC} ${TEST} ${BENCH} all"-            , ""-            ]--    unless (null colls) $-        foldedTellStrLns FoldStackage "Stackage builds..." folds $ tellStrLnsRaw-            [ "  # try building & testing for package collections"-            , "  - for COLL in \"${COLLS[@]}\"; do"-            , "      echo \"== collection $COLL ==\";"-            , "      ghc-travis collection ${COLL} > /dev/null || break;"-            , "      ghc-travis collection ${COLL} | " ++ pkgFilter ++ " > cabal.project.freeze;"-            , "      grep ' collection-id' cabal.project.freeze;"-            , "      rm -rf dist-newstyle/;"-            , "      ${CABAL} new-build -w ${HC} ${TEST} ${BENCH} all || break;"-            , "      if [ \"x$TEST\" = \"x--enable-tests\" ]; then ${CABAL} new-test -w ${HC} ${TEST} ${BENCH} all || break; fi;"-            , "    done"-            , ""-            ]--    -- Have to build last, as we remove cabal.project.local-    unless (equivVersionRanges noVersion $ cfgUnconstrainted config) $ foldedTellStrLns FoldBuildInstalled-        "Building without installed constraints for packages in global-db..." folds $ tellStrLns-        [ comment "Build without installed constraints for packages in global-db"-        , shForJob versions' (cfgUnconstrainted config) "rm -f cabal.project.local; ${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks all;"-        , ""-        ]--    -- and now, as we don't have cabal.project.local;-    -- we can test with other constraint sets-    let constraintSets = cfgConstraintSets config-    unless (null constraintSets) $ do-        tellStrLns-            [ comment "Constraint sets"-            , sh "rm -rf cabal.project.local"-            , ""-            ]-        forM_ constraintSets $ \cs -> do-            let name = csName cs-            let constraintFlags = concatMap (\x ->  " --constraint='" ++ x ++ "'") (csConstraints cs)-            let cmd | csRunTests cs = "${CABAL} new-test  -w ${HC} --enable-tests  --enable-benchmarks"-                    | otherwise     = "${CABAL} new-build -w ${HC} --disable-tests --disable-benchmarks"-            tellStrLns [ comment $ "Constraint set " ++ name ]-            foldedTellStrLns' FoldConstraintSets name ("Constraint set " ++ name) folds $ tellStrLns-                [ shForJob versions' (csGhcVersions cs) $-                  cmd ++ " " ++ constraintFlags ++ " all"-                , ""-                ]-        tellStrLns [""]--    tellStrLnsRaw-        [ "# REGENDATA " ++ show argv-        , "# EOF"-        ]--    return ()-  where-    doctestConfig = cfgDoctest config-    hlintConfig   = cfgHLint config--    hasTests   = F.any (\Pkg{pkgGpd} -> not . null $ condTestSuites pkgGpd) pkgs-    hasLibrary = F.any (\Pkg{pkgGpd} -> isJust $ condLibrary pkgGpd) pkgs--    -- GHC versions which need head.hackage-    headGhcVers = S.filter previewGHC versions--    generateCabalProject dist = do-        tellStrLns-            [ sh "rm -f cabal.project"-            , sh "touch cabal.project"-            ]-        F.forM_  pkgs $ \pkg -> do-            let p | dist      = pkgName pkg ++ "-*/*.cabal"-                  | otherwise = pkgDir pkg-            tellStrLns $-                [ shForJob versions' (pkgJobs pkg) $ "printf 'packages: \"" ++ p ++ "\"\\n' >> cabal.project"-                ]--        case cfgCopyFields config of-            CopyFieldsNone -> return ()-            CopyFieldsAll  -> unless (null (prjOrigFields prj)) $ tellStrLns-                [ sh $ "echo '" ++ l ++ "' >> cabal.project"-                | l <- lines $ C.showFields' 2 $ prjOrigFields prj-                , not (null l)-                ]-            CopyFieldsSome -> do-                F.forM_ (prjConstraints prj) $ \xs -> do-                    let s = concat (lines xs)-                    tellStrLns-                        [ sh $ "echo 'constraints: " ++ s ++ "' >> cabal.project"-                        ]-                F.forM_ (prjAllowNewer prj) $ \xs -> do-                    let s = concat (lines xs)-                    tellStrLns-                        [ sh $ "echo 'allow-newer: " ++ s ++ "' >> cabal.project"-                        ]--                when (prjReorderGoals prj) $-                    tellStrLns-                        [ sh $ "echo 'reorder-goals: True' >> cabal.project"-                        ]--                F.forM_ (prjMaxBackjumps prj) $ \bj ->-                    tellStrLns-                        [ sh $ "echo 'max-backjumps: " ++ show bj ++ "' >> cabal.project"-                        ]--                case prjOptimization prj of-                    OptimizationOn      -> return ()-                    OptimizationOff     -> tellStrLns [ sh $ "echo 'optimization: False' >> cabal.project " ]-                    OptimizationLevel l -> tellStrLns [ sh $ "echo 'optimization: " ++ show l ++ "' >> cabal.project " ]--                F.forM_ (prjSourceRepos prj) $ \repo -> do-                    let repo' = PP.render $ C.prettyFieldGrammar (C.sourceRepoFieldGrammar $ C.RepoKindUnknown "unused") repo-                    tellStrLns [ sh $ "echo 'source-repository-package' >> cabal.project" ]-                    tellStrLns [ sh $ "echo '  " ++ l ++ "' >> cabal.project" | l <- lines repo' ]---        unless (null (cfgLocalGhcOptions config)) $ forM_ pkgs $ \Pkg{pkgName} -> do-            let s = unwords $ map (show . PU.showToken) $ cfgLocalGhcOptions config-            tellStrLns-                [ sh $ "echo 'package " ++ pkgName ++ "' >> cabal.project"-                , sh $ "echo '  ghc-options: " ++ s ++ "' >> cabal.project"-                ]--        -- raw-project is after local-ghc-options so we can override per package.-        unless (null (cfgRawProject config)) $ tellStrLns-            [ sh $ "echo '" ++ l ++ "' >> cabal.project"-            | l <- lines $ C.showFields' 2 $ cfgRawProject config-            , not (null l)-            ]--        -- mandatory cabal.project setup-        -- this have to be last, so configuration doesn't override it.-        tellStrLns-            [ sh $ "printf 'write-ghc-environment-files: always\\n' >> cabal.project"-            ]--        -- also write cabal.project.local file with-        -- @-        -- constraints: base installed-        -- constraints: array installed-        -- ...-        ---        -- omitting any local package names-        case normaliseInstalled (cfgInstalled config) of-            InstalledDiff pns -> tellStrLns-                [ sh $ "touch cabal.project.local"-                , sh $ unwords-                    [ "for pkg in $($HCPKG list --simple-output); do"-                    , "echo $pkg"-                    , "| sed 's/-[^-]*$//'"-                    , "| grep -vE -- " ++ re-                    , "| sed 's/^/constraints: /'"-                    , "| sed 's/$/ installed/'"-                    , ">> cabal.project.local; done"-                    ]-                ]-              where-                pns' = S.map unPackageName pns `S.union` foldMap (S.singleton . pkgName) pkgs-                re = "'^(" ++ intercalate "|" (S.toList pns') ++ ")$'"--            InstalledOnly pns | not (null pns') -> tellStrLns-                [ sh $ "touch cabal.project.local"-                , sh' [2043] $ unwords-                    [ "for pkg in " ++ unwords (S.toList pns') ++ "; do"-                    , "echo \"constraints: $pkg installed\" >> cabal.project"-                    , ">> cabal.project.local; done"-                    ]-                ]-              where-                pns' = S.map unPackageName pns `S.difference` foldMap (S.singleton . pkgName) pkgs--            -- otherwise: nothing-            _ -> pure ()--        tellStrLns-            [ sh $ "cat cabal.project || true"-            , sh $ "cat cabal.project.local || true"-            ]--    projectFile :: FilePath-    projectFile = fromMaybe "cabal.project" isCabalProject--    quotedPaths :: (Package -> FilePath) -> [String]-    quotedPaths f = map (f . quote) pkgs-      where-        quote pkg = pkg{ pkgDir = "\"" ++ pkgDir pkg ++ "\"" }--    showVersions :: Set (Maybe Version) -> String-    showVersions = unwords . map dispGhcVersion . S.toList--    -- specified ersions-    osxVersions' :: Set Version-    osxVersions' = cfgOsx config--    versions :: Set (Maybe Version)-    versions-        | cfgGhcHead config = S.insert Nothing $ S.map Just versions'-        | otherwise         = S.map Just versions'--    ghcVersions :: String-    ghcVersions = showVersions versions--    osxVersions, omittedOsxVersions :: Set Version-    (osxVersions, omittedOsxVersions) = S.partition (`S.member` versions') osxVersions'--    ghcOsxVersions :: String-    ghcOsxVersions = showVersions $ S.map Just osxVersions--    ghcOmittedOsxVersions :: String-    ghcOmittedOsxVersions = showVersions $ S.map Just omittedOsxVersions---collToGhcVer :: String -> Version-collToGhcVer cid = case simpleParse cid of-  Nothing -> error ("invalid collection-id syntax " ++ show cid)-  Just (PackageIdentifier n (versionNumbers -> v))-    | display n /= "lts" -> error ("unknown collection " ++ show cid)-    | isPrefixOf [0] v -> mkVersion [7,8,3]-    | isPrefixOf [1] v -> mkVersion [7,8,4]-    | isPrefixOf [2] v -> mkVersion [7,8,4]-    | isPrefixOf [3] v -> mkVersion [7,10,2]-    | isPrefixOf [4] v -> mkVersion [7,10,3]-    | isPrefixOf [5] v -> mkVersion [7,10,3]-    | isPrefixOf [6] v -> mkVersion [7,10,3]-    | isPrefixOf [7] v -> mkVersion [8,0,1]-    | otherwise -> error ("unknown collection " ++ show cid)------------------------------------------------------------------------------------ Doctest----------------------------------------------------------------------------------doctestJobVersionRange :: VersionRange-doctestJobVersionRange = orLaterVersion $ mkVersion [8,0]---- | Modules arguments to the library------ * We check the library component------ * If there are hs-source-dirs, use them------ * otherwise use exposed + other modules------ * Also add default-extensions------ /Note:/ same argument work for hlint too, but not exactly----doctestArgs :: GenericPackageDescription -> [[String]]-doctestArgs gpd =-    [ libraryModuleArgs c-    | c <- flattenPackageDescription gpd ^.. L.library . traverse-    ] ++-    [ libraryModuleArgs c-    | c <- flattenPackageDescription gpd ^.. L.subLibraries . traverse-    ]--libraryModuleArgs :: PD.Library -> [String]-libraryModuleArgs l-    | null dirsOrMods = []-    | otherwise       = exts ++ dirsOrMods-  where-    bi = l ^. L.buildInfo--    dirsOrMods-        | null (PD.hsSourceDirs bi) = map display (PD.exposedModules l)-        | otherwise                 = PD.hsSourceDirs bi--    exts = map (("-X" ++) . display) (PD.defaultExtensions bi)--executableModuleArgs :: PD.Executable -> [String]-executableModuleArgs e-    | null dirsOrMods = []-    | otherwise       = exts ++ dirsOrMods-  where-    bi = e ^. L.buildInfo--    dirsOrMods-        -- note: we don't try to find main_is location, if hsSourceDirs is empty.-        | null (PD.hsSourceDirs bi) = map display (PD.otherModules bi)-        | otherwise                 = PD.hsSourceDirs bi--    exts = map (("-X" ++) . display) (PD.defaultExtensions bi)------------------------------------------------------------------------------------ HLint----------------------------------------------------------------------------------hlintJobVersionRange :: Set (Maybe Version) -> HLintJob -> VersionRange-hlintJobVersionRange vs HLintJobLatest = case S.maxView vs of-    Just (Just v, _) -> thisVersion v-    _                -> thisVersion $ mkVersion [8,6,3]-hlintJobVersionRange _ (HLintJob v)   = thisVersion v--hlintArgs :: GenericPackageDescription -> [[String]]-hlintArgs gpd =-    [ libraryModuleArgs c-    | c <- flattenPackageDescription gpd ^.. L.library . traverse-    ] ++-    [ libraryModuleArgs c-    | c <- flattenPackageDescription gpd ^.. L.subLibraries . traverse-    ] ++-    [ executableModuleArgs c-    | c <- flattenPackageDescription gpd ^.. L.executables . traverse-    ]+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE MultiWayIf          #-}+{-# LANGUAGE OverloadedLabels    #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- | New-style @.travis.yml@ script generator using cabal 1.24's nix-style+-- tech-preview facilities.+--+-- See also <https://github.com/haskell-CI/haskell-ci>+--+-- NB: This code deliberately avoids relying on non-standard packages and+--     is expected to compile/work with at least GHC 7.0 through GHC 8.0+module HaskellCI (+    main,+    -- * for tests+    parseTravis,+    travisFromConfigFile, Options (..), defaultOptions,+    ) where++import HaskellCI.Prelude++import Data.List                    (intercalate, isPrefixOf, nub, nubBy, sort, sortBy, (\\))+import System.Directory             (canonicalizePath, doesDirectoryExist, doesFileExist, makeRelativeToCurrentDirectory, setCurrentDirectory)+import System.Environment           (getArgs)+import System.Exit                  (ExitCode (..), exitFailure)+import System.FilePath.Posix        (takeDirectory, takeExtension, takeFileName, (</>))+import System.IO                    (hClose, hFlush, hPutStr, hPutStrLn, stderr)+import System.IO.Temp               (withSystemTempFile)+import System.Process               (readProcessWithExitCode)+import Text.ParserCombinators.ReadP (readP_to_S)++import Distribution.PackageDescription        (package, packageDescription, testedWith)+import Distribution.PackageDescription.Parsec (readGenericPackageDescription)+import Distribution.Text+import Distribution.Version++import qualified Data.ByteString       as BS+import qualified Data.List.NonEmpty    as NE+import qualified Data.Set              as S+import qualified Data.Traversable      as T+import qualified Distribution.Compiler as Compiler+import qualified Distribution.Package  as Pkg+import qualified Options.Applicative   as O++import HaskellCI.Cli+import HaskellCI.Compiler+import HaskellCI.Config+import HaskellCI.Config.Dump+import HaskellCI.Diagnostics+import HaskellCI.Glob+import HaskellCI.Jobs+import HaskellCI.Package+import HaskellCI.Project+import HaskellCI.TestedWith+import HaskellCI.Travis+import HaskellCI.YamlSyntax++-------------------------------------------------------------------------------+-- Main+-------------------------------------------------------------------------------++main :: IO ()+main = do+    argv0 <- getArgs+    (cmd, opts) <- O.execParser cliParserInfo+    case cmd of+        CommandListGHC -> do+            putStrLn $ "Supported GHC versions:"+            for_ groupedVersions $ \(v, vs) -> do+                putStr $ prettyMajVersion v ++ ": "+                putStrLn $ intercalate ", " (map display $ toList vs)+        CommandDumpConfig -> do+            putStr $ unlines $ runDG configGrammar++        CommandRegenerate -> do+            let fp = case optOutput opts of+                    Just (OutputFile fp') -> fp'+                    _                     -> defaultTravisPath++            -- read, and then change to the directory+            contents <- readFile fp+            absFp <- canonicalizePath fp+            let dir = takeDirectory fp+            setCurrentDirectory dir+            newFp <- makeRelativeToCurrentDirectory absFp++            case findArgv (lines contents) of+                Nothing     -> do+                    hPutStrLn stderr $ "Error: expected REGENDATA line in " ++ fp+                    exitFailure+                Just argv   -> do+                    (f, opts') <- parseTravis argv+                    doTravis argv f (optionsWithOutputFile newFp <> opts' <> opts)+        CommandTravis f -> doTravis argv0 f opts+  where+    findArgv :: [String] -> Maybe [String]+    findArgv ls = do+        l <- findMaybe (afterInfix "REGENDATA") ls+        readMaybe l++    groupedVersions :: [(Version, NonEmpty Version)]+    groupedVersions = map ((\vs -> (head vs, vs)) . NE.sortBy (flip compare))+                    . groupBy ((==) `on` ghcMajVer)+                    $ sort knownGhcVersions++    prettyMajVersion :: Version -> String+    prettyMajVersion v = case ghcMajVer v of+        (x, y) -> show x ++ "." ++ show y++defaultTravisPath :: FilePath+defaultTravisPath = ".travis.yml"++doTravis :: [String] -> FilePath -> Options -> IO ()+doTravis args path opts = do+    ls <- travisFromConfigFile args opts path+    let contents = unlines ls+    case optOutput opts of+        Nothing              -> writeFile defaultTravisPath contents+        Just OutputStdout    -> putStr contents+        Just (OutputFile fp) -> writeFile fp contents++travisFromConfigFile+    :: forall m. (MonadIO m, MonadDiagnostics m, MonadMask m)+    => [String]+    -> Options+    -> FilePath+    -> m [String]+travisFromConfigFile args opts path = do+    cabalFiles <- getCabalFiles+    config' <- maybe (return emptyConfig) readConfigFile (optConfig opts)+    let config = optConfigMorphism opts config'+    pkgs <- T.mapM (configFromCabalFile config) cabalFiles+    (ghcs, prj) <- case checkVersions (cfgTestedWith config) pkgs of+        Right x     -> return x+        Left []     -> putStrLnErr "panic: checkVersions failed without errors"+        Left (e:es) -> putStrLnErrs (e :| es)++    let prj' | cfgGhcHead config = over (mapped . #pkgJobs) (S.insert GHCHead) prj+             | otherwise         = prj++    ls <- genTravisFromConfigs args config prj' ghcs+    patchTravis config ls+  where+    isCabalProject :: Maybe FilePath+    isCabalProject+        | "cabal.project" `isPrefixOf` takeFileName path = Just path+        | otherwise = Nothing++    getCabalFiles :: m (Project Void FilePath)+    getCabalFiles+        | isNothing isCabalProject = return $ emptyProject & #prjPackages .~ [path]+        | otherwise = do+            contents <- liftIO $ BS.readFile path+            prj  <- either putStrLnErr return $ parseProjectFile path contents+            prj' <- bitraverse findOptProjectPackage findProjectPackage prj+            return prj'+                { prjPackages    = concat $ prjPackages prj' ++ prjOptPackages prj'+                , prjOptPackages = []+                }++    rootdir = takeDirectory path++    -- See findProjectPackages in cabal-install codebase+    -- this is simple variant.+    findProjectPackage :: String -> m [FilePath]+    findProjectPackage pkglocstr = do+        mfp <- checkisFileGlobPackage pkglocstr `mplusMaybeT`+               checkIsSingleFilePackage pkglocstr+        maybe (putStrLnErr $ "bad package location: " ++ pkglocstr) return mfp++    findOptProjectPackage :: String -> m [FilePath]+    findOptProjectPackage pkglocstr = do+        mfp <- checkisFileGlobPackage pkglocstr `mplusMaybeT`+               checkIsSingleFilePackage pkglocstr+        maybe (return []) return mfp++    checkIsSingleFilePackage pkglocstr = do+        let abspath = rootdir </> pkglocstr+        isFile <- liftIO $ doesFileExist abspath+        isDir  <- liftIO $ doesDirectoryExist abspath+        if | isFile && takeExtension pkglocstr == ".cabal" -> return (Just [abspath])+           | isDir -> checkisFileGlobPackage (pkglocstr </> "*.cabal")+           | otherwise -> return Nothing++    -- if it looks like glob, glob+    checkisFileGlobPackage pkglocstr =+        case filter (null . snd) $ readP_to_S parseFilePathGlobRel pkglocstr of+            [(g, "")] -> do+                files <- liftIO $ expandRelGlob rootdir g+                let files' = filter ((== ".cabal") . takeExtension) files+                -- if nothing is matched, skip.+                if null files' then return Nothing else return (Just files')+            _         -> return Nothing++    mplusMaybeT :: Monad m => m (Maybe a) -> m (Maybe a) -> m (Maybe a)+    mplusMaybeT ma mb = do+        mx <- ma+        case mx of+            Nothing -> mb+            Just x  -> return (Just x)++genTravisFromConfigs+    :: (Monad m, MonadDiagnostics m)+    => [String]+    -> Config+    -> Project Void Package+    -> Set CompilerVersion+    -> m [String]+genTravisFromConfigs argv config prj vs = do+    let jobVersions = makeJobVersions config vs+    case makeTravis argv config prj jobVersions of+        Left err     -> putStrLnErr $ displayException err+        Right travis -> do+            describeJobs (cfgTestedWith config) jobVersions (prjPackages prj)+            return $+                lines (prettyYaml id $ reann (travisHeader (cfgInsertVersion config) argv ++) $ toYaml travis)+                +++                [ ""+                , "# REGENDATA " ++ show argv+                , "# EOF"+                ]++-- | Adjust the generated Travis YAML output with patch files, if specified.+-- We do this in a temporary file in case the user did not pass --output (as+-- it would be awkward to patch the generated output otherwise).+patchTravis+    :: (MonadIO m, MonadMask m)+    => Config -> [String] -> m [String]+patchTravis cfg ls+  | null patches = pure ls+  | otherwise =+      withSystemTempFile ".travis.yml.tmp" $ \fp h -> liftIO $ do+        hPutStr h $ unlines ls+        hFlush h+        for_ patches $ applyPatch fp+        hClose h+        lines <$> readFile fp+  where+    patches :: [FilePath]+    patches = cfgTravisPatches cfg++    applyPatch :: FilePath -- ^ The temporary file path to patch+               -> FilePath -- ^ The path of the .patch file+               -> IO ()+    applyPatch temp patch = do+        exists <- doesFileExist patch+        unless exists $ putStrLnErr $ "Cannot find " ++ patch+        (ec, stdOut, stdErr) <- readProcessWithExitCode+            "patch" [ "--input", patch+            , "--silent"+            , temp+            ] ""+        case ec of+            ExitSuccess -> pure ()+            ExitFailure n -> putStrLnErr $ unlines+                [ "patch returned exit code " ++ show n+                , "Stdout: " ++ stdOut+                , "Stderr: " ++ stdErr+                ]++configFromCabalFile+    :: (MonadIO m, MonadDiagnostics m)+    => Config -> FilePath -> m Package+configFromCabalFile cfg cabalFile = do+    gpd <- liftIO $ readGenericPackageDescription maxBound cabalFile++    let compilers = testedWith $ packageDescription gpd+        pkgNameStr = display $ Pkg.pkgName $ package $ packageDescription gpd++    let unknownComps = nub [ c | (c,_) <- compilers, c /= Compiler.GHC, c /= Compiler.GHCJS ]++        ghcVerConstrs   = [ vc | (Compiler.GHC,vc) <- compilers ]+        ghcVerConstrs'  = simplifyVersionRange $ foldr unionVersionRanges noVersion ghcVerConstrs+        specificGhcVers = nub $ mapMaybe isSpecificVersion ghcVerConstrs++        ghcjsVerConstrs   = [ vc | (Compiler.GHCJS,vc) <- compilers ]+        ghcjsVerConstrs'  = simplifyVersionRange $ foldr unionVersionRanges noVersion ghcjsVerConstrs+        specificGhcjsVers = nub $ mapMaybe isSpecificVersion ghcjsVerConstrs++        twoDigitGhcVerConstrs = mapMaybe isTwoDigitGhcVersion ghcVerConstrs :: [Version]++    unless (null twoDigitGhcVerConstrs) $ do+        putStrLnWarn $ "'tested-with:' uses two digit GHC versions (which don't match any existing GHC version): " ++ intercalate ", " (map display twoDigitGhcVerConstrs)+        putStrLnInfo $ "Either use wild-card format, for example 'tested-with: GHC ==7.10.*' or a specific existing version 'tested-with: GHC ==7.10.3'"++    when (null compilers) $ do+        putStrLnErr (unlines $+                     [ "empty or missing top-level 'tested-with:' definition in " ++ cabalFile ++ " file; example definition:"+                     , ""+                     , "tested-with: " ++ intercalate ", " [ "GHC==" ++ display v | v <- lastStableGhcVers ]+                     ])++    unless (null unknownComps) $ do+        putStrLnWarn $ "ignoring unsupported compilers mentioned in tested-with: " ++ show unknownComps++    when (null ghcVerConstrs) $ do+        putStrLnErr "'tested-with:' doesn't mention any 'GHC' version"++    when (isNoVersion ghcVerConstrs') $ do+        putStrLnErr "'tested-with:' describes an empty version range for 'GHC'"++    when (isAnyVersion ghcVerConstrs') $ do+        putStrLnErr "'tested-with:' allows /any/ 'GHC' version"++    let unknownGhcVers = sort $ specificGhcVers \\ knownGhcVersions+    unless (null unknownGhcVers) $ do+        putStrLnErr ("'tested-with:' specifically refers to unknown 'GHC' versions: "+                     ++ intercalate ", " (map display unknownGhcVers) ++ "\n"+                     ++ "Known GHC versions: " ++ intercalate ", " (map display knownGhcVersions))++    let unknownGhcjsVers = sort $ specificGhcjsVers \\ knownGhcjsVersions+    unless (null unknownGhcjsVers) $ do+        putStrLnErr ("'tested-with:' specifically refers to unknown 'GHCJS' versions: "+                     ++ intercalate ", " (map display unknownGhcjsVers) ++ "\n"+                     ++ "Known GHCJS versions: " ++ intercalate ", " (map display knownGhcjsVersions))++    let knownGhcVersions'+            | cfgLastInSeries cfg = filterLastMajor knownGhcVersions+            | otherwise           = knownGhcVersions++    let testedGhcVersions   = filter (`withinRange` ghcVerConstrs') knownGhcVersions'+    let testedGhcjsVersions = filter (`withinRange` ghcjsVerConstrs') knownGhcjsVersions++    when (null testedGhcVersions) $ do+        putStrLnErr "no known GHC version is allowed by the 'tested-with' specification"++    let compilerRange :: Set CompilerVersion+        compilerRange = S.fromList $+            [ GHC v+            | v <- testedGhcVersions+            ] +++            [ GHCJS v+            | v <- testedGhcjsVersions+            ]++    let pkg = Pkg pkgNameStr compilerRange (takeDirectory cabalFile) gpd++    return pkg+  where+    lastStableGhcVers+        = nubBy ((==) `on` ghcMajVer)+        $ sortBy (flip compare)+        $ filter (not . previewGHC defaultHeadHackage . GHC)+        $ knownGhcVersions++    isTwoDigitGhcVersion :: VersionRange -> Maybe Version+    isTwoDigitGhcVersion vr = isSpecificVersion vr >>= t+      where+        t v | [_,_] <- versionNumbers v = Just v+        t _                             = Nothing++    filterLastMajor = map maximum . groupBy ((==) `on` ghcMajVer)
src/HaskellCI/Cli.hs view
@@ -1,18 +1,22 @@+{-# LANGUAGE CPP #-}+ -- | Most of client interface. module HaskellCI.Cli where -import           Prelude                  ()-import           Prelude.Compat+import HaskellCI.Prelude -import           Control.Applicative      ((<|>))-import           System.Exit              (exitFailure)-import           System.IO                (hPutStrLn, stderr)+import System.Exit (exitFailure)+import System.IO   (hPutStrLn, stderr) -import qualified Options.Applicative      as O+import qualified Options.Applicative as O -import           HaskellCI.Config-import           HaskellCI.OptparseGrammar+import HaskellCI.Config+import HaskellCI.OptparseGrammar +#ifndef CURRENT_PACKAGE_VERSION+#define CURRENT_PACKAGE_VERSION "???"+#endif+ ------------------------------------------------------------------------------- -- Command -------------------------------------------------------------------------------@@ -29,37 +33,56 @@ -------------------------------------------------------------------------------  data Options = Options-    { optCollections    :: [String]-    , optOutput         :: Maybe FilePath+    { optOutput         :: Maybe Output     , optConfig         :: Maybe FilePath     , optConfigMorphism :: Config -> Config     } +data Output = OutputStdout | OutputFile FilePath+ instance Semigroup Options where-    Options a b d e <> Options a' b' d' e' =-        Options (a <> a') (b <|> b') (d <|> d') (e' . e)+    Options b d e <> Options b' d' e' =+        Options (b <|> b') (d <|> d') (e' . e)  defaultOptions :: Options defaultOptions = Options-    { optCollections    = []-    , optOutput         = Nothing+    { optOutput         = Nothing     , optConfig         = Nothing     , optConfigMorphism = id     } +optionsWithOutputFile :: FilePath -> Options+optionsWithOutputFile fp = defaultOptions+    { optOutput = Just (OutputFile fp)+    }+ ------------------------------------------------------------------------------- -- Parsers -------------------------------------------------------------------------------  optionsP :: O.Parser Options optionsP = Options-    <$> pure []-    <*> O.optional (O.strOption (O.long "output" <> O.short 'o' <> O.metavar "FILE" <> O.help "Optput file (stdout if omitted)"))+    <$> O.optional outputP     <*> O.optional (O.strOption (O.long "config" <> O.metavar "CONFIGFILE" <> O.help "Configuration file"))     <*> runOptparseGrammar configGrammar +outputP :: O.Parser Output+outputP =+    OutputFile <$> O.strOption (O.long "output" <> O.short 'o' <> O.metavar "FILE" <> O.help "Output file") <|>+    O.flag' OutputStdout (O.long "stdout" <> O.help "Use stdout output")++versionP :: O.Parser (a -> a)+versionP = O.infoOption haskellCIVerStr $ mconcat+    [ O.long "version"+    , O.short 'V'+    , O.help "Print version information"+    ]++haskellCIVerStr :: String+haskellCIVerStr = CURRENT_PACKAGE_VERSION+ cliParserInfo :: O.ParserInfo (Command, Options)-cliParserInfo = O.info ((,) <$> cmdP <*> optionsP O.<**> O.helper) $ mconcat+cliParserInfo = O.info ((,) <$> cmdP <*> optionsP O.<**> versionP O.<**> O.helper) $ mconcat     [ O.fullDesc     , O.header "haskell-ci - generate CI scripts for Haskell projects"     ]@@ -68,7 +91,7 @@         [ O.command "regenerate"  $ O.info (pure CommandRegenerate) $ O.progDesc "Regenerate .travis.yml"         , O.command "travis"      $ O.info travisP                  $ O.progDesc "Generate travis-ci config"         , O.command "list-ghc"    $ O.info (pure CommandListGHC)    $ O.progDesc "List known GHC versions"-        , O.command "dump-config" $ O.info (pure CommandDumpConfig) $ O.progDesc "Dump cabal.haskell-ci config with default values" +        , O.command "dump-config" $ O.info (pure CommandDumpConfig) $ O.progDesc "Dump cabal.haskell-ci config with default values"         ]) <|> travisP      travisP = CommandTravis
+ src/HaskellCI/Compiler.hs view
@@ -0,0 +1,165 @@+-- | This module encodes what we know about GHC, including existing/supported versions.+module HaskellCI.Compiler (+    -- * Compiler version+    CompilerVersion (..),+    maybeGHC,+    isGHCJS,+    previewGHC,+    -- * Compiler version range+    CompilerRange (..),+    compilerWithinRange,+    invertCompilerRange,+    -- * Known versions+    knownGhcVersions,+    knownGhcjsVersions,+    -- * Showing+    dispGhcVersion,+    dispGhcVersionShort,+    dispCabalVersion,+    -- * Cabal version+    correspondingCabalVersion,+    -- * Misc+    ghcMajVer,+    ) where++import HaskellCI.Prelude++import Data.Set             (Set)+import Distribution.Version (Version, VersionRange, hasUpperBound, invertVersionRange, mkVersion, versionNumbers, withinRange)++import qualified Data.Set            as S+import qualified Distribution.Pretty as C++-------------------------------------------------------------------------------+-- CompilerVersion+-------------------------------------------------------------------------------++data CompilerVersion+    = GHCHead+    | GHC Version+    | GHCJS Version+  deriving (Eq, Ord, Show)++maybeGHC :: a -> (Version -> a) -> CompilerVersion -> a+maybeGHC _ f (GHC v) = f v+maybeGHC x _ _       = x++isGHCJS :: CompilerVersion -> Bool+isGHCJS (GHCJS _) = True+isGHCJS _         = False++-------------------------------------------------------------------------------+-- CompilerRange+-------------------------------------------------------------------------------++data CompilerRange+    = Range VersionRange+    | RangeGHC+    | RangeGHCJS+    | RangePoints (Set CompilerVersion)+    | RangeInter CompilerRange CompilerRange+    | RangeUnion CompilerRange CompilerRange+  deriving (Show)++instance Lattice CompilerRange where+    (/\) = RangeInter+    (\/) = RangeUnion++instance BoundedJoinSemiLattice CompilerRange where+    bottom = RangePoints S.empty++instance BoundedMeetSemiLattice CompilerRange where+    top = RangePoints allCompilerVersions++compilerWithinRange :: CompilerVersion -> CompilerRange -> Bool+compilerWithinRange v         (RangeInter a b) = compilerWithinRange v a /\ compilerWithinRange v b+compilerWithinRange v         (RangeUnion a b) = compilerWithinRange v a \/ compilerWithinRange v b+compilerWithinRange (GHC v)   (Range vr)       = withinRange v vr+compilerWithinRange (GHCJS v) (Range vr)       = withinRange v vr+compilerWithinRange GHCHead   (Range vr)       = not (hasUpperBound vr)+compilerWithinRange (GHC _)   RangeGHC         = True+compilerWithinRange GHCHead   RangeGHC         = True+compilerWithinRange (GHCJS _) RangeGHC         = False+compilerWithinRange (GHC _)   RangeGHCJS       = False+compilerWithinRange GHCHead   RangeGHCJS       = False+compilerWithinRange (GHCJS _) RangeGHCJS       = True+compilerWithinRange v         (RangePoints vs) = S.member v vs++invertCompilerRange :: CompilerRange -> CompilerRange+invertCompilerRange (Range vr)       = Range (invertVersionRange vr)+invertCompilerRange RangeGHC         = RangeGHCJS+invertCompilerRange RangeGHCJS       = RangeGHC+invertCompilerRange (RangeInter a b) = RangeUnion (invertCompilerRange a) (invertCompilerRange b)+invertCompilerRange (RangeUnion a b) = RangeInter (invertCompilerRange a) (invertCompilerRange b)+invertCompilerRange (RangePoints vs) = RangePoints (S.difference allCompilerVersions vs)++-------------------------------------------------------------------------------+-- Known versions+-------------------------------------------------------------------------------++knownGhcVersions :: [Version]+knownGhcVersions = fmap mkVersion+    [ [7,0,1],  [7,0,2], [7,0,3], [7,0,4]+    , [7,2,1],  [7,2,2]+    , [7,4,1],  [7,4,2]+    , [7,6,1],  [7,6,2], [7,6,3]+    , [7,8,1],  [7,8,2], [7,8,3], [7,8,4]+    , [7,10,1], [7,10,2], [7,10,3]+    , [8,0,1],  [8,0,2]+    , [8,2,1],  [8,2,2]+    , [8,4,1],  [8,4,2], [8,4,3], [8,4,4]+    , [8,6,1],  [8,6,2], [8,6,3], [8,6,4], [8,6,5]+    , [8,8,1]+    ]++knownGhcjsVersions :: [Version]+knownGhcjsVersions = fmap mkVersion+    [ [8,4]+    ]++allCompilerVersions :: Set CompilerVersion+allCompilerVersions = S.insert GHCHead $ S.fromList $+    [ GHC v | v <- knownGhcVersions ] +++    [ GHCJS v | v <- knownGhcjsVersions ]++-------------------------------------------------------------------------------+-- Combinators+-------------------------------------------------------------------------------++correspondingCabalVersion+    :: Maybe Version    -- ^ Preferred Cabal Version+    -> CompilerVersion  -- ^ GHC Version+    -> Maybe Version+correspondingCabalVersion Nothing   _         = Nothing+correspondingCabalVersion (Just _)  GHCHead   = Nothing+correspondingCabalVersion (Just _)  (GHCJS _) = Just (mkVersion [3,0])+correspondingCabalVersion (Just cv) (GHC gv)+    | gv >= mkVersion [8,8] = Just $ max (mkVersion [3,0]) cv+    | otherwise             = Just $ max (mkVersion [2,4]) cv++dispGhcVersion :: CompilerVersion -> String+dispGhcVersion GHCHead   = "ghc-head"+dispGhcVersion (GHC v)   = "ghc-" ++ C.prettyShow v+dispGhcVersion (GHCJS v) = "ghcjs-" ++ C.prettyShow v++dispGhcVersionShort :: CompilerVersion -> String+dispGhcVersionShort GHCHead   = "ghc-head"+dispGhcVersionShort (GHC v)   = C.prettyShow v+dispGhcVersionShort (GHCJS v) = "ghcjs-" ++ C.prettyShow v++dispCabalVersion :: Maybe Version -> String+dispCabalVersion = maybe "head" C.prettyShow++-- | Alphas, RCs and HEAD.+previewGHC+    :: VersionRange     -- ^ head.hackage range+    -> CompilerVersion+    -> Bool+previewGHC _vr GHCHead   = True+previewGHC  vr (GHC v)   = withinRange v vr || odd (snd (ghcMajVer v))+previewGHC _vr (GHCJS _) = False++ghcMajVer :: Version -> (Int,Int)+ghcMajVer v+    | x:y:_ <- versionNumbers v = (x,y)+    | otherwise = error $ "panic: ghcMajVer called with " ++ show v
src/HaskellCI/Config.hs view
@@ -4,16 +4,12 @@ {-# LANGUAGE OverloadedStrings     #-} module HaskellCI.Config where -import           Control.Monad.IO.Class          (MonadIO (..))-import           Data.Coerce                     (coerce)-import           Data.Generics.Labels            ()-import           Distribution.Simple.Utils       (fromUTF8BS)-import           Distribution.Types.Version      (Version)-import           Distribution.Types.VersionRange (VersionRange, anyVersion,-                                                  noVersion)-import           GHC.Generics                    (Generic)-import           Lens.Micro                      (over)+import HaskellCI.Prelude +import Distribution.Simple.Utils       (fromUTF8BS)+import Distribution.Types.Version      (Version)+import Distribution.Types.VersionRange (VersionRange, anyVersion, noVersion)+ import qualified Data.ByteString                 as BS import qualified Data.Map                        as M import qualified Data.Set                        as S@@ -21,44 +17,50 @@ import qualified Distribution.Compat.CharParsing as C import qualified Distribution.Compat.Newtype     as C import qualified Distribution.FieldGrammar       as C-import qualified Distribution.Fields.Pretty      as C-import qualified Distribution.Parsec.Class       as C-import qualified Distribution.Parsec.Common      as C+import qualified Distribution.Fields             as C+import qualified Distribution.Parsec             as C import qualified Distribution.Parsec.Newtypes    as C-import qualified Distribution.Parsec.Parser      as C-import qualified Distribution.Parsec.ParseResult as C import qualified Distribution.Pretty             as C import qualified Distribution.Types.Version      as C+import qualified Distribution.Types.VersionRange as C import qualified Text.PrettyPrint                as PP -import           HaskellCI.Config.ConstraintSet-import           HaskellCI.Config.CopyFields-import           HaskellCI.Config.Doctest-import           HaskellCI.Config.Folds-import           HaskellCI.Config.HLint-import           HaskellCI.Config.Installed-import           HaskellCI.Config.Jobs-import           HaskellCI.Newtypes-import           HaskellCI.OptionsGrammar-import           HaskellCI.ParsecUtils-import           HaskellCI.TestedWith+import HaskellCI.Config.ConstraintSet+import HaskellCI.Config.CopyFields+import HaskellCI.Config.Doctest+import HaskellCI.Config.Folds+import HaskellCI.Config.HLint+import HaskellCI.Config.Installed+import HaskellCI.Config.Jobs+import HaskellCI.Config.Ubuntu+import HaskellCI.Newtypes+import HaskellCI.OptionsGrammar+import HaskellCI.ParsecUtils+import HaskellCI.TestedWith +defaultHeadHackage :: VersionRange+defaultHeadHackage = C.orLaterVersion (C.mkVersion [8,9])+ -- TODO: split other blocks like DoctestConfig data Config = Config     { cfgCabalInstallVersion :: Maybe Version     , cfgJobs                :: Maybe Jobs+    , cfgUbuntu              :: !Ubuntu     , cfgTestedWith          :: !TestedWithJobs     , cfgCopyFields          :: !CopyFields     , cfgLocalGhcOptions     :: [String]+    , cfgSubmodules          :: !Bool     , cfgCache               :: !Bool-    , cfgNoise               :: !Bool     , cfgInstallDeps         :: !Bool     , cfgInstalled           :: [Installed]     , cfgTests               :: !VersionRange+    , cfgRunTests            :: !VersionRange     , cfgBenchmarks          :: !VersionRange     , cfgHaddock             :: !VersionRange     , cfgNoTestsNoBench      :: !VersionRange     , cfgUnconstrainted      :: !VersionRange+    , cfgHeadHackage         :: !VersionRange+    , cfgGhcjsTests          :: !Bool     , cfgCheck               :: !Bool     , cfgOnlyBranches        :: [String]     , cfgIrcChannels         :: [String]@@ -71,26 +73,31 @@     , cfgLastInSeries        :: !Bool     , cfgOsx                 :: S.Set Version     , cfgApt                 :: S.Set String+    , cfgTravisPatches       :: [FilePath]+    , cfgInsertVersion       :: !Bool+    , cfgColor               :: !Bool     , cfgDoctest             :: !DoctestConfig     , cfgHLint               :: !HLintConfig     , cfgConstraintSets      :: [ConstraintSet]-    , cfgRawProject          :: [C.PrettyField]+    , cfgRawProject          :: [C.PrettyField ()]     }-  deriving (Show, Generic)+  deriving (Generic)  defaultCabalInstallVersion :: Maybe Version-defaultCabalInstallVersion = Just (C.mkVersion [2,4])+defaultCabalInstallVersion = Just (C.mkVersion [3,0])  emptyConfig :: Config emptyConfig = Config     { cfgCabalInstallVersion = defaultCabalInstallVersion     , cfgJobs            = Nothing+    , cfgUbuntu          = Xenial     , cfgTestedWith      = TestedWithUniform     , cfgCopyFields      = CopyFieldsSome     , cfgDoctest         = DoctestConfig-        { cfgDoctestEnabled = False-        , cfgDoctestOptions = []-        , cfgDoctestVersion = defaultDoctestVersion+        { cfgDoctestEnabled    = noVersion+        , cfgDoctestOptions    = []+        , cfgDoctestVersion    = defaultDoctestVersion+        , cfgDoctestFilterPkgs = []         }     , cfgHLint = HLintConfig         { cfgHLintEnabled = False@@ -101,15 +108,18 @@         }     , cfgLocalGhcOptions = []     , cfgConstraintSets  = []+    , cfgSubmodules      = False     , cfgCache           = True-    , cfgNoise           = True     , cfgInstalled       = []     , cfgInstallDeps     = True     , cfgTests           = anyVersion+    , cfgRunTests        = anyVersion     , cfgBenchmarks      = anyVersion     , cfgHaddock         = anyVersion     , cfgNoTestsNoBench  = anyVersion     , cfgUnconstrainted  = anyVersion+    , cfgHeadHackage     = defaultHeadHackage+    , cfgGhcjsTests      = False     , cfgCheck           = True     , cfgOnlyBranches    = []     , cfgIrcChannels     = []@@ -122,6 +132,9 @@     , cfgLastInSeries    = False     , cfgOsx             = S.empty     , cfgApt             = S.empty+    , cfgTravisPatches   = []+    , cfgInsertVersion   = True+    , cfgColor           = True     , cfgRawProject      = []     } @@ -137,22 +150,26 @@         ^^^ metahelp "VERSION" "cabal-install version for all jobs"     <*> C.optionalField       "jobs"                                                          #cfgJobs         ^^^ metahelp "JOBS" "jobs (N:M - cabal:ghc)"+    <*> C.optionalFieldDef    "distribution"                                                  #cfgUbuntu Xenial+        ^^^ metahelp "DIST" "distribution version (xenial, bionic)"     <*> C.optionalFieldDef    "jobs-selection"                                                #cfgTestedWith TestedWithUniform         ^^^ metahelp "uniform|any" "Jobs selection across packages"     <*> C.optionalFieldDef    "copy-fields"                                                   #cfgCopyFields CopyFieldsSome         ^^^ metahelp "none|some|all" "Copy ? fields from cabal.project fields"     <*> C.monoidalFieldAla    "local-ghc-options"         (C.alaList' C.NoCommaFSep C.Token') #cfgLocalGhcOptions         ^^^ metahelp "OPTS" "--ghc-options for local packages"+    <*> C.booleanFieldDef     "submodules"                                                    #cfgSubmodules False+        ^^^ help "Clone submodules, i.e. recursively"     <*> C.booleanFieldDef     "cache"                                                         #cfgCache True         ^^^ help "Disable caching"-    <*> C.booleanFieldDef     "cabal-noise"                                                   #cfgNoise True-        ^^^ help "Make cabal less noisy"     <*> C.booleanFieldDef     "install-dependencies"                                          #cfgInstallDeps True         ^^^ help "Skip separate dependency installation step"     <*> C.monoidalFieldAla    "installed"                 (C.alaList C.FSep)                  #cfgInstalled         ^^^ metahelp "+/-PKG" "Specify 'constraint: ... installed' packages"     <*> rangeField            "tests"                                                         #cfgTests anyVersion-        ^^^ metahelp "RANGE" "Build and run tests with"+        ^^^ metahelp "RANGE" "Build tests with"+    <*> rangeField            "run-tests"                                                     #cfgRunTests anyVersion+        ^^^ metahelp "RANGE" "Run tests with (note: only built tests are run)"     <*> rangeField           "benchmarks"                                                     #cfgBenchmarks anyVersion         ^^^ metahelp "RANGE" "Build benchmarks"     <*> rangeField           "haddock"                                                        #cfgHaddock anyVersion@@ -161,6 +178,10 @@         ^^^ metahelp "RANGE" "Build without tests and benchmarks"     <*> rangeField            "unconstrained"                                                 #cfgUnconstrainted anyVersion         ^^^ metahelp "RANGE" "Make unconstrained build"+    <*> rangeField            "head-hackage"                                                  #cfgHeadHackage defaultHeadHackage+        ^^^ metahelp "RANGE" "Use head.hackage repository. Also marks as allow-failures"+    <*> C.booleanFieldDef "ghcjs-tests"                                                       #cfgGhcjsTests False+        ^^^ help "Run tests with GHCJS (experimental, relies on cabal-plan finding test-suites)"     <*> C.booleanFieldDef "cabal-check"                                                       #cfgCheck True         ^^^ help "Disable cabal check run"     <*> C.monoidalFieldAla    "branches"                  (C.alaList' C.FSep C.Token')        #cfgOnlyBranches@@ -185,6 +206,12 @@         ^^^ metahelp "JOB" "Jobs to additionally build with OSX"     <*> C.monoidalFieldAla    "apt"                       (alaSet' C.NoCommaFSep C.Token')    #cfgApt         ^^^ metahelp "PKG" "Additional apt packages to install"+    <*> C.monoidalFieldAla    "travis-patches"            (C.alaList' C.NoCommaFSep C.Token') #cfgTravisPatches+        ^^^ metahelp "PATCH" ".patch files to apply to the generated Travis YAML file"+    <*> C.booleanFieldDef "insert-version"                                                    #cfgInsertVersion True+        ^^^ help "Don't insert the haskell-ci version into the generated Travis YAML file"+    <*> C.booleanFieldDef     "color"                                                         #cfgColor True+        ^^^ help "Disable coloring cabal output"     <*> C.blurFieldGrammar #cfgDoctest doctestConfigGrammar     <*> C.blurFieldGrammar #cfgHLint   hlintConfigGrammar     <*> pure [] -- constraint sets@@ -214,7 +241,7 @@             return $ over #cfgConstraintSets (cs :)         | name == "raw-project" = do             let fs = C.fromParsecFields cfields-            return $ over #cfgRawProject (++ fs)+            return $ over #cfgRawProject (++ map void fs)         | otherwise = do             C.parseWarning pos C.PWTUnknownSection $ "Unknown section " ++ fromUTF8BS name             return id@@ -224,10 +251,7 @@ -------------------------------------------------------------------------------  newtype Env = Env (M.Map Version String)--instance C.Newtype Env (M.Map Version String) where-    pack = coerce-    unpack = coerce+  deriving anyclass (C.Newtype (M.Map Version String))  instance C.Parsec Env where     parsec = Env . M.fromList <$> C.parsecLeadingCommaList p where
src/HaskellCI/Config/ConstraintSet.hs view
@@ -2,25 +2,26 @@ {-# LANGUAGE OverloadedStrings #-} module HaskellCI.Config.ConstraintSet where -import           Data.Generics.Labels         ()-import           Distribution.Version-import           GHC.Generics                 (Generic)+import HaskellCI.Prelude  import qualified Distribution.FieldGrammar    as C import qualified Distribution.Parsec.Newtypes as C -import           HaskellCI.Newtypes+import HaskellCI.Newtypes  data ConstraintSet = ConstraintSet     { csName        :: String     , csGhcVersions :: VersionRange     , csConstraints :: [String] -- we parse these simply as strings+    , csTests       :: Bool     , csRunTests    :: Bool+    , csBenchmarks  :: Bool+    , csHaddock     :: Bool     }   deriving (Show, Generic)  emptyConstraintSet :: String -> ConstraintSet-emptyConstraintSet n = ConstraintSet n anyVersion [] False+emptyConstraintSet n = ConstraintSet n anyVersion [] False False False False  ------------------------------------------------------------------------------- -- Grammar@@ -32,4 +33,7 @@ constraintSetGrammar name = ConstraintSet name     <$> C.optionalFieldDef "ghc"                                           #csGhcVersions anyVersion     <*> C.monoidalFieldAla "constraints" (C.alaList' C.CommaVCat NoCommas) #csConstraints+    <*> C.booleanFieldDef  "tests"                                         #csTests False     <*> C.booleanFieldDef  "run-tests"                                     #csRunTests False+    <*> C.booleanFieldDef  "benchmarks"                                    #csBenchmarks False+    <*> C.booleanFieldDef  "haddock"                                       #csHaddock False
src/HaskellCI/Config/CopyFields.hs view
@@ -2,8 +2,10 @@ {-# LANGUAGE MultiParamTypeClasses #-} module HaskellCI.Config.CopyFields where +import HaskellCI.Prelude+ import qualified Distribution.Compat.CharParsing as C-import qualified Distribution.Parsec.Class       as C+import qualified Distribution.Parsec             as C import qualified Distribution.Pretty             as C import qualified Text.PrettyPrint                as PP 
src/HaskellCI/Config/Doctest.hs view
@@ -2,19 +2,21 @@ {-# LANGUAGE OverloadedStrings #-} module HaskellCI.Config.Doctest where -import           Data.Generics.Labels         ()-import           Distribution.Version-import           GHC.Generics                 (Generic)+import HaskellCI.Prelude -import qualified Distribution.FieldGrammar    as C-import qualified Distribution.Parsec.Newtypes as C+import Distribution.Version (mkVersion, noVersion, withinVersion) +import qualified Distribution.FieldGrammar      as C+import qualified Distribution.Parsec.Newtypes   as C+import qualified Distribution.Types.PackageName as C+ import HaskellCI.OptionsGrammar  data DoctestConfig = DoctestConfig-    { cfgDoctestEnabled :: !Bool-    , cfgDoctestOptions :: [String]-    , cfgDoctestVersion :: !VersionRange+    { cfgDoctestEnabled    :: !VersionRange+    , cfgDoctestOptions    :: [String]+    , cfgDoctestVersion    :: !VersionRange+    , cfgDoctestFilterPkgs :: ![C.PackageName]     }   deriving (Show, Generic) @@ -29,9 +31,11 @@     :: (OptionsGrammar g, Applicative (g DoctestConfig))     => g DoctestConfig DoctestConfig doctestConfigGrammar = DoctestConfig-    <$> C.booleanFieldDef  "doctest"                                             #cfgDoctestEnabled False+    <$> rangeField         "doctest"                                             #cfgDoctestEnabled noVersion         ^^^ help "Enable Doctest job"     <*> C.monoidalFieldAla "doctest-options" (C.alaList' C.NoCommaFSep C.Token') #cfgDoctestOptions         ^^^ metahelp "OPTS" "Additional Doctest options"     <*> C.optionalFieldDef "doctest-version"                                     #cfgDoctestVersion defaultDoctestVersion         ^^^ metahelp "RANGE" "Doctest version"+    <*> C.monoidalFieldAla "doctest-filter-packages" (C.alaList C.NoCommaFSep)   #cfgDoctestFilterPkgs+        ^^^ metahelp "PKGS" "Filter packages from .ghc.environment file"
src/HaskellCI/Config/Dump.hs view
@@ -1,16 +1,14 @@ module HaskellCI.Config.Dump where -import           Prelude                     ()-import           Prelude.Compat+import HaskellCI.Prelude -import           Data.Coerce                 (coerce)-import           Distribution.Simple.Utils   (fromUTF8BS)+import Distribution.Simple.Utils (fromUTF8BS)  import qualified Distribution.Compat.Newtype as C import qualified Distribution.FieldGrammar   as C import qualified Distribution.Pretty         as C -import           HaskellCI.OptionsGrammar+import HaskellCI.OptionsGrammar  -- TODO: with Cabal-2.6 this can be prettier, using Pretty.Field newtype DumpGrammar s a = DG { runDG :: [String] }@@ -45,10 +43,21 @@         , ""         ] +    freeTextField fn _ = DG+        [ fromUTF8BS fn ++ ":"+        , ""+        ]++    freeTextFieldDef fn _ = DG+        [ fromUTF8BS fn ++ ":"+        , ""+        ]+     prefixedFields _ _   = pure []     knownField _         = pure ()     deprecatedSince _  _ = id     availableSince _ _   = id+    removedIn _ _        = id     hiddenField          = id  instance OptionsGrammar DumpGrammar where
src/HaskellCI/Config/Folds.hs view
@@ -2,15 +2,13 @@ {-# LANGUAGE MultiParamTypeClasses #-} module HaskellCI.Config.Folds where -import           Data.Char                       (isUpper, toLower)-import           Data.Coerce                     (coerce)-import           Data.List                       (intercalate)+import HaskellCI.Prelude  import qualified Data.Map.Strict                 as M import qualified Data.Set                        as S import qualified Distribution.Compat.CharParsing as C import qualified Distribution.Compat.Newtype     as C-import qualified Distribution.Parsec.Class       as C+import qualified Distribution.Parsec             as C import qualified Distribution.Pretty             as C import qualified Text.PrettyPrint                as PP @@ -52,10 +50,7 @@ -------------------------------------------------------------------------------  newtype Folds = Folds { getFolds :: S.Set Fold }--instance C.Newtype Folds (S.Set Fold) where-    pack = coerce-    unpack = coerce+  deriving anyclass (C.Newtype (S.Set Fold))  instance C.Parsec Folds where     parsec = fmap (Folds . S.unions) $ manySpaces $ do
src/HaskellCI/Config/HLint.hs view
@@ -2,14 +2,13 @@ {-# LANGUAGE OverloadedStrings #-} module HaskellCI.Config.HLint where -import           Control.Applicative             ((<|>))-import           Data.Generics.Labels            ()-import           Distribution.Version-import           GHC.Generics                    (Generic)+import HaskellCI.Prelude +import Distribution.Version (withinVersion)+ import qualified Distribution.Compat.CharParsing as C import qualified Distribution.FieldGrammar       as C-import qualified Distribution.Parsec.Class       as C+import qualified Distribution.Parsec             as C import qualified Distribution.Parsec.Newtypes    as C import qualified Distribution.Pretty             as C import qualified Text.PrettyPrint                as PP
src/HaskellCI/Config/Installed.hs view
@@ -1,14 +1,13 @@ module HaskellCI.Config.Installed where -import Control.Applicative ((<|>))-import Data.List (foldl')+import HaskellCI.Prelude -import qualified Distribution.Types.PackageName as C+import qualified Data.Set                        as S import qualified Distribution.Compat.CharParsing as C-import qualified Distribution.Parsec.Class       as C+import qualified Distribution.Parsec             as C import qualified Distribution.Pretty             as C+import qualified Distribution.Types.PackageName  as C import qualified Text.PrettyPrint                as PP-import qualified Data.Set as S  ------------------------------------------------------------------------------- -- Single action
src/HaskellCI/Config/Jobs.hs view
@@ -1,11 +1,11 @@ module HaskellCI.Config.Jobs where -import Control.Applicative ((<|>))+import HaskellCI.Prelude +import qualified Distribution.Compat.CharParsing as C+import qualified Distribution.Parsec             as C import qualified Distribution.Pretty             as C import qualified Text.PrettyPrint                as PP-import qualified Distribution.Compat.CharParsing as C-import qualified Distribution.Parsec.Class       as C  -- | Jobs --
+ src/HaskellCI/Config/Ubuntu.hs view
@@ -0,0 +1,25 @@+module HaskellCI.Config.Ubuntu where++import HaskellCI.Prelude++import qualified Distribution.Parsec as C+import qualified Distribution.Pretty as C+import qualified Text.PrettyPrint    as PP++data Ubuntu = Xenial | Bionic+  deriving (Eq, Ord, Show)++instance C.Parsec Ubuntu where+    parsec = do+        t <- C.parsecToken+        case t of+            "xenial" -> return Xenial+            "bionic" -> return Bionic+            _        -> fail $ "Unknown ubuntu release " ++ t++instance C.Pretty Ubuntu where+    pretty = PP.text . showUbuntu++showUbuntu :: Ubuntu -> String+showUbuntu Xenial = "xenial"+showUbuntu Bionic = "bionic"
+ src/HaskellCI/Diagnostics.hs view
@@ -0,0 +1,45 @@+module HaskellCI.Diagnostics where++import HaskellCI.Prelude++import Control.Monad.Trans.Maybe (MaybeT (..))+import Control.Monad.Writer      (WriterT, runWriterT, tell)+import System.Exit               (exitFailure)+import System.IO                 (hPutStrLn, stderr)++class Monad m => MonadDiagnostics m where+    putStrLnErr  :: String -> m a+    putStrLnErrs :: NonEmpty String -> m a+    putStrLnWarn :: String -> m ()+    putStrLnInfo :: String -> m ()++instance MonadDiagnostics IO where+    putStrLnErr err = do+        hPutStrLn stderr $ "*ERROR* " ++ err+        exitFailure++    putStrLnErrs errs = do+        for_ errs $ \err -> hPutStrLn stderr $ "*ERROR* " ++ err+        exitFailure++    putStrLnWarn = hPutStrLn stderr . ("*WARNING* " ++)+    putStrLnInfo = hPutStrLn stderr . ("*INFO* " ++)++newtype DiagnosticsT m a = Diagnostics { unDiagnostics :: MaybeT (WriterT [String] m) a }+  deriving stock (Functor)+  deriving newtype (Applicative, Monad, MonadIO, MonadCatch, MonadMask, MonadThrow)++runDiagnosticsT :: DiagnosticsT m a -> m (Maybe a, [String])+runDiagnosticsT (Diagnostics m) = runWriterT (runMaybeT m)++instance Monad m => MonadDiagnostics (DiagnosticsT m) where+    putStrLnWarn err = Diagnostics $ tell ["*WARNING* " ++ err]+    putStrLnInfo err = Diagnostics $ tell ["*INFO* " ++ err]++    putStrLnErr err = Diagnostics $ do+        tell ["*ERROR* " ++ err]+        MaybeT $ return Nothing++    putStrLnErrs errs = Diagnostics $ do+        tell $ map ("*ERROR* " ++) (toList errs)+        MaybeT $ return Nothing
− src/HaskellCI/Extras.hs
@@ -1,34 +0,0 @@--- | Various extras, are this in @base@ ?-module HaskellCI.Extras where--import           Control.Applicative ((<|>))-import           Data.List           (isPrefixOf, tails)---- $setup--- >>> import Text.Read (readMaybe)---- | Return the part after the first argument------ >>> afterInfix "BAR" "FOOBAR XYZZY"--- Just " XYZZY"----afterInfix :: Eq a => [a] -> [a] -> Maybe [a]-afterInfix needle haystack = findMaybe (afterPrefix needle) (tails haystack)---- |------ >>> afterPrefix "FOO" "FOOBAR"--- Just "BAR"----afterPrefix :: Eq a => [a] -> [a] -> Maybe [a]-afterPrefix needle haystack-    | needle `isPrefixOf` haystack = Just (drop (length needle) haystack)-    | otherwise                    = Nothing---- |------ >>> findMaybe readMaybe ["foo", "1", "bar"] :: Maybe Int--- Just 1----findMaybe :: (a -> Maybe b) -> [a] -> Maybe b-findMaybe f = foldr (\a b -> f a <|> b) Nothing
− src/HaskellCI/GHC.hs
@@ -1,36 +0,0 @@--- | This module encodes what we know about GHC, including existing/supported versions.-module HaskellCI.GHC where--import           Distribution.Version (Version, mkVersion, versionNumbers)--import qualified Distribution.Pretty             as C--knownGhcVersions :: [Version]-knownGhcVersions = fmap mkVersion-    [ [7,0,1],  [7,0,2], [7,0,3], [7,0,4]-    , [7,2,1],  [7,2,2]-    , [7,4,1],  [7,4,2]-    , [7,6,1],  [7,6,2], [7,6,3]-    , [7,8,1],  [7,8,2], [7,8,3], [7,8,4]-    , [7,10,1], [7,10,2], [7,10,3]-    , [8,0,1],  [8,0,2]-    , [8,2,1],  [8,2,2]-    , [8,4,1],  [8,4,2], [8,4,3], [8,4,4]-    , [8,6,1],  [8,6,2], [8,6,3], [8,6,4]-    ]--ghcAlpha :: Maybe Version-ghcAlpha = Nothing--- ghcAlpha = Just (mkVersion [8,8,1])----dispGhcVersion :: Maybe Version -> String-dispGhcVersion = maybe "head" C.prettyShow---- | Alphas, RCs and HEAD.-previewGHC :: Maybe Version -> Bool-previewGHC = maybe True $ \v -> Just v == ghcAlpha || odd (snd (ghcMajVer v))--ghcMajVer :: Version -> (Int,Int)-ghcMajVer v-    | x:y:_ <- versionNumbers v = (x,y)-    | otherwise = error $ "panic: ghcMajVer called with " ++ show v
src/HaskellCI/Glob.hs view
@@ -1,13 +1,13 @@ module HaskellCI.Glob where -import Control.Applicative as App ((<$>))-import Control.Monad (void, filterM, liftM2)-import Control.Monad.IO.Class-import Data.List (stripPrefix)-import Distribution.Compat.ReadP-import System.Directory (doesDirectoryExist, getDirectoryContents)-import System.FilePath.Posix ((</>))+import HaskellCI.Prelude +import Control.Applicative       as App ((<$>))+import Control.Monad             (filterM, liftM2, void)+import System.Directory          (doesDirectoryExist, getDirectoryContents)+import System.FilePath.Posix     ((</>))+import Text.ParserCombinators.ReadP+ ------------------------------------------------------------------------------- -- Glob -------------------------------------------------------------------------------@@ -58,7 +58,7 @@    | FilePathHomeDir   deriving (Eq, Show) -parseFilePathGlobRel :: ReadP r FilePathGlobRel+parseFilePathGlobRel :: ReadP FilePathGlobRel parseFilePathGlobRel =       parseGlob >>= \globpieces ->           asDir globpieces@@ -79,7 +79,7 @@                    (c:_) | isGlobEscapedChar c -> pfail                    _                           -> return ()) -parseGlob :: ReadP r Glob+parseGlob :: ReadP Glob parseGlob = many1 parsePiece   where     parsePiece = literal +++ wildcard +++ union'@@ -97,10 +97,10 @@                                 && c /= '/' && c /= '\\')     escape  = char '\\' >> satisfy isGlobEscapedChar -    litchars1 :: ReadP r [Char]+    litchars1 :: ReadP [Char]     litchars1 = liftM2 (:) litchar litchars -    litchars :: ReadP r [Char]+    litchars :: ReadP [Char]     litchars = litchars1 <++ return []  isGlobEscapedChar :: Char -> Bool
+ src/HaskellCI/Jobs.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE RecordWildCards #-}+-- | Which jobs to generate. Also helper for diagnostics output.+module HaskellCI.Jobs where++import HaskellCI.Prelude++import qualified Data.Set            as S+import qualified Distribution.Pretty as C++import HaskellCI.Compiler+import HaskellCI.Config+import HaskellCI.Diagnostics+import HaskellCI.Package+import HaskellCI.TestedWith++data JobVersions = JobVersions+    { versions           :: Set CompilerVersion  -- ^ all jobs+    , osxVersions        :: Set Version          -- ^ osx jobs: GHC only+    , omittedOsxVersions :: Set Version+    }++describeJobs :: MonadDiagnostics m => TestedWithJobs -> JobVersions -> [Package] -> m ()+describeJobs twj JobVersions {..} pkgs = do+    putStrLnInfo $ "Generating Travis-CI config for testing for GHC versions: " ++ ghcVersions+    case twj of+        TestedWithUniform -> pure ()+        TestedWithAny     -> for_ pkgs $ \pkg -> do+            -- this omits HEAD version.+            let vr = pkgJobs pkg+            let vs = showVersions vr+            putStrLnInfo $ pkgName pkg ++ " " ++ ": " ++ vs++    unless (null osxVersions) $  do+        putStrLnInfo $ "Also OSX jobs for: " ++ ghcOsxVersions+        unless (S.null omittedOsxVersions) $+            putStrLnWarn $ "Not all GHC versions specified with --osx are generated: " ++ ghcOmittedOsxVersions+  where+    showVersions :: Set CompilerVersion -> String+    showVersions = unwords . map dispGhcVersionShort . S.toList++    showVersionsV :: Set Version -> String+    showVersionsV = unwords . map C.prettyShow . S.toList++    ghcVersions :: String+    ghcVersions = showVersions versions++    ghcOsxVersions :: String+    ghcOsxVersions = showVersionsV osxVersions++    ghcOmittedOsxVersions :: String+    ghcOmittedOsxVersions = showVersionsV omittedOsxVersions++makeJobVersions :: Config -> Set CompilerVersion -> JobVersions+makeJobVersions Config {..} versions' = JobVersions {..} where+    -- All jobs+    versions :: Set CompilerVersion+    versions+        | cfgGhcHead = S.insert GHCHead versions'+        | otherwise  = versions'++    osxVersions' :: Set Version+    osxVersions' = cfgOsx++    osxVersions, omittedOsxVersions :: Set Version+    (osxVersions, omittedOsxVersions) = S.partition (\x -> GHC x `S.member` versions') osxVersions'++
+ src/HaskellCI/List.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE RankNTypes #-}+module HaskellCI.List (+    ListBuilder,+    buildList,+    item,+    ) where++import HaskellCI.Prelude++import Control.Monad (ap)++newtype ListBuilder x a = LB { unLB :: forall r. (([x] -> [x]) -> a -> r) -> r }++instance Functor (ListBuilder x) where+    fmap f (LB k) = LB $ k $ \endo a k' -> k' endo (f a)++instance Applicative (ListBuilder x) where+    pure x = LB $ \f -> f id x+    (<*>)  = ap++instance Monad (ListBuilder x) where+    return = pure++    m >>= k =+        LB $ \r ->+        unLB m $ \endo1 a ->+        unLB (k a) $ \endo2 b ->+        r (endo1 . endo2) b++buildList :: ListBuilder x () -> [x]+buildList (LB f) = f $ \endo _ -> endo []++item :: x -> ListBuilder x ()+item x = LB $ \f -> f (x :) ()
− src/HaskellCI/MakeTravisOutput.hs
@@ -1,212 +0,0 @@-{-# LANGUAGE CPP               #-}-{-# LANGUAGE OverloadedStrings #-}-module HaskellCI.MakeTravisOutput where--import           Prelude                    ()-import           Prelude.Compat--import           Control.Monad              (mzero)-import           Control.Monad.Trans.Class  (lift)-import           Control.Monad.Trans.Maybe  (MaybeT)-import           Control.Monad.Trans.Writer (WriterT, tell)-import           Data.Functor.Identity      (Identity (..))-import           Data.Maybe                 (mapMaybe)-import           Data.Set                   (Set)-import           Data.String                (IsString (..))-import           Distribution.Version--#ifdef MIN_VERSION_ShellCheck-import           ShellCheck.Checker         (checkScript)-import qualified ShellCheck.Interface       as SC-#endif--import qualified Data.Set                   as S-import qualified Data.Text                  as T-import qualified Data.Text.Encoding         as TE-import qualified Data.YAML                  as YAML--import           HaskellCI.Config.Folds-import           HaskellCI.Version---- |  Encode shell command to be YAML safe and (optionally) ShellCheck it.-sh :: String -> Row-sh = sh'-    [ 2034 -- VAR appears unused. Verify it or export it.-    , 2086 -- SC2086: Double quote to prevent globbing and word splitting.-    , 2002 -- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.-    ]--shForJob :: Set Version -> VersionRange -> String -> Row-shForJob  versions vr cmd-    | all (`withinRange` vr) versions       = sh cmd-    | not $ any (`withinRange` vr) versions = RowSkip-    | otherwise                             = sh $ unwords-        [ "if"-        , ghcVersionPredicate vr-        , "; then"-        , cmd-        , "; fi"-        ]---- | Like 'sh' but with explicit SC exclude codes.-sh' :: [Integer] -> String -> Row-#ifndef MIN_VERSION_ShellCheck-sh' _ cmd = rawRow (shImpl cmd)-#else-sh' excl cmd =-    if null (SC.crComments res)-    then rawRow $ shImpl cmd-    else RowErr $ unlines $-        ("ShellCheck! " ++ cmd) :-        [ "SC" ++ show (SC.cCode c) ++ ": " ++ SC.cMessage c-        | pc <- SC.crComments res-        , let c = SC.pcComment pc-        ]--  where-    res = runIdentity $ checkScript iface spec-    iface = SC.SystemInterface $ \n -> return $ Left $ "cannot read file: " ++ n-    spec  = SC.emptyCheckSpec { SC.csFilename = "stdin"-                              , SC.csScript = cmd-                              , SC.csExcludedWarnings = excl-                              , SC.csShellTypeOverride = Just SC.Sh-                              }-#endif---- Non-ShellCheck version of sh'-shImpl :: String -> String-shImpl cmd-    | needsEncoding = "  - " ++ show cmd-    | otherwise     = "  - " ++ cmd-  where-    -- we try to decode optimisticly serialised "- cmd..."-    -- if it's ok, we use it :)-    -- otherwise escape with show-    cmdT  = T.pack cmd-    cmdBS = "- " <> TE.encodeUtf8 cmdT-    needsEncoding = case YAML.decodeStrict cmdBS of-        Right [[t]] | t == cmdT -> False-        _           -> True--comment :: String -> Row-comment c = rawRow $ "  # " ++ c--blank :: Row-blank = rawRow ""--rawRow :: String -> Row-rawRow = Row--type MakeTravisOutput = Result Diagnostic [String]--data Diagnostic-    = Info String-    | Warn String-    | Error String-  deriving (Eq, Show)--formatDiagnostics :: [Diagnostic] -> String-formatDiagnostics = unlines . map formatDiagnostic--formatDiagnostic :: Diagnostic -> String-formatDiagnostic (Error s) = "*ERROR* " ++ s-formatDiagnostic (Warn  s) = "*WARNING* " ++ s-formatDiagnostic (Info  s) = "*INFO* " ++ s---- MaybeT is used to preserve the short-circuiting semantics of 'putStrLnErr'.-type YamlWriter m a = MaybeT (WriterT MakeTravisOutput m) a--putStrLnErr :: Monad m => String -> YamlWriter m a-putStrLnErr m = do-    lift . tell $ Failure [Error m]-    mzero--putStrLnErrs :: Monad m => [String] -> YamlWriter m ()-putStrLnErrs [] = return ()-putStrLnErrs ms = do-    lift (tell (Failure (map Error ms)))-    mzero--putStrLnWarn, putStrLnInfo :: Monad m => String -> YamlWriter m ()-putStrLnWarn m = lift . tell $ Success [Warn m] []-putStrLnInfo m = lift . tell $ Success [Info m] []--tellStrLn :: Monad m => String -> YamlWriter m ()-tellStrLn str = lift . tell $ success [str]--data Row-    = Row String-    | RowErr String-    | RowSkip--instance IsString Row where-    fromString = rawRow--tellStrLns :: Monad m => [Row] -> YamlWriter m ()-tellStrLns rows = case sequenceRows rows of-    Left err    -> lift $ tell $ Failure [Error err]-    Right rows' -> lift $ tell $ success rows'--tellStrLnsRaw :: Monad m => [String] -> YamlWriter m ()-tellStrLnsRaw rows = lift $ tell $ success rows--sequenceRows :: [Row] -> Either String [String]-sequenceRows = sequenceA . mapMaybe f where-    f (Row s)      = Just (Right s)-    f (RowErr err) = Just (Left err)-    f RowSkip      = Nothing------------------------------------------------------------------------------------ Folded----------------------------------------------------------------------------------foldedTellStrLns-    :: Monad m-    => Fold-    -> String-    -> Set Fold-    -> YamlWriter m ()-    -> YamlWriter m ()-foldedTellStrLns label = foldedTellStrLns' label ""--foldedTellStrLns'-    :: Monad m-    => Fold-    -> String-    -> String-    -> Set Fold-    -> YamlWriter m ()-    -> YamlWriter m ()-foldedTellStrLns' label pfx prettyLabel labels output-    | label `S.notMember` labels = output-    | otherwise = tellStrLns prologue >> output >> tellStrLns epilogue-  where-    prologue = [ sh' [2039] $ concat-        [ "echo ", prettyLabel-        , " && echo -en 'travis_fold:start:", showFold' label, "\\\\r'"-        ]]-    epilogue = [ sh' [2039] $ "echo -en 'travis_fold:end:" ++ showFold' label ++ "\\\\r'" ]--    showFold' l = showFold l ++ if null pfx then "" else "-" ++ pfx------------------------------------------------------------------------------------ Result----------------------------------------------------------------------------------data Result e a-    = Success [e] a-    | Failure [e]-    deriving (Eq, Show, Functor)--success :: a -> Result e a-success = Success []--instance Monoid a => Monoid (Result e a) where-    mempty = success mempty-    mappend = (<>)--instance Monoid a => Semigroup (Result e a) where-    Failure err1   <> Failure err2   = Failure $ err1 <> err2-    Failure err1   <> Success err2 _ = Failure $ err1 <> err2-    Success err1 _ <> Failure err2   = Failure $ err1 <> err2-    Success l1 o1  <> Success l2 o2  = Success (mappend l1 l2) (mappend o1 o2)
+ src/HaskellCI/MonadErr.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE FlexibleInstances      #-}+{-# LANGUAGE FunctionalDependencies #-}+module HaskellCI.MonadErr where++import HaskellCI.Prelude++-- | 'MonadErr' is 'MonadError' without @catch@+class Monad m => MonadErr e m | m -> e where+    throwErr :: e -> m a++instance MonadErr e (Either e) where+    throwErr = Left
src/HaskellCI/Newtypes.hs view
@@ -1,35 +1,25 @@ {-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables   #-} module HaskellCI.Newtypes where -import           Control.Applicative             (liftA2, (<|>))-import           Data.Char                       (isSpace)-import           Data.Coerce                     (coerce)-import           Data.Functor.Identity           (Identity (..))-import           Data.Proxy                      (Proxy (..))+import HaskellCI.Prelude  import qualified Data.Set                        as S import qualified Distribution.Compat.CharParsing as C import qualified Distribution.Compat.Newtype     as C-import qualified Distribution.Parsec.Class       as C+import qualified Distribution.Parsec             as C import qualified Distribution.Parsec.Newtypes    as C import qualified Distribution.Pretty             as C import qualified Distribution.Types.Version      as C import qualified Distribution.Types.VersionRange as C import qualified Text.PrettyPrint                as PP -import           HaskellCI.Version- ------------------------------------------------------------------------------- -- PackageLocation -------------------------------------------------------------------------------  newtype PackageLocation = PackageLocation String--instance C.Newtype PackageLocation [Char] where-    pack = coerce-    unpack = coerce+  deriving anyclass (C.Newtype String)  -- | This is a bit tricky since it has to cover globs which have embedded @,@ -- chars. But we don't just want to parse strictly as a glob since we want to@@ -70,10 +60,7 @@ -------------------------------------------------------------------------------  newtype NoCommas = NoCommas String--instance C.Newtype NoCommas [Char] where-    pack = coerce-    unpack = coerce+  deriving anyclass (C.Newtype String)  instance C.Parsec NoCommas where     parsec = NoCommas <$> liftA2 (:) (C.satisfy (not . isSpace)) (C.munch (/= ','))@@ -86,10 +73,7 @@ -------------------------------------------------------------------------------  newtype HeadVersion = HeadVersion { getHeadVersion :: Maybe C.Version }--instance C.Newtype HeadVersion (Maybe C.Version) where-    pack = coerce-    unpack = coerce+  deriving anyclass (C.Newtype (Maybe C.Version))  instance C.Parsec HeadVersion where     parsec = HeadVersion Nothing <$ C.string "head" <|>@@ -104,10 +88,7 @@ -------------------------------------------------------------------------------  newtype Int' = Int' Int--instance C.Newtype Int' Int where-    pack = coerce-    unpack = coerce+  deriving anyclass (C.Newtype Int)  instance C.Parsec Int' where     parsec = Int' <$> C.integral@@ -120,10 +101,7 @@ -------------------------------------------------------------------------------  newtype Range = Range C.VersionRange--instance C.Newtype Range C.VersionRange where-    pack = coerce-    unpack = coerce+  deriving anyclass (C.Newtype C.VersionRange)  instance C.Parsec Range where     parsec = fmap Range $ C.parsec <|> fromBool <$> C.parsec where@@ -141,6 +119,7 @@ -------------------------------------------------------------------------------  newtype AlaSet sep b a = AlaSet { getAlaSet :: S.Set a }+  deriving anyclass (C.Newtype (S.Set a))  alaSet :: sep -> S.Set a -> AlaSet sep (Identity a) a alaSet _ = AlaSet@@ -149,30 +128,12 @@ alaSet' :: sep -> (a -> b) -> S.Set a -> AlaSet sep b a alaSet' _ _ = AlaSet -instance C.Newtype (AlaSet sep wrapper a) (S.Set a) where-    pack = AlaSet-    unpack = getAlaSet--instance (C.Newtype b a, Ord a, Sep sep, C.Parsec b) => C.Parsec (AlaSet sep b a) where-    parsec   = C.pack . S.fromList . map (C.unpack :: b -> a) <$> parseSep (Proxy :: Proxy sep) C.parsec--instance (C.Newtype b a, Sep sep, C.Pretty b) => C.Pretty (AlaSet sep b a) where-    pretty = prettySep (Proxy :: Proxy sep) . map (C.pretty . (C.pack :: a -> b)) . S.toList . C.unpack------------------------------------------------------------------------------------ From Cabal--------------------------------------------------------------------------------+instance (C.Newtype a b, Ord a, C.Sep sep, C.Parsec b) => C.Parsec (AlaSet sep b a) where+    parsec   = C.pack . S.fromList . map (C.unpack :: b -> a) <$> C.parseSep (hack (Proxy :: Proxy sep)) C.parsec -class    Sep sep  where-    prettySep :: Proxy sep -> [PP.Doc] -> PP.Doc-    parseSep :: C.CabalParsing m => Proxy sep -> m a -> m [a]+instance (C.Newtype a b, C.Sep sep, C.Pretty b) => C.Pretty (AlaSet sep b a) where+    pretty = C.prettySep (hack (Proxy :: Proxy sep)) . map (C.pretty . (C.pack :: a -> b)) . S.toList . C.unpack -instance Sep C.CommaVCat where-    prettySep  _ = PP.vcat . PP.punctuate PP.comma-    parseSep   _ = C.parsecLeadingCommaList-instance Sep C.CommaFSep where-    prettySep _ = PP.fsep . PP.punctuate PP.comma-    parseSep   _ = C.parsecLeadingCommaList-instance Sep C.NoCommaFSep where-    prettySep _   = PP.fsep-    parseSep  _ p = C.many (p <* C.spaces)+-- Someone (= me) forgot to export Distribution.Parsec.Newtypes.P+hack :: Proxy a -> proxy a+hack _ = undefined
src/HaskellCI/Optimization.hs view
@@ -1,9 +1,9 @@ module HaskellCI.Optimization where -import Control.Applicative ((<|>))+import HaskellCI.Prelude  import qualified Distribution.Compat.CharParsing as C-import qualified Distribution.Parsec.Class       as C+import qualified Distribution.Parsec             as C import qualified Distribution.Pretty             as C import qualified Text.PrettyPrint                as PP @@ -20,7 +20,7 @@          ite t _ True  = t         ite _ f False = f-    + instance C.Pretty Optimization where     pretty OptimizationOn        = C.pretty True     pretty OptimizationOff       = C.pretty False
src/HaskellCI/OptionsGrammar.hs view
@@ -3,12 +3,14 @@     (C.^^^),     )  where +import HaskellCI.Prelude+ import qualified Distribution.Compat.Lens        as C import qualified Distribution.FieldGrammar       as C-import qualified Distribution.Parsec.Field       as C+import qualified Distribution.Fields             as C import qualified Distribution.Types.VersionRange as C -import           HaskellCI.Newtypes+import HaskellCI.Newtypes  class C.FieldGrammar p => OptionsGrammar p where     metahelp :: String -> String -> p s a -> p s a
src/HaskellCI/OptparseGrammar.hs view
@@ -5,24 +5,22 @@     runOptparseGrammar,     ) where -import           Prelude                     ()-import           Prelude.Compat+import HaskellCI.Prelude -import           Control.Applicative         (many)-import           Data.Foldable               (asum)-import           Distribution.Simple.Utils   (fromUTF8BS)+import Control.Applicative       (many)+import Data.Foldable             (asum)+import Distribution.Simple.Utils (fromUTF8BS)  import qualified Distribution.Compat.Lens    as C import qualified Distribution.Compat.Newtype as C import qualified Distribution.FieldGrammar   as C-import qualified Distribution.Parsec.Class   as C-import qualified Distribution.Parsec.Field   as C+import qualified Distribution.Fields         as C+import qualified Distribution.Parsec         as C import qualified Distribution.Pretty         as C import qualified Distribution.Version        as C import qualified Options.Applicative         as O -import           HaskellCI.OptionsGrammar-import           HaskellCI.Version+import HaskellCI.OptionsGrammar  data SomeParser s where     SP :: (Maybe String -> Maybe String -> O.Parser (s -> s)) -> SomeParser s@@ -73,7 +71,14 @@     knownField _         = pure ()     deprecatedSince _  _ = id     availableSince _ _   = id+    removedIn _ _        = id     hiddenField          = id++    freeTextField fn l = OG+        [ SP $ \m h -> setOptionalOG l $ O.strOption $ optionMods fn m h ]++    freeTextFieldDef fn l = OG+        [ SP $ \m h -> setOG l $ O.strOption $ optionMods fn m h ]  instance OptionsGrammar OptparseGrammar where     help h (OG ps) = OG
src/HaskellCI/Package.hs view
@@ -1,12 +1,15 @@ module HaskellCI.Package where +import HaskellCI.Prelude+ import qualified Distribution.Types.GenericPackageDescription as C-import qualified Distribution.Types.VersionRange              as C +import HaskellCI.Compiler+ data Package = Pkg     { pkgName :: String-    , pkgJobs :: C.VersionRange+    , pkgJobs :: Set CompilerVersion     , pkgDir  :: FilePath     , pkgGpd  :: C.GenericPackageDescription     }-  deriving (Eq, Show)+  deriving (Eq, Show, Generic)
src/HaskellCI/ParsecError.hs view
@@ -2,16 +2,15 @@     renderParseError,     ) where -import           Prelude                    ()-import           Prelude.Compat+import Prelude ()+import Prelude.Compat -import           Distribution.Parsec.Common (PError (..), PWarning (..),-                                             Position (..), showPos, zeroPos)-import           Distribution.Simple.Utils  (fromUTF8BS)-import           System.FilePath            (normalise)+import Distribution.Parsec       (PError (..), PWarning (..), Position (..), showPos, zeroPos)+import Distribution.Simple.Utils (fromUTF8BS)+import System.FilePath           (normalise) -import qualified Data.ByteString            as BS-import qualified Data.ByteString.Char8      as BS8+import qualified Data.ByteString       as BS+import qualified Data.ByteString.Char8 as BS8  -- | Render parse error highlighting the part of the input file. renderParseError
src/HaskellCI/ParsecUtils.hs view
@@ -1,18 +1,18 @@ module HaskellCI.ParsecUtils where -import           Control.Monad                   (unless)-import           System.Directory                (doesFileExist)-import           System.Exit                     (exitFailure)-import           System.IO                       (hPutStr, stderr)+import HaskellCI.Prelude -import qualified Data.ByteString                 as BS-import qualified Distribution.Parsec.Common      as C-import qualified Distribution.Parsec.LexerMonad  as C-import qualified Distribution.Parsec.Parser      as C-import qualified Distribution.Parsec.ParseResult as C-import qualified Text.Parsec                     as P+import System.Directory (doesFileExist)+import System.Exit      (exitFailure)+import System.IO        (hPutStr, stderr) -import           HaskellCI.ParsecError+import qualified Data.ByteString                as BS+import qualified Distribution.Fields            as C+import qualified Distribution.Fields.LexerMonad as C (toPWarnings)+import qualified Distribution.Parsec            as C+import qualified Text.Parsec                    as P++import HaskellCI.ParsecError  readAndParseFile     :: ([C.Field C.Position] -> C.ParseResult a)  -- ^ File fields to final value parser
+ src/HaskellCI/Prelude.hs view
@@ -0,0 +1,88 @@+{-# OPTIONS_GHC -Wno-orphans #-}+module HaskellCI.Prelude (+    module Prelude.Compat,+    module X,+    module HaskellCI.Prelude,+    ) where++import Prelude.Compat hiding (head, tail)++import Algebra.Lattice        as X (BoundedJoinSemiLattice (..), BoundedLattice, BoundedMeetSemiLattice (..), Lattice (..))+import Control.Applicative    as X (liftA2, (<|>))+import Control.Exception      as X (Exception (..))+import Control.Monad          as X (ap, unless, void, when)+import Control.Monad.Catch    as X (MonadCatch, MonadMask, MonadThrow)+import Control.Monad.IO.Class as X (MonadIO (..))+import Data.Bifoldable        as X (Bifoldable (..))+import Data.Bifunctor         as X (Bifunctor (..))+import Data.Bitraversable     as X (Bitraversable (..), bifoldMapDefault, bimapDefault)+import Data.ByteString        as X (ByteString)+import Data.Char              as X (isSpace, isUpper, toLower)+import Data.Coerce            as X (coerce)+import Data.Foldable          as X (for_, toList, traverse_)+import Data.Function          as X (on)+import Data.Functor.Identity  as X (Identity (..))+import Data.List              as X (foldl', intercalate, isPrefixOf, nub, stripPrefix, tails)+import Data.List.NonEmpty     as X (NonEmpty (..), groupBy)+import Data.Maybe             as X (fromMaybe, isJust, isNothing, mapMaybe)+import Data.Proxy             as X (Proxy (..))+import Data.Set               as X (Set)+import Data.String            as X (IsString (fromString))+import Data.Void              as X (Void)+import GHC.Generics           as X (Generic)+import Lens.Micro             as X (mapped, over, (&), (.~), (<&>), (^.), (^..))+import Text.Read              as X (readMaybe)++import Distribution.Version as X (Version, VersionRange, anyVersion, mkVersion, noVersion)++import qualified Distribution.Version as C++import Data.Generics.Labels ()++-------------------------------------------------------------------------------+-- Extras+-------------------------------------------------------------------------------++head :: NonEmpty a -> a+head (x :| _) = x++-- $setup+-- >>> import Text.Read (readMaybe)++-- | Return the part after the first argument+--+-- >>> afterInfix "BAR" "FOOBAR XYZZY"+-- Just " XYZZY"+--+afterInfix :: Eq a => [a] -> [a] -> Maybe [a]+afterInfix needle haystack = findMaybe (afterPrefix needle) (tails haystack)++-- |+--+-- >>> afterPrefix "FOO" "FOOBAR"+-- Just "BAR"+--+afterPrefix :: Eq a => [a] -> [a] -> Maybe [a]+afterPrefix needle haystack+    | needle `isPrefixOf` haystack = Just (drop (length needle) haystack)+    | otherwise                    = Nothing++-- |+--+-- >>> findMaybe readMaybe ["foo", "1", "bar"] :: Maybe Int+-- Just 1+--+findMaybe :: (a -> Maybe b) -> [a] -> Maybe b+findMaybe f = foldr (\a b -> f a <|> b) Nothing++-- | Whether two ranges are equivalent.+equivVersionRanges :: C.VersionRange -> C.VersionRange -> Bool+equivVersionRanges = on (==) C.asVersionIntervals++-------------------------------------------------------------------------------+-- Orphans+-------------------------------------------------------------------------------++instance Lattice VersionRange where+    (/\) = C.intersectVersionRanges+    (\/) = C.unionVersionRanges
src/HaskellCI/Project.hs view
@@ -7,50 +7,54 @@     parseProjectFile,     ) where -import           Data.ByteString                              (ByteString)-import           Data.Generics.Labels                         ()-import           GHC.Generics                                 (Generic)-import           Lens.Micro                                   (over)+import HaskellCI.Prelude  import qualified Data.Map.Strict                              as M import qualified Distribution.CabalSpecVersion                as C import qualified Distribution.FieldGrammar                    as C+import qualified Distribution.Fields                          as C import qualified Distribution.PackageDescription.FieldGrammar as C-import qualified Distribution.Parsec.Common                   as C+import qualified Distribution.Parsec                          as C import qualified Distribution.Parsec.Newtypes                 as C-import qualified Distribution.Parsec.Parser                   as C-import qualified Distribution.Parsec.ParseResult              as C import qualified Distribution.Types.SourceRepo                as C-import qualified Distribution.Fields.Pretty as C -import           HaskellCI.Newtypes-import           HaskellCI.Optimization-import           HaskellCI.ParsecError+import HaskellCI.Newtypes+import HaskellCI.Optimization+import HaskellCI.ParsecError  -- $setup -- >>> :seti -XOverloadedStrings -data Project a = Project+data Project b a = Project     { prjPackages     :: [a]+    , prjOptPackages  :: [b]     , prjConstraints  :: [String]     , prjAllowNewer   :: [String]     , prjReorderGoals :: Bool     , prjMaxBackjumps :: Maybe Int     , prjOptimization :: Optimization     , prjSourceRepos  :: [C.SourceRepo]-    , prjOrigFields   :: [C.PrettyField]+    , prjOrigFields   :: [C.PrettyField ()]     }-  deriving (Show, Functor, Foldable, Traversable, Generic)+  deriving (Functor, Foldable, Traversable, Generic) -emptyProject :: Project [a]-emptyProject = Project [] [] [] False Nothing OptimizationOn [] []+instance Bifunctor Project where bimap = bimapDefault+instance Bifoldable Project where bifoldMap = bifoldMapDefault +instance Bitraversable Project where+    bitraverse f g prj = (\b a -> prj { prjPackages = a, prjOptPackages = b })+        <$> traverse f (prjOptPackages prj)+        <*> traverse g (prjPackages prj)++emptyProject :: Project b a+emptyProject = Project [] [] [] [] False Nothing OptimizationOn [] []+ -- | Parse project file. Extracts only few fields. -- -- >>> fmap prjPackages $ parseProjectFile "cabal.project" "packages: foo bar/*.cabal" -- Right ["foo","bar/*.cabal"] ---parseProjectFile :: FilePath -> ByteString -> Either String (Project String)+parseProjectFile :: FilePath -> ByteString -> Either String (Project String String) parseProjectFile fp bs = do     fields0 <- either (Left . show) Right $ C.readFields bs     let (fields1, sections) = C.partitionFields fields0@@ -62,11 +66,11 @@     knownFields = C.fieldGrammarKnownFieldList $ grammar []      parse origFields fields sections = do-        let prettyOrigFields = C.fromParsecFields $ filter notPackages origFields+        let prettyOrigFields = map void $ C.fromParsecFields $ filter notPackages origFields         prj <- C.parseFieldGrammar C.cabalSpecLatest fields $ grammar prettyOrigFields         foldr ($) prj <$> traverse parseSec (concat sections) -    parseSec :: C.Section C.Position -> C.ParseResult (Project String -> Project String)+    parseSec :: C.Section C.Position -> C.ParseResult (Project String String -> Project String String)     parseSec (C.MkSection (C.Name _pos name) [] fields) | name == "source-repository-package" = do         let fields' = fst $ C.partitionFields fields         repo <- C.parseFieldGrammar C.cabalSpecLatest fields' (C.sourceRepoFieldGrammar $ C.RepoKindUnknown "unused")@@ -78,14 +82,14 @@ notPackages (C.Field (C.Name _ "packages") _) = False notPackages _                                 = True --grammar :: [C.PrettyField] -> C.ParsecFieldGrammar (Project String) (Project String)+grammar :: [C.PrettyField ()] -> C.ParsecFieldGrammar (Project String String) (Project String String) grammar origFields = Project-    <$> C.monoidalFieldAla "packages"      (C.alaList' C.FSep PackageLocation) #prjPackages-    <*> C.monoidalFieldAla "constraints"   (C.alaList' C.CommaVCat NoCommas)   #prjConstraints-    <*> C.monoidalFieldAla "allow-newer"   (C.alaList' C.CommaVCat NoCommas)   #prjAllowNewer-    <*> C.booleanFieldDef  "reorder-goals"                                     #prjReorderGoals False-    <*> C.optionalFieldAla "max-backjumps" Int'                                    #prjMaxBackjumps-    <*> C.optionalFieldDef "optimization"                                      #prjOptimization OptimizationOn+    <$> C.monoidalFieldAla "packages"          (C.alaList' C.FSep PackageLocation) #prjPackages+    <*> C.monoidalFieldAla "optional-packages" (C.alaList' C.FSep PackageLocation) #prjOptPackages+    <*> C.monoidalFieldAla "constraints"       (C.alaList' C.CommaVCat NoCommas)   #prjConstraints+    <*> C.monoidalFieldAla "allow-newer"       (C.alaList' C.CommaVCat NoCommas)   #prjAllowNewer+    <*> C.booleanFieldDef  "reorder-goals"                                         #prjReorderGoals False+    <*> C.optionalFieldAla "max-backjumps"     Int'                                #prjMaxBackjumps+    <*> C.optionalFieldDef "optimization"                                          #prjOptimization OptimizationOn     <*> pure []     <*> pure origFields
+ src/HaskellCI/Sh.hs view
@@ -0,0 +1,148 @@+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE DeriveFunctor         #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module HaskellCI.Sh (+    Sh (..),+    isComment,+    MonadSh (..),+    sh,+    ShM (..),+    runSh,+    ShError (..),+    FromShError (..),+    ) where++import HaskellCI.Prelude++#ifdef MIN_VERSION_ShellCheck+import           ShellCheck.Checker    (checkScript)+import qualified ShellCheck.Interface  as SC+#endif++import qualified Control.Monad.Fail as Fail++import HaskellCI.MonadErr++-------------------------------------------------------------------------------+-- shell command+-------------------------------------------------------------------------------++data Sh+    = Sh String       -- ^ command+    | Comment String  -- ^ comment+  deriving Show++isComment :: Sh -> Bool+isComment (Comment _) = True+isComment (Sh _)      = False++-------------------------------------------------------------------------------+-- class+-------------------------------------------------------------------------------++class Monad m => MonadSh m where+    -- | Write shell command+    sh' :: [Integer] -> String -> m ()++    -- | Write comment+    comment :: String -> m ()++    -- | Commented block.+    --+    -- If the block is empty (or comments only), nothing might be written.+    commentedBlock :: String -> m () -> m ()++sh :: MonadSh m => String -> m ()+sh = sh'+    [ 2034 -- VAR appears unused. Verify it or export it.+    , 2086 -- SC2086: Double quote to prevent globbing and word splitting.+    , 2002 -- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.+    -- TODO: because HEREDOC doesn't work+    , 2129 -- SC2129: Consider using { cmd1; cmd2; } >> file instead of individual redirects+    , 2154 -- SC2154: PKGDIR_splitmix is referenced but not assigned.+    ]++-------------------------------------------------------------------------------+-- Errors+-------------------------------------------------------------------------------++data ShError+    = ShellCheckError String  -- ^ @ShellCheck@ disagrees.+    | ShError String          -- ^ made by 'fail'.+  deriving (Show)++instance Exception ShError where+    displayException (ShellCheckError s) = s+    displayException (ShError s)         = "PANIC " ++ s++class FromShError e where+    fromShError :: ShError -> e++instance FromShError ShError where+    fromShError = id++-------------------------------------------------------------------------------+-- implementation+-------------------------------------------------------------------------------++newtype ShM a = ShM { unShM :: ([Sh] -> [Sh]) -> Either ShError ([Sh] -> [Sh], a) }+  deriving (Functor)++runSh :: (MonadErr e m, FromShError e) => ShM () -> m [Sh]+runSh (ShM f) = case f id of+    Left err      -> throwErr (fromShError err)+    Right (g, ()) -> return (g [])++instance Applicative ShM where+    pure x = ShM $ \shs -> Right (shs, x)+    (<*>) = ap++instance Monad ShM where+    return = pure++    m >>= k = ShM $ \shs0 -> do+        (shs1, x) <- unShM m     shs0+        (shs2, y) <- unShM (k x) shs1+        return (shs2, y)++    fail = Fail.fail++instance Fail.MonadFail ShM where+    fail = throwErr . ShError++instance MonadErr ShError ShM where+    throwErr err = ShM $ \_ -> Left err++unsafeSh :: String -> ShM ()+unsafeSh x = ShM $ \shs -> Right (shs . (Sh x :),      ())++instance MonadSh ShM where+#ifndef MIN_VERSION_ShellCheck+    sh' _ = unsafeSh+#else+    sh' excl cmd+        | null (SC.crComments res) = unsafeSh cmd+        | otherwise                = throwErr $ ShellCheckError $ unlines $+            ("ShellCheck! " ++ cmd) :+            [ "SC" ++ show (SC.cCode c) ++ ": " ++ SC.cMessage c+            | pc <- SC.crComments res+            , let c = SC.pcComment pc+            ]+      where+        res = runIdentity $ checkScript iface spec+        iface = SC.mockedSystemInterface []+        spec  = SC.emptyCheckSpec+            { SC.csFilename          = "stdin"+            , SC.csScript            = cmd+            , SC.csExcludedWarnings  = excl+            , SC.csShellTypeOverride = Just SC.Sh+            }+#endif+    comment x = ShM $ \shs -> Right (shs . (Comment x :), ())++    commentedBlock c m = case runSh m of+        Left err  -> throwErr err+        Right shs+            | all isComment shs -> pure ()+            | otherwise         -> ShM $ \shs1 -> Right+                (shs1 . (\shs2 -> Comment c : shs ++ shs2), ())
+ src/HaskellCI/ShVersionRange.hs view
@@ -0,0 +1,235 @@+module HaskellCI.ShVersionRange (+    compilerVersionPredicate,+    ) where++import HaskellCI.Prelude++import Algebra.Lattice (bottom, top, joins)+import Algebra.Heyting.Free (Free (..))+import Algebra.Lattice.Wide (Wide (..))++import qualified Algebra.Heyting.Free as F+import qualified Algebra.Lattice.Wide as W+import qualified Data.Set             as S+import qualified Distribution.Version as C++import HaskellCI.Compiler++-- $setup+-- >>> import Distribution.Pretty (prettyShow)++compilerVersionPredicate :: Set CompilerVersion -> CompilerRange -> String+compilerVersionPredicate cvs cr+    | S.null ghcjsS = wideToString $ freeToWide ghcFree+    | otherwise     = wideToString $ freeToWide $+        (Var "$GHCJS" /\ ghcjsFree) \/ (Var "! $GHCJS" /\ ghcFree)+  where+    R hdS ghcS ghcjsS = partitionCompilerVersions cvs+    R hdR ghcR ghcjsR = simplifyCompilerRange cr++    -- GHCJS++    ghcjsS' = S.filter (`C.withinRange` ghcjsR) ghcjsS++    ghcjsFree :: Free String+    ghcjsFree = ghcVersionPredicate ghcjsRange++    ghcjsRange = case S.toList ghcjsS' of+        []  -> C.noVersion+        [_] -> C.anyVersion+        _   -> error "multiple GHCJS versions unsupported"++    -- GHC + GHC HEAD++    ghcFree :: Free String+    ghcFree = ghcVersionPredicate (ghcHeadRange \/ ghcRange)++    -- GHC++    ghcD = roundDown ghcS+    ghcS' = S.filter (`C.withinRange` ghcR) ghcS++    isMinGHC u = Just u == fmap fst (S.minView ghcD)++    -- if we build with GHC HEAD, than none of known versions is maxGHC.+    isMaxGHC u | hdS       = False+               | otherwise = Just u == fmap fst (S.maxView ghcD)++    findGhc :: Version -> VersionRange+    findGhc v = case (S.lookupLE v ghcD, S.lookupGT v ghcD) of+        (Nothing, _)      -> C.noVersion+        (Just u, Nothing) -> orLater u+        (Just u, Just w)  -> orLater u /\ earlier w+      where+        orLater u | isMinGHC u = C.anyVersion+                  | otherwise  = C.orLaterVersion u++        earlier u | isMaxGHC u = C.anyVersion+                  | otherwise  = C.earlierVersion u+      ++    ghcRange :: VersionRange+    ghcRange = foldr (\/) C.noVersion $ map findGhc $ S.toList ghcS'++    -- GHC HEAD++    ghcHeadRange :: VersionRange+    ghcHeadRange+        | hdR && hdS = C.laterVersion (S.findMax ghcS)+        | otherwise  = C.noVersion++data R a = R Bool a a+  deriving (Show)++partitionCompilerVersions :: Set CompilerVersion -> R (Set Version)+partitionCompilerVersions = foldr f (R False S.empty S.empty) where+    f (GHC v)   (R hd ghc ghcjs) = R hd (S.insert v ghc) ghcjs+    f (GHCJS v) (R hd ghc ghcjs) = R hd ghc (S.insert v ghcjs)+    f GHCHead   (R _ ghc ghcjs)  = R True ghc ghcjs++simplifyCompilerRange :: CompilerRange -> R VersionRange+simplifyCompilerRange RangeGHC   = R True C.anyVersion C.noVersion+simplifyCompilerRange RangeGHCJS = R False C.noVersion C.anyVersion+simplifyCompilerRange (Range vr) = R (not $ C.hasUpperBound vr) vr vr+simplifyCompilerRange (RangeUnion a b) =+    case (simplifyCompilerRange a, simplifyCompilerRange b) of+        (R x y z, R u v w) -> R (x \/ u) (y \/ v) (z \/ w)+simplifyCompilerRange (RangeInter a b) =+    case (simplifyCompilerRange a, simplifyCompilerRange b) of+        (R x y z, R u v w) -> R (x /\ u) (y /\ v) (z /\ w)+simplifyCompilerRange (RangePoints vs) = foldr f (R False C.noVersion C.noVersion) vs where+    f (GHC v)   (R hd ghc ghcjs) = R hd (C.thisVersion v \/ ghc) ghcjs+    f (GHCJS v) (R hd ghc ghcjs) = R hd ghc (C.thisVersion v \/ ghcjs)+    f GHCHead   (R _  ghc ghcjs) = R True ghc ghcjs++ghcVersionPredicate :: C.VersionRange -> Free String+ghcVersionPredicate vr+    | equivVersionRanges C.noVersion vr  = bottom+    | equivVersionRanges C.anyVersion vr = top+    | otherwise                          = ghcVersionPredicate' vr++ghcVersionPredicate' :: C.VersionRange -> Free String+ghcVersionPredicate' = conj . C.asVersionIntervals+  where+    conj = joins . map disj++    disj :: C.VersionInterval -> Free String+    disj (C.LowerBound v C.InclusiveBound, C.UpperBound u C.InclusiveBound)+        | v == u                = Var ("[ $HCNUMVER -eq " ++ f v ++ " ]")+    disj (lb, C.NoUpperBound)+        | isInclZero lb         = top+        | otherwise             = Var (lower lb)+    disj (lb, C.UpperBound v b)+        | isInclZero lb         = Var (upper v b)+        | otherwise             = Var (lower lb) /\ Var (upper v b)++    isInclZero (C.LowerBound v C.InclusiveBound) = v == C.mkVersion [0]+    isInclZero (C.LowerBound _ C.ExclusiveBound) = False++    lower (C.LowerBound v C.InclusiveBound) = "[ $HCNUMVER -ge " ++ f v ++ " ]"+    lower (C.LowerBound v C.ExclusiveBound) = "[ $HCNUMVER -gt " ++ f v ++ " ]"++    upper v C.InclusiveBound = "[ $HCNUMVER -le " ++ f v ++ " ]"+    upper v C.ExclusiveBound = "[ $HCNUMVER -lt " ++ f v ++ " ]"++    f = ghcVersionToString++-------------------------------------------------------------------------------+-- Utilities+-------------------------------------------------------------------------------++ghcVersionToString :: C.Version -> String+ghcVersionToString v =  case C.versionNumbers v of+    []        -> "0"+    [x]       -> show (x * 10000)+    [x,y]     -> show (x * 10000 + y * 100)+    (x:y:z:_) -> show (x * 10000 + y * 100 + z)++-- | Round down a first version in major series.+--+-- >>> let rd = map prettyShow . S.toList . roundDown . S.fromList . map C.mkVersion+--+-- >>> rd []+-- []+--+-- >>> rd [ [8,0,2] ]+-- ["8.0","8.0.3"]+--+-- >>> rd [ [8,0,2], [8,2,2], [8,4,4], [8,6,5], [8,8,1] ]+-- ["8.0","8.2","8.4","8.6","8.8","8.8.2"]+--+-- >>> rd [ [8,6,1], [8,6,2], [8,6,3], [8,6,4], [8,6,5] ]+-- ["8.6","8.6.2","8.6.3","8.6.4","8.6.5","8.6.6"]+--+roundDown :: Set Version -> Set Version+roundDown = go S.empty . S.toList where+    go !acc []      = acc+    go !acc [v]+        | S.member m acc = S.insert v $ S.insert (up v) acc+        | otherwise      = S.insert m $ S.insert (up v) acc+      where+        m = let (x,y) = ghcMajVer v in C.mkVersion [x,y]+    go !acc (v:vs)+        | S.member m acc = go (S.insert v acc) vs+        | otherwise      = go (S.insert m acc) vs+      where+        m = let (x,y) = ghcMajVer v in C.mkVersion [x,y]++    up v = C.mkVersion $ case C.versionNumbers v of+        []     -> [1]+        (x:xs) -> up' x xs++    up' x []     = [x + 1]+    up' x (y:ys) = x : up' y ys++wideToString :: Wide String -> String+wideToString W.Bottom     = "false"+wideToString W.Top        = "top"+wideToString (W.Middle x) = x+++freeToWide :: Free String -> Wide String+freeToWide z+    | z == top    = top+    | z == bottom = bottom+    | otherwise   = Middle (go 0 z)+  where+    go :: Int -> Free String -> String+    go _ (Var x)  = x+    go _ F.Bottom = "false"+    go _ F.Top    = "true"++    go d (x :/\: y) = parens (d > 3)+        $ go 4 x ++ " && " ++ go 3 y+    go d (x :\/: y) = parens (d > 2)+        $ go 3 x ++ " || " ++ go 2 y++    go d (x :=>: y) = parens (d > 2)+        $ "! { " ++ go 0 x ++ " ; } || " ++ go 2 y++    parens :: Bool -> String -> String+    parens True  s = "{ " ++ s ++ "; }"+    parens False s = s++-------------------------------------------------------------------------------+-- PosNeg+-------------------------------------------------------------------------------++{-+data PosNeg a = Pos a | Neg a+  deriving (Eq, Ord, Show, Functor)++neg :: PosNeg a -> PosNeg a+neg (Pos x) = Neg x+neg (Neg x) = Pos x++instance Applicative PosNeg where+    pure  = Pos+    (<*>) = ap++instance Monad PosNeg where+    return = pure++    Pos x >>= f = f x+    Neg x >>= f = neg (f x)+-}
src/HaskellCI/TestedWith.hs view
@@ -3,24 +3,24 @@     checkVersions,     ) where -import           Prelude                         ()-import           Prelude.Compat+import Prelude ()+import Prelude.Compat -import           Control.Applicative             ((<|>))-import           Data.Generics.Labels            ()-import           Data.List                       (intercalate)+import Control.Applicative  ((<|>))+import Data.Generics.Labels ()+import Data.List            (intercalate)+import Data.Void            (Void)  import qualified Data.Foldable                   as F import qualified Data.Set                        as S import qualified Distribution.Compat.CharParsing as C-import qualified Distribution.Parsec.Class       as C+import qualified Distribution.Parsec             as C import qualified Distribution.Pretty             as C-import qualified Distribution.Types.Version      as C-import qualified Distribution.Types.VersionRange as C import qualified Text.PrettyPrint                as PP -import           HaskellCI.Package-import           HaskellCI.Project+import HaskellCI.Compiler+import HaskellCI.Package+import HaskellCI.Project  data TestedWithJobs     = TestedWithUniform@@ -41,33 +41,35 @@  checkVersions     :: TestedWithJobs-    -> Project (Package, S.Set C.Version)-    -> Either [String] (S.Set C.Version, Project Package)+    -> Project Void Package+    -> Either [String] (S.Set CompilerVersion, Project Void Package) checkVersions TestedWithUniform = checkVersionsUniform checkVersions TestedWithAny     = checkVersionsAny  checkVersionsUniform-    :: Project (Package, S.Set C.Version)-    -> Either [String] (S.Set C.Version, Project Package)+    :: Project Void Package+    -> Either [String] (S.Set CompilerVersion, Project Void Package) checkVersionsUniform prj | null (prjPackages prj) = Left ["Error reading cabal file(s)!"] checkVersionsUniform prj = do     let (errors, names) = F.foldl' collectConfig mempty prj     if not (null errors)     then Left errors-    else Right (allVersions, prj { prjPackages = names })+    else Right (allVersions, prj { prjPackages = names, prjOptPackages = [] })   where-    allVersions = F.foldMap snd prj+    allVersions :: S.Set CompilerVersion+    allVersions = F.foldMap pkgJobs prj      collectConfig         :: ([String], [Package])-        -> (Package, S.Set C.Version)+        -> Package         -> ([String], [Package])-    collectConfig aggregate (pkg, testWith) =+    collectConfig aggregate pkg =         aggregate <> (errors, [pkg])       where+        testWith = pkgJobs pkg         symDiff a b = S.union a b `S.difference` S.intersection a b         diff = symDiff testWith allVersions-        missingVersions = map C.prettyShow $ S.toList diff+        missingVersions = map dispGhcVersion $ S.toList diff         errors | S.null diff = []                | otherwise = pure $ mconcat                     [ pkgName pkg@@ -75,17 +77,11 @@                     ] ++ intercalate "," missingVersions  checkVersionsAny-    :: Project (Package, S.Set C.Version)-    -> Either [String] (S.Set C.Version, Project Package)+    :: Project Void Package+    -> Either [String] (S.Set CompilerVersion, Project Void Package) checkVersionsAny prj | null (prjPackages prj) = Left ["Error reading cabal file(s)!"] checkVersionsAny prj =-    Right (allVersions, uncurry f <$> prj)+    Right (allVersions, prj)   where-    allVersions = F.foldMap snd prj--    f :: Package -> S.Set C.Version -> Package-    f pkg vs = case S.toList vs of-        []      -> pkg { pkgJobs = C.noVersion }-        (v:vs') -> pkg { pkgJobs = foldr g (C.thisVersion v) vs' }--    g = C.unionVersionRanges . C.thisVersion+    allVersions :: S.Set CompilerVersion+    allVersions = F.foldMap pkgJobs prj
+ src/HaskellCI/Tools.hs view
@@ -0,0 +1,112 @@+-- Helpers to generate steps using tools: hlint and doctest+module HaskellCI.Tools (+    -- * Doctest+    doctestJobVersionRange,+    doctestArgs,+    -- * HLint+    hlintJobVersionRange,+    hlintArgs,+    ) where++import HaskellCI.Prelude++import qualified Data.Set                                      as S+import qualified Distribution.PackageDescription               as C+import qualified Distribution.PackageDescription.Configuration as C+import qualified Distribution.Pretty                           as C+import qualified Distribution.Types.VersionRange               as C+import qualified Distribution.Version                          as C++import qualified Distribution.Types.BuildInfo.Lens          as L+import qualified Distribution.Types.PackageDescription.Lens as L++import HaskellCI.Compiler+import HaskellCI.Config.HLint++-------------------------------------------------------------------------------+-- Doctest+-------------------------------------------------------------------------------++doctestJobVersionRange :: CompilerRange+doctestJobVersionRange = RangeGHC /\ Range (C.orLaterVersion $ C.mkVersion [8,0])++-- | Modules arguments to the library+--+-- * We check the library component+--+-- * If there are hs-source-dirs, use them+--+-- * otherwise use exposed + other modules+--+-- * Also add default-extensions+--+-- /Note:/ same argument work for hlint too, but not exactly+--+doctestArgs :: C.GenericPackageDescription -> [[String]]+doctestArgs gpd = nub $+    [ libraryModuleArgs c+    | c <- C.flattenPackageDescription gpd ^.. L.library . traverse+    ] +++    [ libraryModuleArgs c+    | c <- C.flattenPackageDescription gpd ^.. L.subLibraries . traverse+    ]++libraryModuleArgs :: C.Library -> [String]+libraryModuleArgs l+    | null dirsOrMods = []+    | otherwise       = exts ++ dirsOrMods+  where+    bi = l ^. L.buildInfo++    dirsOrMods+        | null (C.hsSourceDirs bi) = map C.prettyShow (C.exposedModules l)+        | otherwise                 = C.hsSourceDirs bi++    exts = map (("-X" ++) . C.prettyShow) (C.defaultExtensions bi)++executableModuleArgs :: C.Executable -> [String]+executableModuleArgs e+    | null dirsOrMods = []+    | otherwise       = exts ++ dirsOrMods+  where+    bi = e ^. L.buildInfo++    dirsOrMods+        -- note: we don't try to find main_is location, if hsSourceDirs is empty.+        | null (C.hsSourceDirs bi) = map C.prettyShow (C.otherModules bi)+        | otherwise                 = C.hsSourceDirs bi++    exts = map (("-X" ++) . C.prettyShow) (C.defaultExtensions bi)++-------------------------------------------------------------------------------+-- HLint+-------------------------------------------------------------------------------++hlintJobVersionRange+    :: Set CompilerVersion  -- ^ all compilers+    -> VersionRange         -- ^ head.hackage+    -> HLintJob             -- ^ hlint-jobs+    -> CompilerRange+hlintJobVersionRange vs headHackage HLintJobLatest = case S.maxView vs' of+    Just (v, _) -> RangePoints (S.singleton (GHC v))+    _           -> RangePoints S.empty+  where+    -- remove non GHC versions, and head.hackage versions+    vs' = S.fromList+        $ filter (\v -> not $ C.withinRange v headHackage)+        $ mapMaybe (maybeGHC Nothing Just)+        $ S.toList vs++hlintJobVersionRange _ _ (HLintJob v)   = RangePoints (S.singleton (GHC v))++hlintArgs :: C.GenericPackageDescription -> [[String]]+hlintArgs gpd = nub $+    [ libraryModuleArgs c+    | c <- C.flattenPackageDescription gpd ^.. L.library . traverse+    ] +++    [ libraryModuleArgs c+    | c <- C.flattenPackageDescription gpd ^.. L.subLibraries . traverse+    ] +++    [ executableModuleArgs c+    | c <- C.flattenPackageDescription gpd ^.. L.executables . traverse+    ]
+ src/HaskellCI/Travis.hs view
@@ -0,0 +1,699 @@+-- | Take configuration, produce 'Travis'.+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# OPTIONS_GHC -Wno-unused-imports -Wno-unused-matches #-}+module HaskellCI.Travis (+    makeTravis,+    travisHeader,+    ) where++import HaskellCI.Prelude+import Prelude           (head)++import qualified Data.Map.Strict                               as M+import qualified Data.Set                                      as S+import qualified Distribution.CabalSpecVersion                 as C+import qualified Distribution.FieldGrammar                     as C+import qualified Distribution.FieldGrammar.Pretty              as C+import qualified Distribution.Fields.Pretty                    as C+import qualified Distribution.Package                          as C+import qualified Distribution.PackageDescription               as C+import qualified Distribution.PackageDescription.Configuration as C+import qualified Distribution.PackageDescription.FieldGrammar  as C+import qualified Distribution.Pretty                           as C+import qualified Distribution.Types.GenericPackageDescription  as C+import qualified Distribution.Types.SourceRepo                 as C+import qualified Distribution.Types.VersionRange               as C+import qualified Distribution.Version                          as C+import qualified Text.PrettyPrint                              as PP++import qualified Distribution.Types.BuildInfo.Lens          as L+import qualified Distribution.Types.PackageDescription.Lens as L++import HaskellCI.Cli+import HaskellCI.Compiler+import HaskellCI.Config+import HaskellCI.Config.ConstraintSet+import HaskellCI.Config.CopyFields+import HaskellCI.Config.Doctest+import HaskellCI.Config.Folds+import HaskellCI.Config.HLint+import HaskellCI.Config.Installed+import HaskellCI.Config.Jobs+import HaskellCI.Config.Ubuntu+import HaskellCI.Jobs+import HaskellCI.List+import HaskellCI.MonadErr+import HaskellCI.Optimization+import HaskellCI.Package+import HaskellCI.Project+import HaskellCI.Sh+import HaskellCI.ShVersionRange+import HaskellCI.Tools+import HaskellCI.Travis.Yaml++-------------------------------------------------------------------------------+-- Travis header+-------------------------------------------------------------------------------++travisHeader :: Bool -> [String] -> [String]+travisHeader insertVersion argv =+    [ "This Travis job script has been generated by a script via"+    , ""+    , "  haskell-ci " ++ unwords [ "'" ++ a ++ "'" | a <- argv ]+    , ""+    , "For more information, see https://github.com/haskell-CI/haskell-ci"+    , ""+    ] +++    if insertVersion then+    [ "version: " ++ haskellCIVerStr+    , ""+    ] else []++-------------------------------------------------------------------------------+-- Generate travis configuration+-------------------------------------------------------------------------------++makeTravis+    :: [String]+    -> Config+    -> Project Void Package+    -> JobVersions+    -> Either ShError Travis -- TODO: writer+makeTravis argv Config {..} prj JobVersions {..} = do+    -- before caching: clear some redundant stuff+    beforeCache <- runSh $ when cfgCache $ do+        sh "rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log"+        comment "remove files that are regenerated by 'cabal update'"+        sh "rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.*" -- legacy+        sh "rm -fv $CABALHOME/packages/hackage.haskell.org/*.json" -- TUF meta-data+        sh "rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache"+        sh "rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar"+        sh "rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx"+        sh "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+    beforeInstall <- runSh $ do+        -- This have to be first+        when anyGHCJS $ sh $ unlines+            [ "if echo $CC | grep -q ghcjs; then"+            , "    GHCJS=true;"+            , "else"+            , "    GHCJS=false;"+            , "fi"+            ]++        when (anyGHCJS || isBionic) $ sh $ unlines $ buildList $ do+            let item' x = item $ "  " ++ x ++ ";"++            item "if [ \"$TRAVIS_OS_NAME\" = \"linux\" ]; then"+            when isBionic $ item' "sudo add-apt-repository -y ppa:hvr/ghc"+            traverse_ item' $ forJob RangeGHCJS "sudo add-apt-repository -y ppa:hvr/ghcjs"+            traverse_ item' $ forJob RangeGHCJS "curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | sudo apt-key add -"+            traverse_ item' $ forJob RangeGHCJS $ "sudo apt-add-repository 'https://deb.nodesource.com/node_8.x " ++ C.prettyShow cfgUbuntu  ++ " main'"+            traverse_ item' $ forJob (boolToBoundedLattice isBionic \/ RangeGHCJS) "sudo apt-get update"+            item' $ "sudo apt-get install $CC" +++                (if S.null cfgApt+                then ""+                else " " ++ unwords (S.toList cfgApt))+            traverse_ item' $ forJob RangeGHCJS "sudo apt-get install -y nodejs cabal-install-3.0" -- TODO: select right `cabal-install` version.+            item "fi"++        -- Adjust $HC+        sh "HC=$(echo \"/opt/$CC/bin/ghc\" | sed 's/-/\\//')"+        sh "WITHCOMPILER=\"-w $HC\""+        shForJob RangeGHCJS "HC=${HC}js"+        shForJob RangeGHCJS "WITHCOMPILER=\"--ghcjs ${WITHCOMPILER}js\""++        -- 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+        when anyGHCJS $ do+            shForJob RangeGHCJS $ "sudo apt-get install -y ghc-8.4.4"+            shForJob RangeGHCJS $ "PATH=\"/opt/ghc/8.4.4/bin:$PATH\""++        sh "HCPKG=\"$HC-pkg\""+        sh "unset CC"+        -- cabal+        sh "CABAL=/opt/ghc/bin/cabal"+        sh "CABALHOME=$HOME/.cabal"+        -- PATH+        sh "export PATH=\"$CABALHOME/bin:$PATH\""+        -- rootdir is useful for manual script additions+        sh "TOP=$(pwd)"+        -- macOS installing+        let haskellOnMacos = "https://haskell.futurice.com/haskell-on-macos.py"+        unless (null cfgOsx) $ do+            sh $ "if [ \"$TRAVIS_OS_NAME\" = \"osx\" ]; then brew update; brew upgrade python@3; curl " ++ haskellOnMacos ++ " | python3 - --make-dirs --install-dir=$HOME/.ghc-install --cabal-alias=head install cabal-install-head ${TRAVIS_COMPILER}; fi"+            sh' [2034,2039] "if [ \"$TRAVIS_OS_NAME\" = \"osx\" ]; then HC=$HOME/.ghc-install/ghc/bin/$TRAVIS_COMPILER; WITHCOMPILER=\"-w $HC\"; HCPKG=${HC/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+        sh "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"+        sh "echo $HCNUMVER"+        -- verbose in .cabal/config is not respected+        -- https://github.com/haskell/cabal/issues/5956+        sh "CABAL=\"$CABAL -vnormal+nowrap+markoutput\""++        -- Color cabal output+        sh' [2039] "set -o pipefail" -- SC2039: In POSIX sh, set option pipefail is undefined. Travis is bash, so it's fine :)+        when cfgColor $ do+            cat' ".colorful.awk"+                [ "function blue(s) { printf \"\\033[0;34m\" s \"\\033[0m \" }"+                , "BEGIN { state = \"output\"; }"+                , "/^-----BEGIN CABAL OUTPUT-----$/ { state = \"cabal\" }"+                , "/^-----END CABAL OUTPUT-----$/ { state = \"output\" }"+                , "!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {"+                , "  if (state == \"cabal\") {"+                , "    print blue($0)"+                , "  } else {"+                , "    print $0"+                , "  }"+                , "}"+                ]+            sh "cat .colorful.awk"+            sh $ unlines+                [ "color_cabal_output () {"+                , "  awk -f $TOP/.colorful.awk"+                , "}"+                ]+            sh "echo text | color_cabal_output"++    -- in install step we install tools and dependencies+    install <- runSh $ do+        sh "${CABAL} --version"+        sh "echo \"$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]\""+        when anyGHCJS $ do+            sh "node --version"+            sh "echo $GHCJS"++        sh "TEST=--enable-tests"+        shForJob (invertCompilerRange $ Range cfgTests) "TEST=--disable-tests"+        sh "BENCH=--enable-benchmarks"+        shForJob (invertCompilerRange $ Range cfgBenchmarks) "BENCH=--disable-benchmarks"+        sh "HEADHACKAGE=false"+        shForJob (Range cfgHeadHackage \/ RangePoints (S.singleton GHCHead)) "HEADHACKAGE=true"++        -- create ~/.cabal/config+        sh "rm -f $CABALHOME/config"+        cat "$CABALHOME/config"+            [ "verbose: normal +nowrap +markoutput" -- https://github.com/haskell/cabal/issues/5956+            , "remote-build-reporting: anonymous"+            , "write-ghc-environment-files: always"+            , "remote-repo-cache: $CABALHOME/packages"+            , "logs-dir:          $CABALHOME/logs"+            , "world-file:        $CABALHOME/world"+            , "extra-prog-path:   $CABALHOME/bin"+            , "symlink-bindir:    $CABALHOME/bin"+            , "installdir:        $CABALHOME/bin"+            , "build-summary:     $CABALHOME/logs/build.log"+            , "store-dir:         $CABALHOME/store"+            , "install-dirs user"+            , "  prefix: $CABALHOME"+            , "repository hackage.haskell.org"+            , "  url: http://hackage.haskell.org/"+            ]++        -- Add head.hackage repository to ~/.cabal/config+        -- (locally you want to add it to cabal.project)+        unless (S.null headGhcVers) $ sh $ unlines $+            [ "if $HEADHACKAGE; then"+            , "echo \"allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\\1/g')\" >> $CABALHOME/config"+            ] +++            lines (catCmd Double "$CABALHOME/config"+            [ "repository head.hackage.ghc.haskell.org"+            , "   url: https://ghc.gitlab.haskell.org/head.hackage/"+            , "   secure: True"+            , "   root-keys: 7541f32a4ccca4f97aea3b22f5e593ba2c0267546016b992dfadcd2fe944e55d"+            , "              26021a13b401500c8eb2761ca95c61f2d625bfef951b939a8124ed12ecf07329"+            , "              f76d08be13e9a61a377a85e2fb63f4c5435d40f8feb3e12eb05905edb8cdea89"+            , "   key-threshold: 3"+            ]) +++            [ "fi"+            ]++        -- Cabal jobs+        for_ (cfgJobs >>= cabalJobs) $ \n ->+            sh $ "echo 'jobs: " ++ show n ++ "' >> $CABALHOME/config"++        -- GHC jobs+        for_ (cfgJobs >>= ghcJobs) $ \m -> do+            catForJob (Range $ C.orLaterVersion (C.mkVersion [7,8])) "$CABALHOME/config"+                [ "program-default-options"+                , "  ghc-options: -j" ++ show m+                ]++        sh "cat $CABALHOME/config"++        -- remove project own cabal.project files+        sh "rm -fv cabal.project cabal.project.local cabal.project.freeze"++        -- Update hackage index.+        sh "travis_retry ${CABAL} v2-update -v"++        -- Install doctest+        let doctestVersionConstraint+                | C.isAnyVersion (cfgDoctestVersion cfgDoctest) = ""+                | otherwise = " --constraint='doctest " ++ C.prettyShow (cfgDoctestVersion cfgDoctest) ++ "'"+        when doctestEnabled $+            shForJob (Range (cfgDoctestEnabled cfgDoctest) /\ doctestJobVersionRange) $+                cabalInTmp $ "v2-install $WITHCOMPILER -j2 doctest" ++ doctestVersionConstraint++        -- Install hlint+        let hlintVersionConstraint+                | C.isAnyVersion (cfgHLintVersion cfgHLint) = ""+                | otherwise = " --constraint='hlint " ++ C.prettyShow (cfgHLintVersion cfgHLint) ++ "'"+        when (cfgHLintEnabled cfgHLint) $ shForJob (hlintJobVersionRange versions cfgHeadHackage (cfgHLintJob cfgHLint)) $+            cabalInTmp $ "v2-install $WITHCOMPILER -j2 hlint" ++ hlintVersionConstraint++        when (anyGHCJS && cfgGhcjsTests) $ shForJob RangeGHCJS $ cabalInTmp "v2-install -w ghc-8.4.4 cabal-plan"++        -- Install happy+        when anyGHCJS $ shForJob RangeGHCJS $ cabalInTmp "v2-install -w ghc-8.4.4 happy"++        -- create cabal.project file+        generateCabalProject False++        -- autoreconf+        for_ pkgs $ \Pkg{pkgDir} ->+            sh $ "if [ -f \"" ++ pkgDir ++ "/configure.ac\" ]; then (cd \"" ++ pkgDir ++ "\" && autoreconf -i); fi"++        -- dump install plan+        sh $ cabal "v2-freeze $WITHCOMPILER ${TEST} ${BENCH}"+        sh "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"+        sh "rm  cabal.project.freeze"++        -- Install dependencies+        when cfgInstallDeps $ do+            -- install dependencies+            sh $ cabal "v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all"++            -- install dependencies for no-test-no-bench+            shForJob (Range cfgNoTestsNoBench) $ cabal "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.+    script <- runSh $ do+        sh "DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)"++        -- sdist+        foldedSh FoldSDist "Packaging..." cfgFolds $ do+            sh $ cabal "v2-sdist all"++        -- unpack+        foldedSh FoldUnpack "Unpacking..." cfgFolds $ do+            sh "mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/"+            sh "cd ${DISTDIR} || false" -- fail explicitly, makes SC happier+            sh "find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \\;"+            sh "find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm       '{}' \\;"++            for_ pkgs $ \Pkg{pkgName} -> do+                sh $ pkgNameDirVariable' pkgName ++ "=\"$(find . -maxdepth 1 -type d -regex '.*/" ++ pkgName ++ "-[0-9.]*')\""++            generateCabalProject True++        -- build no-tests no-benchmarks+        unless (equivVersionRanges C.noVersion cfgNoTestsNoBench) $ foldedSh FoldBuild "Building..." cfgFolds $ do+            comment "this builds all libraries and executables (without tests/benchmarks)"+            shForJob (Range cfgNoTestsNoBench) $ cabal "v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all"++        -- build everything+        foldedSh FoldBuildEverything "Building with tests and benchmarks..." cfgFolds $ do+            comment "build & run tests, build benchmarks"+            sh $ cabal "v2-build $WITHCOMPILER ${TEST} ${BENCH} all"++        -- cabal v2-test fails if there are no test-suites.+        foldedSh FoldTest "Testing..." cfgFolds $ do+            shForJob (RangeGHC /\ Range (cfgTests /\ cfgRunTests) /\ hasTests) $+                cabal "v2-test $WITHCOMPILER ${TEST} ${BENCH} all"++            when cfgGhcjsTests $ shForJob (RangeGHCJS /\ hasTests)+                "for testexe in $(cabal-plan list-bins '*:test:*' | awk '{ print $2 }'); do echo $testexe; nodejs ${testexe}.jsexe/all.js; done"++        -- doctest+        when doctestEnabled $ foldedSh FoldDoctest "Doctest..." cfgFolds $ do+            let doctestOptions = unwords $ cfgDoctestOptions cfgDoctest+            unless (null $ cfgDoctestFilterPkgs cfgDoctest) $ do+                sh $ unlines $ concat+                    [ [ "for ghcenv in .ghc.environment.*; do"+                      , "mv $ghcenv ghcenv;"+                      ]+                    , cfgDoctestFilterPkgs cfgDoctest <&> \pn ->+                        "grep -vE '^package-id " ++ C.unPackageName pn ++ "-([0-9]+(\\.[0-9]+)*)-' ghcenv > ghcenv.tmp; mv ghcenv.tmp ghcenv;"+                    , [ "mv ghcenv $ghcenv;"+                      , "cat $ghcenv;"+                      , "done"+                      ]+                    ]+            for_ pkgs $ \Pkg{pkgName,pkgGpd,pkgJobs} -> do+                for_ (doctestArgs pkgGpd) $ \args -> do+                    let args' = unwords args+                    let vr = Range (cfgDoctestEnabled cfgDoctest)+                          /\ doctestJobVersionRange+                          /\ RangePoints pkgJobs+                    unless (null args) $ shForJob  vr $+                        "(cd " ++ pkgNameDirVariable pkgName ++ " && doctest " ++ doctestOptions ++ " " ++ args' ++ ")"++        -- hlint+        when (cfgHLintEnabled cfgHLint) $ foldedSh FoldHLint "HLint.." cfgFolds $ do+            let "" <+> ys = ys+                xs <+> "" = xs+                xs <+> ys = xs ++ " " ++ ys++                prependSpace "" = ""+                prependSpace xs = " " ++ xs++            let hlintOptions = prependSpace $ maybe "" ("-h ${TOP}/" ++) (cfgHLintYaml cfgHLint) <+> unwords (cfgHLintOptions cfgHLint)++            for_ pkgs $ \Pkg{pkgName,pkgGpd,pkgJobs} -> do+                for_ (hlintArgs pkgGpd) $ \args -> do+                    let args' = unwords args+                    unless (null args) $+                        shForJob (hlintJobVersionRange versions cfgHeadHackage (cfgHLintJob cfgHLint) /\ RangePoints pkgJobs) $+                        "(cd " ++ pkgNameDirVariable pkgName ++ " && hlint" ++ hlintOptions ++ " " ++ args' ++ ")"++        -- cabal check+        when cfgCheck $ foldedSh FoldCheck "cabal check..." cfgFolds $ do+            for_ pkgs $ \Pkg{pkgName,pkgJobs} -> shForJob (RangePoints pkgJobs) $+                "(cd " ++ pkgNameDirVariable pkgName ++ " && ${CABAL} -vnormal check)"++        -- haddock+        when (hasLibrary && not (equivVersionRanges C.noVersion cfgHaddock)) $+            foldedSh FoldHaddock "haddock..." cfgFolds $+                shForJob (RangeGHC /\ Range cfgHaddock) $ cabal "v2-haddock $WITHCOMPILER ${TEST} ${BENCH} all"++        -- unconstained build+        -- Have to build last, as we remove cabal.project.local+        unless (equivVersionRanges C.noVersion cfgUnconstrainted) $+            foldedSh FoldBuildInstalled "Building without installed constraints for packages in global-db..." cfgFolds $ do+                shForJob (Range cfgUnconstrainted) "rm -f cabal.project.local"+                shForJob (Range cfgUnconstrainted) $ cabal "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+        unless (null cfgConstraintSets) $ do+            comment "Constraint sets"+            sh "rm -rf cabal.project.local"++            for_ cfgConstraintSets $ \cs -> do+                let name            = csName cs+                let shForCs         = shForJob (Range (csGhcVersions cs))+                let testFlag        = if csTests cs then "--enable-tests" else "--disable-tests"+                let benchFlag       = if csBenchmarks cs then "--enable-benchmarks" else "--disable-benchmarks"+                let constraintFlags = map (\x ->  "--constraint='" ++ x ++ "'") (csConstraints cs)+                let allFlags        = unwords (testFlag : benchFlag : constraintFlags)++                foldedSh' FoldConstraintSets name ("Constraint set " ++ name) cfgFolds $ do+                    shForCs $ cabal $ "v2-build $WITHCOMPILER " ++ allFlags ++ " all"+                    when (csRunTests cs) $+                        shForCs $ cabal $ "v2-test $WITHCOMPILER " ++ allFlags ++ " all"+                    when (csHaddock cs) $+                        shForCs $ cabal $ "v2-haddock $WITHCOMPILER " ++ allFlags ++ " all"++    -- assemble travis configuration+    return Travis+        { travisLanguage      = "c"+        , travisUbuntu        = cfgUbuntu+        , travisGit           = TravisGit+            { tgSubmodules = cfgSubmodules+            }+        , travisCache         = TravisCache+            { tcDirectories = buildList $ when cfgCache $ do+                item "$HOME/.cabal/packages"+                item "$HOME/.cabal/store"+                -- on OSX ghc is installed in $HOME so we can cache it+                -- independently of linux+                when (cfgCache && not (null cfgOsx)) $ do+                    item "$HOME/.ghc-install"+            }+        , travisBranches      = TravisBranches+            { tbOnly = cfgOnlyBranches+            }+        , travisNotifications = TravisNotifications+            { tnIRC = justIf (not $ null cfgIrcChannels) $ TravisIRC+                { tiChannels = cfgIrcChannels+                , tiSkipJoin = True+                , tiTemplate =+                    [ "\"\\x0313" ++ projectName ++ "\\x03/\\x0306%{branch}\\x03 \\x0314%{commit}\\x03 %{build_url} %{message}\""+                    ]+                }+            }+        , travisServices      = buildList $ do+            when cfgPostgres $ item "postgresql"+        , travisAddons        = TravisAddons+            { taApt      = TravisApt [] []+            , taPostgres = if cfgPostgres then Just "10" else Nothing+            }+        , travisMatrix        = TravisMatrix+            { tmInclude = buildList $ do+                let tellJob :: Bool -> CompilerVersion -> ListBuilder TravisJob ()+                    tellJob osx gv = do+                        let cvs = dispCabalVersion $ correspondingCabalVersion cfgCabalInstallVersion gv+                        let gvs = dispGhcVersion gv++                        -- GHCJS cannot be installed via apt plugin+                        let addGvs | isGHCJS gv = id+                                   | otherwise  = (gvs :)++                        item TravisJob+                            { tjCompiler = gvs+                            , tjOS       = if osx then "osx" else "linux"+                            , tjEnv      = case gv of+                                GHC v -> M.lookup v cfgEnv+                                _     -> Nothing+                            , tjAddons   = TravisAddons+                                { taApt = TravisApt+                                    { taPackages = addGvs $ ("cabal-install-" ++ cvs) : S.toList cfgApt+                                    , taSources  = ["hvr-ghc"]+                                    }+                                , taPostgres = Nothing+                                }+                            }++                for_ (reverse $ S.toList versions) $ tellJob False+                for_ (reverse $ S.toList osxVersions) $ tellJob True . GHC++            , tmAllowFailures =+                [ TravisAllowFailure $ dispGhcVersion compiler+                | compiler <- toList versions+                , previewGHC cfgHeadHackage compiler || maybeGHC False (`C.withinRange` cfgAllowFailures) compiler+                ]+            }+        , travisBeforeCache   = beforeCache+        , travisBeforeInstall = beforeInstall+        , travisInstall       = install+        , travisScript        = script+        }+  where+    pkgs = prjPackages prj+    projectName = fromMaybe (pkgName $ Prelude.head pkgs) cfgProjectName++    justIf True x  = Just x+    justIf False _ = Nothing++    -- TODO: should this be part of MonadSh ?+    foldedSh label = foldedSh' label ""++    isBionic = cfgUbuntu == Bionic+    anyGHCJS = any isGHCJS 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' label sfx plabel labels block+        | label `S.notMember` labels = commentedBlock plabel block+        | otherwise = case runSh block of+            Left err  -> throwErr err+            Right shs+                | all isComment shs -> pure ()+                | otherwise         -> ShM $ \shs1 -> Right $+                    ( shs1+                    . (Comment plabel :)+                    . (Sh ("echo '" ++ plabel ++ "' && echo -en 'travis_fold:start:" ++ label' ++ "\\\\r'") :)+                    . (shs ++)+                    . (Sh ("echo -en 'travis_fold:end:" ++ label' ++ "\\\\r'") :)+                    -- return ()+                    , ()+                    )+      where+        label' | null sfx  = showFold label+               | otherwise = showFold label ++ "-" ++ sfx++    doctestEnabled = any (maybeGHC False (`C.withinRange` cfgDoctestEnabled cfgDoctest)) versions++    -- version range which has tests+    hasTests :: CompilerRange+    hasTests = RangePoints $ S.unions+        [ pkgJobs+        | Pkg{pkgGpd,pkgJobs} <- pkgs+        , not $ null $ C.condTestSuites pkgGpd+        ]++    hasLibrary = any (\Pkg{pkgGpd} -> isJust $ C.condLibrary pkgGpd) pkgs++    -- GHC versions which need head.hackage+    headGhcVers :: Set CompilerVersion+    headGhcVers = S.filter (previewGHC cfgHeadHackage) versions++    cabal :: String -> String+    cabal cmd | cfgColor  = cabalCmd ++ " | color_cabal_output"+              | otherwise = cabalCmd+      where+        cabalCmd = "${CABAL} " ++ cmd++    cabalInTmp :: String -> String+    cabalInTmp cmd = "(cd /tmp && " ++ cabal cmd ++ ")"++    forJob :: CompilerRange -> String -> Maybe String+    forJob vr cmd+        | all (`compilerWithinRange` vr) versions       = Just cmd+        | not $ any (`compilerWithinRange` vr) versions = Nothing+        | otherwise                                     = Just $ unwords+            [ "if"+            , compilerVersionPredicate versions vr+            , "; then"+            , cmd+            , "; fi"+            ]++    shForJob :: CompilerRange -> String -> ShM ()+    shForJob vr cmd = maybe (pure ()) sh (forJob vr cmd)++    catForJob vr fp contents = shForJob vr (catCmd Double fp contents)++    generateCabalProjectFields :: Bool -> [C.PrettyField ()]+    generateCabalProjectFields dist = buildList $ do+        -- copy files from original cabal.project+        case cfgCopyFields of+            CopyFieldsNone -> pure ()+            CopyFieldsAll  -> traverse_ item (prjOrigFields prj)+            CopyFieldsSome -> do+                for_ (prjConstraints prj) $ \xs -> do+                    let s = concat (lines xs)+                    item $ C.PrettyField () "constraints" $ PP.text s++                for_ (prjAllowNewer prj) $ \xs -> do+                    let s = concat (lines xs)+                    item $ C.PrettyField () "allow-newer" $ PP.text s++                when (prjReorderGoals prj) $+                    item $ C.PrettyField () "reorder-goals" $ PP.text "True"++                for_ (prjMaxBackjumps prj) $ \bj ->+                    item $ C.PrettyField () "max-backjumps" $ PP.text $ show bj++                case prjOptimization prj of+                    OptimizationOn      -> return ()+                    OptimizationOff     -> item $ C.PrettyField () "optimization" $ PP.text "False"+                    OptimizationLevel l -> item $ C.PrettyField () "optimization" $ PP.text $ show l++                for_ (prjSourceRepos prj) $ \repo ->+                    item $ C.PrettySection () "source-repository-package" [] $+                        C.prettyFieldGrammar C.cabalSpecLatest (C.sourceRepoFieldGrammar $ C.RepoKindUnknown "unused") repo++        -- local ghc-options+        unless (null cfgLocalGhcOptions) $ for_ pkgs $ \Pkg{pkgName} -> do+            let s = unwords $ map (show . C.showToken) cfgLocalGhcOptions+            item $ C.PrettySection () "package" [PP.text pkgName] $ buildList $+                item $ C.PrettyField () "ghc-options" $ PP.text s++        -- raw-project is after local-ghc-options so we can override per package.+        traverse_ item cfgRawProject++    generateCabalProject :: Bool -> ShM ()+    generateCabalProject dist = do+        comment "Generate cabal.project"+        sh "rm -rf cabal.project cabal.project.local cabal.project.freeze"+        sh "touch cabal.project"++        sh $ unlines+            [ cmd+            | pkg <- pkgs+            , let p | dist      = pkgNameDirVariable (pkgName pkg)+                    | otherwise = pkgDir pkg+            , cmd <- toList $ forJob (RangePoints $ pkgJobs pkg) $+                "echo \"packages: " ++ p ++ "\" >> cabal.project"+            ]++        cat "cabal.project" $ lines $ C.showFields' (const []) 2 $ generateCabalProjectFields dist++        -- also write cabal.project.local file with+        -- @+        -- constraints: base installed+        -- constraints: array installed+        -- ...+        --+        -- omitting any local package names+        case normaliseInstalled cfgInstalled of+            InstalledDiff pns -> sh $ unwords+                [ "for pkg in $($HCPKG list --simple-output); do"+                , "echo $pkg"+                , "| sed 's/-[^-]*$//'"+                , "| (grep -vE -- " ++ re ++ " || true)"+                , "| sed 's/^/constraints: /'"+                , "| sed 's/$/ installed/'"+                , ">> cabal.project.local; done"+                ]+              where+                pns' = S.map C.unPackageName pns `S.union` foldMap (S.singleton . pkgName) pkgs+                re = "'^(" ++ intercalate "|" (S.toList pns') ++ ")$'"++            InstalledOnly pns | not (null pns') -> sh' [2043] $ unwords+                [ "for pkg in " ++ unwords (S.toList pns') ++ "; do"+                , "echo \"constraints: $pkg installed\""+                , ">> cabal.project.local; done"+                ]+              where+                pns' = S.map C.unPackageName pns `S.difference` foldMap (S.singleton . pkgName) pkgs++            -- otherwise: nothing+            _ -> pure ()++        sh "cat cabal.project || true"+        sh "cat cabal.project.local || true"++pkgNameDirVariable' :: String -> String+pkgNameDirVariable' n = "PKGDIR_" ++ map f n where+    f '-' = '_'+    f c   = c++pkgNameDirVariable :: String -> String+pkgNameDirVariable n = "${PKGDIR_" ++ map f n ++ "}" where+    f '-' = '_'+    f c   = c++data Quotes = Single | Double++escape :: Quotes -> String -> String+escape Single xs = "'" ++ concatMap f xs ++ "'" where+    f '\0' = ""+    f '\'' = "'\"'\"'"+    f x    = [x]+escape Double xs = show xs++catCmd :: Quotes -> FilePath -> [String] -> String+catCmd q fp contents = unlines+    [ "echo " ++ escape q l ++ replicate (maxLength - length l) ' ' ++ " >> " ++ fp+    | l <- contents+    ]+  where+    maxLength = foldl' (\a l -> max a (length l)) 0 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 fp contents = sh $ catCmd Double fp contents++cat' :: FilePath -> [String] -> ShM ()+cat' fp contents = sh' [2016, 2129] $ catCmd Single fp contents+-- SC2129: Consider using { cmd1; cmd2; } >> file instead of individual redirects+-- SC2016: Expressions don't expand in single quotes+-- that's the point!++boolToBoundedLattice :: BoundedLattice a => Bool -> a+boolToBoundedLattice True = top+boolToBoundedLattice False = bottom
+ src/HaskellCI/Travis/Yaml.hs view
@@ -0,0 +1,232 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE StrictData        #-}+-- | @travis.yaml@ structure.+module HaskellCI.Travis.Yaml where++import           HaskellCI.Prelude++import qualified Data.Aeson              as Aeson+import qualified Data.List.NonEmpty      as NE++import           HaskellCI.Config.Ubuntu+import           HaskellCI.List+import           HaskellCI.Sh+import           HaskellCI.YamlSyntax++-------------------------------------------------------------------------------+-- Data+-------------------------------------------------------------------------------++data Travis = Travis+    { travisUbuntu        :: !Ubuntu+    , travisLanguage      :: !String+    , travisGit           :: !TravisGit+    , travisCache         :: !TravisCache+    , travisBranches      :: !TravisBranches+    , travisNotifications :: !TravisNotifications+    , travisServices      :: ![String]+    , travisAddons        :: !TravisAddons+    , travisMatrix        :: !TravisMatrix+    , travisBeforeCache   :: ![Sh]+    , travisBeforeInstall :: ![Sh]+    , travisInstall       :: ![Sh]+    , travisScript        :: ![Sh]+    }+  deriving Show++newtype TravisGit = TravisGit+    { tgSubmodules :: Bool+    }+  deriving Show++newtype TravisCache = TravisCache+    { tcDirectories :: [FilePath]+    }+  deriving Show++newtype TravisBranches = TravisBranches+    { tbOnly :: [String]+    }+  deriving Show++newtype TravisNotifications = TravisNotifications+    { tnIRC :: Maybe TravisIRC+    }+  deriving Show++data TravisIRC = TravisIRC+    { tiChannels :: [String]+    , tiSkipJoin :: Bool+    , tiTemplate :: [String]+    }+  deriving Show++data TravisMatrix = TravisMatrix+    { tmInclude       :: [TravisJob]+    , tmAllowFailures :: [TravisAllowFailure]+    }+  deriving Show++data TravisJob = TravisJob+    { tjCompiler :: String+    , tjEnv      :: Maybe String+    , tjAddons   :: TravisAddons+    , tjOS       :: String+    }+  deriving Show++data TravisAddons = TravisAddons+    { taApt      :: TravisApt+    , taPostgres :: Maybe String+    }+  deriving Show++data TravisApt = TravisApt+    { taPackages :: [String]+    , taSources  :: [String]+    }+  deriving Show++newtype TravisAllowFailure = TravisAllowFailure+    { tafCompiler :: String+    }+  deriving Show++-------------------------------------------------------------------------------+-- Serialisation helpers (move to Travis.Yaml?)+-------------------------------------------------------------------------------++(~>) :: String -> Yaml [String] -> ([String], String, Yaml [String])+k ~> v = ([],k,v)++(^^^) :: ([String], String, Yaml [String]) -> String -> ([String], String, Yaml [String])+(a,b,c) ^^^ d = (d : a, b, c)++shListToYaml :: [Sh] -> Yaml [String]+shListToYaml shs = YList [] $ concat+    [ YString cs x : map fromString xs+    | (cs, x :| xs) <- gr shs+    ]+  where+    gr :: [Sh] -> [([String], NonEmpty String)]+    gr [] = []+    gr (Sh x : rest) = case gr rest of+        ([], xs) : xss -> ([], NE.cons x xs) : xss+        xss            -> ([], pure x) : xss++    gr (Comment c : rest) = case gr rest of+        (cs, xs) : xss -> (c : cs, xs) : xss+        []             -> [] -- end of comments are lost++ykeyValuesFilt :: ann -> [(ann, String, Yaml ann)] -> Yaml ann+ykeyValuesFilt ann xs = YKeyValues ann+    [ x+    | x@(_,_,y)  <- xs+    , not (isEmpty y)+    ]++ylistFilt :: ann -> [Yaml ann] -> Yaml ann+ylistFilt ann xs = YList ann+    [ x+    | x <- xs+    , not (isEmpty x)+    ]++isEmpty :: Yaml ann -> Bool+isEmpty (YList _ [])      = True+isEmpty (YKeyValues _ []) = True+isEmpty _                 = False++-------------------------------------------------------------------------------+-- ToYaml+-------------------------------------------------------------------------------++instance ToYaml Travis where+    toYaml Travis {..} = ykeyValuesFilt []+        [ "language"       ~> fromString travisLanguage+        , "dist"           ~> fromString (showUbuntu travisUbuntu)+        , "git"            ~> toYaml travisGit+        , "branches"       ~> toYaml travisBranches+        , "notifications"  ~> toYaml travisNotifications+        , "services"       ~> YList [] (map fromString travisServices)+        , "addons"         ~> toYaml travisAddons+        , "cache"          ~> toYaml travisCache+        , "before_cache"   ~> shListToYaml travisBeforeCache+        , "matrix"         ~> toYaml travisMatrix+        , "before_install" ~> shListToYaml travisBeforeInstall+        , "install"        ~> shListToYaml travisInstall+        , "script"         ~> shListToYaml travisScript+        ]++instance ToYaml TravisGit where+    toYaml TravisGit {..} = ykeyValuesFilt []+        [ "submodules" ~> toYaml tgSubmodules+          ^^^ "whether to recursively clone submodules"+        ]++instance ToYaml TravisBranches where+    toYaml TravisBranches {..} = ykeyValuesFilt []+        [ "only" ~> ylistFilt [] (map fromString tbOnly)+        ]++instance ToYaml TravisNotifications where+    toYaml TravisNotifications {..} = ykeyValuesFilt [] $ buildList $+        for_ tnIRC $ \y -> item $ "irc" ~> toYaml y++instance ToYaml TravisIRC where+    toYaml TravisIRC {..} = ykeyValuesFilt []+        [ "channels"  ~> YList [] (map fromString tiChannels)+        , "skip_join" ~> toYaml tiSkipJoin+        , "template"  ~> YList [] (map fromString tiTemplate)+        ]++instance ToYaml TravisCache where+    toYaml TravisCache {..} = ykeyValuesFilt []+        [ "directories" ~> ylistFilt []+            [ fromString d+            | d <- tcDirectories+            ]+        ]++instance ToYaml TravisMatrix where+    toYaml TravisMatrix {..} = ykeyValuesFilt []+        [ "include"        ~> ylistFilt [] (map toYaml tmInclude)+        , "allow_failures" ~> ylistFilt [] (map toYaml tmAllowFailures)+        ]++instance ToYaml TravisJob where+    toYaml TravisJob {..} = ykeyValuesFilt [] $ buildList $ do+        item $ "compiler" ~> fromString tjCompiler+        item $ "addons" ~> toYaml (Aeson.toJSON tjAddons)+        for_ tjEnv $ \e ->+            item $ "env" ~> fromString e+        unless (tjOS == "linux") $+            item $ "os" ~> fromString tjOS++instance ToYaml TravisAllowFailure where+    toYaml TravisAllowFailure {..} = ykeyValuesFilt []+        [ "compiler" ~> fromString tafCompiler+        ]++instance ToYaml TravisAddons where+    toYaml TravisAddons {..} = ykeyValuesFilt [] $ buildList $ do+        -- no apt on purpose+        for_ taPostgres $ \p ->+            item $ "postgresql" ~> fromString p++-------------------------------------------------------------------------------+-- ToJSON+-------------------------------------------------------------------------------++instance Aeson.ToJSON TravisAddons where+    -- no postgresql on purpose+    toJSON TravisAddons {..} = Aeson.object+        [ "apt" Aeson..= taApt+        ]++instance Aeson.ToJSON TravisApt where+    toJSON TravisApt {..} = Aeson.object+        [ "packages" Aeson..= taPackages+        , "sources"  Aeson..= taSources+        ]
− src/HaskellCI/Version.hs
@@ -1,42 +0,0 @@-module HaskellCI.Version where--import           Data.Function                      (on)-import           Data.List                          (intercalate)--import qualified Distribution.Version as C--ghcVersionPredicate :: C.VersionRange -> String-ghcVersionPredicate = conj . C.asVersionIntervals-  where-    conj = intercalate "  ||  " . map disj--    disj :: C.VersionInterval -> String-    disj (C.LowerBound v C.InclusiveBound, C.UpperBound u C.InclusiveBound)-        | v == u                = "[ $HCNUMVER -eq " ++ f v ++ " ]"-    disj (lb, C.NoUpperBound)-        | isInclZero lb         = "true"-        | otherwise             = lower lb-    disj (lb, C.UpperBound v b)-        | isInclZero lb         = upper v b-        | otherwise             = lower lb ++ " && " ++ upper v b--    isInclZero (C.LowerBound v C.InclusiveBound) = v == C.mkVersion [0]-    isInclZero (C.LowerBound _ C.ExclusiveBound) = False--    lower (C.LowerBound v C.InclusiveBound) = "[ $HCNUMVER -ge " ++ f v ++ " ]"-    lower (C.LowerBound v C.ExclusiveBound) = "[ $HCNUMVER -gt " ++ f v ++ " ]"--    upper v C.InclusiveBound = "[ $HCNUMVER -le " ++ f v ++ " ]"-    upper v C.ExclusiveBound = "[ $HCNUMVER -lt " ++ f v ++ " ]"--    f = ghcVersionToString--ghcVersionToString :: C.Version -> String-ghcVersionToString v =  case C.versionNumbers v of-    []        -> "0"-    [x]       -> show (x * 10000)-    [x,y]     -> show (x * 10000 + y * 100)-    (x:y:z:_) -> show (x * 10000 + y * 100 + z)--equivVersionRanges :: C.VersionRange -> C.VersionRange -> Bool-equivVersionRanges = on (==) C.asVersionIntervals
+ src/HaskellCI/YamlSyntax.hs view
@@ -0,0 +1,317 @@+{-# LANGUAGE DeriveFoldable      #-}+{-# LANGUAGE DeriveFunctor       #-}+{-# LANGUAGE DeriveTraversable   #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE GADTs #-}+module HaskellCI.YamlSyntax (+    Yaml (..),+    reann,+    ToYaml (..),+    prettyYaml,+    ) where++import Prelude ()+import Prelude.Compat++import Data.Bifunctor     (first)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Monoid        (Endo (..))+import Data.String        (IsString (..))++import qualified Data.Aeson              as Aeson+import qualified Data.List.NonEmpty      as NE+import qualified Data.Text               as T+import qualified Data.Text.Encoding      as TE+import qualified Data.Text.Lazy          as TL+import qualified Data.Text.Lazy.Encoding as TLE+import qualified Data.YAML               as YAML+++-- $setup+-- >>> :set -XOverloadedStrings++-------------------------------------------------------------------------------+-- Yaml syntx+-------------------------------------------------------------------------------++-- | This is not complete YAML document tree;+-- only as much as we need in @haskell-ci@.+data Yaml ann+    = YString ann String+    | YBool ann Bool+    | YList ann [Yaml ann]+    | YKeyValues ann [(ann, String, Yaml ann)]+    | YValue ann Aeson.Value  -- ^ inline JSON (for compactness)+  deriving (Eq, Show, Functor, Foldable, Traversable)++instance Monoid ann => IsString (Yaml ann) where+    fromString = YString mempty++-- | Re-annotate top-level term+reann :: (ann -> ann) -> Yaml ann -> Yaml ann+reann f (YString ann s)     = YString (f ann) s+reann f (YBool ann b)       = YBool (f ann) b+reann f (YList ann xs)      = YList (f ann) xs+reann f (YKeyValues ann xs) = YKeyValues (f ann) xs+reann f (YValue ann v)      = YValue (f ann) v++-------------------------------------------------------------------------------+-- Class+-------------------------------------------------------------------------------++class ToYaml a where+    toYaml :: a -> Yaml [String]++instance ann ~ [String] => ToYaml (Yaml ann) where+    toYaml = id++instance ToYaml Bool where+    toYaml = YBool []++instance ToYaml a => ToYaml [a] where+    toYaml = YList [] . map toYaml++instance ToYaml Aeson.Value where+    toYaml = YValue []++-------------------------------------------------------------------------------+-- Converting to string+-------------------------------------------------------------------------------++-- | Convert 'Yaml' to 'String'. @ann@ can be converted to comments.+--+-- == Examples+--+-- >>> let demo = putStr . prettyYaml lines+--+-- >>> demo "foo"+-- foo+--+-- >>> demo "foo: bar"+-- "foo: bar"+--+-- >>> demo $ YString "a comment" "foo"+-- # a comment+-- foo+--+-- >>> demo $ YBool "a comment" True+-- # a comment+-- true+--+-- >>> demo $ YList "" []+-- []+--+-- >>> demo $ YList "" ["foo", "foo: bar"]+-- - foo+-- - "foo: bar"+--+-- >>> demo $ YList "comment1" [YString "comment2" "foo", YString "comment3" "foo: bar"]+-- # comment1+-- #+-- # comment2+-- - foo+-- # comment3+-- - "foo: bar"+--+-- >>> demo $ YKeyValues "" []+-- {}+--+-- >>> demo $ YKeyValues "" [("", "foo", "bar"), ("", "help", "welcome")]+-- foo: bar+-- help: welcome+--+-- >>> let nested = YKeyValues "comment1" [("comment2", "foo", YString "comment3" "bar"), ("comment4", "help", YString "comment5" "welcome")]+-- >>> demo nested+-- # comment1+-- #+-- # comment2+-- #+-- # comment3+-- foo: bar+-- # comment4+-- #+-- # comment5+-- help: welcome+--+-- >>> demo $ YKeyValues "top" [("", "nested", nested)]+-- # top+-- nested:+--   # comment1+--   # +--   # comment2+--   # +--   # comment3+--   foo: bar+--   # comment4+--   # +--   # comment5+--   help: welcome+--+-- >>> demo $ YValue "inline json" $ Aeson.toJSON [True, False, True]+-- # inline json+-- [true,false,true]+--+-- >>> demo $ YKeyValues "" [ ("", "addons", YValue "" $ Aeson.toJSON $ [Just "foo", Just "bar", Nothing]) ]+-- addons: ["foo","bar",null]+--+-- >>> demo $ YString "" $ unlines ["foo","bar","baz"]+-- "foo\nbar\nbaz\n"+--+-- >>> let multiline = YString "" $ unlines ["foo", "bar", "baz"]+-- >>> demo $ YList "" [multiline, multiline]+-- - |+--   foo+--   bar+--   baz+-- - |+--   foo+--   bar+--   baz+--+-- >>> demo $ YKeyValues "" [("", "keyA", multiline), ("", "keyB", multiline)]+-- keyA: |+--   foo+--   bar+--   baz+-- keyB: |+--   foo+--   bar+--   baz+--+prettyYaml :: forall ann. (ann -> [String]) -> Yaml ann -> String+prettyYaml comment' = flatten . go where+    comment :: ann -> [String]+    comment = concatMap lines' . comment' where+        lines' "" = [""]+        lines' s  = lines s ++    go :: Yaml ann -> NonEmpty (Int, Line)+    go (YString ann s) = case literal s of+        Just ss -> pure (0, Line (comment ann) ss)+        Nothing -> pure (0, Line (comment ann) (shows s))++    go (YBool ann b) =+        pure (0, Line (comment ann) (showString $ if b then "true" else "false"))++    go (YValue ann v) =+        pure (0, Line (comment ann) (showString $ TL.unpack $ TLE.decodeUtf8 $ Aeson.encode v))++    go (YList ann [])     = pure (0, Line (comment ann) (showString "[]"))+    go (YList ann (x:xs)) = y :| (ys ++ yss)+      where+        y :: (Int, Line)+        ys :: [(Int, Line)]+        ~(y :| ys) = case goSub x of+            Right ((_, Line cs z) :| zs) ->+                (0, Line (comment ann +++ cs) $ showString "- " . z) :|+                fmap (first succ) zs++            Left (cs, ls) -> +                (0, Line (comment ann +++ cs) $ showString "- |") :|+                [ (1, Line [] (showString l))+                | l <- ls+                ]         ++        yss :: [(Int, Line)]+        yss = do+            e <- goSub <$> xs+            case e of +                Right ((_, Line cs z) :| zs) ->+                    (0, Line cs (showString "- " . z)) :+                    fmap (first succ) zs+                Left (cs, ls) -> +                    (0, Line cs $ showString "- |") :+                    [ (1, Line [] (showString l))+                    | l <- ls+                    ]  ++    go (YKeyValues ann [])     = pure (0, Line (comment ann) (showString "{}"))+    go (YKeyValues ann (x:xs)) = kv (comment ann) x <+> (xs >>= NE.toList . kv [])+      where+        kv :: [String] -> (ann, String, Yaml ann) -> NonEmpty (Int, Line)+        kv cs (ann', k, v) = case goSub v of+            -- single line+            Right ((_, Line cs' s) :| []) | isScalar v ->+                (0, Line (cs +++ comment ann' +++ cs') $+                    showString k . showString ": " . s) :|+                    []+            -- multiline non escaped+            Left (cs', ls) -> +                (0, Line (cs +++ comment ann' +++ cs') $+                    showString k . showString ": |") :|+                    [ (1, Line [] (showString l))+                    | l <- ls+                    ]+            -- multiline+            Right vs -> +                (0, Line (cs +++ comment ann') $ showString k . showChar ':') :|+                NE.toList (fmap (first succ) vs)++    -- which values can be on the same line with `:`+    isScalar YBool {}   = True+    isScalar YString {} = True+    isScalar YValue {}  = True+    isScalar _          = False++    goSub :: Yaml ann -> Either ([String], [String]) (NonEmpty (Int, Line))+    goSub (YString ann s) = case literal s of+        Just ss -> Right (pure (0, Line (comment ann) ss))+        Nothing -> case multiline s of+            Just ll -> Left (comment ann, ll)+            Nothing -> Right (pure (0, Line (comment ann) (shows s)))+    goSub y = Right (go y)+        +    -- given "foo" can it be encode without quotes:+    -- +    --    foo+    --+    literal :: String -> Maybe ShowS+    literal s = case YAML.decodeStrict bs of+        Right [t'] | t == t' -> Just (showString s)+        _                    -> Nothing+      where+        t  = T.pack s+        bs = TE.encodeUtf8 t+        +    -- when not top level, we can encode "foo\nbar\n" as+    --+    --     - |+    --       foo+    --       bar+    --+    -- Note: the input have to end with @\n@ for this to be triggered.+    --+    multiline :: String -> Maybe [String]+    multiline s = case YAML.decodeStrict bs of+        Right [[t']] | t == t' -> Just ls+        _                      -> Nothing+      where+        ls = lines s+        t  = T.pack s++        ys = "- |\n" ++ concatMap (\l -> "  " ++ l ++ "\n") ls+        yt  = T.pack ys+        bs = TE.encodeUtf8 yt++    -- when concatenating comment blocks, we add an empty line in between+    (+++) :: [String] -> [String] -> [String]+    [] +++ xs = xs+    xs +++ [] = xs+    xs +++ ys = xs ++ [""] ++ ys++    -- We can concatenate a list to a 'NonEmpty' list, the result is 'NonEmpty'.+    (<+>) :: NonEmpty a -> [a] -> NonEmpty a+    (x :| xs) <+> ys = x :| (xs ++ ys)++    flatten :: NonEmpty (Int, Line) -> String+    flatten xs = appEndo (foldMap f xs) "" where+        f (lvl, Line cs s) =+            foldMap showComment cs <> g s+          where+            showComment "" = g (showString "#")+            showComment c  = g (showString "# " . showString c)+            g x = Endo (showString lvl' . x . showChar '\n')+            lvl' = replicate (lvl * 2) ' '++-- a 'Line' is comments before in and actual text after!+data Line = Line [String] ShowS
test/Tests.hs view
@@ -1,28 +1,24 @@ {-# LANGUAGE ViewPatterns #-} module Main (main) where -import HaskellCI hiding (main)+import HaskellCI             hiding (main)+import HaskellCI.Diagnostics (runDiagnosticsT) -import Control.Applicative ((<$>), (<*>))-import Control.Exception (ErrorCall(..), throwIO, try)-import Control.Monad.Trans.Maybe-import Control.Monad.Trans.Writer-import Data.Algorithm.Diff (Diff (..), getGroupedDiff)-import Data.IORef-import Data.List (isPrefixOf, stripPrefix)-import Data.Maybe (mapMaybe)-import Data.Monoid (mconcat)-import System.Directory (doesFileExist, removeFile, setCurrentDirectory)-import System.Exit (ExitCode(..), exitFailure)-import System.FilePath (addExtension, (</>))-import System.IO (hPutStrLn, stderr)-import Test.Tasty (TestName, TestTree, defaultMain, testGroup)+import Control.Applicative        ((<$>), (<*>))+import Control.Exception          (ErrorCall (..), throwIO)+import Data.Algorithm.Diff        (Diff (..), getGroupedDiff)+import Data.List                  (stripPrefix)+import Data.Maybe                 (mapMaybe)+import Data.Monoid                (mconcat)+import System.Directory           (doesFileExist, setCurrentDirectory)+import System.FilePath            (addExtension)+import Test.Tasty                 (TestName, TestTree, defaultMain, testGroup) import Test.Tasty.Golden.Advanced (goldenTest)-import Text.Read (readMaybe)+import Text.Read                  (readMaybe) -import qualified Data.ByteString as BS+import qualified Data.ByteString       as BS import qualified Data.ByteString.Char8 as BS8-import qualified System.Console.ANSI as ANSI+import qualified System.Console.ANSI   as ANSI  main :: IO () main = do@@ -32,6 +28,7 @@         , fixtureGoldenTest "cabal.project.empty-line"         , fixtureGoldenTest "cabal.project.fail-versions"         , fixtureGoldenTest "cabal.project.messy"+        , fixtureGoldenTest "cabal.project.travis-patch"         , testGroup "copy-fields"             [ fixtureGoldenTest "cabal.project.copy-fields.all"             , fixtureGoldenTest "cabal.project.copy-fields.some"@@ -57,7 +54,7 @@ fixtureGoldenTest fp = cabalGoldenTest fp outputRef errorRef $ do     (argv, opts) <- makeTravisFlags     let genConfig = travisFromConfigFile argv opts fp-    execWriterT (runMaybeT genConfig)+    runDiagnosticsT genConfig   where     outputRef = addExtension fp "travis.yml"     errorRef = addExtension fp "stderr"@@ -81,11 +78,16 @@     (path, opts) <- parseTravis argv     return (opts, path) +data Result+    = Success [String] [String]+    | Failure [String]+  deriving Eq+ cabalGoldenTest     :: TestName     -> FilePath     -> FilePath-    -> IO MakeTravisOutput+    -> IO (Maybe [String], [String])     -> TestTree cabalGoldenTest name outRef errRef act = goldenTest name readGolden act' cmp upd   where@@ -93,8 +95,8 @@     readData fp = lines . BS8.unpack <$> BS.readFile fp      act' = flip fmap act $ \r -> case r of-        Success ws x -> Success (map formatDiagnostic ws) x-        Failure errs -> Failure (map formatDiagnostic errs)+        (Nothing, diags) -> Failure diags+        (Just x, diags)  -> Success diags x      readGolden = do         refExists <- doesFileExist outRef