spring 1.0.0 → 1.1.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.
@@ -0,0 +1,329 @@
1
+ require "spring/env"
2
+
3
+ module Spring
4
+ module Test
5
+ class RailsVersion
6
+ attr_reader :version
7
+
8
+ def initialize(string)
9
+ @version = Gem::Version.new(string)
10
+ end
11
+
12
+ def rails_3?
13
+ version < Gem::Version.new("4.0.0")
14
+ end
15
+ alias needs_testunit? rails_3?
16
+
17
+ def test_command
18
+ needs_testunit? ? 'bin/testunit' : 'bin/rake test'
19
+ end
20
+
21
+ def controller_tests_dir
22
+ rails_3? ? 'functional' : 'controllers'
23
+ end
24
+
25
+ def bundles_spring?
26
+ version >= Gem::Version.new("4.1.0.beta1")
27
+ end
28
+
29
+ def major
30
+ version.segments[0]
31
+ end
32
+
33
+ def minor
34
+ version.segments[1]
35
+ end
36
+ end
37
+
38
+ class Application
39
+ DEFAULT_TIMEOUT = ENV['CI'] ? 30 : 10
40
+
41
+ attr_reader :root, :spring_env
42
+
43
+ def initialize(root)
44
+ @root = Pathname.new(root)
45
+ @spring_env = Spring::Env.new(root)
46
+ end
47
+
48
+ def exists?
49
+ root.exist?
50
+ end
51
+
52
+ def stdout
53
+ @stdout ||= IO.pipe
54
+ end
55
+
56
+ def stderr
57
+ @stderr ||= IO.pipe
58
+ end
59
+
60
+ def log_file
61
+ @log_file ||= path("tmp/spring.log").open("w+")
62
+ end
63
+
64
+ def env
65
+ @env ||= {
66
+ "GEM_HOME" => gem_home.to_s,
67
+ "GEM_PATH" => "",
68
+ "HOME" => user_home.to_s,
69
+ "RAILS_ENV" => nil,
70
+ "RACK_ENV" => nil,
71
+ "SPRING_LOG" => log_file.path
72
+ }
73
+ end
74
+
75
+ def path(addition)
76
+ root.join addition
77
+ end
78
+
79
+ def gemfile
80
+ path "Gemfile"
81
+ end
82
+
83
+ def gem_home
84
+ path "vendor/gems/#{RUBY_VERSION}"
85
+ end
86
+
87
+ def user_home
88
+ path "user_home"
89
+ end
90
+
91
+ def spring
92
+ gem_home.join "bin/spring"
93
+ end
94
+
95
+ def rails_version
96
+ @rails_version ||= RailsVersion.new(gemfile.read.match(/gem 'rails', '(.*)'/)[1])
97
+ end
98
+
99
+ def spring_test_command
100
+ "#{rails_version.test_command} #{test}"
101
+ end
102
+
103
+ def stop_spring
104
+ run "#{spring} stop"
105
+ rescue Errno::ENOENT
106
+ end
107
+
108
+ def test
109
+ path "test/#{rails_version.controller_tests_dir}/posts_controller_test.rb"
110
+ end
111
+
112
+ def controller
113
+ path "app/controllers/posts_controller.rb"
114
+ end
115
+
116
+ def application_config
117
+ path "config/application.rb"
118
+ end
119
+
120
+ def spring_config
121
+ path "config/spring.rb"
122
+ end
123
+
124
+ def run(command, opts = {})
125
+ start_time = Time.now
126
+
127
+ Bundler.with_clean_env do
128
+ Process.spawn(
129
+ env,
130
+ command.to_s,
131
+ out: stdout.last,
132
+ err: stderr.last,
133
+ in: :close,
134
+ chdir: root.to_s,
135
+ )
136
+ end
137
+
138
+ _, status = Timeout.timeout(opts.fetch(:timeout, DEFAULT_TIMEOUT)) { Process.wait2 }
139
+
140
+ if pid = spring_env.pid
141
+ @server_pid = pid
142
+ lines = `ps -A -o ppid= -o pid= | egrep '^\\s*#{@server_pid}'`.lines
143
+ @application_pids = lines.map { |l| l.split.last.to_i }
144
+ end
145
+
146
+ output = read_streams
147
+ puts dump_streams(command, output) if ENV["SPRING_DEBUG"]
148
+
149
+ @times << (Time.now - start_time) if @times
150
+
151
+ output.merge(status: status, command: command)
152
+ rescue Timeout::Error => e
153
+ raise e, "Output:\n\n#{dump_streams(command, read_streams)}"
154
+ end
155
+
156
+ def with_timing
157
+ @times = []
158
+ yield
159
+ ensure
160
+ @times = nil
161
+ end
162
+
163
+ def last_time
164
+ @times.last
165
+ end
166
+
167
+ def first_time
168
+ @times.first
169
+ end
170
+
171
+ def timing_ratio
172
+ last_time / first_time
173
+ end
174
+
175
+ def read_streams
176
+ {
177
+ stdout: read_stream(stdout.first),
178
+ stderr: read_stream(stderr.first),
179
+ log: read_stream(log_file)
180
+ }
181
+ end
182
+
183
+ def read_stream(stream)
184
+ output = ""
185
+ while IO.select([stream], [], [], 0.5) && !stream.eof?
186
+ output << stream.readpartial(10240)
187
+ end
188
+ output
189
+ end
190
+
191
+ def dump_streams(command, streams)
192
+ output = "$ #{command}\n"
193
+
194
+ streams.each do |name, stream|
195
+ unless stream.chomp.empty?
196
+ output << "--- #{name} ---\n"
197
+ output << "#{stream.chomp}\n"
198
+ end
199
+ end
200
+
201
+ output << "\n"
202
+ output
203
+ end
204
+
205
+ def debug(artifacts)
206
+ artifacts = artifacts.dup
207
+ artifacts.delete :status
208
+ dump_streams(artifacts.delete(:command), artifacts)
209
+ end
210
+
211
+ def await_reload
212
+ raise "no pid" if @application_pids.nil? || @application_pids.empty?
213
+
214
+ Timeout.timeout(DEFAULT_TIMEOUT) do
215
+ sleep 0.1 while @application_pids.any? { |p| process_alive?(p) }
216
+ end
217
+ end
218
+
219
+ def run!(*args)
220
+ artifacts = run(*args)
221
+ unless artifacts[:status].success?
222
+ raise "command failed\n\n#{debug(artifacts)}"
223
+ end
224
+ artifacts
225
+ end
226
+
227
+ def bundle
228
+ run! "(gem list bundler | grep bundler) || gem install bundler", timeout: nil
229
+ run! "bundle update", timeout: nil
230
+ end
231
+
232
+ private
233
+
234
+ def process_alive?(pid)
235
+ Process.kill 0, pid
236
+ true
237
+ rescue Errno::ESRCH
238
+ false
239
+ end
240
+ end
241
+
242
+ class ApplicationGenerator
243
+ attr_reader :version_constraint, :version, :application
244
+
245
+ def initialize(version_constraint)
246
+ @version_constraint = version_constraint
247
+ @version = RailsVersion.new(version_constraint.split(' ').last)
248
+ @application = Application.new(root)
249
+ @bundled = false
250
+ end
251
+
252
+ def root
253
+ "#{TEST_ROOT}/apps/rails-#{version.major}-#{version.minor}-spring-#{Spring::VERSION}"
254
+ end
255
+
256
+ def system(command)
257
+ if ENV["SPRING_DEBUG"]
258
+ puts "$ #{command}\n"
259
+ else
260
+ command = "(#{command}) > /dev/null"
261
+ end
262
+
263
+ Kernel.system(command) or raise "command failed: #{command}"
264
+ puts if ENV["SPRING_DEBUG"]
265
+ end
266
+
267
+ # Sporadic SSL errors keep causing test failures so there are anti-SSL workarounds here
268
+ def generate
269
+ Bundler.with_clean_env do
270
+ system("(gem list rails --installed --version '#{version_constraint}' || " \
271
+ "gem install rails --clear-sources --source http://rubygems.org --version '#{version_constraint}')")
272
+
273
+ skips = %w(--skip-bundle --skip-javascript --skip-sprockets)
274
+ skips << "--skip-spring" if version.bundles_spring?
275
+
276
+ system("rails '_#{version_constraint}_' new #{application.root} #{skips.join(' ')}")
277
+
278
+ FileUtils.mkdir_p(application.gem_home)
279
+ FileUtils.mkdir_p(application.user_home)
280
+ FileUtils.rm_rf(application.path("test/performance"))
281
+
282
+ File.write(application.gemfile, "#{application.gemfile.read}gem 'spring', '#{Spring::VERSION}'\n")
283
+
284
+ if version.needs_testunit?
285
+ File.write(application.gemfile, "#{application.gemfile.read}gem 'spring-commands-testunit'\n")
286
+ end
287
+
288
+ File.write(application.gemfile, application.gemfile.read.sub("https://rubygems.org", "http://rubygems.org"))
289
+
290
+ if application.path("bin").exist?
291
+ FileUtils.cp_r(application.path("bin"), application.path("bin_original"))
292
+ end
293
+ end
294
+
295
+ install_spring
296
+
297
+ application.run! "bundle exec rails g scaffold post title:string"
298
+ application.run! "bundle exec rake db:migrate db:test:clone"
299
+ end
300
+
301
+ def generate_if_missing
302
+ generate unless application.exists?
303
+ end
304
+
305
+ def install_spring
306
+ return if @installed
307
+
308
+ system("gem build spring.gemspec 2>&1")
309
+ application.run! "gem install ../../../spring-#{Spring::VERSION}.gem", timeout: nil
310
+
311
+ application.bundle
312
+
313
+ FileUtils.rm_rf application.path("bin")
314
+
315
+ if application.path("bin_original").exist?
316
+ FileUtils.cp_r application.path("bin_original"), application.path("bin")
317
+ end
318
+
319
+ application.run! "#{application.spring} binstub --all"
320
+ @installed = true
321
+ end
322
+
323
+ def copy_to(path)
324
+ system("rm -rf #{path}")
325
+ system("cp -r #{application.root} #{path}")
326
+ end
327
+ end
328
+ end
329
+ end
@@ -0,0 +1,14 @@
1
+ require 'helper'
2
+ require 'spring/client'
3
+
4
+ class VersionTest < ActiveSupport::TestCase
5
+ test "outputs current version number" do
6
+ version = Spring::Client::Version.new 'version'
7
+
8
+ out, err = capture_io do
9
+ version.call
10
+ end
11
+
12
+ assert_equal "Spring version #{Spring::VERSION}", out.chomp
13
+ end
14
+ end
@@ -1,6 +1,7 @@
1
1
  require "helper"
2
2
  require "tmpdir"
3
3
  require "fileutils"
4
+ require "timeout"
4
5
  require "active_support/core_ext/numeric/time"
5
6
  require "spring/watcher"
6
7
  require "spring/watcher/polling"
@@ -120,22 +121,25 @@ module WatcherTests
120
121
  assert_stale
121
122
  end
122
123
 
123
- def test_can_io_select
124
+ def test_on_stale
124
125
  file = "#{@dir}/omg"
125
126
  touch file, Time.now - 2.seconds
126
127
 
127
128
  watcher.add file
128
129
  watcher.start
129
130
 
130
- io = watcher.to_io
131
+ stale = false
132
+ watcher.on_stale { stale = true }
131
133
 
132
- Thread.new {
133
- sleep LATENCY * 3
134
- touch file, Time.now
135
- }
134
+ touch file, Time.now
136
135
 
137
- assert IO.select([io], [], [], 1), "IO.select timed out before watcher was readable"
138
- assert watcher.stale?
136
+ Timeout.timeout(1) { sleep 0.01 until stale }
137
+ assert stale
138
+
139
+ # Check that we only get notified once
140
+ stale = false
141
+ sleep LATENCY * 3
142
+ assert !stale
139
143
  end
140
144
 
141
145
  def test_add_relative_path
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.0.0
4
+ version: 1.1.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: 2013-11-19 00:00:00.000000000 Z
11
+ date: 2014-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -55,7 +55,10 @@ files:
55
55
  - Rakefile
56
56
  - bin/spring
57
57
  - lib/spring/application.rb
58
+ - lib/spring/application/boot.rb
58
59
  - lib/spring/application_manager.rb
60
+ - lib/spring/binstub.rb
61
+ - lib/spring/boot.rb
59
62
  - lib/spring/client.rb
60
63
  - lib/spring/client/binstub.rb
61
64
  - lib/spring/client/command.rb
@@ -64,6 +67,8 @@ files:
64
67
  - lib/spring/client/run.rb
65
68
  - lib/spring/client/status.rb
66
69
  - lib/spring/client/stop.rb
70
+ - lib/spring/client/version.rb
71
+ - lib/spring/command_wrapper.rb
67
72
  - lib/spring/commands.rb
68
73
  - lib/spring/commands/rails.rb
69
74
  - lib/spring/commands/rake.rb
@@ -81,13 +86,15 @@ files:
81
86
  - lib/spring/watcher/polling.rb
82
87
  - spring.gemspec
83
88
  - test/acceptance/app_test.rb
89
+ - test/acceptance/helper.rb
84
90
  - test/apps/.gitignore
85
91
  - test/helper.rb
86
92
  - test/unit/client/help_test.rb
93
+ - test/unit/client/version_test.rb
87
94
  - test/unit/commands_test.rb
88
95
  - test/unit/process_title_updater_test.rb
89
96
  - test/unit/watcher_test.rb
90
- homepage: http://github.com/jonleighton/spring
97
+ homepage: http://github.com/rails/spring
91
98
  licenses:
92
99
  - MIT
93
100
  metadata: {}
@@ -113,9 +120,12 @@ specification_version: 4
113
120
  summary: Rails application preloader
114
121
  test_files:
115
122
  - test/acceptance/app_test.rb
123
+ - test/acceptance/helper.rb
116
124
  - test/apps/.gitignore
117
125
  - test/helper.rb
118
126
  - test/unit/client/help_test.rb
127
+ - test/unit/client/version_test.rb
119
128
  - test/unit/commands_test.rb
120
129
  - test/unit/process_title_updater_test.rb
121
130
  - test/unit/watcher_test.rb
131
+ has_rdoc: