squared 0.8.8 → 0.9.0.pre1

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.
@@ -163,6 +163,9 @@ module Squared
163
163
  end
164
164
  @pass.items.concat(kwargs[:pass].map { |val| val.is_a?(Regexp) ? val : val.to_s }) if kwargs[:pass]
165
165
  @series = Application.register(self, @base.to_a, exclude: kwargs.fetch(:exclude, []))
166
+ if (n = ARG[:APP][:series_ref_min])
167
+ @series.ref_min = n
168
+ end
166
169
  self.closed = 'begin'
167
170
  pb = @stage.key?('project:begin')
168
171
  pe = @stage.key?('project:end')
@@ -341,7 +344,7 @@ module Squared
341
344
  case val
342
345
  when Symbol
343
346
  found = true
344
- banner_include?(val)
347
+ banner_include?(val, ref: ref)
345
348
  when String
346
349
  true
347
350
  else
@@ -353,7 +356,7 @@ module Squared
353
356
  elsif meth.size == 1
354
357
  meth = meth.first
355
358
  end
356
- elsif !banner_include?(meth = meth.to_sym)
359
+ elsif !banner_include?(meth = meth.to_sym, ref: ref)
357
360
  next
358
361
  end
359
362
  data.order << meth
@@ -403,13 +406,17 @@ module Squared
403
406
  end
404
407
  unless ref.is_a?(Symbol) && (proj = @base.find { |item| item.ref == ref })
405
408
  proj = if !ref.is_a?(Class)
406
- find_project(ref: ref, path: path)
409
+ require_project(ref) || Application.find(ref: ref, path: path)
407
410
  elsif Application.extends(ref)
408
411
  ref
409
412
  end || @kind[name]&.last
410
413
  if proj
411
414
  @base << proj
412
- @banner.items.concat(Array(proj.bannerargs))
415
+ args = Array(proj.bannerargs)
416
+ unless args.empty?
417
+ @banner.store[proj.ref] = args
418
+ @banner.items.concat(args)
419
+ end
413
420
  else
414
421
  proj = Application.impl_project
415
422
  end
@@ -447,16 +454,6 @@ module Squared
447
454
  self
448
455
  end
449
456
 
450
- def assign(ref = @ref, &blk)
451
- proj = ref && find_project(ref: ref)
452
- if proj
453
- proj.class_eval(&blk)
454
- else
455
- warn log_message(Logger::ERROR, 'class not found', subject: main, hint: ref)
456
- end
457
- self
458
- end
459
-
460
457
  def stage(val, first: false, &blk)
461
458
  data = @stage[val]
462
459
  if first == true
@@ -484,7 +481,7 @@ module Squared
484
481
  obj = begin
485
482
  JSON.parse(homepath(obj).read, { symbolize_names: true })
486
483
  rescue => e
487
- warn log_message(Logger::ERROR, e, subject: main)
484
+ warn log_message(Logger::ERROR, e)
488
485
  end
489
486
  end
490
487
  apply_style(data || theme, obj, args, empty: empty) if obj && (!target || data)
@@ -590,7 +587,7 @@ module Squared
590
587
  def task_namespace(val, first: false)
591
588
  return unless (ret = val.to_s.split(':')).size > 1
592
589
 
593
- first ? ret.first : task_join(*ret[0..-2])
590
+ first ? ret.first : task_join(*ret[..-2])
594
591
  end
595
592
 
596
593
  def task_resolve(obj, key)
@@ -645,24 +642,16 @@ module Squared
645
642
  val = val.split(':') if val.is_a?(String)
646
643
  if before || after || opts
647
644
  pos = []
648
- append = lambda do |data|
649
- pos << case data
650
- when Array
651
- data.join(',')
652
- when Hash
653
- data.keys.join('|')
645
+ pos << (before.is_a?(Array) ? before.join(',') : before) if before
646
+ if opts
647
+ pos << if opts.is_a?(Array)
648
+ arg ? "#{arg}=#{opts.join(',')}" : opts.join('|')
654
649
  else
655
- data
650
+ opts
656
651
  end
657
652
  end
658
- append.call(before)
659
- pos << if opts.is_a?(Array)
660
- arg ? "#{arg}=#{opts.join(',')}" : opts.join('|')
661
- else
662
- opts
663
- end
664
- append.call(after)
665
- val << "#{val.pop}[#{pos.compact.join(',')}]"
653
+ pos << (after.is_a?(Array) ? after.join(',') : after) if after
654
+ val << "#{val.pop}[#{pos.join(',')}]"
666
655
  end
667
656
  out ? message(*val) : task_desc(*val)
668
657
  end
@@ -968,7 +957,7 @@ module Squared
968
957
  key = task_name(task_join(name, target))
969
958
  sync = true
970
959
  exception = exception?
971
- if store && (kwargs = store["#{target}:#{name}"])
960
+ if store && (kwargs = store[task_join(target, name)])
972
961
  sync = kwargs[:sync] if kwargs.key?(:sync)
973
962
  exception = kwargs[:exception] if kwargs.key?(:exception)
974
963
  end
@@ -989,9 +978,11 @@ module Squared
989
978
  end
990
979
  end
991
980
  when Array
992
- cmd = args.first
993
- cmd = items.map { |proj| "#{proj.name}:#{cmd}" }
994
- .select { |val| task_defined?(val) }
981
+ cmd = items.filter_map do |proj|
982
+ next unless task_defined?(out = task_join(proj.name, args.first))
983
+
984
+ out
985
+ end
995
986
  next if cmd.empty?
996
987
 
997
988
  args = args.drop(1)
@@ -1032,7 +1023,7 @@ module Squared
1032
1023
  @events[label][name][task] = on
1033
1024
  end
1034
1025
  data[label][name][task] = val
1035
- (data.store[label] ||= {})["#{name}:#{task}"] = store if store
1026
+ (data.store[label] ||= {})[task_join(name, task)] = store if store
1036
1027
  end
1037
1028
  self
1038
1029
  end
@@ -1046,7 +1037,7 @@ module Squared
1046
1037
  Array(group).each do |val|
1047
1038
  val = val.to_s
1048
1039
  if val.start_with?('-')
1049
- target[:exclude] << val[1..-1]
1040
+ target[:exclude] << val[1..]
1050
1041
  else
1051
1042
  target[:group][val] = data
1052
1043
  end
@@ -1055,7 +1046,7 @@ module Squared
1055
1046
  Array(ref).each do |val|
1056
1047
  val = val.to_s
1057
1048
  if val.start_with?('-')
1058
- target[:exclude] << val[1..-1].to_sym
1049
+ target[:exclude] << val[1..].to_sym
1059
1050
  else
1060
1051
  target[:ref][val.to_sym] = data
1061
1052
  end
@@ -1100,10 +1091,6 @@ module Squared
1100
1091
  nil
1101
1092
  end
1102
1093
 
1103
- def find_project(ref:, path: nil)
1104
- require_project(ref) || Application.find(ref: ref, path: path)
1105
- end
1106
-
1107
1094
  def root?(path, pass: [])
1108
1095
  return false unless path.directory?
1109
1096
 
@@ -1133,8 +1120,10 @@ module Squared
1133
1120
  exception != false && exception != Logger::INFO
1134
1121
  end
1135
1122
 
1136
- def banner_include?(val)
1137
- Application.attr_banner.include?(val) || @banner.items.include?(val)
1123
+ def banner_include?(val, ref: nil)
1124
+ return true if Application.attr_banner.include?(val)
1125
+
1126
+ ref ? Array(ref).any? { |proj| @banner.store[proj]&.include?(val) } : @banner.items.include?(val)
1138
1127
  end
1139
1128
 
1140
1129
  def scriptobj
@@ -102,7 +102,7 @@ module Squared
102
102
 
103
103
  @@tasks = {}
104
104
  @@graph = { _: [] }
105
- @@asdf = Pathname.new(ENV['ASDF_DIR'] || "#{Dir.home}/.asdf").yield_self do |path|
105
+ @@asdf = Pathname.new(ENV['ASDF_DIR'] || "#{Dir.home}/.asdf").then do |path|
106
106
  version = if path.join('asdf.sh').exist?
107
107
  15
108
108
  elsif ENV['ASDF_DATA_DIR'] && (path = Pathname.new(ENV['ASDF_DATA_DIR'])).exist?
@@ -640,7 +640,7 @@ module Squared
640
640
  end
641
641
  env('GRAPH', suffix: 'PASS') { |val| pass.concat(split_escape(val)) }
642
642
  start, neg = start.partition { |name| !name.start_with?('-') }
643
- data = graph_collect(self, start, pass: neg.map { |name| name[1..-1] })
643
+ data = graph_collect(self, start, pass: neg.map { |name| name[1..] })
644
644
  unless out
645
645
  data[name] << self
646
646
  on :first, :graph
@@ -700,7 +700,7 @@ module Squared
700
700
  headers = headers.is_a?(Hash) ? headers.merge(data) : data
701
701
  end
702
702
  if file
703
- ext ||= File.extname(file)[1..-1]
703
+ ext ||= File.extname(file)[1..]
704
704
  else
705
705
  require 'open-uri'
706
706
  data = nil
@@ -876,7 +876,7 @@ module Squared
876
876
  return
877
877
  end
878
878
  cmd = cmd.target if cmd.is_a?(OptionPartition)
879
- if interactive && sync && (!@session || !option('y'))
879
+ if interactive && sync && !(@session && option('y'))
880
880
  print_item(series: true)
881
881
  msg, y, h = case interactive
882
882
  when Array
@@ -924,9 +924,9 @@ module Squared
924
924
  end
925
925
  end
926
926
 
927
- def scope(*args, **kwargs, &blk)
927
+ def scope(...)
928
928
  namespace name do
929
- task(*args, **kwargs, &blk)
929
+ task(...)
930
930
  end
931
931
  end
932
932
 
@@ -1174,20 +1174,10 @@ module Squared
1174
1174
  ret = basepath(*args)
1175
1175
  return ret unless ascend && !ret.exist?
1176
1176
 
1177
- case ascend
1178
- when String, Pathname
1179
- root = Pathname.new(ascend).cleanpath
1180
- root = nil unless root.absolute? && root.directory?
1181
- end
1182
1177
  path.parent.ascend.each do |dir|
1183
1178
  target = dir.join(*args)
1184
1179
  return target if target.exist?
1185
-
1186
- if root
1187
- break if dir == root
1188
- elsif workspace.root == dir || parent&.path == dir || (ascend.is_a?(String) && dir.join(ascend).exist?)
1189
- break
1190
- end
1180
+ break if (ascend.is_a?(String) && dir.join(ascend).exist?) || workspace.root == dir || parent&.path == dir
1191
1181
  end
1192
1182
  ret
1193
1183
  end
@@ -1298,26 +1288,25 @@ module Squared
1298
1288
  file = if (val = env('LOG_FILE'))
1299
1289
  Time.now.strftime(val)
1300
1290
  elsif (val = env('LOG_AUTO'))
1301
- require 'date'
1291
+ d = Time.now
1302
1292
  "#{@name}-%s.log" % [case val
1303
1293
  when 'y', 'year'
1304
- Date.today.year
1294
+ d.year
1305
1295
  when 'm', 'month'
1306
- Date.today.strftime('%Y-%m')
1296
+ d.strftime('%Y-%m')
1307
1297
  when 'd', 'day', '1'
1308
- Date.today
1298
+ d.strftime('%Y-%m-%d')
1309
1299
  else
1310
- val.include?('%') ? Time.now.strftime(val) : Time.now.strftime('%FT%T%:z')
1300
+ val.include?('%') ? d.strftime(val) : d.strftime('%FT%T%:z')
1311
1301
  end]
1312
1302
  elsif (val = log[:file])
1313
1303
  if val.is_a?(String)
1314
1304
  Time.now.strftime(val)
1315
1305
  else
1316
- require 'date'
1317
- "#{@name}-#{Date.today}.log"
1306
+ "#{@name}-#{Time.now.strftime('%Y-%m-%d')}.log"
1318
1307
  end
1319
1308
  end
1320
- .yield_self do |path|
1309
+ .then do |path|
1321
1310
  next unless path
1322
1311
 
1323
1312
  @workspace.home.join(env('LOG_DIR', ''), path).realdirpath
@@ -1375,7 +1364,7 @@ module Squared
1375
1364
  run(val, var, sync: sync, banner: banner, **kwargs)
1376
1365
  end
1377
1366
  rescue => e
1378
- on_error(e, exception: exception?(**kwargs))
1367
+ on_error(e, exception: kwargs.fetch(:exception, exception?))
1379
1368
  end
1380
1369
  on :last, from
1381
1370
  end
@@ -1476,7 +1465,7 @@ module Squared
1476
1465
 
1477
1466
  t = uniq.call(name = proj.name)
1478
1467
  j = if out
1479
- if i == items.size.pred || (post = items[i.succ..-1] - done).empty?
1468
+ if i == items.size.pred || (post = items[i.succ..] - done).empty?
1480
1469
  true
1481
1470
  elsif !t.empty? && depth > 0
1482
1471
  (post - t).empty?
@@ -1582,14 +1571,18 @@ module Squared
1582
1571
  end
1583
1572
 
1584
1573
  def env(key, default = nil, suffix: nil, strict: false, ignore: nil, **kwargs, &blk)
1585
- name = "#{key}_#{envname_get}"
1574
+ name = suffix == false ? key : "#{key}_#{envname_get}"
1586
1575
  ret = if suffix
1587
1576
  ENV["#{name}_#{suffix}"] || (ignore == false && ENV["#{key}_#{suffix}"]) || ''
1588
1577
  elsif strict
1589
1578
  ENV[name].to_s
1590
1579
  else
1591
1580
  ignore = ['0'].freeze if ignore.nil?
1592
- ENV[name] || ENV.fetch(key, '')
1581
+ if key =~ /^(.+)_(FORCE|YES|Y)$/ && !(ret = __arg__($2 == 'Y' ? 'YES' : $2, $1)).nil?
1582
+ ret
1583
+ else
1584
+ ENV[name] || ENV.fetch(key, '')
1585
+ end
1593
1586
  end
1594
1587
  env_yield(ret, default, ignore: ignore, **kwargs, &blk)
1595
1588
  end
@@ -1693,19 +1686,38 @@ module Squared
1693
1686
  **kwargs)
1694
1687
  return unless prefix
1695
1688
 
1689
+ getarg = ->(key) { ARG[key][s = prefix.downcase] || ARG[key][s.to_sym] }
1696
1690
  args.each do |key|
1697
- next unless (ret = env(env_key(prefix.to_s.stripext, key), **kwargs)) && (!pat || ret.match?(pat))
1698
-
1699
- if target
1700
- if path
1701
- target << quote_option(key, basepath(ret))
1702
- elsif quote
1703
- target << quote_option(key, ret)
1704
- elsif escape
1705
- target << shell_option(key, ret)
1691
+ ret = case key.downcase
1692
+ when 'force'
1693
+ getarg.call(:FORCE)
1694
+ when 'y'
1695
+ getarg.call(:YES)
1696
+ end
1697
+ return yield(ret) if !ret.nil? && block_given?
1698
+
1699
+ case ret.to_s
1700
+ when '0'
1701
+ next
1702
+ when 'true'
1703
+ return true
1704
+ when 'false'
1705
+ return false
1706
+ else
1707
+ ret ||= env(env_key(prefix.to_s.stripext, key), **kwargs)
1708
+ next unless ret && (!pat || ret.match?(pat))
1709
+
1710
+ if target
1711
+ if path
1712
+ target << quote_option(key, basepath(ret))
1713
+ elsif quote
1714
+ target << quote_option(key, ret)
1715
+ elsif escape
1716
+ target << shell_option(key, ret)
1717
+ end
1706
1718
  end
1719
+ return block_given? ? yield(ret) : ret
1707
1720
  end
1708
- return block_given? ? yield(ret) : ret
1709
1721
  end
1710
1722
  nil
1711
1723
  end
@@ -1818,6 +1830,8 @@ module Squared
1818
1830
 
1819
1831
  case from
1820
1832
  when :outdated
1833
+ return if ENV['BANNER'] == 'false'
1834
+
1821
1835
  out = print_footer("major #{args[0]} / minor #{args[1]} / patch #{args[2]}", right: true).split("\n")
1822
1836
  sub_style!(out[1], **opt_style(theme[:major], /^( +major )(\d+)(.+)$/, 2))
1823
1837
  sub_style!(out[1], **opt_style(theme[:active], /^(.+)(minor )(\d+)(.+)$/, 3))
@@ -1911,7 +1925,7 @@ module Squared
1911
1925
  out << ''
1912
1926
  end
1913
1927
  if from
1914
- out << (from = from.to_s)
1928
+ out << from
1915
1929
  /\A(#{Regexp.escape(from)})(.*)\z/
1916
1930
  end
1917
1931
  else
@@ -2040,27 +2054,27 @@ module Squared
2040
2054
  val
2041
2055
  end
2042
2056
  end
2043
- base.update(data)
2044
- .update(ret)
2057
+ base.update(data, ret)
2045
2058
  end
2046
2059
 
2047
2060
  def merge_opts(base, data)
2061
+ s = '%s %s'
2048
2062
  case data
2049
2063
  when String
2050
2064
  case base
2051
2065
  when String
2052
- "#{base} #{data}"
2066
+ s % [base, data]
2053
2067
  when Hash
2054
- "#{append_hash(base, target: []).join(' ')} #{data}"
2068
+ s % [append_hash(base, target: []).join(' '), data]
2055
2069
  when Enumerable
2056
- "#{base.to_a.join(' ')} #{data}"
2070
+ s % [base.to_a.join(' '), data]
2057
2071
  else
2058
2072
  data
2059
2073
  end
2060
2074
  when Hash
2061
2075
  case base
2062
2076
  when String
2063
- "#{base} #{append_hash(data, target: []).join(' ')}"
2077
+ s % [base, append_hash(data, target: []).join(' ')]
2064
2078
  when Hash
2065
2079
  base.merge(data)
2066
2080
  when Enumerable
@@ -2071,9 +2085,9 @@ module Squared
2071
2085
  when Enumerable
2072
2086
  case base
2073
2087
  when String
2074
- "#{base} #{data.to_a.join(' ')}"
2088
+ s % [base, data.to_a.join(' ')]
2075
2089
  when Hash
2076
- "#{append_hash(base, target: []).join(' ')} #{data.to_a.join(' ')}"
2090
+ s % [append_hash(base, target: []).join(' '), data.to_a.join(' ')]
2077
2091
  when Enumerable
2078
2092
  Set.new(base.to_a + data.to_a).to_a
2079
2093
  else
@@ -2107,6 +2121,17 @@ module Squared
2107
2121
  end || []
2108
2122
  end
2109
2123
 
2124
+ def parse_select(kwargs = {})
2125
+ pa, ch = ENV.fetch('SELECT', '0:0').split(':').map(&:to_i)
2126
+ if pa > 0
2127
+ kwargs[:page] = pa
2128
+ elsif !kwargs.key?(:page)
2129
+ kwargs[:page] = ARG[:PAGE]
2130
+ end
2131
+ kwargs[:max] = ch if ch > 0
2132
+ kwargs
2133
+ end
2134
+
2110
2135
  def param_guard(action, flag, args:, key: nil, pat: nil, values: nil)
2111
2136
  if args && key
2112
2137
  val = args.fetch(key, nil)
@@ -2140,9 +2165,9 @@ module Squared
2140
2165
  end
2141
2166
 
2142
2167
  def choice_index(msg, list, values: nil, accept: nil, series: false, trim: nil, column: nil, multiple: false,
2143
- force: true, **kwargs)
2168
+ force: true, pipe: self.pipe, **kwargs)
2144
2169
  puts unless series || printfirst?
2145
- ret = choice(msg, list, multiple: multiple, force: force, **kwargs)
2170
+ ret = choice(msg, list, multiple: multiple, force: force, pipe: pipe, **parse_select(kwargs))
2146
2171
  unless ret && !ret.empty?
2147
2172
  exit 1 if force
2148
2173
  return
@@ -2226,12 +2251,12 @@ module Squared
2226
2251
  end
2227
2252
 
2228
2253
  def relativepath(*list, all: false)
2229
- list.map { |val| Pathname.new(val) }
2230
- .select { |val| projectpath?(val) }
2231
- .map do |val|
2232
- ret = (val.absolute? ? val.relative_path_from(path) : val.cleanpath).to_s
2233
- all && val.to_s.end_with?('/') ? "#{ret}/*" : ret
2234
- end
2254
+ list.filter_map do |val|
2255
+ next unless projectpath?(file = Pathname.new(val))
2256
+
2257
+ out = (file.absolute? ? file.relative_path_from(path) : file.cleanpath).to_s
2258
+ all && file.to_s.end_with?('/') ? "#{out}/*" : out
2259
+ end
2235
2260
  end
2236
2261
 
2237
2262
  def projectmap(files, resolve: true, parent: false, pass: true)
@@ -2334,6 +2359,19 @@ module Squared
2334
2359
  cur[2] == lat[2] ? 3 : 2
2335
2360
  end
2336
2361
 
2362
+ def semapp(name, *args, minor: true, patch: true, pre: false, env: false)
2363
+ if args.empty?
2364
+ args << '--version'
2365
+ else
2366
+ args.map! { |s| shell_quote(s, force: false) }
2367
+ end
2368
+ n = minor ? patch ? pre ? -1 : 4 : 2 : 0
2369
+ IO.popen([shell_bin(name, env: env), *args], chdir: path, &:read).scan(SEM_VER).first
2370
+ &.slice(0..n)&.join or raise
2371
+ rescue
2372
+ '0.0.0'
2373
+ end
2374
+
2337
2375
  def semmajor?(cur, want)
2338
2376
  (cur[0] == '0' && want[0] == '0' ? cur[2] != want[2] : cur[0] != want[0]) && !want[6]
2339
2377
  end
@@ -2347,7 +2385,7 @@ module Squared
2347
2385
  end
2348
2386
 
2349
2387
  def indexitem(val)
2350
- [$1.to_i, $2 && $2[1..-1]] if val =~ /\A[=^#{indexchar}](\d+)(:.+)?\z/
2388
+ [$1.to_i, $2 && $2[1..]] if val =~ /\A[=^#{indexchar}](\d+)(:.+)?\z/
2351
2389
  end
2352
2390
 
2353
2391
  def indexerror(val, list = nil)
@@ -2451,7 +2489,6 @@ module Squared
2451
2489
  def pwd_set(cmd = nil, pass: false, timeout: nil, from: @on[:from].last, **kwargs, &blk)
2452
2490
  return if from == false
2453
2491
 
2454
- require 'timeout'
2455
2492
  unless (path.to_s == Dir.pwd || pass) && (mri? || !windows?)
2456
2493
  pwd = Dir.pwd
2457
2494
  Dir.chdir(path)
@@ -2748,7 +2785,15 @@ module Squared
2748
2785
  end
2749
2786
 
2750
2787
  def dryrun?(target: @session, prefix: target&.first, **)
2751
- Array(target).include?('--dry-run') || !option('dry-run', target: target, prefix: prefix).nil?
2788
+ val = ENV['DRY_RUN'] if (val = option('dry-run', target: target, prefix: prefix)).nil?
2789
+ case val.to_s
2790
+ when '0' then nil
2791
+ when 'false'
2792
+ return false
2793
+ else
2794
+ return true if val
2795
+ end
2796
+ Array(target).include?('--dry-run')
2752
2797
  end
2753
2798
 
2754
2799
  def pwd?
@@ -2775,9 +2820,7 @@ module Squared
2775
2820
  workspace.warning
2776
2821
  end
2777
2822
 
2778
- def exception?(*level, **kwargs)
2779
- return kwargs[:exception] if kwargs.key?(:exception)
2780
-
2823
+ def exception?(*level)
2781
2824
  ret = exception
2782
2825
  return ret unless ret.is_a?(Numeric)
2783
2826