module Debian.Package.Build.Monad
( Trace, runTrace, traceCommand, traceOut, putLog
, bracketTrace, bracketTrace_
, BaseDir
, askBaseDir, askBuildDir
, BuildDir, buildDirRelative, buildDirAbsolute
, Config, defaultConfig, buildDir, debianDirName, sourceExcludes
, Build, liftTrace, unBuild, runBuild, askConfig
, bracketBuild, bracketBuild_
) where
import System.FilePath ((</>))
import System.IO (hPutStrLn, hFlush, stderr, stdout)
import Control.Applicative ((<$>))
import Control.Monad (when)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Reader (ReaderT, ask, runReaderT)
import Control.Exception (bracket)
readerBracket :: Monad m
=> (m a -> (a -> m b) -> (a -> m c) -> m c)
-> ReaderT r m a
-> (a -> ReaderT r m b)
-> (a -> ReaderT r m c)
-> ReaderT r m c
readerBracket brkt open close body = do
r <- ask
lift $ brkt
(runReaderT open r)
(\a -> runReaderT (close a) r)
(\a -> runReaderT (body a) r)
toBracket_ :: Monad m
=> (m a -> (a -> m b) -> (a -> m c) -> m c)
-> m a
-> m b
-> m c
-> m c
toBracket_ brkt start end body =
brkt start (const end) (const body)
type Trace = ReaderT Bool IO
runTrace :: Trace a -> Bool -> IO a
runTrace = runReaderT
traceIO :: IO () -> Trace ()
traceIO printIO = do
t <- ask
when t $ lift printIO
bracketTrace :: Trace a -> (a -> Trace b) -> (a -> Trace c) -> Trace c
bracketTrace = readerBracket bracket
bracketTrace_ :: Trace a -> Trace b -> Trace c -> Trace c
bracketTrace_ = toBracket_ bracketTrace
tprint :: Char -> String -> IO ()
tprint pc s = do
let fh = stderr
hPutStrLn fh $ pc : " " ++ s
hFlush fh
traceCommand :: String -> Trace ()
traceCommand = traceIO . tprint '+'
traceOut :: String -> Trace ()
traceOut = traceIO . tprint '>'
putLog :: String -> Trace ()
putLog s = traceIO $ do
let fh = stdout
hPutStrLn fh s
hFlush fh
type BaseDir = FilePath
newtype BuildDir = BuildDir (Either FilePath FilePath)
buildDirRelative :: FilePath -> BuildDir
buildDirRelative = BuildDir . Left
buildDirAbsolute :: FilePath -> BuildDir
buildDirAbsolute = BuildDir . Right
unBuildDir :: FilePath -> BuildDir -> FilePath
unBuildDir base (BuildDir b) = either (base </>) id b
instance Show BuildDir where
show = d where
d (BuildDir (Left p)) = "Relative " ++ p
d (BuildDir (Right p)) = "Absolute " ++ p
data Config =
Config
{ buildDir :: BuildDir
, debianDirName :: FilePath
, sourceExcludes :: [FilePath]
} deriving Show
defaultConfig :: (Config, Bool)
defaultConfig = (Config
{ buildDir = buildDirRelative ".debian-build"
, debianDirName = "debian"
, sourceExcludes = [".git", ".hg"]
},
True)
type Build = ReaderT BaseDir (ReaderT Config Trace)
liftTrace :: Trace a -> Build a
liftTrace = lift . lift
unBuild :: Build a -> BaseDir -> Config -> Trace a
unBuild b bd = runReaderT $ runReaderT b bd
runBuild :: Build a -> BaseDir -> Config -> Bool -> IO a
runBuild b bd = runTrace . unBuild b bd
bracketBuild :: Build a -> (a -> Build b) -> (a -> Build c) -> Build c
bracketBuild = readerBracket $ readerBracket bracketTrace
bracketBuild_ :: Build a -> Build b -> Build c -> Build c
bracketBuild_ = toBracket_ bracketBuild
askBaseDir :: Build FilePath
askBaseDir = ask
askConfig :: Build Config
askConfig = lift ask
askBuildDir :: Build FilePath
askBuildDir = do
bd <- buildDir <$> askConfig
(`unBuildDir` bd) <$> askBaseDir