spring 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +3 -0
- data/CHANGELOG.md +13 -2
- data/Gemfile +1 -1
- data/README.md +16 -11
- data/lib/spring/application.rb +97 -20
- data/lib/spring/application_manager.rb +16 -9
- data/lib/spring/client.rb +1 -1
- data/lib/spring/client/binstub.rb +1 -1
- data/lib/spring/client/rails.rb +8 -3
- data/lib/spring/client/run.rb +23 -6
- data/lib/spring/client/status.rb +2 -2
- data/lib/spring/commands.rb +3 -0
- data/lib/spring/commands/rails.rb +7 -0
- data/lib/spring/configuration.rb +1 -1
- data/lib/spring/env.rb +8 -2
- data/lib/spring/errors.rb +15 -1
- data/lib/spring/server.rb +27 -14
- data/lib/spring/version.rb +1 -1
- data/lib/spring/watcher.rb +1 -0
- data/lib/spring/watcher/abstract.rb +9 -7
- data/lib/spring/watcher/polling.rb +1 -1
- data/test/acceptance/app_test.rb +168 -86
- data/test/apps/.gitignore +3 -0
- data/test/unit/watcher_test.rb +12 -0
- metadata +4 -134
- data/test/apps/rails-3-2/.gitignore +0 -18
- data/test/apps/rails-3-2/Gemfile +0 -7
- data/test/apps/rails-3-2/README.rdoc +0 -261
- data/test/apps/rails-3-2/Rakefile +0 -7
- data/test/apps/rails-3-2/app/assets/images/rails.png +0 -0
- data/test/apps/rails-3-2/app/assets/javascripts/application.js +0 -15
- data/test/apps/rails-3-2/app/assets/javascripts/posts.js.coffee +0 -3
- data/test/apps/rails-3-2/app/assets/stylesheets/application.css +0 -13
- data/test/apps/rails-3-2/app/assets/stylesheets/posts.css.scss +0 -3
- data/test/apps/rails-3-2/app/assets/stylesheets/scaffolds.css.scss +0 -69
- data/test/apps/rails-3-2/app/controllers/application_controller.rb +0 -3
- data/test/apps/rails-3-2/app/controllers/posts_controller.rb +0 -83
- data/test/apps/rails-3-2/app/helpers/application_helper.rb +0 -2
- data/test/apps/rails-3-2/app/helpers/posts_helper.rb +0 -2
- data/test/apps/rails-3-2/app/mailers/.gitkeep +0 -0
- data/test/apps/rails-3-2/app/models/.gitkeep +0 -0
- data/test/apps/rails-3-2/app/models/post.rb +0 -3
- data/test/apps/rails-3-2/app/views/layouts/application.html.erb +0 -14
- data/test/apps/rails-3-2/app/views/posts/_form.html.erb +0 -21
- data/test/apps/rails-3-2/app/views/posts/edit.html.erb +0 -6
- data/test/apps/rails-3-2/app/views/posts/index.html.erb +0 -23
- data/test/apps/rails-3-2/app/views/posts/new.html.erb +0 -5
- data/test/apps/rails-3-2/app/views/posts/show.html.erb +0 -10
- data/test/apps/rails-3-2/config.ru +0 -4
- data/test/apps/rails-3-2/config/application.rb +0 -62
- data/test/apps/rails-3-2/config/boot.rb +0 -6
- data/test/apps/rails-3-2/config/database.yml +0 -25
- data/test/apps/rails-3-2/config/environment.rb +0 -5
- data/test/apps/rails-3-2/config/environments/development.rb +0 -37
- data/test/apps/rails-3-2/config/environments/production.rb +0 -67
- data/test/apps/rails-3-2/config/environments/test.rb +0 -37
- data/test/apps/rails-3-2/config/initializers/backtrace_silencers.rb +0 -7
- data/test/apps/rails-3-2/config/initializers/inflections.rb +0 -15
- data/test/apps/rails-3-2/config/initializers/mime_types.rb +0 -5
- data/test/apps/rails-3-2/config/initializers/secret_token.rb +0 -7
- data/test/apps/rails-3-2/config/initializers/session_store.rb +0 -8
- data/test/apps/rails-3-2/config/initializers/wrap_parameters.rb +0 -14
- data/test/apps/rails-3-2/config/locales/en.yml +0 -5
- data/test/apps/rails-3-2/config/routes.rb +0 -60
- data/test/apps/rails-3-2/config/spring.rb +0 -7
- data/test/apps/rails-3-2/db/migrate/20121109171227_create_posts.rb +0 -9
- data/test/apps/rails-3-2/db/schema.rb +0 -22
- data/test/apps/rails-3-2/db/seeds.rb +0 -7
- data/test/apps/rails-3-2/lib/assets/.gitkeep +0 -0
- data/test/apps/rails-3-2/lib/tasks/.gitkeep +0 -0
- data/test/apps/rails-3-2/log/.gitkeep +0 -0
- data/test/apps/rails-3-2/public/404.html +0 -26
- data/test/apps/rails-3-2/public/422.html +0 -26
- data/test/apps/rails-3-2/public/500.html +0 -25
- data/test/apps/rails-3-2/public/favicon.ico +0 -0
- data/test/apps/rails-3-2/public/index.html +0 -241
- data/test/apps/rails-3-2/public/robots.txt +0 -5
- data/test/apps/rails-3-2/script/rails +0 -6
- data/test/apps/rails-3-2/spec/dummy_spec.rb +0 -5
- data/test/apps/rails-3-2/test/fixtures/.gitkeep +0 -0
- data/test/apps/rails-3-2/test/fixtures/posts.yml +0 -7
- data/test/apps/rails-3-2/test/functional/.gitkeep +0 -0
- data/test/apps/rails-3-2/test/functional/posts_controller_test.rb +0 -49
- data/test/apps/rails-3-2/test/integration/.gitkeep +0 -0
- data/test/apps/rails-3-2/test/test_helper.rb +0 -13
- data/test/apps/rails-3-2/test/unit/.gitkeep +0 -0
- data/test/apps/rails-3-2/test/unit/helpers/posts_helper_test.rb +0 -4
- data/test/apps/rails-3-2/test/unit/post_test.rb +0 -7
- data/test/apps/rails-3-2/vendor/assets/javascripts/.gitkeep +0 -0
- data/test/apps/rails-3-2/vendor/assets/stylesheets/.gitkeep +0 -0
- data/test/apps/rails-3-2/vendor/plugins/.gitkeep +0 -0
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,20 @@
|
|
1
|
+
## 0.0.11
|
2
|
+
|
3
|
+
* Added the `rails destroy` command.
|
4
|
+
* Global config file in `~/.spring.rb`
|
5
|
+
* Added logging for debugging. Specify a log file with the
|
6
|
+
`SPRING_LOG` environment variable.
|
7
|
+
* Fix hang on "Run `bundle install` to install missing gems"
|
8
|
+
* Added hack to make backtraces generated when running a command
|
9
|
+
quieter (by stripping out all of the lines relating to spring)
|
10
|
+
* Rails 4 is officially supported
|
11
|
+
|
1
12
|
## 0.0.10
|
2
13
|
|
3
|
-
* Added `Spring.
|
14
|
+
* Added `Spring.watch_method=` configuration option to switch between
|
4
15
|
polling and the `listen` gem. Previously, we used the `listen` gem if
|
5
16
|
it was available, but this makes the option explicit. Set
|
6
|
-
`Spring.
|
17
|
+
`Spring.watch_method = :listen` to use the listen gem.
|
7
18
|
* Fallback when Process.fork is not available. In such cases, the user
|
8
19
|
will not receive the speedup that Spring provides, but won't receive
|
9
20
|
an error either.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -7,13 +7,6 @@ problem as [spork](https://github.com/sporkrb/spork),
|
|
7
7
|
[zeus](https://github.com/burke/zeus) and
|
8
8
|
[commands](https://github.com/rails/commands).
|
9
9
|
|
10
|
-
I made it because we are having a discussion on the rails core team
|
11
|
-
about shipping something to solve this problem with rails. So this is my
|
12
|
-
proposal, as working code.
|
13
|
-
|
14
|
-
(At least I hope it's working code, but this is alpha software at the
|
15
|
-
moment. Please do try it and let me know if you hit problems.)
|
16
|
-
|
17
10
|
## Features
|
18
11
|
|
19
12
|
Spring is most similar to Zeus, but it's implemented in pure Ruby, and
|
@@ -48,6 +41,7 @@ Ruby versions supported:
|
|
48
41
|
Rails versions supported:
|
49
42
|
|
50
43
|
* 3.2
|
44
|
+
* 4.0
|
51
45
|
|
52
46
|
Spring makes extensive use of `Process#fork`, so won't be able to run on
|
53
47
|
any platform which doesn't support that (Windows, JRuby).
|
@@ -158,7 +152,7 @@ Note: Don't use spring binstubs with `bundle install --binstubs`. If
|
|
158
152
|
you do this, spring and bundler will overwrite each other. If _you will_
|
159
153
|
not be using a command with spring, use `bundle binstub [GEM]` to
|
160
154
|
generate a bundler binstub for that specific gem. If you _will_ be
|
161
|
-
using a command with spring, generate a spring binstub
|
155
|
+
using a command with spring, generate a spring binstub _instead of_ a
|
162
156
|
bundler binstub; spring will run your command inside the bundle anyway.
|
163
157
|
|
164
158
|
If we edit any of the application files, or test files, the change will
|
@@ -222,7 +216,7 @@ Spring stopped.
|
|
222
216
|
|
223
217
|
The following commands are shipped by default.
|
224
218
|
|
225
|
-
Custom commands can be specified in
|
219
|
+
Custom commands can be specified in the Spring config file. See
|
226
220
|
[`lib/spring/commands.rb`](https://github.com/jonleighton/spring/blob/master/lib/spring/commands.rb)
|
227
221
|
for examples.
|
228
222
|
|
@@ -275,7 +269,7 @@ speed-up).
|
|
275
269
|
|
276
270
|
## Configuration
|
277
271
|
|
278
|
-
Spring will read `config/spring.rb` for custom settings, described below.
|
272
|
+
Spring will read `~/.spring.rb` and `config/spring.rb` for custom settings, described below.
|
279
273
|
|
280
274
|
### Application root
|
281
275
|
|
@@ -291,7 +285,7 @@ Spring.application_root = './test/dummy'
|
|
291
285
|
### Running code before forking
|
292
286
|
|
293
287
|
There is no `Spring.before_fork` callback. To run something before the
|
294
|
-
fork, you can place it in `config/spring.rb` or in any of the files
|
288
|
+
fork, you can place it in `~/.spring.rb` or `config/spring.rb` or in any of the files
|
295
289
|
which get run when your application initializers, such as
|
296
290
|
`config/application.rb`, `config/environments/*.rb` or
|
297
291
|
`config/initializers/*.rb`.
|
@@ -343,3 +337,14 @@ You may need to add the [`listen` gem](https://github.com/guard/listen) to your
|
|
343
337
|
|
344
338
|
Spring needs a tmp directory. This will default to `Rails.root.join('tmp', 'spring')`.
|
345
339
|
You can set your own configuration directory by setting the `SPRING_TMP_PATH` environment variable.
|
340
|
+
|
341
|
+
## Troubleshooting
|
342
|
+
|
343
|
+
If you want to get more information about what spring is doing, you can
|
344
|
+
specify a log file with the `SPRING_LOG` environment variable:
|
345
|
+
|
346
|
+
```
|
347
|
+
spring stop # if spring is already running
|
348
|
+
export SPRING_LOG=/tmp/spring.log
|
349
|
+
spring rake -T
|
350
|
+
```
|
data/lib/spring/application.rb
CHANGED
@@ -1,69 +1,107 @@
|
|
1
1
|
require "set"
|
2
|
-
|
3
|
-
require "spring/configuration"
|
4
2
|
require "spring/watcher"
|
3
|
+
require "thread"
|
5
4
|
|
6
5
|
module Spring
|
7
6
|
class Application
|
8
|
-
attr_reader :manager, :watcher
|
7
|
+
attr_reader :manager, :watcher, :spring_env
|
9
8
|
|
10
9
|
def initialize(manager, watcher = Spring.watcher)
|
11
|
-
@manager
|
12
|
-
@watcher
|
13
|
-
@setup
|
10
|
+
@manager = manager
|
11
|
+
@watcher = watcher
|
12
|
+
@setup = Set.new
|
13
|
+
@spring_env = Env.new
|
14
|
+
@preloaded = false
|
15
|
+
@mutex = Mutex.new
|
16
|
+
@waiting = 0
|
17
|
+
@exiting = false
|
14
18
|
|
15
19
|
# Workaround for GC bug in Ruby 2 which causes segfaults if watcher.to_io
|
16
20
|
# instances get dereffed.
|
17
21
|
@fds = [manager, watcher.to_io]
|
18
22
|
end
|
19
23
|
|
20
|
-
def
|
24
|
+
def log(message)
|
25
|
+
spring_env.log "[application:#{ENV['RAILS_ENV']}] #{message}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def preloaded?
|
29
|
+
@preloaded
|
30
|
+
end
|
31
|
+
|
32
|
+
def exiting?
|
33
|
+
@exiting
|
34
|
+
end
|
35
|
+
|
36
|
+
def preload
|
37
|
+
log "preloading app"
|
38
|
+
|
21
39
|
require Spring.application_root_path.join("config", "application")
|
22
40
|
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
|
41
|
+
# config/environments/test.rb will have config.cache_classes = true. However
|
42
|
+
# we want it to be false so that we can reload files. This is a hack to
|
43
|
+
# override the effect of config.cache_classes = true. We can then actually
|
44
|
+
# set config.cache_classes = false after loading the environment.
|
45
|
+
Rails::Application.initializer :initialize_dependency_mechanism, group: :all do
|
27
46
|
ActiveSupport::Dependencies.mechanism = :load
|
28
47
|
end
|
29
48
|
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
|
49
|
+
# Ensure eager loading does not take place, even though it usually would do
|
50
|
+
# in test mode with config.cache_classes = true. Eager loading in this situation
|
51
|
+
# just makes the initial run take longer without much gain in subsequent runs,
|
52
|
+
# at least in my testing.
|
53
|
+
Rails::Application::Finisher.initializers.delete_if { |i| i.name == :eager_load! }
|
34
54
|
|
35
55
|
require Spring.application_root_path.join("config", "environment")
|
36
56
|
|
37
|
-
|
57
|
+
Rails.application.config.cache_classes = false
|
58
|
+
disconnect_database
|
38
59
|
|
39
60
|
watcher.add loaded_application_features
|
40
61
|
watcher.add Spring.gemfile, "#{Spring.gemfile}.lock"
|
41
62
|
watcher.add Rails.application.paths["config/initializers"]
|
42
63
|
|
43
|
-
|
64
|
+
@preloaded = true
|
44
65
|
end
|
45
66
|
|
46
67
|
def run
|
68
|
+
log "running"
|
47
69
|
watcher.start
|
48
70
|
|
49
71
|
loop do
|
50
72
|
IO.select(@fds)
|
51
73
|
|
52
74
|
if watcher.stale?
|
53
|
-
|
75
|
+
log "watcher stale; exiting"
|
76
|
+
manager.close
|
77
|
+
@exiting = true
|
78
|
+
try_exit
|
79
|
+
sleep
|
54
80
|
else
|
55
81
|
serve manager.recv_io(UNIXSocket)
|
56
82
|
end
|
57
83
|
end
|
58
84
|
end
|
59
85
|
|
86
|
+
def try_exit
|
87
|
+
@mutex.synchronize {
|
88
|
+
exit if exiting? && @waiting == 0
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
60
92
|
def serve(client)
|
93
|
+
log "got client"
|
61
94
|
manager.puts
|
62
95
|
|
63
96
|
streams = 3.times.map { client.recv_io }
|
97
|
+
[STDOUT, STDERR].zip(streams).each { |a, b| a.reopen(b) }
|
98
|
+
|
99
|
+
preload unless preloaded?
|
100
|
+
|
64
101
|
args = JSON.load(client.read(client.gets.to_i))
|
65
102
|
command = Spring.command(args.shift)
|
66
103
|
|
104
|
+
connect_database
|
67
105
|
setup command
|
68
106
|
|
69
107
|
ActionDispatch::Reloader.cleanup!
|
@@ -71,14 +109,15 @@ module Spring
|
|
71
109
|
|
72
110
|
pid = fork {
|
73
111
|
Process.setsid
|
74
|
-
|
112
|
+
STDIN.reopen(streams.last)
|
75
113
|
IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
|
76
114
|
|
77
|
-
|
115
|
+
connect_database
|
78
116
|
ARGV.replace(args)
|
79
117
|
srand
|
80
118
|
|
81
119
|
invoke_after_fork_callbacks
|
120
|
+
shush_backtraces
|
82
121
|
|
83
122
|
if command.respond_to?(:call)
|
84
123
|
command.call
|
@@ -92,17 +131,29 @@ module Spring
|
|
92
131
|
end
|
93
132
|
}
|
94
133
|
|
134
|
+
disconnect_database
|
135
|
+
[STDOUT, STDERR].each { |stream| stream.reopen(spring_env.log_file) }
|
136
|
+
|
137
|
+
log "forked #{pid}"
|
95
138
|
manager.puts pid
|
96
139
|
|
97
140
|
# Wait in a separate thread so we can run multiple commands at once
|
98
141
|
Thread.new {
|
142
|
+
@mutex.synchronize { @waiting += 1 }
|
143
|
+
|
99
144
|
_, status = Process.wait2 pid
|
145
|
+
log "#{pid} exited with #{status.exitstatus}"
|
146
|
+
|
100
147
|
streams.each(&:close)
|
101
148
|
client.puts(status.exitstatus)
|
102
149
|
client.close
|
150
|
+
|
151
|
+
@mutex.synchronize { @waiting -= 1 }
|
152
|
+
try_exit
|
103
153
|
}
|
104
154
|
|
105
155
|
rescue => e
|
156
|
+
log "exception: #{e}"
|
106
157
|
streams.each(&:close) if streams
|
107
158
|
client.puts(1)
|
108
159
|
client.close
|
@@ -131,5 +182,31 @@ module Spring
|
|
131
182
|
def loaded_application_features
|
132
183
|
$LOADED_FEATURES.select { |f| f.start_with?(File.realpath(Rails.root)) }
|
133
184
|
end
|
185
|
+
|
186
|
+
def disconnect_database
|
187
|
+
ActiveRecord::Base.remove_connection if defined?(ActiveRecord::Base)
|
188
|
+
end
|
189
|
+
|
190
|
+
def connect_database
|
191
|
+
ActiveRecord::Base.establish_connection if defined?(ActiveRecord::Base)
|
192
|
+
end
|
193
|
+
|
194
|
+
# This feels very naughty
|
195
|
+
def shush_backtraces
|
196
|
+
Kernel.module_eval do
|
197
|
+
old_raise = Kernel.method(:raise)
|
198
|
+
remove_method :raise
|
199
|
+
define_method :raise do |*args|
|
200
|
+
begin
|
201
|
+
old_raise.call(*args)
|
202
|
+
ensure
|
203
|
+
if $!
|
204
|
+
lib = File.expand_path("..", __FILE__)
|
205
|
+
$!.backtrace.reject! { |line| line.start_with?(lib) }
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
134
211
|
end
|
135
212
|
end
|
@@ -13,6 +13,10 @@ module Spring
|
|
13
13
|
@mutex = Mutex.new
|
14
14
|
end
|
15
15
|
|
16
|
+
def log(message)
|
17
|
+
server.log(message)
|
18
|
+
end
|
19
|
+
|
16
20
|
# We're not using @mutex.synchronize to avoid the weird "<internal:prelude>:10"
|
17
21
|
# line which messes with backtraces in e.g. rspec
|
18
22
|
def synchronize
|
@@ -28,9 +32,6 @@ module Spring
|
|
28
32
|
end
|
29
33
|
|
30
34
|
def restart
|
31
|
-
# Restarting is a background operation. If it fails, we don't want
|
32
|
-
# any terminal output. The user will see the output when they next
|
33
|
-
# try to run a command.
|
34
35
|
start_child(true)
|
35
36
|
end
|
36
37
|
|
@@ -46,10 +47,12 @@ module Spring
|
|
46
47
|
rescue Errno::ECONNRESET, Errno::EPIPE
|
47
48
|
# The child has died but has not been collected by the wait thread yet,
|
48
49
|
# so start a new child and try again.
|
50
|
+
log "child dead; starting"
|
49
51
|
start
|
50
52
|
yield
|
51
53
|
end
|
52
54
|
else
|
55
|
+
log "child not running; starting"
|
53
56
|
start
|
54
57
|
yield
|
55
58
|
end
|
@@ -63,8 +66,12 @@ module Spring
|
|
63
66
|
child.gets
|
64
67
|
end
|
65
68
|
|
66
|
-
child.gets
|
67
|
-
|
69
|
+
pid = child.gets
|
70
|
+
pid = pid.chomp.to_i if pid
|
71
|
+
log "got worker pid #{pid}"
|
72
|
+
pid
|
73
|
+
rescue Errno::ECONNRESET, Errno::EPIPE => e
|
74
|
+
log "#{e} while reading from child; returning no pid"
|
68
75
|
nil
|
69
76
|
ensure
|
70
77
|
client.close
|
@@ -76,13 +83,11 @@ module Spring
|
|
76
83
|
|
77
84
|
private
|
78
85
|
|
79
|
-
def start_child(
|
86
|
+
def start_child(preload = false)
|
80
87
|
server.application_starting
|
81
88
|
|
82
89
|
@child, child_socket = UNIXSocket.pair
|
83
90
|
@pid = fork {
|
84
|
-
[STDOUT, STDERR].each { |s| s.reopen('/dev/null', 'w') } if silence
|
85
|
-
|
86
91
|
(ObjectSpace.each_object(IO).to_a - [STDOUT, STDERR, STDIN, child_socket])
|
87
92
|
.reject(&:closed?)
|
88
93
|
.each(&:close)
|
@@ -93,7 +98,9 @@ module Spring
|
|
93
98
|
"spring app | #{spring_env.app_name} | started #{distance} ago | #{app_env} mode"
|
94
99
|
}
|
95
100
|
|
96
|
-
Application.new(child_socket)
|
101
|
+
app = Application.new(child_socket)
|
102
|
+
app.preload if preload
|
103
|
+
app.run
|
97
104
|
}
|
98
105
|
child_socket.close
|
99
106
|
end
|
data/lib/spring/client.rb
CHANGED
@@ -47,7 +47,7 @@ module Spring
|
|
47
47
|
# https://github.com/rubygems/rubygems/pull/435
|
48
48
|
|
49
49
|
glob = "{#{Gem::Specification.dirs.join(",")}}/spring-*.gemspec"
|
50
|
-
candidates = Dir[glob].to_a.
|
50
|
+
candidates = Dir[glob].to_a.sort_by { |c| Gem::Version.new(File.basename(c).split(/[-\.]/)[1...-1].join(".")) }
|
51
51
|
|
52
52
|
spec = Gem::Specification.load(candidates.last)
|
53
53
|
|
data/lib/spring/client/rails.rb
CHANGED
@@ -3,12 +3,13 @@ require "set"
|
|
3
3
|
module Spring
|
4
4
|
module Client
|
5
5
|
class Rails < Command
|
6
|
-
COMMANDS = Set.new %w(console runner generate)
|
6
|
+
COMMANDS = Set.new %w(console runner generate destroy)
|
7
7
|
|
8
8
|
ALIASES = {
|
9
9
|
"c" => "console",
|
10
10
|
"r" => "runner",
|
11
|
-
"g" => "generate"
|
11
|
+
"g" => "generate",
|
12
|
+
"d" => "destroy"
|
12
13
|
}
|
13
14
|
|
14
15
|
def self.description
|
@@ -21,7 +22,11 @@ module Spring
|
|
21
22
|
if COMMANDS.include?(command_name)
|
22
23
|
Run.call(["rails_#{command_name}", *args.drop(2)])
|
23
24
|
else
|
24
|
-
|
25
|
+
require "spring/configuration"
|
26
|
+
ARGV.shift
|
27
|
+
Object.const_set(:APP_PATH, Spring.application_root_path.join("config/application").to_s)
|
28
|
+
require Spring.application_root_path.join("config/boot")
|
29
|
+
require "rails/commands"
|
25
30
|
end
|
26
31
|
end
|
27
32
|
end
|
data/lib/spring/client/run.rb
CHANGED
@@ -6,13 +6,15 @@ module Spring
|
|
6
6
|
class Run < Command
|
7
7
|
FORWARDED_SIGNALS = %w(INT QUIT USR1 USR2 INFO) & Signal.list.keys
|
8
8
|
|
9
|
+
def log(message)
|
10
|
+
env.log "[client] #{message}"
|
11
|
+
end
|
12
|
+
|
9
13
|
def server
|
10
14
|
@server ||= UNIXSocket.open(env.socket_name)
|
11
15
|
end
|
12
16
|
|
13
17
|
def call
|
14
|
-
Spring.verify_environment!
|
15
|
-
|
16
18
|
boot_server unless env.server_running?
|
17
19
|
verify_server_version
|
18
20
|
|
@@ -28,18 +30,24 @@ module Spring
|
|
28
30
|
|
29
31
|
def boot_server
|
30
32
|
env.socket_path.unlink if env.socket_path.exist?
|
31
|
-
|
33
|
+
|
34
|
+
pid = fork {
|
32
35
|
require "spring/server"
|
33
36
|
Spring::Server.boot
|
34
37
|
}
|
35
|
-
|
38
|
+
|
39
|
+
until env.socket_path.exist?
|
40
|
+
_, status = Process.waitpid2(pid, Process::WNOHANG)
|
41
|
+
exit status.exitstatus if status
|
42
|
+
sleep 0.1
|
43
|
+
end
|
36
44
|
end
|
37
45
|
|
38
46
|
def verify_server_version
|
39
47
|
server_version = server.gets.chomp
|
40
48
|
if server_version != env.version
|
41
49
|
$stderr.puts <<-ERROR
|
42
|
-
There is a version mismatch
|
50
|
+
There is a version mismatch between the spring client and the server.
|
43
51
|
You should restart the server and make sure to use the same version.
|
44
52
|
|
45
53
|
CLIENT: #{env.version}, SERVER: #{server_version}
|
@@ -55,6 +63,8 @@ ERROR
|
|
55
63
|
end
|
56
64
|
|
57
65
|
def run_command(client, application)
|
66
|
+
log "sending command"
|
67
|
+
|
58
68
|
application.send_io STDOUT
|
59
69
|
application.send_io STDERR
|
60
70
|
application.send_io STDIN
|
@@ -70,9 +80,16 @@ ERROR
|
|
70
80
|
client.close
|
71
81
|
|
72
82
|
if pid && !pid.empty?
|
83
|
+
log "got pid: #{pid}"
|
84
|
+
|
73
85
|
forward_signals(pid.to_i)
|
74
|
-
|
86
|
+
status = application.read.to_i
|
87
|
+
|
88
|
+
log "got exit status #{status}"
|
89
|
+
|
90
|
+
exit status
|
75
91
|
else
|
92
|
+
log "got no pid"
|
76
93
|
exit 1
|
77
94
|
end
|
78
95
|
ensure
|