spring 0.0.10 → 0.0.11

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.
Files changed (91) hide show
  1. data/.travis.yml +3 -0
  2. data/CHANGELOG.md +13 -2
  3. data/Gemfile +1 -1
  4. data/README.md +16 -11
  5. data/lib/spring/application.rb +97 -20
  6. data/lib/spring/application_manager.rb +16 -9
  7. data/lib/spring/client.rb +1 -1
  8. data/lib/spring/client/binstub.rb +1 -1
  9. data/lib/spring/client/rails.rb +8 -3
  10. data/lib/spring/client/run.rb +23 -6
  11. data/lib/spring/client/status.rb +2 -2
  12. data/lib/spring/commands.rb +3 -0
  13. data/lib/spring/commands/rails.rb +7 -0
  14. data/lib/spring/configuration.rb +1 -1
  15. data/lib/spring/env.rb +8 -2
  16. data/lib/spring/errors.rb +15 -1
  17. data/lib/spring/server.rb +27 -14
  18. data/lib/spring/version.rb +1 -1
  19. data/lib/spring/watcher.rb +1 -0
  20. data/lib/spring/watcher/abstract.rb +9 -7
  21. data/lib/spring/watcher/polling.rb +1 -1
  22. data/test/acceptance/app_test.rb +168 -86
  23. data/test/apps/.gitignore +3 -0
  24. data/test/unit/watcher_test.rb +12 -0
  25. metadata +4 -134
  26. data/test/apps/rails-3-2/.gitignore +0 -18
  27. data/test/apps/rails-3-2/Gemfile +0 -7
  28. data/test/apps/rails-3-2/README.rdoc +0 -261
  29. data/test/apps/rails-3-2/Rakefile +0 -7
  30. data/test/apps/rails-3-2/app/assets/images/rails.png +0 -0
  31. data/test/apps/rails-3-2/app/assets/javascripts/application.js +0 -15
  32. data/test/apps/rails-3-2/app/assets/javascripts/posts.js.coffee +0 -3
  33. data/test/apps/rails-3-2/app/assets/stylesheets/application.css +0 -13
  34. data/test/apps/rails-3-2/app/assets/stylesheets/posts.css.scss +0 -3
  35. data/test/apps/rails-3-2/app/assets/stylesheets/scaffolds.css.scss +0 -69
  36. data/test/apps/rails-3-2/app/controllers/application_controller.rb +0 -3
  37. data/test/apps/rails-3-2/app/controllers/posts_controller.rb +0 -83
  38. data/test/apps/rails-3-2/app/helpers/application_helper.rb +0 -2
  39. data/test/apps/rails-3-2/app/helpers/posts_helper.rb +0 -2
  40. data/test/apps/rails-3-2/app/mailers/.gitkeep +0 -0
  41. data/test/apps/rails-3-2/app/models/.gitkeep +0 -0
  42. data/test/apps/rails-3-2/app/models/post.rb +0 -3
  43. data/test/apps/rails-3-2/app/views/layouts/application.html.erb +0 -14
  44. data/test/apps/rails-3-2/app/views/posts/_form.html.erb +0 -21
  45. data/test/apps/rails-3-2/app/views/posts/edit.html.erb +0 -6
  46. data/test/apps/rails-3-2/app/views/posts/index.html.erb +0 -23
  47. data/test/apps/rails-3-2/app/views/posts/new.html.erb +0 -5
  48. data/test/apps/rails-3-2/app/views/posts/show.html.erb +0 -10
  49. data/test/apps/rails-3-2/config.ru +0 -4
  50. data/test/apps/rails-3-2/config/application.rb +0 -62
  51. data/test/apps/rails-3-2/config/boot.rb +0 -6
  52. data/test/apps/rails-3-2/config/database.yml +0 -25
  53. data/test/apps/rails-3-2/config/environment.rb +0 -5
  54. data/test/apps/rails-3-2/config/environments/development.rb +0 -37
  55. data/test/apps/rails-3-2/config/environments/production.rb +0 -67
  56. data/test/apps/rails-3-2/config/environments/test.rb +0 -37
  57. data/test/apps/rails-3-2/config/initializers/backtrace_silencers.rb +0 -7
  58. data/test/apps/rails-3-2/config/initializers/inflections.rb +0 -15
  59. data/test/apps/rails-3-2/config/initializers/mime_types.rb +0 -5
  60. data/test/apps/rails-3-2/config/initializers/secret_token.rb +0 -7
  61. data/test/apps/rails-3-2/config/initializers/session_store.rb +0 -8
  62. data/test/apps/rails-3-2/config/initializers/wrap_parameters.rb +0 -14
  63. data/test/apps/rails-3-2/config/locales/en.yml +0 -5
  64. data/test/apps/rails-3-2/config/routes.rb +0 -60
  65. data/test/apps/rails-3-2/config/spring.rb +0 -7
  66. data/test/apps/rails-3-2/db/migrate/20121109171227_create_posts.rb +0 -9
  67. data/test/apps/rails-3-2/db/schema.rb +0 -22
  68. data/test/apps/rails-3-2/db/seeds.rb +0 -7
  69. data/test/apps/rails-3-2/lib/assets/.gitkeep +0 -0
  70. data/test/apps/rails-3-2/lib/tasks/.gitkeep +0 -0
  71. data/test/apps/rails-3-2/log/.gitkeep +0 -0
  72. data/test/apps/rails-3-2/public/404.html +0 -26
  73. data/test/apps/rails-3-2/public/422.html +0 -26
  74. data/test/apps/rails-3-2/public/500.html +0 -25
  75. data/test/apps/rails-3-2/public/favicon.ico +0 -0
  76. data/test/apps/rails-3-2/public/index.html +0 -241
  77. data/test/apps/rails-3-2/public/robots.txt +0 -5
  78. data/test/apps/rails-3-2/script/rails +0 -6
  79. data/test/apps/rails-3-2/spec/dummy_spec.rb +0 -5
  80. data/test/apps/rails-3-2/test/fixtures/.gitkeep +0 -0
  81. data/test/apps/rails-3-2/test/fixtures/posts.yml +0 -7
  82. data/test/apps/rails-3-2/test/functional/.gitkeep +0 -0
  83. data/test/apps/rails-3-2/test/functional/posts_controller_test.rb +0 -49
  84. data/test/apps/rails-3-2/test/integration/.gitkeep +0 -0
  85. data/test/apps/rails-3-2/test/test_helper.rb +0 -13
  86. data/test/apps/rails-3-2/test/unit/.gitkeep +0 -0
  87. data/test/apps/rails-3-2/test/unit/helpers/posts_helper_test.rb +0 -4
  88. data/test/apps/rails-3-2/test/unit/post_test.rb +0 -7
  89. data/test/apps/rails-3-2/vendor/assets/javascripts/.gitkeep +0 -0
  90. data/test/apps/rails-3-2/vendor/assets/stylesheets/.gitkeep +0 -0
  91. data/test/apps/rails-3-2/vendor/plugins/.gitkeep +0 -0
@@ -2,3 +2,6 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ env:
6
+ - RAILS_VERSION="~> 3.2.0"
7
+ - RAILS_VERSION="~> 4.0.0"
@@ -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.watch_via=` configuration option to switch between
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.watch_via = :listen` to use the listen gem.
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
@@ -3,4 +3,4 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in spring.gemspec
4
4
  gemspec
5
5
 
6
- gem 'listen', :require => false
6
+ gem 'listen', "~> 1.0", :require => false
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 _instaed of_ a
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 `config/spring.rb`. See
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
+ ```
@@ -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 = manager
12
- @watcher = watcher
13
- @setup = Set.new
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 start
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
- # The test environment has config.cache_classes = true set by default.
24
- # However, we don't want this to prevent us from performing class reloading,
25
- # so this gets around that.
26
- ::Rails::Application.initializer :initialize_dependency_mechanism, group: :all do
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
- # This initializer has issues after we disconnect from the DB, but we don't need it.
31
- if defined?(ActiveRecord::Base)
32
- ActiveRecord::Railtie.initializers.delete_if { |i| i.name == "active_record.set_reloader_hooks" }
33
- end
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
- ActiveRecord::Base.remove_connection if defined?(ActiveRecord::Base)
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
- run
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
- exit
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
- [STDOUT, STDERR, STDIN].zip(streams).each { |a, b| a.reopen(b) }
112
+ STDIN.reopen(streams.last)
75
113
  IGNORE_SIGNALS.each { |sig| trap(sig, "DEFAULT") }
76
114
 
77
- ActiveRecord::Base.establish_connection if defined?(ActiveRecord::Base)
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.chomp.to_i # get the pid
67
- rescue Errno::ECONNRESET, Errno::EPIPE
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(silence = false)
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).start
101
+ app = Application.new(child_socket)
102
+ app.preload if preload
103
+ app.run
97
104
  }
98
105
  child_socket.close
99
106
  end
@@ -1,4 +1,4 @@
1
- require "spring/configuration"
1
+ require "spring/errors"
2
2
  require "spring/json"
3
3
 
4
4
  require "spring/client/command"
@@ -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.sort
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
 
@@ -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
- exec "bundle", "exec", *args
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
@@ -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
- fork {
33
+
34
+ pid = fork {
32
35
  require "spring/server"
33
36
  Spring::Server.boot
34
37
  }
35
- sleep 0.1 until env.socket_path.exist?
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 beween the spring client and the server.
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
- exit application.read.to_i
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