Class: Listen::Adapter::Linux

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

Overview

Listener implementation for Linux inotify.

Constant Summary collapse

EVENTS =

Watched inotify events

[:recursive, :attrib, :create, :delete, :move, :close_write]
INOTIFY_LIMIT_MESSAGE =

The message to show when the limit of inotify watchers is not enough

<<-EOS.gsub(/^\s*/, '')
  FATAL: Listen error: unable to monitor directories for changes.

  Please head to https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers
  for information on how to solve this issue.
EOS

Constants inherited from Base

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

Constructor Details

#initialize(listener) ⇒ Linux

Returns a new instance of Linux.



27
28
29
30
# File 'lib/listen/adapter/linux.rb', line 27

def initialize(listener)
  require 'rb-inotify'
  super
end

Class Method Details

.usable?Boolean

Returns:

  • (Boolean)


23
24
25
# File 'lib/listen/adapter/linux.rb', line 23

def self.usable?
  RbConfig::CONFIG['target_os'] =~ /linux/i
end

Instance Method Details

#_change(event_flags) ⇒ Object (private)



81
82
83
84
85
86
87
88
89
90
# File 'lib/listen/adapter/linux.rb', line 81

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

#_dir_event?(event) ⇒ Boolean (private)

Returns:

  • (Boolean)


92
93
94
# File 'lib/listen/adapter/linux.rb', line 92

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

#_event_path(event) ⇒ Object (private)



96
97
98
# File 'lib/listen/adapter/linux.rb', line 96

def _event_path(event)
  Pathname.new(event.absolute_name)
end

#_init_workerINotify::Notifier (private)

Initializes a INotify worker and adds a watcher for each directory passed to the adapter.

Returns:

  • (INotify::Notifier)

    initialized worker



48
49
50
51
52
# File 'lib/listen/adapter/linux.rb', line 48

def _init_worker
  INotify::Notifier.new.tap do |worker|
    _directories_path.each { |path| worker.watch(path, *EVENTS, &_worker_callback) }
  end
end

#_skip_event?(event) ⇒ Boolean (private)

Returns:

  • (Boolean)


71
72
73
74
75
76
77
78
79
# File 'lib/listen/adapter/linux.rb', line 71

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
  return true if _dir_event?(event) && (event.flags & [:close, :modify]).any?
end

#_worker_callbackObject (private)



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

def _worker_callback
  lambda do |event|
    next if _skip_event?(event)

    path = _event_path(event)
    cookie_opts = event.cookie.zero? ? {} : { cookie: event.cookie }

    Celluloid.logger.info "listen: inotify event: #{event.flags.inspect}: #{event.name}"

    if _dir_event?(event)
      _notify_change(path, { type: 'Dir'}.merge(cookie_opts))
    else
      _notify_change(path, { type: 'File', change: _change(event.flags)}.merge(cookie_opts))
    end
  end
end

#startObject



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

def start
  worker = _init_worker
  Thread.new { worker.run }
rescue Errno::ENOSPC
  STDERR.puts INOTIFY_LIMIT_MESSAGE
  STDERR.flush
  abort(INOTIFY_LIMIT_MESSAGE)
end