{-#LANGUAGE RecordWildCards #-}
module Main where
import System.Environment (getArgs)
import System.Console.GetOpt
import System.Posix.Daemon
import Data.List
import Control.Monad
import Filesystem.Path.CurrentOS hiding (concat, null)
import Data.Text as T hiding (foldl, concat, intercalate, null)
import Prelude hiding (FilePath)
import SOS
main :: IO ()
main = do
args <- getArgs
case getOpt Permute options args of
( [], _, []) -> error $ usageInfo header options
( opts, _, []) -> startWithOpts $ foldl (flip id) defaultOptions opts
( _, _, msgs) -> error $ concat msgs ++ usageInfo header options
data Options = Options { optShowVersion :: Bool
, optCommands :: [String]
, optPatterns :: [String]
, optDirectory :: FilePath
, optIsDaemon :: Bool
, optDaemonCmd :: String
} deriving (Show, Eq)
defaultOptions :: Options
defaultOptions = Options { optShowVersion = False
, optCommands = []
, optPatterns = []
, optDirectory = fromText $ T.pack "."
, optIsDaemon = False
, optDaemonCmd = "start"
}
options :: [OptDescr (Options -> Options)]
options = [ Option "v" ["version"]
(NoArg (\opts -> opts { optShowVersion = True }))
"Show version info."
, Option "c" ["command"]
(ReqArg (\c opts -> opts { optCommands = optCommands opts ++ [c] }) "command")
"Add command to run on file event."
, Option "p" ["pattern"]
(ReqArg (\e opts -> opts { optPatterns = optPatterns opts ++ [e] }) "pattern")
"Add pattern to match on file path."
, Option "d" ["directory"]
(ReqArg (\d opts -> opts { optDirectory = decodeString d }) "directory")
"Set directory to watch for changes (default is ./)."
, Option "b" ["daemon"]
(ReqArg (\s opts -> opts { optIsDaemon = True, optDaemonCmd = s }) "start|stop")
"Attempt to run in the background as a daemon. When a previous daemon is running from your working directory this option will kill that process."
]
header :: String
header = "Usage: sos [vb] -c command -p pattern"
version :: String
version = "\nSteel Overseer 1.0.0.0\n"
startWithOpts :: Options -> IO ()
startWithOpts opts = do
let Options{..} = opts
haveOptions = not (null optPatterns)
patternsValid = and $ fmap (not . null) optPatterns
daemonValid = optDaemonCmd == "start" || optDaemonCmd == "stop"
when optShowVersion $ putStrLn version
unless patternsValid $ error "One or more patterns are empty."
unless daemonValid $ error "The argument to -b,--daemon must be one of start or stop."
didKill <- if optIsDaemon && optDaemonCmd == "stop"
then do shouldKillPrev <- isRunning pIdFile
if shouldKillPrev
then do putStrLn "Killing previous steeloverseer daemon..."
killAndWait pIdFile
putStrLn "Done."
else putStrLn "There is no previous daemon to kill."
return shouldKillPrev
else return False
let runSteelOverseer = steelOverseer optDirectory optCommands optPatterns optIsDaemon
when (haveOptions && patternsValid && daemonValid) $
if not optIsDaemon
then runSteelOverseer
else unless didKill $ do
putStrLn "Running in the background as a daemon, logging output to sos.log."
runDetached (Just pIdFile) (ToFile logFile) runSteelOverseer