packages feed

follow-file 0.0.2 → 0.0.3

raw patch · 3 files changed

+101/−69 lines, 3 filesdep ~basedep ~hinotifyPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base, hinotify

API changes (from Hackage documentation)

- System.File.Follow: follow :: (MonadIO m, MonadMask m, MonadBaseControl IO m) => INotify -> Path Abs File -> (Producer m ByteString -> m ()) -> m WatchDescriptor
+ System.File.Follow: follow :: (MonadIO m, MonadMask m, MonadBaseControl IO m) => INotify -> Path Abs File -> (ConduitT i ByteString m () -> m ()) -> m WatchDescriptor

Files

app/Main.hs view
@@ -1,9 +1,10 @@+module Main where+ import Path-import qualified Data.ByteString.Lazy as BS import qualified Data.Text as T import Data.Attoparsec.Text (parseOnly, endOfInput, eitherP) import Data.Attoparsec.Path (absFilePath, relFilePath, absDirPath)-import Data.Conduit ((=$=), runConduit)+import Data.Conduit ((.|), runConduit) import Data.Conduit.Combinators (stdout) import System.INotify (initINotify, removeWatch, killINotify) import System.File.Follow (follow)@@ -14,9 +15,10 @@ import Control.Concurrent (threadDelay)  +main :: IO () main = do-  [f] <- getArgs-  f <- case parseOnly (eitherP absFilePath relFilePath <* endOfInput) (T.pack f) of+  [filePath] <- getArgs+  f <- case parseOnly (eitherP absFilePath relFilePath <* endOfInput) (T.pack filePath) of           Left e -> error e           Right eAR -> case eAR of             Left a -> pure a@@ -27,4 +29,7 @@                 Right d' ->                   pure (d' </> r)   i <- initINotify-  bracket (follow i f (\source -> runConduit $ source =$= stdout)) (\watch -> removeWatch watch >> killINotify i) $ \_ -> forever $ threadDelay 50000+  let obtain = follow i f $ \source -> runConduit (source .| stdout)+      release watch = removeWatch watch >> killINotify i+  bracket obtain release $ \_ ->+    forever (threadDelay 50000) -- run forever
follow-file.cabal view
@@ -1,53 +1,73 @@-Name:                   follow-file-Version:                0.0.2-Author:                 Athan Clark <athan.clark@gmail.com>-Maintainer:             Athan Clark <athan.clark@gmail.com>-License:                BSD3-License-File:           LICENSE-Synopsis:               Be notified when a file gets appended, solely with what was added.-Description:-    See module for docs-Cabal-Version:          >= 1.10-Build-Type:             Simple-Category:               Filesystem+-- This file has been generated from package.yaml by hpack version 0.21.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: 2237e4036e920a20255f1af7b7256b4210fd90eddba2b0938e9df217cf29ccb7 +name:           follow-file+version:        0.0.3+synopsis:       Be notified when a file gets appended, solely with what was added. Warning - only works on linux and for files that are strictly appended, like log files.+description:    Please see the README on Github at <https://github.com/athanclark/follow-file#readme>+category:       Filesystem+homepage:       https://github.com/athanclark/follow-file#readme+bug-reports:    https://github.com/athanclark/follow-file/issues+maintainer:     Athan Clark <athan.clark@gmail.com>+license:        BSD3+license-file:   LICENSE+build-type:     Simple+cabal-version:  >= 1.10 -Library-  Default-Language:     Haskell2010-  HS-Source-Dirs:       src-  GHC-Options:          -Wall-  Exposed-Modules:      System.File.Follow-  Build-Depends:        base >= 4.8 && < 5-                      , attoparsec-                      , attoparsec-path-                      , bytestring-                      , conduit-                      , directory-                      , exceptions-                      , hinotify-                      , monad-control-                      , mtl-                      , path-                      , text-                      , unix-                      , utf8-string+source-repository head+  type: git+  location: https://github.com/athanclark/follow-file -Executable follow-file-  Default-Language:     Haskell2010-  Hs-Source-Dirs:       app-  Main-is:              Main.hs-  Build-Depends:        base-                      , bytestring-                      , follow-file-                      , path-                      , text-                      , attoparsec-                      , attoparsec-path-                      , hinotify-                      , conduit-                      , conduit-combinators-                      , directory+library+  exposed-modules:+      System.File.Follow+  other-modules:+      Paths_follow_file+  hs-source-dirs:+      src+  ghc-options: -Wall+  build-depends:+      attoparsec+    , attoparsec-path+    , base >=4.11 && <5+    , bytestring+    , conduit+    , directory+    , exceptions+    , hinotify >=0.4+    , monad-control+    , mtl+    , path+    , text+    , unix+    , utf8-string+  default-language: Haskell2010 -Source-Repository head-  Type:                 git-  Location:             https://github.com/athanclark/follow-file+executable follow-file+  main-is: Main.hs+  other-modules:+      Paths_follow_file+  hs-source-dirs:+      app+  ghc-options: -Wall -threaded -rtsopts -Wall -with-rtsopts=-N+  build-depends:+      attoparsec+    , attoparsec-path+    , base+    , bytestring+    , conduit+    , conduit-combinators+    , directory+    , exceptions+    , follow-file+    , hinotify+    , monad-control+    , mtl+    , path+    , text+    , unix+    , utf8-string+  default-language: Haskell2010
src/System/File/Follow.hs view
@@ -12,10 +12,10 @@ import qualified Data.ByteString.Lazy.Internal as LBS import qualified Data.ByteString.Internal as BS import qualified Data.ByteString.UTF8 as BS8-import qualified Data.Text as T+import qualified Data.Text.Encoding as T import Data.Attoparsec.Text (parseOnly, endOfInput) import Data.Attoparsec.Path (relFilePath)-import Data.Conduit (Producer, yield)+import Data.Conduit (ConduitT, yield) import Control.Monad (void) import Control.Monad.IO.Class (MonadIO (liftIO)) import Control.Monad.Catch (MonadMask, bracket)@@ -23,6 +23,7 @@ import Path (Path, Abs, File, filename, parent, toFilePath) import System.Posix.IO.ByteString (fdReadBuf, openFd, OpenMode (ReadOnly), defaultFileFlags, closeFd, fdSeek) import System.Posix.Types (FileOffset)+import System.Posix.ByteString.FilePath (RawFilePath) import System.Posix.Files.ByteString (fileSize, getFileStatus) import System.Directory (doesFileExist) import System.INotify (INotify, addWatch, Event (..), EventVariety (..), WatchDescriptor)@@ -38,7 +39,7 @@           )        => INotify        -> Path Abs File-       -> (Producer m BS.ByteString -> m ()) -- ^ Monadic state of @m@ is thrown away for each invocation, not synchronously interleaved.+       -> (ConduitT i BS.ByteString m () -> m ()) -- ^ Monadic state of @m@ is thrown away for each invocation, not synchronously interleaved.        -> m WatchDescriptor follow inotify file f = do   let file' = toFilePath file@@ -67,19 +68,25 @@       stop = do         liftIO (writeIORef positionRef 0)         f (yield mempty)-  liftBaseWith $ \runInBase -> addWatch inotify [Modify, Create, Delete] (toFilePath $ parent file) $ \e ->-    let isFile filePath = parseOnly (relFilePath <* endOfInput) (T.pack filePath) == Right (filename file)+  liftBaseWith $ \runInBase -> addWatch inotify [Modify, Create, Delete] (BS8.fromString $ toFilePath $ parent file) $ \e ->+    let isFile :: RawFilePath -> Bool+        isFile filePath = parseOnly (relFilePath <* endOfInput) (T.decodeUtf8 filePath) == Right (filename file)     in  case e of-          Created {filePath}  | isFile filePath -> void $ runInBase go-                              | otherwise -> pure ()-          Deleted {filePath}  | isFile filePath -> void $ runInBase stop-                              | otherwise -> pure ()-          Modified {maybeFilePath}  | (isFile <$> maybeFilePath) == Just True -> void $ runInBase go-                                    | otherwise -> pure ()-          MovedIn {filePath}  | isFile filePath -> void $ runInBase go-                              | otherwise -> pure ()-          MovedOut {filePath}   | isFile filePath -> void $ runInBase go-                                | otherwise -> pure ()+          Created {filePath}+            | isFile filePath -> void $ runInBase go+            | otherwise -> pure ()+          Deleted {filePath}+            | isFile filePath -> void $ runInBase stop+            | otherwise -> pure ()+          Modified {maybeFilePath}+            | (isFile <$> maybeFilePath) == Just True -> void $ runInBase go+            | otherwise -> pure ()+          MovedIn {filePath}+            | isFile filePath -> void $ runInBase go+            | otherwise -> pure ()+          MovedOut {filePath}+            | isFile filePath -> void $ runInBase go+            | otherwise -> pure ()           DeletedSelf -> error "containing folder deleted"           Unmounted -> error "containing folder unmounted"           QOverflow -> error "queue overflow"