squared 0.0.5 → 0.0.6
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/README.ruby.md +3 -2
- data/lib/squared/common/base.rb +91 -0
- data/lib/squared/common/format.rb +14 -5
- data/lib/squared/common/shell.rb +7 -7
- data/lib/squared/common/system.rb +4 -1
- data/lib/squared/common/task.rb +5 -1
- data/lib/squared/common.rb +1 -78
- data/lib/squared/config.rb +7 -7
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +306 -0
- data/lib/squared/{repo → workspace}/project/base.rb +47 -41
- data/lib/squared/{repo → workspace}/project/git.rb +71 -53
- data/lib/squared/{repo → workspace}/project/node.rb +17 -18
- data/lib/squared/{repo → workspace}/project/python.rb +3 -3
- data/lib/squared/{repo → workspace}/project/ruby.rb +7 -8
- data/lib/squared/{repo → workspace}/project.rb +1 -1
- data/lib/squared/workspace/repo.rb +201 -0
- data/lib/squared/workspace/series.rb +125 -0
- data/lib/squared/{repo.rb → workspace.rb} +6 -3
- data/lib/squared.rb +9 -8
- metadata +13 -10
- data/lib/squared/repo/workspace.rb +0 -552
@@ -1,552 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Squared
|
4
|
-
module Repo
|
5
|
-
class Workspace
|
6
|
-
include Common
|
7
|
-
include Format
|
8
|
-
include System
|
9
|
-
include Task
|
10
|
-
include ::Rake::DSL
|
11
|
-
|
12
|
-
TASK_NAME = {
|
13
|
-
build: [],
|
14
|
-
refresh: [],
|
15
|
-
depend: [],
|
16
|
-
outdated: [],
|
17
|
-
doc: [],
|
18
|
-
test: [],
|
19
|
-
copy: [],
|
20
|
-
clean: []
|
21
|
-
}
|
22
|
-
TASK_BASE = {}
|
23
|
-
TASK_KEYS = TASK_NAME.keys.freeze
|
24
|
-
private_constant :TASK_NAME, :TASK_BASE
|
25
|
-
|
26
|
-
class << self
|
27
|
-
def implement(*objs)
|
28
|
-
objs.each do |obj|
|
29
|
-
next unless obj < Project::Base
|
30
|
-
|
31
|
-
project_kind.unshift(obj)
|
32
|
-
obj.tasks&.each do |val|
|
33
|
-
TASK_NAME[val] = []
|
34
|
-
TASK_BASE[val] = obj
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def find(path: nil, ref: nil)
|
40
|
-
if ref.is_a?(::Symbol) || ref.is_a?(::String)
|
41
|
-
ret = project_kind.find { |proj| proj.to_sym == ref.to_sym }
|
42
|
-
return ret if ret
|
43
|
-
end
|
44
|
-
project_kind.find { |proj| proj.is_a?(path) } if path
|
45
|
-
end
|
46
|
-
|
47
|
-
def to_s
|
48
|
-
super.to_s.match(/[^:]+$/)[0]
|
49
|
-
end
|
50
|
-
|
51
|
-
attr_reader :project_kind
|
52
|
-
end
|
53
|
-
|
54
|
-
@project_kind = []
|
55
|
-
|
56
|
-
attr_reader :main, :root, :home, :series, :theme, :sync, :multiple, :parallel
|
57
|
-
attr_accessor :manifest, :manifest_url, :exception, :pipe, :verbose, :warning
|
58
|
-
|
59
|
-
def initialize(main, *, common: true, **)
|
60
|
-
@main = main.to_s
|
61
|
-
@home = if (val = env('REPO_HOME'))
|
62
|
-
home = Pathname.new(val)
|
63
|
-
if @main == home.basename.to_s
|
64
|
-
@root = home.parent
|
65
|
-
if home.exist?
|
66
|
-
@root = nil unless home.directory?
|
67
|
-
elsif !@root.exist?
|
68
|
-
@root.mkpath
|
69
|
-
elsif !empty?(@root)
|
70
|
-
if repo_prompt(@root)
|
71
|
-
@override = true
|
72
|
-
else
|
73
|
-
@root = nil
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
raise ArgumentError, message('REPO_HOME', val, hint: 'invalid') unless @root
|
78
|
-
|
79
|
-
home.realdirpath
|
80
|
-
elsif (val = env('REPO_ROOT'))
|
81
|
-
@root = Pathname.new(val).realdirpath
|
82
|
-
if !@root.exist?
|
83
|
-
@root.mkpath
|
84
|
-
elsif !empty?(@root)
|
85
|
-
raise ArgumentError, message('REPO_ROOT', val, hint: 'exist') unless repo_prompt(@root)
|
86
|
-
|
87
|
-
@override = true
|
88
|
-
end
|
89
|
-
@root.join(@main).realdirpath
|
90
|
-
else
|
91
|
-
empty?(pwd = Pathname.pwd) ? pwd.join(@main) : pwd
|
92
|
-
end
|
93
|
-
@root ||= @home.parent
|
94
|
-
@series = TASK_NAME.dup
|
95
|
-
@project = {}
|
96
|
-
@script = {
|
97
|
-
group: {},
|
98
|
-
ref: {},
|
99
|
-
build: nil,
|
100
|
-
dev: nil,
|
101
|
-
prod: nil
|
102
|
-
}
|
103
|
-
@exception = !env('PIPE_FAIL', ignore: '0').nil?
|
104
|
-
@pipe = !env('PIPE_OUT', ignore: '0').nil?
|
105
|
-
@verbose = !@pipe
|
106
|
-
@warning = !empty?(@root, repo: false)
|
107
|
-
@sync = []
|
108
|
-
@multiple = []
|
109
|
-
@parallel = []
|
110
|
-
@theme = common && @verbose ? __get__(:theme)[:workspace] : {}
|
111
|
-
end
|
112
|
-
|
113
|
-
def build(**kwargs)
|
114
|
-
return unless enabled?
|
115
|
-
|
116
|
-
default = kwargs[:default]
|
117
|
-
multi = env('REPO_SYNC', ignore: '0') ? [] : kwargs.fetch(:parallel, []).map!(&:to_sym)
|
118
|
-
|
119
|
-
group = {}
|
120
|
-
parent = {}
|
121
|
-
incl = []
|
122
|
-
@project.each do |name, proj|
|
123
|
-
next unless proj.enabled?
|
124
|
-
|
125
|
-
series.each do |key, items|
|
126
|
-
target = "#{name}:#{key}"
|
127
|
-
case key
|
128
|
-
when :build, :refresh, :depend, :copy, :outdated, :doc, :test, :clean
|
129
|
-
valid = proj.has?(key) || ::Rake::Task.task_defined?(target)
|
130
|
-
next unless valid || (key == :refresh && series[:build].include?(target = "#{name}:build"))
|
131
|
-
else
|
132
|
-
next unless task_defined?(proj, key)
|
133
|
-
end
|
134
|
-
if proj.group
|
135
|
-
incl << proj.group
|
136
|
-
(group[:"#{key}:#{proj.group}"] ||= []).push(target)
|
137
|
-
else
|
138
|
-
items << target
|
139
|
-
end
|
140
|
-
next unless (base = find_base(proj))
|
141
|
-
|
142
|
-
unless (id = base.to_sym.to_s) == proj.group
|
143
|
-
incl << id
|
144
|
-
(parent[:"#{key}:#{id}"] ||= []).push(target)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
proj.populate(**kwargs)
|
148
|
-
end
|
149
|
-
series.merge!(parent) if incl.uniq.size > 1
|
150
|
-
series.merge!(group)
|
151
|
-
series[:refresh].clear if series[:refresh].all? { |target| target.end_with?(':build') }
|
152
|
-
|
153
|
-
if repo?
|
154
|
-
branch = env('REPO_MANIFEST') || read_manifest
|
155
|
-
target = branch || manifest
|
156
|
-
stage = nil
|
157
|
-
failfast = true
|
158
|
-
cmd = []
|
159
|
-
newline = ARGV.index { |val| val.start_with?('repo:') }.to_i > 0
|
160
|
-
parse_opts = lambda do |args|
|
161
|
-
collect_args(args, :opts).each do |val|
|
162
|
-
case val
|
163
|
-
when 'no-fail'
|
164
|
-
failfast = false
|
165
|
-
when 'force'
|
166
|
-
cmd << '--force-checkout'
|
167
|
-
when 'rebase'
|
168
|
-
cmd << '--rebase'
|
169
|
-
when 'detach'
|
170
|
-
cmd << '--detach'
|
171
|
-
when 'gc'
|
172
|
-
cmd << '--auto-gc'
|
173
|
-
when 'no-update'
|
174
|
-
cmd << '--no-manifest-update'
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
status = lambda do |val, alt = nil|
|
179
|
-
ver = branch || alt
|
180
|
-
ver ? message('repo', val.sub('{0}', 'opts*=force,rebase,detach,gc,no-update,no-fail'), ver) : 'inactive'
|
181
|
-
end
|
182
|
-
|
183
|
-
namespace :repo do |repo|
|
184
|
-
desc status.('all[{0}]')
|
185
|
-
task :all, [:opts] do |_, args|
|
186
|
-
parse_opts.(args)
|
187
|
-
stage ||= :all
|
188
|
-
repo[:sync].invoke
|
189
|
-
@project.select do |_, proj|
|
190
|
-
if proj.enabled?
|
191
|
-
proj.depend
|
192
|
-
proj.build?
|
193
|
-
end
|
194
|
-
end
|
195
|
-
.each_value { |proj| proj.has?(:dev) ? proj.refresh : proj.build }
|
196
|
-
end
|
197
|
-
|
198
|
-
desc status.("init[manifest?=#{target},{0}]", target)
|
199
|
-
task :init, [:manifest, :opts] do |_, args|
|
200
|
-
parse_opts.(args)
|
201
|
-
stage = :init
|
202
|
-
puts if newline
|
203
|
-
system("repo init -u #{manifest_url} -m #{args.manifest || target}.xml", chdir: root)
|
204
|
-
repo[:all].invoke
|
205
|
-
end
|
206
|
-
|
207
|
-
desc status.('sync[{0}]')
|
208
|
-
task :sync, [:opts] do |_, args|
|
209
|
-
raise LoadError, message('repo is not initialized', 'rake repo:init') unless branch || stage == :init
|
210
|
-
|
211
|
-
parse_opts.(args)
|
212
|
-
cmd << "-j#{ENV.fetch('REPO_JOBS', ::Rake::CpuCounter.count)}"
|
213
|
-
cmd << '--fail-fast' if failfast
|
214
|
-
puts if newline && stage != :init
|
215
|
-
begin
|
216
|
-
shell("repo sync #{cmd.join(' ')}", chdir: root, exception: failfast)
|
217
|
-
rescue StandardError => e
|
218
|
-
emphasize(e, title: "rake stash repo:#{stage || 'sync'}")
|
219
|
-
raise
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
Workspace.project_kind.each { |obj| obj.populate(self, **kwargs) }
|
226
|
-
|
227
|
-
if !series[:build].empty?
|
228
|
-
init = [:depend, dev? && !series[:refresh].empty? ? :refresh : :build]
|
229
|
-
|
230
|
-
task default: default || init[1]
|
231
|
-
|
232
|
-
desc 'init'
|
233
|
-
task init: init
|
234
|
-
elsif default && !series[default].empty?
|
235
|
-
task default: default
|
236
|
-
end
|
237
|
-
|
238
|
-
series.each do |key, items|
|
239
|
-
next if items.empty?
|
240
|
-
|
241
|
-
s = key.to_s
|
242
|
-
if items.size > 1
|
243
|
-
multiple << s
|
244
|
-
unless (valid = multi.include?(key))
|
245
|
-
group = key.to_s
|
246
|
-
valid = multi.include?(group.split(':').first.to_sym) if group.include?(':')
|
247
|
-
end
|
248
|
-
if valid
|
249
|
-
desc "#{key} (thread)"
|
250
|
-
multitask key => items
|
251
|
-
parallel << s
|
252
|
-
|
253
|
-
desc "#{key} (sync)"
|
254
|
-
task "#{key}:sync": items
|
255
|
-
sync << "#{key}:sync"
|
256
|
-
multiple << "#{key}:sync"
|
257
|
-
next
|
258
|
-
end
|
259
|
-
end
|
260
|
-
desc s
|
261
|
-
task key => items
|
262
|
-
end
|
263
|
-
|
264
|
-
yield self if block_given?
|
265
|
-
end
|
266
|
-
|
267
|
-
def repo(url, manifest = 'latest', run: nil, dev: nil, prod: nil)
|
268
|
-
@manifest_url = url
|
269
|
-
@manifest = manifest
|
270
|
-
script = case (val = env('REPO_BUILD'))
|
271
|
-
when 'verbose'
|
272
|
-
@verbose = true
|
273
|
-
run ? "#{run}:verbose" : nil
|
274
|
-
when 'silent'
|
275
|
-
@verbose = false
|
276
|
-
@warning = false
|
277
|
-
run
|
278
|
-
else
|
279
|
-
val || run
|
280
|
-
end
|
281
|
-
case env('REPO_WARN')
|
282
|
-
when '0'
|
283
|
-
@warning = false
|
284
|
-
when '1'
|
285
|
-
@warning = true
|
286
|
-
end
|
287
|
-
return self unless script
|
288
|
-
|
289
|
-
run(script, dev: bool_match(env('REPO_DEV'), dev), prod: bool_match(env('REPO_DEV'), prod))
|
290
|
-
end
|
291
|
-
|
292
|
-
def run(script, group: nil, ref: nil, **kwargs)
|
293
|
-
if group || ref
|
294
|
-
script_command :run, script, group, ref
|
295
|
-
else
|
296
|
-
@script[:build] = script
|
297
|
-
@script[:dev] = kwargs[:dev]
|
298
|
-
@script[:prod] = kwargs[:prod]
|
299
|
-
self
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
def depend(script, group: nil, ref: nil)
|
304
|
-
script_command :depend, script, group, ref
|
305
|
-
end
|
306
|
-
|
307
|
-
def clean(script, group: nil, ref: nil)
|
308
|
-
script_command :clean, script, group, ref
|
309
|
-
end
|
310
|
-
|
311
|
-
def doc(script, group: nil, ref: nil)
|
312
|
-
script_command :doc, script, group, ref
|
313
|
-
end
|
314
|
-
|
315
|
-
def test(script, group: nil, ref: nil)
|
316
|
-
script_command :test, script, group, ref
|
317
|
-
end
|
318
|
-
|
319
|
-
def add(name, path = nil, ref: nil, **kwargs)
|
320
|
-
path = root_path((path || name).to_s)
|
321
|
-
project = if !ref.is_a?(::Class)
|
322
|
-
Workspace.find(path: path, ref: ref)
|
323
|
-
elsif ref < Project::Base
|
324
|
-
ref
|
325
|
-
end
|
326
|
-
instance = (project || Project::Base).new(name, path, self, **kwargs)
|
327
|
-
@project[n = name.to_sym] = instance
|
328
|
-
__get__(:project)[n] = instance unless kwargs[:private]
|
329
|
-
self
|
330
|
-
end
|
331
|
-
|
332
|
-
def group(name, path, **kwargs)
|
333
|
-
root_path(path).children.map do |ent|
|
334
|
-
next unless (dir = Pathname.new(ent)).directory?
|
335
|
-
|
336
|
-
index = 0
|
337
|
-
basename = dir.basename.to_s.to_sym
|
338
|
-
override = kwargs.delete(basename)
|
339
|
-
while @project[basename]
|
340
|
-
index += 1
|
341
|
-
basename = :"#{basename}-#{index}"
|
342
|
-
end
|
343
|
-
[basename, dir, override]
|
344
|
-
end
|
345
|
-
.each do |basename, dir, override|
|
346
|
-
opts = kwargs.dup
|
347
|
-
opts.merge!(override) if override
|
348
|
-
add(basename, dir, group: name, **opts)
|
349
|
-
end
|
350
|
-
self
|
351
|
-
end
|
352
|
-
|
353
|
-
def compose(name, &blk)
|
354
|
-
namespace(name, &blk)
|
355
|
-
self
|
356
|
-
end
|
357
|
-
|
358
|
-
def apply(&blk)
|
359
|
-
instance_eval(&blk)
|
360
|
-
self
|
361
|
-
end
|
362
|
-
|
363
|
-
def style(name, *args, target: nil, empty: false)
|
364
|
-
data = nil
|
365
|
-
if target
|
366
|
-
as_a(target).each_with_index do |val, i|
|
367
|
-
if i == 0
|
368
|
-
break unless (data = __get__(:theme)[val.to_sym])
|
369
|
-
else
|
370
|
-
data = data[val.to_sym] ||= {}
|
371
|
-
end
|
372
|
-
end
|
373
|
-
return unless data
|
374
|
-
end
|
375
|
-
apply_style(data || theme, name, *args, empty: empty)
|
376
|
-
self
|
377
|
-
end
|
378
|
-
|
379
|
-
def script(group: nil, ref: nil)
|
380
|
-
if group || ref
|
381
|
-
(group && @script[:group][group.to_sym]) || (ref && @script[:ref][ref.to_sym])
|
382
|
-
else
|
383
|
-
@script[:build]
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
def env(key, equals: nil, ignore: nil)
|
388
|
-
ret = ENV.fetch("#{key}_#{main.gsub(/[^\w]/, '_').upcase}", ENV[key]).to_s
|
389
|
-
return ret == equals.to_s if equals
|
390
|
-
|
391
|
-
ret.empty? || as_a(ignore).any? { |val| ret == val.to_s } ? nil : ret
|
392
|
-
end
|
393
|
-
|
394
|
-
def read_manifest(*)
|
395
|
-
require 'rexml/document'
|
396
|
-
return unless (file = root_path('.repo/manifest.xml')).exist?
|
397
|
-
|
398
|
-
doc = REXML::Document.new(file.read)
|
399
|
-
doc.elements['manifest/include'].attributes['name']&.sub('.xml', '')
|
400
|
-
end
|
401
|
-
|
402
|
-
def root_path(*args)
|
403
|
-
root.join(*args)
|
404
|
-
end
|
405
|
-
|
406
|
-
def home_path(*args)
|
407
|
-
home.join(*args)
|
408
|
-
end
|
409
|
-
|
410
|
-
def find_base(obj)
|
411
|
-
Workspace.project_kind.find { |proj| obj.instance_of?(proj) }
|
412
|
-
end
|
413
|
-
|
414
|
-
def bool_match(val, pat)
|
415
|
-
case val
|
416
|
-
when nil, ''
|
417
|
-
pat.is_a?(::Regexp) ? pat : nil
|
418
|
-
when '0'
|
419
|
-
false
|
420
|
-
when '1'
|
421
|
-
true
|
422
|
-
else
|
423
|
-
Regexp.new(val)
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
def to_s
|
428
|
-
root.to_s
|
429
|
-
end
|
430
|
-
|
431
|
-
def inspect
|
432
|
-
"#<#{self.class}: #{main} => #{self}>"
|
433
|
-
end
|
434
|
-
|
435
|
-
def enabled?
|
436
|
-
repo? || @project.any? { |_, proj| proj.enabled? }
|
437
|
-
end
|
438
|
-
|
439
|
-
def repo?
|
440
|
-
!manifest_url.nil? && (empty?(root) || @override)
|
441
|
-
end
|
442
|
-
|
443
|
-
def multiple?(val = nil)
|
444
|
-
return multiple.include?(val) && invoked?(val) if val
|
445
|
-
|
446
|
-
::Rake::Task.tasks.any? { |item| item.already_invoked && multiple.include?(item.name) }
|
447
|
-
end
|
448
|
-
|
449
|
-
def sync?(val = nil)
|
450
|
-
return sync.include?(val) && invoked?(val) if val
|
451
|
-
|
452
|
-
::Rake::Task.tasks.any? { |item| item.already_invoked && sync.include?(item.name) }
|
453
|
-
end
|
454
|
-
|
455
|
-
def parallel?(val = nil)
|
456
|
-
return parallel.include?(val) && invoked?(val) if val
|
457
|
-
|
458
|
-
::Rake::Task.tasks.any? { |item| item.already_invoked && parallel.include?(item.name) }
|
459
|
-
end
|
460
|
-
|
461
|
-
def empty?(dir, repo: true)
|
462
|
-
return true if dir.empty? || (repo && dir.join('.repo').directory?)
|
463
|
-
return true if dir.children.size == 1 && dir.join(dir.children.first).to_s == __FILE__
|
464
|
-
|
465
|
-
dir.to_s == root.to_s && !env('REPO_ROOT').nil? && root.children.none? do |path|
|
466
|
-
path.directory? && !path.basename.to_s.start_with?('.') && path.to_s != home.to_s
|
467
|
-
end
|
468
|
-
end
|
469
|
-
|
470
|
-
def task_defined?(obj, key)
|
471
|
-
obj.is_a?(TASK_BASE[key])
|
472
|
-
end
|
473
|
-
|
474
|
-
def dev?(script: nil, pat: nil, global: nil)
|
475
|
-
with?(:dev, script: script, pat: pat, global: global || (pat.nil? && global.nil?))
|
476
|
-
end
|
477
|
-
|
478
|
-
def prod?(script: nil, pat: nil, global: false)
|
479
|
-
return false if global && (@script[:dev] == true || !@script[:prod])
|
480
|
-
|
481
|
-
with?(:prod, script: script, pat: pat, global: global)
|
482
|
-
end
|
483
|
-
|
484
|
-
protected
|
485
|
-
|
486
|
-
def confirm(msg, agree: 'Y', cancel: 'N', default: nil, attempts: 5, timeout: 15)
|
487
|
-
require 'readline'
|
488
|
-
require 'timeout'
|
489
|
-
Timeout.timeout(ENV.fetch('REPO_TIMEOUT', timeout).to_i) do
|
490
|
-
ret = false
|
491
|
-
begin
|
492
|
-
while (ch = Readline.readline(msg, true))
|
493
|
-
case ch.chomp.upcase
|
494
|
-
when agree
|
495
|
-
ret = true
|
496
|
-
break
|
497
|
-
when cancel
|
498
|
-
break
|
499
|
-
when ''
|
500
|
-
case default
|
501
|
-
when agree
|
502
|
-
ret = true
|
503
|
-
break
|
504
|
-
when cancel
|
505
|
-
break
|
506
|
-
end
|
507
|
-
end
|
508
|
-
attempts -= 1
|
509
|
-
exit 1 unless attempts >= 0
|
510
|
-
end
|
511
|
-
rescue Interrupt
|
512
|
-
puts
|
513
|
-
exit 0
|
514
|
-
else
|
515
|
-
ret
|
516
|
-
end
|
517
|
-
end
|
518
|
-
end
|
519
|
-
|
520
|
-
private
|
521
|
-
|
522
|
-
def script_command(task, val, group, ref)
|
523
|
-
if group
|
524
|
-
label = :group
|
525
|
-
items = as_a(group)
|
526
|
-
else
|
527
|
-
label = :ref
|
528
|
-
items = as_a(ref)
|
529
|
-
end
|
530
|
-
items.each { |name| (@script[label][name.to_sym] ||= {})[task] = val }
|
531
|
-
self
|
532
|
-
end
|
533
|
-
|
534
|
-
def repo_prompt(path)
|
535
|
-
return false unless path.directory?
|
536
|
-
|
537
|
-
confirm("#{log_title(:warn)} \"#{sub_style(path, :bold)}\" is not empty. Continue with installation? [y/N] ",
|
538
|
-
default: 'N')
|
539
|
-
end
|
540
|
-
|
541
|
-
def with?(state, script: nil, pat: nil, global: false)
|
542
|
-
if global
|
543
|
-
pat = @script[state] if pat.nil?
|
544
|
-
script ||= @script[:build]
|
545
|
-
end
|
546
|
-
pat.is_a?(::Regexp) ? pat.match?(script) : pat == true
|
547
|
-
end
|
548
|
-
end
|
549
|
-
end
|
550
|
-
end
|
551
|
-
|
552
|
-
Repo = Squared::Repo
|