github.com/nycdavid/zeus@v0.0.0-20201208104106-9ba439429e03/vagrant/lib/vagrant-zeus/commands/zeus-file-monitor.rb (about) 1 module VagrantPlugins::Zeus 2 module Commands 3 class FileMonitor < Vagrant.plugin(2, :command) 4 # these are pointing to ext/ and buid/ in the gem root 5 if /linux/ =~ RUBY_PLATFORM 6 FILE_MONITOR_EXECUTABLE = File.join( 7 File.dirname(__FILE__), 8 '../../../ext/inotify-wrapper/inotify-wrapper' 9 ) 10 else 11 FILE_MONITOR_EXECUTABLE = File.join( 12 File.dirname(__FILE__), 13 '../../../build/fsevents-wrapper' 14 ) 15 end 16 17 class FileWatcher 18 def initialize(machine, env) 19 @machine = machine 20 @env = env 21 end 22 23 def run 24 @zeus_connection = spawn_zeus_connection 25 @file_monitor = spawn_file_monitor 26 27 ui.info("Connected to zeus, watching for changes...") 28 29 modified_files_buf = '' 30 watched_files_buf = '' 31 ended = false 32 33 while !ended 34 ready = IO.select([@file_monitor, @zeus_connection]) 35 ready[0].each do |fh| 36 if fh == @file_monitor 37 begin 38 modified_files_buf += @file_monitor.readpartial(4096) 39 rescue EOFError 40 ui.error("Lost connection to the file monitor process, exiting!") 41 ended = true 42 end 43 modified_files_buf = process_modified_files(modified_files_buf) 44 elsif fh == @zeus_connection 45 begin 46 watched_files_buf += @zeus_connection.readpartial(4096) 47 rescue EOFError 48 ui.error("Lost connection to the zeus socket, exiting!") 49 ended = true 50 end 51 watched_files_buf = process_watched_files(watched_files_buf) 52 end 53 end 54 end 55 ensure 56 if @file_monitor 57 begin 58 Process.kill("KILL", @file_monitor.pid) 59 Process.waitpid(@file_monitor.pid) 60 rescue => e 61 $stderr.puts(e) 62 end 63 end 64 end 65 66 private 67 68 def spawn_file_monitor 69 IO.popen(FILE_MONITOR_EXECUTABLE, 'r+') 70 end 71 72 def spawn_zeus_connection 73 TCPSocket.new('localhost', @machine.config.zeus.file_monitor_port) 74 end 75 76 def process_modified_files(buf) 77 lines = buf.sub(/.*\z/, '').split(/\n/) 78 remaining = buf.sub(/\A.*\n/m, '') 79 80 lines.each do |line| 81 file = host_to_guest_path(line) 82 if file 83 @zeus_connection.write("#{file}\n") 84 end 85 end 86 87 remaining 88 end 89 90 def process_watched_files(buf) 91 lines = buf.sub(/.*\z/, '').split(/\n/) 92 remaining = buf.sub(/\A.*\n/m, '') 93 94 lines.each do |line| 95 file = guest_to_host_path(line) 96 if file 97 @file_monitor.write("#{file}\n") 98 end 99 end 100 101 remaining 102 end 103 104 def guest_to_host_path(path) 105 guest_to_host_map.each do |guest, host| 106 if path.start_with?(guest) 107 return path.sub(/\A#{guest}/, host) 108 end 109 end 110 111 # NOTE: we are explicitly not passing through things that don't live 112 # on a synced folder, because they won't exist in a useful form on 113 # the other side (and the inotify watcher has a slow poll for files 114 # that don't exist) 115 nil 116 end 117 118 def host_to_guest_path(path) 119 host_to_guest_map.each do |host, guest| 120 if path.start_with?(host) 121 return path.sub(/\A#{host}/, guest) 122 end 123 end 124 125 # NOTE: see above - this is less important because it doesn't trigger 126 # the slow poll path, but still unnecessary 127 nil 128 end 129 130 def guest_to_host_map 131 paths = [] 132 @machine.config.vm.synced_folders.map do |_, options| 133 if !options[:disabled] 134 paths.push([ 135 options[:guestpath], 136 File.absolute_path(options[:hostpath]) 137 ]) 138 end 139 end 140 paths.sort_by { |guest, host| guest.length }.reverse 141 end 142 143 def host_to_guest_map 144 paths = [] 145 @machine.config.vm.synced_folders.map do |_, options| 146 if !options[:disabled] 147 paths.push([ 148 File.absolute_path(options[:hostpath]), 149 options[:guestpath] 150 ]) 151 end 152 end 153 paths.sort_by { |host, guest| host.length }.reverse 154 end 155 156 def ui 157 @env.ui 158 end 159 end 160 161 def execute 162 with_target_vms(nil, :single_target => true) do |machine| 163 watcher = FileWatcher.new(machine, @env) 164 while true 165 begin 166 watcher.run 167 rescue => e 168 @env.ui.error(e.message) 169 end 170 sleep 1 171 end 172 end 173 0 174 end 175 end 176 end 177 end