spring 2.1.1 → 4.1.2

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
2
  SHA256:
3
- metadata.gz: 90758ca717a756e672dfeaaf8295f17fcfa38f3ea3bc8bd27093a4354d45b82f
4
- data.tar.gz: 82533f3a3e3f5dc53c3f89d3b2734557bfefcf06b5cbe714238dba64160d56a3
3
+ metadata.gz: 1fb5e5ae37f6bcecf6171f7b6118522938b6e6a7d8fcf68f8484d73c7d4e33a0
4
+ data.tar.gz: 62a6410c2df8ca87c41d612d6470e9bf93dbbbab37ac1c717807173771fcb02c
5
5
  SHA512:
6
- metadata.gz: 80d8a7138fa74ad857a43671e54234da3a9b6265727f170c21905694397ebe5ec9b1102dbce3098835157e49e808cbbc52d74e1894a228ab0b25e521987cc4ca
7
- data.tar.gz: 4366760559dfa2bae19ce7478302b35ca050cd431e39241427dfb5666de3a4eb704039ccdc4b02634556041aba71cebe22a053f4553e63db9d7ecdfbb980bf66
6
+ metadata.gz: 738706552c86e5dc6689f333b0d06598ca28e2018eea91e02c32c519b30be46ec96fe688223cc436734d8cc4a4ae77cb3816d05951e7d0724a4c2de169c64b27
7
+ data.tar.gz: be3196dadc9ea13b0748f5fa17e66084a1c9a7c19a36cf2b588d643585d5493dde016605b45b3fade7e1e7de58cfe95122b0db1801bfe013b8f0964ea654e860
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,9 @@ boot it every time you run a test, rake task or migration.
16
16
 
17
17
  ## Compatibility
18
18
 
19
- * Ruby versions: MRI 2.4, MRI 2.5, MRI 2.6
20
- * Rails versions: 4.2, 5.0, 5.1, 5.2, 6.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, MRI 3.2
20
+ * Rails versions: 6.0, 6.1, 7.0
21
+ * Bundler v2.1+
22
22
 
23
23
  Spring makes extensive use of `Process.fork`, so won't be able to
24
24
  provide a speed up on platforms which don't support forking (Windows, JRuby).
@@ -50,13 +50,14 @@ 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
58
  On platforms where Spring is installed and supported, this snippet
58
59
  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
+ 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
@@ -65,6 +66,19 @@ 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
+ Ensure that `config.enable_reloading` is `true` in the environments that
75
+ Spring manages. That setting is typically configured in
76
+ `config/environments/*.rb`. In particular, make sure it is `true` for the
77
+ `test` environment.
78
+
79
+ Note: in versions of Rails before 7.1, the setting is called `cache_classes`,
80
+ and it needs to be `false` for Spring to work.
81
+
68
82
  ### Usage
69
83
 
70
84
  For this walkthrough I've generated a new Rails application, and run
@@ -168,7 +182,7 @@ Spring is running:
168
182
  ```
169
183
 
170
184
  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
185
+ when you close your terminal. However, if you do want to do a manual shut
172
186
  down, use the `stop` command:
173
187
 
174
188
  ```
@@ -188,12 +202,13 @@ To remove Spring:
188
202
  ### Deployment
189
203
 
190
204
  You must not install Spring on your production environment. To prevent it from
191
- being installed, provide the `--without development test` argument to the
205
+ being installed, run the `bundle config set without 'development test'` before
192
206
  `bundle install` command which is used to install gems on your production
193
207
  machines:
194
208
 
195
209
  ```
196
- $ bundle install --without development test
210
+ $ bundle config set without 'development test'
211
+ $ bundle install
197
212
  ```
198
213
 
199
214
  ## Commands
@@ -238,6 +253,7 @@ You can add these to your Gemfile for additional commands:
238
253
  * [spring-commands-rubocop](https://github.com/p0deje/spring-commands-rubocop)
239
254
  * [spring-commands-rackup](https://github.com/wintersolutions/spring-commands-rackup)
240
255
  * [spring-commands-rack-console](https://github.com/wintersolutions/spring-commands-rack-console)
256
+ * [spring-commands-standard](https://github.com/lakim/spring-commands-standard)
241
257
 
242
258
  ## Use without adding to bundle
243
259
 
@@ -257,12 +273,10 @@ run through Spring, set the `DISABLE_SPRING` environment variable.
257
273
 
258
274
  ## Class reloading
259
275
 
260
- Spring uses Rails' class reloading mechanism
261
- (`ActiveSupport::Dependencies`) to keep your code up to date between
262
- test runs. This is the same mechanism which allows you to see changes
263
- during development when you refresh the page. However, you may never
264
- have used this mechanism with your `test` environment before, and this
265
- can cause problems.
276
+ Spring uses Rails' class reloading mechanism to keep your code up to date
277
+ between test runs. This is the same mechanism which allows you to see changes
278
+ during development when you refresh the page. However, you may never have used
279
+ this mechanism with your `test` environment before, and this can cause problems.
266
280
 
267
281
  It's important to realise that code reloading means that the constants
268
282
  in your application are *different objects* after files have changed:
@@ -362,7 +376,7 @@ application restart, you can specify them with `Spring.watch`:
362
376
  Spring.watch "config/some_config_file.yml"
363
377
  ```
364
378
 
365
- By default Spring polls the filesystem for changes once every 0.2 seconds. This
379
+ By default, Spring polls the filesystem for changes once every 0.2 seconds. This
366
380
  method requires zero configuration, but if you find that it's using too
367
381
  much CPU, then you can use event-based file system listening by
368
382
  installing the
@@ -378,30 +392,38 @@ a command runs:
378
392
  Spring.quiet = true
379
393
  ```
380
394
 
395
+ You can also set the initial state of the `quiet` configuration option to true
396
+ by setting the `SPRING_QUIET` environment variable before executing Spring.
397
+ This is useful if you want to set quiet mode when invoking the Spring executable
398
+ in a subprocess, and cannot or prefer not to set it programmatically
399
+ via the `Spring.quiet` option in `~/.spring.rb` or the app's `config/spring.rb`.
400
+
381
401
  ### Environment variables
382
402
 
383
403
  The following environment variables are used by Spring:
384
404
 
385
- * `DISABLE_SPRING` - If set, Spring will be bypassed and your
405
+ * `DISABLE_SPRING` - If set, Spring will be bypassed, and your
386
406
  application will boot in a foreground process
387
407
  * `SPRING_LOG` - The path to a file which Spring will write log messages
388
408
  to.
389
409
  * `SPRING_TMP_PATH` - The directory where Spring should write its temporary
390
- files (a pidfile and a socket). By default we use the
410
+ files (a pidfile and a socket). By default, we use the
391
411
  `XDG_RUNTIME_DIR` environment variable, or else `Dir.tmpdir`, and then
392
412
  create a directory in that named `spring-$UID`. We don't use your
393
413
  Rails application's `tmp/` directory because that may be on a
394
414
  filesystem which doesn't support UNIX sockets.
395
415
  * `SPRING_APPLICATION_ID` - Used to identify distinct Rails
396
- applications. By default it is an MD5 hash of the current
416
+ applications. By default, it is an MD5 hash of the current
397
417
  `RUBY_VERSION`, and the path to your Rails project root.
398
418
  * `SPRING_SOCKET` - The path which should be used for the UNIX socket
399
419
  which Spring uses to communicate with the long-running Spring server
400
- process. By default this is `SPRING_TMP_PATH/SPRING_APPLICATION_ID`.
420
+ process. By default, this is `SPRING_TMP_PATH/SPRING_APPLICATION_ID`.
401
421
  * `SPRING_PIDFILE` - The path which should be used to store the pid of
402
- the long-running Spring server process. By default this is related to
422
+ the long-running Spring server process. By default, this is related to
403
423
  the socket path; if the socket path is `/foo/bar/spring.sock` the
404
424
  pidfile will be `/foo/bar/spring.pid`.
425
+ * `SPRING_QUIET` - If set, the initial state of the `Spring.quiet`
426
+ configuration option will default to `true`.
405
427
  * `SPRING_SERVER_COMMAND` - The command to run to start up the Spring
406
428
  server when it is not already running. Defaults to `spring _[version]_
407
429
  server --background`.
@@ -1,5 +1,4 @@
1
1
  require "spring/boot"
2
- require "set"
3
2
  require "pty"
4
3
 
5
4
  module Spring
@@ -11,7 +10,8 @@ module Spring
11
10
  @original_env = original_env
12
11
  @spring_env = spring_env
13
12
  @mutex = Mutex.new
14
- @waiting = Set.new
13
+ @waiting = {}
14
+ @clients = {}
15
15
  @preloaded = false
16
16
  @state = :initialized
17
17
  @interrupt = IO.pipe
@@ -91,23 +91,21 @@ module Spring
91
91
 
92
92
  require Spring.application_root_path.join("config", "application")
93
93
 
94
- unless Rails.respond_to?(:gem_version) && Rails.gem_version >= Gem::Version.new('4.2.0')
95
- raise "Spring only supports Rails >= 4.2.0"
94
+ unless Rails.respond_to?(:gem_version) && Rails.gem_version >= Gem::Version.new('6.0.0')
95
+ raise "Spring only supports Rails >= 6.0.0"
96
96
  end
97
97
 
98
- # config/environments/test.rb will have config.cache_classes = true. However
99
- # we want it to be false so that we can reload files. This is a hack to
100
- # override the effect of config.cache_classes = true. We can then actually
101
- # set config.cache_classes = false after loading the environment.
102
- Rails::Application.initializer :initialize_dependency_mechanism, group: :all do
103
- ActiveSupport::Dependencies.mechanism = :load
98
+ Rails::Application.initializer :ensure_reloading_is_enabled, group: :all do
99
+ if Rails.application.config.cache_classes
100
+ raise <<-MSG.strip_heredoc
101
+ Spring reloads, and therefore needs the application to have reloading enabled.
102
+ Please, set config.cache_classes to false in config/environments/#{Rails.env}.rb.
103
+ MSG
104
+ end
104
105
  end
105
106
 
106
107
  require Spring.application_root_path.join("config", "environment")
107
108
 
108
- @original_cache_classes = Rails.application.config.cache_classes
109
- Rails.application.config.cache_classes = false
110
-
111
109
  disconnect_database
112
110
 
113
111
  @preloaded = :success
@@ -117,7 +115,7 @@ module Spring
117
115
  raise e unless initialized?
118
116
  ensure
119
117
  watcher.add loaded_application_features
120
- watcher.add Spring.gemfile, "#{Spring.gemfile}.lock"
118
+ watcher.add Spring.gemfile, Spring.gemfile_lock
121
119
 
122
120
  if defined?(Rails) && Rails.application
123
121
  watcher.add Rails.application.paths["config/initializers"]
@@ -129,7 +127,12 @@ module Spring
129
127
  end
130
128
 
131
129
  def eager_preload
132
- with_pty { preload }
130
+ with_pty do
131
+ # we can't see stderr and there could be issues when it's overflown
132
+ # see https://github.com/rails/spring/issues/396
133
+ STDERR.reopen("/dev/null")
134
+ preload
135
+ end
133
136
  end
134
137
 
135
138
  def run
@@ -151,10 +154,23 @@ module Spring
151
154
  log "got client"
152
155
  manager.puts
153
156
 
157
+ @clients[client] = true
158
+
154
159
  _stdout, stderr, _stdin = streams = 3.times.map { client.recv_io }
155
160
  [STDOUT, STDERR, STDIN].zip(streams).each { |a, b| a.reopen(b) }
156
161
 
157
- preload unless preloaded?
162
+ if preloaded?
163
+ client.puts(0) # preload success
164
+ else
165
+ begin
166
+ preload
167
+ client.puts(0) # preload success
168
+ rescue Exception
169
+ log "preload failed"
170
+ client.puts(1) # preload failure
171
+ raise
172
+ end
173
+ end
158
174
 
159
175
  args, env = JSON.load(client.read(client.gets.to_i)).values_at("args", "env")
160
176
  command = Spring.command(args.shift)
@@ -163,21 +179,14 @@ module Spring
163
179
  setup command
164
180
 
165
181
  if Rails.application.reloaders.any?(&:updated?)
166
- # Rails 5.1 forward-compat. AD::R is deprecated to AS::R in Rails 5.
167
- if defined? ActiveSupport::Reloader
168
- Rails.application.reloader.reload!
169
- else
170
- ActionDispatch::Reloader.cleanup!
171
- ActionDispatch::Reloader.prepare!
172
- end
182
+ Rails.application.reloader.reload!
173
183
  end
174
184
 
175
- # Ensure we boot the process in the directory the command was called from,
176
- # not from the directory Spring started in
177
- original_dir = Dir.pwd
178
- Dir.chdir(env['PWD'] || original_dir)
179
-
180
185
  pid = fork {
186
+ # Make sure to close other clients otherwise their graceful termination
187
+ # will be impossible due to reference from this fork.
188
+ @clients.each_key { |c| c.close if c != client }
189
+
181
190
  Process.setsid
182
191
  IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
183
192
  trap("TERM", "DEFAULT")
@@ -203,14 +212,6 @@ module Spring
203
212
  # Load in the current env vars, except those which *were* changed when Spring started
204
213
  env.each { |k, v| ENV[k] ||= v }
205
214
 
206
- # requiring is faster, so if config.cache_classes was true in
207
- # the environment's config file, then we can respect that from
208
- # here on as we no longer need constant reloading.
209
- if @original_cache_classes
210
- ActiveSupport::Dependencies.mechanism = :require
211
- Rails.application.config.cache_classes = true
212
- end
213
-
214
215
  connect_database
215
216
  srand
216
217
 
@@ -242,14 +243,13 @@ module Spring
242
243
  # (i.e. to prevent `spring rake -T | grep db` from hanging forever),
243
244
  # even when exception is raised before forking (i.e. preloading).
244
245
  reset_streams
245
- Dir.chdir(original_dir)
246
246
  end
247
247
 
248
248
  def terminate
249
249
  if exiting?
250
250
  # Ensure that we do not ignore subsequent termination attempts
251
251
  log "forced exit"
252
- @waiting.each { |pid| Process.kill("TERM", pid) }
252
+ @waiting.each_key { |pid| Process.kill("TERM", pid) }
253
253
  Kernel.exit
254
254
  else
255
255
  state! :terminating
@@ -302,13 +302,26 @@ module Spring
302
302
  Kernel.module_eval do
303
303
  old_raise = Kernel.method(:raise)
304
304
  remove_method :raise
305
- define_method :raise do |*args|
306
- begin
307
- old_raise.call(*args)
308
- ensure
309
- if $!
310
- lib = File.expand_path("..", __FILE__)
311
- $!.backtrace.reject! { |line| line.start_with?(lib) }
305
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.2.0')
306
+ define_method :raise do |*args, **kwargs|
307
+ begin
308
+ old_raise.call(*args, **kwargs)
309
+ ensure
310
+ if $!
311
+ lib = File.expand_path("..", __FILE__)
312
+ $!.backtrace.reject! { |line| line.start_with?(lib) } unless $!.backtrace.frozen?
313
+ end
314
+ end
315
+ end
316
+ else
317
+ define_method :raise do |*args|
318
+ begin
319
+ old_raise.call(*args)
320
+ ensure
321
+ if $!
322
+ lib = File.expand_path("..", __FILE__)
323
+ $!.backtrace.reject! { |line| line.start_with?(lib) } unless $!.backtrace.frozen?
324
+ end
312
325
  end
313
326
  end
314
327
  end
@@ -341,7 +354,7 @@ module Spring
341
354
  end
342
355
 
343
356
  def wait(pid, streams, client)
344
- @mutex.synchronize { @waiting << pid }
357
+ @mutex.synchronize { @waiting[pid] = true }
345
358
 
346
359
  # Wait in a separate thread so we can run multiple commands at once
347
360
  Spring.failsafe_thread {
@@ -1,5 +1,3 @@
1
- require 'set'
2
-
3
1
  module Spring
4
2
  module Client
5
3
  class Binstub < Command
@@ -11,41 +9,36 @@ module Spring
11
9
  # client is not invoked for whatever reason, then the Kernel.exit won't
12
10
  # happen, and so we'll fall back to the lines after this block, which
13
11
  # 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
12
+ LOADER = <<~CODE
13
+ load File.expand_path("spring", __dir__)
14
+ CODE
21
15
 
22
16
  # The defined? check ensures these lines don't execute when we load the
23
17
  # binstub from the application process. Which means that in the application
24
18
  # process we'll execute the lines which come after the LOADER block, which
25
19
  # 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
20
+ SPRING = <<~CODE
21
+ #!/usr/bin/env ruby
22
+
23
+ # This file loads Spring without loading other gems in the Gemfile in order to be fast.
24
+ # It gets overwritten when you run the `spring binstub` command.
25
+
26
+ if !defined?(Spring) && [nil, "development", "test"].include?(ENV["RAILS_ENV"])
27
+ require "bundler"
28
+
29
+ Bundler.locked_gems.specs.find { |spec| spec.name == "spring" }&.tap do |spring|
30
+ Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
31
+ gem "spring", spring.version
32
+ require "spring/binstub"
33
+ end
34
+ end
35
+ CODE
45
36
 
46
37
  OLD_BINSTUB = %{if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?}
47
38
 
48
39
  BINSTUB_VARIATIONS = Regexp.union [
40
+ %{load File.expand_path("spring", __dir__)\n},
41
+ %{begin\n load File.expand_path('../spring', __FILE__)\nrescue LoadError => e\n raise unless e.message.include?('spring')\nend\n},
49
42
  %{begin\n load File.expand_path('../spring', __FILE__)\nrescue LoadError\nend\n},
50
43
  %{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
44
  LOADER
@@ -146,7 +139,7 @@ CODE
146
139
  @mode = :add
147
140
  @items = args.drop(1)
148
141
  .map { |name| find_commands name }
149
- .inject(Set.new, :|)
142
+ .flatten.uniq
150
143
  .map { |command| Item.new(command) }
151
144
  end
152
145
 
@@ -1,9 +1,7 @@
1
- require "set"
2
-
3
1
  module Spring
4
2
  module Client
5
3
  class Rails < Command
6
- COMMANDS = Set.new %w(console runner generate destroy test)
4
+ COMMANDS = %w(console runner generate destroy test)
7
5
 
8
6
  ALIASES = {
9
7
  "c" => "console",
@@ -22,6 +20,8 @@ module Spring
22
20
 
23
21
  if COMMANDS.include?(command_name)
24
22
  Run.call(["rails_#{command_name}", *args.drop(2)])
23
+ elsif command_name&.start_with?("db:") && !command_name.start_with?("db:system")
24
+ Run.call(["rake", *args.drop(1)])
25
25
  else
26
26
  require "spring/configuration"
27
27
  ARGV.shift
@@ -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
@@ -28,9 +28,16 @@ module Spring
28
28
  config = File.expand_path("~/.spring.rb")
29
29
  require config if File.exist?(config)
30
30
 
31
- # If the config/spring.rb contains requires for commands from other gems,
32
- # then we need to be under bundler.
33
- require "bundler/setup"
31
+ # We force the TTY so bundler doesn't show a backtrace in case gems are missing.
32
+ old_env = ENV["BUNDLER_FORCE_TTY"]
33
+ ENV["BUNDLER_FORCE_TTY"] = "true"
34
+ begin
35
+ # If the config/spring.rb contains requires for commands from other gems,
36
+ # then we need to be under bundler.
37
+ require "bundler/setup"
38
+ ensure
39
+ ENV["BUNDLER_FORCE_TTY"] = old_env
40
+ end
34
41
 
35
42
  # Auto-require any Spring extensions which are in the Gemfile
36
43
  Gem::Specification.map(&:name).grep(/^spring-/).each do |command|
@@ -2,16 +2,28 @@ require "spring/errors"
2
2
 
3
3
  module Spring
4
4
  class << self
5
- attr_accessor :application_root, :quiet
5
+ attr_accessor :application_root
6
+ attr_writer :quiet
6
7
 
7
8
  def gemfile
9
+ require "bundler"
10
+
8
11
  if /\s1.9.[0-9]/ === Bundler.ruby_scope.gsub(/[\/\s]+/,'')
9
- ENV["BUNDLE_GEMFILE"] || "Gemfile"
12
+ Pathname.new(ENV["BUNDLE_GEMFILE"] || "Gemfile").expand_path
10
13
  else
11
14
  Bundler.default_gemfile
12
15
  end
13
16
  end
14
17
 
18
+ def gemfile_lock
19
+ case gemfile.to_s
20
+ when /\bgems\.rb\z/
21
+ gemfile.sub_ext('.locked')
22
+ else
23
+ gemfile.sub_ext('.lock')
24
+ end
25
+ end
26
+
15
27
  def after_fork_callbacks
16
28
  @after_fork_callbacks ||= []
17
29
  end
@@ -41,6 +53,10 @@ module Spring
41
53
  @project_root_path ||= find_project_root(Pathname.new(File.expand_path(Dir.pwd)))
42
54
  end
43
55
 
56
+ def quiet
57
+ @quiet || ENV.key?('SPRING_QUIET')
58
+ end
59
+
44
60
  private
45
61
 
46
62
  def find_project_root(current_dir)
data/lib/spring/env.rb CHANGED
@@ -1,10 +1,6 @@
1
1
  require "pathname"
2
- require "fileutils"
3
- require "digest/md5"
4
- require "tmpdir"
5
2
 
6
3
  require "spring/version"
7
- require "spring/sid"
8
4
  require "spring/configuration"
9
5
 
10
6
  module Spring
@@ -33,15 +29,18 @@ module Spring
33
29
  end
34
30
 
35
31
  def tmp_path
32
+ require "tmpdir"
36
33
  path = Pathname.new(
37
34
  ENV["SPRING_TMP_PATH"] ||
38
35
  File.join(ENV['XDG_RUNTIME_DIR'] || Dir.tmpdir, "spring-#{Process.uid}")
39
36
  )
37
+ require "fileutils"
40
38
  FileUtils.mkdir_p(path) unless path.exist?
41
39
  path
42
40
  end
43
41
 
44
42
  def application_id
43
+ require "digest/md5"
45
44
  ENV["SPRING_APPLICATION_ID"] || Digest::MD5.hexdigest(RUBY_VERSION + project_root.to_s)
46
45
  end
47
46
 
data/lib/spring/json.rb CHANGED
@@ -46,11 +46,9 @@ end
46
46
 
47
47
  # See https://github.com/kr/okjson for updates.
48
48
 
49
- require 'stringio'
50
-
51
49
  # Some parts adapted from
52
- # http://golang.org/src/pkg/json/decode.go and
53
- # http://golang.org/src/pkg/utf8/utf8.go
50
+ # https://golang.org/src/pkg/json/decode.go and
51
+ # https://golang.org/src/pkg/utf8/utf8.go
54
52
  module Spring
55
53
  module OkJson
56
54
  Upstream = '43'
@@ -468,19 +466,18 @@ private
468
466
 
469
467
 
470
468
  def strenc(s)
471
- t = StringIO.new
472
- t.putc(?")
469
+ t = '"'.b
473
470
  r = 0
474
471
 
475
472
  while r < s.length
476
473
  case s[r]
477
- when ?" then t.print('\\"')
478
- when ?\\ then t.print('\\\\')
479
- when ?\b then t.print('\\b')
480
- when ?\f then t.print('\\f')
481
- when ?\n then t.print('\\n')
482
- when ?\r then t.print('\\r')
483
- when ?\t then t.print('\\t')
474
+ when ?" then t << '\\"'
475
+ when ?\\ then t << '\\\\'
476
+ when ?\b then t << '\\b'
477
+ when ?\f then t << '\\f'
478
+ when ?\n then t << '\\n'
479
+ when ?\r then t << '\\r'
480
+ when ?\t then t << '\\t'
484
481
  else
485
482
  c = s[r]
486
483
  # In ruby >= 1.9, s[r] is a codepoint, not a byte.
@@ -490,14 +487,14 @@ private
490
487
  if c.ord < Spc.ord
491
488
  c = "\\u%04x" % [c.ord]
492
489
  end
493
- t.write(c)
490
+ t << c
494
491
  rescue
495
- t.write(Ustrerr)
492
+ t << Ustrerr
496
493
  end
497
494
  elsif c < Spc
498
- t.write("\\u%04x" % c)
495
+ t << "\\u%04x" % c
499
496
  elsif Spc <= c && c <= ?~
500
- t.putc(c)
497
+ t << c
501
498
  else
502
499
  n = ucharcopy(t, s, r) # ensure valid UTF-8 output
503
500
  r += n - 1 # r is incremented below
@@ -505,8 +502,8 @@ private
505
502
  end
506
503
  r += 1
507
504
  end
508
- t.putc(?")
509
- t.string
505
+ t << '"'
506
+ t
510
507
  end
511
508
 
512
509
 
@@ -531,7 +528,7 @@ private
531
528
 
532
529
  # 1-byte, 7-bit sequence?
533
530
  if c0 < Utagx
534
- t.putc(c0)
531
+ t << c0
535
532
  return 1
536
533
  end
537
534
 
@@ -544,8 +541,8 @@ private
544
541
  # 2-byte, 11-bit sequence?
545
542
  if c0 < Utag3
546
543
  raise Utf8Error if ((c0&Umask2)<<6 | (c1&Umaskx)) <= Uchar1max
547
- t.putc(c0)
548
- t.putc(c1)
544
+ t << c0
545
+ t << c1
549
546
  return 2
550
547
  end
551
548
 
@@ -559,9 +556,9 @@ private
559
556
  if c0 < Utag4
560
557
  u = (c0&Umask3)<<12 | (c1&Umaskx)<<6 | (c2&Umaskx)
561
558
  raise Utf8Error if u <= Uchar2max
562
- t.putc(c0)
563
- t.putc(c1)
564
- t.putc(c2)
559
+ t << c0
560
+ t << c1
561
+ t << c2
565
562
  return 3
566
563
  end
567
564
 
@@ -574,16 +571,16 @@ private
574
571
  if c0 < Utag5
575
572
  u = (c0&Umask4)<<18 | (c1&Umaskx)<<12 | (c2&Umaskx)<<6 | (c3&Umaskx)
576
573
  raise Utf8Error if u <= Uchar3max
577
- t.putc(c0)
578
- t.putc(c1)
579
- t.putc(c2)
580
- t.putc(c3)
574
+ t << c0
575
+ t << c1
576
+ t << c2
577
+ t << c3
581
578
  return 4
582
579
  end
583
580
 
584
581
  raise Utf8Error
585
582
  rescue Utf8Error
586
- t.write(Ustrerr)
583
+ t << Ustrerr
587
584
  return 1
588
585
  end
589
586
 
data/lib/spring/server.rb CHANGED
@@ -81,7 +81,8 @@ module Spring
81
81
  # This will cause it to be automatically killed once the session
82
82
  # ends (i.e. when the user closes their terminal).
83
83
  def set_pgid
84
- Process.setpgid(0, SID.pgid)
84
+ pgid = Process.getpgid(Process.getsid)
85
+ Process.setpgid(0, pgid)
85
86
  end
86
87
 
87
88
  # Ignore SIGINT and SIGQUIT otherwise the user typing ^C or ^\ on the command line
@@ -1,3 +1,3 @@
1
1
  module Spring
2
- VERSION = "2.1.1"
2
+ VERSION = "4.1.2"
3
3
  end
@@ -1,6 +1,4 @@
1
- require "set"
2
1
  require "pathname"
3
- require "mutex_m"
4
2
 
5
3
  module Spring
6
4
  module Watcher
@@ -10,17 +8,14 @@ module Spring
10
8
  # IO.select([watcher]) # watcher is running in background
11
9
  # watcher.stale? # => true
12
10
  class Abstract
13
- include Mutex_m
14
-
15
11
  attr_reader :files, :directories, :root, :latency
16
12
 
17
13
  def initialize(root, latency)
18
- super()
19
-
14
+ @mutex = Mutex.new
20
15
  @root = File.realpath(root)
21
16
  @latency = latency
22
- @files = Set.new
23
- @directories = Set.new
17
+ @files = {}
18
+ @directories = {}
24
19
  @stale = false
25
20
  @listeners = []
26
21
 
@@ -60,13 +55,13 @@ module Spring
60
55
  end
61
56
  end
62
57
 
63
- synchronize {
58
+ @mutex.synchronize do
64
59
  items.each do |item|
65
60
  if item.directory?
66
- directories << item.realpath.to_s
61
+ directories[item.realpath.to_s] = true
67
62
  else
68
63
  begin
69
- files << item.realpath.to_s
64
+ files[item.realpath.to_s] = true
70
65
  rescue Errno::ENOENT
71
66
  # Race condition. Ignore symlinks whose target was removed
72
67
  # since the check above, or are deeply chained.
@@ -76,7 +71,7 @@ module Spring
76
71
  end
77
72
 
78
73
  subjects_changed
79
- }
74
+ end
80
75
  end
81
76
 
82
77
  def stale?
@@ -12,7 +12,7 @@ module Spring
12
12
  end
13
13
 
14
14
  def check_stale
15
- synchronize do
15
+ @mutex.synchronize do
16
16
  computed = compute_mtime
17
17
  if mtime < computed
18
18
  debug { "check_stale: mtime=#{mtime.inspect} < computed=#{computed.inspect}" }
@@ -91,7 +91,7 @@ module Spring
91
91
  end
92
92
 
93
93
  def expanded_files
94
- files + Dir["{#{directories.map { |d| "#{d}/**/*" }.join(",")}}"]
94
+ (files.keys + Dir["{#{directories.keys.map { |d| "#{d}/**/*" }.join(",")}}"]).uniq
95
95
  end
96
96
  end
97
97
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spring
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 4.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Leighton
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-25 00:00:00.000000000 Z
11
+ date: 2023-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -90,7 +90,6 @@ files:
90
90
  - lib/spring/json.rb
91
91
  - lib/spring/process_title_updater.rb
92
92
  - lib/spring/server.rb
93
- - lib/spring/sid.rb
94
93
  - lib/spring/version.rb
95
94
  - lib/spring/watcher.rb
96
95
  - lib/spring/watcher/abstract.rb
@@ -98,8 +97,9 @@ files:
98
97
  homepage: https://github.com/rails/spring
99
98
  licenses:
100
99
  - MIT
101
- metadata: {}
102
- post_install_message:
100
+ metadata:
101
+ rubygems_mfa_required: 'true'
102
+ post_install_message:
103
103
  rdoc_options: []
104
104
  require_paths:
105
105
  - lib
@@ -107,15 +107,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: 2.4.0
110
+ version: 2.7.0
111
111
  required_rubygems_version: !ruby/object:Gem::Requirement
112
112
  requirements:
113
113
  - - ">="
114
114
  - !ruby/object:Gem::Version
115
115
  version: '0'
116
116
  requirements: []
117
- rubygems_version: 3.0.3
118
- signing_key:
117
+ rubygems_version: 3.3.7
118
+ signing_key:
119
119
  specification_version: 4
120
120
  summary: Rails application preloader
121
121
  test_files: []
data/lib/spring/sid.rb DELETED
@@ -1,42 +0,0 @@
1
- begin
2
- # If rubygems is present, keep it out of the way when loading fiddle,
3
- # otherwise if fiddle is not installed then rubygems will load all
4
- # gemspecs in its (futile) search for fiddle, which is slow.
5
- if respond_to?(:gem_original_require, true)
6
- gem_original_require 'fiddle'
7
- else
8
- require 'fiddle'
9
- end
10
- rescue LoadError
11
- end
12
-
13
- module Spring
14
- module SID
15
- def self.fiddle_func
16
- @fiddle_func ||= Fiddle::Function.new(
17
- DL::Handle::DEFAULT['getsid'],
18
- [Fiddle::TYPE_INT],
19
- Fiddle::TYPE_INT
20
- )
21
- end
22
-
23
- def self.sid
24
- @sid ||= begin
25
- if Process.respond_to?(:getsid)
26
- # Ruby 2
27
- Process.getsid
28
- elsif defined?(Fiddle) and defined?(DL)
29
- # Ruby 1.9.3 compiled with libffi support
30
- fiddle_func.call(0)
31
- else
32
- # last resort: shell out
33
- `ps -p #{Process.pid} -o sess=`.to_i
34
- end
35
- end
36
- end
37
-
38
- def self.pgid
39
- Process.getpgid(sid)
40
- end
41
- end
42
- end