Skip to content

Commit 54e5c38

Browse files
committed
Fix watch batch cancellation flake
1 parent 8cc2141 commit 54e5c38

4 files changed

Lines changed: 239 additions & 138 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ All notable changes to `devloop` will be recorded in this file.
1717
patterns and asks the backend to watch only those files or
1818
directories instead of always watching the whole repository root.
1919

20+
### Fixed
21+
- Native watch registration now resolves file and directory targets at
22+
runtime, so startup no longer depends on those paths already existing
23+
when config is parsed.
24+
2025
## [0.7.0] - 2026-03-27
2126

2227
### Added

src/config.rs

Lines changed: 7 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -133,17 +133,10 @@ impl Config {
133133
}
134134

135135
pub fn compiled_watch_targets(&self) -> Vec<CompiledWatchTarget> {
136-
self.compiled_watch_targets_for(self.watcher.kind)
137-
}
138-
139-
pub fn compiled_watch_targets_for(
140-
&self,
141-
watcher_kind: WatcherKind,
142-
) -> Vec<CompiledWatchTarget> {
143136
let mut targets = BTreeMap::<PathBuf, bool>::new();
144137
for group in self.watch.values() {
145138
for pattern in &group.paths {
146-
let target = CompiledWatchTarget::from_pattern(&self.root, pattern, watcher_kind);
139+
let target = CompiledWatchTarget::from_pattern(&self.root, pattern);
147140
targets
148141
.entry(target.path)
149142
.and_modify(|recursive| *recursive |= target.recursive)
@@ -286,10 +279,9 @@ impl From<(PathBuf, bool)> for CompiledWatchTarget {
286279
}
287280

288281
impl CompiledWatchTarget {
289-
fn from_pattern(root: &Path, pattern: &str, watcher_kind: WatcherKind) -> Self {
282+
fn from_pattern(root: &Path, pattern: &str) -> Self {
290283
let mut prefix = PathBuf::new();
291284
let mut recursive = false;
292-
let mut saw_dynamic_segment = false;
293285
for segment in pattern.split('/') {
294286
if segment.is_empty() || segment == "." {
295287
continue;
@@ -300,7 +292,6 @@ impl CompiledWatchTarget {
300292
}
301293
if segment_has_glob_magic(segment) {
302294
recursive = true;
303-
saw_dynamic_segment = true;
304295
break;
305296
}
306297
prefix.push(segment);
@@ -314,29 +305,15 @@ impl CompiledWatchTarget {
314305
}
315306

316307
if pattern_is_literal(pattern) {
317-
let candidate = root.join(&prefix);
318-
if candidate.is_dir() {
319-
return Self {
320-
path: candidate,
321-
recursive: true,
322-
};
323-
}
324-
325308
return Self {
326-
path: match watcher_kind {
327-
WatcherKind::Native => candidate
328-
.parent()
329-
.map(Path::to_path_buf)
330-
.unwrap_or_else(|| root.to_path_buf()),
331-
WatcherKind::Poll => candidate,
332-
},
309+
path: root.join(prefix),
333310
recursive: false,
334311
};
335312
}
336313

337314
Self {
338315
path: root.join(prefix),
339-
recursive: recursive || !saw_dynamic_segment && !pattern_is_literal(pattern),
316+
recursive,
340317
}
341318
}
342319
}
@@ -1366,43 +1343,20 @@ mod tests {
13661343
config.compiled_watch_targets(),
13671344
vec![
13681345
CompiledWatchTarget {
1369-
path: PathBuf::from("/tmp/example"),
1346+
path: PathBuf::from("/tmp/example/Cargo.toml"),
13701347
recursive: false,
13711348
},
13721349
CompiledWatchTarget {
13731350
path: PathBuf::from("/tmp/example/content"),
13741351
recursive: true,
13751352
},
1376-
CompiledWatchTarget {
1377-
path: PathBuf::from("/tmp/example/src"),
1378-
recursive: true,
1379-
},
1380-
]
1381-
);
1382-
}
1383-
1384-
#[test]
1385-
fn poll_watch_targets_keep_exact_files_for_literal_patterns() {
1386-
let mut config = base_config();
1387-
config.root = PathBuf::from("/tmp/example");
1388-
config.watch.insert(
1389-
"content".into(),
1390-
WatchGroup {
1391-
paths: vec!["watched.txt".into(), "content/banner.html".into()],
1392-
workflow: Some("content".into()),
1393-
},
1394-
);
1395-
1396-
assert_eq!(
1397-
config.compiled_watch_targets_for(WatcherKind::Poll),
1398-
vec![
13991353
CompiledWatchTarget {
14001354
path: PathBuf::from("/tmp/example/content/banner.html"),
14011355
recursive: false,
14021356
},
14031357
CompiledWatchTarget {
1404-
path: PathBuf::from("/tmp/example/watched.txt"),
1405-
recursive: false,
1358+
path: PathBuf::from("/tmp/example/src"),
1359+
recursive: true,
14061360
},
14071361
]
14081362
);

0 commit comments

Comments
 (0)