zeus 0.15.4 → 0.15.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +5 -1
- data/Gemfile.lock +24 -13
- data/bin/pry +16 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/build/zeus-darwin-amd64 +0 -0
- data/build/zeus-linux-386 +0 -0
- data/build/zeus-linux-amd64 +0 -0
- data/lib/zeus.rb +25 -19
- data/lib/zeus/load_tracking.rb +38 -12
- data/lib/zeus/m.rb +3 -13
- data/lib/zeus/rails.rb +21 -20
- data/lib/zeus/version.rb +1 -1
- data/man/build/zeus +1 -1
- data/man/build/zeus-init +1 -1
- data/man/build/zeus-init.txt +1 -1
- data/man/build/zeus-start +1 -1
- data/man/build/zeus-start.txt +1 -1
- data/man/build/zeus.txt +1 -1
- data/spec/assets/exit.rb +1 -0
- data/spec/assets/invalid_syntax.rb +2 -0
- data/spec/assets/load.rb +2 -0
- data/spec/assets/raise.rb +3 -0
- data/spec/assets/require.rb +2 -0
- data/spec/assets/require_relative.rb +2 -0
- data/spec/assets/runtime_error.rb +2 -0
- data/spec/assets/single_file.rb +2 -0
- data/spec/fake_mini_test.rb +17 -6
- data/spec/load_tracking_spec.rb +105 -0
- data/spec/m_spec.rb +35 -16
- data/spec/rails_spec.rb +48 -8
- data/zeus.gemspec +2 -2
- metadata +30 -36
- data/.DS_Store +0 -0
- data/build/fsevents-wrapper +0 -0
- data/ext/inotify-wrapper/extconf.rb +0 -24
- data/ext/inotify-wrapper/inotify-wrapper.cpp +0 -117
- data/spec/spec_helper.rb +0 -38
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 2f28b5877e1a9f2d864f994db8ec997e2bfd2e88
|
|
4
|
+
data.tar.gz: 7e71058d4c5171c6992f5074e5f1df204392019f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4c369f05160ce2dbbb0b631af280f73bc19bdfa524109e03d33c9ef0216f33b0c47e1289d248e7d7b462c275d7960da72acfee86f2dd2c05f47682278cc0a4da
|
|
7
|
+
data.tar.gz: 266f75f0595297687016d2af1d7d7319f62f83a45a8ed815c56c73a2385bd40e46b75478c5f3221dc358a752283b1e0455abb4fe00bbbaefcc64d567db136c73
|
data/Gemfile
CHANGED
|
@@ -3,5 +3,9 @@ source 'https://rubygems.org'
|
|
|
3
3
|
# NOTE: Avoid putting development deps in gemspec
|
|
4
4
|
gemspec development_group: :gem_build_tools
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
group :test, :development do
|
|
7
|
+
gem 'rspec', '~> 3.1'
|
|
8
|
+
gem 'pry', '~> 0.10'
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
gem 'rake', group: :gem_build_tools
|
data/Gemfile.lock
CHANGED
|
@@ -1,33 +1,44 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
zeus (0.15.
|
|
4
|
+
zeus (0.15.10)
|
|
5
5
|
method_source (>= 0.6.7)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
+
coderay (1.1.1)
|
|
10
11
|
diff-lcs (1.2.5)
|
|
11
12
|
method_source (0.8.2)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
rspec
|
|
18
|
-
rspec-
|
|
19
|
-
|
|
13
|
+
pry (0.10.3)
|
|
14
|
+
coderay (~> 1.1.0)
|
|
15
|
+
method_source (~> 0.8.1)
|
|
16
|
+
slop (~> 3.4)
|
|
17
|
+
rake (11.1.2)
|
|
18
|
+
rspec (3.4.0)
|
|
19
|
+
rspec-core (~> 3.4.0)
|
|
20
|
+
rspec-expectations (~> 3.4.0)
|
|
21
|
+
rspec-mocks (~> 3.4.0)
|
|
22
|
+
rspec-core (3.4.4)
|
|
23
|
+
rspec-support (~> 3.4.0)
|
|
24
|
+
rspec-expectations (3.4.0)
|
|
20
25
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
21
|
-
rspec-support (~> 3.
|
|
22
|
-
rspec-mocks (3.1
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
rspec-support (~> 3.4.0)
|
|
27
|
+
rspec-mocks (3.4.1)
|
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
29
|
+
rspec-support (~> 3.4.0)
|
|
30
|
+
rspec-support (3.4.1)
|
|
31
|
+
slop (3.6.0)
|
|
25
32
|
|
|
26
33
|
PLATFORMS
|
|
27
34
|
ruby
|
|
28
35
|
|
|
29
36
|
DEPENDENCIES
|
|
30
37
|
bundler (~> 1.6)
|
|
38
|
+
pry (~> 0.10)
|
|
31
39
|
rake
|
|
32
40
|
rspec (~> 3.1)
|
|
33
41
|
zeus!
|
|
42
|
+
|
|
43
|
+
BUNDLED WITH
|
|
44
|
+
1.12.3
|
data/bin/pry
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# This file was generated by Bundler.
|
|
4
|
+
#
|
|
5
|
+
# The application 'pry' is installed as part of a gem, and
|
|
6
|
+
# this file is here to facilitate running it.
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
require 'pathname'
|
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
|
11
|
+
Pathname.new(__FILE__).realpath)
|
|
12
|
+
|
|
13
|
+
require 'rubygems'
|
|
14
|
+
require 'bundler/setup'
|
|
15
|
+
|
|
16
|
+
load Gem.bin_path('pry', 'pry')
|
data/bin/rake
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# This file was generated by Bundler.
|
|
4
|
+
#
|
|
5
|
+
# The application 'rake' is installed as part of a gem, and
|
|
6
|
+
# this file is here to facilitate running it.
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
require 'pathname'
|
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
|
11
|
+
Pathname.new(__FILE__).realpath)
|
|
12
|
+
|
|
13
|
+
require 'rubygems'
|
|
14
|
+
require 'bundler/setup'
|
|
15
|
+
|
|
16
|
+
load Gem.bin_path('rake', 'rake')
|
data/bin/rspec
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# This file was generated by Bundler.
|
|
4
|
+
#
|
|
5
|
+
# The application 'rspec' is installed as part of a gem, and
|
|
6
|
+
# this file is here to facilitate running it.
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
require 'pathname'
|
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
|
11
|
+
Pathname.new(__FILE__).realpath)
|
|
12
|
+
|
|
13
|
+
require 'rubygems'
|
|
14
|
+
require 'bundler/setup'
|
|
15
|
+
|
|
16
|
+
load Gem.bin_path('rspec-core', 'rspec')
|
data/build/zeus-darwin-amd64
CHANGED
|
Binary file
|
data/build/zeus-linux-386
CHANGED
|
Binary file
|
data/build/zeus-linux-amd64
CHANGED
|
Binary file
|
data/lib/zeus.rb
CHANGED
|
@@ -65,17 +65,11 @@ module Zeus
|
|
|
65
65
|
master.send_io(remote)
|
|
66
66
|
|
|
67
67
|
# Now I need to tell the master about my PID and ID
|
|
68
|
-
local.write "P:#{Process.pid}:#{identifier}\0"
|
|
68
|
+
local.write "P:#{Process.pid}:#{@parent_pid || 0}:#{identifier}\0"
|
|
69
69
|
local.send_io(feature_pipe_r)
|
|
70
70
|
feature_pipe_r.close
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
features = Zeus::LoadTracking.features_loaded_by {
|
|
74
|
-
run_action(local, identifier, feature_pipe_w)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
# the master wants to know about the files that running the action caused us to load.
|
|
78
|
-
Thread.new { notify_features(feature_pipe_w, features) }
|
|
72
|
+
run_action(local, identifier, feature_pipe_w)
|
|
79
73
|
|
|
80
74
|
# We are now 'connected'. From this point, we may receive requests to fork.
|
|
81
75
|
children = Set.new
|
|
@@ -93,15 +87,20 @@ module Zeus
|
|
|
93
87
|
messages.split("\0").each do |new_identifier|
|
|
94
88
|
new_identifier =~ /^(.):(.*)/
|
|
95
89
|
code, ident = $1, $2
|
|
90
|
+
|
|
91
|
+
forked_from = Process.pid
|
|
92
|
+
|
|
96
93
|
pid = fork
|
|
97
94
|
if pid
|
|
98
95
|
# We're in the parent. Record the child:
|
|
99
96
|
children << pid
|
|
100
97
|
elsif code == "S"
|
|
101
98
|
# Child, supposed to start another step:
|
|
99
|
+
@parent_pid = forked_from
|
|
102
100
|
throw(:boot_step, ident.to_sym)
|
|
103
101
|
else
|
|
104
102
|
# Child, supposed to run a command:
|
|
103
|
+
@parent_pid = forked_from
|
|
105
104
|
return [ident.to_sym, local]
|
|
106
105
|
end
|
|
107
106
|
end
|
|
@@ -137,7 +136,7 @@ module Zeus
|
|
|
137
136
|
|
|
138
137
|
plan.after_fork
|
|
139
138
|
client_terminal = local.recv_io
|
|
140
|
-
local.write "P:#{Process.pid}:\0"
|
|
139
|
+
local.write "P:#{Process.pid}:#{@parent_pid}:\0"
|
|
141
140
|
local.close
|
|
142
141
|
|
|
143
142
|
$stdin.reopen(client_terminal)
|
|
@@ -194,20 +193,27 @@ module Zeus
|
|
|
194
193
|
end
|
|
195
194
|
|
|
196
195
|
def run_action(socket, identifier, feature_pipe_w)
|
|
197
|
-
|
|
198
|
-
|
|
196
|
+
# Now we run the action and report its success/fail status to the master.
|
|
197
|
+
features, err = Zeus::LoadTracking.features_loaded_by do
|
|
199
198
|
plan.after_fork unless identifier == :boot
|
|
200
199
|
plan.send(identifier)
|
|
201
|
-
|
|
202
|
-
socket.write "R:OK\0"
|
|
203
|
-
rescue Exception => e
|
|
204
|
-
report_error_to_master(socket, e)
|
|
200
|
+
end
|
|
205
201
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
if err
|
|
203
|
+
# If we received an error, report features to the master syncronously.
|
|
204
|
+
# We need to do this before reporting the error to the master
|
|
205
|
+
# otherwise it will kill us before we can report features.
|
|
206
|
+
begin
|
|
207
|
+
notify_features(feature_pipe_w, features)
|
|
208
|
+
feature_pipe_w.close
|
|
209
|
+
ensure
|
|
210
|
+
report_error_to_master(socket, err)
|
|
209
211
|
end
|
|
210
|
-
|
|
212
|
+
else
|
|
213
|
+
# If we booted successfully, report features in a new thread
|
|
214
|
+
# so we can immediately begin listening for commands.
|
|
215
|
+
socket.write "R:OK\0"
|
|
216
|
+
Thread.new { notify_features(feature_pipe_w, features) }
|
|
211
217
|
end
|
|
212
218
|
end
|
|
213
219
|
end
|
data/lib/zeus/load_tracking.rb
CHANGED
|
@@ -1,23 +1,47 @@
|
|
|
1
1
|
module Zeus
|
|
2
2
|
class LoadTracking
|
|
3
3
|
class << self
|
|
4
|
-
|
|
5
4
|
def features_loaded_by(&block)
|
|
6
|
-
old_features = all_features
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
old_features = all_features
|
|
6
|
+
|
|
7
|
+
# Catch exceptions so we can determine the features
|
|
8
|
+
# that were being loaded at the time of the exception.
|
|
9
|
+
err_features = []
|
|
10
|
+
begin
|
|
11
|
+
yield
|
|
12
|
+
rescue SyntaxError => err
|
|
13
|
+
# SyntaxErrors are a bit weird in that the file containing
|
|
14
|
+
# the error is not in the backtrace, only the error message.
|
|
15
|
+
match = /\A([^:]+):\d+: syntax error/.match(err.message)
|
|
16
|
+
err_features << match[1] if match
|
|
17
|
+
rescue Exception => err
|
|
18
|
+
# Just capture this to add to the err_features list
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if err && err.backtrace
|
|
22
|
+
err_features += err.backtrace.map { |b| b.split(':').first }
|
|
23
|
+
.select { |f| f.start_with?('/') }
|
|
24
|
+
.take_while { |f| f != __FILE__ }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
new_features = all_features + err_features - old_features
|
|
28
|
+
new_features.uniq!
|
|
29
|
+
|
|
30
|
+
[new_features, err]
|
|
10
31
|
end
|
|
11
32
|
|
|
33
|
+
# Check the load path first to see if the file getting loaded is already
|
|
34
|
+
# loaded. Otherwise, add the file to the $untracked_features array which
|
|
35
|
+
# then gets added to $LOADED_FEATURES array.
|
|
12
36
|
def add_feature(file)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
37
|
+
full_path = File.expand_path(file)
|
|
38
|
+
|
|
39
|
+
if find_in_load_path(full_path) || File.exist?(full_path)
|
|
40
|
+
add_extra_feature(full_path)
|
|
17
41
|
end
|
|
18
|
-
add_extra_feature(path) if path
|
|
19
42
|
end
|
|
20
43
|
|
|
44
|
+
# $LOADED_FEATURES global variable is used internally by Rubygems
|
|
21
45
|
def all_features
|
|
22
46
|
untracked = defined?($untracked_features) ? $untracked_features : []
|
|
23
47
|
$LOADED_FEATURES + untracked
|
|
@@ -30,18 +54,20 @@ module Zeus
|
|
|
30
54
|
$untracked_features << path
|
|
31
55
|
end
|
|
32
56
|
|
|
33
|
-
def find_in_load_path(
|
|
34
|
-
$LOAD_PATH.
|
|
57
|
+
def find_in_load_path(file_path)
|
|
58
|
+
$LOAD_PATH.detect { |path| path == file_path }
|
|
35
59
|
end
|
|
36
60
|
end
|
|
37
61
|
end
|
|
38
62
|
end
|
|
39
63
|
|
|
64
|
+
|
|
40
65
|
module Kernel
|
|
41
66
|
|
|
42
67
|
def load(file, *a)
|
|
43
68
|
Kernel.load(file, *a)
|
|
44
69
|
end
|
|
70
|
+
private :load
|
|
45
71
|
|
|
46
72
|
class << self
|
|
47
73
|
alias_method :__load_without_zeus, :load
|
data/lib/zeus/m.rb
CHANGED
|
@@ -194,12 +194,9 @@ module Zeus
|
|
|
194
194
|
|
|
195
195
|
# directly run the tests from here and exit with the status of the tests passing or failing
|
|
196
196
|
case framework
|
|
197
|
-
when :minitest5
|
|
198
|
-
|
|
199
|
-
exit
|
|
200
|
-
when :minitest_old
|
|
201
|
-
nerf_test_unit_autorunner
|
|
202
|
-
exit(MiniTest::Unit.runner.run(test_arguments).to_i)
|
|
197
|
+
when :minitest5, :minitest_old
|
|
198
|
+
ARGV.replace(test_arguments)
|
|
199
|
+
exit
|
|
203
200
|
when :testunit1, :testunit2
|
|
204
201
|
exit Test::Unit::AutoRunner.run(false, nil, test_arguments)
|
|
205
202
|
else
|
|
@@ -348,13 +345,6 @@ module Zeus
|
|
|
348
345
|
end
|
|
349
346
|
end
|
|
350
347
|
|
|
351
|
-
def nerf_test_unit_autorunner
|
|
352
|
-
return unless defined?(Test::Unit::Runner)
|
|
353
|
-
if Test::Unit::Runner.class_variable_get("@@installed_at_exit")
|
|
354
|
-
Test::Unit::Runner.class_variable_set("@@stop_auto_run", true)
|
|
355
|
-
end
|
|
356
|
-
end
|
|
357
|
-
|
|
358
348
|
# Fail loudly if this isn't supported
|
|
359
349
|
def not_supported
|
|
360
350
|
abort "This test framework is not supported! Please open up an issue at https://github.com/qrush/m !"
|
data/lib/zeus/rails.rb
CHANGED
|
@@ -131,6 +131,13 @@ module Zeus
|
|
|
131
131
|
require 'rails/commands/console'
|
|
132
132
|
|
|
133
133
|
if defined?(Pry)
|
|
134
|
+
# Adding Rails Console helpers to Pry.
|
|
135
|
+
if (3..4).include?(::Rails::VERSION::MAJOR)
|
|
136
|
+
require 'rails/console/app'
|
|
137
|
+
require 'rails/console/helpers'
|
|
138
|
+
TOPLEVEL_BINDING.eval('self').extend ::Rails::ConsoleMethods
|
|
139
|
+
end
|
|
140
|
+
|
|
134
141
|
Pry.start
|
|
135
142
|
else
|
|
136
143
|
::Rails::Console.start(::Rails.application)
|
|
@@ -174,20 +181,6 @@ module Zeus
|
|
|
174
181
|
end
|
|
175
182
|
|
|
176
183
|
def test_helper
|
|
177
|
-
# don't let minitest setup another exit hook
|
|
178
|
-
begin
|
|
179
|
-
require 'minitest/unit'
|
|
180
|
-
if defined?(Minitest::Runnable)
|
|
181
|
-
# Minitest 5
|
|
182
|
-
MiniTest.class_variable_set('@@installed_at_exit', true)
|
|
183
|
-
elsif defined?(MiniTest)
|
|
184
|
-
# Old versions of Minitest
|
|
185
|
-
MiniTest::Unit.class_variable_set("@@installed_at_exit", true)
|
|
186
|
-
end
|
|
187
|
-
rescue LoadError
|
|
188
|
-
# noop
|
|
189
|
-
end
|
|
190
|
-
|
|
191
184
|
if ENV['RAILS_TEST_HELPER']
|
|
192
185
|
require ENV['RAILS_TEST_HELPER']
|
|
193
186
|
else
|
|
@@ -209,22 +202,30 @@ module Zeus
|
|
|
209
202
|
# if there are two test frameworks and one of them is RSpec,
|
|
210
203
|
# then "zeus test/rspec/testrb" without arguments runs the
|
|
211
204
|
# RSpec suite by default.
|
|
212
|
-
if
|
|
213
|
-
|
|
214
|
-
RSpec::Core::Runner.
|
|
215
|
-
argv = ["spec"] if argv.empty?
|
|
216
|
-
exit RSpec::Core::Runner.run(argv)
|
|
205
|
+
if using_rspec?(argv)
|
|
206
|
+
ARGV.replace(argv)
|
|
207
|
+
RSpec::Core::Runner.invoke
|
|
217
208
|
else
|
|
209
|
+
require 'minitest/autorun' if using_minitest?
|
|
210
|
+
# Minitest and old Test::Unit
|
|
218
211
|
Zeus::M.run(argv)
|
|
219
212
|
end
|
|
220
213
|
end
|
|
221
214
|
|
|
222
215
|
private
|
|
223
216
|
|
|
217
|
+
def using_rspec?(argv)
|
|
218
|
+
defined?(RSpec) && (argv.empty? || spec_file?(argv))
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def using_minitest?
|
|
222
|
+
defined?(:MiniTest) || defined?(:Minitest)
|
|
223
|
+
end
|
|
224
|
+
|
|
224
225
|
SPEC_DIR_REGEXP = %r"(^|/)spec"
|
|
225
226
|
SPEC_FILE_REGEXP = /.+_spec\.rb$/
|
|
226
227
|
|
|
227
|
-
def spec_file?
|
|
228
|
+
def spec_file?(argv)
|
|
228
229
|
argv.any? do |arg|
|
|
229
230
|
arg.match(Regexp.union(SPEC_DIR_REGEXP, SPEC_FILE_REGEXP))
|
|
230
231
|
end
|
data/lib/zeus/version.rb
CHANGED
data/man/build/zeus
CHANGED
data/man/build/zeus-init
CHANGED
data/man/build/zeus-init.txt
CHANGED
data/man/build/zeus-start
CHANGED
data/man/build/zeus-start.txt
CHANGED
data/man/build/zeus.txt
CHANGED
data/spec/assets/exit.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
exit(1)
|
data/spec/assets/load.rb
ADDED
data/spec/fake_mini_test.rb
CHANGED
|
@@ -1,20 +1,31 @@
|
|
|
1
|
-
module
|
|
2
|
-
|
|
1
|
+
module Minitest
|
|
2
|
+
class Runnable
|
|
3
|
+
end
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class MiniTest
|
|
7
|
+
class Unit
|
|
3
8
|
class TestCase
|
|
4
9
|
end
|
|
5
10
|
end
|
|
6
11
|
end
|
|
7
12
|
|
|
8
13
|
def stub_mini_test_methods
|
|
9
|
-
allow(
|
|
10
|
-
allow(MiniTest::Unit).to receive(:
|
|
14
|
+
allow(Minitest::Runnable).to receive(:runnables).and_return([fake_mt5_suite])
|
|
15
|
+
allow(MiniTest::Unit::TestCase).to receive(:test_suite).and_return([fake_mt_old_suite])
|
|
11
16
|
end
|
|
12
17
|
|
|
13
18
|
def fake_runner
|
|
14
|
-
|
|
19
|
+
@runner ||= double("Runner", :run => 0)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def fake_mt5_suite
|
|
23
|
+
@suite ||= double("TestSuite",
|
|
24
|
+
:runnable_methods => [test_method],
|
|
25
|
+
:instance_method => fake_instance_method(test_method))
|
|
15
26
|
end
|
|
16
27
|
|
|
17
|
-
def
|
|
28
|
+
def fake_mt_old_suite
|
|
18
29
|
@suite ||= double("TestSuite",
|
|
19
30
|
:test_methods => [test_method],
|
|
20
31
|
:instance_method => fake_instance_method(test_method))
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
require 'zeus/load_tracking'
|
|
2
|
+
|
|
3
|
+
describe "Zeus::LoadTracking" do
|
|
4
|
+
let(:test_filename) { __FILE__ }
|
|
5
|
+
let(:test_dirname) { File.dirname(test_filename) }
|
|
6
|
+
|
|
7
|
+
class MyError < StandardError; end
|
|
8
|
+
|
|
9
|
+
describe '.add_feature' do
|
|
10
|
+
context 'already in load path' do
|
|
11
|
+
before do
|
|
12
|
+
# add the dir path of the tempfile to LOAD_PATH
|
|
13
|
+
$LOAD_PATH << test_dirname
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
after { $LOAD_PATH.delete test_dirname }
|
|
17
|
+
|
|
18
|
+
it 'adds full filepath to $untracked_features' do
|
|
19
|
+
Zeus::LoadTracking.add_feature(test_filename)
|
|
20
|
+
|
|
21
|
+
expect($untracked_features).to include(__dir__ + "/load_tracking_spec.rb")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'not in load path' do
|
|
26
|
+
it 'adds full filepath to $untracked_features' do
|
|
27
|
+
Zeus::LoadTracking.add_feature(test_filename)
|
|
28
|
+
|
|
29
|
+
expect($untracked_features).to include(__dir__ + "/load_tracking_spec.rb")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context '.features_loaded_by' do
|
|
34
|
+
it 'returns list of new files loaded when block executes' do
|
|
35
|
+
new_files, = Zeus::LoadTracking.features_loaded_by do
|
|
36
|
+
$untracked_features << "an_untracked_feature.rb"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
expect(new_files).to eq(["an_untracked_feature.rb"])
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe '.features_loaded_by' do
|
|
45
|
+
def expect_to_load(expect_features, expect_err=NilClass)
|
|
46
|
+
new_files, err = Zeus::LoadTracking.features_loaded_by do
|
|
47
|
+
yield
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
expect(new_files.sort).to eq(expect_features.sort)
|
|
51
|
+
expect(err).to be_instance_of(expect_err)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def expand_asset_path(path)
|
|
55
|
+
File.join(__dir__, 'assets', path)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context 'loading valid code' do
|
|
59
|
+
it 'tracks successful require_relative' do
|
|
60
|
+
expect_to_load([expand_asset_path('require_relative.rb')]) do
|
|
61
|
+
require_relative 'assets/require_relative'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'tracks successful require' do
|
|
66
|
+
expect_to_load([expand_asset_path('require.rb')]) do
|
|
67
|
+
require expand_asset_path('require')
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'tracks loads' do
|
|
72
|
+
expect_to_load([expand_asset_path('load.rb')]) do
|
|
73
|
+
load expand_asset_path('load.rb')
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context 'loading invalid code' do
|
|
79
|
+
it 'tracks requires that raise a SyntaxError' do
|
|
80
|
+
expect_to_load([expand_asset_path('invalid_syntax.rb')], SyntaxError) do
|
|
81
|
+
require expand_asset_path('invalid_syntax')
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'tracks requires that raise a RuntimeError' do
|
|
86
|
+
expect_to_load([expand_asset_path('runtime_error.rb')], RuntimeError) do
|
|
87
|
+
require expand_asset_path('runtime_error')
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'tracks requires that exit' do
|
|
92
|
+
expect_to_load([expand_asset_path('exit.rb')], SystemExit) do
|
|
93
|
+
require expand_asset_path('exit')
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'tracks requires that throw in a method call' do
|
|
98
|
+
expect_to_load([expand_asset_path('raise.rb')], MyError) do
|
|
99
|
+
require expand_asset_path('raise')
|
|
100
|
+
raise_it(MyError)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
data/spec/m_spec.rb
CHANGED
|
@@ -1,11 +1,36 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'zeus/rails'
|
|
2
2
|
require 'fake_mini_test'
|
|
3
3
|
|
|
4
4
|
module Zeus::M
|
|
5
5
|
describe Runner do
|
|
6
6
|
let(:test_method) { fake_test_method }
|
|
7
7
|
|
|
8
|
+
matcher :exit_with_code do |exp_code|
|
|
9
|
+
actual = nil
|
|
10
|
+
match do |block|
|
|
11
|
+
begin
|
|
12
|
+
block.call
|
|
13
|
+
rescue SystemExit => e
|
|
14
|
+
actual = e.status
|
|
15
|
+
end
|
|
16
|
+
actual and actual == exp_code
|
|
17
|
+
end
|
|
18
|
+
failure_message do |_block|
|
|
19
|
+
"expected block to call exit(#{exp_code}) but exit" +
|
|
20
|
+
(actual.nil? ? " not called" : "(#{actual}) was called")
|
|
21
|
+
end
|
|
22
|
+
failure_message_when_negated do |_block|
|
|
23
|
+
"expected block not to call exit(#{exp_code})"
|
|
24
|
+
end
|
|
25
|
+
description do
|
|
26
|
+
"expect block to call exit(#{exp_code})"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
8
30
|
before(:each) do
|
|
31
|
+
allow(Dir).to receive(:glob).and_return(["path/to/file.rb"])
|
|
32
|
+
allow(Kernel).to receive(:load)
|
|
33
|
+
|
|
9
34
|
stub_mini_test_methods
|
|
10
35
|
end
|
|
11
36
|
|
|
@@ -15,17 +40,16 @@ module Zeus::M
|
|
|
15
40
|
it "escapes the question mark when using line number" do
|
|
16
41
|
argv = ["path/to/file.rb:2"]
|
|
17
42
|
|
|
18
|
-
expect(fake_runner).to receive(:run).with(["-n", "/(test_my_test_method\\?)/"])
|
|
19
|
-
|
|
20
43
|
expect(lambda { Runner.new(argv).run }).to exit_with_code(0)
|
|
44
|
+
expect(ARGV).to eq(["-n", "/(test_my_test_method\\?)/"])
|
|
21
45
|
end
|
|
22
46
|
|
|
23
47
|
it "does not escape regex on explicit names" do
|
|
24
48
|
argv = ["path/to/file.rb", "--name", fake_special_characters_test_method]
|
|
25
49
|
|
|
26
|
-
allow(fake_runner).to receive(:run).with(["-n", "test_my_test_method?"])
|
|
27
|
-
|
|
28
50
|
expect(lambda { Runner.new(argv).run }).to exit_with_code(0)
|
|
51
|
+
|
|
52
|
+
expect(ARGV).to eq(["-n", "test_my_test_method?"])
|
|
29
53
|
end
|
|
30
54
|
end
|
|
31
55
|
|
|
@@ -33,9 +57,9 @@ module Zeus::M
|
|
|
33
57
|
it "runs the test" do
|
|
34
58
|
argv = ["path/to/file.rb"]
|
|
35
59
|
|
|
36
|
-
allow(fake_runner).to receive(:run).with([])
|
|
37
|
-
|
|
38
60
|
expect(lambda { Runner.new(argv).run }).to exit_with_code(0)
|
|
61
|
+
|
|
62
|
+
expect(ARGV).to eq([])
|
|
39
63
|
end
|
|
40
64
|
end
|
|
41
65
|
|
|
@@ -44,7 +68,6 @@ module Zeus::M
|
|
|
44
68
|
argv = ["path/to/file.rb:100"]
|
|
45
69
|
|
|
46
70
|
expect(STDERR).to receive(:write).with(/No tests found on line 100/)
|
|
47
|
-
expect(fake_runner).to_not receive :run
|
|
48
71
|
|
|
49
72
|
expect(lambda { Runner.new(argv).run }).to_not exit_with_code(0)
|
|
50
73
|
end
|
|
@@ -52,9 +75,8 @@ module Zeus::M
|
|
|
52
75
|
it "runs the test if the correct line number is given" do
|
|
53
76
|
argv = ["path/to/file.rb:2"]
|
|
54
77
|
|
|
55
|
-
expect(fake_runner).to receive(:run).with(["-n", "/(#{fake_test_method})/"])
|
|
56
|
-
|
|
57
78
|
expect(lambda { Runner.new(argv).run }).to exit_with_code(0)
|
|
79
|
+
expect(ARGV).to eq(["-n", "/(#{fake_test_method})/"])
|
|
58
80
|
end
|
|
59
81
|
end
|
|
60
82
|
|
|
@@ -62,17 +84,15 @@ module Zeus::M
|
|
|
62
84
|
it "runs the specified tests when using a pattern in --name option" do
|
|
63
85
|
argv = ["path/to/file.rb", "--name", "/#{fake_test_method}/"]
|
|
64
86
|
|
|
65
|
-
expect(fake_runner).to receive(:run).with(["-n", "/#{fake_test_method}/"])
|
|
66
|
-
|
|
67
87
|
expect(lambda { Runner.new(argv).run }).to exit_with_code(0)
|
|
88
|
+
expect(ARGV).to eq(["-n", "/#{fake_test_method}/"])
|
|
68
89
|
end
|
|
69
90
|
|
|
70
91
|
it "runs the specified tests when using a pattern in -n option" do
|
|
71
92
|
argv = ["path/to/file.rb", "-n", "/method/"]
|
|
72
93
|
|
|
73
|
-
expect(fake_runner).to receive(:run).with(["-n", "/method/"])
|
|
74
|
-
|
|
75
94
|
expect(lambda { Runner.new(argv).run }).to exit_with_code(0)
|
|
95
|
+
expect(ARGV).to eq(["-n", "/method/"])
|
|
76
96
|
end
|
|
77
97
|
|
|
78
98
|
it "aborts if no test matches the given pattern" do
|
|
@@ -87,9 +107,8 @@ module Zeus::M
|
|
|
87
107
|
it "runs the specified tests when using a name (no pattern)" do
|
|
88
108
|
argv = ["path/to/file.rb", "-n", "#{fake_test_method}"]
|
|
89
109
|
|
|
90
|
-
expect(fake_runner).to receive(:run).with(["-n", fake_test_method])
|
|
91
|
-
|
|
92
110
|
expect(lambda { Runner.new(argv).run }).to exit_with_code(0)
|
|
111
|
+
expect(ARGV).to eq(["-n", fake_test_method])
|
|
93
112
|
end
|
|
94
113
|
|
|
95
114
|
it "aborts if no test matches the given test name" do
|
data/spec/rails_spec.rb
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'zeus/rails'
|
|
2
2
|
|
|
3
3
|
module Zeus
|
|
4
4
|
describe Rails do
|
|
5
5
|
subject(:rails) { Rails.new }
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
# We need to catch it first, before setting expectations on
|
|
11
|
-
# helper_file requires below.
|
|
12
|
-
expect(rails).to receive(:require).with("minitest/unit")
|
|
13
|
-
end
|
|
7
|
+
def mock_file_existence(file, result)
|
|
8
|
+
expect(File).to receive(:exists?).with(file).and_return(result)
|
|
9
|
+
end
|
|
14
10
|
|
|
11
|
+
describe "#test_helper" do
|
|
15
12
|
context "when ENV['RAILS_TEST_HELPER'] is set" do
|
|
16
13
|
it "loads the test helper file from the environment variable" do
|
|
17
14
|
helper = "a_test_helper"
|
|
@@ -84,5 +81,48 @@ module Zeus
|
|
|
84
81
|
end
|
|
85
82
|
end
|
|
86
83
|
end
|
|
84
|
+
|
|
85
|
+
describe "#test" do
|
|
86
|
+
def expect_minitest_autorun
|
|
87
|
+
# Zeus::Rails#test_helper will require minitest/unit by default.
|
|
88
|
+
# We need to catch it first, before setting expectations on
|
|
89
|
+
# helper_file requires below.
|
|
90
|
+
expect_any_instance_of(Rails).to receive(:require).with("minitest/autorun")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context 'minitest' do
|
|
94
|
+
before do
|
|
95
|
+
module Zeus::M
|
|
96
|
+
end
|
|
97
|
+
expect(Zeus::M).to receive(:run)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "requires autorun when testing with new minitest" do
|
|
101
|
+
module ::Minitest
|
|
102
|
+
end
|
|
103
|
+
expect_minitest_autorun
|
|
104
|
+
|
|
105
|
+
rails.test
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "requires autorun when testing with old minitest" do
|
|
109
|
+
expect_minitest_autorun
|
|
110
|
+
|
|
111
|
+
rails.test
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
context 'rspec' do
|
|
116
|
+
before do
|
|
117
|
+
class ::RSpec::Core::Runner
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "calls rspec core runner" do
|
|
122
|
+
expect(RSpec::Core::Runner).to receive(:invoke)
|
|
123
|
+
rails.test(['test_spec.rb'])
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
87
127
|
end
|
|
88
128
|
end
|
data/zeus.gemspec
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
version = begin
|
|
6
6
|
require File.expand_path('../lib/zeus/version', __FILE__)
|
|
7
7
|
Zeus::VERSION
|
|
8
|
-
rescue LoadError
|
|
8
|
+
rescue LoadError, NameError
|
|
9
9
|
"0.0.0"
|
|
10
10
|
end
|
|
11
11
|
|
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |gem|
|
|
|
19
19
|
gem.homepage = "http://zeus.is"
|
|
20
20
|
|
|
21
21
|
gem.files = files
|
|
22
|
-
gem.extensions = [
|
|
22
|
+
gem.extensions = []
|
|
23
23
|
gem.executables = ['zeus']
|
|
24
24
|
gem.test_files = []
|
|
25
25
|
gem.name = "zeus"
|
metadata
CHANGED
|
@@ -1,46 +1,41 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: zeus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.15.
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 0.15.10
|
|
6
5
|
platform: ruby
|
|
7
6
|
authors:
|
|
8
7
|
- Burke Libbey
|
|
9
8
|
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 2016-07-26 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: method_source
|
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
|
17
|
-
none: false
|
|
18
16
|
requirements:
|
|
19
|
-
- -
|
|
17
|
+
- - ">="
|
|
20
18
|
- !ruby/object:Gem::Version
|
|
21
19
|
version: 0.6.7
|
|
22
20
|
type: :runtime
|
|
23
21
|
prerelease: false
|
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
-
none: false
|
|
26
23
|
requirements:
|
|
27
|
-
- -
|
|
24
|
+
- - ">="
|
|
28
25
|
- !ruby/object:Gem::Version
|
|
29
26
|
version: 0.6.7
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
|
31
28
|
name: bundler
|
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
|
33
|
-
none: false
|
|
34
30
|
requirements:
|
|
35
|
-
- - ~>
|
|
31
|
+
- - "~>"
|
|
36
32
|
- !ruby/object:Gem::Version
|
|
37
33
|
version: '1.6'
|
|
38
34
|
type: :development
|
|
39
35
|
prerelease: false
|
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
-
none: false
|
|
42
37
|
requirements:
|
|
43
|
-
- - ~>
|
|
38
|
+
- - "~>"
|
|
44
39
|
- !ruby/object:Gem::Version
|
|
45
40
|
version: '1.6'
|
|
46
41
|
description: Boot any rails app in under a second
|
|
@@ -48,13 +43,17 @@ email:
|
|
|
48
43
|
- burke@libbey.me
|
|
49
44
|
executables:
|
|
50
45
|
- zeus
|
|
51
|
-
extensions:
|
|
52
|
-
- ext/inotify-wrapper/extconf.rb
|
|
46
|
+
extensions: []
|
|
53
47
|
extra_rdoc_files: []
|
|
54
48
|
files:
|
|
55
|
-
-
|
|
49
|
+
- Gemfile
|
|
50
|
+
- Gemfile.lock
|
|
51
|
+
- MIT-LICENSE
|
|
52
|
+
- Rakefile
|
|
53
|
+
- bin/pry
|
|
54
|
+
- bin/rake
|
|
55
|
+
- bin/rspec
|
|
56
56
|
- bin/zeus
|
|
57
|
-
- build/fsevents-wrapper
|
|
58
57
|
- build/zeus-darwin-amd64
|
|
59
58
|
- build/zeus-linux-386
|
|
60
59
|
- build/zeus-linux-amd64
|
|
@@ -62,61 +61,56 @@ files:
|
|
|
62
61
|
- examples/custom_plan/custom_plan.rb
|
|
63
62
|
- examples/custom_plan/zeus.json
|
|
64
63
|
- examples/zeus.json
|
|
65
|
-
-
|
|
66
|
-
- ext/inotify-wrapper/inotify-wrapper.cpp
|
|
67
|
-
- Gemfile
|
|
68
|
-
- Gemfile.lock
|
|
64
|
+
- lib/zeus.rb
|
|
69
65
|
- lib/zeus/load_tracking.rb
|
|
66
|
+
- lib/zeus/m.rb
|
|
70
67
|
- lib/zeus/m/test_collection.rb
|
|
71
68
|
- lib/zeus/m/test_method.rb
|
|
72
|
-
- lib/zeus/m.rb
|
|
73
69
|
- lib/zeus/plan.rb
|
|
74
70
|
- lib/zeus/rails.rb
|
|
75
71
|
- lib/zeus/version.rb
|
|
76
|
-
- lib/zeus.rb
|
|
77
72
|
- man/build/zeus
|
|
78
73
|
- man/build/zeus-init
|
|
79
74
|
- man/build/zeus-init.txt
|
|
80
75
|
- man/build/zeus-start
|
|
81
76
|
- man/build/zeus-start.txt
|
|
82
77
|
- man/build/zeus.txt
|
|
83
|
-
-
|
|
84
|
-
-
|
|
78
|
+
- spec/assets/exit.rb
|
|
79
|
+
- spec/assets/invalid_syntax.rb
|
|
80
|
+
- spec/assets/load.rb
|
|
81
|
+
- spec/assets/raise.rb
|
|
82
|
+
- spec/assets/require.rb
|
|
83
|
+
- spec/assets/require_relative.rb
|
|
84
|
+
- spec/assets/runtime_error.rb
|
|
85
|
+
- spec/assets/single_file.rb
|
|
85
86
|
- spec/fake_mini_test.rb
|
|
87
|
+
- spec/load_tracking_spec.rb
|
|
86
88
|
- spec/m_spec.rb
|
|
87
89
|
- spec/rails_spec.rb
|
|
88
|
-
- spec/spec_helper.rb
|
|
89
90
|
- zeus.gemspec
|
|
90
91
|
homepage: http://zeus.is
|
|
91
92
|
licenses:
|
|
92
93
|
- MIT
|
|
94
|
+
metadata: {}
|
|
93
95
|
post_install_message:
|
|
94
96
|
rdoc_options: []
|
|
95
97
|
require_paths:
|
|
96
98
|
- lib
|
|
97
99
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
|
-
none: false
|
|
99
100
|
requirements:
|
|
100
|
-
- -
|
|
101
|
+
- - ">="
|
|
101
102
|
- !ruby/object:Gem::Version
|
|
102
103
|
version: '0'
|
|
103
|
-
segments:
|
|
104
|
-
- 0
|
|
105
|
-
hash: -3287208852062006683
|
|
106
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
|
-
none: false
|
|
108
105
|
requirements:
|
|
109
|
-
- -
|
|
106
|
+
- - ">="
|
|
110
107
|
- !ruby/object:Gem::Version
|
|
111
108
|
version: '0'
|
|
112
|
-
segments:
|
|
113
|
-
- 0
|
|
114
|
-
hash: -3287208852062006683
|
|
115
109
|
requirements: []
|
|
116
110
|
rubyforge_project:
|
|
117
|
-
rubygems_version:
|
|
111
|
+
rubygems_version: 2.4.5.1
|
|
118
112
|
signing_key:
|
|
119
|
-
specification_version:
|
|
113
|
+
specification_version: 4
|
|
120
114
|
summary: Zeus is an intelligent preloader for ruby applications. It allows normal
|
|
121
115
|
development tasks to be run in a fraction of a second.
|
|
122
116
|
test_files: []
|
data/.DS_Store
DELETED
|
Binary file
|
data/build/fsevents-wrapper
DELETED
|
Binary file
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
if /linux/ =~ RUBY_PLATFORM
|
|
2
|
-
open("Makefile", "wb") do |f|
|
|
3
|
-
f.write <<-EOF
|
|
4
|
-
CXX = g++
|
|
5
|
-
CXXFLAGS = -O3 -g -Wall
|
|
6
|
-
|
|
7
|
-
inotify-wrapper: inotify-wrapper.o
|
|
8
|
-
$(CXX) $(CXXFLAGS) $< -o $@
|
|
9
|
-
|
|
10
|
-
%.o: %.cpp
|
|
11
|
-
$(CXX) $(CXXFLAGS) -c $< -o $@
|
|
12
|
-
|
|
13
|
-
install:
|
|
14
|
-
# do nothing
|
|
15
|
-
EOF
|
|
16
|
-
end
|
|
17
|
-
else
|
|
18
|
-
open("Makefile", "wb") do |f|
|
|
19
|
-
f.write <<-EOF
|
|
20
|
-
install:
|
|
21
|
-
# do nothing
|
|
22
|
-
EOF
|
|
23
|
-
end
|
|
24
|
-
end
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
#include <map>
|
|
2
|
-
#include <string>
|
|
3
|
-
|
|
4
|
-
#include <stdio.h>
|
|
5
|
-
#include <stdlib.h>
|
|
6
|
-
#include <string.h>
|
|
7
|
-
#include <errno.h>
|
|
8
|
-
#include <unistd.h>
|
|
9
|
-
#include <sys/types.h>
|
|
10
|
-
#include <sys/inotify.h>
|
|
11
|
-
|
|
12
|
-
#include <errno.h>
|
|
13
|
-
|
|
14
|
-
#define EVENT_SIZE (sizeof (struct inotify_event))
|
|
15
|
-
#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))
|
|
16
|
-
|
|
17
|
-
using namespace std;
|
|
18
|
-
|
|
19
|
-
static int _inotify_fd;
|
|
20
|
-
static map<int, string> _WatchedFiles;
|
|
21
|
-
static map<string, bool> _FileIsWatched;
|
|
22
|
-
|
|
23
|
-
// static int inotifyFlags = IN_ATTRIB | IN_MODIFY | IN_MOVE_SELF | IN_DELETE_SELF;
|
|
24
|
-
static int inotifyFlags = IN_ATTRIB | IN_MODIFY | IN_MOVE_SELF | IN_DELETE_SELF;
|
|
25
|
-
|
|
26
|
-
void maybeAddFileToWatchList(string file)
|
|
27
|
-
{
|
|
28
|
-
if (_FileIsWatched[file]) return;
|
|
29
|
-
|
|
30
|
-
int wd = inotify_add_watch(_inotify_fd, file.c_str(), inotifyFlags);
|
|
31
|
-
int attempts = 0;
|
|
32
|
-
// Files are momentarily inaccessible when they are rewritten. I couldn't
|
|
33
|
-
// find a good way to deal with this, so we poll 'deleted' files for 0.25s or so
|
|
34
|
-
// to see if they reappear.
|
|
35
|
-
while (wd == -1 && errno == ENOENT) {
|
|
36
|
-
usleep(10000);
|
|
37
|
-
wd = inotify_add_watch(_inotify_fd, file.c_str(), inotifyFlags);
|
|
38
|
-
if (attempts++ == 25) break; // try for at most about a quarter of a second
|
|
39
|
-
}
|
|
40
|
-
if (wd != -1) {
|
|
41
|
-
_WatchedFiles[wd] = file;
|
|
42
|
-
_FileIsWatched[file] = true;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// This essentially removes a file from the watchlist then
|
|
47
|
-
// immediately re-adds it. This is because when a file is rewritten,
|
|
48
|
-
// as so many editors love to do, the watchdescriptor no longer refers to
|
|
49
|
-
// the file, so re must re-watch the path.
|
|
50
|
-
void replaceFileInWatchList(int wd, string file)
|
|
51
|
-
{
|
|
52
|
-
_FileIsWatched.erase(file);
|
|
53
|
-
_WatchedFiles.erase(wd);
|
|
54
|
-
inotify_rm_watch(_inotify_fd, wd);
|
|
55
|
-
maybeAddFileToWatchList(file);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
void handleStdin()
|
|
59
|
-
{
|
|
60
|
-
char line[2048];
|
|
61
|
-
if (fgets(line, sizeof(line), stdin) == NULL) return;
|
|
62
|
-
line[strlen(line)-1] = 0;
|
|
63
|
-
|
|
64
|
-
maybeAddFileToWatchList(string(line));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
void handleInotify()
|
|
68
|
-
{
|
|
69
|
-
int length;
|
|
70
|
-
int i = 0;
|
|
71
|
-
char buffer[EVENT_BUF_LEN];
|
|
72
|
-
string filename;
|
|
73
|
-
|
|
74
|
-
length = read(_inotify_fd, buffer, EVENT_BUF_LEN);
|
|
75
|
-
if (length < 0) return;
|
|
76
|
-
|
|
77
|
-
while (i < length) {
|
|
78
|
-
struct inotify_event *event = (struct inotify_event *) &buffer[i];
|
|
79
|
-
string file = _WatchedFiles[event->wd];
|
|
80
|
-
if (file != "") {
|
|
81
|
-
printf("%s\n", file.c_str());
|
|
82
|
-
fflush(stdout);
|
|
83
|
-
replaceFileInWatchList(event->wd, file);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
i += EVENT_SIZE + event->len;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
void go()
|
|
91
|
-
{
|
|
92
|
-
fd_set rfds;
|
|
93
|
-
int retval;
|
|
94
|
-
|
|
95
|
-
for (;;) {
|
|
96
|
-
FD_ZERO(&rfds);
|
|
97
|
-
FD_SET(0, &rfds);
|
|
98
|
-
FD_SET(_inotify_fd, &rfds);
|
|
99
|
-
|
|
100
|
-
retval = select(_inotify_fd+1, &rfds, NULL, NULL, NULL);
|
|
101
|
-
|
|
102
|
-
if (retval == -1) {
|
|
103
|
-
// perror("select");
|
|
104
|
-
} else if (retval) {
|
|
105
|
-
if(feof(stdin)) break;
|
|
106
|
-
if (FD_ISSET(0, &rfds)) handleStdin();
|
|
107
|
-
if (FD_ISSET(_inotify_fd, &rfds)) handleInotify();
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
int main(int argc, const char *argv[])
|
|
114
|
-
{
|
|
115
|
-
_inotify_fd = inotify_init();
|
|
116
|
-
go();
|
|
117
|
-
}
|
data/spec/spec_helper.rb
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
require 'zeus/rails'
|
|
2
|
-
|
|
3
|
-
RSpec::Matchers.define :exit_with_code do |exp_code|
|
|
4
|
-
actual = nil
|
|
5
|
-
match do |block|
|
|
6
|
-
begin
|
|
7
|
-
block.call
|
|
8
|
-
rescue SystemExit => e
|
|
9
|
-
actual = e.status
|
|
10
|
-
end
|
|
11
|
-
actual and actual == exp_code
|
|
12
|
-
end
|
|
13
|
-
failure_message do |block|
|
|
14
|
-
"expected block to call exit(#{exp_code}) but exit" +
|
|
15
|
-
(actual.nil? ? " not called" : "(#{actual}) was called")
|
|
16
|
-
end
|
|
17
|
-
failure_message_when_negated do |block|
|
|
18
|
-
"expected block not to call exit(#{exp_code})"
|
|
19
|
-
end
|
|
20
|
-
description do
|
|
21
|
-
"expect block to call exit(#{exp_code})"
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def stub_system_methods
|
|
26
|
-
allow(Dir).to receive(:glob).and_return(["path/to/file.rb"])
|
|
27
|
-
allow(Kernel).to receive(:load)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def mock_file_existence(file, result)
|
|
31
|
-
expect(File).to receive(:exists?).with(file).and_return(result)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
RSpec.configure do |config|
|
|
35
|
-
config.before(:each) do
|
|
36
|
-
stub_system_methods
|
|
37
|
-
end
|
|
38
|
-
end
|