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,
    :modify,
    :delete,
    :move,
    :close_write
  ],
  wait_for_delay: 0.1
}.freeze
README_URL =
'https://github.com/guard/listen'\
'/blob/master/README.md#increasing-the-amount-of-inotify-watchers'

Instance Attribute Summary

Attributes inherited from Base

#config, #options

Instance Method Summary collapse

Methods inherited from Base

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

Constructor Details

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

Instance Method Details

#_change(event_flags) ⇒ Object (private)



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

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)



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

def _configure(directory, &callback)
  require 'rb-inotify'
  @worker ||= ::INotify::Notifier.new
  @worker.watch(directory.to_s, *options.events, &callback)
rescue Errno::ENOSPC
  raise ::Listen::Error::INotifyMaxWatchesExceeded, <<~EOS
    Unable to monitor directories for changes because iNotify max watches exceeded. See #{README_URL} .
  EOS
end

#_dir_event?(event) ⇒ Boolean (private)

Returns:

  • (Boolean)


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

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

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

rubocop:disable Metrics/MethodLength



42
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
# File 'lib/listen/adapter/linux.rb', line 42

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

  Listen.logger.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
    end
    _queue_change(:dir, dir, rel_path, {})
    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)



37
38
39
# File 'lib/listen/adapter/linux.rb', line 37

def _run
  @worker.run
end

#_skip_event?(event) ⇒ Boolean (private)

rubocop:enable Metrics/MethodLength

Returns:

  • (Boolean)


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

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

#_stopObject (private)



101
102
103
104
105
# File 'lib/listen/adapter/linux.rb', line 101

def _stop
  @worker&.close

  super
end