notify/
config.rs

1//! Configuration types
2
3use std::time::Duration;
4
5/// Indicates how the path should be watched
6#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
7pub struct WatchMode {
8    /// Indicates whether to watch sub-directories as well
9    pub recursive_mode: RecursiveMode,
10    /// Indicates what happens when the relationship of the physical entity and the file path changes
11    pub target_mode: TargetMode,
12}
13
14impl WatchMode {
15    /// Creates a WatchMode that watches directories recursively and tracks the file path
16    pub fn recursive() -> Self {
17        Self {
18            recursive_mode: RecursiveMode::Recursive,
19            target_mode: TargetMode::TrackPath,
20        }
21    }
22
23    /// Creates a WatchMode that watches only the provided directory and tracks the file path
24    pub fn non_recursive() -> Self {
25        Self {
26            recursive_mode: RecursiveMode::NonRecursive,
27            target_mode: TargetMode::TrackPath,
28        }
29    }
30
31    pub(crate) fn upgrade_with(&mut self, other: WatchMode) {
32        self.recursive_mode = self.recursive_mode.upgraded_with(other.recursive_mode);
33        self.target_mode = self.target_mode.upgraded_with(other.target_mode);
34    }
35}
36
37/// Indicates whether only the provided directory or its sub-directories as well should be watched
38#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
39pub enum RecursiveMode {
40    /// Watch all sub-directories as well, including directories created after installing the watch
41    Recursive,
42
43    /// Watch only the provided directory
44    NonRecursive,
45}
46
47impl RecursiveMode {
48    pub(crate) fn is_recursive(&self) -> bool {
49        match *self {
50            RecursiveMode::Recursive => true,
51            RecursiveMode::NonRecursive => false,
52        }
53    }
54
55    pub(crate) fn upgraded_with(self, other: Self) -> Self {
56        match self {
57            RecursiveMode::Recursive => self,
58            RecursiveMode::NonRecursive => {
59                if other == RecursiveMode::Recursive {
60                    other
61                } else {
62                    self
63                }
64            }
65        }
66    }
67}
68
69/// Indicates what happens when the relationship of the physical entity and the file path changes
70#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
71pub enum TargetMode {
72    /// Tracks the file path.
73    ///
74    /// If the underlying physical entity (inode/File ID) at this path is replaced
75    /// (e.g., by a move/rename operation), the watch continues to monitor the new entity
76    /// that now occupies the path.
77    ///
78    /// TODO: watching nested non-existent paths is not implemented yet. <https://github.com/rolldown/notify/issues/32>
79    TrackPath,
80
81    /// Does not track the file path, nor the physical entity.
82    ///
83    /// If the underlying physical entity (inode/File ID) is replaced
84    /// (e.g., by a move/rename operation), the watch stops monitoring.
85    ///
86    /// TODO: fsevents backend and Windows backend does not unwatch on physical entity change yet. <https://github.com/rolldown/notify/issues/33>
87    NoTrack,
88}
89
90impl TargetMode {
91    pub(crate) fn upgraded_with(self, other: Self) -> Self {
92        match self {
93            TargetMode::TrackPath => self,
94            TargetMode::NoTrack => {
95                if other == TargetMode::TrackPath {
96                    other
97                } else {
98                    self
99                }
100            }
101        }
102    }
103}
104
105/// Watcher Backend configuration
106///
107/// This contains multiple settings that may relate to only one specific backend,
108/// such as to correctly configure each backend regardless of what is selected during runtime.
109///
110/// ```rust
111/// # use std::time::Duration;
112/// # use notify::Config;
113/// let config = Config::default()
114///     .with_poll_interval(Duration::from_secs(2))
115///     .with_compare_contents(true);
116/// ```
117///
118/// Some options can be changed during runtime, others have to be set when creating the watcher backend.
119#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
120pub struct Config {
121    /// See [Config::with_poll_interval]
122    poll_interval: Option<Duration>,
123
124    /// See [Config::with_compare_contents]
125    compare_contents: bool,
126
127    follow_symlinks: bool,
128}
129
130impl Config {
131    /// For the [`PollWatcher`](crate::PollWatcher) backend.
132    ///
133    /// Interval between each re-scan attempt. This can be extremely expensive for large
134    /// file trees so it is recommended to measure and tune accordingly.
135    ///
136    /// The default poll frequency is 30 seconds.
137    ///
138    /// This will enable automatic polling, overwriting [`with_manual_polling()`](Config::with_manual_polling).
139    pub fn with_poll_interval(mut self, dur: Duration) -> Self {
140        // TODO: v7.0 break signature to option
141        self.poll_interval = Some(dur);
142        self
143    }
144
145    /// Returns current setting
146    pub fn poll_interval(&self) -> Option<Duration> {
147        // Changed Signature to Option
148        self.poll_interval
149    }
150
151    /// For the [`PollWatcher`](crate::PollWatcher) backend.
152    ///
153    /// Disable automatic polling. Requires calling [`crate::PollWatcher::poll()`] manually.
154    ///
155    /// This will disable automatic polling, overwriting [`with_poll_interval()`](Config::with_poll_interval).
156    pub fn with_manual_polling(mut self) -> Self {
157        self.poll_interval = None;
158        self
159    }
160
161    /// For the [`PollWatcher`](crate::PollWatcher) backend.
162    ///
163    /// Optional feature that will evaluate the contents of changed files to determine if
164    /// they have indeed changed using a fast hashing algorithm.  This is especially important
165    /// for pseudo filesystems like those on Linux under /sys and /proc which are not obligated
166    /// to respect any other filesystem norms such as modification timestamps, file sizes, etc.
167    /// By enabling this feature, performance will be significantly impacted as all files will
168    /// need to be read and hashed at each `poll_interval`.
169    ///
170    /// This can't be changed during runtime. Off by default.
171    pub fn with_compare_contents(mut self, compare_contents: bool) -> Self {
172        self.compare_contents = compare_contents;
173        self
174    }
175
176    /// Returns current setting
177    pub fn compare_contents(&self) -> bool {
178        self.compare_contents
179    }
180
181    /// For the [INotifyWatcher](crate::INotifyWatcher), [KqueueWatcher](crate::KqueueWatcher),
182    /// and [PollWatcher](crate::PollWatcher).
183    ///
184    /// Determine if symbolic links should be followed when recursively watching a directory.
185    ///
186    /// This can't be changed during runtime. On by default.
187    pub fn with_follow_symlinks(mut self, follow_symlinks: bool) -> Self {
188        self.follow_symlinks = follow_symlinks;
189        self
190    }
191
192    /// Returns current setting
193    pub fn follow_symlinks(&self) -> bool {
194        self.follow_symlinks
195    }
196}
197
198impl Default for Config {
199    fn default() -> Self {
200        Self {
201            poll_interval: Some(Duration::from_secs(30)),
202            compare_contents: false,
203            follow_symlinks: true,
204        }
205    }
206}