squared 0.4.6 → 0.4.7

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.
@@ -5,7 +5,7 @@ module Squared
5
5
  module Project
6
6
  class Node < Git
7
7
  OPT_NPM = {
8
- common: %w[dry-run include-workspace-root workspaces=b? w|workspace=b].freeze,
8
+ common: %w[dry-run include-workspace-root workspaces=b? w|workspace=v].freeze,
9
9
  install: %w[prefer-dedupe package-lock-only cpu=b libc=b os=b].freeze,
10
10
  install_base: %w[ignore-scripts install-links strict-peer-deps include=b omit=b install-strategy=b].freeze,
11
11
  install_no: %w[audit bin-links fund package-lock].freeze,
@@ -242,7 +242,7 @@ module Squared
242
242
  items << @workspace.home
243
243
  @workspace.rev_clear(@workspace.find(@workspace.home).name)
244
244
  end
245
- items += as_a(also) if also
245
+ items.concat(as_a(also)) if also
246
246
  return if items.empty?
247
247
 
248
248
  on :first, :copy
@@ -280,7 +280,7 @@ module Squared
280
280
  dest = dir.path
281
281
  @workspace.rev_clear(dir.name)
282
282
  else
283
- raise_error "copy given: #{dir}"
283
+ raise_error "copy: given #{dir}"
284
284
  end
285
285
  next unless from && dest&.directory?
286
286
 
@@ -598,48 +598,48 @@ module Squared
598
598
  else
599
599
  flag
600
600
  end
601
- out = option_sanitize(opts, if yarn == 1
602
- OPT_PNPM[:install_base] + OPT_YARN.fetch(flag, []) + OPT_YARN[:common]
603
- else
604
- OPT_BERRY[flag]
605
- end).first
601
+ op = OptionPartition.new(opts, if yarn == 1
602
+ OPT_PNPM[:install_base] + OPT_YARN.fetch(flag, []) + OPT_YARN[:common]
603
+ else
604
+ OPT_BERRY[flag]
605
+ end, cmd, project: self)
606
+ op.clear
606
607
  append_loglevel
607
- option_clear out
608
608
  run(from: :"package:#{flag}")
609
609
  return
610
610
  elsif pnpm?
611
611
  cmd = session 'pnpm', flag
612
612
  list = OPT_PNPM[:install_base] + OPT_PNPM.fetch(flag, []) + OPT_PNPM[:common]
613
- list += OPT_PNPM[:install_as] unless flag == :dedupe
614
- opts = option_sanitize(opts, list, no: OPT_PNPM[:"#{flag}_no"]).first
613
+ list.concat(OPT_PNPM[:install_as]) unless flag == :dedupe
614
+ no = OPT_PNPM[:"#{flag}_no"]
615
615
  else
616
616
  cmd = session 'npm', flag
617
617
  list = OPT_NPM[:install_base] + OPT_NPM.fetch(flag, []) + OPT_NPM[:common]
618
- list += OPT_NPM[:install_as] unless flag == :dedupe
619
- opts, pat = option_sanitize(opts, list, no: OPT_NPM[:install_no])
618
+ list.concat(OPT_NPM[:install_as]) unless flag == :dedupe
619
+ no = OPT_NPM[:install_no]
620
620
  end
621
- out = []
622
- err = []
623
- opts.each do |opt|
624
- if pat && opt =~ pat
621
+ op = OptionPartition.new(opts, list, cmd, no: no, project: self)
622
+ op.each do |opt|
623
+ if opt =~ op.values
625
624
  case $1
626
625
  when 'w', 'workspace'
627
- cmd << (%r{[\\/]}.match?($2) ? quote_option($1, basepath($2)) : shell_option($1, $2))
626
+ op << ($2.match?(%r{[\\/]}) ? quote_option($1, basepath($2)) : shell_option($1, $2))
628
627
  end
629
628
  elsif opt.include?('=')
630
- err << opt
629
+ op.errors << opt
631
630
  else
632
- out << opt
631
+ op.found << opt
633
632
  end
634
633
  end
634
+ op.swap
635
635
  append_nocolor
636
636
  append_loglevel
637
637
  if flag == :dedupe
638
- option_clear out
638
+ op.clear
639
639
  else
640
- append_value(out, escape: true)
640
+ op.append(escape: true)
641
641
  end
642
- option_clear err
642
+ op.clear(errors: true)
643
643
  run(from: :"package:#{flag}")
644
644
  end
645
645
 
@@ -693,7 +693,8 @@ module Squared
693
693
  end
694
694
  rescue StandardError => e
695
695
  log.debug e
696
- raise if exception
696
+ ret = on(:error, :bump, e)
697
+ raise if exception && ret != true
697
698
  end
698
699
  end
699
700
 
@@ -702,13 +703,25 @@ module Squared
702
703
 
703
704
  cmd = session dependbin, 'pack'
704
705
  if dependtype(:yarn) > 1
705
- out = option_sanitize(opts, OPT_BERRY[:pack]).first
706
- cmd << quote_option('out', Pathname.pwd.join("#{project}-#{version}.tgz")) unless session_arg?('out')
706
+ op = OptionPartition.new(opts, OPT_BERRY[:pack], cmd, project: self)
707
+ op << quote_option('out', Pathname.pwd.join("#{project}-#{version}.tgz")) unless op.arg?('out')
707
708
  else
708
- out = option_sanitize(opts, pnpm? ? OPT_PNPM[:pack] : OPT_NPM[:pack] + OPT_NPM[:common]).first
709
- cmd << quote_option('pack-destination', Dir.pwd) unless session_arg?('pack-destination')
709
+ op = OptionPartition.new(opts, pnpm? ? OPT_PNPM[:pack] : OPT_NPM[:pack] + OPT_NPM[:common], cmd,
710
+ project: self)
711
+ unless pnpm?
712
+ op.each do |opt|
713
+ next unless opt =~ op.values
714
+
715
+ case $1
716
+ when 'w', 'workspace'
717
+ op << ($2.match?(%r{[\\/]}) ? quote_option($1, basepath($2)) : shell_option($1, $2))
718
+ op.found << opt
719
+ end
720
+ end
721
+ end
722
+ op << quote_option('pack-destination', Dir.pwd) unless op.arg?('pack-destination')
710
723
  end
711
- option_clear out
724
+ op.clear
712
725
  run(from: :pack)
713
726
  end
714
727
 
@@ -731,7 +744,7 @@ module Squared
731
744
  when Enumerable
732
745
  target.to_a.join(' ')
733
746
  else
734
- raise_error("compose given: #{target}", hint: from)
747
+ raise_error("compose: given #{target}", hint: from)
735
748
  end
736
749
  end
737
750
  end
@@ -20,7 +20,7 @@ module Squared
20
20
  install: %w[break-system-packages check-build-dependencies compile dry-run force-reinstall I|ignore-installed
21
21
  ignore-requires-python no-build-isolation no-clean no-compile no-deps no-index no-warn-conflicts
22
22
  no-warn-script-location pre prefer-binary require-hashes U|upgrade use-pep517 user abi=b
23
- config-settings=q c|constraint=p extra-index-url=q f|find-links=q global-option=q
23
+ config-settings=q c|constraint=p e|editable=v extra-index-url=q f|find-links=q global-option=q
24
24
  implementation=b i|index-url=q no-binary=q only-binary=q platform=q prefix=p progress-bar=b
25
25
  python-version=q report=p r|requirement=p root=p root-user-action=b src=p t|target=p
26
26
  upgrade-strategy=b].freeze,
@@ -120,12 +120,13 @@ module Squared
120
120
  format_desc action, flag, 'dir,opts*'
121
121
  task flag, [:dir] do |_, args|
122
122
  dir = basepath(param_guard(action, flag, args: args, key: :dir))
123
- opts = python_session('-m venv', opts: args.extras).last
124
- opts = option_sanitize(opts, OPT_PYTHON[:venv]).first
125
- append_value(dir, delim: true)
126
- option_clear(opts, pass: false)
123
+ cmd, opts = python_session('-m venv', opts: args.extras)
124
+ op = OptionPartition.new(opts, OPT_PYTHON[:venv], cmd, project: self)
125
+ op.append(dir, delim: true)
126
+ .clear(pass: false)
127
+ v = op.arg?(/^-v+$/, 'verbose')
127
128
  run(exception: true)
128
- puts(dir.directory? ? "Success: #{dir}" : 'Failed')
129
+ puts(dir.directory? ? "Success: #{dir}" : 'Failed') unless v
129
130
  end
130
131
  elsif venv
131
132
  case flag
@@ -134,7 +135,7 @@ module Squared
134
135
 
135
136
  format_desc action, flag, 'c|reate?,d|epend?'
136
137
  task flag do |_, args|
137
- FileUtils.rm_rf(venv, verbose: true)
138
+ rm_rf(venv, verbose: true)
138
139
  venv_init if has_value?(%w[c create], args.to_a)
139
140
  depend if has_value?(%w[d depend], args.to_a)
140
141
  end
@@ -341,6 +342,7 @@ module Squared
341
342
  cmd << quote_option('e', out.pop || editable || '.')
342
343
  option_clear out
343
344
  when :upgrade
345
+ raise_error('no packages listed', hint: flag) if out.empty?
344
346
  cmd << '--upgrade'
345
347
  cmd << basic_option('upgrade-strategy', strategy) if strategy
346
348
  append_value out
@@ -349,8 +351,6 @@ module Squared
349
351
  end
350
352
 
351
353
  def buildx(flag, opts = [])
352
- out = []
353
- srcdir = nil
354
354
  case flag
355
355
  when :python
356
356
  cmd, opts = python_session('-m build', opts: opts)
@@ -362,20 +362,23 @@ module Squared
362
362
  cmd, opts = hatch_session('build', opts: opts)
363
363
  list = OPT_HATCH[:build]
364
364
  end
365
- option_sanitize(opts, list, single: flag == :python ? /^(?:v+|q+|b+)$/ : /^(?:v+|q+)$/).first.each do |opt|
365
+ srcdir = nil
366
+ op = OptionPartition.new(opts, list, cmd, project: self, single: singleopt(flag))
367
+ op.each do |opt|
366
368
  if !srcdir && basepath(opt).exist? && projectpath?(opt)
367
369
  srcdir = opt
368
370
  else
369
- out << opt
371
+ op.found << opt
370
372
  end
371
373
  end
374
+ op.swap
372
375
  case flag
373
376
  when :poetry
374
377
  if srcdir
375
- if session_arg?('o', 'output')
376
- out << srcdir
378
+ if op.arg?('o', 'output')
379
+ op.extras << srcdir
377
380
  else
378
- cmd << quote_option('output', basepath(srcdir))
381
+ op << quote_option('output', basepath(srcdir))
379
382
  end
380
383
  srcdir = nil
381
384
  end
@@ -385,10 +388,10 @@ module Squared
385
388
  else
386
389
  srcdir ||= path
387
390
  end
388
- cmd << basic_option('p', project) unless ENV['HATCH_PROJECT'] || session_arg?('p', 'project')
391
+ op << basic_option('p', project) unless ENV['HATCH_PROJECT'] || op.arg?('p', 'project')
389
392
  end
390
- cmd << shell_quote(basepath(srcdir)) if srcdir
391
- option_clear out
393
+ op << shell_quote(basepath(srcdir)) if srcdir
394
+ op.clear
392
395
  run(from: :"#{flag}:build")
393
396
  end
394
397
 
@@ -404,13 +407,13 @@ module Squared
404
407
  opts = hatch_session('publish', opts: opts).last
405
408
  list = OPT_HATCH[:publish]
406
409
  end
407
- out = option_sanitize(opts, list, single: flag == :twine ? nil : /^(?:v+|q+)$/).first
408
- if out.empty?
410
+ op = OptionPartition.new(opts, list, @session, project: self, single: singleopt(flag))
411
+ if op.empty?
409
412
  dist = basepath.join('dist')
410
413
  raise_error('no source files found', hint: dist) unless dist.directory? && !dist.empty?
411
- out << "#{dist}/*" unless flag == :poetry
414
+ op.extras << "#{dist}/*" unless flag == :poetry
412
415
  end
413
- append_value out
416
+ op.append
414
417
  run(from: :"#{flag}:publish")
415
418
  end
416
419
 
@@ -419,7 +422,7 @@ module Squared
419
422
  out = append_pip(nil, opts, from: flag)
420
423
  case flag
421
424
  when :uninstall
422
- raise_error('no packages listed', subject: name, hint: 'uninstall') if out.empty?
425
+ raise_error('no packages listed', hint: 'uninstall') if out.empty?
423
426
  cmd.merge(out)
424
427
  when :freeze
425
428
  venv_init
@@ -465,10 +468,9 @@ module Squared
465
468
  def python_session(*cmd, opts: nil)
466
469
  return session('python', *preopts(quiet: false), *cmd, path: venv.nil?) unless opts
467
470
 
468
- out = []
469
- opts = option_sanitize(opts, OPT_PYTHON[:common], target: out, single: /^v+$/).first
470
- ret = session('python', *out, *cmd, path: venv.nil?)
471
- [ret, opts]
471
+ op = OptionPartition.new(opts, OPT_PYTHON[:common], project: self, single: /^v+$/)
472
+ ret = session('python', *op.to_a, *cmd, path: venv.nil?)
473
+ [ret, op.extras]
472
474
  end
473
475
 
474
476
  def poetry_session(*cmd)
@@ -482,48 +484,47 @@ module Squared
482
484
  def hatch_session(*cmd, opts: nil)
483
485
  return session('hatch', *preopts, *cmd, path: venv.nil?) unless opts
484
486
 
485
- out = []
486
- opts = option_sanitize(opts, OPT_HATCH[:common], target: out, single: /^(?:v+|q+)$/).first
487
- ret = session('hatch', *out, *cmd, path: venv.nil?)
488
- [ret, opts]
487
+ op = OptionPartition.new(opts, OPT_HATCH[:common], project: self, single: singleopt)
488
+ ret = session('hatch', *op.to_a, *cmd, path: venv.nil?)
489
+ [ret, op.extras]
489
490
  end
490
491
 
491
- def append_pip(flag, opts, from: nil)
492
+ def append_pip(flag, opts, target: @session, from: nil)
492
493
  if !from || opts.empty?
493
- append_global
494
+ append_global(target: target)
494
495
  return []
495
496
  end
496
- opts, pat = option_sanitize(opts, OPT_PIP[from] + OPT_PIP[:common], single: /^(?:v+|q+)$/)
497
- append_global
497
+ op = OptionPartition.new(opts, OPT_PIP[from] + OPT_PIP[:common], target, project: self, single: singleopt)
498
+ append_global(target: target)
498
499
  if from == :install
499
- out = []
500
500
  edit = nil
501
- opts.each do |opt|
502
- if opt =~ pat
501
+ op.each do |opt|
502
+ if opt =~ op.values
503
503
  case $1
504
504
  when 'e', 'editable'
505
- out << edit if edit && flag == :editable
505
+ op.found << edit if edit && flag == :editable
506
506
  edit = $2
507
507
  end
508
508
  elsif flag == :editable && !edit
509
509
  edit = opt
510
510
  else
511
- out << opt
511
+ op.found << opt
512
512
  end
513
513
  end
514
+ op.swap
514
515
  if edit
515
516
  edit = basepath(edit) unless %r{^[a-z]+(?:\+[a-z]+)?://}i.match?(edit)
516
517
  if flag == :editable
517
- out << edit
518
+ op.extras << edit
518
519
  else
519
520
  target << quote_option('e', edit)
520
521
  end
521
522
  end
522
523
  case flag
523
524
  when :editable, :upgrade
524
- out
525
+ op.extras
525
526
  else
526
- option_clear out
527
+ op.clear
527
528
  []
528
529
  end
529
530
  else
@@ -531,25 +532,25 @@ module Squared
531
532
  end
532
533
  end
533
534
 
534
- def append_editable
535
+ def append_editable(target: @session)
535
536
  return if requirements?
536
537
 
537
- if (val = option('editable', 'e', ignore: false))
538
- session_delete('e', 'editable')
538
+ if (val = option('editable', 'e', target: target, ignore: false))
539
+ session_delete('e', 'editable', target: target)
539
540
  case val
540
541
  when '0', 'false'
541
542
  return
542
543
  else
543
544
  val = basepath(val)
544
545
  end
545
- elsif session_arg?('e', 'editable') || !(val = editable)
546
+ elsif session_arg?('e', 'editable', target: target) || !(val = editable)
546
547
  return
547
548
  end
548
- @session << quote_option('e', val)
549
+ target << quote_option('e', val)
549
550
  end
550
551
 
551
552
  def append_global(target: @session)
552
- if (val = option('cache-dir'))
553
+ if (val = option('cache-dir', target: target))
553
554
  target << case val
554
555
  when '0', 'false'
555
556
  '--no-cache-dir'
@@ -557,11 +558,22 @@ module Squared
557
558
  quote_option('cache-dir', basepath(val))
558
559
  end
559
560
  end
560
- target << shell_option('proxy', val) if (val = option('proxy'))
561
- target << quote_option('python', basepath(val)) if (val = option('python'))
561
+ target << shell_option('proxy', val) if (val = option('proxy', target: target))
562
+ target << quote_option('python', basepath(val)) if (val = option('python', target: target))
562
563
  append_nocolor(target: target)
563
564
  end
564
565
 
566
+ def singleopt(flag = nil)
567
+ case flag
568
+ when :python
569
+ /^(?:v+|q+|b+)$/
570
+ when :twine
571
+ nil
572
+ else
573
+ /^(?:v+|q+)$/
574
+ end
575
+ end
576
+
565
577
  def preopts(quiet: true)
566
578
  ret = []
567
579
  case verbose
@@ -33,20 +33,25 @@ module Squared
33
33
  OPT_GEM = {
34
34
  common: %w[backtrace debug q|quiet no-verbose norc silent V|verbose config-file=p].freeze,
35
35
  install: %w[version=b].freeze,
36
+ install_base: %w[f b|both clear-sources conservative default development development-all E|explain
37
+ ignore-dependencies l|local N|no-document r|remote w|vendor n|bindir=p build-root=p
38
+ bulk-threshold=i document=b? g|file=p? p|http-proxy=q i|install-dir=p platform=q s|source=q
39
+ target-rbconfig=p? P|trust-policy=b without=b].freeze,
36
40
  update: %w[system=b?].freeze,
41
+ uninstall: %w[a D I x vendor n|bindir=p i|install-dir=p platform=b v|version=b].freeze,
37
42
  outdated: %w[b|both clear-sources l|local no-http-proxy r|remote B|bulk-threshold=i p|http-proxy=q?
38
43
  platform=q source=q].freeze,
39
44
  push: %w[no-http-proxy attestation=p host=q key=b otp=b p|http-proxy=q?].freeze,
40
45
  build: %w[force strict o|output=p platform=q].freeze,
41
- exec: %w[conservative prerelease no-prerelease g|gem=b version=b].freeze,
46
+ exec: %w[conservative prerelease no-prerelease g|gem=v version=b].freeze,
42
47
  pristine: %w[all env-shebang extensions no-env-shebang no-extensions only-executables only-missing-extensions
43
48
  only-plugins n|bindir=p i|install-dir=p skip=b v|version=b].freeze,
44
- shared: %w[f b|both clear-sources conservative default development development-all E|explain
45
- ignore-dependencies l|local N|no-document r|remote w|vendor n|bindir=p build-root=p
46
- bulk-threshold=i document=b? g|file=p? p|http-proxy=q i|install-dir=p platform=q s|source=q
47
- target-rbconfig=p? P|trust-policy=b without=b].freeze,
48
- shared_no: %w[env-shebang force format-executable http-proxy lock minimal-deps post-install-message
49
- prerelease suggestions user-install wrappers].freeze
49
+ no: {
50
+ install: %w[env-shebang force format-executable http-proxy lock minimal-deps post-install-message
51
+ prerelease suggestions user-install wrappers].freeze,
52
+ uninstall: %w[abort-on-dependent all check-development executables force format-executable
53
+ ignore-dependencies user-install].freeze
54
+ }.freeze
50
55
  }.freeze
51
56
  private_constant :GEMFILE, :DIR_RUBY, :OPT_RUBY, :OPT_BUNDLE, :OPT_GEM
52
57
 
@@ -72,7 +77,7 @@ module Squared
72
77
  'install' => %i[redownload local prefer-local].freeze,
73
78
  'update' => %i[patch minor major all].freeze,
74
79
  'outdated' => %i[patch minor major].freeze,
75
- 'gem' => %i[install user-install update pristine outdated push build exec].freeze,
80
+ 'gem' => %i[install uninstall update pristine outdated push build exec].freeze,
76
81
  'exec' => nil,
77
82
  'cache' => nil,
78
83
  'config' => nil,
@@ -149,7 +154,7 @@ module Squared
149
154
  end
150
155
  when 'irb'
151
156
  next unless (spec = basepath("#{project}.gemspec") || basepath("#{name}.gemspec"))
152
- next unless basepath('lib').join("#{gemname = File.basename(spec, File.extname(spec))}.rb").exist?
157
+ next unless basepath('lib').join("#{gemname = stripext(spec)}.rb").exist?
153
158
 
154
159
  format_desc action, nil, 'opts*,args*'
155
160
  task action do |_, args|
@@ -378,41 +383,41 @@ module Squared
378
383
  cmd << gempwd << 'outdated'
379
384
  when :push
380
385
  cmd << 'push' << project
381
- when :'user-install'
382
- cmd << 'install' << '--user-install'
383
386
  else
384
387
  cmd << flag
385
388
  end
386
- list = OPT_GEM[flag == :'user-install' ? :install : flag] + OPT_GEM[:common]
389
+ list = OPT_GEM[flag] + OPT_GEM[:common]
390
+ from = :"gem:#{flag}"
387
391
  case flag
388
- when :install, :'user-install', :update
389
- list += OPT_GEM[:shared]
390
- no = OPT_GEM[:shared_no]
392
+ when :install, :update
393
+ list.concat(OPT_GEM[:install_base])
394
+ no = OPT_GEM[:no][:install]
395
+ first = true
396
+ when :uninstall
397
+ no = OPT_GEM[:no][:uninstall]
391
398
  first = true
392
399
  when :pristine
393
400
  first = true
394
401
  end
395
402
  cmd.merge(preopts)
396
- opts, pat = option_sanitize(opts, list, no: no, first: first)
397
- out = []
398
- err = []
399
- opts.each do |opt|
400
- if opt =~ pat
403
+ op = OptionPartition.new(opts, list, cmd, project: self, no: no, first: first)
404
+ op.each do |opt|
405
+ if opt =~ op.values
401
406
  case $1
402
407
  when 'g', 'gem'
403
- cmd << (flag == :exec ? shell_option($1, $2) : quote_option($1, basepath($2)))
408
+ op << (flag == :exec ? shell_option($1, $2) : quote_option($1, basepath($2)))
404
409
  end
405
- elsif opt.match?(/^\w+=/) && !%i[outdated build push exec].include?(flag)
406
- err << opt
410
+ elsif opt.include?('=') && !%i[outdated build push exec].include?(flag)
411
+ op.errors << opt
407
412
  else
408
- out << opt
413
+ op.found << opt
409
414
  end
410
415
  end
411
- from = :"gem:#{flag == :'user-install' ? 'install' : flag}"
416
+ op.swap
412
417
  case flag
413
418
  when :outdated
414
419
  log.info cmd.to_s
415
- option_clear out
420
+ op.clear
416
421
  on :first, from
417
422
  print_item format_banner(cmd.to_s)
418
423
  pwd_set(pass: !pwd.nil?, from: from) do
@@ -489,39 +494,39 @@ module Squared
489
494
  on :last, from
490
495
  return
491
496
  when :build, :push
492
- if !out.empty?
493
- if flag == :build && out.size == 1
494
- cmd << shell_quote(basepath(out.first))
497
+ if !op.empty?
498
+ if flag == :build && op.size == 1
499
+ op << shell_quote(basepath(op.first))
495
500
  else
496
- raise_error("unknown args: #{out.join(', ')}", hint: flag)
501
+ raise_error("unknown args: #{op.join(', ')}", hint: flag)
497
502
  end
498
503
  elsif flag == :build
499
- cmd << "#{project}.gemspec"
504
+ spec = [basepath("#{project}.gemspec"), basepath("#{name}.gemspec"), *Dir.glob(basepath('*.gemspec'))]
505
+ op << File.basename(spec) if (spec = spec.find { |val| File.exist?(val) })
500
506
  end
501
507
  when :exec
502
- raise_error('no command given', hint: flag) if out.empty?
503
- cmd << project << out.join(' ')
508
+ raise_error('missing command', hint: flag) if op.empty?
509
+ op << project << op.join(' ')
504
510
  else
505
- raise_error('no gemname given', hint: flag) if out.empty? && !session_arg?('system')
511
+ raise_error('missing gemname', hint: flag) if op.empty? && !op.arg?('system')
506
512
  if flag == :pristine
507
- if session_arg?('all')
508
- append_repeat 'skip', out
509
- out.clear
510
- elsif (n = out.first.index('@'))
511
- name = out.first
513
+ if op.arg?('all')
514
+ append_repeat 'skip', op.extras
515
+ op.clear
516
+ elsif (n = op.first.index('@'))
517
+ name = op.shift
512
518
  if n == 0
513
- cmd << project
519
+ op << project
514
520
  ver = name[1..-1]
515
521
  else
516
- cmd << shell_escape(name[0, n])
522
+ op << shell_escape(name[0, n])
517
523
  ver = name[n + 1..-1]
518
524
  end
519
- cmd << shell_option('version', ver)
520
- out.clear
525
+ op << shell_option('version', ver)
526
+ op.clear
521
527
  end
522
528
  end
523
- append_value(out, escape: true)
524
- option_clear err
529
+ op.append.clear(errors: true)
525
530
  end
526
531
  run_rb(from: from)
527
532
  end
@@ -530,7 +535,8 @@ module Squared
530
535
  cmd = bundle_session flag
531
536
  args = case flag
532
537
  when 'exec', 'cache', 'check'
533
- option_sanitize(args, OPT_BUNDLE[flag.to_sym] + OPT_BUNDLE[:common], args: flag == :exec).first
538
+ list = OPT_BUNDLE[flag.to_sym] + OPT_BUNDLE[:common]
539
+ OptionPartition.new(args, list, cmd, project: self, args: flag == :exec).extras
534
540
  else
535
541
  args.flatten
536
542
  end
@@ -545,24 +551,23 @@ module Squared
545
551
  end
546
552
 
547
553
  def rake(*args, opts: [])
548
- target = [quote_option('f', rakefile)]
549
- args += option_sanitize(opts, OPT_RUBY[:rake], target: target).first
554
+ op = OptionPartition.new(opts, OPT_RUBY[:rake], [quote_option('f', rakefile)], project: self)
555
+ args.concat(op.extras)
550
556
  if args.empty?
551
557
  args << nil
552
558
  else
553
559
  args.flatten!
554
560
  end
555
- cmd = rake_output(*target)
561
+ cmd = rake_output(*op.to_a)
556
562
  args.map! { |val| cmd.temp(val) }
557
563
  run_s(args, banner: false, from: :rake)
558
564
  end
559
565
 
560
566
  def irb(name, opts = [], path: basepath('lib'))
561
- cmd = session 'irb'
562
- args = option_sanitize(opts, OPT_RUBY[:irb], first: true).first
563
- as_a(name).each { |val| cmd << shell_option('r', val) }
564
- as_a(path).each { |val| cmd << quote_option('I', val) }
565
- cmd.merge(args)
567
+ op = OptionPartition.new(opts, OPT_RUBY[:irb], session('irb'), project: self, first: true)
568
+ as_a(name).each { |val| op << shell_option('r', val) }
569
+ as_a(path).each { |val| op << quote_option('I', val) }
570
+ op.merge(op.extras)
566
571
  run(banner: false)
567
572
  end
568
573
 
@@ -637,15 +642,21 @@ module Squared
637
642
  end
638
643
 
639
644
  def append_bundle(opts, list, target: @session, append: nil)
640
- out = option_sanitize(opts, list, target: target).first
645
+ op = OptionPartition.new(opts, list, target, project: self)
641
646
  if append
642
647
  if append.is_a?(Regexp)
643
- out, err = out.partition { |val| !val.match?(append) }
644
- option_clear(err, target: target)
648
+ op.each do |opt|
649
+ if opt.match?(append)
650
+ op.errors << opt
651
+ else
652
+ op.found << opt
653
+ end
654
+ end
655
+ op.swap.clear(errors: true)
645
656
  end
646
- append_value(out, target: target, escape: true)
657
+ op.append(escape: true)
647
658
  else
648
- option_clear(out, target: target)
659
+ op.clear
649
660
  end
650
661
  end
651
662
 
@@ -696,7 +707,7 @@ module Squared
696
707
  end
697
708
 
698
709
  def preopts
699
- verbosity > 0 && !session_arg?('quiet') ? ['--verbose'] : []
710
+ verbosetype > 1 && !session_arg?('quiet') ? ['--verbose'] : []
700
711
  end
701
712
 
702
713
  def gemdir?