Class: VagrantPlugins::Fsevents::Responder

Inherits:
Object
  • Object
show all
Defined in:
lib/vagrant-fsevents/responder.rb

Overview

Defines how to respond to a change event

Instance Method Summary collapse

Constructor Details

#initialize(logger, alerter) ⇒ Responder

Returns a new instance of Responder.



7
8
9
10
11
# File 'lib/vagrant-fsevents/responder.rb', line 7

def initialize(logger, alerter)
  @logger = logger
  @alerter = alerter
  @recently_changed = Hash.new { |hash, key| hash[key] = 0 }
end

Instance Method Details

#add_locks(events) ⇒ Object

Adds deadzone locks for given events



57
58
59
60
61
62
63
64
# File 'lib/vagrant-fsevents/responder.rb', line 57

def add_locks(events)
  lock_duration = Time.now.to_f + 2 + (0.02 * events.length)
  @alerter.events(events)
  events.each do |event|
    @recently_changed[event.relative_path] = lock_duration
  end
  events
end

#callback(watches, mods, adds, removes) ⇒ Object

This is the main callback that responds to a change detection event



14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/vagrant-fsevents/responder.rb', line 14

def callback(watches, mods, adds, removes)
  @logger.callback_start(mods, adds, removes)

  clear_expired_change_locks

  events_to_sync = watches.map do |_, watch|
    events = ChangeEvents.make(mods, adds, removes, watch)
    add_locks(remove_locked_events(select_by_relevance(events)))
  end

  forward_events_to_vms(events_to_sync.flatten)
rescue StandardError => e
  @logger.error("#{e}: #{e.message}")
end

#callback_procObject

Return the callback as a proc that can be passed to the listener



30
31
32
# File 'lib/vagrant-fsevents/responder.rb', line 30

def callback_proc
  method(:callback).to_proc
end

#clear_expired_change_locksObject

Clear any stored change events from runs older than two seconds



89
90
91
92
93
# File 'lib/vagrant-fsevents/responder.rb', line 89

def clear_expired_change_locks
  @recently_changed.each do |rel_path, time|
    @recently_changed.delete(rel_path) if time < Time.now.to_f
  end
end

#forward_events_to_vms(ungrouped_events) ⇒ Object

Action events that have been bound to a watch and passed checks



73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/vagrant-fsevents/responder.rb', line 73

def forward_events_to_vms(ungrouped_events)
  group_events_by_machine(ungrouped_events).each do |machine, events|
    changed_files = events.map(&:full_path_on_guest)
    delete_events = events.select { |event| event.type == :removed }
    sync_command = "touch -a '#{changed_files.join("' '")}'"

    unless delete_events.empty?
      deleted_files = delete_events.map(&:full_path_on_guest)
      sync_command += "; rm -rf '#{deleted_files.join("' '")}'"
    end

    machine.communicate.execute(sync_command)
  end
end

#group_events_by_machine(events) ⇒ Object



66
67
68
69
70
# File 'lib/vagrant-fsevents/responder.rb', line 66

def group_events_by_machine(events)
  machine_hash = Hash.new { |hash, key| hash[key] = [] }
  events.each { |event| machine_hash[event.watch[:machine]] << event }
  machine_hash
end

#remove_locked_events(events) ⇒ Object

Filters out events still in their change deadzone



45
46
47
48
49
50
51
52
53
54
# File 'lib/vagrant-fsevents/responder.rb', line 45

def remove_locked_events(events)
  events.select do |event|
    if @recently_changed[event.relative_path] >= Time.now.to_f
      @logger.change_too_soon(event.relative_path)
      next
    end

    true
  end
end

#select_by_relevance(events) ⇒ Object

Filters out events whose path or type don’t match their watch



35
36
37
38
39
40
41
42
# File 'lib/vagrant-fsevents/responder.rb', line 35

def select_by_relevance(events)
  events.select do |event|
    next unless event.path.start_with?(event.watch_path)

    watch = event.watch[:opts][:fsevents]
    (watch == true || watch.includes?(event.type))
  end
end