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*/, '')
  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)



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

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

#_dir_event?(event) ⇒ Boolean (private)

Returns:

  • (Boolean)


83
84
85
# File 'lib/listen/adapter/linux.rb', line 83

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

#_event_path(event) ⇒ Object (private)



87
88
89
# File 'lib/listen/adapter/linux.rb', line 87

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



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

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)


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

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)



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

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

    if _dir_event?(event)
      _notify_change(_event_path(event), type: 'Dir')
    else
      _notify_change(_event_path(event), type: 'File', change: _change(event.flags))
    end
  end
end

#startObject



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

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