packages feed

ddc-war-0.2.1.1: DDC/War/Driver/Base.hs

module DDC.War.Driver.Base
        ( Job           (..)
        , JobId         (..)
        , Chain         (..)
        , Product       (..)
        , Result        (..)
        , prettyResult
        , Spec          (..))
where
import BuildBox.Pretty
import BuildBox
import Data.Maybe
import Data.List

-- | A printable job identifier.
data JobId
        = JobId
        { jobIdName             :: String 
        , jobIdWay              :: String }
        deriving Show



-- | A single job to run.
--   The exact specification is defined by the client.
data Job
        =  forall spec result. Spec spec result
        => Job JobId String spec (Build result)

instance Pretty Job where
 ppr (Job jobId actionName spec _)
  = text "Job" <+> text (show jobId) <+> text actionName <+> text (show spec)


-- | A chain of jobs to run one after another.
--   Jobs later in the list are dependent on earlier ones, so if a job fails
--   then we skip the rest.
data Chain
        = Chain [Job]

instance Pretty Chain where
 ppr (Chain jobs)
  =   text "Chain"
  <+> ppr jobs


-- | The product that we got when running a job.
--   This is the information that the interactive interface needs to decide
--   how to proceed. 
data Product
        = ProductStatus 
        { productStatusMsg      :: Doc
        , productStatusSuccess  :: Bool }

        | ProductDiff   
        { productDiffRef        :: FilePath
        , productDiffOut        :: FilePath
        , productDiffDiff       :: FilePath }


-- | Description of a job and the product we got from running it.
data Result
        = Result 
        { resultChainIx         :: Int
        , resultJobIx           :: Int
        , resultJobId           :: JobId
        , resultJobActionName   :: String
        , resultProduct         :: Product }


prettyResult :: Int -> String -> Int -> Result -> Doc
prettyResult chainsTotal prefix padWidth result
        | Result chainIx jobIx jobId actionName product' <- result
        , JobId  testName wayName                       <- jobId
        = let   status
                 = case product' of
                        ProductStatus s _ -> s
                        ProductDiff{}     -> text "diff"

                testName'
                 = fromMaybe testName (stripPrefix prefix testName)

          in   parens (padR  (length $ show chainsTotal)
                             (ppr chainIx)
                   <>  text "."
                   <>        (ppr jobIx))
           <+> padL padWidth (text testName') 
           <+> padL 5        (text wayName)
           <+> padL 8        (text actionName)
           <+> status

        where 

-- Spec -----------------------------------------------------------------------
-- | Class of Job specifications.
class (Show spec, Pretty result)
        => Spec spec result | spec -> result where

 -- | Get a short name to describe the job that this spec describes, 
 --   eg "compile" or "run"
 specActionName    :: spec -> String

 -- | Wrap a specification into a job.
 jobOfSpec         :: JobId -> spec -> Job
 jobOfSpec jobId s = Job jobId (specActionName s) s (buildFromSpec s)

 -- | Create a builder for this job specification.
 buildFromSpec    :: spec -> Build result

 -- | Make the job product from its result.
 --   This cuts away information that the controller doesn't care about.
 productOfResult  :: spec -> result -> Product