doc-review-0.7: src/Config/Command/Run.hs
module Config.Command.Run
( Config(..)
, mkCfg
, opts
)
where
import State.Types ( State )
import Network.URI ( parseRelativeReference, URI )
import Config.GetOpt ( MkCfg, Opts, noArgs, Err, contentDirDesc )
import Config.Store ( storeOptDescr, ParseStore )
import System.Console.GetOpt
import qualified State.Mem ( new )
-- |The configurable settings for an instance of the comments server
data Config =
Config
{ cfgStore :: !(IO State) -- ^How state is stored
, cfgPort :: !Int -- ^What TCP port to listen on
, cfgLogDir :: !FilePath -- ^Where to put the log files
, cfgHostName :: !String -- ^The hostname used by Snap
, cfgContentDir :: !FilePath -- ^Where to look for the
-- documents to index and content
-- to serve. This is mapped to the
-- root of the Web server.
, cfgScanOnStart :: !Bool -- ^Whether to scan for updated
-- ids in the content directory
, cfgStaticDir :: !(Maybe FilePath) -- ^Other static content to serve
, cfgDefaultPage :: !(Maybe URI)
-- ^Where to redirect to if no URL is requested
, cfgRunAs :: !(Maybe String)
, cfgLogTo :: !(Maybe FilePath)
}
mkCfg :: MkCfg Config
mkCfg =
noArgs $
Config
{ cfgStore = State.Mem.new
, cfgPort = 3000
, cfgLogDir = "."
, cfgHostName = "localhost"
, cfgContentDir = "."
, cfgStaticDir = Nothing
, cfgScanOnStart = True
, cfgDefaultPage = Nothing
, cfgRunAs = Nothing
, cfgLogTo = Nothing
}
-- All of the defined options
opts :: [ParseStore (IO State)] -> Opts Config
opts stores =
[ storeOptDescr stores $ \st cfg -> cfg { cfgStore = st }
, Option "" ["no-scan"] (NoArg (soptScan False))
"Do not update the chapter database at startup"
, Option "" ["scan"] (NoArg (soptScan True))
"Scan for updated content at server startup (default)"
, Option "" ["static-dir"] (ReqArg soptStaticDir "DIR")
"Serve static files from this directory"
, contentDirDesc soptContentDir
, Option "p" ["port"] (ReqArg soptPort "PORT")
"Listen on this port"
, Option "" ["log-dir"] (ReqArg soptLogDir "DIR")
"Store the error and access logs in this directory"
, Option "" ["host"] (ReqArg soptHost "HOSTNAME")
"Use this as the Web server host (not for binding address)"
, Option "" ["default-page"] (ReqArg soptDefaultPage "URL")
"Where the server should redirect when the URL / is requested"
, Option "" ["run-as"] (ReqArg soptRunAs "USERNAME")
"If started as root, attempt to drop privileges by \n\
\changing to this user once the port is bound"
, Option "" ["log-to"] (ReqArg soptLogTo "LOGFILE")
"Write a binary log file as a backup in case of primary\n\
\store failure"
]
type Opt = Err (Config -> Config)
-- Turn an option string into something that updates the configuration
soptPort, soptLogDir, soptHost, soptContentDir, soptStaticDir,
soptDefaultPage, soptRunAs, soptLogTo :: String -> Opt
soptLogDir str = return $ \cfg -> cfg { cfgLogDir = str }
soptHost str = return $ \cfg -> cfg { cfgHostName = str }
soptContentDir str = return $ \cfg -> cfg { cfgContentDir = str }
soptStaticDir str = return $ \cfg -> cfg { cfgStaticDir = Just str }
soptRunAs str = return $ \cfg -> cfg { cfgRunAs = Just str }
soptLogTo str = return $ \cfg -> cfg { cfgLogTo = Just str }
soptPort str =
case reads str of
[(x, [])] -> return $ \cfg -> cfg { cfgPort = x }
_ -> fail $ "Bad port: " ++ show str
soptDefaultPage str =
case parseRelativeReference str of
Nothing -> fail $ "Not a valid URI: " ++ show str
Just u -> return $ \cfg ->
cfg { cfgDefaultPage = Just u }
soptScan :: Bool -> Opt
soptScan st = return $ \cfg -> cfg { cfgScanOnStart = st }