Module: Listen::QueueOptimizer

Included in:
Listener
Defined in:
lib/listen/queue_optimizer.rb

Instance Method Summary collapse

Instance Method Details

#_calculate_add_remove_difference(actions, path, default_if_exists) ⇒ Object (private)



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/listen/queue_optimizer.rb', line 49

def _calculate_add_remove_difference(actions, path, default_if_exists)
  added = actions.count { |x| x == :added }
  removed = actions.count { |x| x == :removed }
  diff = added - removed

  # TODO: avoid checking if path exists and instead assume the events are
  # in order (if last is :removed, it doesn't exist, etc.)
  if path.exist?
    if diff > 0
      :added
    elsif diff.zero? && added > 0
      :modified
    else
      default_if_exists
    end
  else
    diff < 0 ? :removed : nil
  end
end

#_detect_possible_editor_save(changes) ⇒ Object (private)



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/listen/queue_optimizer.rb', line 89

def _detect_possible_editor_save(changes)
  return unless changes.size == 2

  from_type = from_change = from = nil
  to_type = to_change = to_dir = to = nil

  changes.each do |data|
    case data[1]
    when :moved_from
      from_type, from_change, _, from, _ = data
    when :moved_to
      to_type, to_change, to_dir, to, _ = data
    else
      return nil
    end
  end

  return unless from && to

  # Expect an ignored moved_from and non-ignored moved_to
  # to qualify as an "editor modify"
  return unless _silenced?(Pathname(from), from_type)
  _silenced?(Pathname(to), to_type) ? nil : [to_dir, to]
end

#_logical_action_for(path, actions) ⇒ Object (private)



41
42
43
44
45
46
47
# File 'lib/listen/queue_optimizer.rb', line 41

def _logical_action_for(path, actions)
  actions << :added if actions.delete(:moved_to)
  actions << :removed if actions.delete(:moved_from)

  modified = actions.detect { |x| x == :modified }
  _calculate_add_remove_difference(actions, path, modified)
end

remove extraneous rb-inotify events, keeping them only if it's a possible editor rename() call (e.g. Kate and Sublime)



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

def _reinterpret_related_changes(cookies)
  table = { moved_to: :added, moved_from: :removed }
  cookies.map do |_, changes|
    data = _detect_possible_editor_save(changes)
    if data
      to_dir, to_file = data
      [[:modified, to_dir, to_file]]
    else
      not_silenced = changes.reject do |type, _, _, path, _|
        _silenced?(Pathname(path), type)
      end
      not_silenced.map do |_, change, dir, path, _|
        [table.fetch(change, change), dir, path]
      end
    end
  end.flatten(1)
end

#_smoosh_changes(changes) ⇒ Object (private)



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/listen/queue_optimizer.rb', line 5

def _smoosh_changes(changes)
  # TODO: adapter could be nil at this point (shutdown)
  if _adapter_class.local_fs?
    cookies = changes.group_by do |_, _, _, _, options|
      (options || {})[:cookie]
    end
    _squash_changes(_reinterpret_related_changes(cookies))
  else
    smooshed = { modified: [], added: [], removed: [] }
    changes.each do |_, change, dir, rel_path, _|
      smooshed[change] << (dir + rel_path).to_s
    end
    smooshed.tap { |s| s.each { |_, v| v.uniq! } }
  end
end

#_squash_changes(changes) ⇒ Object (private)

groups changes into the expected structure expected by clients



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/listen/queue_optimizer.rb', line 23

def _squash_changes(changes)
  # We combine here for backward compatibility
  # Newer clients should receive dir and path separately
  changes = changes.map { |change, dir, path| [change, dir + path] }

  actions = changes.group_by(&:last).map do |path, action_list|
    [_logical_action_for(path, action_list.map(&:first)), path.to_s]
  end
  _log :info, "listen: raw changes: #{actions.inspect}"

  { modified: [], added: [], removed: [] }.tap do |squashed|
    actions.each do |type, path|
      squashed[type] << path unless type.nil?
    end
    _log :info, "listen: final changes: #{squashed.inspect}"
  end
end