spring 2.0.2 → 3.1.0
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 +5 -5
- data/LICENSE.txt +1 -0
- data/README.md +54 -38
- data/lib/spring/application.rb +46 -30
- data/lib/spring/application_manager.rb +4 -2
- data/lib/spring/binstub.rb +0 -20
- data/lib/spring/client/binstub.rb +12 -13
- data/lib/spring/client/help.rb +1 -1
- data/lib/spring/client/rails.rb +3 -1
- data/lib/spring/client/run.rb +23 -4
- data/lib/spring/client/stop.rb +1 -1
- data/lib/spring/commands.rb +1 -1
- data/lib/spring/configuration.rb +16 -1
- data/lib/spring/env.rb +2 -3
- data/lib/spring/errors.rb +1 -1
- data/lib/spring/json.rb +2 -2
- data/lib/spring/process_title_updater.rb +1 -1
- data/lib/spring/server.rb +2 -1
- data/lib/spring/version.rb +1 -1
- metadata +10 -18
- data/lib/spring/sid.rb +0 -42
- data/lib/spring/test/acceptance_test.rb +0 -558
- data/lib/spring/test/application.rb +0 -229
- data/lib/spring/test/application_generator.rb +0 -144
- data/lib/spring/test/rails_version.rb +0 -23
- data/lib/spring/test/watcher_test.rb +0 -194
- data/lib/spring/test.rb +0 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4b47e67e59d8908152f467132052eca96c6b9e7df23e60f8a2c7a55f5861e954
|
|
4
|
+
data.tar.gz: 378c8a4a9dd44c41b7d77145f28f6010d3175fafdeec5e7ce049d0ec2e8babda
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d4d529c07b78b42af5783adcc43a9a0195e81d6a061ce6409598bb6316b64660c38e74c959773a81152390913cf25b982f8b5c5bafa674da9d6394bb29fd8490
|
|
7
|
+
data.tar.gz: bf4009a207501a0ce88b0f1ce4983c9eb035461f41f31e329a4cd842b63efec2f2f6adc3ff25fa23e5b46e8296a2e245ddebda51fed3237eb3758cbe3e73d463
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Spring
|
|
2
2
|
|
|
3
|
-
[](
|
|
3
|
+
[](https://github.com/rails/spring/actions/workflows/ci.yml?branch=main)
|
|
4
|
+
[](https://badge.fury.io/rb/spring)
|
|
5
5
|
|
|
6
6
|
Spring is a Rails application preloader. It speeds up development by
|
|
7
|
-
keeping your application running in the background so you don't need to
|
|
7
|
+
keeping your application running in the background, so you don't need to
|
|
8
8
|
boot it every time you run a test, rake task or migration.
|
|
9
9
|
|
|
10
10
|
## Features
|
|
@@ -16,8 +16,8 @@ boot it every time you run a test, rake task or migration.
|
|
|
16
16
|
|
|
17
17
|
## Compatibility
|
|
18
18
|
|
|
19
|
-
* Ruby versions: MRI
|
|
20
|
-
* Rails versions:
|
|
19
|
+
* Ruby versions: MRI 2.5, MRI 2.6
|
|
20
|
+
* Rails versions: 5.2, 6.0 (Spring is installed by default when you do
|
|
21
21
|
`rails new` to generate your application)
|
|
22
22
|
|
|
23
23
|
Spring makes extensive use of `Process.fork`, so won't be able to
|
|
@@ -27,14 +27,14 @@ provide a speed up on platforms which don't support forking (Windows, JRuby).
|
|
|
27
27
|
|
|
28
28
|
### Setup
|
|
29
29
|
|
|
30
|
-
Add
|
|
30
|
+
Add Spring to your Gemfile:
|
|
31
31
|
|
|
32
32
|
``` ruby
|
|
33
33
|
gem "spring", group: :development
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
(Note: using `gem "spring", git: "..."` *won't* work and is not a
|
|
37
|
-
supported way of using
|
|
37
|
+
supported way of using Spring.)
|
|
38
38
|
|
|
39
39
|
It's recommended to 'springify' the executables in your `bin/`
|
|
40
40
|
directory:
|
|
@@ -50,21 +50,32 @@ code into relevant existing executables. The snippet looks like this:
|
|
|
50
50
|
``` ruby
|
|
51
51
|
begin
|
|
52
52
|
load File.expand_path('../spring', __FILE__)
|
|
53
|
-
rescue LoadError
|
|
53
|
+
rescue LoadError => e
|
|
54
|
+
raise unless e.message.include?('spring')
|
|
54
55
|
end
|
|
55
56
|
```
|
|
56
57
|
|
|
57
|
-
On platforms where
|
|
58
|
-
hooks
|
|
59
|
-
will just be silently ignored and the lines after it will be executed as
|
|
58
|
+
On platforms where Spring is installed and supported, this snippet
|
|
59
|
+
hooks Spring into the execution of commands. In other cases, the snippet
|
|
60
|
+
will just be silently ignored, and the lines after it will be executed as
|
|
60
61
|
normal.
|
|
61
62
|
|
|
62
63
|
If you don't want to prefix every command you type with `bin/`, you
|
|
63
|
-
can [use direnv](https://github.com/
|
|
64
|
+
can [use direnv](https://github.com/direnv/direnv#the-stdlib) to
|
|
64
65
|
automatically add `./bin` to your `PATH` when you `cd` into your application.
|
|
65
66
|
Simply create an `.envrc` file with the command `PATH_add bin` in your
|
|
66
67
|
Rails directory.
|
|
67
68
|
|
|
69
|
+
### Enable reloading
|
|
70
|
+
|
|
71
|
+
Spring reloads application code, and therefore needs the application to have
|
|
72
|
+
reloading enabled.
|
|
73
|
+
|
|
74
|
+
Please, make sure `config.cache_classes` is `false` in the environments that
|
|
75
|
+
Spring manages. That setting is typically configured in
|
|
76
|
+
`config/environments/*.rb`. In particular, make sure it is `false` for the
|
|
77
|
+
`test` environment.
|
|
78
|
+
|
|
68
79
|
### Usage
|
|
69
80
|
|
|
70
81
|
For this walkthrough I've generated a new Rails application, and run
|
|
@@ -90,7 +101,7 @@ user 0m0.281s
|
|
|
90
101
|
sys 0m0.066s
|
|
91
102
|
```
|
|
92
103
|
|
|
93
|
-
That wasn't particularly fast because it was the first run, so
|
|
104
|
+
That wasn't particularly fast because it was the first run, so Spring
|
|
94
105
|
had to boot the application. It's now running:
|
|
95
106
|
|
|
96
107
|
```
|
|
@@ -167,8 +178,8 @@ Spring is running:
|
|
|
167
178
|
26707 spring app | spring-demo-app | started 2 secs ago | development mode
|
|
168
179
|
```
|
|
169
180
|
|
|
170
|
-
There's no need to "shut down"
|
|
171
|
-
when you close your terminal. However if you do want to do a manual shut
|
|
181
|
+
There's no need to "shut down" Spring. This will happen automatically
|
|
182
|
+
when you close your terminal. However, if you do want to do a manual shut
|
|
172
183
|
down, use the `stop` command:
|
|
173
184
|
|
|
174
185
|
```
|
|
@@ -176,9 +187,11 @@ $ bin/spring stop
|
|
|
176
187
|
Spring stopped.
|
|
177
188
|
```
|
|
178
189
|
|
|
190
|
+
From within your code, you can check whether Spring is active with `if defined?(Spring)`.
|
|
191
|
+
|
|
179
192
|
### Removal
|
|
180
193
|
|
|
181
|
-
To remove
|
|
194
|
+
To remove Spring:
|
|
182
195
|
|
|
183
196
|
* 'Unspring' your bin/ executables: `bin/spring binstub --remove --all`
|
|
184
197
|
* Remove spring from your Gemfile
|
|
@@ -186,12 +199,13 @@ To remove spring:
|
|
|
186
199
|
### Deployment
|
|
187
200
|
|
|
188
201
|
You must not install Spring on your production environment. To prevent it from
|
|
189
|
-
being installed,
|
|
202
|
+
being installed, run the `bundle config set without 'development test'` before
|
|
190
203
|
`bundle install` command which is used to install gems on your production
|
|
191
204
|
machines:
|
|
192
205
|
|
|
193
206
|
```
|
|
194
|
-
$ bundle
|
|
207
|
+
$ bundle config set without 'development test'
|
|
208
|
+
$ bundle install
|
|
195
209
|
```
|
|
196
210
|
|
|
197
211
|
## Commands
|
|
@@ -216,7 +230,7 @@ Spring::Commands::Rake.environment_matchers[:default] = "development"
|
|
|
216
230
|
### `rails console`, `rails generate`, `rails runner`
|
|
217
231
|
|
|
218
232
|
These execute the rails command you already know and love. If you run
|
|
219
|
-
a different sub command (e.g. `rails server`) then
|
|
233
|
+
a different sub command (e.g. `rails server`) then Spring will automatically
|
|
220
234
|
pass it through to the underlying `rails` executable (without the
|
|
221
235
|
speed-up).
|
|
222
236
|
|
|
@@ -230,18 +244,22 @@ You can add these to your Gemfile for additional commands:
|
|
|
230
244
|
* [spring-commands-testunit](https://github.com/jonleighton/spring-commands-testunit) - useful for
|
|
231
245
|
running `Test::Unit` tests on Rails 3, since only Rails 4 allows you
|
|
232
246
|
to use `rake test path/to/test` to run a particular test/directory.
|
|
247
|
+
* [spring-commands-parallel-tests](https://github.com/DocSpring/spring-commands-parallel-tests) - Adds the `parallel_*` commands from [`parallel_tests`](https://github.com/grosser/parallel_tests).
|
|
233
248
|
* [spring-commands-teaspoon](https://github.com/alejandrobabio/spring-commands-teaspoon.git)
|
|
234
249
|
* [spring-commands-m](https://github.com/gabrieljoelc/spring-commands-m.git)
|
|
235
250
|
* [spring-commands-rubocop](https://github.com/p0deje/spring-commands-rubocop)
|
|
251
|
+
* [spring-commands-rackup](https://github.com/wintersolutions/spring-commands-rackup)
|
|
252
|
+
* [spring-commands-rack-console](https://github.com/wintersolutions/spring-commands-rack-console)
|
|
253
|
+
* [spring-commands-standard](https://github.com/lakim/spring-commands-standard)
|
|
236
254
|
|
|
237
255
|
## Use without adding to bundle
|
|
238
256
|
|
|
239
|
-
If you don't want
|
|
240
|
-
repository, it's possible to use
|
|
241
|
-
However, using
|
|
257
|
+
If you don't want Spring-related code checked into your source
|
|
258
|
+
repository, it's possible to use Spring without adding to your Gemfile.
|
|
259
|
+
However, using Spring binstubs without adding Spring to the Gemfile is not
|
|
242
260
|
supported.
|
|
243
261
|
|
|
244
|
-
To use
|
|
262
|
+
To use Spring like this, do a `gem install spring` and then prefix
|
|
245
263
|
commands with `spring`. For example, rather than running `bin/rake -T`,
|
|
246
264
|
you'd run `spring rake -T`.
|
|
247
265
|
|
|
@@ -252,12 +270,10 @@ run through Spring, set the `DISABLE_SPRING` environment variable.
|
|
|
252
270
|
|
|
253
271
|
## Class reloading
|
|
254
272
|
|
|
255
|
-
Spring uses Rails' class reloading mechanism
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
have used this mechanism with your `test` environment before, and this
|
|
260
|
-
can cause problems.
|
|
273
|
+
Spring uses Rails' class reloading mechanism to keep your code up to date
|
|
274
|
+
between test runs. This is the same mechanism which allows you to see changes
|
|
275
|
+
during development when you refresh the page. However, you may never have used
|
|
276
|
+
this mechanism with your `test` environment before, and this can cause problems.
|
|
261
277
|
|
|
262
278
|
It's important to realise that code reloading means that the constants
|
|
263
279
|
in your application are *different objects* after files have changed:
|
|
@@ -357,7 +373,7 @@ application restart, you can specify them with `Spring.watch`:
|
|
|
357
373
|
Spring.watch "config/some_config_file.yml"
|
|
358
374
|
```
|
|
359
375
|
|
|
360
|
-
By default Spring polls the filesystem for changes once every 0.2 seconds. This
|
|
376
|
+
By default, Spring polls the filesystem for changes once every 0.2 seconds. This
|
|
361
377
|
method requires zero configuration, but if you find that it's using too
|
|
362
378
|
much CPU, then you can use event-based file system listening by
|
|
363
379
|
installing the
|
|
@@ -377,34 +393,34 @@ Spring.quiet = true
|
|
|
377
393
|
|
|
378
394
|
The following environment variables are used by Spring:
|
|
379
395
|
|
|
380
|
-
* `DISABLE_SPRING` - If set, Spring will be bypassed and your
|
|
396
|
+
* `DISABLE_SPRING` - If set, Spring will be bypassed, and your
|
|
381
397
|
application will boot in a foreground process
|
|
382
398
|
* `SPRING_LOG` - The path to a file which Spring will write log messages
|
|
383
399
|
to.
|
|
384
400
|
* `SPRING_TMP_PATH` - The directory where Spring should write its temporary
|
|
385
|
-
files (a pidfile and a socket). By default we use the
|
|
401
|
+
files (a pidfile and a socket). By default, we use the
|
|
386
402
|
`XDG_RUNTIME_DIR` environment variable, or else `Dir.tmpdir`, and then
|
|
387
403
|
create a directory in that named `spring-$UID`. We don't use your
|
|
388
404
|
Rails application's `tmp/` directory because that may be on a
|
|
389
405
|
filesystem which doesn't support UNIX sockets.
|
|
390
406
|
* `SPRING_APPLICATION_ID` - Used to identify distinct Rails
|
|
391
|
-
applications. By default it is an MD5 hash of the current
|
|
407
|
+
applications. By default, it is an MD5 hash of the current
|
|
392
408
|
`RUBY_VERSION`, and the path to your Rails project root.
|
|
393
409
|
* `SPRING_SOCKET` - The path which should be used for the UNIX socket
|
|
394
410
|
which Spring uses to communicate with the long-running Spring server
|
|
395
|
-
process. By default this is `SPRING_TMP_PATH/SPRING_APPLICATION_ID`.
|
|
411
|
+
process. By default, this is `SPRING_TMP_PATH/SPRING_APPLICATION_ID`.
|
|
396
412
|
* `SPRING_PIDFILE` - The path which should be used to store the pid of
|
|
397
|
-
the long-running Spring server process. By default this is related to
|
|
413
|
+
the long-running Spring server process. By default, this is related to
|
|
398
414
|
the socket path; if the socket path is `/foo/bar/spring.sock` the
|
|
399
415
|
pidfile will be `/foo/bar/spring.pid`.
|
|
400
|
-
* `SPRING_SERVER_COMMAND` - The command to run to start up the
|
|
416
|
+
* `SPRING_SERVER_COMMAND` - The command to run to start up the Spring
|
|
401
417
|
server when it is not already running. Defaults to `spring _[version]_
|
|
402
418
|
server --background`.
|
|
403
419
|
|
|
404
420
|
## Troubleshooting
|
|
405
421
|
|
|
406
|
-
If you want to get more information about what
|
|
407
|
-
run
|
|
422
|
+
If you want to get more information about what Spring is doing, you can
|
|
423
|
+
run Spring explicitly in a separate terminal:
|
|
408
424
|
|
|
409
425
|
```
|
|
410
426
|
$ spring server
|
data/lib/spring/application.rb
CHANGED
|
@@ -12,6 +12,7 @@ module Spring
|
|
|
12
12
|
@spring_env = spring_env
|
|
13
13
|
@mutex = Mutex.new
|
|
14
14
|
@waiting = Set.new
|
|
15
|
+
@clients = Set.new
|
|
15
16
|
@preloaded = false
|
|
16
17
|
@state = :initialized
|
|
17
18
|
@interrupt = IO.pipe
|
|
@@ -91,18 +92,20 @@ module Spring
|
|
|
91
92
|
|
|
92
93
|
require Spring.application_root_path.join("config", "application")
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
# override the effect of config.cache_classes = true. We can then actually
|
|
97
|
-
# set config.cache_classes = false after loading the environment.
|
|
98
|
-
Rails::Application.initializer :initialize_dependency_mechanism, group: :all do
|
|
99
|
-
ActiveSupport::Dependencies.mechanism = :load
|
|
95
|
+
unless Rails.respond_to?(:gem_version) && Rails.gem_version >= Gem::Version.new('5.2.0')
|
|
96
|
+
raise "Spring only supports Rails >= 5.2.0"
|
|
100
97
|
end
|
|
101
98
|
|
|
102
|
-
|
|
99
|
+
Rails::Application.initializer :ensure_reloading_is_enabled, group: :all do
|
|
100
|
+
if Rails.application.config.cache_classes
|
|
101
|
+
raise <<-MSG.strip_heredoc
|
|
102
|
+
Spring reloads, and therefore needs the application to have reloading enabled.
|
|
103
|
+
Please, set config.cache_classes to false in config/environments/#{Rails.env}.rb.
|
|
104
|
+
MSG
|
|
105
|
+
end
|
|
106
|
+
end
|
|
103
107
|
|
|
104
|
-
|
|
105
|
-
Rails.application.config.cache_classes = false
|
|
108
|
+
require Spring.application_root_path.join("config", "environment")
|
|
106
109
|
|
|
107
110
|
disconnect_database
|
|
108
111
|
|
|
@@ -113,7 +116,7 @@ module Spring
|
|
|
113
116
|
raise e unless initialized?
|
|
114
117
|
ensure
|
|
115
118
|
watcher.add loaded_application_features
|
|
116
|
-
watcher.add Spring.gemfile,
|
|
119
|
+
watcher.add Spring.gemfile, Spring.gemfile_lock
|
|
117
120
|
|
|
118
121
|
if defined?(Rails) && Rails.application
|
|
119
122
|
watcher.add Rails.application.paths["config/initializers"]
|
|
@@ -147,10 +150,23 @@ module Spring
|
|
|
147
150
|
log "got client"
|
|
148
151
|
manager.puts
|
|
149
152
|
|
|
150
|
-
|
|
153
|
+
@clients << client
|
|
154
|
+
|
|
155
|
+
_stdout, stderr, _stdin = streams = 3.times.map { client.recv_io }
|
|
151
156
|
[STDOUT, STDERR, STDIN].zip(streams).each { |a, b| a.reopen(b) }
|
|
152
157
|
|
|
153
|
-
|
|
158
|
+
if preloaded?
|
|
159
|
+
client.puts(0) # preload success
|
|
160
|
+
else
|
|
161
|
+
begin
|
|
162
|
+
preload
|
|
163
|
+
client.puts(0) # preload success
|
|
164
|
+
rescue Exception
|
|
165
|
+
log "preload failed"
|
|
166
|
+
client.puts(1) # preload failure
|
|
167
|
+
raise
|
|
168
|
+
end
|
|
169
|
+
end
|
|
154
170
|
|
|
155
171
|
args, env = JSON.load(client.read(client.gets.to_i)).values_at("args", "env")
|
|
156
172
|
command = Spring.command(args.shift)
|
|
@@ -159,39 +175,39 @@ module Spring
|
|
|
159
175
|
setup command
|
|
160
176
|
|
|
161
177
|
if Rails.application.reloaders.any?(&:updated?)
|
|
162
|
-
|
|
163
|
-
if defined? ActiveSupport::Reloader
|
|
164
|
-
Rails.application.reloader.reload!
|
|
165
|
-
else
|
|
166
|
-
ActionDispatch::Reloader.cleanup!
|
|
167
|
-
ActionDispatch::Reloader.prepare!
|
|
168
|
-
end
|
|
178
|
+
Rails.application.reloader.reload!
|
|
169
179
|
end
|
|
170
180
|
|
|
171
181
|
pid = fork {
|
|
182
|
+
# Make sure to close other clients otherwise their graceful termination
|
|
183
|
+
# will be impossible due to reference from this fork.
|
|
184
|
+
@clients.select { |c| c != client }.each(&:close)
|
|
185
|
+
|
|
172
186
|
Process.setsid
|
|
173
187
|
IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
|
|
174
188
|
trap("TERM", "DEFAULT")
|
|
175
189
|
|
|
176
|
-
|
|
190
|
+
unless Spring.quiet
|
|
191
|
+
STDERR.puts "Running via Spring preloader in process #{Process.pid}"
|
|
192
|
+
|
|
193
|
+
if Rails.env.production?
|
|
194
|
+
STDERR.puts "WARNING: Spring is running in production. To fix " \
|
|
195
|
+
"this make sure the spring gem is only present " \
|
|
196
|
+
"in `development` and `test` groups in your Gemfile " \
|
|
197
|
+
"and make sure you always use " \
|
|
198
|
+
"`bundle install --without development test` in production"
|
|
199
|
+
end
|
|
200
|
+
end
|
|
177
201
|
|
|
178
202
|
ARGV.replace(args)
|
|
179
203
|
$0 = command.exec_name
|
|
180
204
|
|
|
181
|
-
# Delete all env vars which are unchanged from before
|
|
205
|
+
# Delete all env vars which are unchanged from before Spring started
|
|
182
206
|
original_env.each { |k, v| ENV.delete k if ENV[k] == v }
|
|
183
207
|
|
|
184
|
-
# Load in the current env vars, except those which *were* changed when
|
|
208
|
+
# Load in the current env vars, except those which *were* changed when Spring started
|
|
185
209
|
env.each { |k, v| ENV[k] ||= v }
|
|
186
210
|
|
|
187
|
-
# requiring is faster, so if config.cache_classes was true in
|
|
188
|
-
# the environment's config file, then we can respect that from
|
|
189
|
-
# here on as we no longer need constant reloading.
|
|
190
|
-
if @original_cache_classes
|
|
191
|
-
ActiveSupport::Dependencies.mechanism = :require
|
|
192
|
-
Rails.application.config.cache_classes = true
|
|
193
|
-
end
|
|
194
|
-
|
|
195
211
|
connect_database
|
|
196
212
|
srand
|
|
197
213
|
|
|
@@ -7,6 +7,7 @@ module Spring
|
|
|
7
7
|
@spring_env = spring_env
|
|
8
8
|
@mutex = Mutex.new
|
|
9
9
|
@state = :running
|
|
10
|
+
@pid = nil
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def log(message)
|
|
@@ -92,7 +93,8 @@ module Spring
|
|
|
92
93
|
def start_child(preload = false)
|
|
93
94
|
@child, child_socket = UNIXSocket.pair
|
|
94
95
|
|
|
95
|
-
Bundler.
|
|
96
|
+
Bundler.with_original_env do
|
|
97
|
+
bundler_dir = File.expand_path("../..", $LOADED_FEATURES.grep(/bundler\/setup\.rb$/).first)
|
|
96
98
|
@pid = Process.spawn(
|
|
97
99
|
{
|
|
98
100
|
"RAILS_ENV" => app_env,
|
|
@@ -101,7 +103,7 @@ module Spring
|
|
|
101
103
|
"SPRING_PRELOAD" => preload ? "1" : "0"
|
|
102
104
|
},
|
|
103
105
|
"ruby",
|
|
104
|
-
"
|
|
106
|
+
*(bundler_dir != RbConfig::CONFIG["rubylibdir"] ? ["-I", bundler_dir] : []),
|
|
105
107
|
"-I", File.expand_path("../..", __FILE__),
|
|
106
108
|
"-e", "require 'spring/application/boot'",
|
|
107
109
|
3 => child_socket,
|
data/lib/spring/binstub.rb
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
command = File.basename($0)
|
|
2
2
|
bin_path = File.expand_path("../../../bin/spring", __FILE__)
|
|
3
3
|
|
|
4
|
-
# When we run a command which does not go through Spring (e.g. DISABLE_SPRING
|
|
5
|
-
# is used, or we just call 'rails' or something) then we get this warning from
|
|
6
|
-
# Rubygems:
|
|
7
|
-
#
|
|
8
|
-
# WARN: Unresolved specs during Gem::Specification.reset: activesupport (<= 5.1, >= 4.2)
|
|
9
|
-
# WARN: Clearing out unresolved specs.
|
|
10
|
-
# Please report a bug if this causes problems.
|
|
11
|
-
#
|
|
12
|
-
# This happens due to our dependency on activesupport, when Bundler.setup gets
|
|
13
|
-
# called. We don't actually *use* the dependency; it is purely there to
|
|
14
|
-
# restrict the Rails version that we're compatible with.
|
|
15
|
-
#
|
|
16
|
-
# When the warning is shown, Rubygems just does the below.
|
|
17
|
-
# Therefore, by doing it ourselves here, we can avoid the warning.
|
|
18
|
-
if Gem::Specification.respond_to?(:unresolved_deps)
|
|
19
|
-
Gem::Specification.unresolved_deps.clear
|
|
20
|
-
else
|
|
21
|
-
Gem.unresolved_deps.clear
|
|
22
|
-
end
|
|
23
|
-
|
|
24
4
|
if command == "spring"
|
|
25
5
|
load bin_path
|
|
26
6
|
else
|
|
@@ -3,11 +3,11 @@ require 'set'
|
|
|
3
3
|
module Spring
|
|
4
4
|
module Client
|
|
5
5
|
class Binstub < Command
|
|
6
|
-
SHEBANG = /\#\!.*\n
|
|
6
|
+
SHEBANG = /\#\!.*\n(\#.*\n)*/
|
|
7
7
|
|
|
8
|
-
# If loading the bin/spring file works, it'll run
|
|
8
|
+
# If loading the bin/spring file works, it'll run Spring which will
|
|
9
9
|
# eventually call Kernel.exit. This means that in the client process
|
|
10
|
-
# we will never execute the lines after this block. But if the
|
|
10
|
+
# we will never execute the lines after this block. But if the Spring
|
|
11
11
|
# client is not invoked for whatever reason, then the Kernel.exit won't
|
|
12
12
|
# happen, and so we'll fall back to the lines after this block, which
|
|
13
13
|
# should cause the "unsprung" version of the command to run.
|
|
@@ -26,7 +26,7 @@ CODE
|
|
|
26
26
|
SPRING = <<'CODE'
|
|
27
27
|
#!/usr/bin/env ruby
|
|
28
28
|
|
|
29
|
-
# This file loads
|
|
29
|
+
# This file loads Spring without using Bundler, in order to be fast.
|
|
30
30
|
# It gets overwritten when you run the `spring binstub` command.
|
|
31
31
|
|
|
32
32
|
unless defined?(Spring)
|
|
@@ -34,7 +34,7 @@ unless defined?(Spring)
|
|
|
34
34
|
require 'bundler'
|
|
35
35
|
|
|
36
36
|
lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read)
|
|
37
|
-
spring = lockfile.specs.detect { |spec| spec.name ==
|
|
37
|
+
spring = lockfile.specs.detect { |spec| spec.name == 'spring' }
|
|
38
38
|
if spring
|
|
39
39
|
Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
|
|
40
40
|
gem 'spring', spring.version
|
|
@@ -46,11 +46,10 @@ CODE
|
|
|
46
46
|
OLD_BINSTUB = %{if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?}
|
|
47
47
|
|
|
48
48
|
BINSTUB_VARIATIONS = Regexp.union [
|
|
49
|
-
%{begin\n load File.expand_path("../spring", __FILE__)\nrescue LoadError\nend\n},
|
|
50
49
|
%{begin\n load File.expand_path('../spring', __FILE__)\nrescue LoadError\nend\n},
|
|
51
50
|
%{begin\n spring_bin_path = File.expand_path('../spring', __FILE__)\n load spring_bin_path\nrescue LoadError => e\n raise unless e.message.end_with? spring_bin_path, 'spring/binstub'\nend\n},
|
|
52
51
|
LOADER
|
|
53
|
-
]
|
|
52
|
+
].map { |binstub| /#{Regexp.escape(binstub).gsub("'", "['\"]")}/ }
|
|
54
53
|
|
|
55
54
|
class Item
|
|
56
55
|
attr_reader :command, :existing
|
|
@@ -79,7 +78,7 @@ CODE
|
|
|
79
78
|
generate(fallback)
|
|
80
79
|
status "upgraded"
|
|
81
80
|
elsif existing.include?(LOADER)
|
|
82
|
-
status "
|
|
81
|
+
status "Spring already present"
|
|
83
82
|
elsif existing =~ BINSTUB_VARIATIONS
|
|
84
83
|
upgraded = existing.sub(BINSTUB_VARIATIONS, LOADER)
|
|
85
84
|
File.write(command.binstub, upgraded)
|
|
@@ -94,15 +93,15 @@ CODE
|
|
|
94
93
|
end
|
|
95
94
|
|
|
96
95
|
File.write(command.binstub, "#{head}#{shebang}#{LOADER}#{tail}")
|
|
97
|
-
status "
|
|
96
|
+
status "Spring inserted"
|
|
98
97
|
else
|
|
99
|
-
status "doesn't appear to be ruby, so cannot use
|
|
98
|
+
status "doesn't appear to be ruby, so cannot use Spring", $stderr
|
|
100
99
|
exit 1
|
|
101
100
|
end
|
|
102
101
|
end
|
|
103
102
|
else
|
|
104
103
|
generate
|
|
105
|
-
status "generated with
|
|
104
|
+
status "generated with Spring"
|
|
106
105
|
end
|
|
107
106
|
end
|
|
108
107
|
|
|
@@ -119,7 +118,7 @@ CODE
|
|
|
119
118
|
def remove
|
|
120
119
|
if existing
|
|
121
120
|
File.write(command.binstub, existing.sub(BINSTUB_VARIATIONS, ""))
|
|
122
|
-
status "
|
|
121
|
+
status "Spring removed"
|
|
123
122
|
end
|
|
124
123
|
end
|
|
125
124
|
end
|
|
@@ -127,7 +126,7 @@ CODE
|
|
|
127
126
|
attr_reader :bindir, :items
|
|
128
127
|
|
|
129
128
|
def self.description
|
|
130
|
-
"Generate
|
|
129
|
+
"Generate Spring based binstubs. Use --all to generate a binstub for all known commands. Use --remove to revert."
|
|
131
130
|
end
|
|
132
131
|
|
|
133
132
|
def self.rails_command
|
data/lib/spring/client/help.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Spring
|
|
|
32
32
|
def formatted_help
|
|
33
33
|
["Version: #{env.version}\n",
|
|
34
34
|
"Usage: spring COMMAND [ARGS]\n",
|
|
35
|
-
*command_help("
|
|
35
|
+
*command_help("Spring itself", spring_commands),
|
|
36
36
|
'',
|
|
37
37
|
*command_help("your application", application_commands)].join("\n")
|
|
38
38
|
end
|
data/lib/spring/client/rails.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Spring
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
def self.description
|
|
17
|
-
"Run a rails command. The following sub commands will use
|
|
17
|
+
"Run a rails command. The following sub commands will use Spring: #{COMMANDS.to_a.join ', '}."
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def call
|
|
@@ -22,6 +22,8 @@ module Spring
|
|
|
22
22
|
|
|
23
23
|
if COMMANDS.include?(command_name)
|
|
24
24
|
Run.call(["rails_#{command_name}", *args.drop(2)])
|
|
25
|
+
elsif command_name.start_with?("db:")
|
|
26
|
+
Run.call(["rake", *args.drop(1)])
|
|
25
27
|
else
|
|
26
28
|
require "spring/configuration"
|
|
27
29
|
ARGV.shift
|
data/lib/spring/client/run.rb
CHANGED
|
@@ -44,7 +44,7 @@ module Spring
|
|
|
44
44
|
require "spring/commands"
|
|
45
45
|
|
|
46
46
|
if Spring.command?(args.first)
|
|
47
|
-
# Command installed since
|
|
47
|
+
# Command installed since Spring started
|
|
48
48
|
stop_server
|
|
49
49
|
cold_run
|
|
50
50
|
else
|
|
@@ -116,7 +116,7 @@ module Spring
|
|
|
116
116
|
def verify_server_version
|
|
117
117
|
server_version = server.gets.chomp
|
|
118
118
|
if server_version != env.version
|
|
119
|
-
$stderr.puts "There is a version mismatch between the
|
|
119
|
+
$stderr.puts "There is a version mismatch between the Spring client " \
|
|
120
120
|
"(#{env.version}) and the server (#{server_version})."
|
|
121
121
|
|
|
122
122
|
if server_booted?
|
|
@@ -142,12 +142,17 @@ module Spring
|
|
|
142
142
|
end
|
|
143
143
|
|
|
144
144
|
def run_command(client, application)
|
|
145
|
-
log "sending command"
|
|
146
|
-
|
|
147
145
|
application.send_io STDOUT
|
|
148
146
|
application.send_io STDERR
|
|
149
147
|
application.send_io STDIN
|
|
150
148
|
|
|
149
|
+
log "waiting for the application to be preloaded"
|
|
150
|
+
preload_status = application.gets
|
|
151
|
+
preload_status = preload_status.chomp if preload_status
|
|
152
|
+
log "app preload status: #{preload_status}"
|
|
153
|
+
exit 1 if preload_status == "1"
|
|
154
|
+
|
|
155
|
+
log "sending command"
|
|
151
156
|
send_json application, "args" => args, "env" => ENV.to_hash
|
|
152
157
|
|
|
153
158
|
pid = server.gets
|
|
@@ -161,6 +166,8 @@ module Spring
|
|
|
161
166
|
if pid && !pid.empty?
|
|
162
167
|
log "got pid: #{pid}"
|
|
163
168
|
|
|
169
|
+
suspend_resume_on_tstp_cont(pid)
|
|
170
|
+
|
|
164
171
|
forward_signals(application)
|
|
165
172
|
status = application.read.to_i
|
|
166
173
|
|
|
@@ -181,6 +188,18 @@ module Spring
|
|
|
181
188
|
end
|
|
182
189
|
end
|
|
183
190
|
|
|
191
|
+
def suspend_resume_on_tstp_cont(pid)
|
|
192
|
+
trap("TSTP") {
|
|
193
|
+
log "suspended"
|
|
194
|
+
Process.kill("STOP", pid.to_i)
|
|
195
|
+
Process.kill("STOP", Process.pid)
|
|
196
|
+
}
|
|
197
|
+
trap("CONT") {
|
|
198
|
+
log "resumed"
|
|
199
|
+
Process.kill("CONT", pid.to_i)
|
|
200
|
+
}
|
|
201
|
+
end
|
|
202
|
+
|
|
184
203
|
def forward_signals(application)
|
|
185
204
|
@signal_queue.each { |sig| kill sig, application }
|
|
186
205
|
|
data/lib/spring/client/stop.rb
CHANGED
data/lib/spring/commands.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Spring
|
|
|
32
32
|
# then we need to be under bundler.
|
|
33
33
|
require "bundler/setup"
|
|
34
34
|
|
|
35
|
-
# Auto-require any
|
|
35
|
+
# Auto-require any Spring extensions which are in the Gemfile
|
|
36
36
|
Gem::Specification.map(&:name).grep(/^spring-/).each do |command|
|
|
37
37
|
begin
|
|
38
38
|
require command
|
data/lib/spring/configuration.rb
CHANGED
|
@@ -5,7 +5,22 @@ module Spring
|
|
|
5
5
|
attr_accessor :application_root, :quiet
|
|
6
6
|
|
|
7
7
|
def gemfile
|
|
8
|
-
|
|
8
|
+
require "bundler"
|
|
9
|
+
|
|
10
|
+
if /\s1.9.[0-9]/ === Bundler.ruby_scope.gsub(/[\/\s]+/,'')
|
|
11
|
+
Pathname.new(ENV["BUNDLE_GEMFILE"] || "Gemfile").expand_path
|
|
12
|
+
else
|
|
13
|
+
Bundler.default_gemfile
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def gemfile_lock
|
|
18
|
+
case gemfile.to_s
|
|
19
|
+
when /\bgems\.rb\z/
|
|
20
|
+
gemfile.sub_ext('.locked')
|
|
21
|
+
else
|
|
22
|
+
gemfile.sub_ext('.lock')
|
|
23
|
+
end
|
|
9
24
|
end
|
|
10
25
|
|
|
11
26
|
def after_fork_callbacks
|