squared 0.3.14 → 0.4.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/CHANGELOG.md +63 -230
- data/README.md +1285 -387
- data/README.ruby.md +546 -0
- data/lib/squared/app.rb +1 -0
- data/lib/squared/common/base.rb +9 -7
- data/lib/squared/common/class.rb +1 -1
- data/lib/squared/common/format.rb +34 -24
- data/lib/squared/common/prompt.rb +3 -3
- data/lib/squared/common/shell.rb +53 -41
- data/lib/squared/common/system.rb +14 -21
- data/lib/squared/common/utils.rb +55 -2
- data/lib/squared/config.rb +1 -3
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +34 -43
- data/lib/squared/workspace/project/base.rb +476 -215
- data/lib/squared/workspace/project/docker.rb +572 -0
- data/lib/squared/workspace/project/git.rb +489 -256
- data/lib/squared/workspace/project/node.rb +86 -92
- data/lib/squared/workspace/project/python.rb +130 -41
- data/lib/squared/workspace/project/ruby.rb +52 -68
- data/lib/squared/workspace/project.rb +7 -1
- data/lib/squared/workspace/repo.rb +12 -5
- data/lib/squared/workspace/series.rb +1 -1
- data/squared.gemspec +4 -4
- metadata +8 -6
@@ -15,8 +15,10 @@ module Squared
|
|
15
15
|
include Rake::DSL
|
16
16
|
|
17
17
|
VAR_SET = %i[parent global envname dependfile theme run script env pass].freeze
|
18
|
-
|
19
|
-
|
18
|
+
BLK_SET = %i[run depend doc lint test copy clean].freeze
|
19
|
+
SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?\b/.freeze
|
20
|
+
URI_SCHEME = %r{^([a-z][a-z\d+-.]*)://[^@:\[\]\\^<>|\s]}i.freeze
|
21
|
+
private_constant :VAR_SET, :BLK_SET, :SEM_VER, :URI_SCHEME
|
20
22
|
|
21
23
|
class << self
|
22
24
|
def populate(*); end
|
@@ -25,7 +27,7 @@ module Squared
|
|
25
27
|
def bannerargs(*); end
|
26
28
|
|
27
29
|
def tasks
|
28
|
-
%i[build
|
30
|
+
(%i[build archive graph] + BLK_SET).freeze
|
29
31
|
end
|
30
32
|
|
31
33
|
def as_path(val)
|
@@ -51,7 +53,8 @@ module Squared
|
|
51
53
|
end
|
52
54
|
|
53
55
|
(@@tasks = {})[ref] = {
|
54
|
-
'graph' => %i[run print].freeze
|
56
|
+
'graph' => %i[run print].freeze,
|
57
|
+
'unpack' => %i[zip tar tgz tar.gz txz tar.xz].freeze
|
55
58
|
}.freeze
|
56
59
|
@@task_desc = Rake::TaskManager.record_task_metadata
|
57
60
|
@@print_order = 0
|
@@ -59,8 +62,8 @@ module Squared
|
|
59
62
|
attr_reader :name, :project, :workspace, :path, :theme, :exception, :pipe, :verbose,
|
60
63
|
:group, :parent, :dependfile
|
61
64
|
|
62
|
-
def initialize(workspace, path, name, *, group: nil, graph: nil, pass: nil, exclude: nil,
|
63
|
-
first: {}, last: {}, error: {}, common: ARG[:COMMON], **kwargs)
|
65
|
+
def initialize(workspace, path, name, *, group: nil, graph: nil, pass: nil, exclude: nil, release: nil,
|
66
|
+
archive: nil, first: {}, last: {}, error: {}, common: ARG[:COMMON], **kwargs)
|
64
67
|
@path = path
|
65
68
|
@workspace = workspace
|
66
69
|
@name = name.to_s.freeze
|
@@ -73,6 +76,13 @@ module Squared
|
|
73
76
|
@copy = kwargs[:copy]
|
74
77
|
@clean = kwargs[:clean]
|
75
78
|
@version = kwargs[:version]
|
79
|
+
@archive = case archive
|
80
|
+
when String, Array
|
81
|
+
{ uri: archive }
|
82
|
+
when Hash
|
83
|
+
archive
|
84
|
+
end
|
85
|
+
@release = release
|
76
86
|
@envname = @name.gsub(/[^\w]+/, '_').upcase.freeze
|
77
87
|
@exception = env_bool(kwargs[:exception], workspace.exception, strict: true)
|
78
88
|
@pipe = env_pipe(kwargs[:pipe], workspace.pipe, strict: true)
|
@@ -80,7 +90,7 @@ module Squared
|
|
80
90
|
when nil
|
81
91
|
workspace.verbose
|
82
92
|
when String
|
83
|
-
|
93
|
+
env_pipe(verbose, workspace.verbose, strict: true, index: true)
|
84
94
|
else
|
85
95
|
verbose
|
86
96
|
end
|
@@ -108,7 +118,7 @@ module Squared
|
|
108
118
|
@parent = nil
|
109
119
|
@global = false
|
110
120
|
run_set(kwargs[:run], kwargs[:env], opts: kwargs.fetch(:opts, true))
|
111
|
-
initialize_ref
|
121
|
+
initialize_ref Base.ref
|
112
122
|
end
|
113
123
|
|
114
124
|
def initialize_ref(ref)
|
@@ -116,7 +126,7 @@ module Squared
|
|
116
126
|
end
|
117
127
|
|
118
128
|
def initialize_build(ref, **kwargs)
|
119
|
-
initialize_ref
|
129
|
+
initialize_ref ref
|
120
130
|
if (@script = @workspace.script_get(group: @group, ref: ref))
|
121
131
|
if @script[:log] && !kwargs.key?(:log)
|
122
132
|
kwargs[:log] = @script[:log]
|
@@ -166,43 +176,40 @@ module Squared
|
|
166
176
|
def initialize_events(ref, **)
|
167
177
|
return unless (events = @workspace.events_get(group: @group, ref: ref))
|
168
178
|
|
169
|
-
events.each
|
179
|
+
events.each do |task, data|
|
180
|
+
data.each { |ev, blk| (@events[ev] ||= {})[task] ||= [blk] }
|
181
|
+
end
|
170
182
|
end
|
171
183
|
|
172
184
|
def initialize_logger(log: nil, **)
|
173
185
|
return if @log
|
174
186
|
|
175
187
|
log = log.is_a?(Hash) ? log.dup : { file: log }
|
176
|
-
|
177
|
-
file =
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
elsif (val = log[:file])
|
190
|
-
file = val.is_a?(String) ? DateTime.now.strftime(val) : "#{@name}-#{Date.today}.log"
|
191
|
-
end
|
192
|
-
if file
|
193
|
-
file = (val = env('LOG_DIR')) ? @workspace.home.join(val, file) : @workspace.home.join(file)
|
188
|
+
unless (file = env('LOG_FILE'))
|
189
|
+
file = case env('LOG_AUTO')
|
190
|
+
when 'y', 'year'
|
191
|
+
"#{@name}-#{Date.today.year}.log"
|
192
|
+
when 'm', 'month'
|
193
|
+
"#{@name}-#{Date.today.strftime('%Y-%m')}.log"
|
194
|
+
when 'd', 'day', '1'
|
195
|
+
"#{@name}-#{Date.today}.log"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
if file ||= log[:file]
|
199
|
+
file = Date.today.strftime(file)
|
200
|
+
file = (dir = env('LOG_DIR')) ? @workspace.home.join(dir, file) : @workspace.home.join(file)
|
194
201
|
begin
|
195
202
|
file = file.realdirpath
|
196
203
|
rescue StandardError => e
|
197
204
|
raise if @exception
|
198
205
|
|
199
206
|
file = nil
|
200
|
-
warn log_message(Logger::WARN, e) if warning?
|
207
|
+
warn log_message(Logger::WARN, e, pass: true) if warning?
|
201
208
|
end
|
202
209
|
end
|
203
210
|
log[:progname] ||= @name
|
204
211
|
if (val = env('LOG_LEVEL', ignore: false))
|
205
|
-
log[:level] = val
|
212
|
+
log[:level] = val.match?(/^\d$/) ? log_sym(val.to_i) : val
|
206
213
|
end
|
207
214
|
log.delete(:file)
|
208
215
|
@log = [file, log]
|
@@ -211,20 +218,18 @@ module Squared
|
|
211
218
|
def initialize_env(dev: nil, prod: nil, **)
|
212
219
|
@dev = env_match('BUILD', dev, suffix: 'DEV', strict: true)
|
213
220
|
@prod = env_match('BUILD', prod, suffix: 'PROD', strict: true)
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
221
|
+
unless @output[2] == false || !(val = env('BUILD', suffix: 'ENV'))
|
222
|
+
data = parse_json(val, hint: "BUILD_#{@envname}_ENV")
|
223
|
+
@output[2] = data if data
|
224
|
+
end
|
225
|
+
unless @output[0] == false || @output[0].is_a?(Array)
|
226
|
+
if (val = env('BUILD', suffix: 'OPTS'))
|
227
|
+
n = @output[0] ? 1 : 3
|
228
|
+
@output[n] = merge_opts(@output[n], shell_split(val, escape: false))
|
229
|
+
end
|
230
|
+
if (val = env(ref.to_s.upcase, suffix: 'OPTS'))
|
231
|
+
@output[4] = merge_opts(@output[4], shell_split(val, escape: false))
|
223
232
|
end
|
224
|
-
end
|
225
|
-
if cmd != false && !cmd.is_a?(Array)
|
226
|
-
@output[cmd ? 1 : 3] = shell_split(val, escape: false, join: true) if (val = env('BUILD', suffix: 'OPTS'))
|
227
|
-
@output[4] = shell_split(val, escape: false, join: true) if !cmd && (val = env('SCRIPT', suffix: 'OPTS'))
|
228
233
|
end
|
229
234
|
@version = val if (val = env('BUILD', suffix: 'VERSION'))
|
230
235
|
return unless (val = env('BUILD', strict: true))
|
@@ -255,18 +260,18 @@ module Squared
|
|
255
260
|
flags.each do |flag|
|
256
261
|
case action
|
257
262
|
when 'graph'
|
258
|
-
|
263
|
+
next unless graph?
|
259
264
|
|
260
265
|
format_desc action, flag, '(-)project*'
|
261
266
|
task flag do |_, args|
|
262
|
-
args = args.to_a.reject { |val| name == val.to_s }
|
267
|
+
args = param_guard(action, flag, args: args.to_a.reject { |val| name == val.to_s })
|
263
268
|
if flag == :run
|
264
269
|
graph args
|
265
270
|
else
|
266
271
|
out, done = graph(args, out: [])
|
267
272
|
out.map! do |val|
|
268
273
|
done.each_with_index do |proj, i|
|
269
|
-
next unless val
|
274
|
+
next unless val.match?(/ #{Regexp.escape(proj.name)}(?:@\d|\z)/)
|
270
275
|
|
271
276
|
val += " (#{i.succ})"
|
272
277
|
break
|
@@ -280,6 +285,25 @@ module Squared
|
|
280
285
|
])
|
281
286
|
end
|
282
287
|
end
|
288
|
+
when 'unpack'
|
289
|
+
format_desc action, flag, 'tag/url,dir,digest?,f/force?'
|
290
|
+
task flag, [:tag, :dir, :digest, :force] do |_, args|
|
291
|
+
tag = param_guard(action, flag, args: args, key: :tag)
|
292
|
+
dir = param_guard(action, flag, args: args, key: :dir)
|
293
|
+
unless tag.match?(URI_SCHEME)
|
294
|
+
raise_error 'no base uri' unless @release
|
295
|
+
|
296
|
+
tag = "#{@release.include?('??') ? @release.sub('??', tag) : @release + tag}.#{flag}"
|
297
|
+
end
|
298
|
+
case (digest = args.digest)
|
299
|
+
when 'f', 'force'
|
300
|
+
digest = nil
|
301
|
+
force = true
|
302
|
+
else
|
303
|
+
force = args.fetch(:force, false)
|
304
|
+
end
|
305
|
+
unpack(basepath(dir), uri: tag, digest: digest, ext: flag.to_s, force: force)
|
306
|
+
end
|
283
307
|
end
|
284
308
|
end
|
285
309
|
end
|
@@ -348,18 +372,19 @@ module Squared
|
|
348
372
|
|
349
373
|
out = obj.link(self, *args, **kwargs, &blk) if obj.respond_to?(:link)
|
350
374
|
if !out
|
351
|
-
warn log_message(Logger::WARN, 'link not compatible', subject: obj.to_s, hint: name)
|
375
|
+
warn log_message(Logger::WARN, 'link not compatible', subject: obj.to_s, hint: name, pass: true)
|
352
376
|
elsif out.respond_to?(:build)
|
353
377
|
out.build
|
354
378
|
end
|
355
379
|
self
|
356
380
|
end
|
357
381
|
|
358
|
-
def build(*args, sync: invoked_sync?('build'), from: :
|
382
|
+
def build(*args, sync: invoked_sync?('build'), from: @buildtype || :build, **)
|
359
383
|
banner = verbose
|
360
384
|
if args.empty?
|
361
|
-
return unless from == :
|
385
|
+
return unless from == (@buildtype || :build)
|
362
386
|
|
387
|
+
run_b(@run, sync: sync, from: from) if series?(@run)
|
363
388
|
args = @output
|
364
389
|
banner = verbose == 1 if task_invoked?('build', 'build:sync')
|
365
390
|
end
|
@@ -370,7 +395,7 @@ module Squared
|
|
370
395
|
a, b, c, d, e = val
|
371
396
|
case b
|
372
397
|
when Hash
|
373
|
-
b = append_hash(b).join(' ')
|
398
|
+
b = append_hash(b, build: true).join(' ')
|
374
399
|
when Enumerable
|
375
400
|
b = b.to_a.join(' ')
|
376
401
|
end
|
@@ -386,7 +411,7 @@ module Squared
|
|
386
411
|
end
|
387
412
|
cmd = cmd.join(' && ')
|
388
413
|
else
|
389
|
-
cmd, opts, var, flags,
|
414
|
+
cmd, opts, var, flags, extra = args
|
390
415
|
end
|
391
416
|
if cmd
|
392
417
|
cmd = as_get(cmd)
|
@@ -394,7 +419,7 @@ module Squared
|
|
394
419
|
flags = append_hash(flags).join(' ') if flags.is_a?(Hash)
|
395
420
|
case opts
|
396
421
|
when Hash
|
397
|
-
opts = append_hash(opts)
|
422
|
+
opts = append_hash(opts, build: true)
|
398
423
|
cmd = as_a(cmd).push(flags).concat(opts).compact.join(' ')
|
399
424
|
when Enumerable
|
400
425
|
cmd = as_a(cmd).concat(opts.to_a)
|
@@ -404,10 +429,9 @@ module Squared
|
|
404
429
|
cmd = [cmd, flags, opts].compact.join(' ') if opts || flags
|
405
430
|
end
|
406
431
|
else
|
407
|
-
return unless respond_to?(:compose)
|
432
|
+
return unless (opts || extra) && respond_to?(:compose)
|
408
433
|
|
409
|
-
cmd = compose(as_get(opts), flags, script: true, args:
|
410
|
-
from = :script if from == :run && script?
|
434
|
+
cmd = compose(as_get(opts), flags, script: true, args: extra, from: from)
|
411
435
|
end
|
412
436
|
run(cmd, var, from: from, banner: banner, sync: sync)
|
413
437
|
end
|
@@ -416,6 +440,12 @@ module Squared
|
|
416
440
|
run_b(@depend, sync: sync, from: :depend)
|
417
441
|
end
|
418
442
|
|
443
|
+
def archive(*, sync: invoked_sync?('archive'), **)
|
444
|
+
return unless @archive.is_a?(Array)
|
445
|
+
|
446
|
+
unpack(path, **@archive, sync: sync, from: :archive)
|
447
|
+
end
|
448
|
+
|
419
449
|
def doc(*, sync: invoked_sync?('doc'), **)
|
420
450
|
run_b(@doc, sync: sync, from: :doc)
|
421
451
|
end
|
@@ -445,27 +475,31 @@ module Squared
|
|
445
475
|
rescue StandardError => e
|
446
476
|
log&.error e
|
447
477
|
ret = on(:error, from, e)
|
448
|
-
raise if
|
478
|
+
raise if exception && ret != true
|
449
479
|
end
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
480
|
+
else
|
481
|
+
if @clean.is_a?(Enumerable) && !series?(@clean)
|
482
|
+
as_a(@clean).each do |val|
|
483
|
+
val = val.to_s
|
484
|
+
path = basepath(val)
|
485
|
+
if path.directory? && val.match?(%r{[\\/]$})
|
486
|
+
log&.warn "rm -rf #{path}"
|
487
|
+
path.rmtree(verbose: verbose)
|
488
|
+
else
|
489
|
+
log&.warn "rm #{path}"
|
490
|
+
(val.include?('*') ? Dir[path] : [path]).each do |file|
|
491
|
+
next unless File.file?(file)
|
492
|
+
|
493
|
+
begin
|
494
|
+
File.delete(file)
|
495
|
+
rescue StandardError => e
|
496
|
+
log&.error e
|
497
|
+
end
|
466
498
|
end
|
467
499
|
end
|
468
500
|
end
|
501
|
+
else
|
502
|
+
run_b(@clean, sync: sync)
|
469
503
|
end
|
470
504
|
end
|
471
505
|
on :last, :clean
|
@@ -502,6 +536,119 @@ module Squared
|
|
502
536
|
end
|
503
537
|
end
|
504
538
|
|
539
|
+
def unpack(target, sync: true, uri: nil, digest: nil, ext: nil, force: false, depth: 1, headers: {},
|
540
|
+
from: :unpack)
|
541
|
+
if !target.exist?
|
542
|
+
target.mkpath
|
543
|
+
elsif !target.directory?
|
544
|
+
raise_error('invalid location', hint: target)
|
545
|
+
elsif !target.empty?
|
546
|
+
raise_error('directory not empty', hint: target) unless force || env('UNPACK_FORCE')
|
547
|
+
create = true
|
548
|
+
end
|
549
|
+
if digest
|
550
|
+
if (n = digest.index(':').to_i) > 0
|
551
|
+
size = digest[0, n].downcase
|
552
|
+
digest = digest[n + 1..-1]
|
553
|
+
else
|
554
|
+
size = digest.size
|
555
|
+
end
|
556
|
+
algo = case size
|
557
|
+
when 32, 'md5'
|
558
|
+
Digest::MD5
|
559
|
+
when 'rmd160'
|
560
|
+
Digest::RMD160
|
561
|
+
when 40, 'sha1'
|
562
|
+
Digest::SHA1
|
563
|
+
when 64, 'sha256'
|
564
|
+
Digest::SHA256
|
565
|
+
when 96, 'sha384'
|
566
|
+
Digest::SHA384
|
567
|
+
when 128, 'sha512'
|
568
|
+
Digest::SHA512
|
569
|
+
else
|
570
|
+
raise_error("invalid checksum: #{digest}", hint: name)
|
571
|
+
end
|
572
|
+
end
|
573
|
+
if (val = env('HEADERS')) && (out = parse_json(val, hint: "HEADERS_#{@envname}"))
|
574
|
+
headers = out
|
575
|
+
end
|
576
|
+
require 'open-uri'
|
577
|
+
data = nil
|
578
|
+
(uri = as_a(uri)).each_with_index do |url, index|
|
579
|
+
last = index == uri.size - 1
|
580
|
+
URI.open(url, headers) do |f|
|
581
|
+
data = f.read
|
582
|
+
if algo && algo.hexdigest(data) != digest
|
583
|
+
data = nil
|
584
|
+
raise_error("checksum failed: #{digest}", hint: url) if last
|
585
|
+
end
|
586
|
+
next if ext && index == 0
|
587
|
+
|
588
|
+
case f.content_type
|
589
|
+
when 'application/zip'
|
590
|
+
ext = 'zip'
|
591
|
+
when 'application/x-gzip'
|
592
|
+
ext = 'tgz'
|
593
|
+
when 'application/x-xz'
|
594
|
+
ext = 'txz'
|
595
|
+
end
|
596
|
+
end
|
597
|
+
if data
|
598
|
+
uri = url
|
599
|
+
break
|
600
|
+
elsif last
|
601
|
+
raise_error('no content', hint: url)
|
602
|
+
end
|
603
|
+
end
|
604
|
+
ext ||= URI.parse(uri).path[/^.+?\.((?:tar\.)?\w+)$/i, 1]
|
605
|
+
if (n = env("#{ext == 'zip' ? 'ZIP' : 'TAR'}_DEPTH", ignore: false))
|
606
|
+
depth = n.to_i
|
607
|
+
end
|
608
|
+
begin
|
609
|
+
require 'tempfile'
|
610
|
+
file = Tempfile.new("#{name}-")
|
611
|
+
file.write(data)
|
612
|
+
file.close
|
613
|
+
if create
|
614
|
+
warn log_message(Logger::WARN, name, 'force remove', hint: target, pass: true)
|
615
|
+
target.rmtree(verbose: true)
|
616
|
+
target.mkpath
|
617
|
+
end
|
618
|
+
case ext
|
619
|
+
when 'zip', 'aar'
|
620
|
+
session 'unzip', shell_quote(file.path), quote_option('d', target)
|
621
|
+
when 'tar', 'tgz', 'tar.gz', 'tar.xz'
|
622
|
+
flags = +(verbose ? 'v' : '')
|
623
|
+
case ext
|
624
|
+
when 'tgz', 'tar.gz'
|
625
|
+
flags += 'z'
|
626
|
+
when 'txz', 'tar.xz'
|
627
|
+
flags += 'J'
|
628
|
+
end
|
629
|
+
session 'tar', "-x#{flags}", basic_option('strip-components', depth), quote_option('f', file.path),
|
630
|
+
quote_option('C', target)
|
631
|
+
depth = 0
|
632
|
+
else
|
633
|
+
raise_error("unsupported format: #{ext}", hint: uri)
|
634
|
+
end
|
635
|
+
run(sync: sync, from: from)
|
636
|
+
while depth > 0 && target.children.size == 1
|
637
|
+
entry = target.children.first
|
638
|
+
break unless entry.directory?
|
639
|
+
|
640
|
+
dest = target.join(File.basename(file.path))
|
641
|
+
FileUtils.mv(entry, dest)
|
642
|
+
dest.children.each { |file| FileUtils.mv(file, target) }
|
643
|
+
dest.rmdir
|
644
|
+
target = entry
|
645
|
+
depth -= 1
|
646
|
+
end
|
647
|
+
ensure
|
648
|
+
file&.unlink
|
649
|
+
end
|
650
|
+
end
|
651
|
+
|
505
652
|
def first(key, *args, **kwargs, &blk)
|
506
653
|
event(:first, key, *args, **kwargs, &blk)
|
507
654
|
end
|
@@ -514,17 +661,38 @@ module Squared
|
|
514
661
|
event(:error, key, *args, **kwargs, &blk)
|
515
662
|
end
|
516
663
|
|
517
|
-
def event(name, key, *args, **kwargs, &blk)
|
518
|
-
|
664
|
+
def event(name, key, *args, override: false, **kwargs, &blk)
|
665
|
+
data = @events[name.to_sym] ||= {}
|
666
|
+
items = if override
|
667
|
+
data[key.to_sym] = []
|
668
|
+
else
|
669
|
+
data[key.to_sym] ||= []
|
670
|
+
end
|
671
|
+
items << [block_given? ? [blk] + args : args, kwargs]
|
672
|
+
self
|
519
673
|
end
|
520
674
|
|
521
675
|
def as(cmd, script, to = nil)
|
522
676
|
script = { "#{script}": to } if to
|
523
677
|
data = (@as ||= {})[cmd.to_sym] ||= {}
|
524
678
|
script.each { |key, val| data[key.to_s] = val }
|
679
|
+
self
|
680
|
+
end
|
681
|
+
|
682
|
+
def series(key, override: false, &blk)
|
683
|
+
if blocks.include?(key.to_sym) && block_given?
|
684
|
+
if !override && series?(target = instance_variable_get(:"@#{key}"))
|
685
|
+
target << blk
|
686
|
+
else
|
687
|
+
instance_variable_set :"@#{key}", [blk]
|
688
|
+
end
|
689
|
+
else
|
690
|
+
log&.warn "series: @#{key} (invalid)"
|
691
|
+
end
|
692
|
+
self
|
525
693
|
end
|
526
694
|
|
527
|
-
def variable_set(key, *val, **kwargs)
|
695
|
+
def variable_set(key, *val, **kwargs, &blk)
|
528
696
|
if variables.include?(key)
|
529
697
|
case key
|
530
698
|
when :build, :run
|
@@ -545,17 +713,22 @@ module Squared
|
|
545
713
|
when :dependfile
|
546
714
|
@dependfile = basepath(*val)
|
547
715
|
else
|
548
|
-
|
716
|
+
if blocks.include?(key) && block_given?
|
717
|
+
series key, &blk
|
718
|
+
else
|
719
|
+
instance_variable_set(:"@#{key}", block_given? && val.empty? ? blk : val.first)
|
720
|
+
end
|
549
721
|
end
|
550
722
|
else
|
551
723
|
log&.warn "variable_set: @#{key} (private)"
|
552
724
|
end
|
725
|
+
self
|
553
726
|
end
|
554
727
|
|
555
728
|
def enabled?(ref = nil, **)
|
556
729
|
return false if ref && !ref?(ref)
|
557
730
|
|
558
|
-
path.directory? && !path.empty?
|
731
|
+
(path.directory? && !path.empty?) || archive?
|
559
732
|
end
|
560
733
|
|
561
734
|
def has?(meth, ref = nil)
|
@@ -569,7 +742,7 @@ module Squared
|
|
569
742
|
end
|
570
743
|
|
571
744
|
def build?
|
572
|
-
!!@output[0] || script?
|
745
|
+
!!@output[0] || script? || series?(@run)
|
573
746
|
end
|
574
747
|
|
575
748
|
def script?
|
@@ -580,6 +753,10 @@ module Squared
|
|
580
753
|
!!@depend
|
581
754
|
end
|
582
755
|
|
756
|
+
def archive?
|
757
|
+
@archive.is_a?(Hash) && (!path.exist? || path.empty?)
|
758
|
+
end
|
759
|
+
|
583
760
|
def graph?
|
584
761
|
@graph.is_a?(Array) && !@graph.empty?
|
585
762
|
end
|
@@ -640,8 +817,12 @@ module Squared
|
|
640
817
|
@ref.reverse_each
|
641
818
|
end
|
642
819
|
|
643
|
-
def basepath(*args
|
644
|
-
|
820
|
+
def basepath(*args)
|
821
|
+
path.join(*args)
|
822
|
+
end
|
823
|
+
|
824
|
+
def rootpath(*args, ascend: nil)
|
825
|
+
ret = basepath(*args)
|
645
826
|
return ret unless ascend && !ret.exist?
|
646
827
|
|
647
828
|
path.parent.ascend.each do |dir|
|
@@ -676,8 +857,10 @@ module Squared
|
|
676
857
|
|
677
858
|
def run(cmd = @session, var = nil, exception: @exception, sync: true, banner: true, chdir: path, from: nil, **)
|
678
859
|
unless cmd
|
679
|
-
|
680
|
-
|
860
|
+
if warning?
|
861
|
+
from &&= from.to_s
|
862
|
+
warn log_message(Logger::WARN, from || 'unknown', subject: project, hint: 'no command given', pass: true)
|
863
|
+
end
|
681
864
|
return
|
682
865
|
end
|
683
866
|
cmd = session_done(cmd)
|
@@ -688,7 +871,7 @@ module Squared
|
|
688
871
|
log&.warn "ENV was discarded: #{var}" if var
|
689
872
|
task_invoke(cmd, exception: exception, warning: warning?)
|
690
873
|
else
|
691
|
-
print_item format_banner(cmd, banner: banner) if sync
|
874
|
+
print_item format_banner(cmd, banner: banner) if sync
|
692
875
|
args = var.is_a?(Hash) ? [var, cmd] : [cmd]
|
693
876
|
shell(*args, chdir: chdir, exception: exception)
|
694
877
|
end
|
@@ -713,18 +896,23 @@ module Squared
|
|
713
896
|
end
|
714
897
|
|
715
898
|
def run_b(obj, from: nil, sync: true)
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
build(*obj, from: from, sync: sync)
|
899
|
+
case obj
|
900
|
+
when Proc, Method
|
901
|
+
obj.call
|
720
902
|
else
|
721
|
-
|
903
|
+
if series?(obj)
|
904
|
+
obj.each(&:call)
|
905
|
+
elsif obj.is_a?(Array) && obj.any? { |val| !val.is_a?(String) }
|
906
|
+
build(*obj, from: from, sync: sync)
|
907
|
+
elsif obj
|
908
|
+
run_s(obj.is_a?(Enumerable) ? obj.to_a : obj, from: from, sync: sync)
|
909
|
+
end
|
722
910
|
end
|
723
911
|
end
|
724
912
|
|
725
913
|
def graph_branch(target, data, tasks = nil, out = nil, sync: true, pass: [], done: [], depth: 0,
|
726
914
|
single: false, last: false, context: nil)
|
727
|
-
tag = ->(proj) { "#{proj.name}#{SEM_VER
|
915
|
+
tag = ->(proj) { "#{proj.name}#{SEM_VER.match?(proj.version) ? "@#{proj.version}" : ''}" }
|
728
916
|
check = ->(deps) { deps.reject { |val| done.include?(val) } }
|
729
917
|
dedupe = lambda do |name|
|
730
918
|
next [] unless (ret = data[name])
|
@@ -764,7 +952,7 @@ module Squared
|
|
764
952
|
|
765
953
|
t = dedupe.(proj.name)
|
766
954
|
j = if out
|
767
|
-
if i == items.size - 1 || check.(post = items[
|
955
|
+
if i == items.size - 1 || check.(post = items[i + 1..-1]).empty?
|
768
956
|
true
|
769
957
|
elsif !t.empty? && depth > 0
|
770
958
|
post.reject { |pr| t.include?(pr) }.empty?
|
@@ -782,13 +970,7 @@ module Squared
|
|
782
970
|
next if pass.include?(meth)
|
783
971
|
|
784
972
|
if workspace.task_defined?(cmd = task_join(proj.name, meth))
|
785
|
-
if ENV.key?(key = "BANNER_#{proj.name.upcase}")
|
786
|
-
key = nil
|
787
|
-
else
|
788
|
-
ENV[key] = '0'
|
789
|
-
end
|
790
973
|
run(cmd, sync: false, banner: false)
|
791
|
-
ENV.delete(key) if key
|
792
974
|
elsif proj.has?(meth, tasks || group ? nil : workspace.baseref)
|
793
975
|
proj.__send__(meth.to_sym, sync: sync)
|
794
976
|
end
|
@@ -802,7 +984,7 @@ module Squared
|
|
802
984
|
k = 0
|
803
985
|
final = data.keys.last
|
804
986
|
while k < depth
|
805
|
-
indent = k > 0
|
987
|
+
indent = k > 0 && ((last && !j) || (j && k == depth - 1) || single)
|
806
988
|
s += "#{indent || (last && data[final].last == context) ? ' ' : a} "
|
807
989
|
k += 1
|
808
990
|
end
|
@@ -814,7 +996,7 @@ module Squared
|
|
814
996
|
done
|
815
997
|
end
|
816
998
|
|
817
|
-
def graph_collect(target, start = [], data: {}, pass: []
|
999
|
+
def graph_collect(target, start = [], data: {}, pass: [])
|
818
1000
|
deps = []
|
819
1001
|
(start.empty? ? target.instance_variable_get(:@graph) : start)&.each do |val|
|
820
1002
|
next if pass.include?(val)
|
@@ -826,21 +1008,18 @@ module Squared
|
|
826
1008
|
else
|
827
1009
|
items = workspace.find(group: val, ref: val.to_sym)
|
828
1010
|
end
|
1011
|
+
|
829
1012
|
items.each do |proj|
|
830
|
-
next if pass.include?(
|
1013
|
+
next if pass.include?(proj.name)
|
831
1014
|
|
832
|
-
if proj.graph? && !data.key?(
|
833
|
-
|
834
|
-
end
|
835
|
-
next if (objs = data.fetch(name, [])).include?(target)
|
1015
|
+
graph_collect(proj, data: data, pass: pass) if proj.graph? && !data.key?(proj.name)
|
1016
|
+
next if (objs = data.fetch(proj.name, [])).include?(target)
|
836
1017
|
|
837
1018
|
deps << proj
|
838
|
-
deps
|
1019
|
+
deps += objs
|
839
1020
|
end
|
840
1021
|
end
|
841
|
-
deps.uniq
|
842
|
-
deps.delete(target)
|
843
|
-
data[target.name] = deps
|
1022
|
+
data[target.name] = deps.uniq.reject { |proj| proj == target }
|
844
1023
|
data
|
845
1024
|
end
|
846
1025
|
|
@@ -860,7 +1039,7 @@ module Squared
|
|
860
1039
|
end
|
861
1040
|
|
862
1041
|
def session(*cmd, prefix: cmd.first, main: true, options: true)
|
863
|
-
prefix =
|
1042
|
+
prefix = prefix.to_s.upcase
|
864
1043
|
if (val = PATH[prefix] || PATH[prefix.to_sym])
|
865
1044
|
cmd[0] = shell_quote(val, force: false)
|
866
1045
|
end
|
@@ -874,8 +1053,7 @@ module Squared
|
|
874
1053
|
def session_delete(*list, target: @session)
|
875
1054
|
ret = []
|
876
1055
|
list.each do |val|
|
877
|
-
|
878
|
-
if (key = target.find { |opt| opt =~ pat })
|
1056
|
+
if (key = target.find { |opt| opt.match?(/^#{Regexp.escape(shell_option(val))}(?: |=|$)/o) })
|
879
1057
|
target.delete(key)
|
880
1058
|
ret << key
|
881
1059
|
end
|
@@ -890,30 +1068,33 @@ module Squared
|
|
890
1068
|
def session_done(cmd)
|
891
1069
|
return cmd unless cmd.respond_to?(:done)
|
892
1070
|
|
893
|
-
raise_error('no args
|
1071
|
+
raise_error('no args added', hint: cmd.first || name) unless cmd.size > 1
|
894
1072
|
@session = nil if cmd == @session
|
895
1073
|
cmd.done
|
896
1074
|
end
|
897
1075
|
|
898
|
-
def option(*args,
|
1076
|
+
def option(*args, prefix: @session&.first, **kwargs)
|
899
1077
|
if prefix
|
900
1078
|
args.each do |val|
|
901
|
-
ret = env("#{
|
1079
|
+
ret = env("#{prefix}_#{val.gsub(/\W/, '_')}".upcase, **kwargs)
|
902
1080
|
return ret if ret
|
903
1081
|
end
|
904
1082
|
end
|
905
1083
|
nil
|
906
1084
|
end
|
907
1085
|
|
908
|
-
def option_sanitize(opts, list, target: @session, no: nil,
|
1086
|
+
def option_sanitize(opts, list, target: @session, no: nil, first: false, pass: ['='])
|
909
1087
|
ret = []
|
910
1088
|
reg = []
|
911
1089
|
bare = []
|
912
1090
|
e = []
|
913
1091
|
b = []
|
1092
|
+
m = []
|
914
1093
|
p = []
|
915
1094
|
q = []
|
1095
|
+
qq = []
|
916
1096
|
i = []
|
1097
|
+
f = []
|
917
1098
|
list = list.map do |val|
|
918
1099
|
x, y = val.split('|')
|
919
1100
|
if y
|
@@ -933,16 +1114,19 @@ module Squared
|
|
933
1114
|
e << flag
|
934
1115
|
when 'b'
|
935
1116
|
b << flag
|
1117
|
+
when 'm'
|
1118
|
+
m << flag
|
936
1119
|
when 'q'
|
1120
|
+
qq << flag if val[n + 2] == 'q'
|
937
1121
|
q << flag
|
938
1122
|
when 'p'
|
939
1123
|
p << flag
|
940
1124
|
when 'i'
|
941
1125
|
i << flag
|
942
|
-
when '
|
943
|
-
|
1126
|
+
when 'f'
|
1127
|
+
f << flag
|
944
1128
|
else
|
945
|
-
|
1129
|
+
reg << Regexp.escape(flag)
|
946
1130
|
end
|
947
1131
|
bare << flag if val.end_with?('?')
|
948
1132
|
else
|
@@ -960,40 +1144,41 @@ module Squared
|
|
960
1144
|
elsif opt.start_with?('no-') && no.include?(name = opt[3..-1])
|
961
1145
|
target << "--no-#{name}"
|
962
1146
|
else
|
963
|
-
if opt =~
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
target <<
|
969
|
-
elsif
|
970
|
-
target << quote_option(
|
971
|
-
elsif
|
972
|
-
target <<
|
1147
|
+
if opt =~ /^([^=]+)=(.+)$/
|
1148
|
+
key = $1
|
1149
|
+
val = $2
|
1150
|
+
match = ->(flag, pat) { flag.include?(key) && pat.match?(val) }
|
1151
|
+
if e.include?(key)
|
1152
|
+
target << shell_option(key, val)
|
1153
|
+
elsif q.include?(key)
|
1154
|
+
target << quote_option(key, val, double: qq.include?(key))
|
1155
|
+
elsif p.include?(key)
|
1156
|
+
target << quote_option(key, basepath(val))
|
1157
|
+
elsif m.include?(key)
|
1158
|
+
target << basic_option(key, val, merge: true)
|
1159
|
+
elsif b.include?(key) || match.(i, /^\d+$/) || match.(f, /^\d*(?:\.\d+)?$/)
|
1160
|
+
target << basic_option(key, val)
|
973
1161
|
else
|
974
1162
|
ret << opt
|
975
1163
|
end
|
976
|
-
opt =
|
1164
|
+
opt = key
|
977
1165
|
else
|
978
1166
|
ret << opt
|
979
|
-
found = true if args
|
980
1167
|
end
|
981
|
-
found = true if first && pass.none? { |
|
1168
|
+
found = true if first && pass.none? { |s| opt.include?(s) }
|
982
1169
|
end
|
983
1170
|
end
|
984
|
-
[ret, reg.empty? ? /\A\s+\z/ :
|
1171
|
+
[ret, reg.empty? ? /\A\s+\z/ : /^(#{reg.join('|')})=(.+)$/]
|
985
1172
|
end
|
986
1173
|
|
987
1174
|
def option_clear(opts, target: @session, **kwargs)
|
988
|
-
return if opts.empty?
|
989
|
-
|
990
1175
|
kwargs[:subject] ||= target&.first
|
991
|
-
kwargs[:hint] ||= '
|
992
|
-
warn log_message(
|
1176
|
+
kwargs[:hint] ||= 'not used'
|
1177
|
+
warn log_message(Logger::WARN, opts.join(', '), pass: true, **kwargs) unless opts.empty?
|
993
1178
|
end
|
994
1179
|
|
995
1180
|
def print_item(*val)
|
996
|
-
puts if @@print_order > 0
|
1181
|
+
puts if @@print_order > 0 && verbose && !stdin?
|
997
1182
|
@@print_order += 1
|
998
1183
|
puts val unless val.empty? || (val.size == 1 && val.first.nil?)
|
999
1184
|
end
|
@@ -1019,7 +1204,7 @@ module Squared
|
|
1019
1204
|
val
|
1020
1205
|
end
|
1021
1206
|
end
|
1022
|
-
out << sub_style(
|
1207
|
+
out << sub_style(ARG[:BORDER][1] * n, styles: border)
|
1023
1208
|
out.join("\n")
|
1024
1209
|
end
|
1025
1210
|
|
@@ -1031,7 +1216,7 @@ module Squared
|
|
1031
1216
|
sub.each { |h| s = sub_style(s, **h) }
|
1032
1217
|
s
|
1033
1218
|
end
|
1034
|
-
ret = [sub_style(
|
1219
|
+
ret = [sub_style(ARG[:BORDER][1] * n, styles: kwargs.key?(:border) ? kwargs[:border] : borderstyle), *lines]
|
1035
1220
|
ret.reverse! if reverse
|
1036
1221
|
ret.join("\n")
|
1037
1222
|
end
|
@@ -1057,7 +1242,7 @@ module Squared
|
|
1057
1242
|
if verbose
|
1058
1243
|
out = []
|
1059
1244
|
if data[:command]
|
1060
|
-
if /\A(?:"((?:[^"]|(?<=\\)")+)"|'((?:[^']|(?<=\\)')+)'|(\S+))
|
1245
|
+
if cmd =~ /\A(?:"((?:[^"]|(?<=\\)")+)"|'((?:[^']|(?<=\\)')+)'|(\S+)) /
|
1061
1246
|
path = $3 || $2 || $1
|
1062
1247
|
cmd = cmd.sub(path, File.basename(path).upcase)
|
1063
1248
|
end
|
@@ -1095,9 +1280,9 @@ module Squared
|
|
1095
1280
|
unless items.empty?
|
1096
1281
|
pad = items.size.to_s.size
|
1097
1282
|
items.each_with_index do |val, i|
|
1098
|
-
next unless reg.empty? || reg.any? { |pat| val[0]
|
1283
|
+
next unless reg.empty? || reg.any? { |pat| val[0].match?(pat) }
|
1099
1284
|
|
1100
|
-
out << "#{
|
1285
|
+
out << "#{i.succ.to_s.rjust(pad)}. #{each ? each.(val) : val[0]}"
|
1101
1286
|
end
|
1102
1287
|
end
|
1103
1288
|
sub = [headerstyle]
|
@@ -1131,9 +1316,9 @@ module Squared
|
|
1131
1316
|
opts.each { |val| target << shell_option(flag, val) }
|
1132
1317
|
end
|
1133
1318
|
|
1134
|
-
def append_hash(data, target: @session)
|
1319
|
+
def append_hash(data, target: @session, build: false)
|
1135
1320
|
target ||= []
|
1136
|
-
if (type = env('BUILD', suffix: 'TYPE') || ENV['BUILD_TYPE'])
|
1321
|
+
if build && (type = env('BUILD', suffix: 'TYPE') || ENV['BUILD_TYPE'])
|
1137
1322
|
type = "__#{type}__"
|
1138
1323
|
if (extra = data[type] || data[type.to_sym]).is_a?(Hash)
|
1139
1324
|
data = data.merge(extra)
|
@@ -1162,7 +1347,7 @@ module Squared
|
|
1162
1347
|
target
|
1163
1348
|
end
|
1164
1349
|
|
1165
|
-
def append_any(val, target: @session, delim: false)
|
1350
|
+
def append_any(val, target: @session, build: false, delim: false)
|
1166
1351
|
if delim && !target.include?('--')
|
1167
1352
|
target << '--'
|
1168
1353
|
else
|
@@ -1172,7 +1357,7 @@ module Squared
|
|
1172
1357
|
when String
|
1173
1358
|
target << val
|
1174
1359
|
when Hash
|
1175
|
-
append_hash(val, target: target)
|
1360
|
+
append_hash(val, target: target, build: build)
|
1176
1361
|
when Enumerable
|
1177
1362
|
if target.is_a?(Array)
|
1178
1363
|
target.concat(val.to_a)
|
@@ -1181,6 +1366,7 @@ module Squared
|
|
1181
1366
|
end
|
1182
1367
|
else
|
1183
1368
|
target.delete('--') if delim
|
1369
|
+
nil
|
1184
1370
|
end
|
1185
1371
|
end
|
1186
1372
|
|
@@ -1189,8 +1375,9 @@ module Squared
|
|
1189
1375
|
|
1190
1376
|
target << '--' if delim && !target.include?('--')
|
1191
1377
|
list.map do |val|
|
1192
|
-
|
1193
|
-
|
1378
|
+
item = escape ? shell_escape(val, quote: quote) : shell_quote(val)
|
1379
|
+
target << item
|
1380
|
+
item
|
1194
1381
|
end
|
1195
1382
|
end
|
1196
1383
|
|
@@ -1198,8 +1385,8 @@ module Squared
|
|
1198
1385
|
**kwargs)
|
1199
1386
|
return if (list = list.flatten).empty?
|
1200
1387
|
|
1201
|
-
list.
|
1202
|
-
next unless (val = option(opt,
|
1388
|
+
list.each do |opt|
|
1389
|
+
next unless (val = option(opt, **kwargs))
|
1203
1390
|
|
1204
1391
|
return target << (if flag
|
1205
1392
|
shell_option(opt, equals ? val : nil, quote: quote, escape: escape, force: force)
|
@@ -1215,7 +1402,7 @@ module Squared
|
|
1215
1402
|
return if (list = list.flatten).empty?
|
1216
1403
|
|
1217
1404
|
ret = []
|
1218
|
-
list.
|
1405
|
+
list.each do |flag|
|
1219
1406
|
next unless (val = option(flag, **kwargs))
|
1220
1407
|
|
1221
1408
|
if val == '0' && no
|
@@ -1228,7 +1415,45 @@ module Squared
|
|
1228
1415
|
end
|
1229
1416
|
|
1230
1417
|
def append_nocolor(target: @session)
|
1231
|
-
target << '--no-color' if !ARG[:COLOR] || stdin? || option('no-color',
|
1418
|
+
target << '--no-color' if !ARG[:COLOR] || stdin? || option('no-color', ignore: false)
|
1419
|
+
end
|
1420
|
+
|
1421
|
+
def merge_opts(base, data)
|
1422
|
+
return data unless base
|
1423
|
+
return base unless data
|
1424
|
+
|
1425
|
+
ret = case data
|
1426
|
+
when String
|
1427
|
+
case base
|
1428
|
+
when String
|
1429
|
+
"#{base} #{data}"
|
1430
|
+
when Hash
|
1431
|
+
"#{append_hash(base).join(' ')} #{data}"
|
1432
|
+
when Enumerable
|
1433
|
+
"#{base.to_a.join(' ')} #{data}"
|
1434
|
+
end
|
1435
|
+
when Hash
|
1436
|
+
case base
|
1437
|
+
when String
|
1438
|
+
"#{base} #{append_hash(data).join(' ')}"
|
1439
|
+
when Hash
|
1440
|
+
base.merge(data)
|
1441
|
+
when Enumerable
|
1442
|
+
base.to_a + append_hash(data)
|
1443
|
+
end
|
1444
|
+
when Enumerable
|
1445
|
+
case base
|
1446
|
+
when String
|
1447
|
+
"#{base} #{data.to_a.join(' ')}"
|
1448
|
+
when Hash
|
1449
|
+
"#{append_hash(base).join(' ')} #{data.to_a.join(' ')}"
|
1450
|
+
when Enumerable
|
1451
|
+
base.to_a + data.to_a
|
1452
|
+
end
|
1453
|
+
else
|
1454
|
+
base
|
1455
|
+
end
|
1456
|
+
ret || data
|
1232
1457
|
end
|
1233
1458
|
|
1234
1459
|
def collect_hash(data, pass: [])
|
@@ -1237,10 +1462,19 @@ module Squared
|
|
1237
1462
|
ret
|
1238
1463
|
end
|
1239
1464
|
|
1240
|
-
def
|
1465
|
+
def parse_json(val, hint: nil)
|
1466
|
+
ret = JSON.parse(val)
|
1467
|
+
raise_error('invalid JSON object', val, hint: hint) unless ret.is_a?(Hash)
|
1468
|
+
rescue StandardError => e
|
1469
|
+
log&.warn e
|
1470
|
+
else
|
1471
|
+
ret
|
1472
|
+
end
|
1473
|
+
|
1474
|
+
def param_guard(action, flag, args: nil, key: nil, pat: nil, values: nil)
|
1241
1475
|
if args && key
|
1242
|
-
val = args
|
1243
|
-
return val unless val.nil? || (pat && !val.match?(pat))
|
1476
|
+
val = args[key]
|
1477
|
+
return val unless val.nil? || (pat && !val.match?(pat)) || (values && !values.include?(val))
|
1244
1478
|
|
1245
1479
|
@session = nil
|
1246
1480
|
raise_error(action, "#{flag}[#{key}]", hint: val.nil? ? 'missing' : 'invalid')
|
@@ -1251,6 +1485,17 @@ module Squared
|
|
1251
1485
|
args
|
1252
1486
|
end
|
1253
1487
|
|
1488
|
+
def relativepath(*files, all: false)
|
1489
|
+
return [] if files.empty?
|
1490
|
+
|
1491
|
+
files.flatten.map { |val| Pathname.new(val) }.select { |val| projectpath?(val) }.map do |val|
|
1492
|
+
val = val.absolute? ? val.to_s.sub(/^#{Regexp.escape(File.join(path, ''))}/o, '') : val.to_s
|
1493
|
+
val = val[2..-1] if val.start_with?('./')
|
1494
|
+
val = "#{val}*" if all && val.end_with?('/')
|
1495
|
+
val
|
1496
|
+
end
|
1497
|
+
end
|
1498
|
+
|
1254
1499
|
def projectmap(files, parent: false)
|
1255
1500
|
files = files.select { |val| projectpath?(val) } unless parent
|
1256
1501
|
files.map { |val| val == '.' ? '.' : shell_quote(basepath(val.strip)) }
|
@@ -1273,41 +1518,16 @@ module Squared
|
|
1273
1518
|
fill ? semver(ret) : ret
|
1274
1519
|
end
|
1275
1520
|
|
1276
|
-
def semcmp(val, other)
|
1277
|
-
return 0 if val == other
|
1278
|
-
|
1279
|
-
a, b = [val, other].map! { |ver| ver.scan(SEM_VER) }
|
1280
|
-
return -1 if b.empty?
|
1281
|
-
return 1 if a.empty?
|
1282
|
-
|
1283
|
-
a, b = [a.first, b.first].map! do |c|
|
1284
|
-
begin
|
1285
|
-
d = Integer(c[5]).to_s
|
1286
|
-
rescue StandardError
|
1287
|
-
d = c[5] ? '-1' : '0'
|
1288
|
-
end
|
1289
|
-
[c[0], c[2], c[4] || '0', d]
|
1290
|
-
end
|
1291
|
-
a.each_with_index do |c, index|
|
1292
|
-
next if c == (d = b[index])
|
1293
|
-
|
1294
|
-
return c.to_i < d.to_i ? 1 : -1
|
1295
|
-
end
|
1296
|
-
0
|
1297
|
-
end
|
1298
|
-
|
1299
1521
|
def indexitem(val)
|
1300
|
-
|
1522
|
+
return unless val =~ /\A\^(\d+)(:.+)?\z/
|
1523
|
+
|
1524
|
+
[$1.to_i, $2 && $2[1..-1]]
|
1301
1525
|
end
|
1302
1526
|
|
1303
1527
|
def indexerror(val, list = nil)
|
1304
1528
|
raise_error("requested index #{val}", hint: list && "of #{list.size}")
|
1305
1529
|
end
|
1306
1530
|
|
1307
|
-
def indexchar
|
1308
|
-
workspace.windows? ? '+' : '^'
|
1309
|
-
end
|
1310
|
-
|
1311
1531
|
def color(val)
|
1312
1532
|
ret = theme[val]
|
1313
1533
|
ret && !ret.empty? ? ret : [val]
|
@@ -1317,22 +1537,28 @@ module Squared
|
|
1317
1537
|
val.compact.map { |s| color(s) }.flatten
|
1318
1538
|
end
|
1319
1539
|
|
1540
|
+
def epochtime
|
1541
|
+
DateTime.now.strftime('%Q').to_i
|
1542
|
+
end
|
1543
|
+
|
1320
1544
|
def on(event, from, *args, **kwargs)
|
1321
|
-
return unless from
|
1545
|
+
return unless from
|
1322
1546
|
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1547
|
+
@events[event][from]&.each do |obj|
|
1548
|
+
if obj.is_a?(Array) && obj[1].is_a?(Hash)
|
1549
|
+
opts = kwargs.empty? ? obj[1] : obj[1].merge(kwargs)
|
1550
|
+
target = obj[0]
|
1551
|
+
else
|
1552
|
+
opts = kwargs
|
1553
|
+
target = obj
|
1554
|
+
end
|
1555
|
+
as_a(target, flat: true).each do |cmd|
|
1556
|
+
case cmd
|
1557
|
+
when Proc, Method
|
1558
|
+
cmd.call(*args, **opts)
|
1559
|
+
when String
|
1560
|
+
run(cmd, **opts)
|
1561
|
+
end
|
1336
1562
|
end
|
1337
1563
|
end
|
1338
1564
|
end
|
@@ -1341,8 +1567,7 @@ module Squared
|
|
1341
1567
|
pwd = Pathname.pwd
|
1342
1568
|
if block_given?
|
1343
1569
|
begin
|
1344
|
-
|
1345
|
-
if (path == pwd || pass == true) && !workspace.jruby_win?
|
1570
|
+
if path == pwd || pass == true || (pass.is_a?(String) && semscan(pass).join >= RUBY_VERSION)
|
1346
1571
|
ret = instance_eval(&blk)
|
1347
1572
|
else
|
1348
1573
|
Dir.chdir(path)
|
@@ -1374,23 +1599,53 @@ module Squared
|
|
1374
1599
|
end
|
1375
1600
|
|
1376
1601
|
def run_set(cmd, val = nil, opts: nil, **)
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1602
|
+
diso = @output[1] == false && !@output[0].nil?
|
1603
|
+
dise = @output[2] == false
|
1604
|
+
parse = lambda do |data|
|
1605
|
+
ret = []
|
1606
|
+
if data[:command]
|
1607
|
+
ret[0] = data[:command]
|
1608
|
+
ret[1] = data[:opts] unless diso
|
1609
|
+
ret[3] = data[:args]
|
1610
|
+
elsif data[:script]
|
1611
|
+
ret[1] = data[:script]
|
1612
|
+
ret[3] = data[:opts]
|
1613
|
+
ret[4] = data[:args]
|
1614
|
+
else
|
1615
|
+
ret[0] = false
|
1616
|
+
end
|
1617
|
+
ret[2] = data[:env] unless dise
|
1618
|
+
ret
|
1619
|
+
end
|
1620
|
+
case cmd
|
1621
|
+
when Array
|
1622
|
+
@output = if cmd.all? { |data| data.is_a?(Hash) }
|
1623
|
+
diso = false
|
1624
|
+
dise = false
|
1625
|
+
cmd.map { |data| parse.(data) }
|
1626
|
+
else
|
1627
|
+
cmd.dup
|
1628
|
+
end
|
1629
|
+
return
|
1630
|
+
when Hash
|
1631
|
+
@output = parse.(data)
|
1632
|
+
else
|
1633
|
+
@output[0] = cmd
|
1634
|
+
end
|
1635
|
+
unless diso
|
1380
1636
|
if opts == false
|
1381
1637
|
@output[1] = false
|
1382
1638
|
elsif opts && opts != true
|
1383
1639
|
@output[1] = opts
|
1384
1640
|
end
|
1385
1641
|
end
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1642
|
+
return if dise
|
1643
|
+
|
1644
|
+
if val.is_a?(Hash)
|
1645
|
+
@output[2] = val
|
1646
|
+
elsif val == false
|
1647
|
+
@output[2] = false
|
1392
1648
|
end
|
1393
|
-
@output[0] = cmd
|
1394
1649
|
end
|
1395
1650
|
|
1396
1651
|
def script_set(cmd, prod: nil, args: nil, **)
|
@@ -1406,6 +1661,8 @@ module Squared
|
|
1406
1661
|
end
|
1407
1662
|
|
1408
1663
|
def as_get(val)
|
1664
|
+
return unless val
|
1665
|
+
|
1409
1666
|
@global && (ret = @as && @as[from] && @as[from][val]) ? ret : val
|
1410
1667
|
end
|
1411
1668
|
|
@@ -1431,8 +1688,7 @@ module Squared
|
|
1431
1688
|
end
|
1432
1689
|
|
1433
1690
|
def projectpath?(val)
|
1434
|
-
val
|
1435
|
-
val.absolute? ? val.to_s.start_with?(File.join(path, '')) : !val.to_s.start_with?(File.join('..', ''))
|
1691
|
+
Pathname.new(val).absolute? ? val.to_s.start_with?(File.join(path, '')) : !val.to_s.start_with?('..')
|
1436
1692
|
end
|
1437
1693
|
|
1438
1694
|
def semmajor?(cur, want)
|
@@ -1441,19 +1697,20 @@ module Squared
|
|
1441
1697
|
|
1442
1698
|
def runnable?(val)
|
1443
1699
|
case val
|
1444
|
-
when String
|
1700
|
+
when String, Enumerable, Proc, Method
|
1445
1701
|
true
|
1446
|
-
when Enumerable
|
1447
|
-
!val.is_a?(Hash)
|
1448
1702
|
else
|
1449
1703
|
false
|
1450
1704
|
end
|
1451
1705
|
end
|
1452
1706
|
|
1707
|
+
def series?(val)
|
1708
|
+
val.is_a?(Array) && val.all? { |p| p.is_a?(Proc) || p.is_a?(Method) }
|
1709
|
+
end
|
1710
|
+
|
1453
1711
|
def session_arg?(*list, target: @session, value: false)
|
1454
1712
|
list.any? do |val|
|
1455
|
-
|
1456
|
-
target.any? { |opt| opt =~ pat }
|
1713
|
+
target.any? { |opt| opt.match?(/^#{Regexp.escape(shell_option(val))}#{value ? '[ =].' : '(?:[ =]|$)'}/o) }
|
1457
1714
|
end
|
1458
1715
|
end
|
1459
1716
|
|
@@ -1490,6 +1747,10 @@ module Squared
|
|
1490
1747
|
Base.tasks + VAR_SET
|
1491
1748
|
end
|
1492
1749
|
|
1750
|
+
def blocks
|
1751
|
+
BLK_SET
|
1752
|
+
end
|
1753
|
+
|
1493
1754
|
def borderstyle
|
1494
1755
|
((data = workspace.banner_get(*@ref, group: group)) && data[:border]) || theme[:border]
|
1495
1756
|
end
|