spring 0.0.5 → 0.0.6

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.
@@ -3,7 +3,7 @@ require "socket"
3
3
  require "spring/env"
4
4
  require "spring/application_manager"
5
5
 
6
- class Spring
6
+ module Spring
7
7
  class Server
8
8
  def self.boot
9
9
  new.boot
@@ -25,15 +25,20 @@ class Spring
25
25
  set_exit_hook
26
26
  write_pidfile
27
27
 
28
+ $0 = "spring server | #{env.app_name} | started #{Time.now}"
29
+
28
30
  server = UNIXServer.open(env.socket_name)
29
31
  loop { serve server.accept }
30
32
  end
31
33
 
32
34
  def serve(client)
35
+ client.puts env.version
33
36
  app_client = client.recv_io
34
37
  rails_env = client.gets.chomp
35
38
 
36
39
  client.puts @applications[rails_env].run(app_client)
40
+ rescue SocketError => e
41
+ raise e unless client.eof?
37
42
  end
38
43
 
39
44
  def set_exit_hook
@@ -45,6 +50,8 @@ class Spring
45
50
  [env.socket_path, env.pidfile_path].each do |path|
46
51
  path.unlink if path.exist?
47
52
  end
53
+
54
+ @applications.values.each(&:stop)
48
55
  end
49
56
  end
50
57
  end
@@ -56,7 +63,7 @@ class Spring
56
63
  @pidfile.fsync
57
64
  else
58
65
  STDERR.puts "#{file.path} is locked; it looks like a server is already running"
59
- exit(1)
66
+ exit 1
60
67
  end
61
68
  end
62
69
  end
@@ -1,6 +1,6 @@
1
1
  require 'fiddle'
2
2
 
3
- class Spring
3
+ module Spring
4
4
  module SID
5
5
  FUNC = Fiddle::Function.new(
6
6
  DL::Handle::DEFAULT['getsid'],
@@ -1,3 +1,3 @@
1
- class Spring
2
- VERSION = "0.0.5"
1
+ module Spring
2
+ VERSION = "0.0.6"
3
3
  end
@@ -1,20 +1,28 @@
1
1
  require 'helper'
2
2
  require 'io/wait'
3
3
  require "timeout"
4
+ require "spring/sid"
5
+ require "spring/env"
4
6
 
5
7
  class AppTest < ActiveSupport::TestCase
6
- BINFILE = File.expand_path('../bin/spring', TEST_ROOT)
7
-
8
8
  def app_root
9
- "#{TEST_ROOT}/apps/rails-3-2"
9
+ Pathname.new("#{TEST_ROOT}/apps/rails-3-2")
10
10
  end
11
11
 
12
12
  def server_pidfile
13
13
  "#{app_root}/tmp/spring/#{Spring::SID.sid}.pid"
14
14
  end
15
15
 
16
+ def spring_env
17
+ @spring_env ||= Spring::Env.new(app_root)
18
+ end
19
+
16
20
  def server_pid
17
- File.exist?(server_pidfile) ? File.read(server_pidfile).to_i : nil
21
+ spring_env.pid
22
+ end
23
+
24
+ def server_running?
25
+ spring_env.server_running?
18
26
  end
19
27
 
20
28
  def stdout
@@ -30,10 +38,15 @@ class AppTest < ActiveSupport::TestCase
30
38
 
31
39
  Bundler.with_clean_env do
32
40
  Process.spawn(
41
+ {
42
+ "GEM_HOME" => "#{app_root}/vendor/gems",
43
+ "GEM_PATH" => "",
44
+ "PATH" => "#{app_root}/vendor/gems/bin:#{ENV["PATH"]}"
45
+ },
33
46
  command,
34
47
  out: stdout.last,
35
48
  err: stderr.last,
36
- chdir: app_root,
49
+ chdir: app_root.to_s,
37
50
  )
38
51
  end
39
52
 
@@ -41,7 +54,9 @@ class AppTest < ActiveSupport::TestCase
41
54
 
42
55
  out, err = read_streams
43
56
 
44
- @times << (Time.now - start_time) if opts.fetch(:timer, true)
57
+ @times << (Time.now - start_time) if @times
58
+
59
+ print_streams(out, err) if ENV["SPRING_DEBUG"]
45
60
 
46
61
  [status, out, err]
47
62
  rescue Timeout::Error
@@ -62,17 +77,17 @@ class AppTest < ActiveSupport::TestCase
62
77
  end
63
78
 
64
79
  def await_reload
65
- sleep 0.2
80
+ sleep 0.4
66
81
  end
67
82
 
68
83
  def assert_successful_run(*args)
69
84
  status, _, _ = app_run(*args)
70
- assert status.success?, 'The run should be successful but it was '
85
+ assert status.success?, "The run should be successful but it wasn't"
71
86
  end
72
87
 
73
88
  def assert_unsuccessful_run(*args)
74
89
  status, _, _ = app_run(*args)
75
- assert !status.success?, 'The run should not be successful but it was'
90
+ assert !status.success?, "The run should not be successful but it was"
76
91
  end
77
92
 
78
93
  def assert_stdout(command, expected)
@@ -80,6 +95,11 @@ class AppTest < ActiveSupport::TestCase
80
95
  assert stdout.include?(expected), "expected '#{expected}' to be printed to stdout. But it wasn't, the stdout is:\n#{stdout}"
81
96
  end
82
97
 
98
+ def assert_stderr(command, expected)
99
+ _, _, stderr = app_run(command)
100
+ assert stderr.include?(expected), "expected '#{expected}' to be printed to stderr. But it wasn't, the stderr is:\n#{stderr}"
101
+ end
102
+
83
103
  def assert_speedup(opts = {})
84
104
  ratio = opts.fetch(:ratio, 0.5)
85
105
  from = opts.fetch(:from, 0)
@@ -89,20 +109,40 @@ class AppTest < ActiveSupport::TestCase
89
109
  assert (second / first) < ratio, "#{second} was not less than #{ratio} of #{first}"
90
110
  end
91
111
 
112
+ def assert_server_running(*args)
113
+ assert server_running?, "The server should be running but it isn't"
114
+ end
115
+
116
+ def assert_server_not_running(*args)
117
+ assert !server_running?, "The server should not be running but it is"
118
+ end
119
+
92
120
  def test_command
93
- "#{BINFILE} test #{@test}"
121
+ "spring test #{@test}"
94
122
  end
95
123
 
124
+ @@installed_spring = false
125
+
96
126
  setup do
97
127
  @test = "#{app_root}/test/functional/posts_controller_test.rb"
98
128
  @test_contents = File.read(@test)
99
129
  @controller = "#{app_root}/app/controllers/posts_controller.rb"
100
130
  @controller_contents = File.read(@controller)
101
131
 
102
- @times = []
132
+ @spring_env = Spring::Env.new(app_root)
133
+
134
+ unless @@installed_spring
135
+ system "gem build spring.gemspec 2>/dev/null 1>/dev/null"
136
+ app_run "gem install ../../../spring-*.gem"
137
+ @@installed_spring = true
138
+ end
139
+
140
+ FileUtils.rm_rf "#{app_root}/bin"
141
+ app_run "(gem list bundler | grep bundler) || gem install bundler", timeout: nil
142
+ app_run "bundle check || bundle update", timeout: nil
143
+ app_run "bundle exec rake db:migrate"
103
144
 
104
- app_run "bundle check || bundle update", timer: false, timeout: nil
105
- app_run "bundle exec rake db:migrate", timer: false
145
+ @times = []
106
146
  end
107
147
 
108
148
  teardown do
@@ -123,7 +163,7 @@ class AppTest < ActiveSupport::TestCase
123
163
  end
124
164
 
125
165
  test "help message when called without arguments" do
126
- assert_stdout BINFILE, 'Usage: spring COMMAND [ARGS]'
166
+ assert_stdout "spring", 'Usage: spring COMMAND [ARGS]'
127
167
  end
128
168
 
129
169
  test "test changes are picked up" do
@@ -176,8 +216,7 @@ class AppTest < ActiveSupport::TestCase
176
216
  CODE
177
217
  File.write(@test, @test_contents.sub("get :index", "Foo.omg"))
178
218
 
179
- # Wait twice to give plenty of time for the wait thread to kick in
180
- 2.times { await_reload }
219
+ await_reload
181
220
 
182
221
  assert_stdout test_command, "RuntimeError: omg"
183
222
  assert_stdout test_command, "RuntimeError: omg"
@@ -209,11 +248,34 @@ class AppTest < ActiveSupport::TestCase
209
248
  end
210
249
  end
211
250
 
251
+ test "stop command kills server" do
252
+ assert_successful_run test_command
253
+ assert_server_running
254
+
255
+ assert_successful_run 'spring stop'
256
+ assert_server_not_running
257
+ end
258
+
212
259
  test "custom commands" do
213
- assert_stdout "#{BINFILE} custom", "omg"
260
+ assert_stdout "spring custom", "omg"
214
261
  end
215
262
 
216
263
  test "runner alias" do
217
- assert_stdout "#{BINFILE} r 'puts 1'", "1"
264
+ assert_stdout "spring r 'puts 1'", "1"
265
+ end
266
+
267
+ test "binstubs" do
268
+ app_run "spring binstub rake"
269
+ assert_successful_run "bin/spring help"
270
+ assert_stdout "bin/rake -T", "rake db:migrate"
271
+ end
272
+
273
+ test "missing config/application.rb" do
274
+ begin
275
+ FileUtils.mv app_root.join("config/application.rb"), app_root.join("config/application.rb.bak")
276
+ assert_stderr "spring rake -T", "unable to find your config/application.rb"
277
+ ensure
278
+ FileUtils.mv app_root.join("config/application.rb.bak"), app_root.join("config/application.rb")
279
+ end
218
280
  end
219
281
  end
@@ -13,3 +13,6 @@
13
13
  # Ignore all logfiles and tempfiles.
14
14
  /log/*.log
15
15
  /tmp
16
+
17
+ /bin
18
+ /vendor/gems/*
@@ -1,5 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'rails', '~> 3.2.8'
3
+ gem 'rails', '~> 3.2.0'
4
4
  gem 'sqlite3'
5
- gem 'spring', path: '../../..'
@@ -1,7 +1,6 @@
1
1
  $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
2
 
3
3
  require "bundler/setup"
4
- require "spring"
5
4
  require "active_support/test_case"
6
5
  require "minitest/autorun"
7
6
 
@@ -3,7 +3,7 @@ require "fileutils"
3
3
  require "active_support/core_ext/numeric/time"
4
4
  require "spring/application_watcher"
5
5
 
6
- class ApplicationWatcherTest < Test::Unit::TestCase
6
+ class ApplicationWatcherTest < ActiveSupport::TestCase
7
7
  def setup
8
8
  @dir = "/tmp/spring"
9
9
  FileUtils.mkdir(@dir)
@@ -19,7 +19,7 @@ class ApplicationWatcherTest < Test::Unit::TestCase
19
19
  FileUtils.touch(file, options)
20
20
  end
21
21
 
22
- def test_file_mtime
22
+ test "file mtime" do
23
23
  file = "#{@dir}/omg"
24
24
  touch file, Time.now - 2.seconds
25
25
 
@@ -31,7 +31,19 @@ class ApplicationWatcherTest < Test::Unit::TestCase
31
31
  assert watcher.stale?
32
32
  end
33
33
 
34
- def test_glob
34
+ test "tolerates enoent" do
35
+ file = "#{@dir}/omg"
36
+ touch file
37
+
38
+ watcher = Spring::ApplicationWatcher.new
39
+ watcher.add_files [file]
40
+
41
+ assert !watcher.stale?
42
+ FileUtils.rm(file)
43
+ assert watcher.stale?
44
+ end
45
+
46
+ test "accepts glob patterns" do
35
47
  FileUtils.mkdir("#{@dir}/1")
36
48
  FileUtils.mkdir("#{@dir}/2")
37
49
 
@@ -0,0 +1,34 @@
1
+ require "helper"
2
+ require "spring/commands"
3
+
4
+ class CommandsTest < ActiveSupport::TestCase
5
+
6
+ test "test command needs a test name" do
7
+ begin
8
+ real_stderr = $stderr
9
+ $stderr = StringIO.new('')
10
+
11
+ command = Spring::Commands::Test.new
12
+ command.call([])
13
+
14
+ assert_equal "you need to specify what test to run: spring test TEST_NAME\n", $stderr.string
15
+ ensure
16
+ $stderr = real_stderr
17
+ end
18
+ end
19
+
20
+ test "prints error message when preloaded file does not exist" do
21
+ begin
22
+ original_stderr = $stderr
23
+ $stderr = StringIO.new('')
24
+ my_command_class = Class.new(Spring::Commands::Command)
25
+ my_command_class.preloads = %w(i_do_not_exist)
26
+
27
+ my_command_class.new.setup
28
+ assert_match /The #<Class:0x[0-9a-f]+> command tried to preload i_do_not_exist but could not find it./, $stderr.string
29
+ ensure
30
+ $stderr = original_stderr
31
+ end
32
+ end
33
+
34
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spring
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-26 00:00:00.000000000 Z
12
+ date: 2013-02-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -58,12 +58,19 @@ files:
58
58
  - README.md
59
59
  - Rakefile
60
60
  - bin/spring
61
- - lib/spring.rb
62
61
  - lib/spring/application.rb
63
62
  - lib/spring/application_manager.rb
64
63
  - lib/spring/application_watcher.rb
64
+ - lib/spring/client.rb
65
+ - lib/spring/client/binstub.rb
66
+ - lib/spring/client/command.rb
67
+ - lib/spring/client/help.rb
68
+ - lib/spring/client/run.rb
69
+ - lib/spring/client/stop.rb
65
70
  - lib/spring/commands.rb
71
+ - lib/spring/configuration.rb
66
72
  - lib/spring/env.rb
73
+ - lib/spring/errors.rb
67
74
  - lib/spring/server.rb
68
75
  - lib/spring/sid.rb
69
76
  - lib/spring/version.rb
@@ -134,9 +141,11 @@ files:
134
141
  - test/apps/rails-3-2/test/unit/post_test.rb
135
142
  - test/apps/rails-3-2/vendor/assets/javascripts/.gitkeep
136
143
  - test/apps/rails-3-2/vendor/assets/stylesheets/.gitkeep
144
+ - test/apps/rails-3-2/vendor/gems/.gitkeep
137
145
  - test/apps/rails-3-2/vendor/plugins/.gitkeep
138
146
  - test/helper.rb
139
147
  - test/unit/application_watcher_test.rb
148
+ - test/unit/commands_test.rb
140
149
  homepage: http://github.com/jonleighton/spring
141
150
  licenses: []
142
151
  post_install_message:
@@ -228,6 +237,8 @@ test_files:
228
237
  - test/apps/rails-3-2/test/unit/post_test.rb
229
238
  - test/apps/rails-3-2/vendor/assets/javascripts/.gitkeep
230
239
  - test/apps/rails-3-2/vendor/assets/stylesheets/.gitkeep
240
+ - test/apps/rails-3-2/vendor/gems/.gitkeep
231
241
  - test/apps/rails-3-2/vendor/plugins/.gitkeep
232
242
  - test/helper.rb
233
243
  - test/unit/application_watcher_test.rb
244
+ - test/unit/commands_test.rb
@@ -1,151 +0,0 @@
1
- require "rbconfig"
2
- require "socket"
3
- require "pty"
4
-
5
- require "spring/version"
6
- require "spring/sid"
7
- require "spring/env"
8
- require "spring/commands"
9
-
10
- class Spring
11
- SERVER_COMMAND = [
12
- File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')),
13
- "-I", File.expand_path("../", __FILE__),
14
- "-r", "spring/server",
15
- "-r", "bundler/setup",
16
- "-e", "Spring::Server.boot"
17
- ]
18
-
19
- FORWARDED_SIGNALS = %w(INT QUIT USR1 USR2 INFO)
20
-
21
- def self.run(args)
22
- exit new.run(args)
23
- end
24
-
25
- attr_reader :env
26
-
27
- def initialize
28
- @env = Env.new
29
- end
30
-
31
- def server_running?
32
- if env.pidfile_path.exist?
33
- pidfile = env.pidfile_path.open('r')
34
- !pidfile.flock(File::LOCK_EX | File::LOCK_NB)
35
- else
36
- false
37
- end
38
- ensure
39
- if pidfile
40
- pidfile.flock(File::LOCK_UN)
41
- pidfile.close
42
- end
43
- end
44
-
45
- # Boot the server into the process group of the current session.
46
- # This will cause it to be automatically killed once the session
47
- # ends (i.e. when the user closes their terminal).
48
- def boot_server
49
- env.socket_path.unlink if env.socket_path.exist?
50
- Process.spawn(*SERVER_COMMAND, pgroup: SID.pgid)
51
- sleep 0.1 until env.socket_path.exist?
52
- end
53
-
54
- def run(args)
55
- if self.class.command_registered?(args.first)
56
- run_command(args)
57
- else
58
- print_help
59
- end
60
- end
61
-
62
- private
63
-
64
- def print_help
65
- puts <<-EOT
66
- Usage: spring COMMAND [ARGS]
67
-
68
- The most common spring commands are:
69
- rake Run a rake task
70
- console Start the Rails console
71
- runner Execute a command with the Rails runner
72
- generate Trigger a Rails generator
73
-
74
- test Execute a Test::Unit test
75
- rspec Execute an RSpec spec
76
- EOT
77
- false
78
- end
79
-
80
- def run_command(args)
81
- boot_server unless server_running?
82
-
83
- application, client = UNIXSocket.pair
84
-
85
- server = UNIXSocket.open(env.socket_name)
86
- server.send_io client
87
- server.puts rails_env_for(args.first)
88
-
89
- application.send_io STDOUT
90
- application.send_io STDERR
91
- application.send_io stdin_slave
92
-
93
- application.puts args.length
94
-
95
- args.each do |arg|
96
- application.puts arg.length
97
- application.write arg
98
- end
99
-
100
- pid = server.gets.chomp
101
-
102
- # We must not close the client socket until we are sure that the application has
103
- # received the FD. Otherwise the FD can end up getting closed while it's in the server
104
- # socket buffer on OS X. This doesn't happen on Linux.
105
- client.close
106
-
107
- if pid.empty?
108
- false
109
- else
110
- forward_signals(pid.to_i)
111
- application.read # FIXME: receive exit status from server
112
- true
113
- end
114
- rescue Errno::ECONNRESET
115
- false
116
- ensure
117
- application.close if application
118
- server.close if server
119
- end
120
-
121
- def rails_env_for(command_name)
122
- command = Spring.command(command_name)
123
-
124
- if command.respond_to?(:env)
125
- command.env
126
- else
127
- ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
128
- end
129
- end
130
-
131
- def stdin_slave
132
- master, slave = PTY.open
133
-
134
- # Sadly I cannot find a way to achieve this without shelling out to stty, or
135
- # using a C extension library. [Ruby does not have direct support for calling
136
- # tcsetattr().] We don't want to use a C extension library so
137
- # that spring can be used by Rails in the future.
138
- system "stty -icanon -echo"
139
- at_exit { system "stty sane" }
140
-
141
- Thread.new { master.write STDIN.read(1) until STDIN.closed? }
142
-
143
- slave
144
- end
145
-
146
- def forward_signals(pid)
147
- (FORWARDED_SIGNALS & Signal.list.keys).each do |sig|
148
- trap(sig) { Process.kill(sig, pid) }
149
- end
150
- end
151
- end