1
1
mirror of https://github.com/srid/ema.git synced 2024-11-25 20:12:20 +03:00

FileSystem.mount: group multiple actions (#31)

* Group initial actions

* refactor
This commit is contained in:
Sridhar Ratnakumar 2021-05-17 18:26:31 -04:00 committed by GitHub
parent ff7692e944
commit 2c33a83733
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -25,6 +25,7 @@ import Control.Monad.Logger
import Data.Default (Default (..)) import Data.Default (Default (..))
import Data.LVar (LVar) import Data.LVar (LVar)
import qualified Data.LVar as LVar import qualified Data.LVar as LVar
import qualified Data.Map.Strict as Map
import System.Directory (canonicalizePath) import System.Directory (canonicalizePath)
import System.FSNotify import System.FSNotify
( ActionPredicate, ( ActionPredicate,
@ -48,7 +49,8 @@ mountOnLVar ::
MonadUnliftIO m, MonadUnliftIO m,
MonadLogger m, MonadLogger m,
Default model, Default model,
Show b Show b,
Ord b
) => ) =>
-- | The directory to mount. -- | The directory to mount.
FilePath -> FilePath ->
@ -64,18 +66,23 @@ mountOnLVar ::
-- to reflect the given `FileAction`. -- to reflect the given `FileAction`.
-- --
-- If the action throws an exception, it will be logged and ignored. -- If the action throws an exception, it will be logged and ignored.
((b, FilePath) -> FileAction -> m (model -> model)) -> ([(b, [FilePath])] -> FileAction -> m (model -> model)) ->
m () m ()
mountOnLVar folder pats var toAction' = do mountOnLVar folder pats var toAction' = do
let toAction x = interceptExceptions id . toAction' x let toAction x = interceptExceptions id . toAction' x
log LevelInfo $ "Mounting path " <> toText folder <> " (filter: " <> show pats <> ") onto LVar" log LevelInfo $ "Mounting path " <> toText folder <> " (filter: " <> show pats <> ") onto LVar"
LVar.set var =<< do LVar.set var =<< do
fs <- filesMatchingWithTag folder pats fs <- filesMatchingWithTag folder pats
initialActions <- traverse (`toAction` Update) fs initialAction <- toAction fs Update
pure $ foldl' (flip ($)) def initialActions pure $ initialAction def
onChange folder $ \fp change -> do onChange folder $ \fp change -> do
whenJust (getTag pats fp) $ \tag -> whenJust (getTag pats fp) $ \tag -> do
LVar.modify var =<< toAction (tag, fp) change -- TODO: We should probably debounce and group frequently-firing events
-- here, but do so such that `change` is the same for the events in the
-- group.
let groupOfOne = one (tag, one fp)
action <- toAction groupOfOne change
LVar.modify var action
where where
-- Log and ignore exceptions -- Log and ignore exceptions
interceptExceptions :: (MonadIO m, MonadUnliftIO m, MonadLogger m) => a -> m a -> m a interceptExceptions :: (MonadIO m, MonadUnliftIO m, MonadLogger m) => a -> m a -> m a
@ -96,10 +103,14 @@ filesMatching parent' pats = do
-- | Like `filesMatching` but with a tag associated with a pattern so as to be -- | Like `filesMatching` but with a tag associated with a pattern so as to be
-- able to tell which pattern a resulting filepath is associated with. -- able to tell which pattern a resulting filepath is associated with.
filesMatchingWithTag :: (MonadIO m, MonadLogger m) => FilePath -> [(b, FilePattern)] -> m [(b, FilePath)] filesMatchingWithTag :: (MonadIO m, MonadLogger m, Ord b) => FilePath -> [(b, FilePattern)] -> m [(b, [FilePath])]
filesMatchingWithTag parent' pats = do filesMatchingWithTag parent' pats = do
filesMatching parent' (snd <$> pats) <&> \xs -> fs <- filesMatching parent' (snd <$> pats)
mapMaybe (\x -> (,x) <$> getTag pats x) xs let m = Map.fromListWith (<>) $
flip mapMaybe fs $ \fp -> do
tag <- getTag pats fp
pure (tag, one fp)
pure $ Map.toList m
getTag :: [(b, FilePattern)] -> FilePath -> Maybe b getTag :: [(b, FilePattern)] -> FilePath -> Maybe b
getTag pats fp = getTag pats fp =