Class: Listen::Adapter::BSD

Inherits:
Base
  • Object
show all
Defined in:
lib/listen/adapter/bsd.rb

Overview

Listener implementation for BSD's kqueue.

Constant Summary collapse

EVENTS =

Watched kqueue events

[:delete, :write, :extend, :attrib, :rename]
BUNDLER_DECLARE_GEM =

The message to show when wdm gem isn't available

<<-EOS.gsub(/^ {6}/, '')
  Please add the following to your Gemfile to avoid polling for changes:
    require 'rbconfig'
    gem 'rb-kqueue', '>= 0.2' if RbConfig::CONFIG['target_os'] =~ /freebsd/i
EOS

Constants inherited from Base

Listen::Adapter::Base::DEFAULT_LATENCY

Instance Attribute Summary

Attributes inherited from Base

#listener

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#_directories_path, #_latency, #_notify_change, #initialize

Constructor Details

This class inherits a constructor from Listen::Adapter::Base

Class Method Details

.usable?Boolean

Returns:

  • (Boolean)


22
23
24
25
26
27
28
29
30
31
# File 'lib/listen/adapter/bsd.rb', line 22

def self.usable?
  if RbConfig::CONFIG['target_os'] =~ /freebsd/i
    require 'rb-kqueue'
    require 'find'
    true
  end
rescue LoadError
  Kernel.warn BUNDLER_DECLARE_GEM
  false
end

Instance Method Details

#_change(event_flags) ⇒ Object (private)



65
66
67
68
69
70
71
72
# File 'lib/listen/adapter/bsd.rb', line 65

def _change(event_flags)
  { modified: [:attrib, :extend],
    added:    [:write],
    removed:  [:rename, :delete] }.each do |change, flags|
    return change unless (flags & event_flags).empty?
  end
  nil
end

#_event_path(event) ⇒ Object (private)



74
75
76
# File 'lib/listen/adapter/bsd.rb', line 74

def _event_path(event)
  Pathname.new(event.watcher.path)
end

#_init_workerINotify::Notifier (private)

Initializes a kqueue Queue and adds a watcher for each files in the directories passed to the adapter.

Returns:

  • (INotify::Notifier)

    initialized kqueue



45
46
47
48
49
50
51
# File 'lib/listen/adapter/bsd.rb', line 45

def _init_worker
  KQueue::Queue.new.tap do |queue|
    _directories_path.each do |path|
      Find.find(path) { |file_path| _watch_file(file_path, queue) }
    end
  end
end

#_new_file_added?(event) ⇒ Boolean (private)

Returns:

  • (Boolean)


78
79
80
# File 'lib/listen/adapter/bsd.rb', line 78

def _new_file_added?(event)
  File.directory?(event.watcher.path) && event.flags.include?(:write)
end

#_watch_file(path, queue) ⇒ Object (private)



89
90
91
# File 'lib/listen/adapter/bsd.rb', line 89

def _watch_file(path, queue)
  queue.watch_file(path, *EVENTS, &_worker_callback)
end

#_watch_for_new_file(event) ⇒ Object (private)



82
83
84
85
86
87
# File 'lib/listen/adapter/bsd.rb', line 82

def _watch_for_new_file(event)
  queue = event.watcher.queue
  Find.find(path) do |file_path|
    _watch_file(file_path, queue) unless queue.watchers.detect { |k,v| v.path == file.to_s }
  end
end

#_worker_callbackObject (private)



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/listen/adapter/bsd.rb', line 53

def _worker_callback
  lambda do |event|
     _notify_change(_event_path(event), type: 'file', change: _change(event.flags))

      # If it is a directory, and it has a write flag, it means a
      # file has been added so find out which and deal with it.
      # No need to check for removed files, kqueue will forget them
      # when the vfs does.
     _watch_for_new_file(event) if _new_file_added?(event)
  end
end

#startObject



33
34
35
36
# File 'lib/listen/adapter/bsd.rb', line 33

def start
  worker = _init_worker
  worker.poll
end