spring 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +3 -0
- data/CHANGELOG.md +13 -2
- data/Gemfile +1 -1
- data/README.md +16 -11
- data/lib/spring/application.rb +97 -20
- data/lib/spring/application_manager.rb +16 -9
- data/lib/spring/client.rb +1 -1
- data/lib/spring/client/binstub.rb +1 -1
- data/lib/spring/client/rails.rb +8 -3
- data/lib/spring/client/run.rb +23 -6
- data/lib/spring/client/status.rb +2 -2
- data/lib/spring/commands.rb +3 -0
- data/lib/spring/commands/rails.rb +7 -0
- data/lib/spring/configuration.rb +1 -1
- data/lib/spring/env.rb +8 -2
- data/lib/spring/errors.rb +15 -1
- data/lib/spring/server.rb +27 -14
- data/lib/spring/version.rb +1 -1
- data/lib/spring/watcher.rb +1 -0
- data/lib/spring/watcher/abstract.rb +9 -7
- data/lib/spring/watcher/polling.rb +1 -1
- data/test/acceptance/app_test.rb +168 -86
- data/test/apps/.gitignore +3 -0
- data/test/unit/watcher_test.rb +12 -0
- metadata +4 -134
- data/test/apps/rails-3-2/.gitignore +0 -18
- data/test/apps/rails-3-2/Gemfile +0 -7
- data/test/apps/rails-3-2/README.rdoc +0 -261
- data/test/apps/rails-3-2/Rakefile +0 -7
- data/test/apps/rails-3-2/app/assets/images/rails.png +0 -0
- data/test/apps/rails-3-2/app/assets/javascripts/application.js +0 -15
- data/test/apps/rails-3-2/app/assets/javascripts/posts.js.coffee +0 -3
- data/test/apps/rails-3-2/app/assets/stylesheets/application.css +0 -13
- data/test/apps/rails-3-2/app/assets/stylesheets/posts.css.scss +0 -3
- data/test/apps/rails-3-2/app/assets/stylesheets/scaffolds.css.scss +0 -69
- data/test/apps/rails-3-2/app/controllers/application_controller.rb +0 -3
- data/test/apps/rails-3-2/app/controllers/posts_controller.rb +0 -83
- data/test/apps/rails-3-2/app/helpers/application_helper.rb +0 -2
- data/test/apps/rails-3-2/app/helpers/posts_helper.rb +0 -2
- data/test/apps/rails-3-2/app/mailers/.gitkeep +0 -0
- data/test/apps/rails-3-2/app/models/.gitkeep +0 -0
- data/test/apps/rails-3-2/app/models/post.rb +0 -3
- data/test/apps/rails-3-2/app/views/layouts/application.html.erb +0 -14
- data/test/apps/rails-3-2/app/views/posts/_form.html.erb +0 -21
- data/test/apps/rails-3-2/app/views/posts/edit.html.erb +0 -6
- data/test/apps/rails-3-2/app/views/posts/index.html.erb +0 -23
- data/test/apps/rails-3-2/app/views/posts/new.html.erb +0 -5
- data/test/apps/rails-3-2/app/views/posts/show.html.erb +0 -10
- data/test/apps/rails-3-2/config.ru +0 -4
- data/test/apps/rails-3-2/config/application.rb +0 -62
- data/test/apps/rails-3-2/config/boot.rb +0 -6
- data/test/apps/rails-3-2/config/database.yml +0 -25
- data/test/apps/rails-3-2/config/environment.rb +0 -5
- data/test/apps/rails-3-2/config/environments/development.rb +0 -37
- data/test/apps/rails-3-2/config/environments/production.rb +0 -67
- data/test/apps/rails-3-2/config/environments/test.rb +0 -37
- data/test/apps/rails-3-2/config/initializers/backtrace_silencers.rb +0 -7
- data/test/apps/rails-3-2/config/initializers/inflections.rb +0 -15
- data/test/apps/rails-3-2/config/initializers/mime_types.rb +0 -5
- data/test/apps/rails-3-2/config/initializers/secret_token.rb +0 -7
- data/test/apps/rails-3-2/config/initializers/session_store.rb +0 -8
- data/test/apps/rails-3-2/config/initializers/wrap_parameters.rb +0 -14
- data/test/apps/rails-3-2/config/locales/en.yml +0 -5
- data/test/apps/rails-3-2/config/routes.rb +0 -60
- data/test/apps/rails-3-2/config/spring.rb +0 -7
- data/test/apps/rails-3-2/db/migrate/20121109171227_create_posts.rb +0 -9
- data/test/apps/rails-3-2/db/schema.rb +0 -22
- data/test/apps/rails-3-2/db/seeds.rb +0 -7
- data/test/apps/rails-3-2/lib/assets/.gitkeep +0 -0
- data/test/apps/rails-3-2/lib/tasks/.gitkeep +0 -0
- data/test/apps/rails-3-2/log/.gitkeep +0 -0
- data/test/apps/rails-3-2/public/404.html +0 -26
- data/test/apps/rails-3-2/public/422.html +0 -26
- data/test/apps/rails-3-2/public/500.html +0 -25
- data/test/apps/rails-3-2/public/favicon.ico +0 -0
- data/test/apps/rails-3-2/public/index.html +0 -241
- data/test/apps/rails-3-2/public/robots.txt +0 -5
- data/test/apps/rails-3-2/script/rails +0 -6
- data/test/apps/rails-3-2/spec/dummy_spec.rb +0 -5
- data/test/apps/rails-3-2/test/fixtures/.gitkeep +0 -0
- data/test/apps/rails-3-2/test/fixtures/posts.yml +0 -7
- data/test/apps/rails-3-2/test/functional/.gitkeep +0 -0
- data/test/apps/rails-3-2/test/functional/posts_controller_test.rb +0 -49
- data/test/apps/rails-3-2/test/integration/.gitkeep +0 -0
- data/test/apps/rails-3-2/test/test_helper.rb +0 -13
- data/test/apps/rails-3-2/test/unit/.gitkeep +0 -0
- data/test/apps/rails-3-2/test/unit/helpers/posts_helper_test.rb +0 -4
- data/test/apps/rails-3-2/test/unit/post_test.rb +0 -7
- data/test/apps/rails-3-2/vendor/assets/javascripts/.gitkeep +0 -0
- data/test/apps/rails-3-2/vendor/assets/stylesheets/.gitkeep +0 -0
- data/test/apps/rails-3-2/vendor/plugins/.gitkeep +0 -0
data/lib/spring/client/status.rb
CHANGED
@@ -21,8 +21,8 @@ module Spring
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def application_pids
|
24
|
-
candidates = `ps -
|
25
|
-
candidates.select { |l| l =~
|
24
|
+
candidates = `ps -A -o ppid= -o pid=`.lines
|
25
|
+
candidates.select { |l| l =~ /^(\s+)?#{env.pid} / }
|
26
26
|
.map { |l| l.split(" ").last }
|
27
27
|
end
|
28
28
|
end
|
data/lib/spring/commands.rb
CHANGED
@@ -31,6 +31,9 @@ module Spring
|
|
31
31
|
|
32
32
|
# Load custom commands, if any.
|
33
33
|
# needs to be at the end to allow modification of existing commands.
|
34
|
+
config = File.expand_path("~/.spring.rb")
|
35
|
+
require config if File.exist?(config)
|
36
|
+
|
34
37
|
config = File.expand_path("./config/spring.rb")
|
35
38
|
require config if File.exist?(config)
|
36
39
|
end
|
@@ -28,6 +28,12 @@ module Spring
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
class RailsDestroy < Rails
|
32
|
+
def command_name
|
33
|
+
"destroy"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
31
37
|
class RailsRunner < Rails
|
32
38
|
def env(tail)
|
33
39
|
previous_option = nil
|
@@ -48,6 +54,7 @@ module Spring
|
|
48
54
|
|
49
55
|
Spring.register_command "rails_console", RailsConsole.new
|
50
56
|
Spring.register_command "rails_generate", RailsGenerate.new
|
57
|
+
Spring.register_command "rails_destroy", RailsDestroy.new
|
51
58
|
Spring.register_command "rails_runner", RailsRunner.new
|
52
59
|
end
|
53
60
|
end
|
data/lib/spring/configuration.rb
CHANGED
data/lib/spring/env.rb
CHANGED
@@ -8,10 +8,11 @@ module Spring
|
|
8
8
|
IGNORE_SIGNALS = %w(INT QUIT)
|
9
9
|
|
10
10
|
class Env
|
11
|
-
attr_reader :root
|
11
|
+
attr_reader :root, :log_file
|
12
12
|
|
13
13
|
def initialize(root = nil)
|
14
|
-
@root
|
14
|
+
@root = root || Pathname.new(File.expand_path('.'))
|
15
|
+
@log_file = File.open(ENV["SPRING_LOG"] || "/dev/null", "a")
|
15
16
|
end
|
16
17
|
|
17
18
|
def version
|
@@ -63,6 +64,11 @@ module Spring
|
|
63
64
|
[Bundler.default_lockfile, Bundler.default_gemfile].select(&:exist?).map(&:mtime).max
|
64
65
|
end
|
65
66
|
|
67
|
+
def log(message)
|
68
|
+
log_file.puts "[#{Time.now}] #{message}"
|
69
|
+
log_file.flush
|
70
|
+
end
|
71
|
+
|
66
72
|
private
|
67
73
|
|
68
74
|
def default_tmp_path
|
data/lib/spring/errors.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Spring
|
2
2
|
class ClientError < StandardError; end
|
3
3
|
|
4
|
-
class UnknownProject <
|
4
|
+
class UnknownProject < StandardError
|
5
5
|
attr_reader :current_dir
|
6
6
|
|
7
7
|
def initialize(current_dir)
|
@@ -15,6 +15,20 @@ module Spring
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
class TmpUnwritable < StandardError
|
19
|
+
attr_reader :tmp_path
|
20
|
+
|
21
|
+
def initialize(tmp_path)
|
22
|
+
@tmp_path = tmp_path
|
23
|
+
end
|
24
|
+
|
25
|
+
def message
|
26
|
+
"Spring is unable to create a socket file at #{tmp_path}. You may need to " \
|
27
|
+
"set the SPRING_TMP_PATH environment variable to use a different path. See " \
|
28
|
+
"the documentation for details."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
18
32
|
class MissingApplication < ClientError
|
19
33
|
attr_reader :project_root
|
20
34
|
|
data/lib/spring/server.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "socket"
|
2
2
|
require "thread"
|
3
3
|
|
4
|
+
require "spring/configuration"
|
4
5
|
require "spring/env"
|
5
6
|
require "spring/application_manager"
|
6
7
|
require "spring/process_title_updater"
|
@@ -28,20 +29,33 @@ module Spring
|
|
28
29
|
@mutex = Mutex.new
|
29
30
|
end
|
30
31
|
|
32
|
+
def log(message)
|
33
|
+
env.log "[server] #{message}"
|
34
|
+
end
|
35
|
+
|
31
36
|
def boot
|
37
|
+
Spring.verify_environment
|
38
|
+
|
32
39
|
write_pidfile
|
33
40
|
set_pgid
|
34
41
|
ignore_signals
|
35
42
|
set_exit_hook
|
36
|
-
redirect_output
|
37
43
|
set_process_title
|
38
44
|
watch_bundle
|
45
|
+
start_server
|
46
|
+
end
|
39
47
|
|
48
|
+
def start_server
|
40
49
|
server = UNIXServer.open(env.socket_name)
|
50
|
+
log "started on #{env.socket_name}"
|
51
|
+
rescue Errno::EPERM
|
52
|
+
raise TmpUnwritable.new(env.tmp_path)
|
53
|
+
else
|
41
54
|
loop { serve server.accept }
|
42
55
|
end
|
43
56
|
|
44
57
|
def serve(client)
|
58
|
+
log "accepted client"
|
45
59
|
client.puts env.version
|
46
60
|
|
47
61
|
app_client = client.recv_io
|
@@ -50,13 +64,17 @@ module Spring
|
|
50
64
|
args, default_rails_env = command.values_at('args', 'default_rails_env')
|
51
65
|
|
52
66
|
if Spring.command?(args.first)
|
67
|
+
log "running command #{args.first}"
|
53
68
|
client.puts
|
54
69
|
client.puts @applications[rails_env_for(args, default_rails_env)].run(app_client)
|
55
70
|
else
|
71
|
+
log "command not found #{args.first}"
|
56
72
|
client.close
|
57
73
|
end
|
58
74
|
rescue SocketError => e
|
59
75
|
raise e unless client.eof?
|
76
|
+
ensure
|
77
|
+
redirect_output
|
60
78
|
end
|
61
79
|
|
62
80
|
def rails_env_for(args, default_rails_env)
|
@@ -93,7 +111,9 @@ module Spring
|
|
93
111
|
@applications.values.each(&:stop)
|
94
112
|
|
95
113
|
[env.socket_path, env.pidfile_path].each do |path|
|
96
|
-
|
114
|
+
if path.exist?
|
115
|
+
path.unlink rescue nil
|
116
|
+
end
|
97
117
|
end
|
98
118
|
end
|
99
119
|
|
@@ -107,19 +127,12 @@ module Spring
|
|
107
127
|
end
|
108
128
|
end
|
109
129
|
|
110
|
-
# We
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
# However we do want server output to go to the terminal in case
|
116
|
-
# there are exceptions etc, so we just open the current terminal
|
117
|
-
# device directly.
|
130
|
+
# We need to redirect STDOUT and STDERR, otherwise the server will
|
131
|
+
# keep the original FDs open which would break piping. (e.g.
|
132
|
+
# `spring rake -T | grep db` would hang forever because the server
|
133
|
+
# would keep the stdout FD open.)
|
118
134
|
def redirect_output
|
119
|
-
|
120
|
-
file = open(STDIN.tty? ? `tty`.chomp : "/dev/null", "a")
|
121
|
-
STDOUT.reopen(file)
|
122
|
-
STDERR.reopen(file)
|
135
|
+
[STDOUT, STDERR].each { |stream| stream.reopen(env.log_file) }
|
123
136
|
end
|
124
137
|
|
125
138
|
def set_process_title
|
data/lib/spring/version.rb
CHANGED
data/lib/spring/watcher.rb
CHANGED
@@ -38,15 +38,17 @@ module Spring
|
|
38
38
|
|
39
39
|
items = items.select(&:exist?)
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
synchronize {
|
42
|
+
items.each do |item|
|
43
|
+
if item.directory?
|
44
|
+
directories << item.realpath.to_s
|
45
|
+
else
|
46
|
+
files << item.realpath.to_s
|
47
|
+
end
|
46
48
|
end
|
47
|
-
end
|
48
49
|
|
49
|
-
|
50
|
+
subjects_changed
|
51
|
+
}
|
50
52
|
end
|
51
53
|
|
52
54
|
def stale?
|
data/test/acceptance/app_test.rb
CHANGED
@@ -4,22 +4,31 @@ require 'io/wait'
|
|
4
4
|
require "timeout"
|
5
5
|
require "spring/sid"
|
6
6
|
require "spring/env"
|
7
|
-
require "pty"
|
8
7
|
|
9
8
|
class AppTest < ActiveSupport::TestCase
|
10
|
-
|
11
|
-
# the ratio more permissive
|
12
|
-
DEFAULT_SPEEDUP = ENV['CI'] ? 0.8 : 0.6
|
9
|
+
DEFAULT_SPEEDUP = 0.8
|
13
10
|
DEFAULT_TIMEOUT = ENV['CI'] ? 30 : 10
|
14
11
|
|
12
|
+
def rails_version
|
13
|
+
ENV['RAILS_VERSION'] || '~> 4.0.0'
|
14
|
+
end
|
15
|
+
|
16
|
+
def rails_3?
|
17
|
+
rails_version.split(" ").last =~ /^3/
|
18
|
+
end
|
19
|
+
|
15
20
|
def app_root
|
16
|
-
Pathname.new("#{TEST_ROOT}/apps/rails-
|
21
|
+
Pathname.new("#{TEST_ROOT}/apps/rails-#{rails_version.scan(/\d/)[0..1].join("-")}")
|
17
22
|
end
|
18
23
|
|
19
24
|
def gem_home
|
20
25
|
app_root.join "vendor/gems/#{RUBY_VERSION}"
|
21
26
|
end
|
22
27
|
|
28
|
+
def user_home
|
29
|
+
app_root.join "user_home"
|
30
|
+
end
|
31
|
+
|
23
32
|
def spring
|
24
33
|
gem_home.join "bin/spring"
|
25
34
|
end
|
@@ -36,8 +45,19 @@ class AppTest < ActiveSupport::TestCase
|
|
36
45
|
@stderr ||= IO.pipe
|
37
46
|
end
|
38
47
|
|
48
|
+
def log_file
|
49
|
+
@log_file ||= File.open("/tmp/spring.log", "w+")
|
50
|
+
end
|
51
|
+
|
39
52
|
def env
|
40
|
-
@env ||= {
|
53
|
+
@env ||= {
|
54
|
+
"GEM_HOME" => gem_home.to_s,
|
55
|
+
"GEM_PATH" => "",
|
56
|
+
"HOME" => user_home.to_s,
|
57
|
+
"RAILS_ENV" => nil,
|
58
|
+
"RACK_ENV" => nil,
|
59
|
+
"SPRING_LOG" => log_file.path
|
60
|
+
}
|
41
61
|
end
|
42
62
|
|
43
63
|
def app_run(command, opts = {})
|
@@ -56,107 +76,157 @@ class AppTest < ActiveSupport::TestCase
|
|
56
76
|
|
57
77
|
_, status = Timeout.timeout(opts.fetch(:timeout, DEFAULT_TIMEOUT)) { Process.wait2 }
|
58
78
|
|
59
|
-
|
60
|
-
|
79
|
+
if pid = spring_env.pid
|
80
|
+
@server_pid = pid
|
81
|
+
lines = `ps -A -o ppid= -o pid= | egrep '^\\s*#{@server_pid}'`.lines
|
82
|
+
@application_pids = lines.map { |l| l.split.last.to_i }
|
83
|
+
end
|
84
|
+
|
85
|
+
output = read_streams
|
86
|
+
puts dump_streams(command, output) if ENV["SPRING_DEBUG"]
|
61
87
|
|
62
88
|
@times << (Time.now - start_time) if @times
|
63
89
|
|
64
|
-
|
65
|
-
status: status,
|
66
|
-
stdout: stdout,
|
67
|
-
stderr: stderr,
|
68
|
-
}
|
90
|
+
output.merge(status: status, command: command)
|
69
91
|
rescue Timeout::Error => e
|
70
|
-
raise e, "Output:\n\n#{dump_streams(command,
|
92
|
+
raise e, "Output:\n\n#{dump_streams(command, read_streams)}"
|
71
93
|
end
|
72
94
|
|
73
95
|
def read_streams
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
96
|
+
{
|
97
|
+
stdout: read_stream(stdout.first),
|
98
|
+
stderr: read_stream(stderr.first),
|
99
|
+
log: read_stream(log_file)
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def read_stream(stream)
|
104
|
+
output = ""
|
105
|
+
while IO.select([stream], [], [], 0.5) && !stream.eof?
|
106
|
+
output << stream.readpartial(10240)
|
78
107
|
end
|
108
|
+
output
|
79
109
|
end
|
80
110
|
|
81
|
-
def dump_streams(command,
|
111
|
+
def dump_streams(command, streams)
|
82
112
|
output = "$ #{command}\n"
|
83
113
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
unless stderr.chomp.empty?
|
90
|
-
output << "--- stderr ---\n"
|
91
|
-
output << "#{stderr.chomp}\n"
|
114
|
+
streams.each do |name, stream|
|
115
|
+
unless stream.chomp.empty?
|
116
|
+
output << "--- #{name} ---\n"
|
117
|
+
output << "#{stream.chomp}\n"
|
118
|
+
end
|
92
119
|
end
|
93
120
|
|
94
121
|
output << "\n"
|
95
122
|
output
|
96
123
|
end
|
97
124
|
|
125
|
+
def alive?(pid)
|
126
|
+
Process.kill 0, pid
|
127
|
+
true
|
128
|
+
rescue Errno::ESRCH
|
129
|
+
false
|
130
|
+
end
|
131
|
+
|
98
132
|
def await_reload
|
99
|
-
|
133
|
+
raise "no pid" if @application_pids.nil? || @application_pids.empty?
|
134
|
+
|
135
|
+
Timeout.timeout(DEFAULT_TIMEOUT) do
|
136
|
+
sleep 0.1 while @application_pids.any? { |p| alive?(p) }
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def debug(artifacts)
|
141
|
+
artifacts = artifacts.dup
|
142
|
+
artifacts.delete :status
|
143
|
+
dump_streams(artifacts.delete(:command), artifacts)
|
100
144
|
end
|
101
145
|
|
102
146
|
def assert_output(artifacts, expected)
|
103
147
|
expected.each do |stream, output|
|
104
148
|
assert artifacts[stream].include?(output),
|
105
|
-
"expected #{stream} to include '#{output}'
|
149
|
+
"expected #{stream} to include '#{output}'.\n\n#{debug(artifacts)}"
|
106
150
|
end
|
107
151
|
end
|
108
152
|
|
109
153
|
def assert_success(command, expected_output = nil)
|
110
|
-
artifacts = app_run(command)
|
111
|
-
assert artifacts[:status].success?, "expected successful exit status\n\n#{
|
154
|
+
artifacts = app_run(*Array(command))
|
155
|
+
assert artifacts[:status].success?, "expected successful exit status\n\n#{debug(artifacts)}"
|
112
156
|
assert_output artifacts, expected_output if expected_output
|
113
157
|
end
|
114
158
|
|
115
159
|
def assert_failure(command, expected_output = nil)
|
116
|
-
artifacts = app_run(command)
|
117
|
-
assert !artifacts[:status].success?, "expected unsuccessful exit status\n\n#{
|
160
|
+
artifacts = app_run(*Array(command))
|
161
|
+
assert !artifacts[:status].success?, "expected unsuccessful exit status\n\n#{debug(artifacts)}"
|
118
162
|
assert_output artifacts, expected_output if expected_output
|
119
163
|
end
|
120
164
|
|
121
165
|
def assert_speedup(ratio = DEFAULT_SPEEDUP)
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
166
|
+
if ENV['CI']
|
167
|
+
yield
|
168
|
+
else
|
169
|
+
@times = []
|
170
|
+
yield
|
171
|
+
assert (@times.last / @times.first) < ratio, "#{@times.last} was not less than #{ratio} of #{@times.first}"
|
172
|
+
@times = nil
|
173
|
+
end
|
126
174
|
end
|
127
175
|
|
128
176
|
def spring_test_command
|
129
177
|
"#{spring} testunit #{@test}"
|
130
178
|
end
|
131
179
|
|
132
|
-
|
180
|
+
def generate_app
|
181
|
+
Bundler.with_clean_env do
|
182
|
+
assert system("(gem list rails --installed --version '#{rails_version}' || " \
|
183
|
+
"gem install rails --version '#{rails_version}') > /dev/null")
|
133
184
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
@spec_contents = File.read(@spec)
|
139
|
-
@controller = "#{app_root}/app/controllers/posts_controller.rb"
|
140
|
-
@controller_contents = File.read(@controller)
|
185
|
+
# Have to shell out otherwise bundler prevents us finding the gem
|
186
|
+
version = `ruby -e 'puts Gem::Specification.find_by_name("rails", "#{rails_version}").version'`.chomp
|
187
|
+
|
188
|
+
assert system("rails _#{version}_ new #{app_root} --skip-bundle --skip-javascript --skip-sprockets > /dev/null")
|
141
189
|
|
142
|
-
unless @@installed
|
143
190
|
FileUtils.mkdir_p(gem_home)
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
191
|
+
FileUtils.mkdir_p(user_home)
|
192
|
+
FileUtils.rm_rf("#{app_root}/test/performance/")
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def install
|
197
|
+
generate_app unless app_root.exist?
|
198
|
+
|
199
|
+
assert system("gem build spring.gemspec 2>/dev/null 1>/dev/null")
|
200
|
+
|
201
|
+
assert_success "gem install ../../../spring-#{Spring::VERSION}.gem"
|
202
|
+
assert_success ["(gem list bundler | grep bundler) || gem install bundler", timeout: nil]
|
203
|
+
assert_success ["bundle check || bundle update", timeout: nil]
|
204
|
+
|
205
|
+
unless File.exist?(@controller)
|
206
|
+
assert_success "bundle exec rails g scaffold post title:string"
|
150
207
|
end
|
151
208
|
|
152
|
-
|
209
|
+
assert_success "bundle exec rake db:migrate db:test:clone"
|
210
|
+
@@installed = true
|
211
|
+
end
|
212
|
+
|
213
|
+
@@installed = false
|
214
|
+
|
215
|
+
setup do
|
216
|
+
@test = "#{app_root}/test/#{rails_3? ? 'functional' : 'controllers'}/posts_controller_test.rb"
|
217
|
+
@controller = "#{app_root}/app/controllers/posts_controller.rb"
|
218
|
+
|
219
|
+
install unless @@installed
|
220
|
+
|
221
|
+
@test_contents = File.read(@test)
|
222
|
+
@controller_contents = File.read(@controller)
|
153
223
|
end
|
154
224
|
|
155
225
|
teardown do
|
156
226
|
app_run "#{spring} stop"
|
157
|
-
File.write(@test,
|
158
|
-
File.write(@spec, @spec_contents)
|
227
|
+
File.write(@test, @test_contents)
|
159
228
|
File.write(@controller, @controller_contents)
|
229
|
+
FileUtils.rm_f("#{app_root}/config/spring.rb")
|
160
230
|
end
|
161
231
|
|
162
232
|
test "basic" do
|
@@ -219,15 +289,13 @@ class AppTest < ActiveSupport::TestCase
|
|
219
289
|
File.write(@test, @test_contents.sub("get :index", "Foo.omg"))
|
220
290
|
|
221
291
|
await_reload
|
222
|
-
|
223
|
-
assert_speedup do
|
224
|
-
2.times { assert_failure spring_test_command, stdout: "RuntimeError: omg" }
|
225
|
-
end
|
292
|
+
assert_failure spring_test_command, stdout: "RuntimeError: omg"
|
226
293
|
ensure
|
227
294
|
File.write(application, application_contents)
|
228
295
|
end
|
229
296
|
|
230
297
|
test "app gets reloaded when preloaded files change (polling watcher)" do
|
298
|
+
env["RAILS_ENV"] = "test"
|
231
299
|
assert_success "#{spring} rails runner 'puts Spring.watcher.class'", stdout: "Polling"
|
232
300
|
assert_app_reloaded
|
233
301
|
end
|
@@ -236,18 +304,17 @@ class AppTest < ActiveSupport::TestCase
|
|
236
304
|
begin
|
237
305
|
gemfile = app_root.join("Gemfile")
|
238
306
|
gemfile_contents = gemfile.read
|
239
|
-
File.write(gemfile, gemfile_contents
|
307
|
+
File.write(gemfile, gemfile_contents + "\ngem 'listen', '~> 1.0'")
|
240
308
|
|
241
|
-
|
242
|
-
config_contents = File.read(config_path)
|
243
|
-
File.write(config_path,config_contents + "\nSpring.watch_method = :listen")
|
309
|
+
File.write("#{app_root}/config/spring.rb", "Spring.watch_method = :listen")
|
244
310
|
|
245
|
-
|
311
|
+
assert_success ["bundle install", timeout: nil]
|
246
312
|
|
313
|
+
env["RAILS_ENV"] = "test"
|
247
314
|
assert_success "#{spring} rails runner 'puts Spring.watcher.class'", stdout: "Listen"
|
315
|
+
|
248
316
|
assert_app_reloaded
|
249
317
|
ensure
|
250
|
-
File.write(config_path,config_contents)
|
251
318
|
File.write(gemfile, gemfile_contents)
|
252
319
|
assert_success "bundle check"
|
253
320
|
end
|
@@ -266,8 +333,6 @@ class AppTest < ActiveSupport::TestCase
|
|
266
333
|
assert_failure spring_test_command
|
267
334
|
|
268
335
|
File.write(application, application_contents)
|
269
|
-
await_reload
|
270
|
-
|
271
336
|
assert_success spring_test_command
|
272
337
|
ensure
|
273
338
|
File.write(application, application_contents)
|
@@ -283,32 +348,55 @@ class AppTest < ActiveSupport::TestCase
|
|
283
348
|
end
|
284
349
|
|
285
350
|
test "custom commands" do
|
351
|
+
File.write("#{app_root}/config/spring.rb", <<-CODE)
|
352
|
+
class CustomCommand
|
353
|
+
def call
|
354
|
+
puts "omg"
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
Spring.register_command "custom", CustomCommand.new
|
359
|
+
CODE
|
360
|
+
|
286
361
|
assert_success "#{spring} custom", stdout: "omg"
|
287
362
|
end
|
288
363
|
|
289
364
|
test "binstubs" do
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
365
|
+
begin
|
366
|
+
FileUtils.mv "#{app_root}/bin", "#{app_root}/bin~" if File.exist?("#{app_root}/bin")
|
367
|
+
|
368
|
+
app_run "#{spring} binstub rake"
|
369
|
+
app_run "#{spring} binstub rails"
|
370
|
+
assert_success "bin/spring help"
|
371
|
+
assert_success "bin/rake -T", stdout: "rake db:migrate"
|
372
|
+
assert_success "bin/rails runner 'puts %(omg)'", stdout: "omg"
|
373
|
+
assert_success "bin/rails server --help", stdout: "Usage: rails server"
|
374
|
+
ensure
|
375
|
+
if File.exist?("#{app_root}/bin~")
|
376
|
+
FileUtils.rm_rf "#{app_root}/bin"
|
377
|
+
FileUtils.mv "#{app_root}/bin~", "#{app_root}/bin"
|
378
|
+
end
|
379
|
+
end
|
295
380
|
end
|
296
381
|
|
297
382
|
test "after fork callback" do
|
298
|
-
|
299
|
-
|
300
|
-
|
383
|
+
File.write("#{app_root}/config/spring.rb", "Spring.after_fork { puts '!callback!' }")
|
384
|
+
assert_success "#{spring} rails runner 'puts 2'", stdout: "!callback!\n2"
|
385
|
+
end
|
301
386
|
|
302
|
-
|
387
|
+
test "global config file evaluated" do
|
388
|
+
begin
|
389
|
+
File.write("#{user_home}/.spring.rb", "Spring.after_fork { puts '!callback!' }")
|
303
390
|
assert_success "#{spring} rails runner 'puts 2'", stdout: "!callback!\n2"
|
304
391
|
ensure
|
305
|
-
|
392
|
+
FileUtils.rm_r("#{user_home}/.spring.rb")
|
306
393
|
end
|
307
394
|
end
|
308
395
|
|
309
396
|
test "missing config/application.rb" do
|
310
397
|
begin
|
311
398
|
FileUtils.mv app_root.join("config/application.rb"), app_root.join("config/application.rb.bak")
|
399
|
+
|
312
400
|
assert_failure "#{spring} rake -T", stderr: "unable to find your config/application.rb"
|
313
401
|
ensure
|
314
402
|
FileUtils.mv app_root.join("config/application.rb.bak"), app_root.join("config/application.rb")
|
@@ -335,24 +423,18 @@ class AppTest < ActiveSupport::TestCase
|
|
335
423
|
assert_success "#{spring} rake -p 'Rails.env'", stdout: "production"
|
336
424
|
end
|
337
425
|
|
338
|
-
test "exit code for failing specs" do
|
339
|
-
assert_success "#{spring} rspec"
|
340
|
-
File.write(@spec, @spec_contents.sub("true.should be_true", "false.should be_true"))
|
341
|
-
assert_failure "#{spring} rspec"
|
342
|
-
end
|
343
|
-
|
344
426
|
test "changing the Gemfile restarts the server" do
|
345
427
|
begin
|
346
428
|
gemfile = app_root.join("Gemfile")
|
347
429
|
gemfile_contents = gemfile.read
|
348
430
|
|
349
|
-
assert_success %(#{spring} rails runner 'require "
|
431
|
+
assert_success %(#{spring} rails runner 'require "sqlite3"')
|
350
432
|
|
351
|
-
File.write(gemfile, gemfile_contents.sub(%{gem '
|
433
|
+
File.write(gemfile, gemfile_contents.sub(%{gem 'sqlite3'}, %{# gem 'sqlite3'}))
|
352
434
|
app_run "bundle check"
|
353
435
|
|
354
436
|
await_reload
|
355
|
-
assert_failure %(#{spring} rails runner 'require "
|
437
|
+
assert_failure %(#{spring} rails runner 'require "sqlite3"'), stderr: "sqlite3"
|
356
438
|
ensure
|
357
439
|
File.write(gemfile, gemfile_contents)
|
358
440
|
assert_success "bundle check"
|