@@ -47,7 +47,7 @@ module Streamly.Internal.FileSystem.Event.Windows
47 -- * Subscribing to events
47 -- * Subscribing to events
49 -- ** Default configuration
49 -- ** Default configuration
50− Config
50+ Config (..)
51 , Event (..)
51 , Event (..)
52 , Toggle (..)
52 , Toggle (..)
@@ -61,22 +61,21 @@ module Streamly.Internal.FileSystem.Event.Windows
61 -- ** Events of Interest
61 -- ** Events of Interest
62 -- *** Root Level Events
62 -- *** Root Level Events
63 , setModifiedFileName
63 , setModifiedFileName
64− , setModifiedDirName
64+ , setRootMoved
65 , setModifiedAttribute
65 , setModifiedAttribute
66 , setModifiedSize
66 , setModifiedSize
67 , setModifiedLastWrite
67 , setModifiedLastWrite
68 , setModifiedSecurity
68 , setModifiedSecurity
70 -- ** Watch APIs
70 -- ** Watch APIs
71− , watchPaths
71+ , watch
73 , watchTrees
72 , watchTrees
74 , watchTreesWith
73 , watchTreesWith
76 -- * Handling Events
75 -- * Handling Events
78 , getRelPath
76 , getRelPath
81 -- ** Item CRUD events
80 -- ** Item CRUD events
82 , isCreated
81 , isCreated
@@ -124,6 +123,7 @@ import System.Win32.Types (BOOL, DWORD, HANDLE, LPVOID, LPDWORD, failIfFalse_)
124import qualified Data.List.NonEmpty as NonEmpty
123import qualified Data.List.NonEmpty as NonEmpty
125import qualified Streamly.Internal.Data.Stream.IsStream as S
124import qualified Streamly.Internal.Data.Stream.IsStream as S
126import qualified Streamly.Internal.Unicode.Stream as U
125import qualified Streamly.Internal.Unicode.Stream as U
126+import qualified Streamly.Internal.Unicode.Utf8 as UTF8
127import qualified Streamly.Internal.Data.Array.Foreign as A
127import qualified Streamly.Internal.Data.Array.Foreign as A
128import Streamly.Internal.Data.Array.Foreign (Array)
128import Streamly.Internal.Data.Array.Foreign (Array)
@@ -179,8 +179,8 @@ setModifiedFileName = setFlag fILE_NOTIFY_CHANGE_FILE_NAME
180-- /Pre-release/
180-- /Pre-release/
182−setModifiedDirName :: Toggle -> Config -> Config
182+setRootMoved :: Toggle -> Config -> Config
183−setModifiedDirName = setFlag fILE_NOTIFY_CHANGE_DIR_NAME
183+setRootMoved = setFlag fILE_NOTIFY_CHANGE_DIR_NAME
185-- | Report when a file attribute is modified.
185-- | Report when a file attribute is modified.
@@ -227,7 +227,7 @@ setModifiedSecurity = setFlag fILE_NOTIFY_CHANGE_SECURITY
227setAllEvents :: Toggle -> Config -> Config
227setAllEvents :: Toggle -> Config -> Config
228setAllEvents s =
228setAllEvents s =
229 setModifiedFileName s
229 setModifiedFileName s
230− . setModifiedDirName s
230+ . setRootMoved s
231 . setModifiedAttribute s
231 . setModifiedAttribute s
232 . setModifiedSize s
232 . setModifiedSize s
233 . setModifiedLastWrite s
233 . setModifiedLastWrite s
@@ -399,32 +399,6 @@ utf8ToStringList = NonEmpty.map utf8ToString
399closePathHandleStream :: SerialT IO (HANDLE, FilePath, Config) -> IO ()
399closePathHandleStream :: SerialT IO (HANDLE, FilePath, Config) -> IO ()
400closePathHandleStream = S.mapM_ (\(h, _, _) -> closeHandle h)
400closePathHandleStream = S.mapM_ (\(h, _, _) -> closeHandle h)
402−-- | Start monitoring a list of file system paths for file system events with
403−-- the supplied configuration operation over the 'defaultConfig'. The
404−-- paths could be files or directories. When the path is a directory, only the
405−-- files and directories directly under the watched directory are monitored,
406−-- contents of subdirectories are not monitored. Monitoring starts from the
407−-- current time onwards.
413− -> NonEmpty (Array Word8)
415−watchPathsWith f = watchTreesWith (f . setRecursiveMode False)
417−-- | Like 'watchPathsWith' but uses the 'defaultConfig' options.
420−-- watchPaths = watchPathsWith id
425−watchPaths :: NonEmpty (Array Word8) -> SerialT IO Event
426−watchPaths = watchPathsWith id
429-- Document the path treatment for Linux/Windows/macOS modules.
403-- Document the path treatment for Linux/Windows/macOS modules.
430-- Remove the utf-8 encoding requirement of paths? It can be encoding agnostic
404-- Remove the utf-8 encoding requirement of paths? It can be encoding agnostic
@@ -450,9 +424,7 @@ watchTreesWith f paths =
454− let cfg = f $ setRecursiveMode True defaultConfig
455− in return $ pathsToHandles (utf8ToStringList paths) cfg
427+ before = return $ pathsToHandles (utf8ToStringList paths) $ f defaultConfig
456 after = liftIO . closePathHandleStream
428 after = liftIO . closePathHandleStream
458-- | Like 'watchTreesWith' but uses the 'defaultConfig' options.
430-- | Like 'watchTreesWith' but uses the 'defaultConfig' options.
@@ -464,18 +436,29 @@ watchTreesWith f paths =
464watchTrees :: NonEmpty (Array Word8) -> SerialT IO Event
436watchTrees :: NonEmpty (Array Word8) -> SerialT IO Event
465watchTrees = watchTreesWith id
437watchTrees = watchTreesWith id
467−-- | Add a trailing "\" at the end of the path if there is none. Do not add a
439+-- | Start monitoring a list of file system paths for file system events with
468−-- "\" if the path is empty.
440+-- the supplied recursive mode and configuration. The paths could be files or
441+-- directories. When recursive mode is True and the path is a directory, the
442+-- whole directory tree under it is watched recursively.
443+-- When recursive mode is False and the path is a directory, only the
444+-- files and directories directly under the watched directory are monitored,
445+-- contents of subdirectories are not monitored. Monitoring starts from the
446+-- current time onwards. The paths are specified as UTF-8 encoded 'Array' of
451+-- ('setModifiedAttribute' On . 'setModifiedLastWrite' Off) defaultConfig
452+-- [Array.fromCString\# "dir"#]
470−ensureTrailingSlash :: String -> String
457+watch :: Bool -> Config -> NonEmpty (Array Word8) -> SerialT IO Event
471−ensureTrailingSlash path =
458+watch rec cfg paths =
472− if null path
459+ case rec of
473− then path
460+ True -> watchTreesWith (\_ -> cfg) paths
474− else
461+ False -> watchTreesWith (\_ -> setRecursiveMode False cfg) paths
476− in if x /= '\\' && x /= '/'
480getFlag :: DWORD -> Event -> Bool
463getFlag :: DWORD -> Event -> Bool
481getFlag mask Event{..} = eventFlags == mask
464getFlag mask Event{..} = eventFlags == mask
@@ -487,8 +470,8 @@ getFlag mask Event{..} = eventFlags == mask
488-- /Pre-release/
471-- /Pre-release/
490−getRelPath :: Event -> String
473+getRelPath :: Event -> Array Word8
491−getRelPath Event{..} = eventRelPath
474+getRelPath Event{..} = (UTF8.toArray . UTF8.pack) eventRelPath
493-- XXX Change the type to Array Word8 to make it compatible with other APIs.
476-- XXX Change the type to Array Word8 to make it compatible with other APIs.
@@ -496,17 +479,10 @@ getRelPath Event{..} = eventRelPath
497-- /Pre-release/
480-- /Pre-release/
499−getRoot :: Event -> String
482+getRoot :: Event -> Array Word8
500−getRoot Event{..} = ensureTrailingSlash eventRootPath
483+getRoot Event{..} = (UTF8.toArray . UTF8.pack) eventRootPath
502−-- XXX Change the type to Array Word8 to make it compatible with other APIs.
504−-- | Get the absolute file system object path for which the event is generated.
505−-- The path is a UTF-8 encoded array of bytes.
509−getAbsPath :: Event -> String
485+getAbsPath :: Event -> Array Word8
510getAbsPath ev = getRoot ev <> getRelPath ev
486getAbsPath ev = getRoot ev <> getRelPath ev
512-- XXX need to document the exact semantics of these.
488-- XXX need to document the exact semantics of these.
@@ -568,9 +544,8 @@ isOverflow Event{..} = totalBytes == 0
568showEvent :: Event -> String
544showEvent :: Event -> String
569showEvent ev@Event{..} =
545showEvent ev@Event{..} =
570 "--------------------------"
546 "--------------------------"
571− ++ "\nRoot = " ++ show (getRoot ev)
547+ ++ "\nRoot = " ++ utf8ToString (getRoot ev)
572− ++ "\nRelative Path = " ++ show (getRelPath ev)
548+ ++ "\nPath = " ++ utf8ToString (getRelPath ev)
573− ++ "\nAbsolute Path = " ++ show (getAbsPath ev)
574 ++ "\nFlags " ++ show eventFlags
549 ++ "\nFlags " ++ show eventFlags
575 ++ showev isOverflow "Overflow"
550 ++ showev isOverflow "Overflow"
576 ++ showev isCreated "Created"
551 ++ showev isCreated "Created"