squared 0.4.3 → 0.4.5
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 +56 -0
- data/README.ruby.md +131 -61
- data/lib/squared/common/format.rb +2 -6
- data/lib/squared/common/shell.rb +2 -1
- data/lib/squared/common/utils.rb +8 -5
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +12 -1
- data/lib/squared/workspace/project/base.rb +121 -46
- data/lib/squared/workspace/project/docker.rb +125 -58
- data/lib/squared/workspace/project/git.rb +59 -66
- data/lib/squared/workspace/project/node.rb +25 -27
- data/lib/squared/workspace/project/python.rb +214 -79
- data/lib/squared/workspace/project/ruby.rb +96 -40
- data/lib/squared/workspace/repo.rb +1 -1
- metadata +3 -3
@@ -11,10 +11,11 @@ module Squared
|
|
11
11
|
include Common::Format
|
12
12
|
include System
|
13
13
|
include Shell
|
14
|
+
include Prompt
|
14
15
|
include Utils
|
15
16
|
include Rake::DSL
|
16
17
|
|
17
|
-
VAR_SET = %i[parent global envname dependfile theme run script env pass].freeze
|
18
|
+
VAR_SET = %i[parent global envname dependfile dependindex theme run script env pass].freeze
|
18
19
|
BLK_SET = %i[run depend doc lint test copy clean].freeze
|
19
20
|
SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?\b/.freeze
|
20
21
|
URI_SCHEME = %r{^([a-z][a-z\d+-.]*)://[^@:\[\]\\^<>|\s]}i.freeze
|
@@ -43,6 +44,10 @@ module Squared
|
|
43
44
|
@ref ||= to_s.downcase.to_sym
|
44
45
|
end
|
45
46
|
|
47
|
+
def subtasks(val)
|
48
|
+
@@tasks[ref] = val.freeze
|
49
|
+
end
|
50
|
+
|
46
51
|
def config?(*)
|
47
52
|
false
|
48
53
|
end
|
@@ -52,13 +57,15 @@ module Squared
|
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
55
|
-
|
56
|
-
'graph' => %i[run print].freeze,
|
57
|
-
'unpack' => %i[zip tar tgz tar.gz txz tar.xz].freeze
|
58
|
-
}.freeze
|
60
|
+
@@tasks = {}
|
59
61
|
@@task_desc = Rake::TaskManager.record_task_metadata
|
60
62
|
@@print_order = 0
|
61
63
|
|
64
|
+
subtasks({
|
65
|
+
'graph' => %i[run print].freeze,
|
66
|
+
'unpack' => %i[zip tar ext].freeze
|
67
|
+
})
|
68
|
+
|
62
69
|
attr_reader :name, :project, :workspace, :path, :theme, :exception, :pipe, :verbose,
|
63
70
|
:group, :parent, :dependfile
|
64
71
|
|
@@ -218,9 +225,8 @@ module Squared
|
|
218
225
|
def initialize_env(dev: nil, prod: nil, **)
|
219
226
|
@dev = env_match('BUILD', dev, suffix: 'DEV', strict: true)
|
220
227
|
@prod = env_match('BUILD', prod, suffix: 'PROD', strict: true)
|
221
|
-
|
222
|
-
|
223
|
-
@output[2] = data if data
|
228
|
+
if @output[2] != false && (val = env('BUILD', suffix: 'ENV'))
|
229
|
+
@output[2] = parse_json(val, hint: "BUILD_#{@envname}_ENV") || @output[2]
|
224
230
|
end
|
225
231
|
unless @output[0] == false || @output[0].is_a?(Array)
|
226
232
|
if (val = env('BUILD', suffix: 'OPTS'))
|
@@ -286,8 +292,11 @@ module Squared
|
|
286
292
|
end
|
287
293
|
end
|
288
294
|
when 'unpack'
|
289
|
-
format_desc
|
290
|
-
|
295
|
+
format_desc(action, flag, 'tag/url,dir,digest?,f/force?', before: flag == :ext ? 'ext' : nil)
|
296
|
+
params = %i[tag dir digest force]
|
297
|
+
params.unshift(:ext) if flag == :ext
|
298
|
+
task flag, params do |_, args|
|
299
|
+
ext = param_guard(action, flag, args: args, key: :ext).downcase if flag == :ext
|
291
300
|
tag = param_guard(action, flag, args: args, key: :tag)
|
292
301
|
dir = param_guard(action, flag, args: args, key: :dir)
|
293
302
|
unless tag.match?(URI_SCHEME)
|
@@ -302,7 +311,7 @@ module Squared
|
|
302
311
|
else
|
303
312
|
force = args.fetch(:force, false)
|
304
313
|
end
|
305
|
-
unpack(basepath(dir), uri: tag, digest: digest, ext: flag.to_s, force: force)
|
314
|
+
unpack(basepath(dir), uri: tag, digest: digest, ext: ext || flag.to_s, force: force)
|
306
315
|
end
|
307
316
|
end
|
308
317
|
end
|
@@ -386,7 +395,7 @@ module Squared
|
|
386
395
|
|
387
396
|
run_b(@run, sync: sync, from: from) if series?(@run)
|
388
397
|
args = @output
|
389
|
-
banner = verbose == 1 if task_invoked?('build', 'build:sync')
|
398
|
+
banner = verbose == 1 if task_invoked?('build', 'build:sync', 'default')
|
390
399
|
end
|
391
400
|
if args.all? { |val| val.is_a?(Array) }
|
392
401
|
cmd = []
|
@@ -570,8 +579,8 @@ module Squared
|
|
570
579
|
raise_error("invalid checksum: #{digest}", hint: name)
|
571
580
|
end
|
572
581
|
end
|
573
|
-
if (val = env('HEADERS')) && (
|
574
|
-
headers =
|
582
|
+
if (val = env('HEADERS')) && (val = parse_json(val, hint: "HEADERS_#{@envname}"))
|
583
|
+
headers = val
|
575
584
|
end
|
576
585
|
require 'open-uri'
|
577
586
|
data = nil
|
@@ -602,7 +611,7 @@ module Squared
|
|
602
611
|
end
|
603
612
|
end
|
604
613
|
ext ||= URI.parse(uri).path[/^.+?\.((?:tar\.)?\w+)$/i, 1]
|
605
|
-
if (n = env("#{ext == 'zip'
|
614
|
+
if (n = env("#{ext == 'zip' || ext == '7z' ? ext.upcase : 'TAR'}_DEPTH", ignore: false))
|
606
615
|
depth = n.to_i
|
607
616
|
end
|
608
617
|
begin
|
@@ -611,24 +620,25 @@ module Squared
|
|
611
620
|
file.write(data)
|
612
621
|
file.close
|
613
622
|
if create
|
614
|
-
warn log_message(Logger::WARN,
|
615
|
-
target.rmtree
|
623
|
+
warn log_message(Logger::WARN, 'force remove', subject: name, hint: target, pass: true)
|
624
|
+
target.rmtree
|
616
625
|
target.mkpath
|
617
626
|
end
|
618
627
|
case ext
|
619
628
|
when 'zip', 'aar'
|
620
629
|
session 'unzip', shell_quote(file.path), quote_option('d', target)
|
621
|
-
when 'tar', 'tgz', 'tar.gz', 'tar.xz'
|
630
|
+
when 'tar', 'tgz', 'tar.gz', 'tar.xz', 'gz', 'xz'
|
622
631
|
flags = +(verbose ? 'v' : '')
|
623
|
-
|
624
|
-
when 'tgz', 'tar.gz'
|
632
|
+
if ext.end_with?('gz')
|
625
633
|
flags += 'z'
|
626
|
-
|
634
|
+
elsif ext.end_with?('xz')
|
627
635
|
flags += 'J'
|
628
636
|
end
|
629
637
|
session 'tar', "-x#{flags}", basic_option('strip-components', depth), quote_option('f', file.path),
|
630
638
|
quote_option('C', target)
|
631
639
|
depth = 0
|
640
|
+
when '7z'
|
641
|
+
session '7z', 'x', shell_quote(file.path), "-o#{shell_quote(target)}"
|
632
642
|
else
|
633
643
|
raise_error("unsupported format: #{ext}", hint: uri)
|
634
644
|
end
|
@@ -790,9 +800,7 @@ module Squared
|
|
790
800
|
end
|
791
801
|
|
792
802
|
def exclude?(*refs)
|
793
|
-
|
794
|
-
|
795
|
-
refs.flatten.any? { |ref| @exclude.include?(ref) }
|
803
|
+
!@exclude.empty? && has_value?(@exclude, refs.flatten)
|
796
804
|
end
|
797
805
|
|
798
806
|
def task_include?(key, ref = nil)
|
@@ -868,19 +876,32 @@ module Squared
|
|
868
876
|
on :first, from
|
869
877
|
begin
|
870
878
|
if cmd.match?(/\A[^:]+:[^:]/) && workspace.task_defined?(cmd)
|
871
|
-
log&.warn "ENV
|
879
|
+
log&.warn "ENV discarded: #{var}" if var
|
872
880
|
task_invoke(cmd, exception: exception, warning: warning?)
|
873
881
|
else
|
874
|
-
print_item format_banner(cmd, banner: banner) if sync
|
882
|
+
print_item format_banner(cmd, banner: banner) if sync
|
883
|
+
if var != false && (pre = runenv)
|
884
|
+
case pre
|
885
|
+
when Hash
|
886
|
+
var = var.is_a?(Hash) ? pre.merge(var) : pre
|
887
|
+
when Enumerable
|
888
|
+
cmd = command(*pre.to_a, cmd)
|
889
|
+
else
|
890
|
+
cmd = command(pre, cmd)
|
891
|
+
end
|
892
|
+
end
|
875
893
|
args = var.is_a?(Hash) ? [var, cmd] : [cmd]
|
876
|
-
shell(*args, chdir: chdir, exception: exception)
|
894
|
+
ret = shell(*args, chdir: chdir, exception: exception)
|
877
895
|
end
|
878
896
|
rescue StandardError => e
|
879
897
|
log&.error e
|
880
898
|
ret = on(:error, from, e)
|
881
899
|
raise unless ret == true
|
900
|
+
|
901
|
+
false
|
882
902
|
else
|
883
903
|
on :last, from
|
904
|
+
ret
|
884
905
|
end
|
885
906
|
end
|
886
907
|
|
@@ -1044,9 +1065,9 @@ module Squared
|
|
1044
1065
|
ret.empty? || (ignore && as_a(ignore).any? { |val| ret == val.to_s }) ? default : ret
|
1045
1066
|
end
|
1046
1067
|
|
1047
|
-
def session(*cmd, prefix: cmd.first, main: true, options: true)
|
1068
|
+
def session(*cmd, prefix: cmd.first, main: true, path: true, options: true)
|
1048
1069
|
prefix = prefix.to_s.upcase
|
1049
|
-
if (val = PATH[prefix] || PATH[prefix.to_sym])
|
1070
|
+
if path && (val = PATH[prefix] || PATH[prefix.to_sym])
|
1050
1071
|
cmd[0] = shell_quote(val, force: false)
|
1051
1072
|
end
|
1052
1073
|
ret = JoinSet.new(cmd.flatten(1))
|
@@ -1059,7 +1080,8 @@ module Squared
|
|
1059
1080
|
def session_delete(*list, target: @session)
|
1060
1081
|
ret = []
|
1061
1082
|
list.each do |val|
|
1062
|
-
|
1083
|
+
pat = /^#{Regexp.escape(shell_option(val))}(?: |=|$)/
|
1084
|
+
if (key = target.find { |opt| opt.match?(pat) })
|
1063
1085
|
target.delete(key)
|
1064
1086
|
ret << key
|
1065
1087
|
end
|
@@ -1089,7 +1111,7 @@ module Squared
|
|
1089
1111
|
nil
|
1090
1112
|
end
|
1091
1113
|
|
1092
|
-
def option_sanitize(opts, list, target: @session, no: nil, first: false, pass: ['='])
|
1114
|
+
def option_sanitize(opts, list, target: @session, no: nil, single: nil, args: false, first: false, pass: ['='])
|
1093
1115
|
ret = []
|
1094
1116
|
reg = []
|
1095
1117
|
bare = []
|
@@ -1101,6 +1123,7 @@ module Squared
|
|
1101
1123
|
qq = []
|
1102
1124
|
i = []
|
1103
1125
|
f = []
|
1126
|
+
si = []
|
1104
1127
|
list = list.map do |val|
|
1105
1128
|
x, y = val.split('|')
|
1106
1129
|
if y
|
@@ -1131,6 +1154,8 @@ module Squared
|
|
1131
1154
|
i << flag
|
1132
1155
|
when 'f'
|
1133
1156
|
f << flag
|
1157
|
+
when 'n'
|
1158
|
+
si << flag
|
1134
1159
|
else
|
1135
1160
|
reg << Regexp.escape(flag)
|
1136
1161
|
end
|
@@ -1145,12 +1170,14 @@ module Squared
|
|
1145
1170
|
opts.each do |opt|
|
1146
1171
|
next ret << opt if found
|
1147
1172
|
|
1148
|
-
if
|
1173
|
+
if single&.match?(opt)
|
1174
|
+
target << "-#{opt}"
|
1175
|
+
elsif bare.include?(opt)
|
1149
1176
|
target << (opt.size == 1 ? "-#{opt}" : "--#{opt}")
|
1150
1177
|
elsif opt.start_with?('no-') && no.include?(name = opt[3..-1])
|
1151
1178
|
target << "--no-#{name}"
|
1152
1179
|
else
|
1153
|
-
if opt =~
|
1180
|
+
if opt =~ /\A([^=]+)=(.+)\z/
|
1154
1181
|
key = $1
|
1155
1182
|
val = $2
|
1156
1183
|
match = ->(flag, pat) { flag.include?(key) && pat.match?(val) }
|
@@ -1162,7 +1189,7 @@ module Squared
|
|
1162
1189
|
target << quote_option(key, basepath(val))
|
1163
1190
|
elsif m.include?(key)
|
1164
1191
|
target << basic_option(key, val, merge: true)
|
1165
|
-
elsif b.include?(key) || match.(i, /^\d+$/) || match.(f, /^\d*(?:\.\d+)?$/)
|
1192
|
+
elsif b.include?(key) || match.(i, /^\d+$/) || match.(f, /^\d*(?:\.\d+)?$/) || match.(si, /^-?\d+$/)
|
1166
1193
|
target << basic_option(key, val)
|
1167
1194
|
else
|
1168
1195
|
ret << opt
|
@@ -1170,6 +1197,7 @@ module Squared
|
|
1170
1197
|
opt = key
|
1171
1198
|
else
|
1172
1199
|
ret << opt
|
1200
|
+
found = true if args
|
1173
1201
|
end
|
1174
1202
|
found = true if first && pass.none? { |s| opt.include?(s) }
|
1175
1203
|
end
|
@@ -1177,14 +1205,20 @@ module Squared
|
|
1177
1205
|
[ret, reg.empty? ? /\A\s+\z/ : /^(#{reg.join('|')})=(.+)$/]
|
1178
1206
|
end
|
1179
1207
|
|
1180
|
-
def option_clear(opts, target: @session, **kwargs)
|
1208
|
+
def option_clear(opts, target: @session, pass: true, append: false, **kwargs)
|
1209
|
+
return if opts.empty?
|
1210
|
+
|
1181
1211
|
kwargs[:subject] ||= target&.first
|
1182
|
-
kwargs[:hint] ||= '
|
1183
|
-
warn log_message(Logger::WARN, opts.join(', '), pass: true, **kwargs)
|
1212
|
+
kwargs[:hint] ||= 'unrecognized'
|
1213
|
+
warn log_message(Logger::WARN, opts.join(', '), pass: true, **kwargs)
|
1214
|
+
append_value(opts, delim: true) if append
|
1215
|
+
return if pass || confirm("Run? [#{sub_style(target, styles: theme[:inline])}] [y/N] ", 'N', timeout: 30)
|
1216
|
+
|
1217
|
+
raise_error 'user cancelled'
|
1184
1218
|
end
|
1185
1219
|
|
1186
1220
|
def print_item(*val)
|
1187
|
-
puts if @@print_order > 0 &&
|
1221
|
+
puts if @@print_order > 0 && stdout?
|
1188
1222
|
@@print_order += 1
|
1189
1223
|
puts val unless val.empty? || (val.size == 1 && val.first.nil?)
|
1190
1224
|
end
|
@@ -1236,7 +1270,7 @@ module Squared
|
|
1236
1270
|
end
|
1237
1271
|
|
1238
1272
|
def format_banner(cmd, banner: true)
|
1239
|
-
return unless banner &&
|
1273
|
+
return unless banner && banner?
|
1240
1274
|
|
1241
1275
|
if (data = workspace.banner_get(*@ref, group: group))
|
1242
1276
|
return if data.empty?
|
@@ -1468,18 +1502,19 @@ module Squared
|
|
1468
1502
|
ret
|
1469
1503
|
end
|
1470
1504
|
|
1471
|
-
def parse_json(val, hint: nil)
|
1505
|
+
def parse_json(val, kind: Hash, hint: nil)
|
1472
1506
|
ret = JSON.parse(val)
|
1473
|
-
raise_error(
|
1507
|
+
raise_error("invalid JSON #{kind.name}", val, hint: hint) if kind && !ret.is_a?(kind)
|
1474
1508
|
rescue StandardError => e
|
1475
1509
|
log&.warn e
|
1510
|
+
warn log_message(Logger::WARN, e, subject: name, pass: true) if warning?
|
1476
1511
|
else
|
1477
1512
|
ret
|
1478
1513
|
end
|
1479
1514
|
|
1480
1515
|
def param_guard(action, flag, args: nil, key: nil, pat: nil, values: nil)
|
1481
1516
|
if args && key
|
1482
|
-
val = args
|
1517
|
+
val = args.fetch(key, nil)
|
1483
1518
|
return val unless val.nil? || (pat && !val.match?(pat)) || (values && !values.include?(val))
|
1484
1519
|
|
1485
1520
|
@session = nil
|
@@ -1491,19 +1526,36 @@ module Squared
|
|
1491
1526
|
args
|
1492
1527
|
end
|
1493
1528
|
|
1529
|
+
def runenv
|
1530
|
+
nil
|
1531
|
+
end
|
1532
|
+
|
1533
|
+
def command(*args)
|
1534
|
+
if workspace.powershell?
|
1535
|
+
"powershell.exe -Command \"& {#{args.join(' ; ')}}\""
|
1536
|
+
else
|
1537
|
+
args.join(' && ')
|
1538
|
+
end
|
1539
|
+
end
|
1540
|
+
|
1494
1541
|
def relativepath(*files, all: false)
|
1495
1542
|
return [] if files.empty?
|
1496
1543
|
|
1544
|
+
pat = /^#{Regexp.escape(File.join(path, ''))}/
|
1497
1545
|
files.flatten.map { |val| Pathname.new(val) }.select { |val| projectpath?(val) }.map do |val|
|
1498
|
-
val = val.absolute? ? val.to_s.sub(
|
1546
|
+
val = val.absolute? ? val.to_s.sub(pat, '') : val.to_s
|
1499
1547
|
val = val[2..-1] if val.start_with?('./')
|
1500
1548
|
val = "#{val}*" if all && val.end_with?('/')
|
1501
1549
|
val
|
1502
1550
|
end
|
1503
1551
|
end
|
1504
1552
|
|
1505
|
-
def projectmap(files, parent: false)
|
1506
|
-
|
1553
|
+
def projectmap(files, parent: false, pass: true)
|
1554
|
+
unless parent
|
1555
|
+
project = files.select { |val| projectpath?(val) }
|
1556
|
+
raise_error 'pathspec not within worktree' unless pass || files.size == project.size
|
1557
|
+
files = project
|
1558
|
+
end
|
1507
1559
|
files.map { |val| val == '.' ? '.' : shell_quote(basepath(val.strip)) }
|
1508
1560
|
end
|
1509
1561
|
|
@@ -1716,7 +1768,8 @@ module Squared
|
|
1716
1768
|
|
1717
1769
|
def session_arg?(*list, target: @session, value: false)
|
1718
1770
|
list.any? do |val|
|
1719
|
-
|
1771
|
+
pat = /^#{Regexp.escape(shell_option(val))}#{value ? '[ =].' : '(?:[ =]|$)'}/
|
1772
|
+
target.any? { |opt| opt.match?(pat) }
|
1720
1773
|
end
|
1721
1774
|
end
|
1722
1775
|
|
@@ -1741,14 +1794,36 @@ module Squared
|
|
1741
1794
|
end
|
1742
1795
|
end
|
1743
1796
|
|
1797
|
+
def banner?
|
1798
|
+
ARG[:BANNER] && !env('BANNER', equals: '0')
|
1799
|
+
end
|
1800
|
+
|
1744
1801
|
def stdin?
|
1745
1802
|
pipe == 0
|
1746
1803
|
end
|
1747
1804
|
|
1805
|
+
def stdout?
|
1806
|
+
!!verbose && !stdin?
|
1807
|
+
end
|
1808
|
+
|
1748
1809
|
def warning?
|
1749
1810
|
workspace.warning
|
1750
1811
|
end
|
1751
1812
|
|
1813
|
+
def has_value?(data, val)
|
1814
|
+
return data.value?(val) if data.is_a?(::Hash)
|
1815
|
+
return data.is_a?(::Enumerable) && data.to_a.include?(val) if !val.is_a?(::Enumerable) || val.is_a?(::Hash)
|
1816
|
+
|
1817
|
+
val.to_a.any? do |obj|
|
1818
|
+
case data
|
1819
|
+
when ::Hash
|
1820
|
+
data.value?(obj)
|
1821
|
+
when ::Enumerable
|
1822
|
+
data.to_a.include?(obj)
|
1823
|
+
end
|
1824
|
+
end
|
1825
|
+
end
|
1826
|
+
|
1752
1827
|
def variables
|
1753
1828
|
Base.tasks + VAR_SET
|
1754
1829
|
end
|