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,145 @@
|
|
|
1
|
+
module Spring
|
|
2
|
+
class ApplicationManager
|
|
3
|
+
attr_reader :pid, :child, :app_env, :spawn_env, :spring_env, :status
|
|
4
|
+
|
|
5
|
+
def initialize(app_env, spawn_env, spring_env)
|
|
6
|
+
@app_env = app_env
|
|
7
|
+
@spawn_env = spawn_env
|
|
8
|
+
@spring_env = spring_env
|
|
9
|
+
@mutex = Mutex.new
|
|
10
|
+
@state = :running
|
|
11
|
+
@pid = nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def log(message)
|
|
15
|
+
spring_env.log "[application_manager:#{app_env}] #{message}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# We're not using @mutex.synchronize to avoid the weird "<internal:prelude>:10"
|
|
19
|
+
# line which messes with backtraces in e.g. rspec
|
|
20
|
+
def synchronize
|
|
21
|
+
@mutex.lock
|
|
22
|
+
yield
|
|
23
|
+
ensure
|
|
24
|
+
@mutex.unlock
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def start
|
|
28
|
+
start_child
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def restart
|
|
32
|
+
return if @state == :stopping
|
|
33
|
+
start_child(true)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def alive?
|
|
37
|
+
@pid
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def with_child
|
|
41
|
+
synchronize do
|
|
42
|
+
if alive?
|
|
43
|
+
begin
|
|
44
|
+
yield
|
|
45
|
+
rescue Errno::ECONNRESET, Errno::EPIPE, Errno::EINVAL
|
|
46
|
+
# The child has died but has not been collected by the wait thread yet,
|
|
47
|
+
# so start a new child and try again.
|
|
48
|
+
log "child dead; starting"
|
|
49
|
+
start
|
|
50
|
+
yield
|
|
51
|
+
end
|
|
52
|
+
else
|
|
53
|
+
log "child not running; starting"
|
|
54
|
+
start
|
|
55
|
+
yield
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Returns the pid of the process running the command, or nil if the application process died.
|
|
61
|
+
def run(client)
|
|
62
|
+
with_child do
|
|
63
|
+
child.send_io client
|
|
64
|
+
child.gets or raise Errno::EPIPE
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
pid = child.gets.to_i
|
|
68
|
+
|
|
69
|
+
unless pid.zero?
|
|
70
|
+
log "got worker pid #{pid}"
|
|
71
|
+
pid
|
|
72
|
+
end
|
|
73
|
+
rescue Errno::ECONNRESET, Errno::EPIPE => e
|
|
74
|
+
log "#{e} while reading from child; returning no pid"
|
|
75
|
+
nil
|
|
76
|
+
ensure
|
|
77
|
+
client.close
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def stop
|
|
81
|
+
log "stopping"
|
|
82
|
+
@state = :stopping
|
|
83
|
+
|
|
84
|
+
if pid
|
|
85
|
+
Process.kill('TERM', pid)
|
|
86
|
+
Process.wait(pid)
|
|
87
|
+
end
|
|
88
|
+
rescue Errno::ESRCH, Errno::ECHILD
|
|
89
|
+
# Don't care
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def start_child(preload = false)
|
|
95
|
+
@child, child_socket = UNIXSocket.pair
|
|
96
|
+
|
|
97
|
+
Bundler.with_original_env do
|
|
98
|
+
bundler_dir = File.expand_path("../..", $LOADED_FEATURES.grep(/bundler\/setup\.rb$/).first)
|
|
99
|
+
@pid = Process.spawn(
|
|
100
|
+
{
|
|
101
|
+
"RAILS_ENV" => app_env,
|
|
102
|
+
"RACK_ENV" => app_env,
|
|
103
|
+
"SPRING_ORIGINAL_ENV" => JSON.dump(Spring::ORIGINAL_ENV),
|
|
104
|
+
"SPRING_PRELOAD" => preload ? "1" : "0",
|
|
105
|
+
"SPRING_SPAWN_ENV" => JSON.dump(spawn_env.compact),
|
|
106
|
+
**spawn_env,
|
|
107
|
+
},
|
|
108
|
+
"ruby",
|
|
109
|
+
*(bundler_dir != RbConfig::CONFIG["rubylibdir"] ? ["-I", bundler_dir] : []),
|
|
110
|
+
"-I", File.expand_path("../..", __FILE__),
|
|
111
|
+
"-e", "require 'spring/application/boot'",
|
|
112
|
+
3 => child_socket,
|
|
113
|
+
4 => spring_env.log_file,
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
start_wait_thread(pid, child) if child.gets
|
|
118
|
+
child_socket.close
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def start_wait_thread(pid, child)
|
|
122
|
+
Process.detach(pid)
|
|
123
|
+
|
|
124
|
+
Spring.failsafe_thread {
|
|
125
|
+
# The recv can raise an ECONNRESET, killing the thread, but that's ok
|
|
126
|
+
# as if it does we're no longer interested in the child
|
|
127
|
+
loop do
|
|
128
|
+
IO.select([child])
|
|
129
|
+
peek = child.recv(1, Socket::MSG_PEEK)
|
|
130
|
+
break if peek.nil? || peek.empty?
|
|
131
|
+
sleep 0.01
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
log "child #{pid} shutdown"
|
|
135
|
+
|
|
136
|
+
synchronize {
|
|
137
|
+
if @pid == pid
|
|
138
|
+
@pid = nil
|
|
139
|
+
restart
|
|
140
|
+
end
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
command = File.basename($0)
|
|
2
|
+
bin_path = File.expand_path("../../../bin/spring", __FILE__)
|
|
3
|
+
|
|
4
|
+
if command == "spring"
|
|
5
|
+
load bin_path
|
|
6
|
+
else
|
|
7
|
+
disable = ENV["DISABLE_SPRING"]
|
|
8
|
+
|
|
9
|
+
if Process.respond_to?(:fork) && (disable.nil? || disable.empty? || disable == "0")
|
|
10
|
+
ARGV.unshift(command)
|
|
11
|
+
load bin_path
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
module Spring
|
|
2
|
+
module Client
|
|
3
|
+
class Binstub < Command
|
|
4
|
+
SHEBANG = /\#\!.*\n(\#.*\n)*/
|
|
5
|
+
|
|
6
|
+
# If loading the bin/spring file works, it'll run Spring which will
|
|
7
|
+
# eventually call Kernel.exit. This means that in the client process
|
|
8
|
+
# we will never execute the lines after this block. But if the Spring
|
|
9
|
+
# client is not invoked for whatever reason, then the Kernel.exit won't
|
|
10
|
+
# happen, and so we'll fall back to the lines after this block, which
|
|
11
|
+
# should cause the "unsprung" version of the command to run.
|
|
12
|
+
LOADER = <<~CODE
|
|
13
|
+
load File.expand_path("spring", __dir__)
|
|
14
|
+
CODE
|
|
15
|
+
|
|
16
|
+
# The defined? check ensures these lines don't execute when we load the
|
|
17
|
+
# binstub from the application process. Which means that in the application
|
|
18
|
+
# process we'll execute the lines which come after the LOADER block, which
|
|
19
|
+
# is what we want.
|
|
20
|
+
SPRING = <<~CODE
|
|
21
|
+
#!/usr/bin/env ruby
|
|
22
|
+
|
|
23
|
+
# This file loads Spring without loading other gems in the Gemfile in order to be fast.
|
|
24
|
+
# It gets overwritten when you run the `spring binstub` command.
|
|
25
|
+
|
|
26
|
+
if !defined?(Spring) && [nil, "development", "test"].include?(ENV["RAILS_ENV"])
|
|
27
|
+
require "bundler"
|
|
28
|
+
|
|
29
|
+
Bundler.definition.requested_specs.find { |spec| spec.name == "spring" }&.tap do |spring|
|
|
30
|
+
Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
|
|
31
|
+
gem "spring", spring.version
|
|
32
|
+
require "spring/binstub"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
CODE
|
|
36
|
+
|
|
37
|
+
OLD_BINSTUB = %{if !Process.respond_to?(:fork) || Gem::Specification.find_all_by_name("spring").empty?}
|
|
38
|
+
|
|
39
|
+
BINSTUB_VARIATIONS = Regexp.union [
|
|
40
|
+
%{load File.expand_path("spring", __dir__)\n},
|
|
41
|
+
%{begin\n load File.expand_path('../spring', __FILE__)\nrescue LoadError => e\n raise unless e.message.include?('spring')\nend\n},
|
|
42
|
+
%{begin\n load File.expand_path('../spring', __FILE__)\nrescue LoadError\nend\n},
|
|
43
|
+
%{begin\n spring_bin_path = File.expand_path('../spring', __FILE__)\n load spring_bin_path\nrescue LoadError => e\n raise unless e.message.end_with? spring_bin_path, 'spring/binstub'\nend\n},
|
|
44
|
+
LOADER
|
|
45
|
+
].map { |binstub| /#{Regexp.escape(binstub).gsub("'", "['\"]")}/ }
|
|
46
|
+
|
|
47
|
+
class Item
|
|
48
|
+
attr_reader :command, :existing
|
|
49
|
+
|
|
50
|
+
def initialize(command)
|
|
51
|
+
@command = command
|
|
52
|
+
|
|
53
|
+
if command.binstub.exist?
|
|
54
|
+
@existing = command.binstub.read
|
|
55
|
+
elsif command.name == "rails"
|
|
56
|
+
scriptfile = Spring.application_root_path.join("script/rails")
|
|
57
|
+
@existing = scriptfile.read if scriptfile.exist?
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def status(text, stream = $stdout)
|
|
62
|
+
stream.puts "* #{command.binstub_name}: #{text}"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def add
|
|
66
|
+
if existing
|
|
67
|
+
if existing.include?(OLD_BINSTUB)
|
|
68
|
+
fallback = existing.match(/#{Regexp.escape OLD_BINSTUB}\n(.*)else/m)[1]
|
|
69
|
+
fallback.gsub!(/^ /, "")
|
|
70
|
+
fallback = nil if fallback.include?("exec")
|
|
71
|
+
generate(fallback)
|
|
72
|
+
status "upgraded"
|
|
73
|
+
elsif existing.include?(LOADER)
|
|
74
|
+
status "Spring already present"
|
|
75
|
+
elsif existing =~ BINSTUB_VARIATIONS
|
|
76
|
+
upgraded = existing.sub(BINSTUB_VARIATIONS, LOADER)
|
|
77
|
+
File.write(command.binstub, upgraded)
|
|
78
|
+
status "upgraded"
|
|
79
|
+
else
|
|
80
|
+
head, shebang, tail = existing.partition(SHEBANG)
|
|
81
|
+
|
|
82
|
+
if shebang.include?("ruby")
|
|
83
|
+
unless command.binstub.exist?
|
|
84
|
+
FileUtils.touch command.binstub
|
|
85
|
+
command.binstub.chmod 0755
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
File.write(command.binstub, "#{head}#{shebang}#{LOADER}#{tail}")
|
|
89
|
+
status "Spring inserted"
|
|
90
|
+
else
|
|
91
|
+
status "doesn't appear to be ruby, so cannot use Spring", $stderr
|
|
92
|
+
exit 1
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
else
|
|
96
|
+
generate
|
|
97
|
+
status "generated with Spring"
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def generate(fallback = nil)
|
|
102
|
+
unless fallback
|
|
103
|
+
fallback = "require 'bundler/setup'\n" \
|
|
104
|
+
"load Gem.bin_path('#{command.gem_name}', '#{command.exec_name}')\n"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
File.write(command.binstub, "#!/usr/bin/env ruby\n#{LOADER}#{fallback}")
|
|
108
|
+
command.binstub.chmod 0755
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def remove
|
|
112
|
+
if existing
|
|
113
|
+
File.write(command.binstub, existing.sub(BINSTUB_VARIATIONS, ""))
|
|
114
|
+
status "Spring removed"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
attr_reader :bindir, :items
|
|
120
|
+
|
|
121
|
+
def self.description
|
|
122
|
+
"Generate Spring based binstubs. Use --all to generate a binstub for all known commands. Use --remove to revert."
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def self.rails_command
|
|
126
|
+
@rails_command ||= CommandWrapper.new("rails")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def self.call(args)
|
|
130
|
+
require "spring/commands"
|
|
131
|
+
super
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def initialize(args)
|
|
135
|
+
super
|
|
136
|
+
|
|
137
|
+
@bindir = env.root.join("bin")
|
|
138
|
+
@all = false
|
|
139
|
+
@mode = :add
|
|
140
|
+
@items = args.drop(1)
|
|
141
|
+
.map { |name| find_commands name }
|
|
142
|
+
.flatten.uniq
|
|
143
|
+
.map { |command| Item.new(command) }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def find_commands(name)
|
|
147
|
+
case name
|
|
148
|
+
when "--all"
|
|
149
|
+
@all = true
|
|
150
|
+
commands = Spring.commands.dup
|
|
151
|
+
commands.delete_if { |command_name, _| command_name.start_with?("rails_") }
|
|
152
|
+
commands.values + [self.class.rails_command]
|
|
153
|
+
when "--remove"
|
|
154
|
+
@mode = :remove
|
|
155
|
+
[]
|
|
156
|
+
when "rails"
|
|
157
|
+
[self.class.rails_command]
|
|
158
|
+
else
|
|
159
|
+
if command = Spring.commands[name]
|
|
160
|
+
[command]
|
|
161
|
+
else
|
|
162
|
+
$stderr.puts "The '#{name}' command is not known to spring."
|
|
163
|
+
exit 1
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def call
|
|
169
|
+
case @mode
|
|
170
|
+
when :add
|
|
171
|
+
bindir.mkdir unless bindir.exist?
|
|
172
|
+
|
|
173
|
+
File.write(spring_binstub, SPRING)
|
|
174
|
+
spring_binstub.chmod 0755
|
|
175
|
+
|
|
176
|
+
items.each(&:add)
|
|
177
|
+
when :remove
|
|
178
|
+
spring_binstub.delete if @all
|
|
179
|
+
items.each(&:remove)
|
|
180
|
+
else
|
|
181
|
+
raise ArgumentError
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def spring_binstub
|
|
186
|
+
bindir.join("spring")
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require "spring/version"
|
|
2
|
+
|
|
3
|
+
module Spring
|
|
4
|
+
module Client
|
|
5
|
+
class Help < Command
|
|
6
|
+
attr_reader :spring_commands, :application_commands
|
|
7
|
+
|
|
8
|
+
def self.description
|
|
9
|
+
"Print available commands."
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.call(args)
|
|
13
|
+
require "spring/commands"
|
|
14
|
+
super
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def initialize(args, spring_commands = nil, application_commands = nil)
|
|
18
|
+
super args
|
|
19
|
+
|
|
20
|
+
@spring_commands = spring_commands || Spring::Client::COMMANDS.dup
|
|
21
|
+
@application_commands = application_commands || Spring.commands.dup
|
|
22
|
+
|
|
23
|
+
@spring_commands.delete_if { |k, v| k.start_with?("-") }
|
|
24
|
+
|
|
25
|
+
@application_commands["rails"] = @spring_commands.delete("rails")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def call
|
|
29
|
+
puts formatted_help
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def formatted_help
|
|
33
|
+
["Version: #{env.version}\n",
|
|
34
|
+
"Usage: spring COMMAND [ARGS]\n",
|
|
35
|
+
*command_help("Spring itself", spring_commands),
|
|
36
|
+
'',
|
|
37
|
+
*command_help("your application", application_commands)].join("\n")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def command_help(subject, commands)
|
|
41
|
+
["Commands for #{subject}:\n",
|
|
42
|
+
*commands.sort_by(&:first).map { |name, command| display(name, command) }.compact]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def all_commands
|
|
48
|
+
spring_commands.merge application_commands
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def display(name, command)
|
|
52
|
+
if command.description
|
|
53
|
+
" #{name.ljust(max_name_width)} #{command.description}"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def max_name_width
|
|
58
|
+
@max_name_width ||= all_commands.keys.map(&:length).max
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Spring
|
|
2
|
+
module Client
|
|
3
|
+
class Rails < Command
|
|
4
|
+
COMMANDS = %w(console runner generate destroy test)
|
|
5
|
+
|
|
6
|
+
ALIASES = {
|
|
7
|
+
"c" => "console",
|
|
8
|
+
"r" => "runner",
|
|
9
|
+
"g" => "generate",
|
|
10
|
+
"d" => "destroy",
|
|
11
|
+
"t" => "test"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
def self.description
|
|
15
|
+
"Run a rails command. The following sub commands will use Spring: #{COMMANDS.to_a.join ', '}."
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def call
|
|
19
|
+
command_name = ALIASES[args[1]] || args[1]
|
|
20
|
+
|
|
21
|
+
if COMMANDS.include?(command_name)
|
|
22
|
+
Run.call(["rails_#{command_name}", *args.drop(2)])
|
|
23
|
+
elsif command_name&.start_with?("db:") && !command_name.start_with?("db:system")
|
|
24
|
+
Run.call(["rake", *args.drop(1)])
|
|
25
|
+
else
|
|
26
|
+
require "spring/configuration"
|
|
27
|
+
ARGV.shift
|
|
28
|
+
load Dir.glob(Spring.application_root_path.join("{bin,script}/rails")).first
|
|
29
|
+
exit
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|