Repository navigation
feat(cabal-install): add --watch to common commands (GNU/Linux-only) - #12485
blackheaven wants to merge 2 commits into
Conversation
10885da to
99dd310
Compare
Bodigrim
left a comment
There was a problem hiding this comment.
Very interesting! Are build-type: Custom and build-type: Hooks supported?
| manual: True | ||
|
|
||
| flag fswatch | ||
| description: Enable the --watch flag (adds the fsnotify dependency, Linux only) |
There was a problem hiding this comment.
Why do we need to hide fsnotify behind the flag? It's not a particularly huge dependency from the look at it, and it's better not to introduce new flags if we can do without them.
There was a problem hiding this comment.
I have introduced the flag exists purely to keep the bootstrap plans (bootstrap/linux-*.json) unchanged. Bootstrap builds must be buildable from the pinned plan alone, and adding fsnotify unconditionally pulled in hinotify (Linux-only) plus ~10 transitive deps — which broke the Bootstrap macos-15 CI job.
I can investigate, but I do not have a Macintosh to test.
There was a problem hiding this comment.
I don't see how if os(linux) build-depends: fsnotify could affect build plans for macOS. Updating pinned bootstrap plans is not a big deal.
|
|
||
| if os(linux) && flag(fswatch) | ||
| build-depends: fsnotify >= 0.4.1 && < 0.5 | ||
| cpp-options: -DHAVE_FSWATCH |
There was a problem hiding this comment.
No need to pass an additional CPP option, you can check #ifdef MIN_VERSION_fsnotify.
| -- | File extensions for which a @create@ event in an already-watched source | ||
| -- directory triggers a re-run (handles newly created module files). | ||
| watchCreateExtensions :: [String] | ||
| watchCreateExtensions = |
There was a problem hiding this comment.
The list lacks Alex and Happy file extensions. Is it possible to come up with a more principled approach, which does not require to hardcode such a list?
| -- (so that newly written modules trigger a rebuild). | ||
| watchEventRelevant :: [FilePath] -> WatchEventInfo -> Bool | ||
| watchEventRelevant names (path, isCreate) = | ||
| fileName `elem` names |
There was a problem hiding this comment.
I imagine names can get rather large, at which point linear search through a list of strings with repeated prefixes will become slow.
| watchEventRelevant :: [FilePath] -> WatchEventInfo -> Bool | ||
| watchEventRelevant names (path, isCreate) = | ||
| fileName `elem` names | ||
| || (isCreate && takeExtension path `elem` watchCreateExtensions) |
There was a problem hiding this comment.
Will a newly created file, which was not there when the --watch started, be tracked for subsequent changes? Which part of the code enables this?
There was a problem hiding this comment.
Yes. Watchers are per-directory, not per-file: filesToDirWatches + groupDirWatches register one watchDir per parent directory of the watched files, and inotify reports events for the whole directory.
The first event of a new file
arrives as Added and passes watchEventRelevant via the create-extension rule (Added{} → True + extension in watchCreateExtensions) — that's the part that catches the creation itself.
Yes, at the same fidelity as cabal's own change detection. |
- Rethrow failures from the watched command verbatim once the watcher is started instead of mislabeling them as WatchStartFailed - Make the debounce drain actually block for the coalescing window (tryReadTChan never retried, so bursts caused double rebuilds) - Collapse an unreachable nested try in watchLoop (ExitCode is a SomeException); merge the now-redundant unit test - Watch the source directory itself in the MonitorFileGlob fallback - Document that reruns reuse the startup-time elaborated plan and that install --watch effectively watches only per-package files
99dd310 to
64b9f93
Compare
Add a
--watchoptions to auto-launch some commandssignificance: significantin the changelog file.Manual QA notes
Tested on GNU/Linux (NixOS, GHC 9.10.3):
cabal build --watch: initial build runs; appending to a watched sourcefile triggers
File ... changed, re-running...and a rebuild; a failingrebuild is reported and the watcher keeps running; Ctrl-C stops it.
cabal sdist --watch: touchingp.cabalre-generates the tarball.cabal check --watch: a failing re-check (introduced warning) is reportedand the watcher keeps watching (the loop catches
ExitCodeas well assynchronous exceptions; a Ctrl-C during a re-run still terminates).
v1-install --watchfails immediately withError: [Cabal-7170] The '--watch' flag is not supported by the 'v1-install' command.--watchis accepted (but ignored) by other nix-style commands such asfreeze/path, mirroring the--dry-runprecedent; it is excluded fromthe saved user config.
command dies immediately with
Error: [Cabal-7169] The '--watch' flag is only supported on Linux.