squared 0.7.6 → 0.8.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.
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
- require 'logger'
5
4
 
6
5
  require_relative 'support/class'
7
6
  require_relative 'support/utils'
@@ -10,6 +9,7 @@ module Squared
10
9
  module Workspace
11
10
  module Project
12
11
  class Base
12
+ include Enumerable
13
13
  include Comparable
14
14
  include Common::Format
15
15
  include System
@@ -25,7 +25,7 @@ module Squared
25
25
  VAR_SET = %i[parent global script index envname desc dependfile dependname dependindex theme archive env graph
26
26
  dev prod timeout pass only exclude serve asdf].freeze
27
27
  BLK_SET = %i[run depend doc lint test copy clean].freeze
28
- SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+))?[-.]?(\S+)?\b/.freeze
28
+ SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+))?(?:([-.])?(\S+))?\b/.freeze
29
29
  URI_SCHEME = %r{\A([a-z][a-z\d+-.]*)://[^@:\[\]\\^<>|\s]}i.freeze
30
30
  TASK_METADATA = Rake::TaskManager.record_task_metadata
31
31
  private_constant :OPTIONS, :VAR_SET, :BLK_SET, :SEM_VER, :URI_SCHEME, :TASK_METADATA
@@ -343,7 +343,7 @@ module Squared
343
343
  tag ||= if @release
344
344
  "%s.#{ext}" % [@release.include?('??') ? @release.sub('??', tag) : @release + tag]
345
345
  else
346
- raise_error ArgumentError, "no base uri: #{tag}", hint: ext
346
+ raise ArgumentError, message('no base uri', tag, hint: ext)
347
347
  end
348
348
  end
349
349
  force = case (digest = args.digest)
@@ -471,10 +471,10 @@ module Squared
471
471
  cmd = args.each_with_object([]) do |val, out|
472
472
  case val.first
473
473
  when Proc
474
- instance_exec(*val[1..-1], &val.first)
474
+ instance_exec(*val.drop(1), &val.first)
475
475
  next
476
476
  when Method
477
- val.first.call(*val[1..-1])
477
+ val.first.call(*val.drop(1))
478
478
  next
479
479
  end
480
480
  a, b, c, d, e = val
@@ -542,7 +542,7 @@ module Squared
542
542
  on_error(e, exception: true)
543
543
  end
544
544
  else
545
- print_error('prereqs', "method: #{meth}", subject: name, hint: 'undefined')
545
+ print_error('prereqs', 'method', meth, subject: name, hint: 'undefined')
546
546
  end
547
547
  end
548
548
  elsif proj.build?
@@ -582,10 +582,10 @@ module Squared
582
582
  case @clean
583
583
  when Struct
584
584
  if (val = instance_eval(&@clean.block) || @clean.run)
585
- @clean = @clean.tap do
586
- @clean = val
587
- clean(*args, sync: sync, pass: true, **kwargs)
588
- end
585
+ cur = @clean
586
+ @clean = val
587
+ clean(*args, sync: sync, pass: true, **kwargs)
588
+ @clean = cur
589
589
  end
590
590
  when String
591
591
  run_s(@clean, sync: sync)
@@ -661,9 +661,10 @@ module Squared
661
661
  if !target.exist?
662
662
  target.mkpath
663
663
  elsif !target.directory?
664
- raise_error Errno::EEXIST, target, hint: uri
664
+ raise Errno::EEXIST, message(target, hint: uri)
665
665
  elsif !file && !target.empty?
666
- raise_error Errno::EEXIST, target, hint: uri unless force || env('UNPACK_FORCE')
666
+ raise Errno::EEXIST, message(target, hint: uri) unless force || env('UNPACK_FORCE')
667
+
667
668
  create = true
668
669
  end
669
670
  if digest
@@ -683,7 +684,7 @@ module Squared
683
684
  when 128, 'sha512'
684
685
  Digest::SHA512
685
686
  else
686
- raise_error "invalid checksum: #{digest}", hint: uri
687
+ raise message('invalid checksum', digest, hint: uri)
687
688
  end
688
689
  end
689
690
  env('HEADERS') do |val|
@@ -701,14 +702,14 @@ module Squared
701
702
  data = f.read
702
703
  if algo && algo.hexdigest(data) != digest
703
704
  data = nil
704
- raise_error "invalid checksum: #{digest}", hint: url if i == uri.size.pred
705
+ raise message('invalid checksum', digest, hint: url) if i == uri.size.pred
705
706
  end
706
707
  next if ext && i == 0
707
708
 
708
709
  case f.content_type
709
710
  when 'application/zip'
710
711
  ext = 'zip'
711
- when %r{application/(?:x-)?gzip}
712
+ when %r{application/(x-)?gzip}
712
713
  ext = 'tgz'
713
714
  when 'application/x-xz'
714
715
  ext = 'txz'
@@ -719,7 +720,7 @@ module Squared
719
720
  break uri = url if data
720
721
  end
721
722
  unless data && (ext ||= URI.decode_www_form_component(URI.parse(uri).path[/\.([\w%]+)(?:\?|\z)/, 1]))
722
- raise_error(data ? TypeError : RuntimeError, "no content#{' type' if data}", hint: uri)
723
+ raise(data ? TypeError : RuntimeError, message("no content#{' type' if data}", hint: uri))
723
724
  end
724
725
  end
725
726
  ext = ext.downcase
@@ -748,7 +749,7 @@ module Squared
748
749
  case ext
749
750
  when 'zip', 'aar'
750
751
  session 'unzip', shell_quote(file), quote_option('d', target)
751
- when 'tar', /\A(?:t|tar\.)?[gx]z\z/
752
+ when 'tar', /\A(t|tar\.)?[gx]z\z/
752
753
  flags = +(silent? ? '' : 'v')
753
754
  if ext.end_with?('gz')
754
755
  flags += 'z'
@@ -764,7 +765,7 @@ module Squared
764
765
  session 'gem', 'unpack', shell_quote(file), quote_option('target', target)
765
766
  depth = 0 unless val
766
767
  else
767
- raise_error("unsupported format: #{ext}", hint: uri || file)
768
+ raise message('unsupported format', ext, hint: uri || file)
768
769
  end
769
770
  run(sync: sync, banner: verbose, from: from)
770
771
  while depth > 0 && target.children.size == 1
@@ -1018,13 +1019,13 @@ module Squared
1018
1019
 
1019
1020
  alias apply variable_set
1020
1021
 
1021
- def enabled?(ref = nil, **)
1022
+ def enabled?(ref: nil, **)
1022
1023
  return false if ref && Array(ref).none? { |val| ref?(val) }
1023
1024
 
1024
1025
  (path.directory? && !path.empty?) || archive?
1025
1026
  end
1026
1027
 
1027
- def has?(meth, ref = nil, all: false, missing: false)
1028
+ def has?(meth, ref: nil, all: false, missing: false)
1028
1029
  return false if ref && !ref?(ref)
1029
1030
 
1030
1031
  pred = :"#{meth}?"
@@ -1105,8 +1106,8 @@ module Squared
1105
1106
  !@exclude.empty? && has_value?(@exclude, *refs)
1106
1107
  end
1107
1108
 
1108
- def task_include?(key, ref = nil)
1109
- workspace.task_include?(self, key, ref) && !@pass.include?(key.to_s)
1109
+ def task_include?(key, ref: nil)
1110
+ workspace.task_include?(self, key, ref: ref) && !@pass.include?(key.to_s)
1110
1111
  end
1111
1112
 
1112
1113
  def version(*)
@@ -1189,6 +1190,20 @@ module Squared
1189
1190
  keys.empty? ? ret : ret.dig(*keys)
1190
1191
  end
1191
1192
 
1193
+ def each(from: :run, ref: nil, accept: nil, &blk)
1194
+ from = from.to_s.split(':').last if from.is_a?(Symbol)
1195
+ items = ref ? children.select { |proj| proj.ref?(ref) } : children
1196
+ if items.empty?
1197
+ print_error("nothing to #{from}", subject: name)
1198
+ elsif accept && !confirm_basic("#{from.capitalize} workspace?", items.map(&:name).join(', '), accept,
1199
+ prefix: 'npm')
1200
+ items.clear
1201
+ end
1202
+ return items.to_enum unless block_given?
1203
+
1204
+ items.each(&blk)
1205
+ end
1206
+
1192
1207
  def inspect
1193
1208
  "#<#{self.class}: #{name} => #{self}>"
1194
1209
  end
@@ -1351,7 +1366,7 @@ module Squared
1351
1366
  else
1352
1367
  if series?(obj)
1353
1368
  obj.each(&:call)
1354
- elsif obj.is_a?(Array) && obj.any? { |val| val.nil? || !val.is_a?(String) }
1369
+ elsif obj.is_a?(Array) && obj.any? { |val| !val.is_a?(String) }
1355
1370
  build(*obj, **kwargs)
1356
1371
  elsif obj
1357
1372
  run_s(*Array(obj), **kwargs)
@@ -1389,7 +1404,7 @@ module Squared
1389
1404
  elsif ws.task_defined?(val = task_join(name, meth)) || (meth.include?(':') && ws.task_defined?(val = meth))
1390
1405
  run(val, var, sync: sync, banner: banner, **kwargs)
1391
1406
  elsif from
1392
- print_error(from, "method: #{meth}", subject: name, hint: 'undefined')
1407
+ print_error(from, 'method', meth, subject: name, hint: 'undefined')
1393
1408
  end
1394
1409
  end
1395
1410
  end
@@ -1422,11 +1437,7 @@ module Squared
1422
1437
  when 0
1423
1438
  f
1424
1439
  when 1
1425
- if items.empty?
1426
- "#{d}#{b * 4} #{f}"
1427
- else
1428
- "#{last ? d : c}#{b * 3}#{e} #{f}"
1429
- end
1440
+ items.empty? ? "#{d}#{b * 4} #{f}" : "#{last ? d : c}#{b * 3}#{e} #{f}"
1430
1441
  else
1431
1442
  "#{single ? ' ' : a}#{' ' * depth.pred}#{last ? d : c}#{b * 3}#{items.empty? ? b : e} #{f}"
1432
1443
  end
@@ -1490,7 +1501,7 @@ module Squared
1490
1501
  end
1491
1502
  run(cmd, sync: false, banner: false)
1492
1503
  ENV.delete(key) if key
1493
- elsif proj.has?(meth, tasks || graph ? nil : workspace.baseref)
1504
+ elsif proj.has?(meth, ref: (workspace.baseref unless tasks || graph))
1494
1505
  proj.__send__(meth, sync: sync)
1495
1506
  end
1496
1507
  end
@@ -1572,11 +1583,13 @@ module Squared
1572
1583
  end
1573
1584
  cache = @timeout[:_]
1574
1585
  cache[1] ||= workspace.timeout_get(*@ref, group: group)
1575
- cache[0][ret] = if cmd[1..-1].find { |val| val =~ /\A([A-Za-z][\w-]*)(?<![-_])(?: |\z)/ }
1586
+ cache[0][ret] = if cmd.drop(1).find { |val| val =~ /\A([A-Za-z][\w-]*)(?<![-_])(?: |\z)/ }
1576
1587
  command = :"#{prefix}_#{$1}"
1577
1588
  cache[1][command] || @timeout[command]
1578
1589
  end || cache[1][prefix.to_sym] || @timeout[prefix.to_sym]
1579
- main ? @session = ret : ret
1590
+ return ret unless main
1591
+
1592
+ @session = ret
1580
1593
  end
1581
1594
 
1582
1595
  def session_timeout(cmd)
@@ -1636,9 +1649,9 @@ module Squared
1636
1649
 
1637
1650
  def session_done(cmd)
1638
1651
  return cmd.to_s unless cmd.respond_to?(:done)
1652
+ raise message('no command added', hint: cmd.first) unless cmd.size > 1
1639
1653
 
1640
- raise_error 'no command added', hint: cmd.first unless cmd.size > 1
1641
- @session = nil if cmd == @session
1654
+ @session = nil if cmd.equal?(@session)
1642
1655
  cmd.done
1643
1656
  end
1644
1657
 
@@ -1655,12 +1668,14 @@ module Squared
1655
1668
  args.each do |key|
1656
1669
  next unless (ret = env(env_key(prefix.to_s.stripext, key), **kwargs)) && (!pat || ret.match?(pat))
1657
1670
 
1658
- if path
1659
- target << quote_option(key, basepath(ret))
1660
- elsif quote
1661
- target << quote_option(key, ret)
1662
- elsif escape
1663
- target << shell_option(key, ret)
1671
+ if target
1672
+ if path
1673
+ target << quote_option(key, basepath(ret))
1674
+ elsif quote
1675
+ target << quote_option(key, ret)
1676
+ elsif escape
1677
+ target << shell_option(key, ret)
1678
+ end
1664
1679
  end
1665
1680
  return block_given? ? yield(ret) : ret
1666
1681
  end
@@ -1668,7 +1683,7 @@ module Squared
1668
1683
  end
1669
1684
 
1670
1685
  def write_lines(data, grep: [], prefix: nil, sub: nil, banner: nil, loglevel: nil, pass: false, first: false)
1671
- grep = (matchmap(grep, prefix) unless grep.empty?)
1686
+ grep = (matchmap(grep, prefix: prefix) unless grep.empty?)
1672
1687
  sub = (as_a(sub) unless stdin?)
1673
1688
  ret = 0
1674
1689
  lines = data.each_with_object([]) do |line, out|
@@ -1804,15 +1819,15 @@ module Squared
1804
1819
  out = []
1805
1820
  if data.command
1806
1821
  if command
1807
- if cmd =~ /\A(?:"((?:[^"]|(?<=\\)")+)"|'((?:[^']|(?<=\\)')+)'|(\S+))( |\z)/
1822
+ if cmd =~ /\A(?:"((?:[^"]|(?<=\\)")+)"|'((?:[^']|(?<=\\)')+)'|(\S+))(?: |\z)/
1808
1823
  arg = $3 || $2 || $1
1809
1824
  cmd = cmd.sub(arg, data.command == 0 ? arg.stripext : arg.stripext.upcase)
1810
1825
  end
1811
1826
  if strip || (strip.nil? && data.order.include?(:path))
1812
- cmd = cmd.gsub(/(?:#{s = Regexp.escape(File.join(path, ''))}?(?=["'])|#{s})/, '')
1813
- .gsub(/(?: -[^ ])? (?:""|'')/, '')
1827
+ s = Regexp.escape(File.join(path, ''))
1828
+ cmd = cmd.gsub(/(#{s}?(?=["'])|#{s})/, '').gsub(/( -[^ ])? (""|'')/, '')
1814
1829
  end
1815
- cmd.gsub!(/(?<= )(["'])([\w.-]+)\1(?= |\z)/, '\2') unless quote
1830
+ cmd = cmd.gsub(/(?<= )(["'])([\w.-]+)\1(?= |\z)/, '\2') unless quote
1816
1831
  end
1817
1832
  out << cmd.subhint(hint)
1818
1833
  end
@@ -1829,7 +1844,7 @@ module Squared
1829
1844
  __send__ meth
1830
1845
  end
1831
1846
  end
1832
- val = val.compact.join(s)
1847
+ val = val.reject { |item| !item || item == true }.join(s)
1833
1848
  next unless found && !val.empty?
1834
1849
  elsif (val = __send__(val)).nil?
1835
1850
  next
@@ -2034,11 +2049,6 @@ module Squared
2034
2049
  end
2035
2050
  end
2036
2051
 
2037
- def collect_hash(data, pass: [])
2038
- data = data.reject { |key,| pass.include?(key) } unless pass.empty?
2039
- data.values.flatten
2040
- end
2041
-
2042
2052
  def replace_bin(val)
2043
2053
  a, b = val.split(' ', 2)
2044
2054
  return val if val.start_with?(/["']/) || a.include?(File::Separator)
@@ -2048,7 +2058,7 @@ module Squared
2048
2058
 
2049
2059
  def parse_json(val, kind: Hash, key: nil, hint: nil, &blk)
2050
2060
  ret = JSON.parse(val)
2051
- raise_error 'invalid JSON'.subhint(kind.name), val, hint: hint if kind && !ret.is_a?(kind)
2061
+ raise message('invalid JSON', kind.name, hint: hint) if kind && !ret.is_a?(kind)
2052
2062
  return ret unless key
2053
2063
 
2054
2064
  block_given? ? ret.fetch(key, &blk) : ret[key]
@@ -2068,18 +2078,18 @@ module Squared
2068
2078
  return val unless val.nil? || (pat && !val.match?(pat)) || (values && !values.include?(val))
2069
2079
 
2070
2080
  @session = nil
2071
- raise_error(action, "#{flag}[#{key}]", hint: val.nil? ? 'missing' : 'invalid')
2081
+ raise message(action, "#{flag}[#{key}]", hint: val.nil? ? 'missing' : 'invalid')
2072
2082
  elsif args.is_a?(Array) && args.empty?
2073
2083
  @session = nil
2074
- raise_error action, "#{flag}+", hint: 'empty'
2084
+ raise message(action, "#{flag}+", hint: 'empty')
2075
2085
  end
2076
2086
  args
2077
2087
  end
2078
2088
 
2079
- def confirm_basic(msg, hint, default = 'Y', style: :inline, target: @session, prefix: nil, **kwargs)
2089
+ def confirm_basic(msg, hint, accept = 'Y', style: :inline, target: @session, prefix: nil, **kwargs)
2080
2090
  return true if prefix ? option('y', prefix: prefix) : target && option('y', target: target)
2081
2091
 
2082
- confirm("#{msg} [#{sub_style(hint.to_s, style.is_a?(Symbol) ? theme[style] : style)}]", default, **kwargs)
2092
+ confirm("#{msg} [#{sub_style(hint.to_s, style.is_a?(Symbol) ? theme[style] : style)}]", accept, **kwargs)
2083
2093
  end
2084
2094
 
2085
2095
  def confirm_semver(msg, type, style: (type == 1 && theme[:major]) || :inline, timeout: 0, **kwargs)
@@ -2139,12 +2149,8 @@ module Squared
2139
2149
  ret
2140
2150
  end
2141
2151
 
2142
- def accept_b(val, yes = false)
2143
- [val, true, yes]
2144
- end
2145
-
2146
- def accept_y(val, bool = false)
2147
- [val, bool, true]
2152
+ def accept_b(val, ret: true, yes: false)
2153
+ [val, ret, yes]
2148
2154
  end
2149
2155
 
2150
2156
  def command_args(args, min: 0, force: false, **kwargs)
@@ -2205,10 +2211,6 @@ module Squared
2205
2211
  end
2206
2212
  end
2207
2213
 
2208
- def symjoin(*args, char: ':')
2209
- args.join(char).to_sym
2210
- end
2211
-
2212
2214
  def semver(val)
2213
2215
  return val if val[3]
2214
2216
 
@@ -2233,9 +2235,9 @@ module Squared
2233
2235
 
2234
2236
  a, b = [a.first, b.first].map do |c|
2235
2237
  d = begin
2236
- Integer(c[5]).to_s
2238
+ Integer(c[6]).to_s
2237
2239
  rescue
2238
- c[5] ? '-1' : '0'
2240
+ c[6] ? '-1' : '0'
2239
2241
  end
2240
2242
  [c[0], c[2], c[4] || '0', d]
2241
2243
  end
@@ -2250,7 +2252,7 @@ module Squared
2250
2252
  def sembump(val, flag = :patch, join: true)
2251
2253
  ret = semscan(val, fill: false)
2252
2254
  case flag
2253
- when :major
2255
+ when :major, :premajor
2254
2256
  ret[2] = if ret[0] != '0' || ret[2].nil?
2255
2257
  ret[0] = ret[0].succ
2256
2258
  '0'
@@ -2258,16 +2260,29 @@ module Squared
2258
2260
  ret[2].succ
2259
2261
  end
2260
2262
  ret[4] = '0'
2261
- when :minor
2263
+ when :minor, :preminor
2262
2264
  if ret[0] == '0'
2263
2265
  ret[4] &&= ret[4].succ
2264
2266
  else
2265
2267
  ret[2] = ret[2].succ
2266
2268
  ret[4] &&= '0'
2267
2269
  end
2268
- when :patch
2270
+ when :patch, :prepatch
2269
2271
  ret[4] &&= ret[4].succ
2270
2272
  end
2273
+ case flag
2274
+ when :premajor, :preminor, :prepatch
2275
+ ret[5] ||= '-'
2276
+ ret[6] = '0'
2277
+ when :prerelease
2278
+ if !ret[6]
2279
+ ret[5] = '-'
2280
+ ret[6] = '0'
2281
+ elsif ret[6].match?(/^\d+$/)
2282
+ ret[5] ||= '-'
2283
+ ret[6] = ret[6].succ
2284
+ end
2285
+ end
2271
2286
  join ? ret.join : ret
2272
2287
  end
2273
2288
 
@@ -2278,7 +2293,7 @@ module Squared
2278
2293
  end
2279
2294
 
2280
2295
  def semmajor?(cur, want)
2281
- (cur[0] == '0' && want[0] == '0' ? cur[2] != want[2] : cur[0] != want[0]) && !want[5]
2296
+ (cur[0] == '0' && want[0] == '0' ? cur[2] != want[2] : cur[0] != want[0]) && !want[6]
2282
2297
  end
2283
2298
 
2284
2299
  def semgte?(val, other = nil)
@@ -2294,7 +2309,7 @@ module Squared
2294
2309
  end
2295
2310
 
2296
2311
  def indexerror(val, list = nil)
2297
- raise_error IndexError, "requested index #{val}", hint: ("of #{list.size}" if list)
2312
+ raise IndexError, message("requested index #{val}", hint: ("of #{list.size}" if list))
2298
2313
  end
2299
2314
 
2300
2315
  def indexchar
@@ -2406,11 +2421,7 @@ module Squared
2406
2421
  yield
2407
2422
  end
2408
2423
  rescue Timeout::Error => e
2409
- if cmd
2410
- print_error(Logger::ERROR, cmd, subject: name, hint: e)
2411
- else
2412
- print_error(Logger::ERROR, e, subject: name)
2413
- end
2424
+ print_error(Logger::ERROR, e, subject: name, hint: cmd)
2414
2425
  exit 1 unless exception?(Logger::DEBUG, Logger::INFO)
2415
2426
  rescue => e
2416
2427
  on_error(e, from, **kwargs)
@@ -2673,7 +2684,7 @@ module Squared
2673
2684
  when true, false
2674
2685
  run
2675
2686
  else
2676
- $?.success?
2687
+ $?&.success?
2677
2688
  end
2678
2689
  if cond.none? { |val| val == false }
2679
2690
  if block_given?
@@ -2698,7 +2709,7 @@ module Squared
2698
2709
  end
2699
2710
 
2700
2711
  def stdout?
2701
- !!verbose && !stdin?
2712
+ !silent? && !stdin?
2702
2713
  end
2703
2714
 
2704
2715
  def verbose?
@@ -2714,8 +2725,10 @@ module Squared
2714
2725
  end
2715
2726
 
2716
2727
  def exception?(*level)
2717
- ex = exception
2718
- level.empty? ? ex != false && ex != Logger::INFO : ex.is_a?(Numeric) && level.include?(ex)
2728
+ ret = exception
2729
+ return ret unless ret.is_a?(Numeric)
2730
+
2731
+ level.empty? ? ret != Logger::INFO : level.include?(ret)
2719
2732
  end
2720
2733
 
2721
2734
  def strict?