mini-clean-kit 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.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/mini-clean-kit.gemspec +12 -0
  3. data/spring-4.7.0/LICENSE.txt +23 -0
  4. data/spring-4.7.0/README.md +467 -0
  5. data/spring-4.7.0/bin/spring +49 -0
  6. data/spring-4.7.0/lib/spring/application/boot.rb +25 -0
  7. data/spring-4.7.0/lib/spring/application.rb +449 -0
  8. data/spring-4.7.0/lib/spring/application_manager.rb +145 -0
  9. data/spring-4.7.0/lib/spring/binstub.rb +13 -0
  10. data/spring-4.7.0/lib/spring/boot.rb +10 -0
  11. data/spring-4.7.0/lib/spring/client/binstub.rb +190 -0
  12. data/spring-4.7.0/lib/spring/client/command.rb +18 -0
  13. data/spring-4.7.0/lib/spring/client/help.rb +62 -0
  14. data/spring-4.7.0/lib/spring/client/rails.rb +34 -0
  15. data/spring-4.7.0/lib/spring/client/run.rb +297 -0
  16. data/spring-4.7.0/lib/spring/client/server.rb +18 -0
  17. data/spring-4.7.0/lib/spring/client/status.rb +30 -0
  18. data/spring-4.7.0/lib/spring/client/stop.rb +22 -0
  19. data/spring-4.7.0/lib/spring/client/version.rb +11 -0
  20. data/spring-4.7.0/lib/spring/client.rb +48 -0
  21. data/spring-4.7.0/lib/spring/command_wrapper.rb +82 -0
  22. data/spring-4.7.0/lib/spring/commands/rails.rb +112 -0
  23. data/spring-4.7.0/lib/spring/commands/rake.rb +30 -0
  24. data/spring-4.7.0/lib/spring/commands.rb +57 -0
  25. data/spring-4.7.0/lib/spring/configuration.rb +99 -0
  26. data/spring-4.7.0/lib/spring/env.rb +115 -0
  27. data/spring-4.7.0/lib/spring/errors.rb +36 -0
  28. data/spring-4.7.0/lib/spring/failsafe_thread.rb +14 -0
  29. data/spring-4.7.0/lib/spring/json.rb +623 -0
  30. data/spring-4.7.0/lib/spring/process_title_updater.rb +65 -0
  31. data/spring-4.7.0/lib/spring/server.rb +162 -0
  32. data/spring-4.7.0/lib/spring/version.rb +3 -0
  33. data/spring-4.7.0/lib/spring/watcher/abstract.rb +117 -0
  34. data/spring-4.7.0/lib/spring/watcher/polling.rb +98 -0
  35. data/spring-4.7.0/lib/spring/watcher.rb +30 -0
  36. metadata +75 -0
@@ -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,18 @@
1
+ require "spring/env"
2
+
3
+ module Spring
4
+ module Client
5
+ class Command
6
+ def self.call(args)
7
+ new(args).call
8
+ end
9
+
10
+ attr_reader :args, :env
11
+
12
+ def initialize(args)
13
+ @args = args
14
+ @env = Env.new
15
+ end
16
+ end
17
+ end
18
+ 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
@@ -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,11 @@
1
+ require "spring/version"
2
+
3
+ module Spring
4
+ module Client
5
+ class Version < Command
6
+ def call
7
+ puts "Spring version #{Spring::VERSION}"
8
+ end
9
+ end
10
+ end
11
+ end