Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Listen 3x proposal #318

Merged
merged 47 commits into from
Jun 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
bdc4120
drop Ruby 1.9 build in Travis
e2 Jun 12, 2015
39aa8f5
fix exception message in threaded Adapter
e2 Jun 12, 2015
4df8c9e
remove TCP functionality for Listen 3.x
e2 Jun 12, 2015
d0c29d4
refactor record to contain one watched dir
e2 Jun 12, 2015
a41ab6a
avoid hitchhiking Celluloid's Logger
e2 Jun 12, 2015
23ad1b2
make QueueOptimizer a proper, independent class
e2 Jun 12, 2015
1690e16
refactor Listener with Silencer::Controller class
e2 Jun 12, 2015
5e9c0a8
refactor out callback loop to EventProcessor class
e2 Jun 12, 2015
4b61fa8
refactor record to contain one watched dir
e2 Jun 12, 2015
2853f17
remove Celluloid
e2 Jun 12, 2015
83e24e2
rework Listener spec
e2 Jun 12, 2015
f765f7f
add fake_path spec helper
e2 Jun 14, 2015
e91c764
add new refactored Event::* classes
e2 Jun 14, 2015
40536d7
add Backend class for handling adapters
e2 Jun 14, 2015
1f5d17a
add Adapter::Config class
e2 Jun 14, 2015
43f4e39
add Listener::Config class
e2 Jun 14, 2015
a79969b
allow using installed Listen in dev
e2 Jun 14, 2015
f8f406e
Guardfile: run acceptance specs after normal specs
e2 Jun 14, 2015
c31bb87
clear up logging functionality
e2 Jun 14, 2015
666c2bb
rework Adapter to use Record and Config
e2 Jun 14, 2015
29dc723
make wait_for_delay default adapter specific
e2 Jun 14, 2015
309a3f6
fix Linux adapter specs
e2 Jun 14, 2015
4e825ee
add TODO for polling
e2 Jun 14, 2015
f5bf958
add TODOs for Change
e2 Jun 14, 2015
3ae5098
allow Change to use Silencer and Queue directly
e2 Jun 14, 2015
1347ceb
rename Change#change to #invalidate
e2 Jun 14, 2015
c3ea159
remove TODO
e2 Jun 14, 2015
8c3899c
use processing? instead of nice but ambiguous listen?
e2 Jun 14, 2015
eda455d
cosmetic changes in Directory
e2 Jun 14, 2015
bee701b
try to be a bit smarter at detecting type
e2 Jun 14, 2015
bfd49cb
allow ThreadPool to work with stubs
e2 Jun 14, 2015
a176745
rework and reduce Listener class
e2 Jun 14, 2015
39981ec
remove TCP-related local_fs? methods
e2 Jun 14, 2015
a7b9f67
allow choosing poling/native acceptance tests
e2 Jun 14, 2015
80a57f9
rework Adapter spec to test Record usage
e2 Jun 14, 2015
52a54ff
fix/improve Darwin specs for Record usage
e2 Jun 14, 2015
ca19d3d
fix and improve Linux adapter for Record usage
e2 Jun 14, 2015
f738db7
refactor and update Directory spec
e2 Jun 14, 2015
76c3b64
rework and update Listener spec
e2 Jun 14, 2015
3f34579
completely rework QueueOptimizer spec
e2 Jun 14, 2015
d679604
let acceptance specs bypass Listen API
e2 Jun 14, 2015
937c008
fix typo
e2 Jun 15, 2015
7bfdcce
avoid inspecting inotify events when not debugging
e2 Jun 26, 2015
d6ba1b2
give events time to accumulate in Polling
e2 Jun 26, 2015
9c57303
bump MRI to 2.2.2 on Travis
e2 Jun 26, 2015
bf98fc8
bump RSpec version in Gemfile
e2 Jun 26, 2015
0696aa0
remove rspec-retry due to RSpec monkeypatching
e2 Jun 26, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
language: ruby
bundler_args: --without development
rvm:
- 1.9.3
- 2.2.0
- 2.2.2
- jruby
- rbx-2
matrix:
Expand All @@ -18,5 +17,5 @@ os:
- linux
- osx
env:
- LISTEN_TESTS_DEFAULT_LAG=0.8 LISTEN_TESTS_DEFAULT_TCP_LAG=1.2
- LISTEN_TESTS_DEFAULT_LAG=0.8
sudo: false
15 changes: 9 additions & 6 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
source 'https://rubygems.org'

gemspec development_group: :gem_build_tools
# Create this file to use pristine/installed version of Listen for development
use_installed = "./use_installed_guard"
if File.exist?(use_installed)
STDERR.puts "WARNING: using installed version of Listen for development" \
" (remove #{use_installed} file to use local version)"
else
gemspec development_group: :gem_build_tools
end

require 'rbconfig'

case RbConfig::CONFIG['target_os']
when /mswin|mingw|cygwin/i
gem 'wdm', '>= 0.1.0'
Kernel.warn 'NOTE: Celluloid may not work properly on your platform'
when /bsd|dragonfly/i
gem 'rb-kqueue', '>= 0.2'
end

group :test do
gem 'celluloid', github: 'celluloid/celluloid', branch: '0-16-stable'
gem 'celluloid-io', '>= 0.15.0'
gem 'rake'
gem 'rspec', '~> 3.2'
gem 'rspec-retry'
gem 'rspec', '~> 3.3'
gem 'coveralls'
end

Expand Down
14 changes: 12 additions & 2 deletions Guardfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ignore(%r{spec/\.fixtures/})

group :specs, halt_on_fail: true do
guard :rspec, cmd: 'bundle exec rspec', failed_mode: :keep do
watch(%r{^spec/.+_spec\.rb$})
guard :rspec, cmd: 'bundle exec rspec -t ~acceptance', failed_mode: :keep, all_after_pass: true do
watch(%r{^spec/lib/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^spec/support/*}) { 'spec' }
watch('spec/spec_helper.rb') { 'spec' }
Expand All @@ -13,4 +13,14 @@ group :specs, halt_on_fail: true do
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
watch(%r{(?:.+/)?\.rubocop_todo\.yml$}) { |m| File.dirname(m[0]) }
end

# TODO: guard rspec should have a configurable file for this to work
# TODO: also split up Rakefile
guard :rspec, cmd: 'bundle exec rspec -t acceptance', failed_mode: :keep, all_after_pass: true do
watch(%r{^spec/lib/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^spec/support/*}) { 'spec' }
watch('spec/spec_helper.rb') { 'spec' }
watch(%r{^spec/acceptance/.+_spec\.rb$})
end
end
46 changes: 3 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ Make sure you know these few basic tricks: https://github.com/guard/listen/wiki/
* Detects file modification, addition and removal.
* You can watch multiple directories.
* Regexp-patterns for ignoring paths for more accuracy and speed
* Forwarding file events over TCP, [more info](#forwarding-file-events-over-tcp) below.
* Increased change detection accuracy on OS X HFS and VFAT volumes.
* Tested on MRI Ruby environments (1.9+ only) via [Travis CI](https://travis-ci.org/guard/listen),

Expand All @@ -29,6 +28,8 @@ Please note that:
- Specs suite on JRuby and Rubinius aren't reliable on Travis CI, but should work.
- Windows and \*BSD adapter aren't continuously and automaticaly tested.

NOTE: TCP functionality has been moved to a separate gem (listen-server and listen-client)

## Pending features / issues

* symlinked directories aren't fully transparent yet: https://github.com/guard/listen/issues/279
Expand Down Expand Up @@ -166,7 +167,7 @@ force_polling: true # Force the use of the polling a
relative: false # Whether changes should be relative to current dir or not
# default: false

debug: true # Enable Celluloid logger
debug: true # Enable Listen logger
# default: false

polling_fallback_message: 'custom message' # Set a custom polling fallback message (or disable it with false)
Expand Down Expand Up @@ -247,47 +248,6 @@ Also, if the directories you're watching contain many files, make sure you're:

When in doubt, LISTEN_GEM_DEBUGGING=2 can help discover the actual events and time they happened.

## Forwarding file events over TCP

Listen is capable of forwarding file events over the network using a messaging protocol. This can be useful for virtualized development environments when file events are unavailable, as is the case with shared folders in VMs.

[Vagrant](https://github.com/mitchellh/vagrant) uses Listen in it's rsync-auto mode to solve this issue.

To broadcast events over TCP programmatically, use the `forward_to` option with an address - just a port or a hostname/port combination:

```ruby
listener = Listen.to 'path/to/app', forward_to: '10.0.0.2:4000' do |modified, added, removed|
# After broadcasting the changes to any connected recipients,
# this block will still be called
end
listener.start
sleep
```

As a convenience, the `listen` script is supplied which listens to a directory and forwards the events to a network address

```bash
listen -f "10.0.0.2:4000" # changes in current directory are sent as absolute paths
listen -r -f "10.0.0.2:4000" # changes in current directory are sent as relative paths
listen -v -d "/projects/my_project" -f "10.0.0.2:4000" # changes in given directory are also shown
```

*NOTE: if you are using a gem like `guard` and the paths on host and guest are not exactly the same, you'll generally want to use the `-r` option for relative paths*

To connect to a broadcasting listener as a recipient, specify its address using `Listen.on`:

```ruby
listener = Listen.on '10.0.0.2:4000' do |modified, added, removed|
# This block will be called
end
listener.start
sleep
```

### Security considerations

Since file events potentially expose sensitive information, care must be taken when specifying the broadcaster address. It is recommended to **always** specify a hostname and make sure it is as specific as possible to reduce any undesirable eavesdropping.

## Development

* Documentation hosted at [RubyDoc](http://rubydoc.info/github/guard/listen/master/frames).
Expand Down
59 changes: 19 additions & 40 deletions lib/listen.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
require 'celluloid'
require 'logger'
require 'listen/logger'
require 'listen/listener'

require 'listen/internals/thread_pool'

# Always set up logging by default first time file is required
#
# NOTE: If you need to clear the logger completely, do so *after*
# requiring this file. If you need to set a custom logger,
# require the listen/logger file and set the logger before requiring
# this file.
Listen.setup_default_logger_if_unset

# Won't print anything by default because of level - unless you've set
# LISTEN_GEM_DEBUGGING or provided your own logger with a high enough level
Listen::Logger.info "Listen loglevel set to: #{Listen.logger.level}"
Listen::Logger.info "Listen version: #{Listen::VERSION}"

module Listen
class << self
# Listens to file system modifications on a either single directory or
# multiple directories.
#
# When :forward_to is specified, this listener will broadcast modifications
# over TCP.
#
# @param (see Listen::Listener#new)
#
# @yield [modified, added, removed] the changed files
Expand All @@ -21,18 +32,12 @@ class << self
# @return [Listen::Listener] the listener
#
def to(*args, &block)
Celluloid.boot unless Celluloid.running?
options = args.last.is_a?(Hash) ? args.last : {}
target = options.delete(:forward_to)
args = ([target, :broadcaster] + args) if target
_add_listener(*args, &block)
@listeners ||= []
Listener.new(*args, &block).tap do |listener|
@listeners << listener
end
end

# Stop all listeners & Celluloid
#
# Use it for testing purpose or when you are sure that Celluloid could be
# ended.
#
# This is used by the `listen` binary to handle Ctrl-C
#
def stop
Expand All @@ -45,32 +50,6 @@ def stop
listener.stop
end
@listeners = nil

Celluloid.shutdown
end

# Listens to file system modifications broadcast over TCP.
#
# @param [String/Fixnum] target to listen on (hostname:port or port)
#
# @yield [modified, added, removed] the changed files
# @yieldparam [Array<String>] modified the list of modified files
# @yieldparam [Array<String>] added the list of added files
# @yieldparam [Array<String>] removed the list of removed files
#
# @return [Listen::Listener] the listener
#
def on(target, *args, &block)
_add_listener(target, :recipient, *args, &block)
end

private

def _add_listener(*args, &block)
@listeners ||= []
Listener.new(*args, &block).tap do |listener|
@listeners << listener
end
end
end
end
4 changes: 1 addition & 3 deletions lib/listen/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ module Adapter
'Learn more at https://github.com/guard/listen#listen-adapters.'

def self.select(options = {})
_log :debug, 'Adapter: considering TCP ...'
return TCP if options[:force_tcp]
_log :debug, 'Adapter: considering polling ...'
return Polling if options[:force_polling]
_log :debug, 'Adapter: considering optimized backend...'
Expand All @@ -39,7 +37,7 @@ def self._warn_polling_fallback(options)
end

def self._log(type, message)
Celluloid::Logger.send(type, message)
Listen::Logger.send(type, message)
end
end
end
Loading