spring 0.9.1 → 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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/CHANGELOG.md +51 -0
- data/README.md +118 -53
- data/bin/spring +1 -0
- data/lib/spring/application/boot.rb +16 -0
- data/lib/spring/application.rb +131 -64
- data/lib/spring/application_manager.rb +51 -40
- data/lib/spring/binstub.rb +13 -0
- data/lib/spring/boot.rb +8 -0
- data/lib/spring/client/binstub.rb +150 -39
- data/lib/spring/client/help.rb +4 -12
- data/lib/spring/client/rails.rb +1 -3
- data/lib/spring/client/version.rb +11 -0
- data/lib/spring/client.rb +8 -5
- data/lib/spring/command_wrapper.rb +86 -0
- data/lib/spring/commands/rails.rb +1 -2
- data/lib/spring/commands/rake.rb +0 -4
- data/lib/spring/commands.rb +3 -2
- data/lib/spring/configuration.rb +11 -2
- data/lib/spring/env.rb +24 -22
- data/lib/spring/errors.rb +0 -14
- data/lib/spring/server.rb +10 -34
- data/lib/spring/version.rb +1 -1
- data/lib/spring/watcher/abstract.rb +7 -8
- data/spring.gemspec +2 -1
- data/test/acceptance/app_test.rb +178 -345
- data/test/acceptance/helper.rb +329 -0
- data/test/unit/client/version_test.rb +14 -0
- data/test/unit/watcher_test.rb +12 -8
- metadata +14 -4
data/lib/spring/env.rb
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
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 :
|
|
14
|
+
attr_reader :log_file
|
|
12
15
|
|
|
13
16
|
def initialize(root = nil)
|
|
14
|
-
@root
|
|
15
|
-
@
|
|
17
|
+
@root = root
|
|
18
|
+
@project_root = root
|
|
19
|
+
@log_file = File.open(ENV["SPRING_LOG"] || "/dev/null", "a")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def root
|
|
23
|
+
@root ||= Spring.application_root_path
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def project_root
|
|
27
|
+
@project_root ||= Spring.project_root_path
|
|
16
28
|
end
|
|
17
29
|
|
|
18
30
|
def version
|
|
@@ -20,13 +32,17 @@ module Spring
|
|
|
20
32
|
end
|
|
21
33
|
|
|
22
34
|
def tmp_path
|
|
23
|
-
path =
|
|
35
|
+
path = Pathname.new(Dir.tmpdir + "/spring")
|
|
24
36
|
FileUtils.mkdir_p(path) unless path.exist?
|
|
25
37
|
path
|
|
26
38
|
end
|
|
27
39
|
|
|
40
|
+
def application_id
|
|
41
|
+
Digest::MD5.hexdigest(project_root.to_s)
|
|
42
|
+
end
|
|
43
|
+
|
|
28
44
|
def socket_path
|
|
29
|
-
tmp_path.join(
|
|
45
|
+
tmp_path.join(application_id)
|
|
30
46
|
end
|
|
31
47
|
|
|
32
48
|
def socket_name
|
|
@@ -34,7 +50,7 @@ module Spring
|
|
|
34
50
|
end
|
|
35
51
|
|
|
36
52
|
def pidfile_path
|
|
37
|
-
tmp_path.join("
|
|
53
|
+
tmp_path.join("#{application_id}.pid")
|
|
38
54
|
end
|
|
39
55
|
|
|
40
56
|
def pid
|
|
@@ -49,7 +65,7 @@ module Spring
|
|
|
49
65
|
end
|
|
50
66
|
|
|
51
67
|
def server_running?
|
|
52
|
-
pidfile = pidfile_path.open('r')
|
|
68
|
+
pidfile = pidfile_path.open('r+')
|
|
53
69
|
!pidfile.flock(File::LOCK_EX | File::LOCK_NB)
|
|
54
70
|
rescue Errno::ENOENT
|
|
55
71
|
false
|
|
@@ -60,23 +76,9 @@ module Spring
|
|
|
60
76
|
end
|
|
61
77
|
end
|
|
62
78
|
|
|
63
|
-
def bundle_mtime
|
|
64
|
-
[Bundler.default_lockfile, Bundler.default_gemfile].select(&:exist?).map(&:mtime).max
|
|
65
|
-
end
|
|
66
|
-
|
|
67
79
|
def log(message)
|
|
68
|
-
log_file.puts "[#{Time.now}] #{message}"
|
|
80
|
+
log_file.puts "[#{Time.now}] [#{Process.pid}] #{message}"
|
|
69
81
|
log_file.flush
|
|
70
82
|
end
|
|
71
|
-
|
|
72
|
-
private
|
|
73
|
-
|
|
74
|
-
def default_tmp_path
|
|
75
|
-
if ENV['SPRING_TMP_PATH']
|
|
76
|
-
Pathname.new(ENV['SPRING_TMP_PATH'])
|
|
77
|
-
else
|
|
78
|
-
root.join('tmp/spring')
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
83
|
end
|
|
82
84
|
end
|
data/lib/spring/errors.rb
CHANGED
|
@@ -15,20 +15,6 @@ module Spring
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
class TmpUnwritable < StandardError
|
|
19
|
-
attr_reader :tmp_path
|
|
20
|
-
|
|
21
|
-
def initialize(tmp_path)
|
|
22
|
-
@tmp_path = tmp_path
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def message
|
|
26
|
-
"Spring is unable to create a socket file at #{tmp_path}. You may need to " \
|
|
27
|
-
"set the SPRING_TMP_PATH environment variable to use a different path. See " \
|
|
28
|
-
"the documentation for details."
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
18
|
class MissingApplication < ClientError
|
|
33
19
|
attr_reader :project_root
|
|
34
20
|
|
data/lib/spring/server.rb
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
module Spring
|
|
2
|
+
ORIGINAL_ENV = ENV.to_hash
|
|
3
|
+
end
|
|
3
4
|
|
|
4
|
-
require "spring/
|
|
5
|
-
require "spring/env"
|
|
5
|
+
require "spring/boot"
|
|
6
6
|
require "spring/application_manager"
|
|
7
|
-
require "spring/process_title_updater"
|
|
8
|
-
require "spring/json"
|
|
9
7
|
|
|
10
|
-
# Must be last, as it requires bundler/setup
|
|
8
|
+
# Must be last, as it requires bundler/setup, which alters the load path
|
|
11
9
|
require "spring/commands"
|
|
12
10
|
|
|
13
|
-
# readline must be required before we setpgid, otherwise the require may hang,
|
|
14
|
-
# if readline has been built against libedit. See issue #70.
|
|
15
|
-
require "readline"
|
|
16
|
-
|
|
17
11
|
module Spring
|
|
18
12
|
class Server
|
|
19
13
|
def self.boot
|
|
@@ -24,7 +18,7 @@ module Spring
|
|
|
24
18
|
|
|
25
19
|
def initialize(env = Env.new)
|
|
26
20
|
@env = env
|
|
27
|
-
@applications = Hash.new { |h, k| h[k] = ApplicationManager.new(
|
|
21
|
+
@applications = Hash.new { |h, k| h[k] = ApplicationManager.new(k) }
|
|
28
22
|
@pidfile = env.pidfile_path.open('a')
|
|
29
23
|
@mutex = Mutex.new
|
|
30
24
|
end
|
|
@@ -41,16 +35,12 @@ module Spring
|
|
|
41
35
|
ignore_signals
|
|
42
36
|
set_exit_hook
|
|
43
37
|
set_process_title
|
|
44
|
-
watch_bundle
|
|
45
38
|
start_server
|
|
46
39
|
end
|
|
47
40
|
|
|
48
41
|
def start_server
|
|
49
42
|
server = UNIXServer.open(env.socket_name)
|
|
50
43
|
log "started on #{env.socket_name}"
|
|
51
|
-
rescue Errno::EPERM
|
|
52
|
-
raise TmpUnwritable.new(env.tmp_path)
|
|
53
|
-
else
|
|
54
44
|
loop { serve server.accept }
|
|
55
45
|
end
|
|
56
46
|
|
|
@@ -78,13 +68,7 @@ module Spring
|
|
|
78
68
|
end
|
|
79
69
|
|
|
80
70
|
def rails_env_for(args, default_rails_env)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if command.respond_to?(:env)
|
|
84
|
-
env = command.env(args.drop(1))
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
env || default_rails_env
|
|
71
|
+
Spring.command(args.first).env(args.drop(1)) || default_rails_env
|
|
88
72
|
end
|
|
89
73
|
|
|
90
74
|
# Boot the server into the process group of the current session.
|
|
@@ -97,7 +81,7 @@ module Spring
|
|
|
97
81
|
# Ignore SIGINT and SIGQUIT otherwise the user typing ^C or ^\ on the command line
|
|
98
82
|
# will kill the server/application.
|
|
99
83
|
def ignore_signals
|
|
100
|
-
IGNORE_SIGNALS.each { |sig| trap(sig,
|
|
84
|
+
IGNORE_SIGNALS.each { |sig| trap(sig, "IGNORE") }
|
|
101
85
|
end
|
|
102
86
|
|
|
103
87
|
def set_exit_hook
|
|
@@ -108,13 +92,13 @@ module Spring
|
|
|
108
92
|
end
|
|
109
93
|
|
|
110
94
|
def shutdown
|
|
111
|
-
@applications.values.each(&:stop)
|
|
112
|
-
|
|
113
95
|
[env.socket_path, env.pidfile_path].each do |path|
|
|
114
96
|
if path.exist?
|
|
115
97
|
path.unlink rescue nil
|
|
116
98
|
end
|
|
117
99
|
end
|
|
100
|
+
|
|
101
|
+
@applications.values.map { |a| Thread.new { a.stop } }.map(&:join)
|
|
118
102
|
end
|
|
119
103
|
|
|
120
104
|
def write_pidfile
|
|
@@ -140,13 +124,5 @@ module Spring
|
|
|
140
124
|
"spring server | #{env.app_name} | started #{distance} ago"
|
|
141
125
|
}
|
|
142
126
|
end
|
|
143
|
-
|
|
144
|
-
def watch_bundle
|
|
145
|
-
@bundle_mtime = env.bundle_mtime
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def application_starting
|
|
149
|
-
@mutex.synchronize { exit if env.bundle_mtime != @bundle_mtime }
|
|
150
|
-
end
|
|
151
127
|
end
|
|
152
128
|
end
|
data/lib/spring/version.rb
CHANGED
|
@@ -22,7 +22,7 @@ module Spring
|
|
|
22
22
|
@files = Set.new
|
|
23
23
|
@directories = Set.new
|
|
24
24
|
@stale = false
|
|
25
|
-
@
|
|
25
|
+
@listeners = []
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def add(*items)
|
|
@@ -55,15 +55,14 @@ module Spring
|
|
|
55
55
|
@stale
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
-
def
|
|
59
|
-
@
|
|
60
|
-
@io_listener.write "." if @io_listener
|
|
58
|
+
def on_stale(&block)
|
|
59
|
+
@listeners << block
|
|
61
60
|
end
|
|
62
61
|
|
|
63
|
-
def
|
|
64
|
-
|
|
65
|
-
@
|
|
66
|
-
|
|
62
|
+
def mark_stale
|
|
63
|
+
return if stale?
|
|
64
|
+
@stale = true
|
|
65
|
+
@listeners.each(&:call)
|
|
67
66
|
end
|
|
68
67
|
|
|
69
68
|
def restart
|
data/spring.gemspec
CHANGED
|
@@ -10,7 +10,8 @@ Gem::Specification.new do |gem|
|
|
|
10
10
|
gem.email = ["j@jonathanleighton.com"]
|
|
11
11
|
gem.description = %q{Rails application preloader}
|
|
12
12
|
gem.summary = %q{Rails application preloader}
|
|
13
|
-
gem.homepage = "http://github.com/
|
|
13
|
+
gem.homepage = "http://github.com/rails/spring"
|
|
14
|
+
gem.license = "MIT"
|
|
14
15
|
|
|
15
16
|
gem.files = `git ls-files`.split($/)
|
|
16
17
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|