{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TupleSections #-}
module Data.Conduit.INotify where
import Conduit (ConduitT, MonadIO, bracketP, lift, liftIO, (.|))
import qualified Conduit as C (await, awaitForever, mapInput, sourceHandle, yield)
import Control.Concurrent.STM (TVar, modifyTVar, newTVar, newTVarIO, readTVarIO, writeTVar)
import Control.Concurrent.STM.TMQueue (TMQueue, closeTMQueue, newTMQueue, writeTMQueue)
import Control.Monad.STM (STM, atomically)
import Control.Monad.Trans.Resource (MonadResource)
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS (hGetSome, null)
import qualified Data.ByteString.Lazy.Internal as BS (defaultChunkSize)
import qualified Data.Conduit.List as C (catMaybes, map, mapMaybe)
import Data.Conduit.TQueue (sourceTMQueue)
import Data.Foldable (traverse_)
import Data.List.NonEmpty (NonEmpty ((:|)))
import qualified Data.List.NonEmpty as NonEmpty (toList)
import Data.Map (Map)
import qualified Data.Map as Map (delete, fromList, insert, notMember)
import System.Directory (canonicalizePath)
import System.FilePath (takeDirectory, takeFileName, (</>))
import System.FilePath.ByteString (encodeFilePath)
import System.FilePath.Posix.ByteString (decodeFilePath)
import System.INotify (filePath)
import qualified System.INotify as INotify (Event (Ignored, Modified, MovedIn), EventVariety (DeleteSelf, Modify, MoveIn), INotify, WatchDescriptor, addWatch, removeWatch)
import qualified System.IO as IO (Handle, IOMode (ReadMode), SeekMode (AbsoluteSeek), hClose, hSeek, hTell, openFile)
inotifyEventsSource ::
(MonadResource m, Monad m) =>
INotify.INotify ->
NonEmpty INotify.EventVariety ->
FilePath ->
STM (ConduitT () INotify.Event m (), STM ())
inotifyEventsSource :: INotify
-> NonEmpty EventVariety
-> FilePath
-> STM (ConduitT () Event m (), STM ())
inotifyEventsSource INotify
i NonEmpty EventVariety
events FilePath
fp = do
TMQueue Event
q <- STM (TMQueue Event)
forall a. STM (TMQueue a)
newTMQueue
(ConduitT () Event m (), STM ())
-> STM (ConduitT () Event m (), STM ())
forall (m :: * -> *) a. Monad m => a -> m a
return (IO WatchDescriptor
-> (WatchDescriptor -> IO ())
-> (WatchDescriptor -> ConduitT () Event m ())
-> ConduitT () Event m ()
forall (m :: * -> *) a i o r.
MonadResource m =>
IO a -> (a -> IO ()) -> (a -> ConduitT i o m r) -> ConduitT i o m r
bracketP (TMQueue Event -> IO WatchDescriptor
initialize TMQueue Event
q) WatchDescriptor -> IO ()
cleanup (TMQueue Event -> WatchDescriptor -> ConduitT () Event m ()
forall (m :: * -> *) a p z.
MonadIO m =>
TMQueue a -> p -> ConduitT z a m ()
inside TMQueue Event
q), TMQueue Event -> STM ()
forall a. TMQueue a -> STM ()
closeTMQueue TMQueue Event
q)
where
initialize :: TMQueue Event -> IO WatchDescriptor
initialize TMQueue Event
q = INotify
-> [EventVariety]
-> RawFilePath
-> (Event -> IO ())
-> IO WatchDescriptor
INotify.addWatch INotify
i (NonEmpty EventVariety -> [EventVariety]
forall a. NonEmpty a -> [a]
NonEmpty.toList NonEmpty EventVariety
events) (FilePath -> RawFilePath
encodeFilePath FilePath
fp) (STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> (Event -> STM ()) -> Event -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TMQueue Event -> Event -> STM ()
forall a. TMQueue a -> a -> STM ()
writeTMQueue TMQueue Event
q)
cleanup :: WatchDescriptor -> IO ()
cleanup = WatchDescriptor -> IO ()
INotify.removeWatch
inside :: TMQueue a -> p -> ConduitT z a m ()
inside TMQueue a
q p
_ = TMQueue a -> ConduitT z a m ()
forall (m :: * -> *) a z.
MonadIO m =>
TMQueue a -> ConduitT z a m ()
sourceTMQueue TMQueue a
q
sourceHandleEof :: MonadIO m => IO.Handle -> ConduitT () (Maybe ByteString) m ()
sourceHandleEof :: Handle -> ConduitT () (Maybe RawFilePath) m ()
sourceHandleEof Handle
h = Handle -> ConduitT () RawFilePath m ()
forall (m :: * -> *) i.
MonadIO m =>
Handle -> ConduitT i RawFilePath m ()
C.sourceHandle Handle
h ConduitT () RawFilePath m ()
-> ConduitM RawFilePath (Maybe RawFilePath) m ()
-> ConduitT () (Maybe RawFilePath) m ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| (RawFilePath -> Maybe RawFilePath)
-> ConduitM RawFilePath (Maybe RawFilePath) m ()
forall (m :: * -> *) a b. Monad m => (a -> b) -> ConduitT a b m ()
C.map RawFilePath -> Maybe RawFilePath
forall a. a -> Maybe a
Just ConduitM RawFilePath (Maybe RawFilePath) m ()
-> ConduitM RawFilePath (Maybe RawFilePath) m ()
-> ConduitM RawFilePath (Maybe RawFilePath) m ()
forall a. Semigroup a => a -> a -> a
<> Maybe RawFilePath -> ConduitM RawFilePath (Maybe RawFilePath) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Maybe RawFilePath
forall a. Maybe a
Nothing
sourceFileFollowModify ::
(MonadResource m, MonadIO m) =>
INotify.INotify ->
FilePath ->
STM (ConduitT () (Maybe ByteString) m (), STM ())
sourceFileFollowModify :: INotify
-> FilePath -> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
sourceFileFollowModify INotify
i FilePath
fp =
do
(ConduitT () Event m ()
eventsSource, STM ()
closeWatch) <- INotify
-> NonEmpty EventVariety
-> FilePath
-> STM (ConduitT () Event m (), STM ())
forall (m :: * -> *).
(MonadResource m, Monad m) =>
INotify
-> NonEmpty EventVariety
-> FilePath
-> STM (ConduitT () Event m (), STM ())
inotifyEventsSource INotify
i (EventVariety
INotify.Modify EventVariety -> [EventVariety] -> NonEmpty EventVariety
forall a. a -> [a] -> NonEmpty a
:| [] ) FilePath
fp
(ConduitT () (Maybe RawFilePath) m (), STM ())
-> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
forall (m :: * -> *) a. Monad m => a -> m a
return (IO Handle
-> (Handle -> IO ())
-> (Handle -> ConduitT () (Maybe RawFilePath) m ())
-> ConduitT () (Maybe RawFilePath) m ()
forall (m :: * -> *) a i o r.
MonadResource m =>
IO a -> (a -> IO ()) -> (a -> ConduitT i o m r) -> ConduitT i o m r
bracketP (FilePath -> IOMode -> IO Handle
IO.openFile FilePath
fp IOMode
IO.ReadMode) Handle -> IO ()
IO.hClose (ConduitT () Event m ()
-> Handle -> ConduitT () (Maybe RawFilePath) m ()
forall (m :: * -> *).
MonadIO m =>
ConduitT () Event m ()
-> Handle -> ConduitT () (Maybe RawFilePath) m ()
inside ConduitT () Event m ()
eventsSource), STM ()
closeWatch)
where
inside :: MonadIO m => ConduitT () INotify.Event m () -> IO.Handle -> ConduitT () (Maybe ByteString) m ()
inside :: ConduitT () Event m ()
-> Handle -> ConduitT () (Maybe RawFilePath) m ()
inside ConduitT () Event m ()
eventsSource Handle
h =
Handle -> ConduitT () (Maybe RawFilePath) m ()
forall (m :: * -> *).
MonadIO m =>
Handle -> ConduitT () (Maybe RawFilePath) m ()
sourceHandleEof Handle
h
ConduitT () (Maybe RawFilePath) m ()
-> ConduitT () (Maybe RawFilePath) m ()
-> ConduitT () (Maybe RawFilePath) m ()
forall a. Semigroup a => a -> a -> a
<> (ConduitT () Event m ()
eventsSource ConduitT () Event m ()
-> ConduitM Event (Maybe RawFilePath) m ()
-> ConduitT () (Maybe RawFilePath) m ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| (Event -> ConduitM Event (Maybe RawFilePath) m ())
-> ConduitM Event (Maybe RawFilePath) m ()
forall (m :: * -> *) i o r.
Monad m =>
(i -> ConduitT i o m r) -> ConduitT i o m ()
C.awaitForever (\Event
e -> (Event -> ())
-> (() -> Maybe Event)
-> ConduitT () (Maybe RawFilePath) m ()
-> ConduitM Event (Maybe RawFilePath) m ()
forall (m :: * -> *) i1 i2 o r.
Monad m =>
(i1 -> i2)
-> (i2 -> Maybe i1) -> ConduitT i2 o m r -> ConduitT i1 o m r
C.mapInput (() -> Event -> ()
forall a b. a -> b -> a
const ()) (Maybe Event -> () -> Maybe Event
forall a b. a -> b -> a
const (Maybe Event -> () -> Maybe Event)
-> Maybe Event -> () -> Maybe Event
forall a b. (a -> b) -> a -> b
$ Event -> Maybe Event
forall a. a -> Maybe a
Just Event
e) (ConduitT () (Maybe RawFilePath) m ()
-> ConduitM Event (Maybe RawFilePath) m ())
-> ConduitT () (Maybe RawFilePath) m ()
-> ConduitM Event (Maybe RawFilePath) m ()
forall a b. (a -> b) -> a -> b
$ Handle -> ConduitT () (Maybe RawFilePath) m ()
forall (m :: * -> *).
MonadIO m =>
Handle -> ConduitT () (Maybe RawFilePath) m ()
sourceHandleEof Handle
h))
ConduitT () (Maybe RawFilePath) m ()
-> ConduitT () (Maybe RawFilePath) m ()
-> ConduitT () (Maybe RawFilePath) m ()
forall a. Semigroup a => a -> a -> a
<> Handle -> ConduitT () (Maybe RawFilePath) m ()
forall (m :: * -> *).
MonadIO m =>
Handle -> ConduitT () (Maybe RawFilePath) m ()
sourceHandleEof Handle
h
sourceFileFollowModify' :: (MonadResource m, MonadIO m) => INotify.INotify -> FilePath -> STM (ConduitT () ByteString m (), STM ())
sourceFileFollowModify' :: INotify -> FilePath -> STM (ConduitT () RawFilePath m (), STM ())
sourceFileFollowModify' INotify
i FilePath
fp = do
(ConduitT () (Maybe RawFilePath) m ()
source, STM ()
close) <- INotify
-> FilePath -> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
forall (m :: * -> *).
(MonadResource m, MonadIO m) =>
INotify
-> FilePath -> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
sourceFileFollowModify INotify
i FilePath
fp
(ConduitT () RawFilePath m (), STM ())
-> STM (ConduitT () RawFilePath m (), STM ())
forall (m :: * -> *) a. Monad m => a -> m a
return (ConduitT () (Maybe RawFilePath) m ()
source ConduitT () (Maybe RawFilePath) m ()
-> ConduitM (Maybe RawFilePath) RawFilePath m ()
-> ConduitT () RawFilePath m ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM (Maybe RawFilePath) RawFilePath m ()
forall (m :: * -> *) a. Monad m => ConduitT (Maybe a) a m ()
C.catMaybes, STM ()
close)
replacableBracketP ::
MonadResource m =>
IO a ->
(a -> IO ()) ->
((m a, m ()) -> ConduitT i o m ()) ->
ConduitT i o m ()
replacableBracketP :: IO a
-> (a -> IO ())
-> ((m a, m ()) -> ConduitT i o m ())
-> ConduitT i o m ()
replacableBracketP IO a
initialize a -> IO ()
cleanup (m a, m ()) -> ConduitT i o m ()
inside =
let getOrInitialize :: TVar (Maybe a) -> m a
getOrInitialize TVar (Maybe a)
var = IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ do
Maybe a
maybeA <- TVar (Maybe a) -> IO (Maybe a)
forall a. TVar a -> IO a
readTVarIO TVar (Maybe a)
var
case Maybe a
maybeA of
Just a
a -> a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
Maybe a
Nothing -> do
a
a <- IO a
initialize
STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar (Maybe a) -> Maybe a -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (Maybe a)
var (a -> Maybe a
forall a. a -> Maybe a
Just a
a)
a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
cleanupAndUnset :: TVar (Maybe a) -> m ()
cleanupAndUnset TVar (Maybe a)
var = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
Maybe a
maybeA <- TVar (Maybe a) -> IO (Maybe a)
forall a. TVar a -> IO a
readTVarIO TVar (Maybe a)
var
(a -> IO ()) -> Maybe a -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ a -> IO ()
cleanup Maybe a
maybeA
STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar (Maybe a) -> Maybe a -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (Maybe a)
var Maybe a
forall a. Maybe a
Nothing
in IO (TVar (Maybe a))
-> (TVar (Maybe a) -> IO ())
-> (TVar (Maybe a) -> ConduitT i o m ())
-> ConduitT i o m ()
forall (m :: * -> *) a i o r.
MonadResource m =>
IO a -> (a -> IO ()) -> (a -> ConduitT i o m r) -> ConduitT i o m r
bracketP
(IO a
initialize IO a -> (a -> IO (TVar (Maybe a))) -> IO (TVar (Maybe a))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe a -> IO (TVar (Maybe a))
forall a. a -> IO (TVar a)
newTVarIO (Maybe a -> IO (TVar (Maybe a)))
-> (a -> Maybe a) -> a -> IO (TVar (Maybe a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe a
forall a. a -> Maybe a
Just)
TVar (Maybe a) -> IO ()
forall (m :: * -> *). MonadIO m => TVar (Maybe a) -> m ()
cleanupAndUnset
(\TVar (Maybe a)
var -> (m a, m ()) -> ConduitT i o m ()
inside (TVar (Maybe a) -> m a
forall (m :: * -> *). MonadIO m => TVar (Maybe a) -> m a
getOrInitialize TVar (Maybe a)
var, TVar (Maybe a) -> m ()
forall (m :: * -> *). MonadIO m => TVar (Maybe a) -> m ()
cleanupAndUnset TVar (Maybe a)
var))
inotifyEventsSourceRotate :: MonadResource m => INotify.INotify -> NonEmpty INotify.EventVariety -> FilePath -> STM (ConduitT () INotify.Event m (), STM ())
inotifyEventsSourceRotate :: INotify
-> NonEmpty EventVariety
-> FilePath
-> STM (ConduitT () Event m (), STM ())
inotifyEventsSourceRotate INotify
i NonEmpty EventVariety
events FilePath
fp = do
TMQueue Event
q <- STM (TMQueue Event)
forall a. STM (TMQueue a)
newTMQueue
let c :: ConduitM a Event m ()
c = TMQueue Event -> ConduitM a Event m ()
forall (m :: * -> *) a z.
MonadIO m =>
TMQueue a -> ConduitT z a m ()
sourceTMQueue TMQueue Event
q ConduitM a Event m ()
-> ConduitM Event Event m () -> ConduitM a Event m ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| IO (TVar (Maybe WatchDescriptor))
-> (TVar (Maybe WatchDescriptor) -> IO ())
-> ((m (TVar (Maybe WatchDescriptor)), m ())
-> ConduitM Event Event m ())
-> ConduitM Event Event m ()
forall (m :: * -> *) a i o.
MonadResource m =>
IO a
-> (a -> IO ())
-> ((m a, m ()) -> ConduitT i o m ())
-> ConduitT i o m ()
replacableBracketP (TMQueue Event -> IO (TVar (Maybe WatchDescriptor))
initialize TMQueue Event
q) TVar (Maybe WatchDescriptor) -> IO ()
cleanup (m (TVar (Maybe WatchDescriptor)), m ())
-> ConduitM Event Event m ()
forall (m :: * -> *).
MonadIO m =>
(m (TVar (Maybe WatchDescriptor)), m ())
-> ConduitT Event Event m ()
inside
(ConduitT () Event m (), STM ())
-> STM (ConduitT () Event m (), STM ())
forall (m :: * -> *) a. Monad m => a -> m a
return (ConduitT () Event m ()
forall a. ConduitM a Event m ()
c, TMQueue Event -> STM ()
forall a. TMQueue a -> STM ()
closeTMQueue TMQueue Event
q)
where
initialize :: TMQueue INotify.Event -> IO (TVar (Maybe INotify.WatchDescriptor))
initialize :: TMQueue Event -> IO (TVar (Maybe WatchDescriptor))
initialize TMQueue Event
q = do
WatchDescriptor
w <- INotify
-> [EventVariety]
-> RawFilePath
-> (Event -> IO ())
-> IO WatchDescriptor
INotify.addWatch INotify
i (EventVariety
INotify.DeleteSelf EventVariety -> [EventVariety] -> [EventVariety]
forall a. a -> [a] -> [a]
: NonEmpty EventVariety -> [EventVariety]
forall a. NonEmpty a -> [a]
NonEmpty.toList NonEmpty EventVariety
events) (FilePath -> RawFilePath
encodeFilePath FilePath
fp) (STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> (Event -> STM ()) -> Event -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TMQueue Event -> Event -> STM ()
forall a. TMQueue a -> a -> STM ()
writeTMQueue TMQueue Event
q)
Maybe WatchDescriptor -> IO (TVar (Maybe WatchDescriptor))
forall a. a -> IO (TVar a)
newTVarIO (Maybe WatchDescriptor -> IO (TVar (Maybe WatchDescriptor)))
-> Maybe WatchDescriptor -> IO (TVar (Maybe WatchDescriptor))
forall a b. (a -> b) -> a -> b
$ WatchDescriptor -> Maybe WatchDescriptor
forall a. a -> Maybe a
Just WatchDescriptor
w
cleanup :: TVar (Maybe INotify.WatchDescriptor) -> IO ()
cleanup :: TVar (Maybe WatchDescriptor) -> IO ()
cleanup TVar (Maybe WatchDescriptor)
var = TVar (Maybe WatchDescriptor) -> IO (Maybe WatchDescriptor)
forall a. TVar a -> IO a
readTVarIO TVar (Maybe WatchDescriptor)
var IO (Maybe WatchDescriptor)
-> (Maybe WatchDescriptor -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (WatchDescriptor -> IO ()) -> Maybe WatchDescriptor -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ WatchDescriptor -> IO ()
INotify.removeWatch
inside :: MonadIO m => (m (TVar (Maybe INotify.WatchDescriptor)), m ()) -> ConduitT INotify.Event INotify.Event m ()
inside :: (m (TVar (Maybe WatchDescriptor)), m ())
-> ConduitT Event Event m ()
inside (m (TVar (Maybe WatchDescriptor))
getOrInit, m ()
unset) = do
TVar (Maybe WatchDescriptor)
var <- m (TVar (Maybe WatchDescriptor))
-> ConduitT Event Event m (TVar (Maybe WatchDescriptor))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m (TVar (Maybe WatchDescriptor))
getOrInit
Maybe Event
event <- ConduitT Event Event m (Maybe Event)
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await
case Maybe Event
event of
Just e :: Event
e@Event
INotify.Ignored -> do
Event -> ConduitT Event Event m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Event
e
IO () -> ConduitT Event Event m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ConduitT Event Event m ())
-> IO () -> ConduitT Event Event m ()
forall a b. (a -> b) -> a -> b
$ STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar (Maybe WatchDescriptor) -> Maybe WatchDescriptor -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (Maybe WatchDescriptor)
var Maybe WatchDescriptor
forall a. Maybe a
Nothing
m () -> ConduitT Event Event m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m ()
unset
(m (TVar (Maybe WatchDescriptor)), m ())
-> ConduitT Event Event m ()
forall (m :: * -> *).
MonadIO m =>
(m (TVar (Maybe WatchDescriptor)), m ())
-> ConduitT Event Event m ()
inside (m (TVar (Maybe WatchDescriptor))
getOrInit, m ()
unset)
Just Event
other -> do
Event -> ConduitT Event Event m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Event
other
(m (TVar (Maybe WatchDescriptor)), m ())
-> ConduitT Event Event m ()
forall (m :: * -> *).
MonadIO m =>
(m (TVar (Maybe WatchDescriptor)), m ())
-> ConduitT Event Event m ()
inside (m (TVar (Maybe WatchDescriptor))
getOrInit, m ()
unset)
Maybe Event
Nothing ->
() -> ConduitT Event Event m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
inotifyEventsSourceRotateMultiple :: MonadResource m => INotify.INotify -> [(NonEmpty INotify.EventVariety, FilePath)] -> STM (ConduitT () (INotify.Event, FilePath) m (), STM ())
inotifyEventsSourceRotateMultiple :: INotify
-> [(NonEmpty EventVariety, FilePath)]
-> STM (ConduitT () (Event, FilePath) m (), STM ())
inotifyEventsSourceRotateMultiple INotify
i [(NonEmpty EventVariety, FilePath)]
eventsToFp = do
TMQueue (Event, FilePath)
q <- STM (TMQueue (Event, FilePath))
forall a. STM (TMQueue a)
newTMQueue
let c :: ConduitM a (Event, FilePath) m ()
c = TMQueue (Event, FilePath) -> ConduitM a (Event, FilePath) m ()
forall (m :: * -> *) a z.
MonadIO m =>
TMQueue a -> ConduitT z a m ()
sourceTMQueue TMQueue (Event, FilePath)
q ConduitM a (Event, FilePath) m ()
-> ConduitM (Event, FilePath) (Event, FilePath) m ()
-> ConduitM a (Event, FilePath) m ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| IO (TVar (Map FilePath WatchDescriptor))
-> (TVar (Map FilePath WatchDescriptor) -> IO ())
-> ((m (TVar (Map FilePath WatchDescriptor)), m ())
-> ConduitM (Event, FilePath) (Event, FilePath) m ())
-> ConduitM (Event, FilePath) (Event, FilePath) m ()
forall (m :: * -> *) a i o.
MonadResource m =>
IO a
-> (a -> IO ())
-> ((m a, m ()) -> ConduitT i o m ())
-> ConduitT i o m ()
replacableBracketP (TMQueue (Event, FilePath)
-> IO (TVar (Map FilePath WatchDescriptor))
initialize TMQueue (Event, FilePath)
q) TVar (Map FilePath WatchDescriptor) -> IO ()
cleanup (TMQueue (Event, FilePath)
-> (m (TVar (Map FilePath WatchDescriptor)), m ())
-> ConduitM (Event, FilePath) (Event, FilePath) m ()
forall (m :: * -> *).
MonadIO m =>
TMQueue (Event, FilePath)
-> (m (TVar (Map FilePath WatchDescriptor)), m ())
-> ConduitT (Event, FilePath) (Event, FilePath) m ()
inside TMQueue (Event, FilePath)
q)
(ConduitT () (Event, FilePath) m (), STM ())
-> STM (ConduitT () (Event, FilePath) m (), STM ())
forall (m :: * -> *) a. Monad m => a -> m a
return (ConduitT () (Event, FilePath) m ()
forall a. ConduitM a (Event, FilePath) m ()
c, TMQueue (Event, FilePath) -> STM ()
forall a. TMQueue a -> STM ()
closeTMQueue TMQueue (Event, FilePath)
q)
where
initializeSingle :: TMQueue (INotify.Event, FilePath) -> NonEmpty INotify.EventVariety -> FilePath -> IO INotify.WatchDescriptor
initializeSingle :: TMQueue (Event, FilePath)
-> NonEmpty EventVariety -> FilePath -> IO WatchDescriptor
initializeSingle TMQueue (Event, FilePath)
q NonEmpty EventVariety
events FilePath
fp =
INotify
-> [EventVariety]
-> RawFilePath
-> (Event -> IO ())
-> IO WatchDescriptor
INotify.addWatch INotify
i (NonEmpty EventVariety -> [EventVariety]
forall a. NonEmpty a -> [a]
NonEmpty.toList NonEmpty EventVariety
events) (FilePath -> RawFilePath
encodeFilePath FilePath
fp) (STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> (Event -> STM ()) -> Event -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TMQueue (Event, FilePath) -> (Event, FilePath) -> STM ()
forall a. TMQueue a -> a -> STM ()
writeTMQueue TMQueue (Event, FilePath)
q ((Event, FilePath) -> STM ())
-> (Event -> (Event, FilePath)) -> Event -> STM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,FilePath
fp))
initialize :: TMQueue (INotify.Event, FilePath) -> IO (TVar (Map FilePath INotify.WatchDescriptor))
initialize :: TMQueue (Event, FilePath)
-> IO (TVar (Map FilePath WatchDescriptor))
initialize TMQueue (Event, FilePath)
q = do
[(FilePath, WatchDescriptor)]
ws <- ((NonEmpty EventVariety, FilePath)
-> IO (FilePath, WatchDescriptor))
-> [(NonEmpty EventVariety, FilePath)]
-> IO [(FilePath, WatchDescriptor)]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (\(NonEmpty EventVariety
events, FilePath
fp) -> (FilePath
fp,) (WatchDescriptor -> (FilePath, WatchDescriptor))
-> IO WatchDescriptor -> IO (FilePath, WatchDescriptor)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TMQueue (Event, FilePath)
-> NonEmpty EventVariety -> FilePath -> IO WatchDescriptor
initializeSingle TMQueue (Event, FilePath)
q NonEmpty EventVariety
events FilePath
fp) [(NonEmpty EventVariety, FilePath)]
eventsToFp
Map FilePath WatchDescriptor
-> IO (TVar (Map FilePath WatchDescriptor))
forall a. a -> IO (TVar a)
newTVarIO (Map FilePath WatchDescriptor
-> IO (TVar (Map FilePath WatchDescriptor)))
-> Map FilePath WatchDescriptor
-> IO (TVar (Map FilePath WatchDescriptor))
forall a b. (a -> b) -> a -> b
$ [(FilePath, WatchDescriptor)] -> Map FilePath WatchDescriptor
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(FilePath, WatchDescriptor)]
ws
cleanup :: TVar (Map FilePath INotify.WatchDescriptor) -> IO ()
cleanup :: TVar (Map FilePath WatchDescriptor) -> IO ()
cleanup TVar (Map FilePath WatchDescriptor)
var = TVar (Map FilePath WatchDescriptor)
-> IO (Map FilePath WatchDescriptor)
forall a. TVar a -> IO a
readTVarIO TVar (Map FilePath WatchDescriptor)
var IO (Map FilePath WatchDescriptor)
-> (Map FilePath WatchDescriptor -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (WatchDescriptor -> IO ()) -> Map FilePath WatchDescriptor -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ WatchDescriptor -> IO ()
INotify.removeWatch
inside :: MonadIO m => TMQueue (INotify.Event, FilePath) -> (m (TVar (Map FilePath INotify.WatchDescriptor)), m ()) -> ConduitT (INotify.Event, FilePath) (INotify.Event, FilePath) m ()
inside :: TMQueue (Event, FilePath)
-> (m (TVar (Map FilePath WatchDescriptor)), m ())
-> ConduitT (Event, FilePath) (Event, FilePath) m ()
inside TMQueue (Event, FilePath)
q (m (TVar (Map FilePath WatchDescriptor))
getOrInit, m ()
unset) = do
TVar (Map FilePath WatchDescriptor)
var <- m (TVar (Map FilePath WatchDescriptor))
-> ConduitT
(Event, FilePath)
(Event, FilePath)
m
(TVar (Map FilePath WatchDescriptor))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m (TVar (Map FilePath WatchDescriptor))
getOrInit
Map FilePath WatchDescriptor
ws <- IO (Map FilePath WatchDescriptor)
-> ConduitT
(Event, FilePath)
(Event, FilePath)
m
(Map FilePath WatchDescriptor)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Map FilePath WatchDescriptor)
-> ConduitT
(Event, FilePath)
(Event, FilePath)
m
(Map FilePath WatchDescriptor))
-> IO (Map FilePath WatchDescriptor)
-> ConduitT
(Event, FilePath)
(Event, FilePath)
m
(Map FilePath WatchDescriptor)
forall a b. (a -> b) -> a -> b
$ TVar (Map FilePath WatchDescriptor)
-> IO (Map FilePath WatchDescriptor)
forall a. TVar a -> IO a
readTVarIO TVar (Map FilePath WatchDescriptor)
var
IO () -> ConduitT (Event, FilePath) (Event, FilePath) m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ConduitT (Event, FilePath) (Event, FilePath) m ())
-> IO () -> ConduitT (Event, FilePath) (Event, FilePath) m ()
forall a b. (a -> b) -> a -> b
$ ((NonEmpty EventVariety, FilePath) -> IO ())
-> [(NonEmpty EventVariety, FilePath)] -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (\(NonEmpty EventVariety
events, FilePath
fp) -> if FilePath -> Map FilePath WatchDescriptor -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.notMember FilePath
fp Map FilePath WatchDescriptor
ws then TMQueue (Event, FilePath)
-> NonEmpty EventVariety -> FilePath -> IO WatchDescriptor
initializeSingle TMQueue (Event, FilePath)
q NonEmpty EventVariety
events FilePath
fp IO WatchDescriptor -> (WatchDescriptor -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ())
-> (WatchDescriptor -> STM ()) -> WatchDescriptor -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TVar (Map FilePath WatchDescriptor)
-> (Map FilePath WatchDescriptor -> Map FilePath WatchDescriptor)
-> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar TVar (Map FilePath WatchDescriptor)
var ((Map FilePath WatchDescriptor -> Map FilePath WatchDescriptor)
-> STM ())
-> (WatchDescriptor
-> Map FilePath WatchDescriptor -> Map FilePath WatchDescriptor)
-> WatchDescriptor
-> STM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath
-> WatchDescriptor
-> Map FilePath WatchDescriptor
-> Map FilePath WatchDescriptor
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert FilePath
fp else () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) [(NonEmpty EventVariety, FilePath)]
eventsToFp
Maybe (Event, FilePath)
event <- ConduitT
(Event, FilePath) (Event, FilePath) m (Maybe (Event, FilePath))
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await
case Maybe (Event, FilePath)
event of
Just e :: (Event, FilePath)
e@(Event
INotify.Ignored, FilePath
fp) -> do
(Event, FilePath)
-> ConduitT (Event, FilePath) (Event, FilePath) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield (Event, FilePath)
e
IO () -> ConduitT (Event, FilePath) (Event, FilePath) m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ConduitT (Event, FilePath) (Event, FilePath) m ())
-> IO () -> ConduitT (Event, FilePath) (Event, FilePath) m ()
forall a b. (a -> b) -> a -> b
$ STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar (Map FilePath WatchDescriptor)
-> (Map FilePath WatchDescriptor -> Map FilePath WatchDescriptor)
-> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar TVar (Map FilePath WatchDescriptor)
var (FilePath
-> Map FilePath WatchDescriptor -> Map FilePath WatchDescriptor
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete FilePath
fp)
TMQueue (Event, FilePath)
-> (m (TVar (Map FilePath WatchDescriptor)), m ())
-> ConduitT (Event, FilePath) (Event, FilePath) m ()
forall (m :: * -> *).
MonadIO m =>
TMQueue (Event, FilePath)
-> (m (TVar (Map FilePath WatchDescriptor)), m ())
-> ConduitT (Event, FilePath) (Event, FilePath) m ()
inside TMQueue (Event, FilePath)
q (m (TVar (Map FilePath WatchDescriptor))
getOrInit, m ()
unset)
Just (Event, FilePath)
other -> do
(Event, FilePath)
-> ConduitT (Event, FilePath) (Event, FilePath) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield (Event, FilePath)
other
TMQueue (Event, FilePath)
-> (m (TVar (Map FilePath WatchDescriptor)), m ())
-> ConduitT (Event, FilePath) (Event, FilePath) m ()
forall (m :: * -> *).
MonadIO m =>
TMQueue (Event, FilePath)
-> (m (TVar (Map FilePath WatchDescriptor)), m ())
-> ConduitT (Event, FilePath) (Event, FilePath) m ()
inside TMQueue (Event, FilePath)
q (m (TVar (Map FilePath WatchDescriptor))
getOrInit, m ()
unset)
Maybe (Event, FilePath)
Nothing ->
() -> ConduitT (Event, FilePath) (Event, FilePath) m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
data FollowFileEvent = Replaced | Modified deriving (FollowFileEvent -> FollowFileEvent -> Bool
(FollowFileEvent -> FollowFileEvent -> Bool)
-> (FollowFileEvent -> FollowFileEvent -> Bool)
-> Eq FollowFileEvent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FollowFileEvent -> FollowFileEvent -> Bool
$c/= :: FollowFileEvent -> FollowFileEvent -> Bool
== :: FollowFileEvent -> FollowFileEvent -> Bool
$c== :: FollowFileEvent -> FollowFileEvent -> Bool
Eq, Int -> FollowFileEvent -> ShowS
[FollowFileEvent] -> ShowS
FollowFileEvent -> FilePath
(Int -> FollowFileEvent -> ShowS)
-> (FollowFileEvent -> FilePath)
-> ([FollowFileEvent] -> ShowS)
-> Show FollowFileEvent
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [FollowFileEvent] -> ShowS
$cshowList :: [FollowFileEvent] -> ShowS
show :: FollowFileEvent -> FilePath
$cshow :: FollowFileEvent -> FilePath
showsPrec :: Int -> FollowFileEvent -> ShowS
$cshowsPrec :: Int -> FollowFileEvent -> ShowS
Show)
sourceFileFollowModifyRotateWithSeek ::
(MonadResource m, MonadIO m) =>
INotify.INotify ->
FilePath ->
FilePath ->
STM (ConduitT () (Maybe ByteString) m (), STM ())
sourceFileFollowModifyRotateWithSeek :: INotify
-> FilePath
-> FilePath
-> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
sourceFileFollowModifyRotateWithSeek INotify
i FilePath
parent FilePath
fp = do
(ConduitT () (Event, FilePath) m ()
eventsSource, STM ()
closeWatch) <- INotify
-> [(NonEmpty EventVariety, FilePath)]
-> STM (ConduitT () (Event, FilePath) m (), STM ())
forall (m :: * -> *).
MonadResource m =>
INotify
-> [(NonEmpty EventVariety, FilePath)]
-> STM (ConduitT () (Event, FilePath) m (), STM ())
inotifyEventsSourceRotateMultiple INotify
i [(EventVariety
INotify.MoveIn EventVariety -> [EventVariety] -> NonEmpty EventVariety
forall a. a -> [a] -> NonEmpty a
:| [], FilePath
parent), (EventVariety
INotify.DeleteSelf EventVariety -> [EventVariety] -> NonEmpty EventVariety
forall a. a -> [a] -> NonEmpty a
:| [EventVariety
INotify.Modify], FilePath
parent FilePath -> ShowS
</> FilePath
fp)]
TVar (Maybe Integer)
positionVar <- Maybe Integer -> STM (TVar (Maybe Integer))
forall a. a -> STM (TVar a)
newTVar Maybe Integer
forall a. Maybe a
Nothing
(ConduitT () (Maybe RawFilePath) m (), STM ())
-> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
forall (m :: * -> *) a. Monad m => a -> m a
return (ConduitT () (Event, FilePath) m ()
eventsSource ConduitT () (Event, FilePath) m ()
-> ConduitM (Event, FilePath) (Maybe RawFilePath) m ()
-> ConduitT () (Maybe RawFilePath) m ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ((Event, FilePath) -> Maybe FollowFileEvent)
-> ConduitT (Event, FilePath) FollowFileEvent m ()
forall (m :: * -> *) a b.
Monad m =>
(a -> Maybe b) -> ConduitT a b m ()
C.mapMaybe (Event, FilePath) -> Maybe FollowFileEvent
handleINotifyEvent ConduitT (Event, FilePath) FollowFileEvent m ()
-> ConduitM FollowFileEvent (Maybe RawFilePath) m ()
-> ConduitM (Event, FilePath) (Maybe RawFilePath) m ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| IO Handle
-> (Handle -> IO ())
-> ((m Handle, m ())
-> ConduitM FollowFileEvent (Maybe RawFilePath) m ())
-> ConduitM FollowFileEvent (Maybe RawFilePath) m ()
forall (m :: * -> *) a i o.
MonadResource m =>
IO a
-> (a -> IO ())
-> ((m a, m ()) -> ConduitT i o m ())
-> ConduitT i o m ()
replacableBracketP (TVar (Maybe Integer) -> IO Handle
initialize TVar (Maybe Integer)
positionVar) Handle -> IO ()
cleanup (TVar (Maybe Integer)
-> (m Handle, m ())
-> ConduitM FollowFileEvent (Maybe RawFilePath) m ()
forall (m :: * -> *).
MonadIO m =>
TVar (Maybe Integer)
-> (m Handle, m ())
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
inside TVar (Maybe Integer)
positionVar), STM ()
closeWatch)
where
handleINotifyEvent :: (Event, FilePath) -> Maybe FollowFileEvent
handleINotifyEvent (INotify.Modified {}, FilePath
fp') = if FilePath
fp' FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
parent FilePath -> ShowS
</> FilePath
fp then FollowFileEvent -> Maybe FollowFileEvent
forall a. a -> Maybe a
Just FollowFileEvent
Modified else Maybe FollowFileEvent
forall a. Maybe a
Nothing
handleINotifyEvent (INotify.MovedIn {filePath :: Event -> RawFilePath
filePath = RawFilePath
fp'}, FilePath
parent') = if FilePath
parent FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
parent' Bool -> Bool -> Bool
&& FilePath
fp FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== RawFilePath -> FilePath
decodeFilePath RawFilePath
fp' then FollowFileEvent -> Maybe FollowFileEvent
forall a. a -> Maybe a
Just FollowFileEvent
Replaced else Maybe FollowFileEvent
forall a. Maybe a
Nothing
handleINotifyEvent (Event, FilePath)
_ = Maybe FollowFileEvent
forall a. Maybe a
Nothing
initialize :: TVar (Maybe Integer) -> IO IO.Handle
initialize :: TVar (Maybe Integer) -> IO Handle
initialize TVar (Maybe Integer)
positionVar = do
Handle
newHandle <- FilePath -> IOMode -> IO Handle
IO.openFile (FilePath
parent FilePath -> ShowS
</> FilePath
fp) IOMode
IO.ReadMode
Maybe Integer
maybePosition <- TVar (Maybe Integer) -> IO (Maybe Integer)
forall a. TVar a -> IO a
readTVarIO TVar (Maybe Integer)
positionVar
(Integer -> IO ()) -> Maybe Integer -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Handle -> SeekMode -> Integer -> IO ()
IO.hSeek Handle
newHandle SeekMode
IO.AbsoluteSeek) Maybe Integer
maybePosition
Handle -> IO Handle
forall (m :: * -> *) a. Monad m => a -> m a
return Handle
newHandle
cleanup :: IO.Handle -> IO ()
cleanup :: Handle -> IO ()
cleanup = Handle -> IO ()
IO.hClose
inside :: MonadIO m => TVar (Maybe Integer) -> (m IO.Handle, m ()) -> ConduitT FollowFileEvent (Maybe ByteString) m ()
inside :: TVar (Maybe Integer)
-> (m Handle, m ())
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
inside TVar (Maybe Integer)
positionVar (m Handle
getOrInit, m ()
unset) = do
Handle
handle <- m Handle -> ConduitT FollowFileEvent (Maybe RawFilePath) m Handle
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Handle
getOrInit
RawFilePath
line <- IO RawFilePath
-> ConduitT FollowFileEvent (Maybe RawFilePath) m RawFilePath
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO RawFilePath
-> ConduitT FollowFileEvent (Maybe RawFilePath) m RawFilePath)
-> IO RawFilePath
-> ConduitT FollowFileEvent (Maybe RawFilePath) m RawFilePath
forall a b. (a -> b) -> a -> b
$ Handle -> Int -> IO RawFilePath
BS.hGetSome Handle
handle Int
BS.defaultChunkSize
if RawFilePath -> Bool
BS.null RawFilePath
line
then do
Maybe RawFilePath
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield Maybe RawFilePath
forall a. Maybe a
Nothing
Maybe FollowFileEvent
event <- ConduitT
FollowFileEvent (Maybe RawFilePath) m (Maybe FollowFileEvent)
forall (m :: * -> *) i. Monad m => Consumer i m (Maybe i)
C.await
case Maybe FollowFileEvent
event of
Just FollowFileEvent
Replaced -> do
Integer
pos <- IO Integer
-> ConduitT FollowFileEvent (Maybe RawFilePath) m Integer
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Integer
-> ConduitT FollowFileEvent (Maybe RawFilePath) m Integer)
-> IO Integer
-> ConduitT FollowFileEvent (Maybe RawFilePath) m Integer
forall a b. (a -> b) -> a -> b
$ Handle -> IO Integer
IO.hTell Handle
handle
IO () -> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ConduitT FollowFileEvent (Maybe RawFilePath) m ())
-> IO () -> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
forall a b. (a -> b) -> a -> b
$ STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar (Maybe Integer) -> Maybe Integer -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (Maybe Integer)
positionVar (Maybe Integer -> STM ()) -> Maybe Integer -> STM ()
forall a b. (a -> b) -> a -> b
$ Integer -> Maybe Integer
forall a. a -> Maybe a
Just Integer
pos
m () -> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m ()
unset
TVar (Maybe Integer)
-> (m Handle, m ())
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
forall (m :: * -> *).
MonadIO m =>
TVar (Maybe Integer)
-> (m Handle, m ())
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
inside TVar (Maybe Integer)
positionVar (m Handle
getOrInit, m ()
unset)
Just FollowFileEvent
Modified ->
TVar (Maybe Integer)
-> (m Handle, m ())
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
forall (m :: * -> *).
MonadIO m =>
TVar (Maybe Integer)
-> (m Handle, m ())
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
inside TVar (Maybe Integer)
positionVar (m Handle
getOrInit, m ()
unset)
Maybe FollowFileEvent
Nothing ->
(FollowFileEvent -> ())
-> (() -> Maybe FollowFileEvent)
-> ConduitT () (Maybe RawFilePath) m ()
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
forall (m :: * -> *) i1 i2 o r.
Monad m =>
(i1 -> i2)
-> (i2 -> Maybe i1) -> ConduitT i2 o m r -> ConduitT i1 o m r
C.mapInput (() -> FollowFileEvent -> ()
forall a b. a -> b -> a
const ()) (Maybe FollowFileEvent -> () -> Maybe FollowFileEvent
forall a b. a -> b -> a
const Maybe FollowFileEvent
event) (Handle -> ConduitT () (Maybe RawFilePath) m ()
forall (m :: * -> *).
MonadIO m =>
Handle -> ConduitT () (Maybe RawFilePath) m ()
sourceHandleEof Handle
handle)
else do
Maybe RawFilePath
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
C.yield (Maybe RawFilePath
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ())
-> Maybe RawFilePath
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
forall a b. (a -> b) -> a -> b
$ RawFilePath -> Maybe RawFilePath
forall a. a -> Maybe a
Just RawFilePath
line
TVar (Maybe Integer)
-> (m Handle, m ())
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
forall (m :: * -> *).
MonadIO m =>
TVar (Maybe Integer)
-> (m Handle, m ())
-> ConduitT FollowFileEvent (Maybe RawFilePath) m ()
inside TVar (Maybe Integer)
positionVar (m Handle
getOrInit, m ()
unset)
sourceFileFollowModifyRotateWithSeek' ::
(MonadResource m, MonadIO m) =>
INotify.INotify ->
FilePath ->
FilePath ->
STM (ConduitT () ByteString m (), STM ())
sourceFileFollowModifyRotateWithSeek' :: INotify
-> FilePath
-> FilePath
-> STM (ConduitT () RawFilePath m (), STM ())
sourceFileFollowModifyRotateWithSeek' INotify
i FilePath
parent FilePath
fp = do
(ConduitT () (Maybe RawFilePath) m ()
source, STM ()
close) <- INotify
-> FilePath
-> FilePath
-> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
forall (m :: * -> *).
(MonadResource m, MonadIO m) =>
INotify
-> FilePath
-> FilePath
-> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
sourceFileFollowModifyRotateWithSeek INotify
i FilePath
parent FilePath
fp
(ConduitT () RawFilePath m (), STM ())
-> STM (ConduitT () RawFilePath m (), STM ())
forall (m :: * -> *) a. Monad m => a -> m a
return (ConduitT () (Maybe RawFilePath) m ()
source ConduitT () (Maybe RawFilePath) m ()
-> ConduitM (Maybe RawFilePath) RawFilePath m ()
-> ConduitT () RawFilePath m ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM (Maybe RawFilePath) RawFilePath m ()
forall (m :: * -> *) a. Monad m => ConduitT (Maybe a) a m ()
C.catMaybes, STM ()
close)
sourceFileFollowModifyRotateWithSeekIO ::
(MonadResource m, MonadIO m) =>
INotify.INotify ->
FilePath ->
IO (ConduitT () (Maybe ByteString) m (), STM ())
sourceFileFollowModifyRotateWithSeekIO :: INotify
-> FilePath -> IO (ConduitT () (Maybe RawFilePath) m (), STM ())
sourceFileFollowModifyRotateWithSeekIO INotify
i FilePath
fp = do
FilePath
absoluteFp <- FilePath -> IO FilePath
canonicalizePath FilePath
fp
STM (ConduitT () (Maybe RawFilePath) m (), STM ())
-> IO (ConduitT () (Maybe RawFilePath) m (), STM ())
forall a. STM a -> IO a
atomically (STM (ConduitT () (Maybe RawFilePath) m (), STM ())
-> IO (ConduitT () (Maybe RawFilePath) m (), STM ()))
-> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
-> IO (ConduitT () (Maybe RawFilePath) m (), STM ())
forall a b. (a -> b) -> a -> b
$ INotify
-> FilePath
-> FilePath
-> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
forall (m :: * -> *).
(MonadResource m, MonadIO m) =>
INotify
-> FilePath
-> FilePath
-> STM (ConduitT () (Maybe RawFilePath) m (), STM ())
sourceFileFollowModifyRotateWithSeek INotify
i (ShowS
takeDirectory FilePath
absoluteFp) (ShowS
takeFileName FilePath
absoluteFp)
sourceFileFollowModifyRotateWithSeekIO' ::
(MonadResource m, MonadIO m) =>
INotify.INotify ->
FilePath ->
IO (ConduitT () ByteString m (), STM ())
sourceFileFollowModifyRotateWithSeekIO' :: INotify -> FilePath -> IO (ConduitT () RawFilePath m (), STM ())
sourceFileFollowModifyRotateWithSeekIO' INotify
i FilePath
fp = do
(ConduitT () (Maybe RawFilePath) m ()
source, STM ()
close) <- INotify
-> FilePath -> IO (ConduitT () (Maybe RawFilePath) m (), STM ())
forall (m :: * -> *).
(MonadResource m, MonadIO m) =>
INotify
-> FilePath -> IO (ConduitT () (Maybe RawFilePath) m (), STM ())
sourceFileFollowModifyRotateWithSeekIO INotify
i FilePath
fp
(ConduitT () RawFilePath m (), STM ())
-> IO (ConduitT () RawFilePath m (), STM ())
forall (m :: * -> *) a. Monad m => a -> m a
return (ConduitT () (Maybe RawFilePath) m ()
source ConduitT () (Maybe RawFilePath) m ()
-> ConduitM (Maybe RawFilePath) RawFilePath m ()
-> ConduitT () RawFilePath m ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM (Maybe RawFilePath) RawFilePath m ()
forall (m :: * -> *) a. Monad m => ConduitT (Maybe a) a m ()
C.catMaybes, STM ()
close)