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
  ]
}
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'

      # Base versions have known conflicts/bugs
      # Even master branches may not work...
      gem 'ffi', github: 'carpetsmoker/ffi', ref: 'ac63e07f7'
      gem 'celluloid', github: 'celluloid/celluloid', ref: '7fdef04'
    end
EOS
BSD_EXPERIMENTAL =
<<-EOS.gsub(/^ {6}/, '')
  NOTE *BSD SUPPORT IS EXPERIMENTAL!

  In fact, it likely WONT WORK!!!!

  (see: https://github.com/guard/listen/issues/220)

  If you're brave enough, feel free to suggest pull requests and
  experiment on your own. For help, browse existing issues marked 'bsd'
  for clues, tips and workaround.
EOS

Instance Attribute Summary

Attributes inherited from Base

#options

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#_log, _log, #_queue_change, #configure, #initialize, local_fs?, #start

Constructor Details

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

Class Method Details

.usable?Boolean

Returns:

  • (Boolean)


46
47
48
49
50
51
52
53
54
55
# File 'lib/listen/adapter/bsd.rb', line 46

def self.usable?
  return false unless super
  Kernel.warn BSD_EXPERIMENTAL
  require 'rb-kqueue'
  require 'find'
  true
rescue LoadError
  Kernel.warn BUNDLER_DECLARE_GEM
  false
end

Instance Method Details

#_change(event_flags) ⇒ Object (private)



88
89
90
91
92
93
94
95
96
# File 'lib/listen/adapter/bsd.rb', line 88

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)



59
60
61
62
63
64
# File 'lib/listen/adapter/bsd.rb', line 59

def _configure(directory, &_callback)
  @worker ||= KQueue::Queue.new
  # 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)



98
99
100
# File 'lib/listen/adapter/bsd.rb', line 98

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

#_find(*paths) ⇒ Object (private)

Quick rubocop workaround



116
117
118
# File 'lib/listen/adapter/bsd.rb', line 116

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

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



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/listen/adapter/bsd.rb', line 70

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)
  else
    path = full_path.relative_path_from(dir)
    _queue_change(:file, dir, path, 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 path.directory?
end

#_runObject (private)



66
67
68
# File 'lib/listen/adapter/bsd.rb', line 66

def _run
  @worker.run
end

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



111
112
113
# File 'lib/listen/adapter/bsd.rb', line 111

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

#_watch_for_new_file(event) ⇒ Object (private)



102
103
104
105
106
107
108
109
# File 'lib/listen/adapter/bsd.rb', line 102

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