squared 0.5.2 → 0.5.4

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.
@@ -19,10 +19,10 @@ module Squared
19
19
  include ::Comparable
20
20
 
21
21
  VAR_SET = %i[parent global script index envname desc dependfile dependindex theme archive env dev prod graph
22
- pass exclude].freeze
22
+ pass only exclude].freeze
23
23
  BLK_SET = %i[run depend doc lint test copy clean].freeze
24
- SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?\b/.freeze
25
- URI_SCHEME = %r{^([a-z][a-z\d+-.]*)://[^@:\[\]\\^<>|\s]}i.freeze
24
+ SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+))?-?(\S+)?\b/.freeze
25
+ URI_SCHEME = %r{\A([a-z][a-z\d+-.]*)://[^@:\[\]\\^<>|\s]}i.freeze
26
26
  TASK_METADATA = Rake::TaskManager.record_task_metadata
27
27
  private_constant :VAR_SET, :BLK_SET, :SEM_VER, :URI_SCHEME, :TASK_METADATA
28
28
 
@@ -73,8 +73,8 @@ module Squared
73
73
  'unpack' => %i[zip tar gem ext].freeze
74
74
  })
75
75
 
76
- attr_reader :name, :project, :workspace, :path, :theme, :exception, :pipe, :verbose,
77
- :group, :parent, :dependfile
76
+ attr_reader :name, :project, :workspace, :path, :theme, :group, :parent, :dependfile,
77
+ :exception, :pipe, :verbose
78
78
 
79
79
  def initialize(workspace, path, name, *, group: nil, first: {}, last: {}, error: {}, common: ARG[:COMMON],
80
80
  **kwargs)
@@ -89,16 +89,15 @@ module Squared
89
89
  @test = kwargs[:test]
90
90
  @copy = kwargs[:copy]
91
91
  @clean = kwargs[:clean]
92
- @version = kwargs[:version]
93
92
  @release = kwargs[:release]
93
+ self.version = kwargs[:version]
94
+ self.exception = kwargs[:exception]
95
+ self.pipe = kwargs[:pipe]
96
+ self.verbose = kwargs[:verbose]
94
97
  @output = []
95
98
  @ref = []
96
99
  @children = []
97
- @events = {
98
- first: first,
99
- last: last,
100
- error: error
101
- }
100
+ @events = hashobj.update({ first: first, last: last, error: error })
102
101
  @envname = env_key(@name).freeze
103
102
  @desc = (@name.include?(':') ? @name.split(':').join(ARG[:SPACE]) : @name).freeze
104
103
  @parent = nil
@@ -110,11 +109,9 @@ module Squared
110
109
  @session = nil
111
110
  @index = -1
112
111
  run_set(kwargs[:run], kwargs[:env], opts: kwargs.fetch(:opts, true))
113
- exception_set kwargs[:exception]
114
- pipe_set kwargs[:pipe]
115
- verbose_set kwargs[:verbose]
116
112
  graph_set kwargs[:graph]
117
113
  pass_set kwargs[:pass]
114
+ only_set kwargs[:only]
118
115
  exclude_set kwargs[:exclude]
119
116
  archive_set kwargs[:archive]
120
117
  theme_set common
@@ -176,9 +173,7 @@ module Squared
176
173
  def initialize_events(ref, **)
177
174
  return unless (events = @workspace.events_get(group: @group, ref: ref))
178
175
 
179
- events.each do |task, data|
180
- data.each { |ev, blk| (@events[ev] ||= {})[task] ||= [blk] }
181
- end
176
+ events.each { |task, data| data.each { |ev, blk| @events[ev][task] ||= [blk] } }
182
177
  end
183
178
 
184
179
  def initialize_logger(log: nil, **)
@@ -218,7 +213,7 @@ module Squared
218
213
  def initialize_env(dev: nil, prod: nil, **)
219
214
  @dev = env_match('BUILD', dev, suffix: 'DEV', strict: true)
220
215
  @prod = env_match('BUILD', prod, suffix: 'PROD', strict: true)
221
- if @output[2] != false && (val = env('BUILD', suffix: 'ENV'))
216
+ unless @output[2] == false || !(val = env('BUILD', suffix: 'ENV'))
222
217
  @output[2] = parse_json(val, hint: "BUILD_#{@envname}_ENV") || @output[2]
223
218
  end
224
219
  unless @output[0] == false || @output[0].is_a?(Array)
@@ -284,6 +279,29 @@ module Squared
284
279
  nil
285
280
  end
286
281
 
282
+ def version=(val)
283
+ @version = val&.to_s
284
+ end
285
+
286
+ def exception=(val)
287
+ @exception = env_bool(val, workspace.exception, strict: true)
288
+ end
289
+
290
+ def pipe=(val)
291
+ @pipe = env_pipe(val, workspace.pipe, strict: true)
292
+ end
293
+
294
+ def verbose=(val)
295
+ @verbose = case val
296
+ when NilClass
297
+ workspace.verbose
298
+ when String
299
+ env_bool(val, workspace.verbose, strict: true, index: true)
300
+ else
301
+ val
302
+ end
303
+ end
304
+
287
305
  def ref
288
306
  Base.ref
289
307
  end
@@ -294,7 +312,7 @@ module Squared
294
312
 
295
313
  namespace name do
296
314
  Base.subtasks do |action, flags|
297
- next if @pass.include?(action)
315
+ next if task_pass?(action)
298
316
 
299
317
  namespace action do
300
318
  flags.each do |flag|
@@ -500,11 +518,9 @@ module Squared
500
518
  if proj.respond_to?(meth.to_sym)
501
519
  begin
502
520
  proj.__send__(meth, sync: sync)
503
- rescue StandardError => e
504
- ret = on :error, :prereqs, e
505
- raise unless ret == true
506
- else
507
521
  next
522
+ rescue StandardError => e
523
+ on_error(:prereqs, e, exception: true)
508
524
  end
509
525
  end
510
526
  warn log_message(Logger::WARN, name, 'method not found', subject: 'prereqs', hint: meth)
@@ -557,9 +573,7 @@ module Squared
557
573
  begin
558
574
  @clean.each { |cmd, opts| build(cmd.to_s, opts, sync: sync) }
559
575
  rescue StandardError => e
560
- log&.error e
561
- ret = on :error, from, e
562
- raise if exception && ret != true
576
+ on_error e, from
563
577
  end
564
578
  else
565
579
  if @clean.is_a?(Enumerable) && !series?(@clean)
@@ -608,8 +622,7 @@ module Squared
608
622
  end
609
623
  ret = graph_branch(self, data, tasks, out, sync: sync, pass: pass)
610
624
  rescue StandardError => e
611
- ret = on :error, :graph, e
612
- raise unless ret == true
625
+ on_error(:graph, e, exception: true)
613
626
  else
614
627
  if out
615
628
  [out, ret]
@@ -618,13 +631,13 @@ module Squared
618
631
  end
619
632
  end
620
633
 
621
- def unpack(target, uri:, sync: true, digest: nil, ext: nil, force: false, depth: 1, headers: {}, from: :unpack)
622
- require 'open-uri'
634
+ def unpack(target, file = nil, uri: nil, sync: true, digest: nil, ext: nil, force: false, depth: 1, headers: {},
635
+ verbose: self.verbose, from: :unpack)
623
636
  if !target.exist?
624
637
  target.mkpath
625
638
  elsif !target.directory?
626
639
  raise_error('invalid location', hint: target)
627
- elsif !target.empty?
640
+ elsif !file && !target.empty?
628
641
  raise_error('directory not empty', hint: target) unless force || env('UNPACK_FORCE')
629
642
  create = true
630
643
  end
@@ -645,50 +658,59 @@ module Squared
645
658
  when 128, 'sha512'
646
659
  Digest::SHA512
647
660
  else
648
- raise_error("invalid checksum: #{digest}", hint: name)
661
+ raise_error "invalid checksum: #{digest}"
649
662
  end
650
663
  end
651
664
  if (val = env('HEADERS')) && (val = parse_json(val, hint: "HEADERS_#{@envname}"))
652
665
  headers = headers.is_a?(Hash) ? headers.merge(val) : val
653
666
  end
654
- data = nil
655
- (uri = Array(uri)).each_with_index do |url, index|
656
- URI.open(url, headers) do |f|
657
- data = f.read
658
- if algo && algo.hexdigest(data) != digest
659
- data = nil
660
- raise_error("checksum failed: #{digest}", hint: url) if index == uri.size - 1
661
- end
662
- next if ext && index == 0
663
-
664
- case f.content_type
665
- when 'application/zip'
666
- ext = 'zip'
667
- when 'application/x-gzip'
668
- ext = 'tgz'
669
- when 'application/x-xz'
670
- ext = 'txz'
667
+ if file
668
+ ext ||= File.extname(file)[1..-1]
669
+ else
670
+ require 'open-uri'
671
+ data = nil
672
+ (uri = Array(uri)).each_with_index do |url, index|
673
+ URI.open(url, headers) do |f|
674
+ data = f.read
675
+ if algo && algo.hexdigest(data) != digest
676
+ data = nil
677
+ raise_error("checksum failed: #{digest}", hint: url) if index == uri.size - 1
678
+ end
679
+ next if ext && index == 0
680
+
681
+ case f.content_type
682
+ when 'application/zip'
683
+ ext = 'zip'
684
+ when 'application/x-gzip'
685
+ ext = 'tgz'
686
+ when 'application/x-xz'
687
+ ext = 'txz'
688
+ end
671
689
  end
690
+ break uri = url if data
691
+ end
692
+ unless data && (ext ||= URI.parse(uri).path[/\.(\w+)(?:\?|\z)/, 1])
693
+ raise_error("no content#{data ? ' type' : ''}", hint: uri)
672
694
  end
673
- break uri = url if data
674
- end
675
- unless data && (ext ||= URI.parse(uri).path[/\.(\w+)(?:\?|\z)/, 1])
676
- raise_error("no content#{data ? ' type' : ''}", hint: uri)
677
695
  end
678
696
  ext = ext.downcase
679
697
  if (val = env("#{%w[zip 7z gem].include?(ext) ? ext.upcase : 'TAR'}_DEPTH", ignore: false))
680
698
  depth = val.to_i
681
699
  end
682
700
  begin
683
- if ext == 'gem'
684
- dir = Dir.mktmpdir
685
- file = File.new(File.join(dir, File.basename(uri)), 'w')
686
- else
687
- require 'tempfile'
688
- file = Tempfile.new("#{name}-")
701
+ unless file
702
+ if ext == 'gem'
703
+ dir = Dir.mktmpdir
704
+ file = File.new(File.join(dir, File.basename(uri)), 'w')
705
+ else
706
+ require 'tempfile'
707
+ file = Tempfile.new("#{name}-")
708
+ end
709
+ file.write(data)
710
+ file.close
711
+ file = Pathname.new(file)
712
+ delete = true
689
713
  end
690
- file.write(data)
691
- file.close
692
714
  if create
693
715
  warn log_message(Logger::WARN, 'force remove', subject: name, hint: target)
694
716
  target.rmtree
@@ -696,7 +718,7 @@ module Squared
696
718
  end
697
719
  case ext
698
720
  when 'zip', 'aar'
699
- session 'unzip', shell_quote(file.path), quote_option('d', target)
721
+ session 'unzip', shell_quote(file), quote_option('d', target)
700
722
  when 'tar', 'tgz', 'tar.gz', 'tar.xz', 'gz', 'xz'
701
723
  flags = +(verbose ? 'v' : '')
702
724
  if ext.end_with?('gz')
@@ -704,24 +726,24 @@ module Squared
704
726
  elsif ext.end_with?('xz')
705
727
  flags += 'J'
706
728
  end
707
- session 'tar', "-x#{flags}", basic_option('strip-components', depth), quote_option('f', file.path),
729
+ session 'tar', "-x#{flags}", basic_option('strip-components', depth), quote_option('f', file),
708
730
  quote_option('C', target)
709
731
  depth = 0
710
732
  when '7z'
711
- session '7z', 'x', shell_quote(file.path), "-o#{shell_quote(target)}"
733
+ session '7z', 'x', shell_quote(file), "-o#{shell_quote(target)}"
712
734
  when 'gem'
713
- session 'gem', 'unpack', shell_quote(file.path), quote_option('target', target)
735
+ session 'gem', 'unpack', shell_quote(file), quote_option('target', target)
714
736
  depth = 0 unless val
715
737
  else
716
- raise_error("unsupported format: #{ext}", hint: uri)
738
+ raise_error("unsupported format: #{ext}", hint: uri || file)
717
739
  end
718
- run(sync: sync, from: from)
740
+ run(sync: sync, banner: verbose, from: from)
719
741
  while depth > 0 && target.children.size == 1
720
742
  entry = target.children.first
721
743
  break unless entry.directory?
722
744
 
723
745
  i = 0
724
- while (dest = target + "#{File.basename(file.path)}-#{i}").exist?
746
+ while (dest = target + "#{File.basename(file)}-#{i}").exist?
725
747
  i += 1
726
748
  end
727
749
  FileUtils.mv(entry, dest)
@@ -733,8 +755,8 @@ module Squared
733
755
  ensure
734
756
  if dir
735
757
  remove_entry dir
736
- else
737
- file&.unlink
758
+ elsif delete && file&.exist?
759
+ file.unlink
738
760
  end
739
761
  end
740
762
  end
@@ -752,7 +774,7 @@ module Squared
752
774
  end
753
775
 
754
776
  def event(name, key, *args, override: false, **kwargs, &blk)
755
- data = @events[name.to_sym] ||= {}
777
+ data = @events[name.to_sym]
756
778
  items = if override
757
779
  data[key.to_sym] = []
758
780
  else
@@ -806,6 +828,8 @@ module Squared
806
828
  graph_set val
807
829
  when :pass
808
830
  pass_set val
831
+ when :only
832
+ only_set val
809
833
  when :exclude
810
834
  exclude_set val
811
835
  when :parent
@@ -966,11 +990,11 @@ module Squared
966
990
  puts_oe(*args, pipe: pipe)
967
991
  end
968
992
 
969
- def run(cmd = @session, var = nil, exception: @exception, sync: true, from: nil, banner: true, chdir: path,
970
- interactive: nil, **)
993
+ def run(cmd = @session, var = nil, exception: self.exception, sync: true, from: nil, banner: true, chdir: path,
994
+ interactive: nil, hint: nil, **)
971
995
  unless cmd
972
- from = from&.to_s || 'unknown'
973
- return warn log_message(Logger::WARN, 'no command given', subject: project, hint: from, pass: true)
996
+ warn log_message(Logger::WARN, 'no command given', subject: project, hint: from || 'unknown', pass: true)
997
+ return
974
998
  end
975
999
  i = interactive && !(@session && option('y'))
976
1000
  cmd = cmd.target if cmd.is_a?(OptionPartition)
@@ -984,9 +1008,7 @@ module Squared
984
1008
  else
985
1009
  ['Run', 'Y']
986
1010
  end
987
- unless confirm("#{title}? [#{sub_style(cmd, styles: theme[:inline])}]", y)
988
- raise_error('user cancelled', hint: from)
989
- end
1011
+ exit 1 unless confirm("#{title}? [#{sub_style(cmd, styles: theme[:inline])}]", y)
990
1012
  end
991
1013
  log&.info cmd
992
1014
  on :first, from
@@ -995,7 +1017,7 @@ module Squared
995
1017
  log&.warn "ENV discarded: #{var}" if var
996
1018
  task_invoke(cmd, exception: exception, warning: warning?)
997
1019
  else
998
- print_item format_banner(cmd, banner: banner) if sync
1020
+ print_item format_banner(hint ? "#{cmd} (#{hint})" : cmd, banner: banner) if sync
999
1021
  if var != false && (pre = runenv)
1000
1022
  case pre
1001
1023
  when Hash
@@ -1010,10 +1032,7 @@ module Squared
1010
1032
  ret = shell(*args, chdir: chdir, exception: exception)
1011
1033
  end
1012
1034
  rescue StandardError => e
1013
- log&.error e
1014
- ret = on :error, from, e
1015
- raise unless ret == true
1016
-
1035
+ on_error(from, e, exception: true)
1017
1036
  false
1018
1037
  else
1019
1038
  on :last, from
@@ -1237,7 +1256,7 @@ module Squared
1237
1256
  def session_done(cmd)
1238
1257
  return cmd unless cmd.respond_to?(:done)
1239
1258
 
1240
- raise_error('no args added', hint: cmd.first || name) unless cmd.size > 1
1259
+ raise_error('no args added', hint: cmd.first) unless cmd.size > 1
1241
1260
  @session = nil if cmd == @session
1242
1261
  cmd.done
1243
1262
  end
@@ -1269,6 +1288,10 @@ module Squared
1269
1288
  puts 'Success'
1270
1289
  end
1271
1290
 
1291
+ def print_error(err, loglevel: Logger::WARN, pass: false)
1292
+ warn log_message(loglevel, err, pass: pass) if warning?
1293
+ end
1294
+
1272
1295
  def print_item(*val)
1273
1296
  puts unless printfirst?
1274
1297
  printsucc
@@ -1311,7 +1334,7 @@ module Squared
1311
1334
  ret.join("\n")
1312
1335
  end
1313
1336
 
1314
- def print_status(*args, from: nil)
1337
+ def print_status(*args, from: nil, **kwargs)
1315
1338
  return if stdin?
1316
1339
 
1317
1340
  case from
@@ -1320,6 +1343,12 @@ module Squared
1320
1343
  out[1] = sub_style(out[1], pat: /^( +major )(\d+)(.+)$/, styles: theme[:major], index: 2)
1321
1344
  out[1] = sub_style(out[1], pat: /^(.+)(minor )(\d+)(.+)$/, styles: theme[:active], index: 3)
1322
1345
  puts out
1346
+ when :completed
1347
+ if verbose && kwargs[:start]
1348
+ msg = sub_style('completed', styles: theme[:active])
1349
+ puts log_message(Logger::INFO, *args, msg, subject: kwargs[:subject],
1350
+ hint: time_format(epochtime - kwargs[:start]))
1351
+ end
1323
1352
  end
1324
1353
  end
1325
1354
 
@@ -1381,7 +1410,7 @@ module Squared
1381
1410
  unless items.empty?
1382
1411
  pad = items.size.to_s.size
1383
1412
  items.each_with_index do |val, i|
1384
- next unless reg.empty? || reg.any? { |pat| val[0].match?(pat) }
1413
+ next unless matchany?(val[0], reg)
1385
1414
 
1386
1415
  out << ('%*d. %s' % [pad, i.succ, each ? each.call(val) : val[0]])
1387
1416
  end
@@ -1484,11 +1513,11 @@ module Squared
1484
1513
  list.flatten.each do |opt|
1485
1514
  next unless (val = option(opt, **kwargs))
1486
1515
 
1487
- return target << (if flag
1488
- shell_option(opt, equals ? val : nil, quote: quote, escape: escape, force: force)
1489
- else
1490
- shell_quote val
1491
- end)
1516
+ return target << if flag
1517
+ shell_option(opt, equals ? val : nil, quote: quote, escape: escape, force: force)
1518
+ else
1519
+ shell_quote val
1520
+ end
1492
1521
  end
1493
1522
  nil
1494
1523
  end
@@ -1604,13 +1633,9 @@ module Squared
1604
1633
  multiple: false, force: true, **kwargs)
1605
1634
  puts if !series && !printfirst?
1606
1635
  msg = "#{msg} (optional)" unless force
1607
- unless (ret = choice(msg, list, multiple: multiple, force: force, **kwargs)) || !force
1608
- raise_error 'user cancelled'
1609
- end
1610
- if ret.nil? || ret.empty?
1611
- return unless force
1612
-
1613
- exit 1
1636
+ unless (ret = choice(msg, list, multiple: multiple, force: force, **kwargs)) && !ret.empty?
1637
+ exit 1 if force
1638
+ return
1614
1639
  end
1615
1640
  ret = multiple ? ret.map! { |val| val.sub(trim, '') } : ret.sub(trim, '') if trim
1616
1641
  if column
@@ -1655,8 +1680,8 @@ module Squared
1655
1680
  ret
1656
1681
  end
1657
1682
 
1658
- def command_args(args, force: false, **kwargs)
1659
- return unless args.size == 1 && !option('i', 'interactive', **kwargs, equals: '0')
1683
+ def command_args(args, min: 0, force: false, **kwargs)
1684
+ return if args.size > min || option('i', 'interactive', **kwargs, equals: '0')
1660
1685
 
1661
1686
  readline('Enter arguments', force: force)
1662
1687
  end
@@ -1701,6 +1726,17 @@ module Squared
1701
1726
  files.map { |val| val == '.' ? '.' : shell_quote(path + val) }
1702
1727
  end
1703
1728
 
1729
+ def matchmap(list, prefix = nil)
1730
+ list.map do |val|
1731
+ if val.is_a?(Regexp)
1732
+ val
1733
+ else
1734
+ val = ".*#{val}" if prefix && !val.sub!(/\A(\^|\\A)/, '')
1735
+ Regexp.new("#{prefix}#{val == '*' ? '.+' : val}")
1736
+ end
1737
+ end
1738
+ end
1739
+
1704
1740
  def semver(val)
1705
1741
  return val if val[3]
1706
1742
 
@@ -1717,6 +1753,26 @@ module Squared
1717
1753
  val.scan(SEM_VER).first.yield_self { |data| fill ? semver(data) : data }
1718
1754
  end
1719
1755
 
1756
+ def semcmp(val, other)
1757
+ return 0 if val == other
1758
+
1759
+ a, b = [val, other].map! { |ver| ver.scan(SEM_VER) }
1760
+ return -1 if b.empty?
1761
+ return 1 if a.empty?
1762
+
1763
+ a, b = [a.first, b.first].map! { |c| [c[0], c[2], c[4] || '0', c[5] ? '-1' : '0'] }
1764
+ a.each_with_index do |c, index|
1765
+ next if c == (d = b[index])
1766
+
1767
+ return c.to_i < d.to_i ? 1 : -1
1768
+ end
1769
+ 0
1770
+ end
1771
+
1772
+ def semgte?(val, other)
1773
+ semcmp(val, other) != 1
1774
+ end
1775
+
1720
1776
  def indexitem(val)
1721
1777
  [$1.to_i, $2 && $2[1..-1]] if val =~ /\A[=^#{indexchar}](\d+)(:.+)?\z/
1722
1778
  end
@@ -1758,9 +1814,9 @@ module Squared
1758
1814
  end
1759
1815
 
1760
1816
  def on(event, from, *args, **kwargs)
1761
- return unless from && (data = @events[event])
1817
+ return unless from && @events.key?(event)
1762
1818
 
1763
- data[from]&.each do |obj|
1819
+ Array(@events[event][from]).each do |obj|
1764
1820
  target, opts = if obj.is_a?(Array) && obj[1].is_a?(Hash)
1765
1821
  [obj[0], kwargs.empty? ? obj[1] : obj[1].merge(kwargs)]
1766
1822
  else
@@ -1777,27 +1833,31 @@ module Squared
1777
1833
  end
1778
1834
  end
1779
1835
 
1780
- def pwd_set(pass: false, from: nil)
1781
- pass = semscan(pass).join <= RUBY_VERSION if pass.is_a?(String)
1782
- pwd = Dir.pwd
1783
- if (path.to_s == pwd || pass == true) && !workspace.jruby_win?
1784
- ret = yield
1785
- else
1786
- Dir.chdir(path)
1787
- ret = yield
1788
- Dir.chdir(pwd)
1836
+ def on_error(err, from, exception: self.exception, pass: false, dryrun: false)
1837
+ log&.error err
1838
+ unless dryrun
1839
+ ret = on :error, from, err
1840
+ raise err if exception && ret != true
1789
1841
  end
1842
+ print_error(err, pass: pass) unless ret
1843
+ end
1844
+
1845
+ def pwd_set(pass: false, dryrun: false, from: nil)
1846
+ pwd = Dir.pwd
1847
+ return yield if (path.to_s == pwd || pass == true) && (workspace.mri? || !workspace.windows?)
1848
+
1849
+ Dir.chdir path
1850
+ ret = yield
1851
+ Dir.chdir pwd
1790
1852
  rescue StandardError => e
1791
- log&.error e
1792
- ret = on :error, from, e
1793
- raise if exception && ret != true
1853
+ on_error(e, from, dryrun: dryrun)
1794
1854
  else
1795
1855
  ret
1796
1856
  end
1797
1857
 
1798
1858
  def run_set(cmd, val = nil, opts: nil, **)
1799
- diso = @output[1] == false && !@output[0].nil?
1800
- dise = @output[2] == false
1859
+ noopt = @output[1] == false && !@output[0].nil?
1860
+ noenv = @output[2] == false
1801
1861
  parse = lambda do |data|
1802
1862
  ret = []
1803
1863
  if data[:command]
@@ -1817,8 +1877,8 @@ module Squared
1817
1877
  case cmd
1818
1878
  when Array
1819
1879
  @output = if cmd.all? { |data| data.is_a?(Hash) }
1820
- diso = false
1821
- dise = false
1880
+ noopt = false
1881
+ noenv = false
1822
1882
  cmd.map { |data| parse.call(data) }
1823
1883
  else
1824
1884
  cmd.dup
@@ -1829,14 +1889,14 @@ module Squared
1829
1889
  else
1830
1890
  @output[0] = cmd
1831
1891
  end
1832
- unless diso
1892
+ unless noopt
1833
1893
  if opts == false
1834
1894
  @output[1] = false
1835
1895
  elsif opts && opts != true
1836
1896
  @output[1] = opts
1837
1897
  end
1838
1898
  end
1839
- return if dise
1899
+ return if noenv
1840
1900
 
1841
1901
  if val.is_a?(Hash)
1842
1902
  @output[2] = val
@@ -1865,25 +1925,6 @@ module Squared
1865
1925
  @parent = val if val.is_a?(Project::Base)
1866
1926
  end
1867
1927
 
1868
- def exception_set(val)
1869
- @exception = env_bool(val, workspace.exception, strict: true)
1870
- end
1871
-
1872
- def pipe_set(val)
1873
- @pipe = env_pipe(val, workspace.pipe, strict: true)
1874
- end
1875
-
1876
- def verbose_set(val)
1877
- @verbose = case val
1878
- when NilClass
1879
- workspace.verbose
1880
- when String
1881
- env_bool(val, workspace.verbose, strict: true, index: true)
1882
- else
1883
- val
1884
- end
1885
- end
1886
-
1887
1928
  def graph_set(val)
1888
1929
  @graph = if val
1889
1930
  Array(val).map { |s| workspace.prefix ? workspace.task_name(s).to_sym : s.to_sym }.freeze
@@ -1891,7 +1932,11 @@ module Squared
1891
1932
  end
1892
1933
 
1893
1934
  def pass_set(val)
1894
- @pass = (val ? as_a(val, :to_s) : []).freeze
1935
+ @pass = Array(val).freeze
1936
+ end
1937
+
1938
+ def only_set(val)
1939
+ @only = val && as_a(val, :to_s).freeze
1895
1940
  end
1896
1941
 
1897
1942
  def exclude_set(val)
@@ -1950,6 +1995,14 @@ module Squared
1950
1995
  end
1951
1996
  end
1952
1997
 
1998
+ def task_pass?(key)
1999
+ @only ? !@only.include?(key) : @pass.include?(key)
2000
+ end
2001
+
2002
+ def matchany?(val, list, empty: true)
2003
+ list.empty? ? empty : list.any? { |pat| val.match?(pat) }
2004
+ end
2005
+
1953
2006
  def projectpath?(val)
1954
2007
  Pathname.new(val).cleanpath.yield_self do |file|
1955
2008
  file.absolute? ? file.to_s.start_with?(File.join(path, '')) : !file.to_s.start_with?(File.join('..', ''))
@@ -2051,6 +2104,14 @@ module Squared
2051
2104
  BLK_SET
2052
2105
  end
2053
2106
 
2107
+ def hashobj
2108
+ Workspace::Support.hashobj
2109
+ end
2110
+
2111
+ def hashlist
2112
+ Workspace::Support.hashlist
2113
+ end
2114
+
2054
2115
  def borderstyle
2055
2116
  workspace.banner_get(*@ref, group: group)&.border || theme[:border]
2056
2117
  end