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 +8/−0
- LICENSE +668/−25
- fixtures/cabal.haskell-ci +55/−1
- fixtures/cabal.project.copy-fields.all.stderr +1/−1
- fixtures/cabal.project.copy-fields.all.travis.yml +153/−115
- fixtures/cabal.project.copy-fields.none.stderr +1/−1
- fixtures/cabal.project.copy-fields.none.travis.yml +141/−105
- fixtures/cabal.project.copy-fields.some.stderr +1/−1
- fixtures/cabal.project.copy-fields.some.travis.yml +147/−111
- fixtures/cabal.project.empty-line.stderr +1/−1
- fixtures/cabal.project.empty-line.travis.yml +160/−132
- fixtures/cabal.project.fail-versions.stderr +3/−3
- fixtures/cabal.project.haskell-ci +2/−0
- fixtures/cabal.project.messy.stderr +1/−1
- fixtures/cabal.project.messy.travis.yml +154/−126
- fixtures/cabal.project.travis-patch +1/−0
- fixtures/cabal.project.travis-patch.patch +13/−0
- fixtures/cabal.project.travis-patch.stderr +1/−0
- fixtures/cabal.project.travis-patch.travis.yml +177/−0
- fixtures/haskell-ci.cabal +43/−15
- fixtures/haskell-ci.cabal.stderr +2/−2
- fixtures/haskell-ci.cabal.travis.yml +138/−114
- haskell-ci.cabal +43/−15
- src/Distribution/Fields/Pretty.hs +0/−134
- src/HaskellCI.hs +353/−1033
- src/HaskellCI/Cli.hs +41/−18
- src/HaskellCI/Compiler.hs +165/−0
- src/HaskellCI/Config.hs +65/−41
- src/HaskellCI/Config/ConstraintSet.hs +9/−5
- src/HaskellCI/Config/CopyFields.hs +3/−1
- src/HaskellCI/Config/Doctest.hs +13/−9
- src/HaskellCI/Config/Dump.hs +14/−5
- src/HaskellCI/Config/Folds.hs +3/−8
- src/HaskellCI/Config/HLint.hs +4/−5
- src/HaskellCI/Config/Installed.hs +4/−5
- src/HaskellCI/Config/Jobs.hs +3/−3
- src/HaskellCI/Config/Ubuntu.hs +25/−0
- src/HaskellCI/Diagnostics.hs +45/−0
- src/HaskellCI/Extras.hs +0/−34
- src/HaskellCI/GHC.hs +0/−36
- src/HaskellCI/Glob.hs +11/−11
- src/HaskellCI/Jobs.hs +67/−0
- src/HaskellCI/List.hs +34/−0
- src/HaskellCI/MakeTravisOutput.hs +0/−212
- src/HaskellCI/MonadErr.hs +12/−0
- src/HaskellCI/Newtypes.hs +15/−54
- src/HaskellCI/Optimization.hs +3/−3
- src/HaskellCI/OptionsGrammar.hs +4/−2
- src/HaskellCI/OptparseGrammar.hs +14/−9
- src/HaskellCI/Package.hs +6/−3
- src/HaskellCI/ParsecError.hs +7/−8
- src/HaskellCI/ParsecUtils.hs +11/−11
- src/HaskellCI/Prelude.hs +88/−0
- src/HaskellCI/Project.hs +31/−27
- src/HaskellCI/Sh.hs +148/−0
- src/HaskellCI/ShVersionRange.hs +235/−0
- src/HaskellCI/TestedWith.hs +26/−30
- src/HaskellCI/Tools.hs +112/−0
- src/HaskellCI/Travis.hs +699/−0
- src/HaskellCI/Travis/Yaml.hs +232/−0
- src/HaskellCI/Version.hs +0/−42
- src/HaskellCI/YamlSyntax.hs +317/−0
- test/Tests.hs +24/−22
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