Open codylerum opened 11 years ago
On jruby I got this warning message on install:
gem install wdm Fetching: wdm-0.1.0.gem (100%)
Building native extensions. This could take a while...
ERROR: Error installing wdm:
ERROR: Failed to build gem native extension.
/Users/Thibaud/.rbenv/versions/jruby-1.7.3/bin/jruby extconf.rb
NotImplementedError: C extension support is not enabled. Pass -Xcext.enabled=true to JRuby or set JRUBY_OPTS or modify .jrubyrc to enable.
(root) at /Users/Thibaud/.rbenv/versions/jruby-1.7.3/lib/ruby/shared/mkmf.rb:8
require at org/jruby/RubyKernel.java:1027
(root) at /Users/Thibaud/.rbenv/versions/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:1
(root) at extconf.rb:1
Gem files will remain installed in /Users/Thibaud/.rbenv/versions/jruby-1.7.3/lib/ruby/gems/shared/gems/wdm-0.1.0 for inspection.
Results logged to /Users/Thibaud/.rbenv/versions/jruby-1.7.3/lib/ruby/gems/shared/gems/wdm-0.1.0/ext/wdm/gem_make.out
Even if it doesn't work yet on jruby, it would be great if the gem installation was possible for Listen
users. More info: https://github.com/guard/listen/pull/97
Thanks @Maher4Ever !
Just played a bit with the Java 7 WatchService and it's not to hard to make use of the file modification detection on Jruby:
require 'java'
fs = java.nio.file.FileSystems.default
watcher = fs.new_watch_service
path = fs.getPath '/tmp'
path.register(watcher,
java.nio.file.StandardWatchEventKinds::ENTRY_CREATE,
java.nio.file.StandardWatchEventKinds::ENTRY_DELETE,
java.nio.file.StandardWatchEventKinds::ENTRY_MODIFY)
puts 'Listening'
while true do
key = watcher.take
key.poll_events.each do |event|
next if event.kind == java.nio.file.StandardWatchEventKinds::OVERFLOW
file = event.context.to_absolute_path.to_file
puts event.kind, file
end
key.reset
end
However there's a huge delay (1-3 seconds) on OS X until the event is received, so you might want to try it on Windows to see if there's less delay. If you're interested, I started a JVM adapter for Listen, but I've quickly loosed interest since I don't use Windows and also not JRuby for development, but perhaps you might want to pick it up:
diff --git a/Gemfile b/Gemfile
index 7a077ba..0ec8dac 100644
--- a/Gemfile
+++ b/Gemfile
@@ -13,7 +13,7 @@ gem 'wdm', '~> 0.0.3' if RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
group :development do
gem 'guard-rspec'
gem 'yard'
- gem 'redcarpet'
+ #gem 'redcarpet'
gem 'pimpmychangelog'
end
diff --git a/lib/listen/adapter.rb b/lib/listen/adapter.rb
index a904093..c539b57 100644
--- a/lib/listen/adapter.rb
+++ b/lib/listen/adapter.rb
@@ -9,7 +9,7 @@ module Listen
:mutex, :changed_directories, :turnstile, :latency
# The list of existing optimized adapters.
- OPTIMIZED_ADAPTERS = %w[Darwin Linux BSD Windows]
+ OPTIMIZED_ADAPTERS = %w[JVM Darwin Linux BSD Windows]
# The list of existing fallback adapters.
FALLBACK_ADAPTERS = %w[Polling]
diff --git a/lib/listen/adapters/jvm.rb b/lib/listen/adapters/jvm.rb
index e69de29..b27f006 100644
--- a/lib/listen/adapters/jvm.rb
+++ b/lib/listen/adapters/jvm.rb
@@ -0,0 +1,97 @@
+module Listen
+ module Adapters
+
+ # Listener implementation for the Java Virtual Machine
+ #
+ class JVM < Adapter
+
+ attr_accessor :worker, :worker_thread, :poll_thread
+
+ # Initializes the Adapter.
+ #
+ # @see Listen::Adapter#initialize
+ #
+ def initialize(directories, options = {}, &callback)
+ super
+ @worker = init_worker
+ end
+
+ # Starts the adapter.
+ #
+ # @param [Boolean] blocking whether or not to block the current thread after starting
+ #
+ def start(blocking = true)
+ super
+
+ @worker_thread = Thread.new do
+ until stopped
+ key = worker.take
+
+ key.poll_events.each do |event|
+ next if paused || event.kind == java.nio.file.StandardWatchEventKinds::OVERFLOW
+
+ file = event.context.to_absolute_path.to_file
+
+ mutex.synchronize do
+ @changed_directories << (file.directory? ? file : file.parent_file)
+ end
+ end
+
+ key.reset
+ end
+ end
+
+ @poll_thread = Thread.new { poll_changed_directories } if report_changes?
+ worker_thread.join if blocking
+ end
+
+ # Stops the adapter.
+ #
+ def stop
+ mutex.synchronize do
+ return if stopped
+ super
+ end
+
+ worker.close
+ Thread.kill(worker_thread) if worker_thread
+ poll_thread.join if poll_thread
+ end
+
+ # Checks if the adapter is running on the JVM.
+ #
+ # @return [Boolean] whether usable or not
+ #
+ def self.usable?
+ return true if defined? JRUBY_VERSION
+ end
+
+ private
+
+ # Initializes a WatchService and adds a WatchKey for each files in
+ # the directories passed to the adapter.
+ #
+ # @return [WatchService] initialized watch service
+ #
+ def init_worker
+ require 'java'
+
+ fs = java.nio.file.FileSystems.default
+ watcher = fs.new_watch_service
+
+ directories.each do |dir|
+ path = fs.getPath dir
+ path.register(watcher,
+ java.nio.file.StandardWatchEventKinds::ENTRY_CREATE,
+ java.nio.file.StandardWatchEventKinds::ENTRY_DELETE,
+ java.nio.file.StandardWatchEventKinds::ENTRY_MODIFY)
+
+ end
+
+ watcher
+ end
+
+ end
+
+ end
+end
diff --git a/spec/listen/adapters/jvm_spec.rb b/spec/listen/adapters/jvm_spec.rb
index e69de29..f6bd398 100644
--- a/spec/listen/adapters/jvm_spec.rb
+++ b/spec/listen/adapters/jvm_spec.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe Listen::Adapters::JVM do
+ if jruby?
+ if Listen::Adapters::JVM.usable?
+ it 'is usable on the JVM' do
+ described_class.should be_usable
+ end
+
+ it_should_behave_like 'a filesystem adapter'
+ it_should_behave_like 'an adapter that call properly listener#on_change'
+ else
+ it "isn't usable on BSD with #{RbConfig::CONFIG['RUBY_INSTALL_NAME']}" do
+ described_class.should_not be_usable
+ end
+ end
+ end
+
+ unless jruby?
+ it "isn't usable without the JVM" do
+ described_class.should_not be_usable
+ end
+ end
+
+end
diff --git a/spec/support/platform_helper.rb b/spec/support/platform_helper.rb
index 480b21f..c5af12e 100644
--- a/spec/support/platform_helper.rb
+++ b/spec/support/platform_helper.rb
@@ -13,3 +13,7 @@ end
def windows?
RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
end
+
+def jruby?
+ defined? JRUBY_VERSION
+end
Nice!
Very good. We should definitely try to get something along these lines working (either in wdm, in the listen gem or in a separate JRuby-specific notifier), since Listen is depending on polling on JRuby/Windows at the moment (with a very noticable delay, much longer than 1-3 seconds).
Will / has this been merged to master? I use guard/listen on Windows, too and also using JRuby to work around compatibility issues, it recommends wdm as it would just simply poll otherwise, which is very slow and inefficient.
@mechanicalduck I really not sure @Maher4Ever hasn't be active for a long time now and @netzpirat past away a few month ago, maybe the best would be to fork this repo.
Since a lot of windows users are using JRuby to work around/through other compatibility issues, what would be the issues involved with creating a java compatible gem?