spring 0.0.9 → 0.0.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.
- data/CHANGELOG.md +27 -0
- data/Gemfile +0 -2
- data/README.md +35 -40
- data/bin/spring +7 -3
- data/lib/spring/application.rb +25 -4
- data/lib/spring/client.rb +2 -2
- data/lib/spring/client/help.rb +2 -0
- data/lib/spring/client/run.rb +10 -4
- data/lib/spring/commands.rb +8 -215
- data/lib/spring/commands/cucumber.rb +15 -0
- data/lib/spring/commands/rails.rb +53 -0
- data/lib/spring/commands/rake.rb +26 -0
- data/lib/spring/commands/rspec.rb +15 -0
- data/lib/spring/commands/testunit.rb +32 -0
- data/lib/spring/configuration.rb +5 -1
- data/lib/spring/env.rb +0 -1
- data/lib/spring/json.rb +621 -0
- data/lib/spring/server.rb +8 -6
- data/lib/spring/version.rb +1 -1
- data/lib/spring/watcher.rb +16 -11
- data/lib/spring/watcher/abstract.rb +2 -0
- data/lib/spring/watcher/listen.rb +5 -14
- data/test/acceptance/app_test.rb +18 -9
- data/test/apps/rails-3-2/Gemfile +1 -4
- data/test/apps/rails-3-2/config/spring.rb +1 -1
- data/test/unit/commands_test.rb +0 -35
- data/test/unit/watcher_test.rb +7 -2
- metadata +8 -3
- data/lib/spring/client/start.rb +0 -17
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
## 0.0.10
|
2
|
+
|
3
|
+
* Added `Spring.watch_via=` configuration option to switch between
|
4
|
+
polling and the `listen` gem. Previously, we used the `listen` gem if
|
5
|
+
it was available, but this makes the option explicit. Set
|
6
|
+
`Spring.watch_via = :listen` to use the listen gem.
|
7
|
+
* Fallback when Process.fork is not available. In such cases, the user
|
8
|
+
will not receive the speedup that Spring provides, but won't receive
|
9
|
+
an error either.
|
10
|
+
* Don't preload `test_helper` or `spec_helper` by default. This was
|
11
|
+
causing people subtle problems (for example see #113) and is perhaps
|
12
|
+
surprising behaviour. It may be desirable but it depends on the
|
13
|
+
application, therefore we suggest it to people in the README but no
|
14
|
+
longer do it by default.
|
15
|
+
* Don't stay connected to database in the application processes. There's
|
16
|
+
no need to keep a connection open.
|
17
|
+
* Avoid using the database in the application processes. Previously,
|
18
|
+
reloading the autoloaded constants would inadvertantly cause a
|
19
|
+
connection to the database, which would then prevent tasks like
|
20
|
+
db:create from running (because at that point the database doesn't
|
21
|
+
exist)
|
22
|
+
* Removed ability to specify list of files for a command to preload. We
|
23
|
+
weren't using this any more internally, and this is easy to do by
|
24
|
+
placing requires in suitable locations in the Rails boot process
|
25
|
+
(which is not explained in the README).
|
26
|
+
* Seed the random number generator on each run.
|
27
|
+
|
1
28
|
## 0.0.9
|
2
29
|
|
3
30
|
* Added `Spring::Commands::Rake.environment_matchers` for matching
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -233,15 +233,20 @@ spring repository.
|
|
233
233
|
|
234
234
|
### `testunit`
|
235
235
|
|
236
|
-
Runs a test (e.g. Test::Unit, MiniTest::Unit, etc.)
|
236
|
+
Runs a test (e.g. Test::Unit, MiniTest::Unit, etc.)
|
237
237
|
|
238
238
|
This command can also recursively run a directory of tests. For example,
|
239
239
|
`spring testunit test/functional` will run `test/functional/**/*_test.rb`.
|
240
240
|
|
241
|
+
If your test helper file takes a while to load, consider preloading it
|
242
|
+
(see "Running code before forking" below).
|
243
|
+
|
241
244
|
### `rspec`
|
242
245
|
|
243
|
-
Runs an rspec spec, exactly the same as the `rspec` executable.
|
244
|
-
|
246
|
+
Runs an rspec spec, exactly the same as the `rspec` executable.
|
247
|
+
|
248
|
+
If your spec helper file takes a while to load, consider preloading it
|
249
|
+
(see "Running code before forking" below).
|
245
250
|
|
246
251
|
### `cucumber`
|
247
252
|
|
@@ -268,11 +273,11 @@ a different sub command (e.g. `rails server`) then spring will automatically
|
|
268
273
|
pass it through to the underlying `rails` executable (without the
|
269
274
|
speed-up).
|
270
275
|
|
271
|
-
## Configuration
|
276
|
+
## Configuration
|
272
277
|
|
273
278
|
Spring will read `config/spring.rb` for custom settings, described below.
|
274
279
|
|
275
|
-
###
|
280
|
+
### Application root
|
276
281
|
|
277
282
|
Spring must know how to find your Rails application. If you have a
|
278
283
|
normal app everything works out of the box. If you are working on a
|
@@ -283,26 +288,20 @@ Spring where your app is located:
|
|
283
288
|
Spring.application_root = './test/dummy'
|
284
289
|
```
|
285
290
|
|
286
|
-
###
|
287
|
-
|
288
|
-
Every Spring command has the ability to preload a set of files. The
|
289
|
-
`test` command for example preloads `test_helper` (it also adds the
|
290
|
-
`test/` directory to your load path). If the
|
291
|
-
defaults don't work for your application you can configure the
|
292
|
-
preloads for every command:
|
293
|
-
|
294
|
-
```ruby
|
295
|
-
# if your test helper is called "helper"
|
296
|
-
Spring::Commands::TestUnit.preloads = %w(helper)
|
291
|
+
### Running code before forking
|
297
292
|
|
298
|
-
|
299
|
-
|
293
|
+
There is no `Spring.before_fork` callback. To run something before the
|
294
|
+
fork, you can place it in `config/spring.rb` or in any of the files
|
295
|
+
which get run when your application initializers, such as
|
296
|
+
`config/application.rb`, `config/environments/*.rb` or
|
297
|
+
`config/initializers/*.rb`.
|
300
298
|
|
301
|
-
|
302
|
-
|
303
|
-
|
299
|
+
For example, if loading your test helper is slow, you might like to
|
300
|
+
preload it to speed up your test runs. To do this you could put a
|
301
|
+
`require Rails.root.join("test/helper")` in
|
302
|
+
`config/environments/test.rb`.
|
304
303
|
|
305
|
-
###
|
304
|
+
### Running code after forking
|
306
305
|
|
307
306
|
You might want to run code after Spring forked off the process but
|
308
307
|
before the actual command is run. You might want to use an
|
@@ -320,31 +319,27 @@ If you want to register multiple callbacks you can simply call
|
|
320
319
|
|
321
320
|
### Watching files and directories
|
322
321
|
|
323
|
-
|
324
|
-
boots.
|
322
|
+
Spring will automatically detect file changes to any file loaded when the server
|
323
|
+
boots. Changes will cause the affected environments to be restarted.
|
324
|
+
|
325
|
+
If there are additional files or directories which should trigger an
|
326
|
+
application restart, you can specify them with `Spring.watch`:
|
325
327
|
|
326
328
|
```ruby
|
327
329
|
Spring.watch "spec/factories"
|
328
330
|
```
|
329
331
|
|
330
|
-
|
331
|
-
|
332
|
-
### tmp directory
|
333
|
-
|
334
|
-
Spring needs a tmp directory. This will default to `Rails.root.join('tmp', 'spring')`.
|
335
|
-
You can set your own configuration directory by setting the `SPRING_TMP_PATH` environment variable.
|
336
|
-
|
337
|
-
### Filesystem polling speed
|
338
|
-
|
339
|
-
By default Spring will check the filesystem for changes once every 0.2 seconds. This
|
332
|
+
By default Spring polls the filesystem for changes once every 0.2 seconds. This
|
340
333
|
method requires zero configuration, but if you find that it's using too
|
341
|
-
much CPU, then you can turn on event-based file system listening
|
342
|
-
adding the following to to your `Gemfile`:
|
334
|
+
much CPU, then you can turn on event-based file system listening:
|
343
335
|
|
344
336
|
```ruby
|
345
|
-
|
346
|
-
gem 'listen'
|
347
|
-
end
|
337
|
+
Spring.watch_method = :listen
|
348
338
|
```
|
349
339
|
|
350
|
-
|
340
|
+
You may need to add the [`listen` gem](https://github.com/guard/listen) to your `Gemfile`.
|
341
|
+
|
342
|
+
### tmp directory
|
343
|
+
|
344
|
+
Spring needs a tmp directory. This will default to `Rails.root.join('tmp', 'spring')`.
|
345
|
+
You can set your own configuration directory by setting the `SPRING_TMP_PATH` environment variable.
|
data/bin/spring
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
if Process.respond_to?(:fork)
|
4
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
5
|
+
require 'spring/client'
|
6
|
+
Spring::Client.run(ARGV)
|
7
|
+
else
|
8
|
+
exec "bundle", "exec", *ARGV
|
9
|
+
end
|
data/lib/spring/application.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require "set"
|
2
|
-
require "json"
|
3
2
|
|
4
3
|
require "spring/configuration"
|
5
4
|
require "spring/watcher"
|
@@ -28,10 +27,17 @@ module Spring
|
|
28
27
|
ActiveSupport::Dependencies.mechanism = :load
|
29
28
|
end
|
30
29
|
|
30
|
+
# This initializer has issues after we disconnect from the DB, but we don't need it.
|
31
|
+
if defined?(ActiveRecord::Base)
|
32
|
+
ActiveRecord::Railtie.initializers.delete_if { |i| i.name == "active_record.set_reloader_hooks" }
|
33
|
+
end
|
34
|
+
|
31
35
|
require Spring.application_root_path.join("config", "environment")
|
32
36
|
|
37
|
+
ActiveRecord::Base.remove_connection if defined?(ActiveRecord::Base)
|
38
|
+
|
33
39
|
watcher.add loaded_application_features
|
34
|
-
watcher.add
|
40
|
+
watcher.add Spring.gemfile, "#{Spring.gemfile}.lock"
|
35
41
|
watcher.add Rails.application.paths["config/initializers"]
|
36
42
|
|
37
43
|
run
|
@@ -55,7 +61,7 @@ module Spring
|
|
55
61
|
manager.puts
|
56
62
|
|
57
63
|
streams = 3.times.map { client.recv_io }
|
58
|
-
args = JSON.
|
64
|
+
args = JSON.load(client.read(client.gets.to_i))
|
59
65
|
command = Spring.command(args.shift)
|
60
66
|
|
61
67
|
setup command
|
@@ -67,8 +73,23 @@ module Spring
|
|
67
73
|
Process.setsid
|
68
74
|
[STDOUT, STDERR, STDIN].zip(streams).each { |a, b| a.reopen(b) }
|
69
75
|
IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
|
76
|
+
|
77
|
+
ActiveRecord::Base.establish_connection if defined?(ActiveRecord::Base)
|
78
|
+
ARGV.replace(args)
|
79
|
+
srand
|
80
|
+
|
70
81
|
invoke_after_fork_callbacks
|
71
|
-
|
82
|
+
|
83
|
+
if command.respond_to?(:call)
|
84
|
+
command.call
|
85
|
+
else
|
86
|
+
exec_name = command.exec_name
|
87
|
+
gem_name = command.gem_name if command.respond_to?(:gem_name)
|
88
|
+
|
89
|
+
exec = Gem.bin_path(gem_name || exec_name, exec_name)
|
90
|
+
$0 = exec
|
91
|
+
load exec
|
92
|
+
end
|
72
93
|
}
|
73
94
|
|
74
95
|
manager.puts pid
|
data/lib/spring/client.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require "spring/configuration"
|
2
|
+
require "spring/json"
|
3
|
+
|
2
4
|
require "spring/client/command"
|
3
5
|
require "spring/client/run"
|
4
6
|
require "spring/client/help"
|
5
7
|
require "spring/client/binstub"
|
6
|
-
require "spring/client/start"
|
7
8
|
require "spring/client/stop"
|
8
9
|
require "spring/client/status"
|
9
10
|
require "spring/client/rails"
|
@@ -13,7 +14,6 @@ module Spring
|
|
13
14
|
COMMANDS = {
|
14
15
|
"help" => Client::Help,
|
15
16
|
"binstub" => Client::Binstub,
|
16
|
-
"start" => Client::Start,
|
17
17
|
"stop" => Client::Stop,
|
18
18
|
"status" => Client::Status,
|
19
19
|
"rails" => Client::Rails
|
data/lib/spring/client/help.rb
CHANGED
data/lib/spring/client/run.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require "rbconfig"
|
2
2
|
require "socket"
|
3
|
-
require "json"
|
4
3
|
|
5
4
|
module Spring
|
6
5
|
module Client
|
@@ -29,7 +28,10 @@ module Spring
|
|
29
28
|
|
30
29
|
def boot_server
|
31
30
|
env.socket_path.unlink if env.socket_path.exist?
|
32
|
-
|
31
|
+
fork {
|
32
|
+
require "spring/server"
|
33
|
+
Spring::Server.boot
|
34
|
+
}
|
33
35
|
sleep 0.1 until env.socket_path.exist?
|
34
36
|
end
|
35
37
|
|
@@ -48,7 +50,7 @@ ERROR
|
|
48
50
|
|
49
51
|
def connect_to_application(client)
|
50
52
|
server.send_io client
|
51
|
-
send_json server, args
|
53
|
+
send_json server, "args" => args, "default_rails_env" => default_rails_env
|
52
54
|
server.gets or raise CommandNotFound
|
53
55
|
end
|
54
56
|
|
@@ -95,9 +97,13 @@ ERROR
|
|
95
97
|
def send_json(socket, data)
|
96
98
|
data = JSON.dump(data)
|
97
99
|
|
98
|
-
socket.puts data.
|
100
|
+
socket.puts data.bytesize
|
99
101
|
socket.write data
|
100
102
|
end
|
103
|
+
|
104
|
+
def default_rails_env
|
105
|
+
ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
106
|
+
end
|
101
107
|
end
|
102
108
|
end
|
103
109
|
end
|
data/lib/spring/commands.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
require "spring/watcher"
|
2
2
|
|
3
|
-
# If the config/spring.rb contains requires for commands from other gems,
|
4
|
-
# then we need to be under bundler.
|
5
|
-
require "bundler/setup"
|
6
|
-
|
7
3
|
module Spring
|
8
4
|
@commands = {}
|
9
5
|
|
@@ -23,218 +19,15 @@ module Spring
|
|
23
19
|
commands.fetch name
|
24
20
|
end
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
@preloads ||= superclass.preloads.dup
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.preloads=(val)
|
35
|
-
@preloads = val
|
36
|
-
end
|
37
|
-
|
38
|
-
def preloads
|
39
|
-
self.class.preloads
|
40
|
-
end
|
41
|
-
|
42
|
-
def setup
|
43
|
-
preload_files
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def preload_files
|
49
|
-
preloads.each do |file|
|
50
|
-
begin
|
51
|
-
require file
|
52
|
-
rescue LoadError => e
|
53
|
-
$stderr.puts <<-MESSAGE
|
54
|
-
The #{self.class} command tried to preload #{file} but could not find it.
|
55
|
-
You can configure what to preload in your `config/spring.rb` with:
|
56
|
-
#{self.class}.preloads = %w(files to preload)
|
57
|
-
MESSAGE
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
class TestUnit < Command
|
64
|
-
preloads << "test_helper"
|
65
|
-
|
66
|
-
def env(*)
|
67
|
-
"test"
|
68
|
-
end
|
69
|
-
|
70
|
-
def setup
|
71
|
-
$LOAD_PATH.unshift "test"
|
72
|
-
super
|
73
|
-
end
|
74
|
-
|
75
|
-
def call(args)
|
76
|
-
if args.empty?
|
77
|
-
args = ['test']
|
78
|
-
end
|
79
|
-
|
80
|
-
ARGV.replace args
|
81
|
-
args.each do |arg|
|
82
|
-
path = File.expand_path(arg)
|
83
|
-
if File.directory?(path)
|
84
|
-
Dir[File.join path, "**", "*_test.rb"].each { |f| require f }
|
85
|
-
else
|
86
|
-
require path
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def description
|
92
|
-
"Execute a Test::Unit test."
|
93
|
-
end
|
94
|
-
end
|
95
|
-
Spring.register_command "testunit", TestUnit.new
|
96
|
-
|
97
|
-
class RSpec < Command
|
98
|
-
preloads << "spec_helper"
|
99
|
-
|
100
|
-
def env(*)
|
101
|
-
"test"
|
102
|
-
end
|
103
|
-
|
104
|
-
def setup
|
105
|
-
$LOAD_PATH.unshift "spec"
|
106
|
-
require 'rspec/core'
|
107
|
-
::RSpec::Core::Runner.disable_autorun!
|
108
|
-
super
|
109
|
-
end
|
110
|
-
|
111
|
-
def call(args)
|
112
|
-
$0 = "rspec"
|
113
|
-
Kernel.exit ::RSpec::Core::Runner.run(args)
|
114
|
-
end
|
115
|
-
|
116
|
-
def description
|
117
|
-
"Execute an RSpec spec."
|
118
|
-
end
|
119
|
-
end
|
120
|
-
Spring.register_command "rspec", RSpec.new
|
121
|
-
|
122
|
-
class Cucumber < Command
|
123
|
-
def env(*)
|
124
|
-
"test"
|
125
|
-
end
|
22
|
+
require "spring/commands/rails"
|
23
|
+
require "spring/commands/rake"
|
24
|
+
require "spring/commands/testunit"
|
25
|
+
require "spring/commands/rspec"
|
26
|
+
require "spring/commands/cucumber"
|
126
27
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
end
|
131
|
-
|
132
|
-
def call(args)
|
133
|
-
# Cucumber's execute funtion returns `true` if any of the steps failed or
|
134
|
-
# some other error occured.
|
135
|
-
Kernel.exit(1) if ::Cucumber::Cli::Main.execute(args)
|
136
|
-
end
|
137
|
-
|
138
|
-
def description
|
139
|
-
"Execute a Cucumber feature."
|
140
|
-
end
|
141
|
-
end
|
142
|
-
Spring.register_command "cucumber", Cucumber.new
|
143
|
-
|
144
|
-
class Rake < Command
|
145
|
-
class << self
|
146
|
-
attr_accessor :environment_matchers
|
147
|
-
end
|
148
|
-
|
149
|
-
self.environment_matchers = {
|
150
|
-
/^(test|spec|cucumber)($|:)/ => "test"
|
151
|
-
}
|
152
|
-
|
153
|
-
def env(args)
|
154
|
-
self.class.environment_matchers.each do |matcher, environment|
|
155
|
-
return environment if matcher === args.first
|
156
|
-
end
|
157
|
-
nil
|
158
|
-
end
|
159
|
-
|
160
|
-
def setup
|
161
|
-
super
|
162
|
-
require "rake"
|
163
|
-
end
|
164
|
-
|
165
|
-
def call(args)
|
166
|
-
ARGV.replace args
|
167
|
-
::Rake.application.run
|
168
|
-
end
|
169
|
-
|
170
|
-
def description
|
171
|
-
"Run a rake task."
|
172
|
-
end
|
173
|
-
end
|
174
|
-
Spring.register_command "rake", Rake.new
|
175
|
-
|
176
|
-
class RailsConsole < Command
|
177
|
-
def env(args)
|
178
|
-
args.first if args.first && !args.first.index("-")
|
179
|
-
end
|
180
|
-
|
181
|
-
def setup
|
182
|
-
require "rails/commands/console"
|
183
|
-
end
|
184
|
-
|
185
|
-
def call(args)
|
186
|
-
ARGV.replace args
|
187
|
-
::Rails::Console.start(::Rails.application)
|
188
|
-
end
|
189
|
-
|
190
|
-
def description
|
191
|
-
nil
|
192
|
-
end
|
193
|
-
end
|
194
|
-
Spring.register_command "rails_console", RailsConsole.new
|
195
|
-
|
196
|
-
class RailsGenerate < Command
|
197
|
-
def setup
|
198
|
-
super
|
199
|
-
Rails.application.load_generators
|
200
|
-
end
|
201
|
-
|
202
|
-
def call(args)
|
203
|
-
ARGV.replace args
|
204
|
-
require "rails/commands/generate"
|
205
|
-
end
|
206
|
-
|
207
|
-
def description
|
208
|
-
nil
|
209
|
-
end
|
210
|
-
end
|
211
|
-
Spring.register_command "rails_generate", RailsGenerate.new
|
212
|
-
|
213
|
-
class RailsRunner < Command
|
214
|
-
def env(tail)
|
215
|
-
previous_option = nil
|
216
|
-
tail.reverse.each do |option|
|
217
|
-
case option
|
218
|
-
when /--environment=(\w+)/ then return $1
|
219
|
-
when '-e' then return previous_option
|
220
|
-
end
|
221
|
-
previous_option = option
|
222
|
-
end
|
223
|
-
nil
|
224
|
-
end
|
225
|
-
|
226
|
-
def call(args)
|
227
|
-
Object.const_set(:APP_PATH, Rails.root.join('config/application'))
|
228
|
-
ARGV.replace args
|
229
|
-
require "rails/commands/runner"
|
230
|
-
end
|
231
|
-
|
232
|
-
def description
|
233
|
-
nil
|
234
|
-
end
|
235
|
-
end
|
236
|
-
Spring.register_command "rails_runner", RailsRunner.new
|
237
|
-
end
|
28
|
+
# If the config/spring.rb contains requires for commands from other gems,
|
29
|
+
# then we need to be under bundler.
|
30
|
+
require "bundler/setup"
|
238
31
|
|
239
32
|
# Load custom commands, if any.
|
240
33
|
# needs to be at the end to allow modification of existing commands.
|