2-- Module : Streamly.FileSystem.Event
3-- Copyright : (c) 2020 Composewell Technologies
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
6-- Stability : pre-release
9-- File system event notification API portable across Linux, macOS and Windows
12-- Note that recursive directory tree watch does not work reliably on Linux
13-- (see notes in the Linux module), therefore, recursive watch API is not
14-- provided in this module. However, you can use it from the platform specific
17-- For platform specific APIs please see the following modules:
19-- * "Streamly.Internal.FileSystem.Event.Darwin"
20-- * "Streamly.Internal.FileSystem.Event.Linux"
21-- * "Streamly.Internal.FileSystem.Event.Windows"
23-- XXX Need to ensure that the signatures of the exported APIs are same on all
26module Streamly.Internal.FileSystem.Event
37 -- ** Item CRUD events
43 -- ** Exception Conditions
51import Data.List.NonEmpty (NonEmpty)
52import Data.Word (Word8)
53import Streamly.Data.Array (Array)
54import Streamly.Data.Stream (Stream)
56#if defined(CABAL_OS_DARWIN)
57import Streamly.Internal.FileSystem.Event.Darwin (Event)
58import qualified Streamly.Internal.FileSystem.Event.Darwin as Event
59#elif defined(CABAL_OS_LINUX)
60import Streamly.Internal.FileSystem.Event.Linux (Event)
61import qualified Streamly.Internal.FileSystem.Event.Linux as Event
62#elif defined(CABAL_OS_WINDOWS)
63import Streamly.Internal.FileSystem.Event.Windows (Event)
64import qualified Streamly.Internal.FileSystem.Event.Windows as Event
66#error "FS Events not supported on this platform"
69-- XXX Ensure that defaultConfig is the same for all platforms.
71-- XXX Ensure that equivalent events are generated on all platforms when same
72-- operations are done. Document any differences in behavior on different
73-- platforms. Any events that are not common to all platforms should be
76-- XXX Only need to set common event types for macOS/Linux/Windows
77-- XXX write a test, that generates all types of events that can possibly
78-- occur on each platform. Then create a common test that only checks
79-- for the common subset of those.
81-------------------------------------------------------------------------------
83-------------------------------------------------------------------------------
85-- macOS and Windows seem to do a path level watch i.e. they watch the path
86-- rather than the underlying inode, possibly they can map the inode back to a
87-- path?. On Linux we cannot keep watching a watch root if the inode it is
88-- pointing to has moved. However, the inode continues to be watched in this
89-- case instead of the path, which is not the case for macOS.
91-- To make the behavior same for all platforms, for the Linux case we will have
92-- to stop watching the inode if it moves from under the path
93-- (setUnwatchMoved). And on macOS we can stop watching a path if the inode
94-- under it changes i.e. just filter out events for that path.
96-- Also, to make the behavior of Linux same as macOS we need to set
97-- setFollowSymLinks on Linux.
99-- XXX Verify all the cases mentioned below using test cases.
100-- XXX Make it fail if the watch root is a file. It works on macOS and Linux
101-- but does not work on Windows.
103-- | Start monitoring a list of directories or symbolic links to directories
104-- for file system events. Monitoring starts from the current time onwards.
105-- The paths are specified as UTF-8 encoded 'Array' of 'Word8'.
107-- If a watch root is a symbolic link then the target of the link is watched.
108-- Fails if the watched path does not exist. If the user does not have
109-- permissions (read and execute?) on the watch root then no events are
110-- generated. No events are generated if the watch root itself is renamed or
113-- This API watches for changes in the watch root directory only, any changes
114-- in the subdirectories of the watch root are not watched. However, on macOS
115-- the watch is always recursive, but do not rely on that behavior, it may
116-- change without notice in future. If you want to use recursive watch please
117-- use platform specific modules.
121watch :: NonEmpty (Array Word8) -> Stream IO Event
122#if defined(CABAL_OS_DARWIN)
123watch = Event.watchRecursive
128-- | Like 'watch' except that if a watched path is a directory the whole
129-- directory tree under it is watched recursively.
131-- On Linux 'watchRecursive' may be more expensive than 'watch'.
135_watchRecursive :: NonEmpty (Array Word8) -> Stream IO Event
136_watchRecursive = Event.watchRecursive
138-------------------------------------------------------------------------------
140-------------------------------------------------------------------------------
142-- XXX Ensure that on all paltforms the path has same conventions. That is do
143-- not have a trailing path separator on one platfrom and not on another.
145-- XXX We should use getRelPath instead so that the behavior when the root is a
146-- symlink becomes platform independent.
148-- | Get the absolute path of the file system object for which the event is
149-- generated. The path is a UTF-8 encoded array of bytes.
151-- When the watch root is a symlink the behavior is different on different
154-- * On Linux and Windows, the absolute path returned is via the original
157-- * On macOS the absolute path returned is via the real path of the root after
158-- resolving the symlink.
160-- This API is subject to removal in future, to be replaced by a platform
161-- independent @getRelPath@.
165getAbsPath :: Event -> Array Word8
166getAbsPath = Event.getAbsPath
168-- | Determine whether the event indicates creation of an object within the
169-- monitored path. This event is generated when any file system object is
172-- For hard links the behavior is different on different operating systems. On
173-- macOS hard linking does not generate a create event, it generates an
174-- 'isInodeAttrsChanged' event on the directory instead (see the Darwin
175-- module). On Linux and Windows hard linking generates a create event.
179isCreated :: Event -> Bool
180isCreated = Event.isCreated
182-- XXX To make the behavior consistent, can we block the event on watch root on
185-- | Determine whether the event indicates deletion of an object within the
186-- monitored path. On Linux and Windows hard link deletion generates a delete
189-- On Linux and Windows, this event does not occur when the watch root itself
190-- is deleted. On macOS it occurs on deleting the watch root when it is not a
193-- See also 'isRootDeleted' event for Linux.
197isDeleted :: Event -> Bool
198isDeleted = Event.isDeleted
200-- | Determine whether the event indicates rename of an object within the
201-- monitored path. This event is generated when an object is renamed within the
202-- watched directory or if it is moved out of or in the watched directory.
203-- Moving hard links is no different than other types of objects.
207isMoved :: Event -> Bool
208isMoved = Event.isMoved
210-- XXX Make the Windows behavior consistent with other platforms by removing
211-- the event from directories.
213-- | Determine whether the event indicates modification of an object within the
214-- monitored path. This event is generated on file modification on all
217-- On Linux and macOS this event is never generated for directories. On
218-- Windows (in recursive watch mode) this event is generated for directories as
219-- well when an object is created in or deleted from the directory.
223isModified :: Event -> Bool
224isModified = Event.isModified
226-- | An event that indicates that some events before this may have been lost,
227-- therefore, we need to take some recovery action.
231isEventsLost :: Event -> Bool
232isEventsLost = Event.isEventsLost
234-------------------------------------------------------------------------------
236-------------------------------------------------------------------------------
238-- | Convert an 'Event' record to a String representation. Note that the output
239-- of this function may be different on different platforms because it may
240-- contain platform specific details.
244showEvent :: Event -> String
245showEvent = Event.showEvent
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list