packages feed

streamly-fsnotify 1.0.1.0 → 1.1.0.0

raw patch · 4 files changed

+48/−47 lines, 4 filesdep +filepathdep −pathsPVP ok

version bump matches the API change (PVP)

Dependencies added: filepath

Dependencies removed: paths

API changes (from Hackage documentation)

- Streamly.FSNotify: type StopWatching m = m ()
+ Streamly.FSNotify: data StopWatching m
- Streamly.FSNotify: Added :: Path Absolute -> UTCTime -> FSEntryType -> Event
+ Streamly.FSNotify: Added :: FilePath -> UTCTime -> FSEntryType -> Event
- Streamly.FSNotify: Modified :: Path Absolute -> UTCTime -> FSEntryType -> Event
+ Streamly.FSNotify: Modified :: FilePath -> UTCTime -> FSEntryType -> Event
- Streamly.FSNotify: Other :: Path Absolute -> UTCTime -> Text -> Event
+ Streamly.FSNotify: Other :: FilePath -> UTCTime -> Text -> Event
- Streamly.FSNotify: Removed :: Path Absolute -> UTCTime -> FSEntryType -> Event
+ Streamly.FSNotify: Removed :: FilePath -> UTCTime -> FSEntryType -> Event
- Streamly.FSNotify: eventPath :: Event -> FsPath
+ Streamly.FSNotify: eventPath :: Event -> FilePath
- Streamly.FSNotify: hasExtension :: FileExt -> EventPredicate
+ Streamly.FSNotify: hasExtension :: FilePath -> EventPredicate
- Streamly.FSNotify: watchDirectory :: (IsStream t, MonadAsync m) => FsPath -> EventPredicate -> m (StopWatching m, t m Event)
+ Streamly.FSNotify: watchDirectory :: (IsStream t, MonadAsync m) => FilePath -> EventPredicate -> m (StopWatching m, t m Event)
- Streamly.FSNotify: watchDirectoryWith :: (IsStream t, MonadAsync m) => WatchConfig -> FsPath -> EventPredicate -> m (StopWatching m, t m Event)
+ Streamly.FSNotify: watchDirectoryWith :: (IsStream t, MonadAsync m) => WatchConfig -> FilePath -> EventPredicate -> m (StopWatching m, t m Event)
- Streamly.FSNotify: watchTree :: (IsStream t, MonadAsync m) => FsPath -> EventPredicate -> m (StopWatching m, t m Event)
+ Streamly.FSNotify: watchTree :: (IsStream t, MonadAsync m) => FilePath -> EventPredicate -> m (StopWatching m, t m Event)
- Streamly.FSNotify: watchTreeWith :: (IsStream t, MonadAsync m) => WatchConfig -> FsPath -> EventPredicate -> m (StopWatching m, t m Event)
+ Streamly.FSNotify: watchTreeWith :: (IsStream t, MonadAsync m) => WatchConfig -> FilePath -> EventPredicate -> m (StopWatching m, t m Event)

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for streamly-fsnotify +## 1.1.0.0 -- 2020-05-27++* Use abstract newtype for `StopWatching`.+* Remove typed filepaths. Power-to-weight ratio was too low.+ ## 1.0.1.0 -- 2020-05-27  * George Thomas takes over as maintainer. Metadata changes.
README.md view
@@ -1,5 +1,3 @@-# ``streamly-fsnotify``- ## What's the deal with this library?  [``streamly``][1] is an undoubtedly awesome library - [fast][2], flexible, and@@ -15,26 +13,26 @@  {-# LANGUAGE LambdaCase #-} +import System.FilePath ((</>)) import Streamly.FSNotify (EventPredicate, hasExtension, isDirectory, invert, isDeletion, conj, watchTree)-import System.Path (FsPath, FileExt(FileExt), fromFilePath) import qualified Streamly.Prelude as SP  -- conj -> both must be true -- invert -> true when the argument would be false and vice versa isCSourceFile :: EventPredicate-isCSourceFile = hasExtension (FileExt "c") `conj` invert isDirectory+isCSourceFile = hasExtension "c" `conj` invert isDirectory  notDeletion :: EventPredicate notDeletion = invert isDeletion -srcPath :: FsPath-srcPath = fromFilePath "/home/koz/c-project"+srcPath :: FilePath+srcPath = "home" </> "koz" </> "c-project"  -- first value given by watchTree stops the watcher -- we don't use it here, but if you want to, just call it main :: IO () main = do-    (_, stream) <- watchTree srcPath (isCSourceFile `conj` notDeletion)+    (_, stream) <- watchTree srcPath $ isCSourceFile `conj` notDeletion     SP.drain . SP.mapM go $ stream   where     go = \case@@ -48,10 +46,9 @@ * Cross-platform - should work anywhere both ``streamly`` and ``fsnotify`` do. * Efficient (event-driven, so won't shred your CPU or load your RAM). * Able to do one-level and recursive watching.+* Compositional and principled treatment of event filtering predicates. * Extensive set of filtering predicates, so you don't have to see events you   don't care about!-* Compositional and principled treatment of file paths and event filtering-  predicates.  ## Sounds good? Can I use it? 
src/Streamly/FSNotify.hs view
@@ -12,26 +12,26 @@  > {-# LANGUAGE LambdaCase #-} >+> import System.FilePath ((</>)) > import Streamly.FSNotify (EventPredicate, hasExtension, isDirectory, invert, isDeletion, conj, watchTree)-> import System.Path (FsPath, FileExt(FileExt), fromFilePath) > import qualified Streamly.Prelude as SP > > -- conj -> both must be true > -- invert -> true when the argument would be false and vice versa > isCSourceFile :: EventPredicate-> isCSourceFile = hasExtension (FileExt "c") `conj` invert isDirectory+> isCSourceFile = hasExtension "c" `conj` invert isDirectory > > notDeletion :: EventPredicate > notDeletion = invert isDeletion >-> srcPath :: FsPath-> srcPath = fromFilePath "/home/koz/c-project"+> srcPath :: FilePath+> srcPath = "home" </> "koz" </> "c-project" > > -- first value given by watchTree stops the watcher > -- we don't use it here, but if you want to, just call it > main :: IO () > main = do->     (_, stream) <- watchTree srcPath (isCSourceFile `conj` notDeletion)+>     (_, stream) <- watchTree srcPath $ isCSourceFile `conj` notDeletion >     SP.drain . SP.mapM go $ stream >   where >     go = \case@@ -41,7 +41,7 @@ -} module Streamly.FSNotify (     -- * Basic types-    FSEntryType(..), Event(..), StopWatching,+    FSEntryType(..), Event(..), StopWatching(stopWatching),     eventPath, eventTime, eventFSEntry,     -- * Events and predicates     EventPredicate(..),@@ -58,7 +58,7 @@ import Data.Text (Text, pack) import Data.Time.Clock (UTCTime) import Streamly (IsStream, MonadAsync)-import System.Path (Path, FsPath(..), FileExt, Absolute, isExtensionOf, toFilePath, makeAbsolute, fromAbsoluteFilePath)+import System.FilePath (isExtensionOf)  import qualified Streamly.Prelude as SP import qualified System.FSNotify as FSN@@ -70,22 +70,22 @@  -- | A file system notification. data Event-    = Added (Path Absolute) UTCTime FSEntryType -- ^ Creation event-    | Modified (Path Absolute) UTCTime FSEntryType -- ^ Modification event-    | Removed (Path Absolute) UTCTime FSEntryType -- ^ Deletion event-    | Other (Path Absolute) UTCTime Text -- ^ Some other kind of event+    = Added FilePath UTCTime FSEntryType -- ^ Creation event+    | Modified FilePath UTCTime FSEntryType -- ^ Modification event+    | Removed FilePath UTCTime FSEntryType -- ^ Deletion event+    | Other FilePath UTCTime Text -- ^ Some other kind of event     deriving (Eq, Show) --- | A function, which, when executed, stops a file system watch.-type StopWatching m = m ()+-- | An object, which, when executed with 'stopWatching', stops a file system watch.+newtype StopWatching m = StopWatching { stopWatching :: m () }  -- | Helper to retrieve the file path associated with an event.-eventPath :: Event -> FsPath+eventPath :: Event -> FilePath eventPath = \case-    Added p _ _ -> FsPath p-    Modified p _ _ -> FsPath p-    Removed p _ _ -> FsPath p-    Other p _ _ -> FsPath p+    Added p _ _ -> p+    Modified p _ _ -> p+    Removed p _ _ -> p+    Other p _ _ -> p  -- | Helper to retrieve an event's timestamp. eventTime :: Event -> UTCTime@@ -140,11 +140,11 @@  -- | The trivial predicate (allows any event through). everything :: EventPredicate-everything = EventPredicate . const $ True+everything = EventPredicate $ const True  -- | The null predicate (allows no events through). nothing :: EventPredicate-nothing = EventPredicate . const $ False+nothing = EventPredicate $ const False  -- | Allows through events that are caused by directories. -- Note that this will assume that non-\'basic\' events (that is, not creations, modifications or deletions) do not stem@@ -157,8 +157,8 @@  -- | Allows through events triggered by file system entries with a specific -- extension.-hasExtension :: FileExt -> EventPredicate-hasExtension fe = EventPredicate $ isExtensionOf fe . \case+hasExtension :: FilePath -> EventPredicate+hasExtension fe = EventPredicate $ (fe `isExtensionOf`) . \case     Added p _ _ -> p     Modified p _ _ -> p     Removed p _ _ -> p@@ -196,20 +196,20 @@ {- Watchers -}  -- | Watch a given directory, but only at one level (thus, subdirectories will __not__ be watched recursively).-watchDirectory :: (IsStream t, MonadAsync m) => FsPath -> EventPredicate -> m (StopWatching m, t m Event)+watchDirectory :: (IsStream t, MonadAsync m) => FilePath -> EventPredicate -> m (StopWatching m, t m Event) watchDirectory = watch FSN.watchDirChan FSN.defaultConfig  -- | As 'watchDirectory', but with a specified set of watch options. watchDirectoryWith :: (IsStream t, MonadAsync m) =>-    FSN.WatchConfig -> FsPath -> EventPredicate -> m (StopWatching m, t m Event)+    FSN.WatchConfig -> FilePath -> EventPredicate -> m (StopWatching m, t m Event) watchDirectoryWith = watch FSN.watchDirChan  -- | Watch a given directory recursively (thus, subdirectories will also have their contents watched).-watchTree :: (IsStream t, MonadAsync m) => FsPath -> EventPredicate -> m (StopWatching m, t m Event)+watchTree :: (IsStream t, MonadAsync m) => FilePath -> EventPredicate -> m (StopWatching m, t m Event) watchTree = watch FSN.watchTreeChan FSN.defaultConfig  -- | As 'watchTree', but with a specified set of watch options.-watchTreeWith :: (IsStream t, MonadAsync m) => FSN.WatchConfig -> FsPath -> EventPredicate -> m (StopWatching m, t m Event)+watchTreeWith :: (IsStream t, MonadAsync m) => FSN.WatchConfig -> FilePath -> EventPredicate -> m (StopWatching m, t m Event) watchTreeWith = watch FSN.watchTreeChan  @@ -217,22 +217,21 @@  watch :: (IsStream t, MonadAsync m) =>     (FSN.WatchManager -> FilePath -> FSN.ActionPredicate -> FSN.EventChannel -> IO FSN.StopListening) ->-    FSN.WatchConfig -> FsPath -> EventPredicate -> m (StopWatching m, t m Event)+    FSN.WatchConfig -> FilePath -> EventPredicate -> m (StopWatching m, t m Event) watch f conf p predicate = do-    manager <- liftIO . FSN.startManagerConf $ conf-    fp <- toFilePath <$> liftIO (makeAbsolute p)+    manager <- liftIO $ FSN.startManagerConf conf     let pred' = runPredicate predicate . mungeEvent     chan <- liftIO newChan-    stop <- liftIO $ f manager fp pred' chan-    let reallyStop = liftIO stop >> liftIO (FSN.stopManager manager)-    pure (reallyStop, SP.repeatM . liftIO . fmap mungeEvent $ readChan chan)+    stop <- liftIO $ f manager p pred' chan+    let reallyStop = StopWatching $ liftIO stop >> liftIO (FSN.stopManager manager)+    pure (reallyStop, SP.repeatM $ liftIO $ mungeEvent <$> readChan chan)  mungeEvent :: FSN.Event -> Event mungeEvent = \case-    FSN.Added p t b-> Added (fromAbsoluteFilePath p) t (isDir b)-    FSN.Modified p t b-> Modified (fromAbsoluteFilePath p) t (isDir b)-    FSN.Removed p t b-> Modified (fromAbsoluteFilePath p) t (isDir b)-    FSN.Unknown p t s-> Other (fromAbsoluteFilePath p) t (pack s)+    FSN.Added p t b -> Added p t (isDir b)+    FSN.Modified p t b -> Modified p t (isDir b)+    FSN.Removed p t b -> Modified p t (isDir b)+    FSN.Unknown p t s -> Other p t (pack s)  isDir :: Bool -> FSEntryType isDir = bool NotDir Dir
streamly-fsnotify.cabal view
@@ -1,6 +1,6 @@ cabal-version:       3.0 name:                streamly-fsnotify-version:             1.0.1.0+version:             1.1.0.0 synopsis:            Folder watching as a Streamly stream. description:     Provides Streamly streams for both single-level and recursive folder watching.@@ -20,8 +20,8 @@         Streamly.FSNotify     build-depends:         base >= 4.9 && < 5,+        filepath ^>= 1.4.2.1,         fsnotify ^>= 0.3.0.1,-        paths ^>= 0.2.0.0,         semirings ^>= 0.5.2,         streamly ^>= 0.7.0,         text ^>= 1.2.3.0,