spring 1.6.0 → 1.7.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 +4 -4
- data/LICENSE.txt +2 -2
- data/README.md +46 -5
- data/bin/spring +0 -2
- data/lib/spring/application/boot.rb +2 -1
- data/lib/spring/application.rb +24 -5
- data/lib/spring/application_manager.rb +5 -3
- data/lib/spring/client/binstub.rb +1 -1
- data/lib/spring/client/run.rb +33 -36
- data/lib/spring/client/server.rb +18 -0
- data/lib/spring/client.rb +2 -0
- data/lib/spring/env.rb +15 -8
- data/lib/spring/server.rb +27 -7
- data/lib/spring/test/acceptance_test.rb +37 -12
- data/lib/spring/test/application.rb +2 -2
- data/lib/spring/test/application_generator.rb +5 -1
- data/lib/spring/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf3b9b590f0a6bce1bf2b23dc01cd32884a8d992
|
|
4
|
+
data.tar.gz: 6fd9d0cd5224af34ff7cec5b485140eba506463d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b6c32c4667c1cb86d499332953b78b6933bb5f34d527701e64f52ba00b5155ee89e1d78e552b9c3fec81d827fd5923dfc37ba00910df87f7d9ebca7a698a96e5
|
|
7
|
+
data.tar.gz: 8aa47cb7a911eac35f9eb25db622bddcdc3df93ea1d0f947f160e2e564daff71a2485fa6f3346c66b1c7c813e28ffc2c206c00f248a7ae55cb6a0689e25a1bff
|
data/LICENSE.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c) 2012 Jon Leighton
|
|
1
|
+
Copyright (c) 2012-2016 Jon Leighton
|
|
2
2
|
|
|
3
3
|
MIT License
|
|
4
4
|
|
|
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
|
@@ -16,7 +16,7 @@ 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
|
|
19
|
+
* Ruby versions: MRI 1.9.3, MRI 2.0, MRI 2.1, MRI 2.2
|
|
20
20
|
* Rails versions: 4.0+ (in Rails 4.1 and up Spring is included by default)
|
|
21
21
|
|
|
22
22
|
Spring makes extensive use of `Process.fork`, so won't be able to
|
|
@@ -73,6 +73,7 @@ Let's run a test:
|
|
|
73
73
|
|
|
74
74
|
```
|
|
75
75
|
$ time bin/rake test test/controllers/posts_controller_test.rb
|
|
76
|
+
Running via Spring preloader in process 2734
|
|
76
77
|
Run options:
|
|
77
78
|
|
|
78
79
|
# Running tests:
|
|
@@ -103,6 +104,7 @@ The next run is faster:
|
|
|
103
104
|
|
|
104
105
|
```
|
|
105
106
|
$ time bin/rake test test/controllers/posts_controller_test.rb
|
|
107
|
+
Running via Spring preloader in process 8352
|
|
106
108
|
Run options:
|
|
107
109
|
|
|
108
110
|
# Running tests:
|
|
@@ -147,6 +149,7 @@ environment gets booted up:
|
|
|
147
149
|
|
|
148
150
|
```
|
|
149
151
|
$ bin/rake routes
|
|
152
|
+
Running via Spring preloader in process 2363
|
|
150
153
|
posts GET /posts(.:format) posts#index
|
|
151
154
|
POST /posts(.:format) posts#create
|
|
152
155
|
new_post GET /posts/new(.:format) posts#new
|
|
@@ -353,13 +356,51 @@ installing the
|
|
|
353
356
|
[spring-watcher-listen](https://github.com/jonleighton/spring-watcher-listen)
|
|
354
357
|
gem.
|
|
355
358
|
|
|
359
|
+
### Quiet output
|
|
360
|
+
|
|
361
|
+
To disable the "Running via Spring preloader" message which is shown each time
|
|
362
|
+
a command runs:
|
|
363
|
+
|
|
364
|
+
``` ruby
|
|
365
|
+
Spring.quiet = true
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Environment variables
|
|
369
|
+
|
|
370
|
+
The following environment variables are used by Spring:
|
|
371
|
+
|
|
372
|
+
* `DISABLE_SPRING` - If set, Spring will be bypassed and your
|
|
373
|
+
application will boot in a foreground process
|
|
374
|
+
* `SPRING_LOG` - The path to a file which Spring will write log messages
|
|
375
|
+
to.
|
|
376
|
+
* `SPRING_TMP_PATH` - The directory where Spring should write its temporary
|
|
377
|
+
files (a pidfile and a socket). By default we use the
|
|
378
|
+
`XDG_RUNTIME_DIR` environment variable, or else `Dir.tmpdir`, and then
|
|
379
|
+
create a directory in that named `spring-$UID`. We don't use your
|
|
380
|
+
Rails application's `tmp/` directory because that may be on a
|
|
381
|
+
filesystem which doesn't support UNIX sockets.
|
|
382
|
+
* `SPRING_APPLICATION_ID` - Used to identify distinct Rails
|
|
383
|
+
applications. By default it is an MD5 hash of the current
|
|
384
|
+
`RUBY_VERSION`, and the path to your Rails project root.
|
|
385
|
+
* `SPRING_SOCKET` - The path which should be used for the UNIX socket
|
|
386
|
+
which Spring uses to communicate with the long-running Spring server
|
|
387
|
+
process. By default this is `SPRING_TMP_PATH/SPRING_APPLICATION_ID`.
|
|
388
|
+
* `SPRING_PIDFILE` - The path which should be used to store the pid of
|
|
389
|
+
the long-running Spring server process. By default this is related to
|
|
390
|
+
the socket path; if the socket path is `/foo/bar/spring.sock` the
|
|
391
|
+
pidfile will be `/foo/bar/spring.pid`.
|
|
392
|
+
* `SPRING_SERVER_COMMAND` - The command to run to start up the spring
|
|
393
|
+
server when it is not already running. Defaults to `spring _[version]_
|
|
394
|
+
server --background`.
|
|
395
|
+
|
|
356
396
|
## Troubleshooting
|
|
357
397
|
|
|
358
398
|
If you want to get more information about what spring is doing, you can
|
|
359
|
-
|
|
399
|
+
run spring explicitly in a separate terminal:
|
|
360
400
|
|
|
361
401
|
```
|
|
362
|
-
|
|
363
|
-
export SPRING_LOG=/tmp/spring.log
|
|
364
|
-
spring rake -T
|
|
402
|
+
$ spring server
|
|
365
403
|
```
|
|
404
|
+
|
|
405
|
+
Logging output will be printed to stdout. You can also send log output
|
|
406
|
+
to a file with the `SPRING_LOG` environment variable.
|
data/bin/spring
CHANGED
|
@@ -46,6 +46,4 @@ end
|
|
|
46
46
|
lib = File.expand_path("../../lib", __FILE__)
|
|
47
47
|
$LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib) # enable local development
|
|
48
48
|
require 'spring/client'
|
|
49
|
-
# if the user knows that spring is called, do not show running spring
|
|
50
|
-
Spring.quiet = true if $0.include? 'spring'
|
|
51
49
|
Spring::Client.run(ARGV)
|
|
@@ -5,7 +5,8 @@ require "spring/application"
|
|
|
5
5
|
|
|
6
6
|
app = Spring::Application.new(
|
|
7
7
|
UNIXSocket.for_fd(3),
|
|
8
|
-
Spring::JSON.load(ENV.delete("SPRING_ORIGINAL_ENV").dup)
|
|
8
|
+
Spring::JSON.load(ENV.delete("SPRING_ORIGINAL_ENV").dup),
|
|
9
|
+
Spring::Env.new(log_file: IO.for_fd(4))
|
|
9
10
|
)
|
|
10
11
|
|
|
11
12
|
Signal.trap("TERM") { app.terminate }
|
data/lib/spring/application.rb
CHANGED
|
@@ -6,10 +6,10 @@ module Spring
|
|
|
6
6
|
class Application
|
|
7
7
|
attr_reader :manager, :watcher, :spring_env, :original_env
|
|
8
8
|
|
|
9
|
-
def initialize(manager, original_env)
|
|
9
|
+
def initialize(manager, original_env, spring_env = Env.new)
|
|
10
10
|
@manager = manager
|
|
11
11
|
@original_env = original_env
|
|
12
|
-
@spring_env =
|
|
12
|
+
@spring_env = spring_env
|
|
13
13
|
@mutex = Mutex.new
|
|
14
14
|
@waiting = Set.new
|
|
15
15
|
@preloaded = false
|
|
@@ -99,7 +99,7 @@ module Spring
|
|
|
99
99
|
@preloaded = :success
|
|
100
100
|
rescue Exception => e
|
|
101
101
|
@preloaded = :failure
|
|
102
|
-
watcher.add e.backtrace.map { |line| line
|
|
102
|
+
watcher.add e.backtrace.map { |line| line[/^(.*)\:\d+/, 1] }
|
|
103
103
|
raise e unless initialized?
|
|
104
104
|
ensure
|
|
105
105
|
watcher.add loaded_application_features
|
|
@@ -149,14 +149,22 @@ module Spring
|
|
|
149
149
|
setup command
|
|
150
150
|
|
|
151
151
|
if Rails.application.reloaders.any?(&:updated?)
|
|
152
|
-
|
|
153
|
-
|
|
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
|
|
154
159
|
end
|
|
155
160
|
|
|
156
161
|
pid = fork {
|
|
162
|
+
Process.setsid
|
|
157
163
|
IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
|
|
158
164
|
trap("TERM", "DEFAULT")
|
|
159
165
|
|
|
166
|
+
STDERR.puts "Running via Spring preloader in process #{Process.pid}" unless Spring.quiet
|
|
167
|
+
|
|
160
168
|
ARGV.replace(args)
|
|
161
169
|
$0 = command.exec_name
|
|
162
170
|
|
|
@@ -311,6 +319,17 @@ module Spring
|
|
|
311
319
|
exit_if_finished
|
|
312
320
|
end
|
|
313
321
|
}
|
|
322
|
+
|
|
323
|
+
Thread.new {
|
|
324
|
+
while signal = client.gets.chomp
|
|
325
|
+
begin
|
|
326
|
+
Process.kill(signal, -Process.getpgid(pid))
|
|
327
|
+
client.puts(0)
|
|
328
|
+
rescue Errno::ESRCH
|
|
329
|
+
client.puts(1)
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
}
|
|
314
333
|
end
|
|
315
334
|
|
|
316
335
|
private
|
|
@@ -2,9 +2,9 @@ module Spring
|
|
|
2
2
|
class ApplicationManager
|
|
3
3
|
attr_reader :pid, :child, :app_env, :spring_env, :status
|
|
4
4
|
|
|
5
|
-
def initialize(app_env)
|
|
5
|
+
def initialize(app_env, spring_env)
|
|
6
6
|
@app_env = app_env
|
|
7
|
-
@spring_env =
|
|
7
|
+
@spring_env = spring_env
|
|
8
8
|
@mutex = Mutex.new
|
|
9
9
|
@state = :running
|
|
10
10
|
end
|
|
@@ -101,9 +101,11 @@ module Spring
|
|
|
101
101
|
"SPRING_PRELOAD" => preload ? "1" : "0"
|
|
102
102
|
},
|
|
103
103
|
"ruby",
|
|
104
|
+
"-I", File.expand_path("../..", $LOADED_FEATURES.grep(/bundler\/setup\.rb$/).first),
|
|
104
105
|
"-I", File.expand_path("../..", __FILE__),
|
|
105
106
|
"-e", "require 'spring/application/boot'",
|
|
106
|
-
3 => child_socket
|
|
107
|
+
3 => child_socket,
|
|
108
|
+
4 => spring_env.log_file,
|
|
107
109
|
)
|
|
108
110
|
end
|
|
109
111
|
|
|
@@ -38,7 +38,7 @@ unless defined?(Spring)
|
|
|
38
38
|
require 'bundler'
|
|
39
39
|
|
|
40
40
|
if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m))
|
|
41
|
-
Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq }
|
|
41
|
+
Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) }
|
|
42
42
|
gem 'spring', match[1]
|
|
43
43
|
require 'spring/binstub'
|
|
44
44
|
end
|
data/lib/spring/client/run.rb
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require "spring/commands"
|
|
2
1
|
require "rbconfig"
|
|
3
2
|
require "socket"
|
|
4
3
|
require "bundler"
|
|
@@ -9,6 +8,8 @@ module Spring
|
|
|
9
8
|
FORWARDED_SIGNALS = %w(INT QUIT USR1 USR2 INFO WINCH) & Signal.list.keys
|
|
10
9
|
TIMEOUT = 1
|
|
11
10
|
|
|
11
|
+
attr_reader :server
|
|
12
|
+
|
|
12
13
|
def initialize(args)
|
|
13
14
|
super
|
|
14
15
|
@signal_queue = []
|
|
@@ -18,20 +19,20 @@ module Spring
|
|
|
18
19
|
env.log "[client] #{message}"
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
def
|
|
22
|
-
@server
|
|
22
|
+
def connect
|
|
23
|
+
@server = UNIXSocket.open(env.socket_name)
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
def call
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
begin
|
|
28
|
+
connect
|
|
29
|
+
rescue Errno::ENOENT, Errno::ECONNRESET, Errno::ECONNREFUSED
|
|
29
30
|
cold_run
|
|
31
|
+
else
|
|
32
|
+
warm_run
|
|
30
33
|
end
|
|
31
|
-
rescue Errno::ECONNRESET
|
|
32
|
-
exit 1
|
|
33
34
|
ensure
|
|
34
|
-
server.close if
|
|
35
|
+
server.close if server
|
|
35
36
|
end
|
|
36
37
|
|
|
37
38
|
def warm_run
|
|
@@ -50,6 +51,7 @@ module Spring
|
|
|
50
51
|
|
|
51
52
|
def cold_run
|
|
52
53
|
boot_server
|
|
54
|
+
connect
|
|
53
55
|
run
|
|
54
56
|
end
|
|
55
57
|
|
|
@@ -61,16 +63,13 @@ module Spring
|
|
|
61
63
|
queue_signals
|
|
62
64
|
connect_to_application(client)
|
|
63
65
|
run_command(client, application)
|
|
66
|
+
rescue Errno::ECONNRESET
|
|
67
|
+
exit 1
|
|
64
68
|
end
|
|
65
69
|
|
|
66
70
|
def boot_server
|
|
67
71
|
env.socket_path.unlink if env.socket_path.exist?
|
|
68
|
-
|
|
69
|
-
pid = Process.spawn(
|
|
70
|
-
gem_env,
|
|
71
|
-
"ruby",
|
|
72
|
-
"-e", "gem 'spring', '#{Spring::VERSION}'; require 'spring/server'; Spring::Server.boot"
|
|
73
|
-
)
|
|
72
|
+
pid = Process.spawn(gem_env, env.server_command, out: File::NULL)
|
|
74
73
|
|
|
75
74
|
until env.socket_path.exist?
|
|
76
75
|
_, status = Process.waitpid2(pid, Process::WNOHANG)
|
|
@@ -99,12 +98,12 @@ module Spring
|
|
|
99
98
|
server_version = server.gets.chomp
|
|
100
99
|
if server_version != env.version
|
|
101
100
|
$stderr.puts <<-ERROR
|
|
102
|
-
There is a version mismatch between the spring client and the server.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
CLIENT: #{env.version}, SERVER: #{server_version}
|
|
101
|
+
There is a version mismatch between the spring client (#{env.version}) and the server (#{server_version}).
|
|
102
|
+
Restarting to resolve.
|
|
106
103
|
ERROR
|
|
107
|
-
|
|
104
|
+
|
|
105
|
+
stop_server
|
|
106
|
+
cold_run
|
|
108
107
|
end
|
|
109
108
|
end
|
|
110
109
|
|
|
@@ -139,9 +138,7 @@ ERROR
|
|
|
139
138
|
if pid && !pid.empty?
|
|
140
139
|
log "got pid: #{pid}"
|
|
141
140
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
forward_signals(pid.to_i)
|
|
141
|
+
forward_signals(application)
|
|
145
142
|
status = application.read.to_i
|
|
146
143
|
|
|
147
144
|
log "got exit status #{status}"
|
|
@@ -161,26 +158,26 @@ ERROR
|
|
|
161
158
|
end
|
|
162
159
|
end
|
|
163
160
|
|
|
164
|
-
def forward_signals(
|
|
165
|
-
@signal_queue.each { |sig| kill sig,
|
|
161
|
+
def forward_signals(application)
|
|
162
|
+
@signal_queue.each { |sig| kill sig, application }
|
|
166
163
|
|
|
167
164
|
FORWARDED_SIGNALS.each do |sig|
|
|
168
|
-
trap(sig) { forward_signal sig,
|
|
165
|
+
trap(sig) { forward_signal sig, application }
|
|
169
166
|
end
|
|
170
|
-
rescue Errno::ESRCH
|
|
171
167
|
end
|
|
172
168
|
|
|
173
|
-
def forward_signal(sig,
|
|
174
|
-
kill(sig,
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
169
|
+
def forward_signal(sig, application)
|
|
170
|
+
if kill(sig, application) != 0
|
|
171
|
+
# If the application process is gone, then don't block the
|
|
172
|
+
# signal on this process.
|
|
173
|
+
trap(sig, 'DEFAULT')
|
|
174
|
+
Process.kill(sig, Process.pid)
|
|
175
|
+
end
|
|
180
176
|
end
|
|
181
177
|
|
|
182
|
-
def kill(sig,
|
|
183
|
-
|
|
178
|
+
def kill(sig, application)
|
|
179
|
+
application.puts(sig)
|
|
180
|
+
application.gets.to_i
|
|
184
181
|
end
|
|
185
182
|
|
|
186
183
|
def send_json(socket, data)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Spring
|
|
2
|
+
module Client
|
|
3
|
+
class Server < Command
|
|
4
|
+
def self.description
|
|
5
|
+
"Explicitly start a Spring server in the foreground"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def call
|
|
9
|
+
require "spring/server"
|
|
10
|
+
Spring::Server.boot(foreground: foreground?)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def foreground?
|
|
14
|
+
!args.include?("--background")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/spring/client.rb
CHANGED
|
@@ -9,6 +9,7 @@ require "spring/client/stop"
|
|
|
9
9
|
require "spring/client/status"
|
|
10
10
|
require "spring/client/rails"
|
|
11
11
|
require "spring/client/version"
|
|
12
|
+
require "spring/client/server"
|
|
12
13
|
|
|
13
14
|
module Spring
|
|
14
15
|
module Client
|
|
@@ -22,6 +23,7 @@ module Spring
|
|
|
22
23
|
"rails" => Client::Rails,
|
|
23
24
|
"-v" => Client::Version,
|
|
24
25
|
"--version" => Client::Version,
|
|
26
|
+
"server" => Client::Server,
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
def self.run(args)
|
data/lib/spring/env.rb
CHANGED
|
@@ -14,10 +14,10 @@ module Spring
|
|
|
14
14
|
class Env
|
|
15
15
|
attr_reader :log_file
|
|
16
16
|
|
|
17
|
-
def initialize(
|
|
18
|
-
@root = root
|
|
19
|
-
@project_root = root
|
|
20
|
-
@log_file = File.open(ENV["SPRING_LOG"] || File::NULL, "a")
|
|
17
|
+
def initialize(options = {})
|
|
18
|
+
@root = options[:root]
|
|
19
|
+
@project_root = options[:root]
|
|
20
|
+
@log_file = options[:log_file] || File.open(ENV["SPRING_LOG"] || File::NULL, "a")
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def root
|
|
@@ -33,17 +33,20 @@ module Spring
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def tmp_path
|
|
36
|
-
path = Pathname.new(
|
|
36
|
+
path = Pathname.new(
|
|
37
|
+
ENV["SPRING_TMP_PATH"] ||
|
|
38
|
+
File.join(ENV['XDG_RUNTIME_DIR'] || Dir.tmpdir, "spring-#{Process.uid}")
|
|
39
|
+
)
|
|
37
40
|
FileUtils.mkdir_p(path) unless path.exist?
|
|
38
41
|
path
|
|
39
42
|
end
|
|
40
43
|
|
|
41
44
|
def application_id
|
|
42
|
-
Digest::MD5.hexdigest(RUBY_VERSION + project_root.to_s)
|
|
45
|
+
ENV["SPRING_APPLICATION_ID"] || Digest::MD5.hexdigest(RUBY_VERSION + project_root.to_s)
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
def socket_path
|
|
46
|
-
tmp_path.join(application_id)
|
|
49
|
+
Pathname.new(ENV["SPRING_SOCKET"] || tmp_path.join(application_id))
|
|
47
50
|
end
|
|
48
51
|
|
|
49
52
|
def socket_name
|
|
@@ -51,7 +54,7 @@ module Spring
|
|
|
51
54
|
end
|
|
52
55
|
|
|
53
56
|
def pidfile_path
|
|
54
|
-
|
|
57
|
+
Pathname.new(ENV["SPRING_PIDFILE"] || socket_path.dirname.join("#{socket_path.basename(".*")}.pid"))
|
|
55
58
|
end
|
|
56
59
|
|
|
57
60
|
def pid
|
|
@@ -105,5 +108,9 @@ module Spring
|
|
|
105
108
|
rescue Errno::ESRCH
|
|
106
109
|
# already dead
|
|
107
110
|
end
|
|
111
|
+
|
|
112
|
+
def server_command
|
|
113
|
+
ENV["SPRING_SERVER_COMMAND"] || "spring _#{Spring::VERSION}_ server --background"
|
|
114
|
+
end
|
|
108
115
|
end
|
|
109
116
|
end
|
data/lib/spring/server.rb
CHANGED
|
@@ -10,19 +10,24 @@ require "spring/commands"
|
|
|
10
10
|
|
|
11
11
|
module Spring
|
|
12
12
|
class Server
|
|
13
|
-
def self.boot
|
|
14
|
-
new.boot
|
|
13
|
+
def self.boot(options = {})
|
|
14
|
+
new(options).boot
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
attr_reader :env
|
|
18
18
|
|
|
19
|
-
def initialize(
|
|
20
|
-
@
|
|
21
|
-
@
|
|
19
|
+
def initialize(options = {})
|
|
20
|
+
@foreground = options.fetch(:foreground, false)
|
|
21
|
+
@env = options[:env] || default_env
|
|
22
|
+
@applications = Hash.new { |h, k| h[k] = ApplicationManager.new(k, env) }
|
|
22
23
|
@pidfile = env.pidfile_path.open('a')
|
|
23
24
|
@mutex = Mutex.new
|
|
24
25
|
end
|
|
25
26
|
|
|
27
|
+
def foreground?
|
|
28
|
+
@foreground
|
|
29
|
+
end
|
|
30
|
+
|
|
26
31
|
def log(message)
|
|
27
32
|
env.log "[server] #{message}"
|
|
28
33
|
end
|
|
@@ -31,8 +36,8 @@ module Spring
|
|
|
31
36
|
Spring.verify_environment
|
|
32
37
|
|
|
33
38
|
write_pidfile
|
|
34
|
-
set_pgid
|
|
35
|
-
ignore_signals
|
|
39
|
+
set_pgid unless foreground?
|
|
40
|
+
ignore_signals unless foreground?
|
|
36
41
|
set_exit_hook
|
|
37
42
|
set_process_title
|
|
38
43
|
start_server
|
|
@@ -42,6 +47,7 @@ module Spring
|
|
|
42
47
|
server = UNIXServer.open(env.socket_name)
|
|
43
48
|
log "started on #{env.socket_name}"
|
|
44
49
|
loop { serve server.accept }
|
|
50
|
+
rescue Interrupt
|
|
45
51
|
end
|
|
46
52
|
|
|
47
53
|
def serve(client)
|
|
@@ -126,5 +132,19 @@ module Spring
|
|
|
126
132
|
"spring server | #{env.app_name} | started #{distance} ago"
|
|
127
133
|
}
|
|
128
134
|
end
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
def default_env
|
|
139
|
+
Env.new(log_file: default_log_file)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def default_log_file
|
|
143
|
+
if foreground? && !ENV["SPRING_LOG"]
|
|
144
|
+
$stdout
|
|
145
|
+
else
|
|
146
|
+
nil
|
|
147
|
+
end
|
|
148
|
+
end
|
|
129
149
|
end
|
|
130
150
|
end
|
|
@@ -28,6 +28,10 @@ module Spring
|
|
|
28
28
|
@app ||= Spring::Test::Application.new("#{Spring::Test.root}/apps/tmp")
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
def spring_env
|
|
32
|
+
app.spring_env
|
|
33
|
+
end
|
|
34
|
+
|
|
31
35
|
def assert_output(artifacts, expected)
|
|
32
36
|
expected.each do |stream, output|
|
|
33
37
|
assert artifacts[stream].include?(output),
|
|
@@ -92,30 +96,25 @@ module Spring
|
|
|
92
96
|
|
|
93
97
|
test "help message when called without arguments" do
|
|
94
98
|
assert_success "bin/spring", stdout: 'Usage: spring COMMAND [ARGS]'
|
|
95
|
-
assert
|
|
99
|
+
assert spring_env.server_running?
|
|
96
100
|
end
|
|
97
101
|
|
|
98
102
|
test "shows help" do
|
|
99
103
|
assert_success "bin/spring help", stdout: 'Usage: spring COMMAND [ARGS]'
|
|
100
104
|
assert_success "bin/spring -h", stdout: 'Usage: spring COMMAND [ARGS]'
|
|
101
105
|
assert_success "bin/spring --help", stdout: 'Usage: spring COMMAND [ARGS]'
|
|
102
|
-
refute
|
|
106
|
+
refute spring_env.server_running?
|
|
103
107
|
end
|
|
104
108
|
|
|
105
109
|
test "tells the user that spring is being used when used automatically via binstubs" do
|
|
106
|
-
assert_success "bin/rails runner ''",
|
|
107
|
-
assert_success app.spring_test_command,
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
test "does not tell the user that spring is being used when the user used spring manually" do
|
|
111
|
-
refute_output_includes "spring rails runner ''", stdout: "Running via Spring preloader in process"
|
|
112
|
-
refute_output_includes "spring rake test", stdout: "Running via Spring preloader in process"
|
|
110
|
+
assert_success "bin/rails runner ''", stderr: "Running via Spring preloader in process"
|
|
111
|
+
assert_success app.spring_test_command, stderr: "Running via Spring preloader in process"
|
|
113
112
|
end
|
|
114
113
|
|
|
115
114
|
test "does not tell the user that spring is being used when used automatically via binstubs but quiet is enabled" do
|
|
116
115
|
File.write("#{app.user_home}/.spring.rb", "Spring.quiet = true")
|
|
117
116
|
assert_success "bin/rails runner ''"
|
|
118
|
-
refute_output_includes "bin/rails runner ''",
|
|
117
|
+
refute_output_includes "bin/rails runner ''", stderr: 'Running via Spring preloader in process'
|
|
119
118
|
end
|
|
120
119
|
|
|
121
120
|
test "test changes are picked up" do
|
|
@@ -189,10 +188,10 @@ module Spring
|
|
|
189
188
|
|
|
190
189
|
test "stop command kills server" do
|
|
191
190
|
app.run app.spring_test_command
|
|
192
|
-
assert
|
|
191
|
+
assert spring_env.server_running?, "The server should be running but it isn't"
|
|
193
192
|
|
|
194
193
|
assert_success "bin/spring stop"
|
|
195
|
-
assert !
|
|
194
|
+
assert !spring_env.server_running?, "The server should not be running but it is"
|
|
196
195
|
end
|
|
197
196
|
|
|
198
197
|
test "custom commands" do
|
|
@@ -500,6 +499,32 @@ module Spring
|
|
|
500
499
|
expr = "p Kernel.private_instance_methods.include?(:raise)"
|
|
501
500
|
assert_success %(bin/rails runner '#{expr}'), stdout: "true"
|
|
502
501
|
end
|
|
502
|
+
|
|
503
|
+
test "custom bundle path" do
|
|
504
|
+
bundle_path = app.path(".bundle/#{Bundler.ruby_scope}")
|
|
505
|
+
bundle_path.dirname.mkpath
|
|
506
|
+
|
|
507
|
+
FileUtils.cp_r "#{app.gem_home}/", bundle_path.to_s
|
|
508
|
+
|
|
509
|
+
app.run! "bundle install --path .bundle --clean --local"
|
|
510
|
+
|
|
511
|
+
assert_speedup do
|
|
512
|
+
2.times { assert_success "bundle exec rails runner ''" }
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
test "booting a foreground server" do
|
|
517
|
+
FileUtils.cd(app.root) do
|
|
518
|
+
assert !spring_env.server_running?
|
|
519
|
+
app.run "spring server &"
|
|
520
|
+
|
|
521
|
+
Timeout.timeout(1) do
|
|
522
|
+
sleep 0.1 until spring_env.server_running?
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
assert_success app.spring_test_command
|
|
526
|
+
end
|
|
527
|
+
end
|
|
503
528
|
end
|
|
504
529
|
end
|
|
505
530
|
end
|
|
@@ -9,7 +9,7 @@ module Spring
|
|
|
9
9
|
|
|
10
10
|
def initialize(root)
|
|
11
11
|
@root = Pathname.new(root)
|
|
12
|
-
@spring_env = Spring::Env.new(root)
|
|
12
|
+
@spring_env = Spring::Env.new(root: root)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def exists?
|
|
@@ -117,7 +117,7 @@ module Spring
|
|
|
117
117
|
|
|
118
118
|
output.merge(status: status, command: command)
|
|
119
119
|
rescue Timeout::Error => e
|
|
120
|
-
raise
|
|
120
|
+
raise Timeout::Error, "While running command:\n\n#{dump_streams(command, read_streams)}"
|
|
121
121
|
end
|
|
122
122
|
|
|
123
123
|
def with_timing
|
|
@@ -58,6 +58,10 @@ module Spring
|
|
|
58
58
|
append_to_file(application.gemfile, "gem 'spring-commands-testunit'")
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
if RUBY_VERSION == "1.9.3"
|
|
62
|
+
append_to_file(application.gemfile, "gem 'mime-types', '~> 2'")
|
|
63
|
+
end
|
|
64
|
+
|
|
61
65
|
rewrite_file(application.gemfile) do |c|
|
|
62
66
|
c.sub!("https://rubygems.org", "http://rubygems.org")
|
|
63
67
|
c.gsub!(/(gem '(byebug|web-console|sdoc|jbuilder)')/, "# \\1")
|
|
@@ -112,7 +116,7 @@ module Spring
|
|
|
112
116
|
system("gem build #{name}.gemspec 2>&1")
|
|
113
117
|
end
|
|
114
118
|
|
|
115
|
-
application.run! "gem install #{spec.gem_dir}/#{name}-*.gem", timeout: nil
|
|
119
|
+
application.run! "gem install #{spec.gem_dir}/#{name}-*.gem --no-ri --no-rdoc", timeout: nil
|
|
116
120
|
end
|
|
117
121
|
end
|
|
118
122
|
|
data/lib/spring/version.rb
CHANGED
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: 1.
|
|
4
|
+
version: 1.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jon Leighton
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2016-04-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -75,6 +75,7 @@ files:
|
|
|
75
75
|
- lib/spring/client/help.rb
|
|
76
76
|
- lib/spring/client/rails.rb
|
|
77
77
|
- lib/spring/client/run.rb
|
|
78
|
+
- lib/spring/client/server.rb
|
|
78
79
|
- lib/spring/client/status.rb
|
|
79
80
|
- lib/spring/client/stop.rb
|
|
80
81
|
- lib/spring/client/version.rb
|
|
@@ -119,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
119
120
|
version: '0'
|
|
120
121
|
requirements: []
|
|
121
122
|
rubyforge_project:
|
|
122
|
-
rubygems_version: 2.
|
|
123
|
+
rubygems_version: 2.5.1
|
|
123
124
|
signing_key:
|
|
124
125
|
specification_version: 4
|
|
125
126
|
summary: Rails application preloader
|