spring 0.0.8 → 1.0.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.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +3 -0
  3. data/CHANGELOG.md +113 -0
  4. data/Gemfile +1 -3
  5. data/README.md +129 -187
  6. data/bin/spring +27 -0
  7. data/lib/spring/application.rb +121 -20
  8. data/lib/spring/application_manager.rb +21 -13
  9. data/lib/spring/client/binstub.rb +45 -41
  10. data/lib/spring/client/help.rb +4 -1
  11. data/lib/spring/client/rails.rb +8 -3
  12. data/lib/spring/client/run.rb +33 -10
  13. data/lib/spring/client/status.rb +2 -2
  14. data/lib/spring/client.rb +3 -3
  15. data/lib/spring/commands/rails.rb +60 -0
  16. data/lib/spring/commands/rake.rb +34 -0
  17. data/lib/spring/commands.rb +12 -195
  18. data/lib/spring/configuration.rb +6 -2
  19. data/lib/spring/env.rb +27 -18
  20. data/lib/spring/errors.rb +1 -1
  21. data/lib/spring/json.rb +626 -0
  22. data/lib/spring/server.rb +60 -29
  23. data/lib/spring/version.rb +1 -1
  24. data/lib/spring/watcher/abstract.rb +11 -7
  25. data/lib/spring/watcher/listen.rb +8 -10
  26. data/lib/spring/watcher/polling.rb +1 -1
  27. data/lib/spring/watcher.rb +17 -11
  28. data/spring.gemspec +1 -0
  29. data/test/acceptance/app_test.rb +270 -73
  30. data/test/apps/.gitignore +3 -0
  31. data/test/unit/client/help_test.rb +2 -0
  32. data/test/unit/commands_test.rb +8 -49
  33. data/test/unit/watcher_test.rb +22 -2
  34. metadata +18 -151
  35. data/lib/spring/client/start.rb +0 -17
  36. data/test/apps/rails-3-2/.gitignore +0 -18
  37. data/test/apps/rails-3-2/Gemfile +0 -9
  38. data/test/apps/rails-3-2/README.rdoc +0 -261
  39. data/test/apps/rails-3-2/Rakefile +0 -7
  40. data/test/apps/rails-3-2/app/assets/images/rails.png +0 -0
  41. data/test/apps/rails-3-2/app/assets/javascripts/application.js +0 -15
  42. data/test/apps/rails-3-2/app/assets/javascripts/posts.js.coffee +0 -3
  43. data/test/apps/rails-3-2/app/assets/stylesheets/application.css +0 -13
  44. data/test/apps/rails-3-2/app/assets/stylesheets/posts.css.scss +0 -3
  45. data/test/apps/rails-3-2/app/assets/stylesheets/scaffolds.css.scss +0 -69
  46. data/test/apps/rails-3-2/app/controllers/application_controller.rb +0 -3
  47. data/test/apps/rails-3-2/app/controllers/posts_controller.rb +0 -83
  48. data/test/apps/rails-3-2/app/helpers/application_helper.rb +0 -2
  49. data/test/apps/rails-3-2/app/helpers/posts_helper.rb +0 -2
  50. data/test/apps/rails-3-2/app/mailers/.gitkeep +0 -0
  51. data/test/apps/rails-3-2/app/models/.gitkeep +0 -0
  52. data/test/apps/rails-3-2/app/models/post.rb +0 -3
  53. data/test/apps/rails-3-2/app/views/layouts/application.html.erb +0 -14
  54. data/test/apps/rails-3-2/app/views/posts/_form.html.erb +0 -21
  55. data/test/apps/rails-3-2/app/views/posts/edit.html.erb +0 -6
  56. data/test/apps/rails-3-2/app/views/posts/index.html.erb +0 -23
  57. data/test/apps/rails-3-2/app/views/posts/new.html.erb +0 -5
  58. data/test/apps/rails-3-2/app/views/posts/show.html.erb +0 -10
  59. data/test/apps/rails-3-2/config/application.rb +0 -62
  60. data/test/apps/rails-3-2/config/boot.rb +0 -6
  61. data/test/apps/rails-3-2/config/database.yml +0 -25
  62. data/test/apps/rails-3-2/config/environment.rb +0 -5
  63. data/test/apps/rails-3-2/config/environments/development.rb +0 -37
  64. data/test/apps/rails-3-2/config/environments/production.rb +0 -67
  65. data/test/apps/rails-3-2/config/environments/test.rb +0 -37
  66. data/test/apps/rails-3-2/config/initializers/backtrace_silencers.rb +0 -7
  67. data/test/apps/rails-3-2/config/initializers/inflections.rb +0 -15
  68. data/test/apps/rails-3-2/config/initializers/mime_types.rb +0 -5
  69. data/test/apps/rails-3-2/config/initializers/secret_token.rb +0 -7
  70. data/test/apps/rails-3-2/config/initializers/session_store.rb +0 -8
  71. data/test/apps/rails-3-2/config/initializers/wrap_parameters.rb +0 -14
  72. data/test/apps/rails-3-2/config/locales/en.yml +0 -5
  73. data/test/apps/rails-3-2/config/routes.rb +0 -60
  74. data/test/apps/rails-3-2/config/spring.rb +0 -7
  75. data/test/apps/rails-3-2/config.ru +0 -4
  76. data/test/apps/rails-3-2/db/migrate/20121109171227_create_posts.rb +0 -9
  77. data/test/apps/rails-3-2/db/schema.rb +0 -22
  78. data/test/apps/rails-3-2/db/seeds.rb +0 -7
  79. data/test/apps/rails-3-2/lib/assets/.gitkeep +0 -0
  80. data/test/apps/rails-3-2/lib/tasks/.gitkeep +0 -0
  81. data/test/apps/rails-3-2/log/.gitkeep +0 -0
  82. data/test/apps/rails-3-2/public/404.html +0 -26
  83. data/test/apps/rails-3-2/public/422.html +0 -26
  84. data/test/apps/rails-3-2/public/500.html +0 -25
  85. data/test/apps/rails-3-2/public/favicon.ico +0 -0
  86. data/test/apps/rails-3-2/public/index.html +0 -241
  87. data/test/apps/rails-3-2/public/robots.txt +0 -5
  88. data/test/apps/rails-3-2/script/rails +0 -6
  89. data/test/apps/rails-3-2/test/fixtures/.gitkeep +0 -0
  90. data/test/apps/rails-3-2/test/fixtures/posts.yml +0 -7
  91. data/test/apps/rails-3-2/test/functional/.gitkeep +0 -0
  92. data/test/apps/rails-3-2/test/functional/posts_controller_test.rb +0 -49
  93. data/test/apps/rails-3-2/test/integration/.gitkeep +0 -0
  94. data/test/apps/rails-3-2/test/performance/browsing_test.rb +0 -12
  95. data/test/apps/rails-3-2/test/test_helper.rb +0 -13
  96. data/test/apps/rails-3-2/test/unit/.gitkeep +0 -0
  97. data/test/apps/rails-3-2/test/unit/helpers/posts_helper_test.rb +0 -4
  98. data/test/apps/rails-3-2/test/unit/post_test.rb +0 -7
  99. data/test/apps/rails-3-2/vendor/assets/javascripts/.gitkeep +0 -0
  100. data/test/apps/rails-3-2/vendor/assets/stylesheets/.gitkeep +0 -0
  101. data/test/apps/rails-3-2/vendor/plugins/.gitkeep +0 -0
@@ -0,0 +1,34 @@
1
+ module Spring
2
+ module Commands
3
+ class Rake
4
+ class << self
5
+ attr_accessor :environment_matchers
6
+ end
7
+
8
+ self.environment_matchers = {
9
+ :default => "test",
10
+ /^test($|:)/ => "test"
11
+ }
12
+
13
+ def env(args)
14
+ # This is an adaption of the matching that Rake itself does.
15
+ # See: https://github.com/jimweirich/rake/blob/3754a7639b3f42c2347857a0878beb3523542aee/lib/rake/application.rb#L691-L692
16
+ if env = args.grep(/^(RAILS|RACK)_ENV=(.*)$/m).last
17
+ return env.split("=").last
18
+ end
19
+
20
+ self.class.environment_matchers.each do |matcher, environment|
21
+ return environment if matcher === (args.first || :default)
22
+ end
23
+
24
+ nil
25
+ end
26
+
27
+ def exec_name
28
+ "rake"
29
+ end
30
+ end
31
+
32
+ Spring.register_command "rake", Rake.new
33
+ end
34
+ end
@@ -1,6 +1,4 @@
1
- # If the config/spring.rb contains requires for commands from other gems,
2
- # then we need to be under bundler.
3
- require "bundler/setup"
1
+ require "spring/watcher"
4
2
 
5
3
  module Spring
6
4
  @commands = {}
@@ -21,203 +19,22 @@ module Spring
21
19
  commands.fetch name
22
20
  end
23
21
 
24
- module Commands
25
- class Command
26
- @preloads = []
22
+ require "spring/commands/rails"
23
+ require "spring/commands/rake"
27
24
 
28
- def self.preloads
29
- @preloads ||= superclass.preloads.dup
30
- end
31
-
32
- def self.preloads=(val)
33
- @preloads = val
34
- end
35
-
36
- def preloads
37
- self.class.preloads
38
- end
39
-
40
- def setup
41
- preload_files
42
- end
43
-
44
- private
45
-
46
- def preload_files
47
- preloads.each do |file|
48
- begin
49
- require file
50
- rescue LoadError => e
51
- $stderr.puts <<-MESSAGE
52
- The #{self.class} command tried to preload #{file} but could not find it.
53
- You can configure what to preload in your `config/spring.rb` with:
54
- #{self.class}.preloads = %w(files to preload)
55
- MESSAGE
56
- end
57
- end
58
- end
59
- end
60
-
61
- class TestUnit < Command
62
- preloads << "test_helper"
63
-
64
- def env(*)
65
- "test"
66
- end
67
-
68
- def setup
69
- $LOAD_PATH.unshift "test"
70
- super
71
- end
72
-
73
- def call(args)
74
- if args.size > 0
75
- ARGV.replace args
76
- path = File.expand_path(args.first)
77
-
78
- if File.directory?(path)
79
- Dir[File.join path, "**", "*_test.rb"].each { |f| require f }
80
- else
81
- require path
82
- end
83
- else
84
- $stderr.puts "you need to specify what test to run: spring test TEST_NAME"
85
- end
86
- end
87
-
88
- def description
89
- "Execute a Test::Unit test."
90
- end
91
- end
92
- Spring.register_command "testunit", TestUnit.new
93
-
94
- class RSpec < Command
95
- preloads << "spec_helper"
96
-
97
- def env(*)
98
- "test"
99
- end
100
-
101
- def setup
102
- $LOAD_PATH.unshift "spec"
103
- require 'rspec/core'
104
- ::RSpec::Core::Runner.disable_autorun!
105
- super
106
- end
107
-
108
- def call(args)
109
- $0 = "rspec"
110
- ::RSpec::Core::Runner.run(args)
111
- end
112
-
113
- def description
114
- "Execute an RSpec spec."
115
- end
116
- end
117
- Spring.register_command "rspec", RSpec.new
118
-
119
- class Cucumber < Command
120
- def env(*)
121
- "test"
122
- end
123
-
124
- def setup
125
- super
126
- require 'cucumber'
127
- end
128
-
129
- def call(args)
130
- ::Cucumber::Cli::Main.execute(args)
131
- end
132
-
133
- def description
134
- "Execute a Cucumber feature."
135
- end
136
- end
137
- Spring.register_command "cucumber", Cucumber.new
138
-
139
- class Rake < Command
140
- def setup
141
- super
142
- require "rake"
143
- end
144
-
145
- def call(args)
146
- ARGV.replace args
147
- ::Rake.application.run
148
- end
149
-
150
- def description
151
- "Run a rake task."
152
- end
153
- end
154
- Spring.register_command "rake", Rake.new
155
-
156
- class RailsConsole < Command
157
- def env(tail)
158
- tail.first if tail.first && !tail.first.index("-")
159
- end
160
-
161
- def setup
162
- require "rails/commands/console"
163
- end
164
-
165
- def call(args)
166
- ARGV.replace args
167
- ::Rails::Console.start(::Rails.application)
168
- end
169
-
170
- def description
171
- nil
172
- end
173
- end
174
- Spring.register_command "rails_console", RailsConsole.new
175
-
176
- class RailsGenerate < Command
177
- def setup
178
- super
179
- Rails.application.load_generators
180
- end
181
-
182
- def call(args)
183
- ARGV.replace args
184
- require "rails/commands/generate"
185
- end
186
-
187
- def description
188
- nil
189
- end
190
- end
191
- Spring.register_command "rails_generate", RailsGenerate.new
192
-
193
- class RailsRunner < Command
194
- def env(tail)
195
- previous_option = nil
196
- tail.reverse.each do |option|
197
- case option
198
- when /--environment=(\w+)/ then return $1
199
- when '-e' then return previous_option
200
- end
201
- previous_option = option
202
- end
203
- nil
204
- end
25
+ # Load custom commands, if any.
26
+ # needs to be at the end to allow modification of existing commands.
27
+ config = File.expand_path("~/.spring.rb")
28
+ require config if File.exist?(config)
205
29
 
206
- def call(args)
207
- Object.const_set(:APP_PATH, Rails.root.join('config/application'))
208
- ARGV.replace args
209
- require "rails/commands/runner"
210
- end
30
+ # If the config/spring.rb contains requires for commands from other gems,
31
+ # then we need to be under bundler.
32
+ require "bundler/setup"
211
33
 
212
- def description
213
- nil
214
- end
215
- end
216
- Spring.register_command "rails_runner", RailsRunner.new
34
+ Gem::Specification.map(&:name).grep(/^spring-commands-/).each do |command|
35
+ require command
217
36
  end
218
37
 
219
- # Load custom commands, if any.
220
- # needs to be at the end to allow modification of existing commands.
221
38
  config = File.expand_path("./config/spring.rb")
222
39
  require config if File.exist?(config)
223
40
  end
@@ -4,6 +4,10 @@ module Spring
4
4
  class << self
5
5
  attr_accessor :application_root
6
6
 
7
+ def gemfile
8
+ ENV['BUNDLE_GEMFILE'] || "Gemfile"
9
+ end
10
+
7
11
  def after_fork_callbacks
8
12
  @after_fork_callbacks ||= []
9
13
  end
@@ -12,7 +16,7 @@ module Spring
12
16
  after_fork_callbacks << block
13
17
  end
14
18
 
15
- def verify_environment!
19
+ def verify_environment
16
20
  application_root_path
17
21
  end
18
22
 
@@ -27,7 +31,7 @@ module Spring
27
31
  private
28
32
 
29
33
  def find_project_root(current_dir = Pathname.new(Dir.pwd))
30
- if current_dir.join("Gemfile").exist?
34
+ if current_dir.join(gemfile).exist?
31
35
  current_dir
32
36
  elsif current_dir.root?
33
37
  raise UnknownProject.new(Dir.pwd)
data/lib/spring/env.rb CHANGED
@@ -1,17 +1,25 @@
1
1
  require "pathname"
2
2
  require "fileutils"
3
+ require "digest/md5"
4
+ require "tmpdir"
3
5
 
4
6
  require "spring/version"
5
7
  require "spring/sid"
8
+ require "spring/configuration"
6
9
 
7
10
  module Spring
8
11
  IGNORE_SIGNALS = %w(INT QUIT)
9
12
 
10
13
  class Env
11
- attr_reader :root
14
+ attr_reader :log_file
12
15
 
13
16
  def initialize(root = nil)
14
- @root = root || Pathname.new(File.expand_path('.'))
17
+ @root = root
18
+ @log_file = File.open(ENV["SPRING_LOG"] || "/dev/null", "a")
19
+ end
20
+
21
+ def root
22
+ @root ||= Spring.application_root_path
15
23
  end
16
24
 
17
25
  def version
@@ -19,13 +27,17 @@ module Spring
19
27
  end
20
28
 
21
29
  def tmp_path
22
- path = default_tmp_path
30
+ path = Pathname.new(Dir.tmpdir + "/spring")
23
31
  FileUtils.mkdir_p(path) unless path.exist?
24
32
  path
25
33
  end
26
34
 
35
+ def application_id
36
+ Digest::MD5.hexdigest(root.to_s)
37
+ end
38
+
27
39
  def socket_path
28
- tmp_path.join("spring")
40
+ tmp_path.join(application_id)
29
41
  end
30
42
 
31
43
  def socket_name
@@ -33,7 +45,7 @@ module Spring
33
45
  end
34
46
 
35
47
  def pidfile_path
36
- tmp_path.join("spring.pid")
48
+ tmp_path.join("#{application_id}.pid")
37
49
  end
38
50
 
39
51
  def pid
@@ -48,12 +60,10 @@ module Spring
48
60
  end
49
61
 
50
62
  def server_running?
51
- if pidfile_path.exist?
52
- pidfile = pidfile_path.open('r')
53
- !pidfile.flock(File::LOCK_EX | File::LOCK_NB)
54
- else
55
- false
56
- end
63
+ pidfile = pidfile_path.open('r')
64
+ !pidfile.flock(File::LOCK_EX | File::LOCK_NB)
65
+ rescue Errno::ENOENT
66
+ false
57
67
  ensure
58
68
  if pidfile
59
69
  pidfile.flock(File::LOCK_UN)
@@ -61,14 +71,13 @@ module Spring
61
71
  end
62
72
  end
63
73
 
64
- private
74
+ def bundle_mtime
75
+ [Bundler.default_lockfile, Bundler.default_gemfile].select(&:exist?).map(&:mtime).max
76
+ end
65
77
 
66
- def default_tmp_path
67
- if ENV['SPRING_TMP_PATH']
68
- Pathname.new(ENV['SPRING_TMP_PATH'])
69
- else
70
- root.join('tmp/spring')
71
- end
78
+ def log(message)
79
+ log_file.puts "[#{Time.now}] #{message}"
80
+ log_file.flush
72
81
  end
73
82
  end
74
83
  end
data/lib/spring/errors.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Spring
2
2
  class ClientError < StandardError; end
3
3
 
4
- class UnknownProject < ClientError
4
+ class UnknownProject < StandardError
5
5
  attr_reader :current_dir
6
6
 
7
7
  def initialize(current_dir)