squared 0.4.7 → 0.4.9
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 +106 -1
- data/README.ruby.md +57 -28
- data/lib/squared/common/base.rb +1 -0
- data/lib/squared/common/class.rb +19 -1
- data/lib/squared/common/format.rb +35 -38
- data/lib/squared/common/prompt.rb +66 -3
- data/lib/squared/common/shell.rb +30 -19
- data/lib/squared/common/system.rb +3 -3
- data/lib/squared/common/utils.rb +11 -10
- data/lib/squared/config.rb +4 -5
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +46 -34
- data/lib/squared/workspace/project/base.rb +191 -70
- data/lib/squared/workspace/project/docker.rb +79 -40
- data/lib/squared/workspace/project/git.rb +742 -392
- data/lib/squared/workspace/project/node.rb +35 -51
- data/lib/squared/workspace/project/python.rb +42 -48
- data/lib/squared/workspace/project/ruby.rb +316 -100
- data/lib/squared/workspace/project/support/class.rb +37 -19
- data/lib/squared/workspace/repo.rb +10 -12
- data/lib/squared/workspace/series.rb +11 -7
- data/lib/squared/workspace.rb +2 -9
- metadata +3 -3
@@ -4,7 +4,6 @@ require 'json'
|
|
4
4
|
require 'date'
|
5
5
|
require 'time'
|
6
6
|
require 'logger'
|
7
|
-
require 'digest'
|
8
7
|
|
9
8
|
module Squared
|
10
9
|
module Workspace
|
@@ -22,7 +21,8 @@ module Squared
|
|
22
21
|
BLK_SET = %i[run depend doc lint test copy clean].freeze
|
23
22
|
SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?\b/.freeze
|
24
23
|
URI_SCHEME = %r{^([a-z][a-z\d+-.]*)://[^@:\[\]\\^<>|\s]}i.freeze
|
25
|
-
|
24
|
+
TASK_METADATA = Rake::TaskManager.record_task_metadata
|
25
|
+
private_constant :VAR_SET, :BLK_SET, :SEM_VER, :URI_SCHEME, :TASK_METADATA
|
26
26
|
|
27
27
|
class << self
|
28
28
|
def populate(*); end
|
@@ -47,7 +47,9 @@ module Squared
|
|
47
47
|
@ref ||= to_s.downcase.to_sym
|
48
48
|
end
|
49
49
|
|
50
|
-
def subtasks(val)
|
50
|
+
def subtasks(val = nil, &blk)
|
51
|
+
return @@tasks[val || ref].each(&blk) if block_given?
|
52
|
+
|
51
53
|
@@tasks[ref] = val.freeze
|
52
54
|
end
|
53
55
|
|
@@ -61,12 +63,11 @@ module Squared
|
|
61
63
|
end
|
62
64
|
|
63
65
|
@@tasks = {}
|
64
|
-
@@task_desc = Rake::TaskManager.record_task_metadata
|
65
66
|
@@print_order = 0
|
66
67
|
|
67
68
|
subtasks({
|
68
69
|
'graph' => %i[run print].freeze,
|
69
|
-
'unpack' => %i[zip tar ext].freeze
|
70
|
+
'unpack' => %i[zip tar gem ext].freeze
|
70
71
|
})
|
71
72
|
|
72
73
|
attr_reader :name, :project, :workspace, :path, :theme, :exception, :pipe, :verbose,
|
@@ -97,7 +98,7 @@ module Squared
|
|
97
98
|
@exception = env_bool(kwargs[:exception], workspace.exception, strict: true)
|
98
99
|
@pipe = env_pipe(kwargs[:pipe], workspace.pipe, strict: true)
|
99
100
|
@verbose = case verbose
|
100
|
-
when
|
101
|
+
when NilClass
|
101
102
|
workspace.verbose
|
102
103
|
when String
|
103
104
|
env_bool(verbose, workspace.verbose, strict: true, index: true)
|
@@ -212,7 +213,7 @@ module Squared
|
|
212
213
|
file = val.is_a?(String) ? Time.now.strftime(val) : "#{@name}-#{Date.today}.log"
|
213
214
|
end
|
214
215
|
if file
|
215
|
-
file = (val = env('LOG_DIR')) ? @workspace.home.join(val, file) : @workspace.home
|
216
|
+
file = (val = env('LOG_DIR')) ? @workspace.home.join(val, file) : @workspace.home + file
|
216
217
|
begin
|
217
218
|
file = file.realdirpath
|
218
219
|
rescue StandardError => e
|
@@ -224,7 +225,7 @@ module Squared
|
|
224
225
|
end
|
225
226
|
log[:progname] ||= @name
|
226
227
|
if (val = env('LOG_LEVEL', ignore: false))
|
227
|
-
log[:level] = val.match?(
|
228
|
+
log[:level] = val.match?(/\d/) ? log_sym(val.to_i) : val
|
228
229
|
end
|
229
230
|
log.delete(:file)
|
230
231
|
@log = [file, log]
|
@@ -239,10 +240,10 @@ module Squared
|
|
239
240
|
unless @output[0] == false || @output[0].is_a?(Array)
|
240
241
|
if (val = env('BUILD', suffix: 'OPTS'))
|
241
242
|
n = @output[0] ? 1 : 3
|
242
|
-
@output[n] = merge_opts(@output[n], shell_split(val
|
243
|
+
@output[n] = merge_opts(@output[n], shell_split(val))
|
243
244
|
end
|
244
245
|
if (val = env(ref.to_s.upcase, suffix: 'OPTS'))
|
245
|
-
@output[4] = merge_opts(@output[4], shell_split(val
|
246
|
+
@output[4] = merge_opts(@output[4], shell_split(val))
|
246
247
|
end
|
247
248
|
end
|
248
249
|
@version = val if (val = env('BUILD', suffix: 'VERSION'))
|
@@ -267,7 +268,7 @@ module Squared
|
|
267
268
|
return unless ref?(Base.ref)
|
268
269
|
|
269
270
|
namespace name do
|
270
|
-
|
271
|
+
Base.subtasks do |action, flags|
|
271
272
|
next if @pass.include?(action)
|
272
273
|
|
273
274
|
namespace action do
|
@@ -300,17 +301,21 @@ module Squared
|
|
300
301
|
end
|
301
302
|
end
|
302
303
|
when 'unpack'
|
303
|
-
format_desc(action, flag, 'tag/url,dir,digest?,f
|
304
|
+
format_desc(action, flag, 'tag/url,dir,digest?,f|force?', before: flag == :ext ? 'ext' : nil)
|
304
305
|
params = %i[tag dir digest force]
|
305
306
|
params.unshift(:ext) if flag == :ext
|
306
307
|
task flag, params do |_, args|
|
307
|
-
ext = param_guard(action, flag, args: args, key: :ext)
|
308
|
+
ext = flag == :ext ? param_guard(action, flag, args: args, key: :ext) : flag.to_s
|
308
309
|
tag = param_guard(action, flag, args: args, key: :tag)
|
309
310
|
dir = param_guard(action, flag, args: args, key: :dir)
|
310
311
|
unless tag.match?(URI_SCHEME)
|
311
|
-
|
312
|
-
|
313
|
-
|
312
|
+
if flag == :gem
|
313
|
+
tag = "https://rubygems.org/downloads/#{File.basename(tag, '.gem')}.gem"
|
314
|
+
elsif @release
|
315
|
+
tag = "%s.#{ext}" % [@release.include?('??') ? @release.sub('??', tag) : @release + tag]
|
316
|
+
else
|
317
|
+
raise_error("no base uri: #{tag}", hint: ext)
|
318
|
+
end
|
314
319
|
end
|
315
320
|
case (digest = args.digest)
|
316
321
|
when 'f', 'force'
|
@@ -319,7 +324,7 @@ module Squared
|
|
319
324
|
else
|
320
325
|
force = args.fetch(:force, false)
|
321
326
|
end
|
322
|
-
unpack(
|
327
|
+
unpack(path + dir, uri: tag, digest: digest, ext: ext, force: force)
|
323
328
|
end
|
324
329
|
end
|
325
330
|
end
|
@@ -351,15 +356,15 @@ module Squared
|
|
351
356
|
end
|
352
357
|
end
|
353
358
|
if path.is_a?(String) && (seg = path[%r{^(.+)[\\/]\*+$}, 1])
|
354
|
-
return self unless checkdir.(path = basepath(seg))
|
359
|
+
return self unless checkdir.call(path = basepath(seg))
|
355
360
|
|
356
|
-
path = path.children.select { |val| checkdir.(val) }
|
361
|
+
path = path.children.select { |val| checkdir.call(val) }
|
357
362
|
end
|
358
363
|
if path.is_a?(Array)
|
359
364
|
name = @name if name == true
|
360
365
|
path.each { |val| add(val, name && task_join(name, File.basename(val)), **kwargs, &blk) }
|
361
366
|
return self
|
362
|
-
elsif !projectpath?(path = basepath(path)) || !checkdir.(path)
|
367
|
+
elsif !projectpath?(path = basepath(path)) || !checkdir.call(path)
|
363
368
|
return self
|
364
369
|
elsif name.is_a?(Symbol)
|
365
370
|
name = name.to_s
|
@@ -396,19 +401,26 @@ module Squared
|
|
396
401
|
self
|
397
402
|
end
|
398
403
|
|
399
|
-
def build(*args, sync: invoked_sync?('build'), from:
|
404
|
+
def build(*args, sync: invoked_sync?('build'), from: :run, **)
|
400
405
|
banner = verbose
|
401
406
|
if args.empty?
|
402
|
-
return unless from ==
|
407
|
+
return unless from == :run
|
403
408
|
|
404
409
|
run_b(@run, sync: sync, from: from) if series?(@run)
|
405
410
|
args = @output
|
406
411
|
banner = verbosetype > 1 if task_invoked?('build', 'build:sync', 'default')
|
407
412
|
end
|
413
|
+
if args.first.is_a?(Struct)
|
414
|
+
f, blk = args.first.to_a
|
415
|
+
args[0] = instance_eval(&blk) || f
|
416
|
+
return unless args[0]
|
417
|
+
end
|
408
418
|
if args.all? { |val| val.is_a?(Array) }
|
409
419
|
cmd = []
|
410
420
|
var = {}
|
411
421
|
args.each do |val|
|
422
|
+
next instance_exec(*val[1..-1], &val[0]) if val.first.is_a?(Proc)
|
423
|
+
|
412
424
|
a, b, c, d, e = val
|
413
425
|
case b
|
414
426
|
when Hash
|
@@ -431,7 +443,7 @@ module Squared
|
|
431
443
|
cmd, opts, var, flags, extra = args
|
432
444
|
end
|
433
445
|
if cmd
|
434
|
-
cmd = as_get
|
446
|
+
cmd = as_get cmd
|
435
447
|
opts = compose(opts, script: false) if opts && respond_to?(:compose)
|
436
448
|
flags = append_hash(flags).join(' ') if flags.is_a?(Hash)
|
437
449
|
case opts
|
@@ -449,6 +461,7 @@ module Squared
|
|
449
461
|
return unless (opts || extra) && respond_to?(:compose)
|
450
462
|
|
451
463
|
cmd = compose(as_get(opts), flags, script: true, args: extra, from: from)
|
464
|
+
from = :script if from == :run && script?
|
452
465
|
end
|
453
466
|
run(cmd, var, from: from, banner: banner, sync: sync)
|
454
467
|
end
|
@@ -479,11 +492,18 @@ module Squared
|
|
479
492
|
run_b(@copy, sync: sync, from: :copy)
|
480
493
|
end
|
481
494
|
|
482
|
-
def clean(
|
495
|
+
def clean(*args, sync: invoked_sync?('clean'), pass: false, **kwargs)
|
483
496
|
return unless @clean
|
484
497
|
|
485
|
-
on :first, :clean
|
498
|
+
on :first, :clean unless pass
|
486
499
|
case @clean
|
500
|
+
when Struct
|
501
|
+
if (any = instance_eval(&@clean.block) || @clean.run)
|
502
|
+
temp = @clean
|
503
|
+
@clean = any
|
504
|
+
clean(*args, sync: sync, pass: true, **kwargs)
|
505
|
+
@clean = temp
|
506
|
+
end
|
487
507
|
when String
|
488
508
|
run_s(@clean, sync: sync)
|
489
509
|
when Hash
|
@@ -497,13 +517,13 @@ module Squared
|
|
497
517
|
else
|
498
518
|
if @clean.is_a?(Enumerable) && !series?(@clean)
|
499
519
|
@clean.each do |val|
|
500
|
-
|
501
|
-
if
|
502
|
-
log&.warn "rm -rf #{
|
503
|
-
rm_rf(
|
520
|
+
entry = path + (val = val.to_s)
|
521
|
+
if entry.directory? && val.match?(%r{[\\/]$})
|
522
|
+
log&.warn "rm -rf #{entry}"
|
523
|
+
rm_rf(entry, verbose: verbose)
|
504
524
|
else
|
505
|
-
log&.warn "rm #{
|
506
|
-
(val.include?('*') ? Dir[
|
525
|
+
log&.warn "rm #{entry}"
|
526
|
+
(val.include?('*') ? Dir[entry] : [entry]).each do |file|
|
507
527
|
next unless File.file?(file)
|
508
528
|
|
509
529
|
begin
|
@@ -518,7 +538,7 @@ module Squared
|
|
518
538
|
run_b(@clean, sync: sync)
|
519
539
|
end
|
520
540
|
end
|
521
|
-
on :last, :clean
|
541
|
+
on :last, :clean unless pass
|
522
542
|
end
|
523
543
|
|
524
544
|
def graph(start = [], tasks = nil, sync: invoked_sync?('graph'), pass: [], out: nil)
|
@@ -552,7 +572,7 @@ module Squared
|
|
552
572
|
end
|
553
573
|
end
|
554
574
|
|
555
|
-
def unpack(target, sync: true,
|
575
|
+
def unpack(target, uri:, sync: true, digest: nil, ext: nil, force: false, depth: 1, headers: {},
|
556
576
|
from: :unpack)
|
557
577
|
if !target.exist?
|
558
578
|
target.mkpath
|
@@ -561,8 +581,11 @@ module Squared
|
|
561
581
|
elsif !target.empty?
|
562
582
|
raise_error('directory not empty', hint: target) unless force || env('UNPACK_FORCE')
|
563
583
|
create = true
|
584
|
+
elsif !uri
|
585
|
+
raise_error('no download uri', hint: target)
|
564
586
|
end
|
565
587
|
if digest
|
588
|
+
require 'digest'
|
566
589
|
if (n = digest.index(':').to_i) > 0
|
567
590
|
size = digest[0, n].downcase
|
568
591
|
digest = digest[n + 1..-1]
|
@@ -616,13 +639,19 @@ module Squared
|
|
616
639
|
raise_error('no content', hint: url)
|
617
640
|
end
|
618
641
|
end
|
619
|
-
ext ||= URI.parse(uri).path[/\.(\w+)(\?|$)/i, 1]
|
620
|
-
|
621
|
-
|
642
|
+
raise_error('no content type', hint: uri) unless ext ||= URI.parse(uri).path[/\.(\w+)(\?|$)/i, 1]
|
643
|
+
ext = ext.downcase
|
644
|
+
if (val = env("#{%w[zip 7z gem].include?(ext) ? ext.upcase : 'TAR'}_DEPTH", ignore: false))
|
645
|
+
depth = val.to_i
|
622
646
|
end
|
623
647
|
begin
|
624
|
-
|
625
|
-
|
648
|
+
if ext == 'gem'
|
649
|
+
dir = Dir.mktmpdir
|
650
|
+
file = File.new(File.join(dir, File.basename(uri)), 'w')
|
651
|
+
else
|
652
|
+
require 'tempfile'
|
653
|
+
file = Tempfile.new("#{name}-")
|
654
|
+
end
|
626
655
|
file.write(data)
|
627
656
|
file.close
|
628
657
|
if create
|
@@ -630,7 +659,7 @@ module Squared
|
|
630
659
|
target.rmtree
|
631
660
|
target.mkpath
|
632
661
|
end
|
633
|
-
case ext
|
662
|
+
case ext
|
634
663
|
when 'zip', 'aar'
|
635
664
|
session 'unzip', shell_quote(file.path), quote_option('d', target)
|
636
665
|
when 'tar', 'tgz', 'tar.gz', 'tar.xz', 'gz', 'xz'
|
@@ -645,6 +674,9 @@ module Squared
|
|
645
674
|
depth = 0
|
646
675
|
when '7z'
|
647
676
|
session '7z', 'x', shell_quote(file.path), "-o#{shell_quote(target)}"
|
677
|
+
when 'gem'
|
678
|
+
session 'gem', 'unpack', shell_quote(file.path), quote_option('target', target)
|
679
|
+
depth = 0 unless val
|
648
680
|
else
|
649
681
|
raise_error("unsupported format: #{ext}", hint: uri)
|
650
682
|
end
|
@@ -653,15 +685,22 @@ module Squared
|
|
653
685
|
entry = target.children.first
|
654
686
|
break unless entry.directory?
|
655
687
|
|
656
|
-
|
657
|
-
|
658
|
-
|
688
|
+
i = 0
|
689
|
+
while (dest = target + "#{File.basename(file.path)}-#{i}").exist?
|
690
|
+
i += 1
|
691
|
+
end
|
692
|
+
FileUtils.mv(entry, dest)
|
693
|
+
dest.children.each { |child| FileUtils.mv(child, target) }
|
659
694
|
dest.rmdir
|
660
695
|
target = entry
|
661
696
|
depth -= 1
|
662
697
|
end
|
663
698
|
ensure
|
664
|
-
|
699
|
+
if dir
|
700
|
+
remove_entry dir
|
701
|
+
elsif file
|
702
|
+
file.unlink
|
703
|
+
end
|
665
704
|
end
|
666
705
|
end
|
667
706
|
|
@@ -721,7 +760,7 @@ module Squared
|
|
721
760
|
@parent = val if (val = val.first).is_a?(Project::Base)
|
722
761
|
when :graph
|
723
762
|
@graph = case val.first
|
724
|
-
when
|
763
|
+
when NilClass, FalseClass
|
725
764
|
nil
|
726
765
|
else
|
727
766
|
val.flatten.map!(&:to_s).freeze
|
@@ -877,7 +916,7 @@ module Squared
|
|
877
916
|
end
|
878
917
|
return
|
879
918
|
end
|
880
|
-
cmd = session_done
|
919
|
+
cmd = session_done cmd
|
881
920
|
log&.info cmd
|
882
921
|
on :first, from
|
883
922
|
begin
|
@@ -924,7 +963,13 @@ module Squared
|
|
924
963
|
|
925
964
|
def run_b(obj, from: nil, sync: true)
|
926
965
|
case obj
|
927
|
-
when
|
966
|
+
when Struct
|
967
|
+
if (any = instance_eval(&obj.block) || obj.run)
|
968
|
+
run_b(any, from: from, sync: sync)
|
969
|
+
end
|
970
|
+
when Proc
|
971
|
+
instance_eval(&obj)
|
972
|
+
when Method
|
928
973
|
obj.call
|
929
974
|
else
|
930
975
|
if series?(obj)
|
@@ -953,14 +998,14 @@ module Squared
|
|
953
998
|
end
|
954
999
|
start = target.name
|
955
1000
|
if depth == 0
|
956
|
-
items = check.(dedupe.(start))
|
1001
|
+
items = check.call(dedupe.call(start))
|
957
1002
|
single = items.size == 1
|
958
1003
|
else
|
959
|
-
items = check.(data[start])
|
1004
|
+
items = check.call(data[start])
|
960
1005
|
end
|
961
1006
|
if out
|
962
1007
|
a, b, c, d, e = ARG[:GRAPH]
|
963
|
-
f = tag.(target)
|
1008
|
+
f = tag.call(target)
|
964
1009
|
out << case depth
|
965
1010
|
when 0
|
966
1011
|
f
|
@@ -977,15 +1022,15 @@ module Squared
|
|
977
1022
|
items.each_with_index do |proj, i|
|
978
1023
|
next if done.include?(proj)
|
979
1024
|
|
980
|
-
t = dedupe.(proj.name)
|
1025
|
+
t = dedupe.call(proj.name)
|
981
1026
|
j = if out
|
982
|
-
if i == items.size - 1 || check.(post = items[i + 1..-1]).empty?
|
1027
|
+
if i == items.size - 1 || check.call(post = items[i + 1..-1]).empty?
|
983
1028
|
true
|
984
1029
|
elsif !t.empty? && depth > 0
|
985
1030
|
post.reject { |pr| t.include?(pr) }.empty?
|
986
1031
|
end
|
987
1032
|
end
|
988
|
-
unless start == proj.name || (none = check.(t).empty?)
|
1033
|
+
unless start == proj.name || (none = check.call(t).empty?)
|
989
1034
|
graph_branch(proj, data, tasks, out, sync: sync, pass: pass, done: done, depth: depth.succ,
|
990
1035
|
single: single, last: j == true, context: target)
|
991
1036
|
end
|
@@ -1011,7 +1056,7 @@ module Squared
|
|
1011
1056
|
elsif none
|
1012
1057
|
a, b, c, d = ARG[:GRAPH]
|
1013
1058
|
out << if depth == 0
|
1014
|
-
"#{i == items.size - 1 ? d : c}#{b * 4} #{tag.(proj)}"
|
1059
|
+
"#{i == items.size - 1 ? d : c}#{b * 4} #{tag.call(proj)}"
|
1015
1060
|
else
|
1016
1061
|
s = ''.dup
|
1017
1062
|
k = 0
|
@@ -1021,7 +1066,7 @@ module Squared
|
|
1021
1066
|
s += "#{indent || (last && data[final].last == context) ? ' ' : a} "
|
1022
1067
|
k += 1
|
1023
1068
|
end
|
1024
|
-
s + "#{j ? d : c}#{b * 3} #{tag.(proj)}"
|
1069
|
+
s + "#{j ? d : c}#{b * 3} #{tag.call(proj)}"
|
1025
1070
|
end
|
1026
1071
|
end
|
1027
1072
|
done << proj
|
@@ -1078,7 +1123,7 @@ module Squared
|
|
1078
1123
|
end
|
1079
1124
|
ret = JoinSet.new(cmd.flatten(1))
|
1080
1125
|
if options && (val = env("#{prefix}_OPTIONS"))
|
1081
|
-
split_escape(val).each { |opt| ret.last(fill_option(opt),
|
1126
|
+
split_escape(val).each { |opt| ret.last(fill_option(opt), /\A(--?[^ =]+)[ =].+\z/m) }
|
1082
1127
|
end
|
1083
1128
|
main ? @session = ret : ret
|
1084
1129
|
end
|
@@ -1086,7 +1131,7 @@ module Squared
|
|
1086
1131
|
def session_delete(*args, target: @session)
|
1087
1132
|
ret = []
|
1088
1133
|
args.each do |val|
|
1089
|
-
pat =
|
1134
|
+
pat = /\A#{Regexp.escape(shell_option(val))}(?: |=|\z)/
|
1090
1135
|
if (key = target.find { |opt| opt.match?(pat) })
|
1091
1136
|
target.delete(key)
|
1092
1137
|
ret << key
|
@@ -1128,6 +1173,10 @@ module Squared
|
|
1128
1173
|
OptionPartition.clear(target, opts, styles: theme[:inline], **kwargs)
|
1129
1174
|
end
|
1130
1175
|
|
1176
|
+
def print_success(*)
|
1177
|
+
puts 'Success'
|
1178
|
+
end
|
1179
|
+
|
1131
1180
|
def print_item(*val)
|
1132
1181
|
puts if @@print_order > 0 && stdout?
|
1133
1182
|
@@print_order += 1
|
@@ -1160,7 +1209,7 @@ module Squared
|
|
1160
1209
|
|
1161
1210
|
def print_footer(*lines, sub: nil, reverse: false, right: false, **kwargs)
|
1162
1211
|
n = Project.max_width(lines)
|
1163
|
-
sub = as_a
|
1212
|
+
sub = as_a sub
|
1164
1213
|
lines.map! do |val|
|
1165
1214
|
s = right ? val.rjust(n) : val.ljust(n)
|
1166
1215
|
sub.each { |h| s = sub_style(s, **h) }
|
@@ -1172,7 +1221,7 @@ module Squared
|
|
1172
1221
|
end
|
1173
1222
|
|
1174
1223
|
def format_desc(action, flag, opts = nil, **kwargs)
|
1175
|
-
return unless
|
1224
|
+
return unless TASK_METADATA
|
1176
1225
|
|
1177
1226
|
ret = [@desc, action]
|
1178
1227
|
ret << flag if flag
|
@@ -1232,7 +1281,7 @@ module Squared
|
|
1232
1281
|
items.each_with_index do |val, i|
|
1233
1282
|
next unless reg.empty? || reg.any? { |pat| val[0].match?(pat) }
|
1234
1283
|
|
1235
|
-
out << "#{i.succ.to_s.rjust(pad)}. #{each ? each.(val) : val[0]}"
|
1284
|
+
out << "#{i.succ.to_s.rjust(pad)}. #{each ? each.call(val) : val[0]}"
|
1236
1285
|
end
|
1237
1286
|
end
|
1238
1287
|
sub = [headerstyle]
|
@@ -1287,7 +1336,7 @@ module Squared
|
|
1287
1336
|
append_repeat(key, val, target: target)
|
1288
1337
|
when Numeric
|
1289
1338
|
target << basic_option(key, val)
|
1290
|
-
when
|
1339
|
+
when FalseClass
|
1291
1340
|
target << shell_option(key).sub(/^--(?!no-)/, '--no-')
|
1292
1341
|
else
|
1293
1342
|
target << shell_option(key, val.is_a?(String) ? val : nil)
|
@@ -1427,7 +1476,7 @@ module Squared
|
|
1427
1476
|
end
|
1428
1477
|
end
|
1429
1478
|
|
1430
|
-
def param_guard(action, flag, args
|
1479
|
+
def param_guard(action, flag, args:, key: nil, pat: nil, values: nil)
|
1431
1480
|
if args && key
|
1432
1481
|
val = args.fetch(key, nil)
|
1433
1482
|
return val unless val.nil? || (pat && !val.match?(pat)) || (values && !values.include?(val))
|
@@ -1441,6 +1490,74 @@ module Squared
|
|
1441
1490
|
args
|
1442
1491
|
end
|
1443
1492
|
|
1493
|
+
def confirm_outdated(pkg, ver, rev, lock: false)
|
1494
|
+
a = sub_style(case rev
|
1495
|
+
when 1
|
1496
|
+
'MAJOR'
|
1497
|
+
when 2
|
1498
|
+
'MINOR'
|
1499
|
+
else
|
1500
|
+
'PATCH'
|
1501
|
+
end, styles: theme[:header])
|
1502
|
+
b = sub_style("#{pkg} #{ver}", styles: theme[:inline])
|
1503
|
+
c, d = rev == 1 || lock ? ['y/N', 'N'] : ['Y/n', 'Y']
|
1504
|
+
e = lock ? " #{sub_style('(locked)', styles: color(:red))}" : ''
|
1505
|
+
confirm("Upgrade to #{a}? #{b + e} [#{c}] ", d)
|
1506
|
+
end
|
1507
|
+
|
1508
|
+
def choice_index(msg, list, values: nil, multiple: false, accept: nil, series: false, trim: nil, column: nil,
|
1509
|
+
attempts: 5, force: true)
|
1510
|
+
puts if !series && @@print_order > 0
|
1511
|
+
msg = "#{msg} (optional)" unless force
|
1512
|
+
unless (ret = choice(msg, list, multiple: multiple, force: force, attempts: attempts)) || !force
|
1513
|
+
raise_error 'user cancelled'
|
1514
|
+
end
|
1515
|
+
if ret.nil? || ret.empty?
|
1516
|
+
return unless force
|
1517
|
+
|
1518
|
+
exit 1
|
1519
|
+
end
|
1520
|
+
ret = multiple ? ret.map! { |val| val.sub(trim, '') } : ret.sub(trim, '') if trim
|
1521
|
+
if column
|
1522
|
+
a, b = as_a(column)
|
1523
|
+
ret = as_a(ret).map! { |val| val[a, b || 1] }
|
1524
|
+
ret = ret.first unless multiple
|
1525
|
+
end
|
1526
|
+
if accept
|
1527
|
+
a = as_a(ret).map { |val| sub_style(val, styles: theme[:inline]) }.join(', ')
|
1528
|
+
accept = as_a(accept).map { |val| as_a(val) }
|
1529
|
+
if accept.any? { |val| val[1] == true }
|
1530
|
+
ret = [ret]
|
1531
|
+
multiple = -1
|
1532
|
+
end
|
1533
|
+
loop do
|
1534
|
+
c = confirm("#{accept.first[0]}#{a ? " [#{a}]" : ''} [y/N] ", 'N', timeout: 60)
|
1535
|
+
if accept.shift[1] == true
|
1536
|
+
ret << c
|
1537
|
+
elsif !c
|
1538
|
+
break
|
1539
|
+
end
|
1540
|
+
a = nil
|
1541
|
+
break if accept.empty?
|
1542
|
+
end
|
1543
|
+
exit 1 unless accept.empty?
|
1544
|
+
end
|
1545
|
+
if values
|
1546
|
+
ret = [ret] unless accept && multiple == -1
|
1547
|
+
values.each do |val|
|
1548
|
+
if val.is_a?(Array)
|
1549
|
+
val, force = val
|
1550
|
+
else
|
1551
|
+
force = false
|
1552
|
+
end
|
1553
|
+
val = readline(val, force: force)
|
1554
|
+
ret << (val.empty? ? nil : val)
|
1555
|
+
end
|
1556
|
+
end
|
1557
|
+
@@print_order += 1 unless series
|
1558
|
+
ret
|
1559
|
+
end
|
1560
|
+
|
1444
1561
|
def runenv
|
1445
1562
|
nil
|
1446
1563
|
end
|
@@ -1470,7 +1587,7 @@ module Squared
|
|
1470
1587
|
raise_error 'pathspec not within worktree' unless pass || files.size == proj.size
|
1471
1588
|
files = proj
|
1472
1589
|
end
|
1473
|
-
files.map { |val| val == '.' ? '.' : shell_quote(
|
1590
|
+
files.map { |val| val == '.' ? '.' : shell_quote(path + val) }
|
1474
1591
|
end
|
1475
1592
|
|
1476
1593
|
def semver(val)
|
@@ -1506,7 +1623,7 @@ module Squared
|
|
1506
1623
|
end
|
1507
1624
|
|
1508
1625
|
def colormap(val)
|
1509
|
-
val.compact.
|
1626
|
+
val.compact.flat_map { |s| color(s) }
|
1510
1627
|
end
|
1511
1628
|
|
1512
1629
|
def epochtime
|
@@ -1515,7 +1632,7 @@ module Squared
|
|
1515
1632
|
|
1516
1633
|
def verbosetype
|
1517
1634
|
case verbose
|
1518
|
-
when
|
1635
|
+
when TrueClass
|
1519
1636
|
1
|
1520
1637
|
when Numeric
|
1521
1638
|
verbose.succ
|
@@ -1546,15 +1663,15 @@ module Squared
|
|
1546
1663
|
end
|
1547
1664
|
end
|
1548
1665
|
|
1549
|
-
def pwd_set(done = nil, pass: false, from: nil, dryrun: false
|
1666
|
+
def pwd_set(done = nil, pass: false, from: nil, dryrun: false)
|
1550
1667
|
pwd = Pathname.pwd
|
1551
1668
|
if block_given?
|
1552
1669
|
begin
|
1553
|
-
if path == pwd || pass == true || (pass.is_a?(String) && semscan(pass).join
|
1554
|
-
ret =
|
1670
|
+
if path == pwd || pass == true || (pass.is_a?(String) && semscan(pass).join <= RUBY_VERSION)
|
1671
|
+
ret = yield
|
1555
1672
|
else
|
1556
1673
|
Dir.chdir(path)
|
1557
|
-
ret =
|
1674
|
+
ret = yield
|
1558
1675
|
Dir.chdir(pwd)
|
1559
1676
|
end
|
1560
1677
|
rescue StandardError => e
|
@@ -1605,13 +1722,13 @@ module Squared
|
|
1605
1722
|
@output = if cmd.all? { |data| data.is_a?(Hash) }
|
1606
1723
|
diso = false
|
1607
1724
|
dise = false
|
1608
|
-
cmd.map { |data| parse.(data) }
|
1725
|
+
cmd.map { |data| parse.call(data) }
|
1609
1726
|
else
|
1610
1727
|
cmd.dup
|
1611
1728
|
end
|
1612
1729
|
return
|
1613
1730
|
when Hash
|
1614
|
-
@output = parse.(data)
|
1731
|
+
@output = parse.call(data)
|
1615
1732
|
else
|
1616
1733
|
@output[0] = cmd
|
1617
1734
|
end
|
@@ -1717,6 +1834,10 @@ module Squared
|
|
1717
1834
|
end
|
1718
1835
|
end
|
1719
1836
|
|
1837
|
+
def success?(ret)
|
1838
|
+
ret == true && stdout? && banner?
|
1839
|
+
end
|
1840
|
+
|
1720
1841
|
def banner?
|
1721
1842
|
ARG[:BANNER] && !env('BANNER', equals: '0')
|
1722
1843
|
end
|