module WatchIt
( defaultMain
, watchIt
) where
import WatchIt.Options
import WatchIt.Types
import Control.Concurrent (threadDelay)
import Control.Monad (forever, void, when)
import Data.Pool (Pool (..), createPool, tryWithResource)
import Data.Streaming.Process (Inherited (..), shell, streamingProcess,
waitForStreamingProcess)
import qualified Data.Text as Text
import qualified Filesystem.Path.CurrentOS as FS
import Options.Applicative (execParser)
import System.FSNotify (eventPath, watchDir, watchTree,
withManager)
defaultMain :: IO ()
defaultMain = do
options <- execParser infoOptions
watchIt $ parseConfig options
parseConfig :: Options -> Config
parseConfig options = Config
{ configPath = withDef configPath optionsPath FS.decodeString
, configFilter = withDef configFilter optionsExt
(flip FS.hasExtension . Text.pack)
, configAction = withDef configAction optionsCmd (const . run)
, configForce = withDef configForce optionsForce id
, configNumJobs = withDef configNumJobs optionsNumJobs id
, configRecur = withDef configRecur optionsNotRec not
}
where
withDef conf opt f = maybe (conf defaultConfig) f (opt options)
watchIt :: Config -> IO ()
watchIt config = do
let path = configPath config
let filterEvent = configFilter config . eventPath
let numJobs = configNumJobs config
pool <- createWorkerPool numJobs
let action = configAction config
let handleEvent = withPool pool action . eventPath
let forced = configForce config
let watch = if configRecur config then watchTree else watchDir
let longDelay = 12 * 3600 * 10000
putStrLn "watchit started..."
withManager $ \man -> do
when forced $ action FS.empty
void $ watch man path
filterEvent
handleEvent
forever $ threadDelay longDelay
createWorkerPool :: Int -> IO (Pool ())
createWorkerPool stripes =
createPool
(return ())
(const $ return ())
stripes timeLeftOpen numPerStripe
where
timeLeftOpen = 1
numPerStripe = 1
withPool :: Pool a -> (FS.FilePath -> IO ()) -> FS.FilePath -> IO ()
withPool pool f file =
void $ tryWithResource pool $ const $ f file
run :: String -> IO ()
run cmd = do
putStrLn $ replicate 72 '-'
(Inherited, Inherited, Inherited, handle) <-
streamingProcess (shell cmd)
waitForStreamingProcess handle >>= print