vagrant-listen-server 0.0.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a30b9bb31559cff8314063a36ebbe2b42f041504
4
- data.tar.gz: f19e8fe12f1e3700841cb95a4caf7ecbfe0334cc
3
+ metadata.gz: 2cdf2e1170398757ee77d0f77d7366215c800ac8
4
+ data.tar.gz: a9de6204420690db4cfe7a98ebc3827a43c75eaa
5
5
  SHA512:
6
- metadata.gz: c1b0dda84cc0a2a0951f4f3b6810bdf8dc7ead5d5ab2b1c55939190c41a710198757d63e14550ebae86e612e640974c390d3ee8c0bb61719a2f7a5298f54ba86
7
- data.tar.gz: 0c19dc5641435505ebfae14329a5dc0d30ebf20f8dd0e47b4e8edc82aa72b750f0af16a271af4cfa8b8bf2c2689db81b89126927aa42a24ccb96ea09b9e5eb77
6
+ metadata.gz: 996828c785f9869b42ff44040e1a690e3facf5ceeb7eba5309d243406136069c7e51fbec0be53573813aa40ba2b46407e647d13c123a849046bb45c096e4920f
7
+ data.tar.gz: 1bea636775f295df277e33ed412ba0b8ea118af011495f94b08d9e267a635fc0047f7939a7b33d912303ab529da20f4190c8a2ffc91bdd31f41124ea668cb35e
data/README.md CHANGED
@@ -14,29 +14,56 @@ are impossible. Statting takes forever.
14
14
  Since polling implementations will probably rely on statting the file in some
15
15
  way, this creates a pretty awful experience.
16
16
 
17
- The best answer I've managed to find is forwarding filesystem events. The
18
- listen gem is already used by vagrant, (as part of rsync-auto) and allows
19
- forwarding of filesystem events over TCP, so that's what I've tried to stick
20
- with.
17
+ I have tried to keep dependencies to a minimum and only rely on ruby stdlib and
18
+ gems already required by vagrant. The listen gem is used by vagrant (as part
19
+ of rsync-auto) so it is used for file system notifications.
21
20
 
22
21
 
23
22
  ## Clients
24
23
 
25
- The main reason I developed this was to allow filesystem events to be pushed
26
- to a broccoli build pipeline.
24
+ Clients should run inside the virtual machine as part of your build process.
25
+ Instead of listenting for filesystem events, they should listen on a tcp
26
+ connection.
27
27
 
28
- Ideally, you can subscribe to the file changes and trigger builds / whatever in
29
- your app
28
+ The message format is a newline separated, json encoded object with keys `type`
29
+ and `data`. The two message types:
30
30
 
31
- You can also write a simple server that touches all files on the guest, however
32
- you'll have to be aware of loops created if filesystem notifications are passed
33
- back from the guest to the host.
31
+ **listen**
32
+
33
+ {"type": "listen", "data": [modified, added, removed]}
34
+
35
+ data is an array of 3 arrays containing the full path of the files that are
36
+ modified, added and removed (in that order).
37
+
38
+ **ping**
39
+
40
+ {"type": "ping", "data": "message to be echoed"}
41
+
42
+ response will be of type "pong". Data will be echoed back to the client.
43
+
44
+
45
+ In many cases, a simple client that touches all modified files on the guest is
46
+ sufficient, however you'll have to be aware of loops created if filesystem
47
+ notifications are passed back from the guest to the host in any way. Listen
48
+ coalesces events for us, so there is no need to do so in your client.
34
49
 
35
50
  See the [examples](/examples) section for some implementations. Currently there
36
51
  is solely my node based client, but if you're using this in any other
37
52
  languages, please add your client and submit a pull request!
38
53
 
39
54
 
55
+ ## Keepalives
56
+
57
+ Ideally, the client and server sockets would both support keepalives. But we
58
+ can't rely on that working on both guest and host - windows has spotty support,
59
+ and many languages don't give control over socket flags (it's awkward in ruby).
60
+ Instead, the client can send a ping message to check the connection is alive.
61
+
62
+ A simple client can safely ignore keepalive messages.
63
+
64
+ http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/
65
+
66
+
40
67
  ## Usage
41
68
 
42
69
  Install the plugin:
@@ -46,19 +73,29 @@ Install the plugin:
46
73
  Then in your Vagrantfile:
47
74
 
48
75
  ```ruby
49
- config.vm.synced_folder '/host/code', '/client/code'
50
-
51
- # You have to specify a private network for the guest to connect to.
52
- config.vm.network :private_network, ip: '172.16.172.16'
53
-
54
- if Vagrant.has_plugin? 'vagrant-listen-server'
55
- # The host will always be the same IP as the private network with the last
56
- # octet as .1
57
- config.listen_server.ip = '172.168.172.1'
58
- config.listen_server.port = 4000
59
- config.listen_server.folders = '/host/code'
60
- config.listen_server.pid_file = '/tmp/servername.listen.pid'
61
- end
76
+ config.vm.synced_folder '/host/code', '/client/code'
77
+
78
+ # You have to specify a private network for the guest to connect to.
79
+ config.vm.network :private_network, ip: '172.16.172.16'
80
+
81
+ if Vagrant.has_plugin? 'vagrant-listen-server'
82
+ # The host will always be the same IP as the private network with the last
83
+ # octet as .1
84
+ config.listen_server.ip = '172.168.172.1'
85
+ config.listen_server.port = 4000
86
+ config.listen_server.folders = '/host/code'
87
+ config.listen_server.pid_file = '/tmp/servername.listen.pid'
88
+ end
89
+ ```
90
+
91
+ Because sleep states of both the host and guest machines can mess with long
92
+ connections in unexpected ways, you can use the command to control the listen
93
+ server.
94
+
95
+ ```bash
96
+ vagrant listen stop
97
+ vagrant listen start
98
+ vagrant listen status
62
99
  ```
63
100
 
64
101
 
@@ -78,7 +115,7 @@ Hasn't been updated to work with vagrant's new plugin system.
78
115
  To develop locally
79
116
  ```
80
117
  gem build vagrant-listen-server.gemspec
81
- vagrant plugin install vagrant-listen-server-0.0.1.gem
118
+ vagrant plugin install vagrant-listen-server-*.gem
82
119
  ```
83
120
 
84
121
  Other good vagrant plugins used for reference:
@@ -1,48 +1,36 @@
1
1
  var net = require('net');
2
2
 
3
-
4
3
  // Assuming the existence of some `build` method that returns a promise.
5
4
  var sequence = build();
6
5
 
7
-
8
- // gathers rapid changes as one build
9
- var timeout = null;
10
- var scheduleBuild = function() {
11
- if (timeout) { return; }
12
-
13
- // we want the timeout to start now before we wait for the current build
14
- var timeoutPromise = new Promise(function(resolve) {
15
- timeout = setTimeout(resolve, 100);
16
- });
17
-
18
- var timeoutThenBuild = function() {
19
- timeoutPromise.then(function() {
20
- timeout = null
21
- return build();
22
- });
23
- };
24
-
25
- // we want the current promise to be waiting for the current build
26
- // regardless if it fails or not.
27
- sequence = sequence.then(timeoutThenBuild, timeoutThenBuild);
28
- };
29
-
30
-
31
6
  var port = 4000;
32
7
  var host = '172.16.172.1';
33
8
  var client = new net.Socket();
9
+ var interval = null;
34
10
 
35
11
  client.connect(port, host, function() {
36
12
  console.log('Connected to listen server: ', host, port);
13
+
14
+ interval = setInterval(function() {
15
+ message = JSON.stringify({type: 'ping', message: 'listen-watcher'});
16
+ client.write(message + '\n');
17
+ , 1000);
37
18
  });
38
19
 
39
20
  client.on('data', function(data) {
40
21
  // message is [modified, added, removed]
41
22
  console.log('Data received', data)
42
23
  var message = JSON.parse(data.toString().trim())
43
- scheduleBuild();
24
+
25
+ if (message.type === 'pong') { return; }
26
+ if (message.type !== 'listen') { throw Error('Unknown message type'); }
27
+
28
+ // We want the current promise to be waiting for the current build
29
+ // regardless if it fails or not.
30
+ sequence = sequence.then(build, build);
44
31
  });
45
32
 
46
33
  client.on('close', function() {
47
34
  console.log('Connection closed');
35
+ interval && clearInterval(interval);
48
36
  });
@@ -1,5 +1,6 @@
1
1
  require 'vagrant-listen-server/version'
2
2
  require 'vagrant-listen-server/plugin'
3
+ require 'vagrant-listen-server/command'
3
4
 
4
5
  module VagrantPlugins
5
6
  module ListenServer
@@ -2,18 +2,6 @@ require 'listen'
2
2
  require 'socket'
3
3
  require 'json'
4
4
 
5
- # No ActiveSupport in vagrant
6
- def array_wrap object
7
- if object.nil?
8
- []
9
- elsif object.respond_to?(:to_ary)
10
- object.to_ary || [object]
11
- else
12
- [object]
13
- end
14
- end
15
-
16
-
17
5
  module VagrantPlugins
18
6
  module ListenServer
19
7
  module Action
@@ -23,95 +11,10 @@ module VagrantPlugins
23
11
  end
24
12
 
25
13
  def call(env)
26
- @env = env
27
- @ui = env[:ui]
28
- @machine = env[:machine]
29
-
30
- config = @machine.config.listen_server
31
- folders = array_wrap config.folders
32
-
33
- @ui.info "Starting listen server - #{config.ip}:#{config.port}"
34
-
35
- # Check whether the daemon is already running.
36
- if File.exists? config.pid_file
37
- pid = File.read config.pid_file
38
- begin
39
- Process.getpgid pid.to_i
40
- @ui.info 'Warning - listen server already running'
41
- return @app.call(env)
42
- rescue Errno::ESRCH
43
- @ui.info "Warning - stale PID: #{pid}"
44
- end
45
- end
46
-
47
14
  out = @app.call(env)
48
-
49
- # Vagrant-notify uses fork here, but that doesn't work on windows:
50
- # https://github.com/fgrehm/vagrant-notify/blob/master/lib/vagrant-notify/server.rb
51
- # Only real option is to switch to Process.spawn? I need a windows
52
- # machine to test it out on...
53
- pid = fork do
54
- $0 = "vagrant-listen-server - #{@machine.name}"
55
-
56
- clients = []
57
- server = TCPServer.new config.ip, config.port
58
-
59
- callback = Proc.new do |modified, added, removed|
60
- bad_clients = []
61
- # @ui.info "Listen fired - #{clients.count} clients.\n #{modified}\n #{added}\n #{removed}"
62
- clients.each do |client|
63
- begin
64
- client.puts [modified, added, removed].to_json
65
- rescue Errno::EPIPE
66
- @ui.info "Connection broke! #{client}"
67
- # Don't want to change the list of threads as we iterate.
68
- bad_clients.push client
69
- end
70
- end
71
-
72
- bad_clients.each do |client|
73
- clients.delete client
74
- end
75
- end
76
- listener = Listen.to(*folders, &callback)
77
- listener.start
78
-
79
- # server.accept blocks - we need it in its own thread so we can
80
- # continue to have listener callbacks fired, and so we can sleep
81
- # and catch any interrupts from vagrant.
82
- Thread.new do
83
- loop do
84
- Thread.fork(server.accept) do |client|
85
- @ui.info "New connection - #{client}"
86
- clients.push client
87
- end
88
- end
89
- end
90
-
91
- # TODO: this error won't happen on the listen anymore - it will
92
- # happen somewhere on the tcp call. Not sure where.
93
- #
94
- # begin
95
- # listener.start
96
- # rescue Errno::EADDRNOTAVAIL
97
- # @ui.info "Can't start server - Port in use"
98
- # exit
99
- # end
100
-
101
- # Uhh... this needs work. Vagrant steals the interrupt from us and
102
- # there's no way to get it back
103
- # * https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/action/runner.rb#L49
104
- # Is there a way to register more callbacks to the busy block?
105
- # * https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/util/busy.rb
106
- while not env[:interrupted]
107
- sleep 1
108
- end
109
- @ui.info "Listen sleep finished"
110
- end
111
-
112
- Process.detach pid
113
- File.write config.pid_file, pid
114
- @ui.info "Listen server started on PID #{pid}"
15
+ # config = env[:machine].config.listen_server
16
+ vm = env[:machine]
17
+ Daemon.start vm
115
18
 
116
19
  out
117
20
  end
@@ -123,22 +26,11 @@ module VagrantPlugins
123
26
  end
124
27
 
125
28
  def call(env)
126
- @ui = env[:ui]
127
- config = env[:machine].config.listen_server
128
- @ui.info 'Killing listen server'
129
- if File.exists? config.pid_file
130
- pid = File.read config.pid_file
131
- begin
132
- Process.kill 'INT', pid.to_i
133
- rescue Errno::ESRCH
134
- @ui.info 'Stale PID file - no server found'
135
- end
136
- File.delete config.pid_file
137
- else
138
- @ui.info 'No listen server found'
139
- end
29
+ out = @app.call env
30
+ vm = env[:machine]
31
+ Daemon.stop vm
140
32
 
141
- @app.call(env)
33
+ out
142
34
  end
143
35
  end
144
36
  end
@@ -0,0 +1,35 @@
1
+ module VagrantPlugins
2
+ module ListenServer
3
+ class Command < Vagrant.plugin('2', :command)
4
+ def self.synopsis
5
+ "Check the status of the vagrant-listen server"
6
+ end
7
+
8
+ def execute
9
+ opts = OptionParser.new do |o|
10
+ o.banner = 'Usage: vagrant listen [start|stop|status]'
11
+ end
12
+
13
+ command = @argv.shift
14
+ argv = parse_options opts
15
+
16
+ with_target_vms nil, single_target: true do |vm|
17
+ # puts "ENV #{vm.env.inspect}"
18
+ # puts "CONFIG #{vm.config.inspect}"
19
+ # puts "LISTEN #{vm.config.listen_server.inspect}"
20
+
21
+ case command
22
+ when 'status' then Daemon.status vm.config.listen_server
23
+ when 'stop' then Daemon.stop vm
24
+ when 'start' then Daemon.start vm
25
+ else
26
+ puts 'Unknown command'
27
+ exit 1
28
+ end
29
+ end
30
+
31
+ 0
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,201 @@
1
+ def array_wrap object
2
+ if object.nil?
3
+ []
4
+ elsif object.respond_to?(:to_ary)
5
+ object.to_ary || [object]
6
+ else
7
+ [object]
8
+ end
9
+ end
10
+
11
+
12
+ # TODO: pre-fork use vagrant logging, post fork use puts.
13
+ def log message
14
+ puts message
15
+ end
16
+
17
+
18
+ module Daemon
19
+ def self.status_code config
20
+ return :stopped unless File.exists? config.pid_file
21
+
22
+ pid = File.read config.pid_file
23
+ begin
24
+ Process.getpgid pid.to_i
25
+ return pid.to_i
26
+ rescue Errno::ESRCH
27
+ return :stale
28
+ end
29
+ :stopped
30
+ end
31
+
32
+ def self.status config
33
+ code = self.status_code config
34
+ case code
35
+ when Fixnum then log "Running - PID: #{code}"
36
+ when :stopped then log 'Stopped'
37
+ when :stale then log 'Stopped. Stale PID file.'
38
+ else
39
+ log "Unknown status - #{code}"
40
+ end
41
+ end
42
+
43
+ # Wasted way too long trying to use Process.daemon. Doing it by hand. Code
44
+ # courtesy of:
45
+ # https://gist.github.com/mynameisrufus/1372491/b76b60fb1842bf0507f47869ab19ad50a045b214
46
+ # See also:
47
+ # * http://stackoverflow.com/questions/1740308/create-a-daemon-with-double-fork-in-ruby
48
+ # * http://allenlsy.com/working-with-unix-process-in-ruby/
49
+ #
50
+ # Related: Process.detach isn't what you think. It creates a process to
51
+ # monitor the child so that this can exit without creating a zombie. Because
52
+ # we want to remove parents, this actually makes life harder than just doing
53
+ # a double fork.
54
+ #
55
+ # Vagrant-notify uses fork as well, but that doesn't work on windows:
56
+ # https://github.com/fgrehm/vagrant-notify/blob/master/lib/vagrant-notify/server.rb
57
+ # Only real option is to switch to Process.spawn? I need a windows
58
+ # machine to test it out on... Vagrant::Util::Subprocess allows spawning an
59
+ # executable, but I don't know how to make that launch the included ruby
60
+ # binary and make sure it's running the right file.
61
+ def self.daemonize! out='/dev/null', err='/dev/null'
62
+ raise 'First fork failed' if (pid = fork) == -1
63
+ return nil unless pid.nil?
64
+ Process.setsid
65
+ raise 'Second fork failed' if (pid = fork) == -1
66
+ exit unless pid.nil?
67
+
68
+ # Dir.chdir '/'
69
+ # File.umask 0000
70
+
71
+ $stdin.reopen '/dev/null'
72
+ $stdout.reopen File.new(out, "a")
73
+ $stderr.reopen File.new(err, "a")
74
+ $stdout.sync = $stderr.sync = true
75
+
76
+ Process.pid
77
+ end
78
+
79
+
80
+ def self.start vm
81
+ config = vm.config.listen_server
82
+ log "Starting listen server - #{config.ip}:#{config.port}"
83
+
84
+ status = self.status_code config
85
+ if status == :running
86
+ log 'Server already running.'
87
+ return 1
88
+ end
89
+
90
+ File.delete config.pid_file if status == :stale
91
+
92
+ # TODO: use machine name in log file name.
93
+ # TODO: use machine name in PID file and drop it from config.
94
+ pid = daemonize! '/tmp/listen.log', '/tmp/listen.log'
95
+ # Usually a daemon wants the parent to exit here, but we need vagrant to
96
+ # keep going with its init process.
97
+ return unless pid
98
+
99
+ $0 = "vagrant-listen-server - #{vm.name}"
100
+
101
+ File.write config.pid_file, pid
102
+
103
+ log "Listen server started on PID #{pid}"
104
+
105
+ clients = []
106
+ begin
107
+ server = TCPServer.new config.ip, config.port
108
+ rescue Errno::EADDRINUSE
109
+ log "Can't start server - Port in use"
110
+ exit 1
111
+ end
112
+
113
+ send_to_clients = Proc.new do |type, data|
114
+ bad_clients = []
115
+ log "Sending #{type} to #{clients.count} clients."
116
+
117
+ clients.each do |client|
118
+ begin
119
+ client.puts ({type: type, data: data}).to_json
120
+ rescue Errno::EPIPE
121
+ log "Connection broke! #{client}"
122
+ # Don't want to change the list of threads as we iterate.
123
+ bad_clients.push client
124
+ end
125
+ end
126
+
127
+ bad_clients.each do |client|
128
+ clients.delete client
129
+ end
130
+ end
131
+
132
+ callback = Proc.new do |modified, added, removed|
133
+ log "Listen fired"
134
+ send_to_clients.call :listen, [modified, added, removed]
135
+ end
136
+
137
+ folders = array_wrap config.folders
138
+
139
+ # There is a recurring bug that keeps popping up in listen where only the
140
+ # first directory is watched. Create a new listen object for each folder as
141
+ # a workaround.
142
+ # https://github.com/guard/listen/issues/243
143
+ listeners = folders.map do |folder|
144
+ Listen.to(folder, &callback)
145
+ end
146
+
147
+ listeners.each &:start
148
+
149
+ # server.accept is blocking - we need it in its own thread so we can
150
+ # continue to have listener callbacks fired, and so we can sleep and catch
151
+ # any interrupts.
152
+ Thread.new do
153
+ loop do
154
+ Thread.fork(server.accept) do |client|
155
+ log "New connection - #{client}"
156
+ clients.push client
157
+
158
+ loop do
159
+ line = client.gets.chomp
160
+ # Currently, the only message type is a ping. Don't bother checking
161
+ # type for now.
162
+ data = JSON.parse line
163
+ log 'ping received'
164
+ client.puts ({type: 'pong', data: data['message']}).to_json
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ exiting = false
171
+ Signal.trap 'INT' do
172
+ log 'SIGINT caught'
173
+ exiting = true
174
+ end
175
+
176
+ while not exiting
177
+ # Original idea was to have the server ping. This requires more work on
178
+ # the client for a basic implementation though, so now the client pings.
179
+ # send_to_clients.call :echo, 'ping'
180
+ sleep 0.5
181
+ end
182
+
183
+ listeners.each &:stop
184
+ log "Listen sleep finished"
185
+ end
186
+
187
+
188
+ def self.stop vm
189
+ log 'Killing listen server'
190
+ config = vm.config.listen_server
191
+ status = self.status_code config
192
+ unless status.is_a? Fixnum
193
+ log 'Server is not running.'
194
+ return 1
195
+ end
196
+
197
+ pid = File.read config.pid_file
198
+ Process.kill 'INT', pid.to_i
199
+ File.delete config.pid_file
200
+ end
201
+ end
@@ -1,4 +1,5 @@
1
1
  require_relative 'action'
2
+ require_relative 'daemon'
2
3
 
3
4
  require 'rbconfig'
4
5
  os = RbConfig::CONFIG['target_os']
@@ -23,6 +24,11 @@ module VagrantPlugins
23
24
  Config
24
25
  end
25
26
 
27
+ command :listen do
28
+ require_relative 'command'
29
+ Command
30
+ end
31
+
26
32
  action_hook(:listen_server, :machine_action_up) do |hook|
27
33
  hook.append(Action::StartServer)
28
34
  end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module ListenServer
3
- VERSION = '0.0.5'
3
+ VERSION = '0.2.0'
4
4
  end
5
5
  end
@@ -17,9 +17,13 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ['lib']
19
19
 
20
+ # Shouldn't have to do this, but we want to make sure not to tie to an old
21
+ # version of listen and accidentally pull in the celluloid dependency.
22
+ spec.add_runtime_dependency 'listen', '~> 3.0', '>= 3.0.2'
23
+
24
+ spec.add_dependency 'rb-kqueue', '~> 0.2', '>= 0.2.3'
20
25
  spec.add_dependency 'rb-inotify', '~> 0.9', '>= 0.9.5'
21
26
  spec.add_dependency 'rb-fsevent', '~> 0.9', '>= 0.9.4'
22
- spec.add_dependency 'rb-kqueue', '~> 0.2', '>= 0.2.3'
23
27
  # wdm is already included in the vagrant gem spec.
24
28
  # spec.add_runtime_dependency 'wdm', '~> 0.10', '>= 0.10.0'
25
29
 
metadata CHANGED
@@ -1,37 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-listen-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Kelso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-18 00:00:00.000000000 Z
11
+ date: 2015-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rb-inotify
14
+ name: listen
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.9'
19
+ version: '3.0'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 0.9.5
22
+ version: 3.0.2
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '0.9'
29
+ version: '3.0'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 0.9.5
32
+ version: 3.0.2
33
33
  - !ruby/object:Gem::Dependency
34
- name: rb-fsevent
34
+ name: rb-kqueue
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.2'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.2.3
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '0.2'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.2.3
53
+ - !ruby/object:Gem::Dependency
54
+ name: rb-inotify
35
55
  requirement: !ruby/object:Gem::Requirement
36
56
  requirements:
37
57
  - - "~>"
@@ -39,7 +59,7 @@ dependencies:
39
59
  version: '0.9'
40
60
  - - ">="
41
61
  - !ruby/object:Gem::Version
42
- version: 0.9.4
62
+ version: 0.9.5
43
63
  type: :runtime
44
64
  prerelease: false
45
65
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,27 +69,27 @@ dependencies:
49
69
  version: '0.9'
50
70
  - - ">="
51
71
  - !ruby/object:Gem::Version
52
- version: 0.9.4
72
+ version: 0.9.5
53
73
  - !ruby/object:Gem::Dependency
54
- name: rb-kqueue
74
+ name: rb-fsevent
55
75
  requirement: !ruby/object:Gem::Requirement
56
76
  requirements:
57
77
  - - "~>"
58
78
  - !ruby/object:Gem::Version
59
- version: '0.2'
79
+ version: '0.9'
60
80
  - - ">="
61
81
  - !ruby/object:Gem::Version
62
- version: 0.2.3
82
+ version: 0.9.4
63
83
  type: :runtime
64
84
  prerelease: false
65
85
  version_requirements: !ruby/object:Gem::Requirement
66
86
  requirements:
67
87
  - - "~>"
68
88
  - !ruby/object:Gem::Version
69
- version: '0.2'
89
+ version: '0.9'
70
90
  - - ">="
71
91
  - !ruby/object:Gem::Version
72
- version: 0.2.3
92
+ version: 0.9.4
73
93
  - !ruby/object:Gem::Dependency
74
94
  name: bundler
75
95
  requirement: !ruby/object:Gem::Requirement
@@ -113,7 +133,9 @@ files:
113
133
  - examples/node-client.js
114
134
  - lib/vagrant-listen-server.rb
115
135
  - lib/vagrant-listen-server/action.rb
136
+ - lib/vagrant-listen-server/command.rb
116
137
  - lib/vagrant-listen-server/config.rb
138
+ - lib/vagrant-listen-server/daemon.rb
117
139
  - lib/vagrant-listen-server/plugin.rb
118
140
  - lib/vagrant-listen-server/version.rb
119
141
  - vagrant-listen-server.gemspec