Class: Listen::Adapter::BSD

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

Constant Summary collapse

OS_REGEXP =
/bsd|dragonfly/i
DEFAULTS =
{
  events: [
    :delete,
    :write,
    :extend,
    :attrib,
    :rename
    # :link, :revoke
  ]
}.freeze
BUNDLER_DECLARE_GEM =
<<-EOS.gsub(/^ {6}/, '')
  Please add the following to your Gemfile to avoid polling for changes:
    require 'rbconfig'
    if RbConfig::CONFIG['target_os'] =~ /#{OS_REGEXP}/
      gem 'rb-kqueue', '>= 0.2'
    end
EOS

Instance Attribute Summary

Attributes inherited from Base

#config, #options

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#_log_exception, #_queue_change, #_stop, #_timed, #configure, #initialize, #start, #started?, #stop

Constructor Details

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

Class Method Details

.usable?Boolean

Returns:

  • (Boolean)


31
32
33
34
35
36
37
38
39
# File 'lib/listen/adapter/bsd.rb', line 31

def self.usable?
  return false unless super
  require 'rb-kqueue'
  require 'find'
  true
rescue LoadError
  Listen.adapter_warn(BUNDLER_DECLARE_GEM)
  false
end

Instance Method Details

#_change(event_flags) ⇒ Object (private)



73
74
75
76
77
78
79
80
# File 'lib/listen/adapter/bsd.rb', line 73

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

#_configure(directory, &callback) ⇒ Object (private)



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

def _configure(directory, &callback)
  @worker ||= KQueue::Queue.new
  @callback = callback
  # use Record to make a snapshot of dir, so we
  # can detect new files
  _find(directory.to_s) { |path| _watch_file(path, @worker) }
end

#_event_path(event) ⇒ Object (private)



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

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

#_find(*paths, &block) ⇒ Object (private)

Quick rubocop workaround



102
103
104
# File 'lib/listen/adapter/bsd.rb', line 102

def _find(*paths, &block)
  Find.send(:find, *paths, &block)
end

#_process_event(dir, event) ⇒ Object (private)



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/listen/adapter/bsd.rb', line 55

def _process_event(dir, event)
  full_path = _event_path(event)
  if full_path.directory?
    # Force dir content tracking to kick in, or we won't have
    # names of added files
    _queue_change(:dir, dir, '.', recursive: true)
  elsif full_path.exist?
    path = full_path.relative_path_from(dir)
    _queue_change(:file, dir, path.to_s, change: _change(event.flags))
  end

  # 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 full_path.directory?
end

#_runObject (private)



51
52
53
# File 'lib/listen/adapter/bsd.rb', line 51

def _run
  @worker.run
end

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



95
96
97
98
99
# File 'lib/listen/adapter/bsd.rb', line 95

def _watch_file(path, queue)
  queue.watch_file(path, *options.events, &@callback)
rescue Errno::ENOENT => e
  Listen.logger.warn "kqueue: watch file failed: #{e.message}"
end

#_watch_for_new_file(event) ⇒ Object (private)



86
87
88
89
90
91
92
93
# File 'lib/listen/adapter/bsd.rb', line 86

def _watch_for_new_file(event)
  queue = event.watcher.queue
  _find(_event_path(event).to_s) do |file_path|
    unless queue.watchers.find { |_, v| v.path == file_path.to_s }
      _watch_file(file_path, queue)
    end
  end
end