{-| Defines the entry point of the @feed-gipeda@ executable and the command line parsing associated with that. -} import Control.Applicative import Control.Logging as Logging import Control.Monad (join) import Data.Functor import Data.List (elemIndex) import FeedGipeda import Options.Applicative import System.Directory (getAppUserDataDirectory) import System.FilePath (()) import Text.Read (readMaybe) endpoint :: ReadM Endpoint endpoint = do s <- str case elemIndex ':' s of Nothing -> readerError "Expected a colon separator" Just idx -> do let (host, port') = splitAt idx s case readMaybe (drop 1 port') of Just port -> return (Endpoint host port) Nothing -> readerError "Port was not integral" paths :: FilePath -> Parser Paths paths defaultConfig = Paths <$> option str (long "config" <> value defaultConfig <> metavar "FILEPATH" <> help ("Path to the YAML file containing a list of watched repositories. Will be watched for changes. Defaults to " ++ defaultConfig ++ ".")) <*> option str (long "gipeda" <> value "gipeda" <> metavar "FILEPATH" <> help "Custom path to the gipeda executable") cmd :: Parser Command cmd = flag' Check (long "check" <> help "Verify that the given config file is well-formed and exit") <|> Build <$> option (WatchForChanges . fromIntegral <$> auto) (long "watch" <> metavar "SECONDS" <> value Once <> help "Don't quit when done, watch the config file for changes and refetch watched repositories every SECONDS seconds and benchmark new commits.") <*> option (fromIntegral <$> auto) (long "timeout" <> metavar "SECONDS" <> value (fromIntegral (30*60)) <> help "Timeout for a benchmark run. A slave is canceled if it needs more than SECONDS seconds. Defaults to 30 minutes.") deployment :: Parser Deployment deployment = option (Deploy <$> str) (long "deploy-to" <> metavar "SSH_PATH" <> value NoDeployment <> help "ssh or local path under which to deploy site/ folders with rsync") processRole :: Parser ProcessRole processRole = impl <$> optional (option endpoint (long "master" <> metavar "ENDPOINT" <> help "Start in master mode, distributing work items. Identified via the given TCP endpoint (ipadress:portnumber).")) <*> optional (option endpoint (long "slave" <> metavar "ENDPOINT" <> help "Start in slave mode, requesting work items from a master node. Identified via the given TCP endpoint (ipadress:portnumber).")) where impl Nothing Nothing = Both (Endpoint "localhost" 1337) (Endpoint "localhost" 1338) impl (Just ep) Nothing = Master ep impl Nothing (Just ep) = Slave ep impl (Just mep) (Just sep) = Both mep sep verbosity :: Parser Verbosity verbosity = flag NotVerbose Verbose (long "verbose" <> short 'v' <> help "Show log messages intended for debugging") parser :: IO (Parser (IO ())) parser = do defaultConfig <- getAppUserDataDirectory ("feed-gipeda" "feed-gipeda.yaml") return $ FeedGipeda.feedGipeda <$> paths defaultConfig <*> cmd <*> deployment <*> processRole <*> verbosity main :: IO () main = Logging.withStdoutLogging $ do p <- parser join $ execParser $ info (helper <*> p) $ fullDesc <> header "feed-gipeda - watch git repositories and feed benchmark results to gipeda" -- <> progDesc "" -- TODO