On MacOS, Dir.tmpdir gives me a folder inside "/var/folders/". However,
/var is a symlink to /private/var.
Previously, the nonexistent directory test would fail because it was
initialized with /var/folders/... but the filenames from listen would be
the realpaths.
This commit normalizes the dirs by calling realpath on them if they
exist. This is done on boot!, so it will work with newly directories
through the symlink.
`EventedFileUpdateChecker` will search the parent directory if the
specified directory does not exist.
Since `test/mailers/previews` is included in the watch target by default,
if there is no test directory (e.g. using `rspec`), the Rails root directory
will be included in the watch target.
```
$ rails new app
$ cd app
$ ./bin/rails r "p Rails.application.reloaders.last.send(:directories_to_watch).include?(Rails.root)"
false
$ rm -rf test
$ ./bin/rails r "p Rails.application.reloaders.last.send(:directories_to_watch).include?(Rails.root)"
true
```
This causes `node_modules` to be included in watch target. Adding parent
directories to watch target may include unexpected directories.
In order to avoid this, fixed that parents of nonexistent directories are
not added to the watch targets, instead checking that the directory
exists when checking changes.
Related to #32700.
[Matthew Draper & Yuji Yaginuma]
Currently, executing the `test_initialize_raises_an_ArgumentError_if_no_block_given`
test alone will result in an error.
```
$ ./bin/test test/evented_file_update_checker_test.rb -n test_initialize_raises_an_ArgumentError_if_no_block_given
Run options: -n test_initialize_raises_an_ArgumentError_if_no_block_given --seed 6692
# Running:
E
Error:
EventedFileUpdateCheckerTest#test_initialize_raises_an_ArgumentError_if_no_block_given:
NameError: uninitialized constant EventedFileUpdateCheckerTest::Listen
rails/activesupport/test/evented_file_update_checker_test.rb:21:in `teardown'
```
This is because if do not specify a file or directory for
`EventedFileUpdateChecker`, do not require `listen`, and using listen
method in teardown.
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/evented_file_update_checker.rb#L53..L65
Therefore, added listen's require to avoid errors.
Pretty proud of this. We are testing distributed processes synchronized via pipes which makes it deterministic. Pretty cool.
We boot a listener in the parent process we then fork. Before we touch the file we verify the fork is booted using pipes. Then the parent process will touch the file while the fork waits on a pipe. Once the parent process signals that the file has been touched we continue inside of the fork.
We need one file checker booted per process as talked about in #24990. Before we do a check to see if any updates have been registered by the listener we first check to make sure that the current process has booted a listener.
We are intentionally not starting a listener when the checker is created. This way we can avoid #25259 in which puma warns of multiple threads created before fork. As written the listener for each process will be invoked by the `ActionDispatch::Executor` middleware when the `updated?` method is called. This is the first middleware on the stack and will be invoked before application code is read into memory.
The downside of this approach is that the API is a little less obvious. I.e. that you have to call `updated?` to get the listener to start is not intuitive. We could make `boot!` not private if we want to make the API a little nicer. Alternatively we could boot when the checker is initialized however this reintroduces the puma threads warning, and also means that in cases of `rails server` or when using `preload!` that we have extra threads notifying of changes on a process that we don't care about.
[close#24990] [close#25259]