{-# LANGUAGE RecordWildCards #-} import Data.Set (fromList) import Stackage.Build (build, defaultBuildSettings) import Stackage.BuildPlan (readBuildPlan, writeBuildPlan) import Stackage.CheckPlan (checkPlan) import Stackage.GhcPkg (getGhcVersion) import Stackage.Init (stackageInit) import Stackage.Select (defaultSelectSettings, select) import Stackage.Tarballs (makeTarballs) import Stackage.Test (runTestSuites) import Stackage.Types import Stackage.Util (allowPermissive) import System.Environment (getArgs, getProgName) import System.IO (hFlush, stdout) data SelectArgs = SelectArgs { excluded :: [String] , noPlatform :: Bool , ignoreUpgradeable :: Bool , onlyPermissive :: Bool , allowed :: [String] , buildPlanDest :: FilePath , globalDB :: Bool } parseSelectArgs :: [String] -> IO SelectArgs parseSelectArgs = loop SelectArgs { excluded = [] , noPlatform = True , ignoreUpgradeable = False , onlyPermissive = False , allowed = [] , buildPlanDest = defaultBuildPlan , globalDB = False } where loop x [] = return x loop x ("--exclude":y:rest) = loop x { excluded = y : excluded x } rest loop x ("--no-platform":rest) = loop x { noPlatform = True } rest loop x ("--platform":rest) = loop x { noPlatform = False } rest loop x ("--ignore-upgradeable":rest) = loop x { ignoreUpgradeable = True } rest loop x ("--only-permissive":rest) = loop x { onlyPermissive = True } rest loop x ("--allow":y:rest) = loop x { allowed = y : allowed x } rest loop x ("--build-plan":y:rest) = loop x { buildPlanDest = y } rest loop x ("--use-global-db":rest) = loop x { globalDB = True } rest loop _ (y:_) = error $ "Did not understand argument: " ++ y data BuildArgs = BuildArgs { sandbox :: String , buildPlanSrc :: FilePath , extraArgs' :: [String] -> [String] , noDocs :: Bool , buildCores :: Maybe Int , testThreads :: Maybe Int } parseBuildArgs :: GhcMajorVersion -> [String] -> IO BuildArgs parseBuildArgs version = loop BuildArgs { sandbox = sandboxRoot $ defaultBuildSettings Nothing version , buildPlanSrc = defaultBuildPlan , extraArgs' = id , noDocs = False , buildCores = Nothing , testThreads = Nothing } where loop x [] = return x loop x ("--sandbox":y:rest) = loop x { sandbox = y } rest loop x ("--build-plan":y:rest) = loop x { buildPlanSrc = y } rest loop x ("--arg":y:rest) = loop x { extraArgs' = extraArgs' x . (y:) } rest loop x ("--no-docs":rest) = loop x { noDocs = True } rest loop x ("-j":y:rest) = loop x { buildCores = Just $ read y } rest loop x ("--test-threads":y:rest) = loop x { testThreads = Just $ read y } rest loop _ (y:_) = error $ "Did not understand argument: " ++ y defaultBuildPlan :: FilePath defaultBuildPlan = "build-plan.txt" withBuildSettings :: [String] -> (BuildSettings -> BuildPlan -> IO a) -> IO a withBuildSettings args f = do version <- getGhcVersion BuildArgs {..} <- parseBuildArgs version args bp <- readBuildPlan buildPlanSrc let bs = defaultBuildSettings buildCores version modTestThreads settings' = case testThreads of Nothing -> settings' Just t -> settings' { testWorkerThreads = t } settings = modTestThreads bs { sandboxRoot = sandbox , extraArgs = extraArgs' . extraArgs bs , buildDocs = not noDocs } f settings bp main :: IO () main = do args <- getArgs case args of "select":rest -> do SelectArgs {..} <- parseSelectArgs rest ghcVersion <- getGhcVersion bp <- select (defaultSelectSettings ghcVersion $ not noPlatform) { excludedPackages = fromList $ map PackageName excluded , requireHaskellPlatform = not noPlatform , ignoreUpgradeableCore = ignoreUpgradeable , allowedPackage = if onlyPermissive then allowPermissive allowed else const $ Right () , useGlobalDatabase = globalDB } writeBuildPlan buildPlanDest bp ("check":rest) -> withBuildSettings rest checkPlan ("build":rest) -> withBuildSettings rest build ("test":rest) -> withBuildSettings rest runTestSuites ("tarballs":rest) -> withBuildSettings rest $ const makeTarballs ["init"] -> do putStrLn "Note: init isn't really ready for prime time use." putStrLn "Using it may make it impossible to build stackage." putStr "Are you sure you want continue (y/n)? " hFlush stdout x <- getLine case x of c:_ | c `elem` "yY" -> stackageInit _ -> putStrLn "Probably a good decision, exiting." ["update"] -> stackageInit >> error "FIXME update" _ -> do pn <- getProgName putStrLn $ "Usage: " ++ pn ++ " " putStrLn "Available commands:" --putStrLn " update Download updated Stackage databases. Automatically calls init." --putStrLn " init Initialize your cabal file to use Stackage" putStrLn " uploads" putStrLn " select [--no-clean] [--no-platform] [--exclude package...] [--only-permissive] [--allow package] [--build-plan file]" putStrLn " check [--build-plan file] [--sandbox rootdir] [--arg cabal-arg]" putStrLn " build [--build-plan file] [--sandbox rootdir] [--arg cabal-arg]" putStrLn " test [--build-plan file] [--sandbox rootdir] [--arg cabal-arg] [--no-docs]"