giga-safe-hub 0.0.1
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.
Potentially problematic release.
This version of giga-safe-hub might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/giga-safe-hub.gemspec +12 -0
- data/spring-4.7.0/LICENSE.txt +23 -0
- data/spring-4.7.0/README.md +467 -0
- data/spring-4.7.0/bin/spring +49 -0
- data/spring-4.7.0/lib/spring/application/boot.rb +25 -0
- data/spring-4.7.0/lib/spring/application.rb +597 -0
- data/spring-4.7.0/lib/spring/application_manager.rb +145 -0
- data/spring-4.7.0/lib/spring/binstub.rb +13 -0
- data/spring-4.7.0/lib/spring/boot.rb +10 -0
- data/spring-4.7.0/lib/spring/client/binstub.rb +190 -0
- data/spring-4.7.0/lib/spring/client/command.rb +18 -0
- data/spring-4.7.0/lib/spring/client/help.rb +62 -0
- data/spring-4.7.0/lib/spring/client/rails.rb +34 -0
- data/spring-4.7.0/lib/spring/client/run.rb +297 -0
- data/spring-4.7.0/lib/spring/client/server.rb +18 -0
- data/spring-4.7.0/lib/spring/client/status.rb +30 -0
- data/spring-4.7.0/lib/spring/client/stop.rb +22 -0
- data/spring-4.7.0/lib/spring/client/version.rb +11 -0
- data/spring-4.7.0/lib/spring/client.rb +48 -0
- data/spring-4.7.0/lib/spring/command_wrapper.rb +82 -0
- data/spring-4.7.0/lib/spring/commands/rails.rb +112 -0
- data/spring-4.7.0/lib/spring/commands/rake.rb +30 -0
- data/spring-4.7.0/lib/spring/commands.rb +57 -0
- data/spring-4.7.0/lib/spring/configuration.rb +99 -0
- data/spring-4.7.0/lib/spring/env.rb +115 -0
- data/spring-4.7.0/lib/spring/errors.rb +36 -0
- data/spring-4.7.0/lib/spring/failsafe_thread.rb +14 -0
- data/spring-4.7.0/lib/spring/json.rb +623 -0
- data/spring-4.7.0/lib/spring/process_title_updater.rb +65 -0
- data/spring-4.7.0/lib/spring/server.rb +162 -0
- data/spring-4.7.0/lib/spring/version.rb +3 -0
- data/spring-4.7.0/lib/spring/watcher/abstract.rb +117 -0
- data/spring-4.7.0/lib/spring/watcher/polling.rb +98 -0
- data/spring-4.7.0/lib/spring/watcher.rb +30 -0
- metadata +75 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
require "rbconfig"
|
|
2
|
+
require "socket"
|
|
3
|
+
require "bundler"
|
|
4
|
+
|
|
5
|
+
module Spring
|
|
6
|
+
module Client
|
|
7
|
+
class Run < Command
|
|
8
|
+
FORWARDED_SIGNALS = %w(INT QUIT USR1 USR2 INFO WINCH) & Signal.list.keys
|
|
9
|
+
ServerReadTimeout = Class.new(StandardError)
|
|
10
|
+
|
|
11
|
+
attr_reader :server
|
|
12
|
+
|
|
13
|
+
def initialize(args)
|
|
14
|
+
super
|
|
15
|
+
|
|
16
|
+
@signal_queue = []
|
|
17
|
+
@server_booted = false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def log(message)
|
|
21
|
+
env.log "[client] #{message}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def connect
|
|
25
|
+
@server = UNIXSocket.open(env.socket_name)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def call
|
|
29
|
+
begin
|
|
30
|
+
connect
|
|
31
|
+
rescue Errno::ENOENT, Errno::ECONNRESET, Errno::ECONNREFUSED
|
|
32
|
+
cold_run
|
|
33
|
+
else
|
|
34
|
+
warm_run
|
|
35
|
+
end
|
|
36
|
+
ensure
|
|
37
|
+
server.close if server
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def warm_run
|
|
41
|
+
run
|
|
42
|
+
rescue CommandNotFound
|
|
43
|
+
require "spring/commands"
|
|
44
|
+
|
|
45
|
+
if Spring.command?(args.first)
|
|
46
|
+
# Command installed since Spring started
|
|
47
|
+
stop_server
|
|
48
|
+
cold_run
|
|
49
|
+
else
|
|
50
|
+
raise
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def cold_run
|
|
55
|
+
boot_server
|
|
56
|
+
connect
|
|
57
|
+
run
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def run
|
|
61
|
+
verify_server_version
|
|
62
|
+
|
|
63
|
+
application, client = UNIXSocket.pair
|
|
64
|
+
|
|
65
|
+
queue_signals
|
|
66
|
+
connect_to_application(client)
|
|
67
|
+
run_command(client, application)
|
|
68
|
+
rescue Errno::ECONNRESET
|
|
69
|
+
exit 1
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def boot_server
|
|
73
|
+
env.socket_path.unlink if env.socket_path.exist?
|
|
74
|
+
|
|
75
|
+
pid = Process.spawn(server_process_env, env.server_command, out: File::NULL)
|
|
76
|
+
timeout = Time.now + Spring.boot_timeout
|
|
77
|
+
|
|
78
|
+
@server_booted = true
|
|
79
|
+
|
|
80
|
+
until env.socket_path.exist?
|
|
81
|
+
_, status = Process.waitpid2(pid, Process::WNOHANG)
|
|
82
|
+
|
|
83
|
+
if status
|
|
84
|
+
exit status.exitstatus
|
|
85
|
+
elsif Time.now > timeout
|
|
86
|
+
$stderr.puts "Starting Spring server with `#{env.server_command}` " \
|
|
87
|
+
"timed out after #{Spring.boot_timeout} seconds"
|
|
88
|
+
exit 1
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
sleep 0.1
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def server_booted?
|
|
96
|
+
@server_booted
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def gem_env
|
|
100
|
+
bundle = Bundler.bundle_path.to_s
|
|
101
|
+
paths = Gem.path + ENV["GEM_PATH"].to_s.split(File::PATH_SEPARATOR)
|
|
102
|
+
|
|
103
|
+
{
|
|
104
|
+
"GEM_PATH" => [bundle, *paths].uniq.join(File::PATH_SEPARATOR),
|
|
105
|
+
"GEM_HOME" => bundle
|
|
106
|
+
}
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def reset_env
|
|
110
|
+
ENV.slice(*Spring.reset_on_env)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def server_process_env
|
|
114
|
+
reset_env.merge(gem_env)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def stop_server
|
|
118
|
+
server.close
|
|
119
|
+
@server = nil
|
|
120
|
+
env.stop
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def verify_server_version
|
|
124
|
+
begin
|
|
125
|
+
line = read_server_line
|
|
126
|
+
rescue ServerReadTimeout
|
|
127
|
+
if waiting_for_server_boot?
|
|
128
|
+
begin
|
|
129
|
+
# Try again, but with same timeout as booting, as server might still be booting
|
|
130
|
+
# from another client starting it.
|
|
131
|
+
line = read_server_line(Spring.boot_timeout)
|
|
132
|
+
rescue ServerReadTimeout
|
|
133
|
+
reboot_or_raise_connection_error
|
|
134
|
+
return
|
|
135
|
+
end
|
|
136
|
+
else
|
|
137
|
+
reboot_or_raise_connection_error
|
|
138
|
+
return
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if line.nil?
|
|
143
|
+
reboot_or_raise_connection_error
|
|
144
|
+
return
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
server_version = line.chomp
|
|
148
|
+
if server_version != env.version
|
|
149
|
+
$stderr.puts "There is a version mismatch between the Spring client " \
|
|
150
|
+
"(#{env.version}) and the server (#{server_version})."
|
|
151
|
+
|
|
152
|
+
if server_booted?
|
|
153
|
+
$stderr.puts "We already tried to reboot the server, but the mismatch is still present."
|
|
154
|
+
exit 1
|
|
155
|
+
else
|
|
156
|
+
$stderr.puts "Restarting to resolve."
|
|
157
|
+
stop_server
|
|
158
|
+
cold_run
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def read_server_line(timeout = Spring.connect_timeout)
|
|
164
|
+
raise ServerReadTimeout if IO.select([server], [], [], timeout).nil?
|
|
165
|
+
|
|
166
|
+
server.gets
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def waiting_for_server_boot?
|
|
170
|
+
!server_booted? && env.server_running?
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def reboot_or_raise_connection_error
|
|
174
|
+
if server_booted?
|
|
175
|
+
raise "Error connecting to Spring server"
|
|
176
|
+
else
|
|
177
|
+
stop_server
|
|
178
|
+
cold_run
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def connect_to_application(client)
|
|
183
|
+
server.send_io client
|
|
184
|
+
send_json server, "args" => args, "default_rails_env" => default_rails_env, "spawn_env" => spawn_env, "reset_env" => reset_env
|
|
185
|
+
|
|
186
|
+
if IO.select([server], [], [], Spring.connect_timeout)
|
|
187
|
+
server.gets or raise CommandNotFound
|
|
188
|
+
else
|
|
189
|
+
raise "Error connecting to Spring server"
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def run_command(client, application)
|
|
194
|
+
application.send_io STDOUT
|
|
195
|
+
application.send_io STDERR
|
|
196
|
+
application.send_io STDIN
|
|
197
|
+
|
|
198
|
+
log "waiting for the application to be preloaded"
|
|
199
|
+
preload_status = application.gets
|
|
200
|
+
preload_status = preload_status.chomp if preload_status
|
|
201
|
+
log "app preload status: #{preload_status}"
|
|
202
|
+
exit 1 if preload_status == "1"
|
|
203
|
+
|
|
204
|
+
log "sending command"
|
|
205
|
+
send_json application, "args" => args, "env" => ENV.to_hash
|
|
206
|
+
|
|
207
|
+
pid = server.gets
|
|
208
|
+
pid = pid.chomp if pid
|
|
209
|
+
|
|
210
|
+
# We must not close the client socket until we are sure that the application has
|
|
211
|
+
# received the FD. Otherwise the FD can end up getting closed while it's in the server
|
|
212
|
+
# socket buffer on OS X. This doesn't happen on Linux.
|
|
213
|
+
client.close
|
|
214
|
+
|
|
215
|
+
if pid && !pid.empty?
|
|
216
|
+
log "got pid: #{pid}"
|
|
217
|
+
|
|
218
|
+
suspend_resume_on_tstp_cont(pid)
|
|
219
|
+
|
|
220
|
+
forward_signals(application)
|
|
221
|
+
status = application.read
|
|
222
|
+
log "got exit status #{status.inspect}"
|
|
223
|
+
|
|
224
|
+
# Status should always be an integer. If it is empty, something unexpected must have happened to the server.
|
|
225
|
+
if status.to_s.strip.empty?
|
|
226
|
+
log "unexpected empty exit status, app crashed?"
|
|
227
|
+
exit 1
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
exit status.to_i
|
|
231
|
+
else
|
|
232
|
+
log "got no pid"
|
|
233
|
+
exit 1
|
|
234
|
+
end
|
|
235
|
+
ensure
|
|
236
|
+
application.close
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def queue_signals
|
|
240
|
+
FORWARDED_SIGNALS.each do |sig|
|
|
241
|
+
trap(sig) { @signal_queue << sig }
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def suspend_resume_on_tstp_cont(pid)
|
|
246
|
+
trap("TSTP") {
|
|
247
|
+
log "suspended"
|
|
248
|
+
Process.kill("STOP", pid.to_i)
|
|
249
|
+
Process.kill("STOP", Process.pid)
|
|
250
|
+
}
|
|
251
|
+
trap("CONT") {
|
|
252
|
+
log "resumed"
|
|
253
|
+
Process.kill("CONT", pid.to_i)
|
|
254
|
+
}
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def forward_signals(application)
|
|
258
|
+
@signal_queue.each { |sig| kill sig, application }
|
|
259
|
+
|
|
260
|
+
FORWARDED_SIGNALS.each do |sig|
|
|
261
|
+
trap(sig) { forward_signal sig, application }
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def forward_signal(sig, application)
|
|
266
|
+
if kill(sig, application) != 0
|
|
267
|
+
# If the application process is gone, then don't block the
|
|
268
|
+
# signal on this process.
|
|
269
|
+
trap(sig, 'DEFAULT')
|
|
270
|
+
Process.kill(sig, Process.pid)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def kill(sig, application)
|
|
275
|
+
application.puts(sig)
|
|
276
|
+
application.gets.to_i
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def send_json(socket, data)
|
|
280
|
+
data = JSON.dump(data)
|
|
281
|
+
|
|
282
|
+
socket.puts data.bytesize
|
|
283
|
+
socket.write data
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def default_rails_env
|
|
287
|
+
ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def spawn_env
|
|
291
|
+
Spring.spawn_on_env.to_h do |key|
|
|
292
|
+
[key, ENV[key]]
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Spring
|
|
2
|
+
module Client
|
|
3
|
+
class Server < Command
|
|
4
|
+
def self.description
|
|
5
|
+
"Explicitly start a Spring server in the foreground"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def call
|
|
9
|
+
require "spring/server"
|
|
10
|
+
Spring::Server.boot(foreground: foreground?)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def foreground?
|
|
14
|
+
!args.include?("--background")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Spring
|
|
2
|
+
module Client
|
|
3
|
+
class Status < Command
|
|
4
|
+
def self.description
|
|
5
|
+
"Show current status."
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def call
|
|
9
|
+
if env.server_running?
|
|
10
|
+
puts "Spring is running:"
|
|
11
|
+
puts
|
|
12
|
+
print_process env.pid
|
|
13
|
+
application_pids.each { |pid| print_process pid }
|
|
14
|
+
else
|
|
15
|
+
puts "Spring is not running."
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def print_process(pid)
|
|
20
|
+
puts `ps -p #{pid} -o pid= -o command=`
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def application_pids
|
|
24
|
+
candidates = `ps -ax -o ppid= -o pid=`.lines
|
|
25
|
+
candidates.select { |l| l =~ /^(\s+)?#{env.pid} / }
|
|
26
|
+
.map { |l| l.split(" ").last }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require "spring/version"
|
|
2
|
+
|
|
3
|
+
module Spring
|
|
4
|
+
module Client
|
|
5
|
+
class Stop < Command
|
|
6
|
+
def self.description
|
|
7
|
+
"Stop all Spring processes for this project."
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call
|
|
11
|
+
case env.stop
|
|
12
|
+
when :stopped
|
|
13
|
+
puts "Spring stopped."
|
|
14
|
+
when :killed
|
|
15
|
+
$stderr.puts "Spring did not stop; killing forcibly."
|
|
16
|
+
when :not_running
|
|
17
|
+
puts "Spring is not running"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require "spring/errors"
|
|
2
|
+
require "spring/json"
|
|
3
|
+
|
|
4
|
+
require "spring/client/command"
|
|
5
|
+
require "spring/client/run"
|
|
6
|
+
require "spring/client/help"
|
|
7
|
+
require "spring/client/binstub"
|
|
8
|
+
require "spring/client/stop"
|
|
9
|
+
require "spring/client/status"
|
|
10
|
+
require "spring/client/rails"
|
|
11
|
+
require "spring/client/version"
|
|
12
|
+
require "spring/client/server"
|
|
13
|
+
|
|
14
|
+
module Spring
|
|
15
|
+
module Client
|
|
16
|
+
COMMANDS = {
|
|
17
|
+
"help" => Client::Help,
|
|
18
|
+
"-h" => Client::Help,
|
|
19
|
+
"--help" => Client::Help,
|
|
20
|
+
"binstub" => Client::Binstub,
|
|
21
|
+
"stop" => Client::Stop,
|
|
22
|
+
"status" => Client::Status,
|
|
23
|
+
"rails" => Client::Rails,
|
|
24
|
+
"-v" => Client::Version,
|
|
25
|
+
"--version" => Client::Version,
|
|
26
|
+
"server" => Client::Server,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
def self.run(args)
|
|
30
|
+
command_for(args.first).call(args)
|
|
31
|
+
rescue CommandNotFound
|
|
32
|
+
Client::Help.call(args)
|
|
33
|
+
rescue ClientError => e
|
|
34
|
+
$stderr.puts e.message
|
|
35
|
+
exit 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.command_for(name)
|
|
39
|
+
COMMANDS[name] || Client::Run
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# allow users to add hooks that do not run in the server
|
|
45
|
+
# or modify start/stop
|
|
46
|
+
if File.exist?("config/spring_client.rb")
|
|
47
|
+
require "./config/spring_client.rb"
|
|
48
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require "spring/configuration"
|
|
2
|
+
|
|
3
|
+
module Spring
|
|
4
|
+
class CommandWrapper
|
|
5
|
+
attr_reader :name, :command
|
|
6
|
+
|
|
7
|
+
def initialize(name, command = nil)
|
|
8
|
+
@name = name
|
|
9
|
+
@command = command
|
|
10
|
+
@setup = false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def description
|
|
14
|
+
if command.respond_to?(:description)
|
|
15
|
+
command.description
|
|
16
|
+
else
|
|
17
|
+
"Runs the #{name} command"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def setup?
|
|
22
|
+
@setup
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def setup
|
|
26
|
+
if !setup? && command.respond_to?(:setup)
|
|
27
|
+
command.setup
|
|
28
|
+
@setup = true
|
|
29
|
+
return true
|
|
30
|
+
else
|
|
31
|
+
@setup = true
|
|
32
|
+
return false
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def call
|
|
37
|
+
if command.respond_to?(:call)
|
|
38
|
+
command.call
|
|
39
|
+
else
|
|
40
|
+
load exec
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def gem_name
|
|
45
|
+
if command.respond_to?(:gem_name)
|
|
46
|
+
command.gem_name
|
|
47
|
+
else
|
|
48
|
+
exec_name
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def exec_name
|
|
53
|
+
if command.respond_to?(:exec_name)
|
|
54
|
+
command.exec_name
|
|
55
|
+
else
|
|
56
|
+
name
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def binstub
|
|
61
|
+
Spring.application_root_path.join(binstub_name)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def binstub_name
|
|
65
|
+
"bin/#{name}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def exec
|
|
69
|
+
if binstub.exist?
|
|
70
|
+
binstub.to_s
|
|
71
|
+
else
|
|
72
|
+
Gem.bin_path(gem_name, exec_name)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def env(args)
|
|
77
|
+
if command.respond_to?(:env)
|
|
78
|
+
command.env(args)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module Spring
|
|
2
|
+
module Commands
|
|
3
|
+
class Rails
|
|
4
|
+
def call
|
|
5
|
+
ARGV.unshift command_name
|
|
6
|
+
load Dir.glob(::Rails.root.join("{bin,script}/rails")).first
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def description
|
|
10
|
+
nil
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class RailsConsole < Rails
|
|
15
|
+
def env(args)
|
|
16
|
+
return args.first if args.first && !args.first.index("-")
|
|
17
|
+
|
|
18
|
+
environment = nil
|
|
19
|
+
|
|
20
|
+
args.each.with_index do |arg, i|
|
|
21
|
+
if arg =~ /--environment=(\w+)/
|
|
22
|
+
environment = $1
|
|
23
|
+
elsif i > 0 && args[i - 1] == "-e"
|
|
24
|
+
environment = arg
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
environment
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def command_name
|
|
32
|
+
"console"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class RailsGenerate < Rails
|
|
37
|
+
def command_name
|
|
38
|
+
"generate"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class RailsDestroy < Rails
|
|
43
|
+
def command_name
|
|
44
|
+
"destroy"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class RailsRunner < Rails
|
|
49
|
+
def call
|
|
50
|
+
ARGV.replace extract_environment(ARGV).first
|
|
51
|
+
super
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def env(args)
|
|
55
|
+
extract_environment(args).last
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def command_name
|
|
59
|
+
"runner"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def extract_environment(args)
|
|
63
|
+
environment = nil
|
|
64
|
+
|
|
65
|
+
args = args.select.with_index { |arg, i|
|
|
66
|
+
case arg
|
|
67
|
+
when "-e"
|
|
68
|
+
false
|
|
69
|
+
when /--environment=(\w+)/
|
|
70
|
+
environment = $1
|
|
71
|
+
false
|
|
72
|
+
else
|
|
73
|
+
if i > 0 && args[i - 1] == "-e"
|
|
74
|
+
environment = arg
|
|
75
|
+
false
|
|
76
|
+
else
|
|
77
|
+
true
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
[args, environment]
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class RailsTest < Rails
|
|
87
|
+
def env(args)
|
|
88
|
+
environment = "test"
|
|
89
|
+
|
|
90
|
+
args.each.with_index do |arg, i|
|
|
91
|
+
if arg =~ /--environment=(\w+)/
|
|
92
|
+
environment = $1
|
|
93
|
+
elsif i > 0 && args[i - 1] == "-e"
|
|
94
|
+
environment = arg
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
environment
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def command_name
|
|
102
|
+
"test"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
Spring.register_command "rails_console", RailsConsole.new
|
|
107
|
+
Spring.register_command "rails_generate", RailsGenerate.new
|
|
108
|
+
Spring.register_command "rails_destroy", RailsDestroy.new
|
|
109
|
+
Spring.register_command "rails_runner", RailsRunner.new
|
|
110
|
+
Spring.register_command "rails_test", RailsTest.new
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
end
|
|
27
|
+
|
|
28
|
+
Spring.register_command "rake", Rake.new
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require "spring/watcher"
|
|
2
|
+
require "spring/command_wrapper"
|
|
3
|
+
|
|
4
|
+
module Spring
|
|
5
|
+
@commands = {}
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
attr_reader :commands
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.register_command(name, command = nil)
|
|
12
|
+
commands[name] = CommandWrapper.new(name, command)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.command?(name)
|
|
16
|
+
commands.include? name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.command(name)
|
|
20
|
+
commands.fetch name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
require "spring/commands/rails"
|
|
24
|
+
require "spring/commands/rake"
|
|
25
|
+
|
|
26
|
+
# Load custom commands, if any.
|
|
27
|
+
# needs to be at the end to allow modification of existing commands.
|
|
28
|
+
config = File.expand_path("~/.spring.rb")
|
|
29
|
+
require config if File.exist?(config)
|
|
30
|
+
|
|
31
|
+
# We force the TTY so bundler doesn't show a backtrace in case gems are missing.
|
|
32
|
+
old_env = ENV["BUNDLER_FORCE_TTY"]
|
|
33
|
+
ENV["BUNDLER_FORCE_TTY"] = "true"
|
|
34
|
+
begin
|
|
35
|
+
# If the config/spring.rb contains requires for commands from other gems,
|
|
36
|
+
# then we need to be under bundler.
|
|
37
|
+
require "bundler/setup"
|
|
38
|
+
ensure
|
|
39
|
+
ENV["BUNDLER_FORCE_TTY"] = old_env
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Auto-require any Spring extensions which are in the Gemfile
|
|
43
|
+
Gem::Specification.map(&:name).grep(/^spring-/).each do |command|
|
|
44
|
+
begin
|
|
45
|
+
require command
|
|
46
|
+
rescue LoadError => error
|
|
47
|
+
if error.message.include?(command)
|
|
48
|
+
require command.gsub("-", "/")
|
|
49
|
+
else
|
|
50
|
+
raise
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
config = File.expand_path("./config/spring.rb")
|
|
56
|
+
require config if File.exist?(config)
|
|
57
|
+
end
|