Class: Listen::Adapter::Linux

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

Overview

Constant Summary collapse

OS_REGEXP =
/linux/i
DEFAULTS =
{
  events: [
    :recursive,
    :attrib,
    :create,
    :delete,
    :move,
    :close_write
  ]
}
WIKI_URL =
'https://github.com/guard/listen'\
'/wiki/Increasing-the-amount-of-inotify-watchers'
INOTIFY_LIMIT_MESSAGE =
<<-EOS.gsub(/^\s*/, '')
  FATAL: Listen error: unable to monitor directories for changes.
  Visit #{WIKI_URL} for info on how to fix this.
EOS

Instance Attribute Summary

Attributes inherited from Base

#options

Instance Method Summary collapse

Methods inherited from Base

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

Constructor Details

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

Instance Method Details

#_change(event_flags) ⇒ Object (private)



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

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

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



28
29
30
31
32
33
34
35
36
37
# File 'lib/listen/adapter/linux.rb', line 28

def _configure(directory, &callback)
  require 'rb-inotify'
  @worker ||= INotify::Notifier.new
  @worker.watch(directory.to_s, *options.events, &callback)
rescue Errno::ENOSPC
  # workaround - Celluloid catches abort and prints nothing
  STDERR.puts INOTIFY_LIMIT_MESSAGE
  STDERR.flush
  abort(INOTIFY_LIMIT_MESSAGE)
end

#_dir_event?(event) ⇒ Boolean (private)

Returns:

  • (Boolean)


99
100
101
# File 'lib/listen/adapter/linux.rb', line 99

def _dir_event?(event)
  event.flags.include?(:isdir)
end

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



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/listen/adapter/linux.rb', line 43

def _process_event(dir, event)
  # NOTE: avoid using event.absolute_name since new API
  # will need to have a custom recursion implemented
  # to properly match events to configured directories
  path = Pathname.new(event.watcher.path) + event.name
  rel_path = path.relative_path_from(dir).to_s

  _log :debug, "inotify: #{rel_path} (#{event.flags.inspect})"

  if /1|true/ =~ ENV['LISTEN_GEM_SIMULATE_FSEVENT']
    if (event.flags & [:moved_to, :moved_from]) || _dir_event?(event)
      rel_path = path.dirname.relative_path_from(dir).to_s
      _queue_change(:dir, dir, rel_path, {})
    else
      _queue_change(:dir, dir, rel_path, {})
    end
    return
  end

  return if _skip_event?(event)

  cookie_params = event.cookie.zero? ? {} : { cookie: event.cookie }

  # Note: don't pass options to force rescanning the directory, so we can
  # detect moving/deleting a whole tree
  if _dir_event?(event)
    _queue_change(:dir, dir, rel_path, cookie_params)
    return
  end

  params = cookie_params.merge(change: _change(event.flags))

  _queue_change(:file, dir, rel_path, params)
end

#_runObject (private)



39
40
41
# File 'lib/listen/adapter/linux.rb', line 39

def _run
  @worker.run
end

#_skip_event?(event) ⇒ Boolean (private)

Returns:

  • (Boolean)


78
79
80
81
82
83
84
85
86
# File 'lib/listen/adapter/linux.rb', line 78

def _skip_event?(event)
  # Event on root directory
  return true if event.name == ''
  # INotify reports changes to files inside directories as events
  # on the directories themselves too.
  #
  # @see http://linux.die.net/man/7/inotify
  _dir_event?(event) && (event.flags & [:close, :modify]).any?
end