spring 2.0.2 → 4.0.0

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: 42ad763baaed56f6c7dd36b05566eec2e008481b
4
- data.tar.gz: 6f228d8ea63046f99353e83e732a72ef1900b0fd
2
+ SHA256:
3
+ metadata.gz: 9f13e2a4d08faffc1b15c2f1dfe801a3b0b6a12b80d7a66a39601e74ccf3feff
4
+ data.tar.gz: 60c63476055ff6050668abfc79489f7c6fbbfc9a7b3a11ea998cb5b2ab86ef9a
5
5
  SHA512:
6
- metadata.gz: b049078c55028bbba601d2ca065fff5e3904cfd27b4ab6b719b7488e1bd044247cb88716126d46e5f26abb6296818d606b717ae4c0ad4c9c04726ff43e22c50e
7
- data.tar.gz: 12560b678ff15621efb6b479a443048330088f40ad328b920525785d59aa64064895565f96db5bb14801ce6c516106f3296ec8966a83b55142e915fa0df7bf74
6
+ metadata.gz: 9c467ea15cea498f05ec7e5211bb014163e37a75557d9694e03cc4d6d6e94d4b62c6edcede752e61c4ff51accf472939150c7fc01901aab94cd60d4d06c8a8b1
7
+ data.tar.gz: 6d363498591c949b3a49885c38d8694db924d9a2b24c2cc8499236d67739f4cb863eff5db114385bba8cb02bf996af48acd892cbf5e2edebe495bf3bdfffca93
data/LICENSE.txt CHANGED
@@ -1,3 +1,4 @@
1
+ Copyright (c) 2017-2021 Rafael Mendonça França
1
2
  Copyright (c) 2012-2017 Jon Leighton
2
3
 
3
4
  MIT License
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,9 +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
21
- `rails new` to generate your application)
19
+ * Ruby versions: MRI 2.7, MRI 3.0, MRI 3.1
20
+ * Rails versions: 6.0, 6.1, 7.0
22
21
 
23
22
  Spring makes extensive use of `Process.fork`, so won't be able to
24
23
  provide a speed up on platforms which don't support forking (Windows, JRuby).
@@ -27,14 +26,14 @@ provide a speed up on platforms which don't support forking (Windows, JRuby).
27
26
 
28
27
  ### Setup
29
28
 
30
- Add spring to your Gemfile:
29
+ Add Spring to your Gemfile:
31
30
 
32
31
  ``` ruby
33
32
  gem "spring", group: :development
34
33
  ```
35
34
 
36
35
  (Note: using `gem "spring", git: "..."` *won't* work and is not a
37
- supported way of using spring.)
36
+ supported way of using Spring.)
38
37
 
39
38
  It's recommended to 'springify' the executables in your `bin/`
40
39
  directory:
@@ -50,21 +49,32 @@ code into relevant existing executables. The snippet looks like this:
50
49
  ``` ruby
51
50
  begin
52
51
  load File.expand_path('../spring', __FILE__)
53
- rescue LoadError
52
+ rescue LoadError => e
53
+ raise unless e.message.include?('spring')
54
54
  end
55
55
  ```
56
56
 
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
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
60
60
  normal.
61
61
 
62
62
  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
63
+ can [use direnv](https://github.com/direnv/direnv#the-stdlib) to
64
64
  automatically add `./bin` to your `PATH` when you `cd` into your application.
65
65
  Simply create an `.envrc` file with the command `PATH_add bin` in your
66
66
  Rails directory.
67
67
 
68
+ ### Enable reloading
69
+
70
+ Spring reloads application code, and therefore needs the application to have
71
+ reloading enabled.
72
+
73
+ Please, make sure `config.cache_classes` is `false` in the environments that
74
+ Spring manages. That setting is typically configured in
75
+ `config/environments/*.rb`. In particular, make sure it is `false` for the
76
+ `test` environment.
77
+
68
78
  ### Usage
69
79
 
70
80
  For this walkthrough I've generated a new Rails application, and run
@@ -90,7 +100,7 @@ user 0m0.281s
90
100
  sys 0m0.066s
91
101
  ```
92
102
 
93
- That wasn't particularly fast because it was the first run, so spring
103
+ That wasn't particularly fast because it was the first run, so Spring
94
104
  had to boot the application. It's now running:
95
105
 
96
106
  ```
@@ -167,8 +177,8 @@ Spring is running:
167
177
  26707 spring app | spring-demo-app | started 2 secs ago | development mode
168
178
  ```
169
179
 
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
180
+ There's no need to "shut down" Spring. This will happen automatically
181
+ when you close your terminal. However, if you do want to do a manual shut
172
182
  down, use the `stop` command:
173
183
 
174
184
  ```
@@ -176,9 +186,11 @@ $ bin/spring stop
176
186
  Spring stopped.
177
187
  ```
178
188
 
189
+ From within your code, you can check whether Spring is active with `if defined?(Spring)`.
190
+
179
191
  ### Removal
180
192
 
181
- To remove spring:
193
+ To remove Spring:
182
194
 
183
195
  * 'Unspring' your bin/ executables: `bin/spring binstub --remove --all`
184
196
  * Remove spring from your Gemfile
@@ -186,12 +198,13 @@ To remove spring:
186
198
  ### Deployment
187
199
 
188
200
  You must not install Spring on your production environment. To prevent it from
189
- being installed, provide the `--without development test` argument to the
201
+ being installed, run the `bundle config set without 'development test'` before
190
202
  `bundle install` command which is used to install gems on your production
191
203
  machines:
192
204
 
193
205
  ```
194
- $ bundle install --without development test
206
+ $ bundle config set without 'development test'
207
+ $ bundle install
195
208
  ```
196
209
 
197
210
  ## Commands
@@ -216,7 +229,7 @@ Spring::Commands::Rake.environment_matchers[:default] = "development"
216
229
  ### `rails console`, `rails generate`, `rails runner`
217
230
 
218
231
  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
232
+ a different sub command (e.g. `rails server`) then Spring will automatically
220
233
  pass it through to the underlying `rails` executable (without the
221
234
  speed-up).
222
235
 
@@ -230,18 +243,22 @@ You can add these to your Gemfile for additional commands:
230
243
  * [spring-commands-testunit](https://github.com/jonleighton/spring-commands-testunit) - useful for
231
244
  running `Test::Unit` tests on Rails 3, since only Rails 4 allows you
232
245
  to use `rake test path/to/test` to run a particular test/directory.
246
+ * [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
247
  * [spring-commands-teaspoon](https://github.com/alejandrobabio/spring-commands-teaspoon.git)
234
248
  * [spring-commands-m](https://github.com/gabrieljoelc/spring-commands-m.git)
235
249
  * [spring-commands-rubocop](https://github.com/p0deje/spring-commands-rubocop)
250
+ * [spring-commands-rackup](https://github.com/wintersolutions/spring-commands-rackup)
251
+ * [spring-commands-rack-console](https://github.com/wintersolutions/spring-commands-rack-console)
252
+ * [spring-commands-standard](https://github.com/lakim/spring-commands-standard)
236
253
 
237
254
  ## Use without adding to bundle
238
255
 
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
256
+ If you don't want Spring-related code checked into your source
257
+ repository, it's possible to use Spring without adding to your Gemfile.
258
+ However, using Spring binstubs without adding Spring to the Gemfile is not
242
259
  supported.
243
260
 
244
- To use spring like this, do a `gem install spring` and then prefix
261
+ To use Spring like this, do a `gem install spring` and then prefix
245
262
  commands with `spring`. For example, rather than running `bin/rake -T`,
246
263
  you'd run `spring rake -T`.
247
264
 
@@ -252,12 +269,10 @@ run through Spring, set the `DISABLE_SPRING` environment variable.
252
269
 
253
270
  ## Class reloading
254
271
 
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.
272
+ Spring uses Rails' class reloading mechanism to keep your code up to date
273
+ between test runs. This is the same mechanism which allows you to see changes
274
+ during development when you refresh the page. However, you may never have used
275
+ this mechanism with your `test` environment before, and this can cause problems.
261
276
 
262
277
  It's important to realise that code reloading means that the constants
263
278
  in your application are *different objects* after files have changed:
@@ -357,7 +372,7 @@ application restart, you can specify them with `Spring.watch`:
357
372
  Spring.watch "config/some_config_file.yml"
358
373
  ```
359
374
 
360
- By default Spring polls the filesystem for changes once every 0.2 seconds. This
375
+ By default, Spring polls the filesystem for changes once every 0.2 seconds. This
361
376
  method requires zero configuration, but if you find that it's using too
362
377
  much CPU, then you can use event-based file system listening by
363
378
  installing the
@@ -377,34 +392,34 @@ Spring.quiet = true
377
392
 
378
393
  The following environment variables are used by Spring:
379
394
 
380
- * `DISABLE_SPRING` - If set, Spring will be bypassed and your
395
+ * `DISABLE_SPRING` - If set, Spring will be bypassed, and your
381
396
  application will boot in a foreground process
382
397
  * `SPRING_LOG` - The path to a file which Spring will write log messages
383
398
  to.
384
399
  * `SPRING_TMP_PATH` - The directory where Spring should write its temporary
385
- files (a pidfile and a socket). By default we use the
400
+ files (a pidfile and a socket). By default, we use the
386
401
  `XDG_RUNTIME_DIR` environment variable, or else `Dir.tmpdir`, and then
387
402
  create a directory in that named `spring-$UID`. We don't use your
388
403
  Rails application's `tmp/` directory because that may be on a
389
404
  filesystem which doesn't support UNIX sockets.
390
405
  * `SPRING_APPLICATION_ID` - Used to identify distinct Rails
391
- applications. By default it is an MD5 hash of the current
406
+ applications. By default, it is an MD5 hash of the current
392
407
  `RUBY_VERSION`, and the path to your Rails project root.
393
408
  * `SPRING_SOCKET` - The path which should be used for the UNIX socket
394
409
  which Spring uses to communicate with the long-running Spring server
395
- process. By default this is `SPRING_TMP_PATH/SPRING_APPLICATION_ID`.
410
+ process. By default, this is `SPRING_TMP_PATH/SPRING_APPLICATION_ID`.
396
411
  * `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
412
+ the long-running Spring server process. By default, this is related to
398
413
  the socket path; if the socket path is `/foo/bar/spring.sock` the
399
414
  pidfile will be `/foo/bar/spring.pid`.
400
- * `SPRING_SERVER_COMMAND` - The command to run to start up the spring
415
+ * `SPRING_SERVER_COMMAND` - The command to run to start up the Spring
401
416
  server when it is not already running. Defaults to `spring _[version]_
402
417
  server --background`.
403
418
 
404
419
  ## Troubleshooting
405
420
 
406
- If you want to get more information about what spring is doing, you can
407
- run spring explicitly in a separate terminal:
421
+ If you want to get more information about what Spring is doing, you can
422
+ run Spring explicitly in a separate terminal:
408
423
 
409
424
  ```
410
425
  $ spring server
@@ -11,7 +11,8 @@ module Spring
11
11
  @original_env = original_env
12
12
  @spring_env = spring_env
13
13
  @mutex = Mutex.new
14
- @waiting = Set.new
14
+ @waiting = {}
15
+ @clients = {}
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
- # config/environments/test.rb will have config.cache_classes = true. However
95
- # we want it to be false so that we can reload files. This is a hack to
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('6.0.0')
96
+ raise "Spring only supports Rails >= 6.0.0"
100
97
  end
101
98
 
102
- 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
103
107
 
104
- @original_cache_classes = Rails.application.config.cache_classes
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, "#{Spring.gemfile}.lock"
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
- stdout, stderr, stdin = streams = 3.times.map { client.recv_io }
153
+ @clients[client] = true
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
- 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
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
- # Rails 5.1 forward-compat. AD::R is deprecated to AS::R in Rails 5.
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.each_key { |c| c.close if c != client }
185
+
172
186
  Process.setsid
173
187
  IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
174
188
  trap("TERM", "DEFAULT")
175
189
 
176
- 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
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 spring started
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 spring started
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
 
@@ -229,7 +245,7 @@ module Spring
229
245
  if exiting?
230
246
  # Ensure that we do not ignore subsequent termination attempts
231
247
  log "forced exit"
232
- @waiting.each { |pid| Process.kill("TERM", pid) }
248
+ @waiting.each_key { |pid| Process.kill("TERM", pid) }
233
249
  Kernel.exit
234
250
  else
235
251
  state! :terminating
@@ -288,7 +304,7 @@ module Spring
288
304
  ensure
289
305
  if $!
290
306
  lib = File.expand_path("..", __FILE__)
291
- $!.backtrace.reject! { |line| line.start_with?(lib) }
307
+ $!.backtrace.reject! { |line| line.start_with?(lib) } unless $!.backtrace.frozen?
292
308
  end
293
309
  end
294
310
  end
@@ -321,7 +337,7 @@ module Spring
321
337
  end
322
338
 
323
339
  def wait(pid, streams, client)
324
- @mutex.synchronize { @waiting << pid }
340
+ @mutex.synchronize { @waiting[pid] = true }
325
341
 
326
342
  # Wait in a separate thread so we can run multiple commands at once
327
343
  Spring.failsafe_thread {
@@ -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_unbundled_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,54 +3,48 @@ 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.
14
- LOADER = <<CODE
15
- begin
16
- load File.expand_path('../spring', __FILE__)
17
- rescue LoadError => e
18
- raise unless e.message.include?('spring')
19
- end
20
- CODE
14
+ LOADER = <<~CODE
15
+ load File.expand_path("spring", __dir__)
16
+ CODE
21
17
 
22
18
  # The defined? check ensures these lines don't execute when we load the
23
19
  # binstub from the application process. Which means that in the application
24
20
  # process we'll execute the lines which come after the LOADER block, which
25
21
  # is what we want.
26
- SPRING = <<'CODE'
27
- #!/usr/bin/env ruby
28
-
29
- # This file loads spring without using Bundler, in order to be fast.
30
- # It gets overwritten when you run the `spring binstub` command.
31
-
32
- unless defined?(Spring)
33
- require 'rubygems'
34
- require 'bundler'
35
-
36
- lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read)
37
- spring = lockfile.specs.detect { |spec| spec.name == "spring" }
38
- if spring
39
- Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
40
- gem 'spring', spring.version
41
- require 'spring/binstub'
42
- end
43
- end
44
- CODE
22
+ SPRING = <<~CODE
23
+ #!/usr/bin/env ruby
24
+
25
+ # This file loads Spring without using loading other gems in the Gemfile, in order to be fast.
26
+ # It gets overwritten when you run the `spring binstub` command.
27
+
28
+ if !defined?(Spring) && [nil, "development", "test"].include?(ENV["RAILS_ENV"])
29
+ require "bundler"
30
+
31
+ Bundler.locked_gems.specs.find { |spec| spec.name == "spring" }&.tap do |spring|
32
+ Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
33
+ gem "spring", spring.version
34
+ require "spring/binstub"
35
+ end
36
+ end
37
+ CODE
45
38
 
46
39
  OLD_BINSTUB = %{if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?}
47
40
 
48
41
  BINSTUB_VARIATIONS = Regexp.union [
49
- %{begin\n load File.expand_path("../spring", __FILE__)\nrescue LoadError\nend\n},
42
+ %{load File.expand_path("spring", __dir__)\n},
43
+ %{begin\n load File.expand_path('../spring', __FILE__)\nrescue LoadError => e\n raise unless e.message.include?('spring')\nend\n},
50
44
  %{begin\n load File.expand_path('../spring', __FILE__)\nrescue LoadError\nend\n},
51
45
  %{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
46
  LOADER
53
- ]
47
+ ].map { |binstub| /#{Regexp.escape(binstub).gsub("'", "['\"]")}/ }
54
48
 
55
49
  class Item
56
50
  attr_reader :command, :existing
@@ -79,7 +73,7 @@ CODE
79
73
  generate(fallback)
80
74
  status "upgraded"
81
75
  elsif existing.include?(LOADER)
82
- status "spring already present"
76
+ status "Spring already present"
83
77
  elsif existing =~ BINSTUB_VARIATIONS
84
78
  upgraded = existing.sub(BINSTUB_VARIATIONS, LOADER)
85
79
  File.write(command.binstub, upgraded)
@@ -94,15 +88,15 @@ CODE
94
88
  end
95
89
 
96
90
  File.write(command.binstub, "#{head}#{shebang}#{LOADER}#{tail}")
97
- status "spring inserted"
91
+ status "Spring inserted"
98
92
  else
99
- status "doesn't appear to be ruby, so cannot use spring", $stderr
93
+ status "doesn't appear to be ruby, so cannot use Spring", $stderr
100
94
  exit 1
101
95
  end
102
96
  end
103
97
  else
104
98
  generate
105
- status "generated with spring"
99
+ status "generated with Spring"
106
100
  end
107
101
  end
108
102
 
@@ -119,7 +113,7 @@ CODE
119
113
  def remove
120
114
  if existing
121
115
  File.write(command.binstub, existing.sub(BINSTUB_VARIATIONS, ""))
122
- status "spring removed"
116
+ status "Spring removed"
123
117
  end
124
118
  end
125
119
  end
@@ -127,7 +121,7 @@ CODE
127
121
  attr_reader :bindir, :items
128
122
 
129
123
  def self.description
130
- "Generate spring based binstubs. Use --all to generate a binstub for all known commands. Use --remove to revert."
124
+ "Generate Spring based binstubs. Use --all to generate a binstub for all known commands. Use --remove to revert."
131
125
  end
132
126
 
133
127
  def self.rails_command
@@ -147,7 +141,7 @@ CODE
147
141
  @mode = :add
148
142
  @items = args.drop(1)
149
143
  .map { |name| find_commands name }
150
- .inject(Set.new, :|)
144
+ .flatten.uniq
151
145
  .map { |command| Item.new(command) }
152
146
  end
153
147
 
@@ -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
@@ -3,7 +3,7 @@ require "set"
3
3
  module Spring
4
4
  module Client
5
5
  class Rails < Command
6
- COMMANDS = Set.new %w(console runner generate destroy test)
6
+ COMMANDS = %w(console runner generate destroy test)
7
7
 
8
8
  ALIASES = {
9
9
  "c" => "console",
@@ -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