spring 2.0.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 492a555d7260fc775b233acca0a3fddfb2d20c88
4
- data.tar.gz: ccfc69cc32e5105e3de6cb75ae19538d3958b44e
2
+ SHA256:
3
+ metadata.gz: 1f2e2dd87b67447e8ec1404be4f904fe1339e536dabddde397662313a7bb116d
4
+ data.tar.gz: 467c115d0fff87ded2aa4a7d761419f74ce9b45798f12568e21d97e1b261599f
5
5
  SHA512:
6
- metadata.gz: 7bb6d3f377d2004b10b01dcba207c2b1ec285f5e04d1721edc4ad436d6e50d99337d8ba584f08d5a99daf60ef06af853435a760edf467360a5a93919ec1d35ec
7
- data.tar.gz: dea0ae70aa4e56ef9aeb525faa1350b711c1f90d87171ce1d530380469da3773b478285a50ab94b628cf6afb81e05237a8cc269cc09a1a3408275af59ff6db7c
6
+ metadata.gz: 3cc3b61d71972b7150fdbf7331ce1e55d447fabecbc4ba55914ce2621a9221fbb913efa31b715f80f77ff807dba06b3f89e26454ef623d8d2bc26af6b6f442a3
7
+ data.tar.gz: b459527ad5f9301dd75b1e2f5c9d6e6418e7c019c3a0073a4c6e905b9118db5193bcad051bba88fd5f55cbf124037332ed6a940cd857e4c59d67127d02dbb951
data/LICENSE.txt CHANGED
@@ -1,4 +1,5 @@
1
- Copyright (c) 2012-2016 Jon Leighton
1
+ Copyright (c) 2017-2021 Rafael Mendonça França
2
+ Copyright (c) 2012-2017 Jon Leighton
2
3
 
3
4
  MIT License
4
5
 
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Spring
2
2
 
3
- [![Build Status](https://travis-ci.org/rails/spring.svg?branch=master)](https://travis-ci.org/rails/spring)
4
- [![Gem Version](https://badge.fury.io/rb/spring.svg)](http://badge.fury.io/rb/spring)
3
+ [![Build Status](https://github.com/rails/spring/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/rails/spring/actions/workflows/ci.yml?branch=main)
4
+ [![Gem Version](https://badge.fury.io/rb/spring.svg)](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 1.9.3, MRI 2.0, MRI 2.1, MRI 2.2
20
- * Rails versions: 4.2, 5.0 (Spring is installed by default when you do
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 spring to your Gemfile:
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 spring.)
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 spring is installed and supported, this snippet
58
- hooks spring into the execution of commands. In other cases, the snippet
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/zimbatm/direnv#the-stdlib) to
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 spring
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" spring. This will happen automatically
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 spring:
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, provide the `--without development test` argument to the
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 install --without development test
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 spring will automatically
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 spring-related code checked into your source
240
- repository, it's possible to use spring without adding to your Gemfile.
241
- However, using spring binstubs without adding spring to the Gemfile is not
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 spring like this, do a `gem install spring` and then prefix
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
- (`ActiveSupport::Dependencies`) to keep your code up to date between
257
- test runs. This is the same mechanism which allows you to see changes
258
- during development when you refresh the page. However, you may never
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 spring
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 spring is doing, you can
407
- run spring explicitly in a separate terminal:
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
@@ -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
@@ -66,7 +67,17 @@ module Spring
66
67
 
67
68
  def start_watcher
68
69
  @watcher = Spring.watcher
69
- @watcher.on_stale { state! :watcher_stale }
70
+
71
+ @watcher.on_stale do
72
+ state! :watcher_stale
73
+ end
74
+
75
+ if @watcher.respond_to? :on_debug
76
+ @watcher.on_debug do |message|
77
+ spring_env.log "[watcher:#{app_env}] #{message}"
78
+ end
79
+ end
80
+
70
81
  @watcher.start
71
82
  end
72
83
 
@@ -81,18 +92,20 @@ module Spring
81
92
 
82
93
  require Spring.application_root_path.join("config", "application")
83
94
 
84
- # config/environments/test.rb will have config.cache_classes = true. However
85
- # we want it to be false so that we can reload files. This is a hack to
86
- # override the effect of config.cache_classes = true. We can then actually
87
- # set config.cache_classes = false after loading the environment.
88
- Rails::Application.initializer :initialize_dependency_mechanism, group: :all do
89
- 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"
90
97
  end
91
98
 
92
- require Spring.application_root_path.join("config", "environment")
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
93
107
 
94
- @original_cache_classes = Rails.application.config.cache_classes
95
- Rails.application.config.cache_classes = false
108
+ require Spring.application_root_path.join("config", "environment")
96
109
 
97
110
  disconnect_database
98
111
 
@@ -103,7 +116,7 @@ module Spring
103
116
  raise e unless initialized?
104
117
  ensure
105
118
  watcher.add loaded_application_features
106
- watcher.add Spring.gemfile, "#{Spring.gemfile}.lock"
119
+ watcher.add Spring.gemfile, Spring.gemfile_lock
107
120
 
108
121
  if defined?(Rails) && Rails.application
109
122
  watcher.add Rails.application.paths["config/initializers"]
@@ -137,10 +150,23 @@ module Spring
137
150
  log "got client"
138
151
  manager.puts
139
152
 
140
- stdout, stderr, stdin = streams = 3.times.map { client.recv_io }
153
+ @clients << client
154
+
155
+ _stdout, stderr, _stdin = streams = 3.times.map { client.recv_io }
141
156
  [STDOUT, STDERR, STDIN].zip(streams).each { |a, b| a.reopen(b) }
142
157
 
143
- preload unless preloaded?
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
144
170
 
145
171
  args, env = JSON.load(client.read(client.gets.to_i)).values_at("args", "env")
146
172
  command = Spring.command(args.shift)
@@ -149,39 +175,39 @@ module Spring
149
175
  setup command
150
176
 
151
177
  if Rails.application.reloaders.any?(&:updated?)
152
- # Rails 5.1 forward-compat. AD::R is deprecated to AS::R in Rails 5.
153
- if defined? ActiveSupport::Reloader
154
- Rails.application.reloader.reload!
155
- else
156
- ActionDispatch::Reloader.cleanup!
157
- ActionDispatch::Reloader.prepare!
158
- end
178
+ Rails.application.reloader.reload!
159
179
  end
160
180
 
161
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
+
162
186
  Process.setsid
163
187
  IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
164
188
  trap("TERM", "DEFAULT")
165
189
 
166
- STDERR.puts "Running via Spring preloader in process #{Process.pid}" unless Spring.quiet
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
167
201
 
168
202
  ARGV.replace(args)
169
203
  $0 = command.exec_name
170
204
 
171
- # Delete all env vars which are unchanged from before spring started
205
+ # Delete all env vars which are unchanged from before Spring started
172
206
  original_env.each { |k, v| ENV.delete k if ENV[k] == v }
173
207
 
174
- # Load in the current env vars, except those which *were* changed when spring started
208
+ # Load in the current env vars, except those which *were* changed when Spring started
175
209
  env.each { |k, v| ENV[k] ||= v }
176
210
 
177
- # requiring is faster, so if config.cache_classes was true in
178
- # the environment's config file, then we can respect that from
179
- # here on as we no longer need constant reloading.
180
- if @original_cache_classes
181
- ActiveSupport::Dependencies.mechanism = :require
182
- Rails.application.config.cache_classes = true
183
- end
184
-
185
211
  connect_database
186
212
  srand
187
213
 
@@ -278,7 +304,7 @@ module Spring
278
304
  ensure
279
305
  if $!
280
306
  lib = File.expand_path("..", __FILE__)
281
- $!.backtrace.reject! { |line| line.start_with?(lib) }
307
+ $!.backtrace.reject! { |line| line.start_with?(lib) } unless $!.backtrace.frozen?
282
308
  end
283
309
  end
284
310
  end
@@ -295,10 +321,11 @@ module Spring
295
321
  def with_pty
296
322
  PTY.open do |master, slave|
297
323
  [STDOUT, STDERR, STDIN].each { |s| s.reopen slave }
298
- Thread.new { master.read }
324
+ reader_thread = Spring.failsafe_thread { master.read }
299
325
  begin
300
326
  yield
301
327
  ensure
328
+ reader_thread.kill
302
329
  reset_streams
303
330
  end
304
331
  end
@@ -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.with_clean_env do
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
- "-I", File.expand_path("../..", $LOADED_FEATURES.grep(/bundler\/setup\.rb$/).first),
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,
@@ -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 spring which will
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 spring
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 spring without using Bundler, in order to be fast.
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,8 @@ unless defined?(Spring)
34
34
  require 'bundler'
35
35
 
36
36
  lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read)
37
- if spring = lockfile.specs.detect { |spec| spec.name == "spring" }
37
+ spring = lockfile.specs.detect { |spec| spec.name == 'spring' }
38
+ if spring
38
39
  Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
39
40
  gem 'spring', spring.version
40
41
  require 'spring/binstub'
@@ -45,11 +46,10 @@ CODE
45
46
  OLD_BINSTUB = %{if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?}
46
47
 
47
48
  BINSTUB_VARIATIONS = Regexp.union [
48
- %{begin\n load File.expand_path("../spring", __FILE__)\nrescue LoadError\nend\n},
49
49
  %{begin\n load File.expand_path('../spring', __FILE__)\nrescue LoadError\nend\n},
50
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},
51
51
  LOADER
52
- ]
52
+ ].map { |binstub| /#{Regexp.escape(binstub).gsub("'", "['\"]")}/ }
53
53
 
54
54
  class Item
55
55
  attr_reader :command, :existing
@@ -78,7 +78,7 @@ CODE
78
78
  generate(fallback)
79
79
  status "upgraded"
80
80
  elsif existing.include?(LOADER)
81
- status "spring already present"
81
+ status "Spring already present"
82
82
  elsif existing =~ BINSTUB_VARIATIONS
83
83
  upgraded = existing.sub(BINSTUB_VARIATIONS, LOADER)
84
84
  File.write(command.binstub, upgraded)
@@ -93,15 +93,15 @@ CODE
93
93
  end
94
94
 
95
95
  File.write(command.binstub, "#{head}#{shebang}#{LOADER}#{tail}")
96
- status "spring inserted"
96
+ status "Spring inserted"
97
97
  else
98
- status "doesn't appear to be ruby, so cannot use spring", $stderr
98
+ status "doesn't appear to be ruby, so cannot use Spring", $stderr
99
99
  exit 1
100
100
  end
101
101
  end
102
102
  else
103
103
  generate
104
- status "generated with spring"
104
+ status "generated with Spring"
105
105
  end
106
106
  end
107
107
 
@@ -118,7 +118,7 @@ CODE
118
118
  def remove
119
119
  if existing
120
120
  File.write(command.binstub, existing.sub(BINSTUB_VARIATIONS, ""))
121
- status "spring removed"
121
+ status "Spring removed"
122
122
  end
123
123
  end
124
124
  end
@@ -126,7 +126,7 @@ CODE
126
126
  attr_reader :bindir, :items
127
127
 
128
128
  def self.description
129
- "Generate spring based binstubs. Use --all to generate a binstub for all known commands. Use --remove to revert."
129
+ "Generate Spring based binstubs. Use --all to generate a binstub for all known commands. Use --remove to revert."
130
130
  end
131
131
 
132
132
  def self.rails_command
@@ -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("spring itself", spring_commands),
35
+ *command_help("Spring itself", spring_commands),
36
36
  '',
37
37
  *command_help("your application", application_commands)].join("\n")
38
38
  end
@@ -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 spring: #{COMMANDS.to_a.join ', '}."
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
@@ -44,7 +44,7 @@ module Spring
44
44
  require "spring/commands"
45
45
 
46
46
  if Spring.command?(args.first)
47
- # Command installed since spring started
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 spring client " \
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
 
@@ -4,7 +4,7 @@ module Spring
4
4
  module Client
5
5
  class Stop < Command
6
6
  def self.description
7
- "Stop all spring processes for this project."
7
+ "Stop all Spring processes for this project."
8
8
  end
9
9
 
10
10
  def call