class Listen::Adapter

Constants

DEFAULT_LATENCY

The default delay between checking for changes.

POLLING_FALLBACK_MESSAGE

The default warning message when falling back to polling adapter.

Attributes

directories[RW]
latency[RW]
paused[RW]

Public Class Methods

new(directories, options = {}, &callback) click to toggle source

Initializes the adapter.

@param [String, Array<String>] directories the directories to watch @param [Hash] options the adapter options @option options [Float] latency the delay between checking for changes in seconds

@yield [changed_dirs, options] callback Callback called when a change happens @yieldparam [Array<String>] changed_dirs the changed directories @yieldparam [Hash] options callback options (like :recursive => true)

@return [Listen::Adapter] the adapter

# File lib/listen/adapter.rb, line 60
def initialize(directories, options = {}, &callback)
  @directories  = Array(directories)
  @callback     = callback
  @latency    ||= DEFAULT_LATENCY
  @latency      = options[:latency] if options[:latency]
  @paused       = false
  @mutex        = Mutex.new
  @changed_dirs = Set.new
  @turnstile    = Turnstile.new
end
select_and_initialize(directories, options = {}, &callback) click to toggle source

Selects the appropriate adapter implementation for the current OS and initializes it.

@param [String, Array<String>] directories the directories to watch @param [Hash] options the adapter options @option options [Boolean] force_polling to force polling or not @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it @option options [Float] latency the delay between checking for changes in seconds

@yield [changed_dirs, options] callback Callback called when a change happens @yieldparam [Array<String>] changed_dirs the changed directories @yieldparam [Hash] options callback options (like :recursive => true)

@return [Listen::Adapter] the chosen adapter

# File lib/listen/adapter.rb, line 31
def self.select_and_initialize(directories, options = {}, &callback)
  return Adapters::Polling.new(directories, options, &callback) if options.delete(:force_polling)

  if Adapters::Darwin.usable_and_works?(directories, options)
    Adapters::Darwin.new(directories, options, &callback)
  elsif Adapters::Linux.usable_and_works?(directories, options)
    Adapters::Linux.new(directories, options, &callback)
  elsif Adapters::Windows.usable_and_works?(directories, options)
    Adapters::Windows.new(directories, options, &callback)
  else
    unless options[:polling_fallback_message] == false
      Kernel.warn(options[:polling_fallback_message] || POLLING_FALLBACK_MESSAGE)
    end
    Adapters::Polling.new(directories, options, &callback)
  end
end
usable_and_works?(directories, options = {}) click to toggle source

Checks if the adapter is usable and works on the current OS.

@param [String, Array<String>] directories the directories to watch @param [Hash] options the adapter options @option options [Float] latency the delay between checking for changes in seconds

@return [Boolean] whether usable and work or not

# File lib/listen/adapter.rb, line 109
def self.usable_and_works?(directories, options = {})
  usable? && Array(directories).all? { |d| works?(d, options) }
end
works?(directory, options = {}) click to toggle source

Runs a tests to determine if the adapter can actually pick up changes in a given directory and returns the result.

@note This test takes some time depending the adapter latency.

@param [String, Pathname] directory the directory to watch @param [Hash] options the adapter options @option options [Float] latency the delay between checking for changes in seconds

@return [Boolean] whether the adapter works or not

# File lib/listen/adapter.rb, line 124
def self.works?(directory, options = {})
  work = false
  test_file = "#{directory}/.listen_test"
  callback = lambda { |changed_dirs, options| work = true }
  adapter  = self.new(directory, options, &callback)
  adapter.start(false)

  FileUtils.touch(test_file)

  t = Thread.new { sleep(adapter.latency * 5); adapter.stop }

  adapter.wait_for_callback
  work
ensure
  Thread.kill(t) if t
  FileUtils.rm(test_file) if File.exists?(test_file)
  adapter.stop if adapter && adapter.started?
end

Public Instance Methods

start(blocking = true) click to toggle source

Starts the adapter.

@param [Boolean] blocking whether or not to block the current thread after starting

# File lib/listen/adapter.rb, line 75
def start(blocking = true)
  @stop = false
end
started?() click to toggle source

Returns whether the adapter is statred or not

@return [Boolean] whether the adapter is started or not

# File lib/listen/adapter.rb, line 90
def started?
  @stop.nil? ? false : !@stop
end
stop() click to toggle source

Stops the adapter.

# File lib/listen/adapter.rb, line 81
def stop
  @stop = true
  @turnstile.signal # ensure no thread is blocked
end
wait_for_callback() click to toggle source

Blocks the main thread until the poll thread calls the callback.

# File lib/listen/adapter.rb, line 97
def wait_for_callback
  @turnstile.wait unless @paused
end