spring 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|