squared 0.8.4 → 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.
@@ -4,7 +4,7 @@ module Squared
4
4
  module Workspace
5
5
  module Project
6
6
  class Python < Git
7
- DEP_PYTHON = %w[poetry.lock setup.cfg pyproject.toml setup.py requirements.txt].freeze
7
+ DEP_PYTHON = %w[poetry.lock pdm.lock pylock.toml setup.cfg pyproject.toml setup.py requirements.txt].freeze
8
8
  DIR_PYTHON = (DEP_PYTHON + %w[meson.build README.rst]).freeze
9
9
  OPT_PYTHON = {
10
10
  common: %w[b=+ B d E h i I O P q=+ s S u v=+ V=+ x c=q m=b W=b X=q check-hash-based-pycs=b].freeze,
@@ -58,8 +58,8 @@ module Squared
58
58
  u|username=qq].freeze
59
59
  }.freeze
60
60
  OPT_PDM = {
61
- common: %w[I|ignore-python no-cache n|non-interactive].freeze,
62
- build: %w[C=bm no-clean no-isolation no-sdist no-wheel q|quiet v|verbose=+ config-setting=q d|dest=p
61
+ common: %w[c|config I|ignore-python no-cache n|non-interactive].freeze,
62
+ build: %w[C=bm no-clean no-isolation no-sdist no-wheel q|quiet v|verbose=+ config-setting=qq d|dest=p
63
63
  p|project=p k|skip=b].freeze,
64
64
  publish: %w[no-build no-very-ssl q|quiet S|sign skip-existing v|verbose=+ ca-certs=p c|comment=q d|dest=p
65
65
  i|identity=b P|password=q p|project=p r|repository=q k|skip=b u|username=qq].freeze
@@ -131,7 +131,7 @@ module Squared
131
131
  initialize_build(Python.ref, **kwargs)
132
132
  initialize_env(**kwargs)
133
133
  end
134
- dependfile_set(DEP_PYTHON, default: 2)
134
+ dependfile_set(DEP_PYTHON, default: 4)
135
135
  serve_set kwargs[:serve]
136
136
  editable_set editable
137
137
  venv_set kwargs[:venv]
@@ -297,7 +297,7 @@ module Squared
297
297
  install flag, ['upgrade', *args.to_a, 'pip']
298
298
  end
299
299
  when :freeze
300
- format_desc action, flag, "file?=#{DEP_PYTHON[4]},u/ninstall?,opts*"
300
+ format_desc action, flag, "file?=#{DEP_PYTHON[6]},u/ninstall?,opts*"
301
301
  task flag do |_, args|
302
302
  opts = args.to_a
303
303
  if has_value!(opts, 'u', 'uninstall')
@@ -351,7 +351,7 @@ module Squared
351
351
  'eager'
352
352
  when /^only-if|needed$/
353
353
  'only-if-needed'
354
- end.yield_self do |val|
354
+ end.then do |val|
355
355
  if val
356
356
  args.extras << "upgrade-strategy=#{val}"
357
357
  else
@@ -430,7 +430,17 @@ module Squared
430
430
  workspace.rev_clear(name, sync: sync)
431
431
  if !flag && poetry?
432
432
  cmd = poetry_session 'install -n'
433
+ if prod?
434
+ cmd << '--only=main'
435
+ else
436
+ option('with') { |val| cmd << basic_option('with', val) }
437
+ option('without') { |val| cmd << basic_option('without', val) }
438
+ end
433
439
  cmd << '--no-root' if option('no-root')
440
+ elsif !flag && pdm?
441
+ cmd = pdm_session 'install'
442
+ cmd << '--prod' if prod?
443
+ option('G', 'group') { |val| cmd << basic_option('G', val) }
434
444
  else
435
445
  cmd = pip_session 'install'
436
446
  cmd << '--upgrade-strategy=eager' if env('UPDATE') || env('PYTHON_UPDATE')
@@ -447,9 +457,13 @@ module Squared
447
457
  else
448
458
  append_global
449
459
  end
450
- if exist?(DEP_PYTHON[4]) && !session_arg?('r', 'requirement')
451
- cmd << basic_option('r', DEP_PYTHON[4])
452
- cmd << basic_option('c', 'constraints.txt') if exist?('constraints.txt')
460
+ unless session_arg?('r', 'requirement')
461
+ if exist?(DEP_PYTHON[2])
462
+ cmd << basic_option('r', DEP_PYTHON[2])
463
+ elsif exist?(DEP_PYTHON[6])
464
+ cmd << basic_option('r', DEP_PYTHON[6])
465
+ cmd << basic_option('c', 'constraints.txt') if exist?('constraints.txt')
466
+ end
453
467
  end
454
468
  append_editable
455
469
  end
@@ -569,8 +583,9 @@ module Squared
569
583
  end
570
584
  if found > 0
571
585
  items = if se
572
- choice('Select a package', items.map(&:first),
573
- multiple: true, force: false, index: true, border: true).map { |n| items[n.pred].last }
586
+ choice('Select a package', items.map(&:first), multiple: true, force: false, index: true,
587
+ border: true, **parse_select)
588
+ .map { |n| items[n.pred].last }
574
589
  elsif ia
575
590
  items.map(&:last)
576
591
  else
@@ -786,7 +801,7 @@ module Squared
786
801
  ret = kwargs[:requirement] || begin
787
802
  file = op.detect { |val| op.exist?(val) }
788
803
  op.remove(file) if file
789
- basepath(file || DEP_PYTHON[4])
804
+ basepath(file || DEP_PYTHON[6])
790
805
  end
791
806
  op.add_quote(ret)
792
807
  .clear
@@ -832,7 +847,7 @@ module Squared
832
847
  end
833
848
  print_run(op, banner, **kwargs)
834
849
  run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception?), from: symjoin('pip', flag))
835
- .yield_self { |val| ret || val }
850
+ .then { |val| ret || val }
836
851
  end
837
852
 
838
853
  def serve(root, opts = [], bind: 'localhost', port: nil, **)
@@ -1039,7 +1054,15 @@ module Squared
1039
1054
  end
1040
1055
  end
1041
1056
  ret.last[1] += val
1042
- elsif line.strip =~ /^(\S+)\s*=\s*([+-]?[\d.]+|true|false|("""|'''|["'\[{])(.*))$/
1057
+ elsif line.strip =~ /^(\S+)\s*=\s*
1058
+ (
1059
+ [+-]?(?:[\d._]+(?:[eE].+)?|0x[\dA-Fa-f]+|0[ob]\d+|nan|inf)
1060
+ |true|false
1061
+ |\d{4}-\d{2}-\d{2}.*
1062
+ |\d{2}:\d{2}.*
1063
+ |("""|'''|["'\[{])(.*)
1064
+ )$/x
1065
+ name = $1
1043
1066
  if (val = $4)
1044
1067
  case (ch = $3)
1045
1068
  when '{', '['
@@ -1059,11 +1082,21 @@ module Squared
1059
1082
  true
1060
1083
  when 'false'
1061
1084
  false
1085
+ when /^\d{4}-/
1086
+ Time.parse(ch)
1087
+ when /^\d{2}:/
1088
+ Time.strptime(ch, '%T')
1089
+ when /nan$/
1090
+ Float::NAN
1091
+ when /inf$/
1092
+ Float::INFINITY * (ch[0] == '-' ? -1 : 1)
1093
+ when /^[+-]?0[xob]/
1094
+ eval ch
1062
1095
  else
1063
1096
  ch.include?('.') ? ch.to_f : ch.to_i
1064
1097
  end
1065
1098
  end
1066
- ret << [$1, val]
1099
+ ret << [name, val]
1067
1100
  end
1068
1101
  if !ch && (val = ret.last[1]).is_a?(String) && (val.match?(/\A\{.+\}\z/m) || val.match?(/\A\[.+\]\z/m))
1069
1102
  ret.last[1] = JSON.parse(val) rescue nil
@@ -1082,7 +1115,7 @@ module Squared
1082
1115
  end
1083
1116
 
1084
1117
  def pyprojectfile
1085
- @pyprojectfile = basepath!(DEP_PYTHON[2]) || false if @pyprojectfile.nil?
1118
+ @pyprojectfile = basepath!(DEP_PYTHON[4]) || false if @pyprojectfile.nil?
1086
1119
  @pyprojectfile || nil
1087
1120
  end
1088
1121
 
@@ -1139,7 +1172,7 @@ module Squared
1139
1172
  if windows?
1140
1173
  shell_quote(venvbin.join(powershell? ? 'Activate.ps1' : 'activate.bat'), option: false)
1141
1174
  else
1142
- { 'VIRTUAL_ENV' => venv.to_s, 'PATH' => "#{venvbin}:#{ENV['PATH']}" }
1175
+ { 'VIRTUAL_ENV' => venv.to_s, 'PATH' => task_join(venvbin, ENV['PATH']) }
1143
1176
  end
1144
1177
  end
1145
1178
 
@@ -1221,6 +1254,8 @@ module Squared
1221
1254
  if poetry?
1222
1255
  dir += (windows? ? 'Scripts/python.exe' : 'bin/python')
1223
1256
  cmd = poetry_session 'env use'
1257
+ elsif pdm?
1258
+ cmd = pdm_session 'use -f'
1224
1259
  else
1225
1260
  puts "Success: #{dir}"
1226
1261
  return
@@ -1264,13 +1299,17 @@ module Squared
1264
1299
  end
1265
1300
 
1266
1301
  def setuptools?
1267
- dependtype == 2 || dependtype == 4
1302
+ dependtype == 4 || dependtype == 6
1268
1303
  end
1269
1304
 
1270
1305
  def poetry?
1271
1306
  dependtype == 1
1272
1307
  end
1273
1308
 
1309
+ def pdm?
1310
+ dependtype == 2
1311
+ end
1312
+
1274
1313
  def twine?
1275
1314
  venv_package?('twine')
1276
1315
  end
@@ -1280,7 +1319,7 @@ module Squared
1280
1319
  end
1281
1320
 
1282
1321
  def requirements?
1283
- dependtype == 5
1322
+ dependtype == 7
1284
1323
  end
1285
1324
  end
1286
1325
 
@@ -236,10 +236,10 @@ module Squared
236
236
  File.foreach(rakefile) do |line|
237
237
  next unless line.match?(%r{\brequire\s+(["'])bundler/gem_tasks\1})
238
238
 
239
- cmd = bundle_output('exec rake').to_s
240
- @output[0] = "#{cmd} build"
241
- @copy = "#{cmd} install"
242
- @clean = "#{cmd} clean" if @clean.nil?
239
+ cmd = "#{bundle_output('exec rake')} %s"
240
+ @output[0] = cmd % 'build'
241
+ @copy = cmd % 'install'
242
+ @clean = cmd % 'clean' if @clean.nil?
243
243
  break
244
244
  end
245
245
  rescue => e
@@ -329,7 +329,7 @@ module Squared
329
329
  opts = args.to_a
330
330
  cmd = opts.delete('::')
331
331
  if (n = opts.index('c'))
332
- args = opts.slice!(n.succ..-1)
332
+ args = opts.slice!(n.succ..)
333
333
  else
334
334
  file = opts.shift
335
335
  args = []
@@ -459,11 +459,13 @@ module Squared
459
459
  when :build, :push, :exec, :update
460
460
  format_desc(action, flag, 'opts*', after: case flag
461
461
  when :exec then 'command,args*'
462
- when :push then 'file/:'
462
+ when :push then 'file/:,d/dry-run?'
463
463
  when :update then 'name*'
464
464
  end)
465
465
  task flag do |_, args|
466
- gem(flag, opts: args.to_a, banner: true)
466
+ opts = args.to_a
467
+ filter = { dryrun: true } if flag == :push && has_value!(opts, 'd', 'dry-run')
468
+ gem(flag, opts: opts, banner: true, filter: filter)
467
469
  end
468
470
  when :install, :uninstall, :pristine
469
471
  format_desc(action, flag, 'opts*', after: flag == :pristine ? 'name*|name?@version' : 'name*')
@@ -565,18 +567,23 @@ module Squared
565
567
  task flag do |_, args|
566
568
  args = args.to_a
567
569
  multiline = case args.first
568
- when ';', '#'
570
+ when ';', /^#+$/
569
571
  args.shift
570
572
  else
571
573
  %w[## ;]
572
574
  end
573
- msg = if Prompt.reline.respond_to?(:readmultiline)
574
- 'ruby>'
575
- else
576
- multiline = Array(multiline)
577
- 'Enter script'
578
- end
579
- command = ENV['RUBY_E'] || readline(msg, force: true, multiline: multiline)
575
+ unless (command = ENV['RUBY_E'])
576
+ command = if Prompt.reline.respond_to?(:readmultiline)
577
+ require 'ripper'
578
+ readline('ruby>', force: true, multiline: multiline) do |code|
579
+ next if code.strip.empty? || !Ripper.sexp(code)
580
+
581
+ Array(multiline).any? { |s| code.split.last.match?(/(?<!#{s[-1]})#{s}$/) }
582
+ end
583
+ else
584
+ readline('Enter script', force: true, multiline: Array(multiline))
585
+ end
586
+ end
580
587
  ruby(flag, opts: args.to_a, command: command)
581
588
  end
582
589
  when :version
@@ -699,7 +706,7 @@ module Squared
699
706
  .lines
700
707
  .map { |line| line.sub(/#.*$/, '').strip }
701
708
  .reject(&:empty?)
702
- .yield_self do |lines|
709
+ .then do |lines|
703
710
  target = lines.find { |line| line.include?(tool) }
704
711
  target ? [target] : lines
705
712
  end
@@ -786,7 +793,7 @@ module Squared
786
793
  when '1', 'true' then nil
787
794
  else
788
795
  if val.start_with?('~')
789
- val = File.join(Dir.home, val == '~' ? '.bundle' : val[1..-1])
796
+ val = File.join(Dir.home, val == '~' ? '.bundle' : val[1..])
790
797
  if prod?
791
798
  config_set('binstubs', shell_quote(val), global: true)
792
799
  val = nil
@@ -844,11 +851,11 @@ module Squared
844
851
  def outdated(flag = nil, opts = [], sync: invoked_sync?('outdated', flag))
845
852
  cmd = bundle_output 'outdated'
846
853
  if flag
847
- se = has_value!(opts, 's', 'select')
854
+ se = has_value! opts, 's', 'select'
848
855
  ia = has_value!(opts, 'i', 'interactive') && !se
849
- up = has_value!(opts, 'u', 'update')
856
+ up = has_value! opts, 'u', 'update'
850
857
  opts << 'only-explicit' if has_value!(opts, 'e', 'explicit')
851
- dryrun = has_value!(opts, 'd', 'dry-run')
858
+ dryrun = has_value! opts, 'd', 'dry-run'
852
859
  if !sync || stdin?
853
860
  se = false
854
861
  ia = false
@@ -976,8 +983,9 @@ module Squared
976
983
  if found > 0
977
984
  unless Array(items).empty?
978
985
  gems = if se
979
- choice('Select a package', items.map(&:first),
980
- multiple: true, force: false, index: true, border: true).map { |n| items[n.pred].last }
986
+ choice('Select a package', items.map(&:first), multiple: true, force: false, index: true,
987
+ border: true, **parse_select)
988
+ .map { |n| items[n.pred].last }
981
989
  else
982
990
  items.map(&:last)
983
991
  end
@@ -1211,8 +1219,9 @@ module Squared
1211
1219
  puts 'No updates were found'
1212
1220
  else
1213
1221
  if items
1214
- update = choice('Select a package', items.map(&:first),
1215
- multiple: true, force: false, index: true, border: true).map { |n| items[n.pred].last }
1222
+ update = choice('Select a package', items.map(&:first), multiple: true, force: false, index: true,
1223
+ border: true, **parse_select)
1224
+ .map { |n| items[n.pred].last }
1216
1225
  end
1217
1226
  unless Array(update).empty?
1218
1227
  opts = ['f']
@@ -1296,7 +1305,12 @@ module Squared
1296
1305
 
1297
1306
  op.add_path(file)
1298
1307
  end
1299
- return run(from: from, interactive: ['Push', 'N', target || gemname]) unless with || !banner
1308
+ if dryrun? || kwargs[:filter]&.fetch(:dryrun, nil)
1309
+ print_item "> #{op}"
1310
+ exit 0
1311
+ elsif !with && banner
1312
+ return run(from: from, interactive: ['Push', 'N', target || gemname])
1313
+ end
1300
1314
  when :exec
1301
1315
  min = if op.arg?('g', 'gem')
1302
1316
  1
@@ -1365,9 +1379,9 @@ module Squared
1365
1379
  name = op.remove_at(n)
1366
1380
  n = name.index('@')
1367
1381
  pre, ver = if n == 0
1368
- [gemname, name[1..-1]]
1382
+ [gemname, name[1..]]
1369
1383
  else
1370
- [name[0, n], name[n.succ..-1]]
1384
+ [name[0, n], name[n.succ..]]
1371
1385
  end
1372
1386
  op.adjoin(pre, quote_option('version', ver))
1373
1387
  .clear
@@ -1672,7 +1686,7 @@ module Squared
1672
1686
  def serve(root, *, bind: nil, port: 3000, **kwargs)
1673
1687
  require 'webrick'
1674
1688
  rescue LoadError => e
1675
- print_error(e, pass: true)
1689
+ print_error(e, subject: name, hint: 'webrick', pass: true)
1676
1690
  else
1677
1691
  config = kwargs.merge({ DocumentRoot: root })
1678
1692
  config[:BindAddress] = bind if bind
@@ -1826,10 +1840,7 @@ module Squared
1826
1840
  set.call(ver, val)
1827
1841
  end
1828
1842
  end
1829
- if semgte?('2.6')
1830
- target = RUBY_VERSION.start_with?('2.6') ? RubyVM : $LOAD_PATH
1831
- parse.call(target.resolve_feature_path(gemname)&.last)
1832
- end
1843
+ parse.call($LOAD_PATH.resolve_feature_path(gemname)&.last)
1833
1844
  unless gemdir || pwd_set { parse.call(`#{bundle_output('show', gemname)}`) }
1834
1845
  raise Errno::ENOENT, 'gems home'
1835
1846
  end
@@ -2057,7 +2068,7 @@ module Squared
2057
2068
  end
2058
2069
 
2059
2070
  def gemlib
2060
- @gemlib ||= Set.new(['lib']).yield_self do |lib|
2071
+ @gemlib ||= Set.new(['lib']).then do |lib|
2061
2072
  if (spec = gemspec)
2062
2073
  lib.merge(spec.require_paths || [])
2063
2074
  end
@@ -153,7 +153,7 @@ module Squared
153
153
  return true if super
154
154
  return extras.include?(obj) unless (n = extras.index(@partition))
155
155
 
156
- extras[0..n].include?(obj)
156
+ extras[..n].include?(obj)
157
157
  end
158
158
 
159
159
  def multiple?(val)
@@ -19,7 +19,6 @@ module Squared
19
19
  class << self
20
20
  include Common::Format
21
21
  include Shell
22
- include Prompt
23
22
 
24
23
  def append(target, *args, delim: false, escape: false, quote: true, strip: nil, double: false, filter: nil,
25
24
  pass: nil, **kwargs)
@@ -82,7 +81,7 @@ module Squared
82
81
  kwargs[:hint] ||= 'unrecognized'
83
82
  append(target, opts, delim: true) if kwargs.delete(:append)
84
83
  warn log_warn(opts.join(', '), pass: true, **kwargs)
85
- exit 1 unless !strict && (pass || confirm("Run? [#{sub_style(target, styles)}]", 'N'))
84
+ exit 1 unless !strict && (pass || Common::Prompt.confirm("Run? [#{sub_style(target, styles)}]", 'N'))
86
85
  end
87
86
 
88
87
  def delete_key(target, *args, value: false, reverse: false, count: -1)
@@ -104,7 +103,7 @@ module Squared
104
103
  next if s.empty? || pass == i
105
104
 
106
105
  if s == '--'
107
- ret << s << args[i.succ..-1].join(' ')
106
+ ret << s << args[i.succ..].join(' ')
108
107
  break
109
108
  end
110
109
  next ret << s unless s.start_with?('-')
@@ -139,7 +138,7 @@ module Squared
139
138
  j = val =~ OPT_VALUE ? $1 : val
140
139
  (out[j] ||= []) << i unless pass.include?(j)
141
140
  end
142
- .map { |item| item[1].size > 1 ? item[1][0..-2] : [] }
141
+ .map { |item| item[1].size > 1 ? item[1][..-2] : [] }
143
142
  .reject(&:empty?)
144
143
  return if data.empty?
145
144
 
@@ -152,12 +151,12 @@ module Squared
152
151
  val = val.strip
153
152
  return [val, nil, ''] unless (i = val.index('='))
154
153
 
155
- last = val[i.succ..-1].strip
154
+ last = val[i.succ..].strip
156
155
  if last =~ /\A(["'])(.*)\1\z/m
157
156
  last = $2
158
157
  quote = $1
159
158
  end
160
- [val[0..i.pred], last, quote || '']
159
+ [val[...i], last, quote || '']
161
160
  end
162
161
 
163
162
  def parse_arg!(name, val)
@@ -174,7 +173,7 @@ module Squared
174
173
  r << matchopts(s, value) unless s.empty?
175
174
  a = target.to_a
176
175
  if (n = a.index('--'))
177
- a = a[0..n]
176
+ a = a[..n]
178
177
  end
179
178
  r.any? { |pat| a.any?(pat) }
180
179
  end
@@ -193,6 +192,8 @@ module Squared
193
192
  false
194
193
  end
195
194
 
195
+ alias filter select
196
+
196
197
  private
197
198
 
198
199
  def matchopt(val, value = false)
@@ -224,7 +225,7 @@ module Squared
224
225
  :merge, :compact, :delete, :delete?, :delete_if, :grep, :grep_v, :inspect, :to_a, :to_s
225
226
  def_delegators :@extras, :empty?, :member?, :each, :each_with_index, :each_with_object, :partition, :dup,
226
227
  :first, :shift, :unshift, :pop, :push, :concat, :index, :join, :detect, :map, :map!, :select,
227
- :select!, :reject, :slice, :slice!, :size
228
+ :select!, :filter, :filter!, :reject, :slice, :slice!, :size
228
229
 
229
230
  def_delegator :@extras, :delete, :remove
230
231
  def_delegator :@extras, :delete_at, :remove_at
@@ -269,7 +270,7 @@ module Squared
269
270
  x, y = val.split('|', 2)
270
271
  if y
271
272
  if (n = val.index('='))
272
- x += val[n..-1]
273
+ x += val[n..]
273
274
  end
274
275
  [x, y]
275
276
  else
@@ -318,7 +319,7 @@ module Squared
318
319
  bare.concat(mod)
319
320
  when '/'
320
321
  begin
321
- val = val[n.succ..-1]
322
+ val = val[n.succ..]
322
323
  pat = eval(val)
323
324
  raise SyntaxError unless pat.is_a?(Regexp)
324
325
 
@@ -327,7 +328,7 @@ module Squared
327
328
  warn "#{self.class}: invalid pattern (#{val})"
328
329
  end
329
330
  when '{'
330
- group = val[(n + 2)..-1].chomp!('}')&.split(',')
331
+ group = val[(n + 2)..].chomp!('}')&.split(',')
331
332
  if group
332
333
  mod.each { |key| ar[key] = group }
333
334
  else
@@ -396,7 +397,7 @@ module Squared
396
397
  else
397
398
  add(opt.size == 1 ? "-#{opt}" : "--#{opt}")
398
399
  end
399
- elsif opt.start_with?(/no[-_]/) && no.include?(s = opt[3..-1])
400
+ elsif opt.start_with?(/no[-_]/) && no.include?(s = opt[3..])
400
401
  add "--no-#{s}"
401
402
  else
402
403
  has = lambda do |list, key|
@@ -408,17 +409,23 @@ module Squared
408
409
  if opt =~ OPT_VALUE
409
410
  key = $1
410
411
  val = $2
412
+ if val =~ QUOTE_VALUE
413
+ val = $2
414
+ double = $1 == '"'
415
+ end
411
416
  get = ->(h) { h[key] || h.find { |k,| k.end_with?(':*') }.last }
412
417
  kwargs = { sep: se[key] || sep, merge: has.call(m, key), switch: sw[key] }
418
+ kwargs[:double] = double unless double.nil?
413
419
  if has.call(e, key) || (has.call(bl, key) && bool.include?(val))
414
420
  add shell_option(key, val, **kwargs)
415
421
  elsif has.call(ex, key) && bool.include?(val)
416
422
  add shell_option(key, val, explicit: explicit, **kwargs)
417
423
  elsif has.call(q, key)
418
- add quote_option(key, val, double: has.call(qq, key), **kwargs)
424
+ kwargs[:double] = true if has.call(qq, key)
425
+ add quote_option(key, val, **kwargs)
419
426
  elsif has.call(p, key)
420
- if val =~ QUOTE_VALUE
421
- add shell_option(key, val, double: $1 == '"', escape: false, **kwargs)
427
+ if !double.nil?
428
+ add shell_option(key, val, escape: false, **kwargs)
422
429
  elsif path
423
430
  add quote_option(key, path + val, **kwargs)
424
431
  else
@@ -448,8 +455,8 @@ module Squared
448
455
  push opt
449
456
  end
450
457
  opt = key unless opt == last
451
- elsif has.call(m, key = opt[0]) && opt[1..-1] =~ QUOTE_VALUE
452
- add basic_option(key, $2, double: $1 == '"', **kwargs, merge: true)
458
+ elsif has.call(m, key = opt[0]) && opt[1..] =~ QUOTE_VALUE
459
+ add basic_option(key, $2, double: $1 == '"' || has.call(qq, key), **kwargs, merge: true)
453
460
  opt = key
454
461
  else
455
462
  push opt
@@ -606,7 +613,7 @@ module Squared
606
613
  else
607
614
  args.each { |val| remove val }
608
615
  end
609
- args = temp[0, index] + args + temp[index..-1]
616
+ args = temp[0, index] + args + temp[index..]
610
617
  target.clear
611
618
  end
612
619
  merge args
@@ -215,8 +215,8 @@ module Squared
215
215
  opts << '--force-checkout'
216
216
  when 'rebase', 'detach'
217
217
  opts << "--#{val}"
218
- when /^(fetch-)?submodules$/
219
- opts << '--fetch-submodules' if repo_submodules?(true, **envargs)
218
+ when /^(recurse-)?submodules$/
219
+ opts << '--recurse-submodules' if repo_submodules?(true, **envargs)
220
220
  when /^(fail-)?fast$/
221
221
  opts << '--fail-fast'
222
222
  when /^no-(manifest-)?update$/
@@ -228,7 +228,7 @@ module Squared
228
228
  if (jobs = ENV['REPO_JOBS']) || opts.none?(/^--?j(obs)?$/)
229
229
  opts << "-j#{jobs || Rake::CpuCounter.count}"
230
230
  end
231
- opts << '--fetch-submodules' if repo_submodules?(**envargs)
231
+ opts << '--recurse-submodules' if repo_submodules?(**envargs)
232
232
  begin
233
233
  repo_run('sync', opts, exception: opts.include?('--fail-fast'), options: stage != 'init')
234
234
  rescue Errno::ENOENT => e
@@ -262,7 +262,7 @@ module Squared
262
262
  return false unless root.directory?
263
263
 
264
264
  path = sub_style root, theme[:inline]
265
- @repo_override = case env('REPO_Y')
265
+ @repo_override = case __arg__('YES', 'REPO') || env('REPO_Y')
266
266
  when '0', 'false'
267
267
  false
268
268
  when '1', 'true'
@@ -281,7 +281,7 @@ module Squared
281
281
  env('REPO_OPTIONS', **kwargs) { |val| cmd << val } if options
282
282
  cmd = cmd.join(' ')
283
283
  puts log_message(cmd, subject: main, hint: root) if verbose
284
- Common::System.shell(cmd, chdir: root, exception: exception)
284
+ Common::System.shell(cmd, chdir: root, exception: exception || env('REPO_FAIL', equals: %w[1 true]))
285
285
  end
286
286
 
287
287
  def repo_bin
@@ -345,7 +345,7 @@ module Squared
345
345
  def repo_opts(*args)
346
346
  return args unless (n = ARGV.index('--'))
347
347
 
348
- ARGV[n.succ..-1].concat(args)
348
+ ARGV[n.succ..].concat(args)
349
349
  end
350
350
 
351
351
  def repo_submodules?(val = false, **kwargs)
@@ -9,6 +9,7 @@ module Squared
9
9
  extend Forwardable
10
10
 
11
11
  attr_reader :sync, :multiple, :parallel
12
+ attr_writer :ref_min
12
13
 
13
14
  def_delegators :@data, :[], :each, :each_key, :keys, :key?, :include?, :fetch, :update, :merge!, :any?, :none?,
14
15
  :delete, :delete_if, :find, :find_all, :to_a, :to_s, :inspect
@@ -19,6 +20,7 @@ module Squared
19
20
  @sync = []
20
21
  @multiple = []
21
22
  @parallel = []
23
+ @ref_min = 2
22
24
  @chain = {}
23
25
  @exclude = exclude.freeze
24
26
  @task = Struct::SeriesData.new(workspace.config_get(:rename))
@@ -56,7 +58,7 @@ module Squared
56
58
  @session = {
57
59
  group: Support.hashlist,
58
60
  parent: Support.hashlist,
59
- id: []
61
+ id: Set.new
60
62
  }.freeze
61
63
  end
62
64
 
@@ -85,7 +87,7 @@ module Squared
85
87
 
86
88
  def build(parallel: [], pattern: [], **)
87
89
  subcheck = ->(val) { (ns = task_namespace(val)) && parallel.include?(ns) }
88
- update @session[:parent] if @session[:id].uniq.size > 1
90
+ update @session[:parent] if @session[:id].size >= @ref_min
89
91
  update @session[:group]
90
92
  each do |key, items|
91
93
  next if exclude?(key, empty: true) || @workspace.task_exclude?(t = name_get(key))
data/squared.gemspec CHANGED
@@ -11,21 +11,23 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = "Rake task generator for managing multi-language workspaces."
12
12
  spec.description = "Rake task generator for managing multi-language workspaces."
13
13
  spec.homepage = "https://github.com/anpham6/squared-ruby"
14
- spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
15
15
  spec.licenses = ["BSD-3-Clause"]
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = spec.homepage
19
19
  spec.metadata["documentation_uri"] = "https://squared.readthedocs.io"
20
20
 
21
- spec.files = Dir["lib/**/*"] +
22
- %w[CHANGELOG.md LICENSE README.md squared.gemspec]
23
21
  spec.bindir = "exe"
24
- spec.executables = []
22
+ spec.executables = Dir["exe/*"].map { |f| File.basename(f) }
23
+
24
+ spec.files = Dir["exe/*"] + Dir["lib/**/*"] +
25
+ %w[CHANGELOG.md LICENSE README.md squared.gemspec]
25
26
  spec.require_paths = ["lib"]
26
27
 
27
28
  spec.add_dependency "rake"
29
+ spec.add_dependency "optparse"
28
30
  spec.add_dependency "logger"
29
31
  spec.add_dependency "rexml"
30
- spec.add_dependency "readline"
32
+ spec.add_dependency "reline"
31
33
  end