squared 0.4.5 → 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.
@@ -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,
@@ -99,7 +104,7 @@ module Squared
99
104
  File.foreach(file) do |line|
100
105
  next unless line.match?(%r{\brequire\s+(["'])bundler/gem_tasks\1})
101
106
 
102
- cmd = bundle_output('exec', 'rake').to_s
107
+ cmd = bundle_output('exec rake').to_s
103
108
  @output[0] = "#{cmd} build"
104
109
  @copy = "#{cmd} install"
105
110
  @clean = "#{cmd} clean" if @clean.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|
@@ -201,7 +206,7 @@ module Squared
201
206
  if @depend
202
207
  super
203
208
  elsif outdated?
204
- workspace.rev_clear name
209
+ workspace.rev_clear(name)
205
210
  cmd = bundle_session 'install'
206
211
  if (n = option('jobs')).to_i > 0
207
212
  cmd << "-j#{n}"
@@ -375,46 +380,44 @@ module Squared
375
380
  cmd = gem_session
376
381
  case flag
377
382
  when :outdated
378
- if (pwd = gempwd)
379
- cmd << pwd
380
- end
381
- cmd << 'outdated'
383
+ cmd << gempwd << 'outdated'
382
384
  when :push
383
385
  cmd << 'push' << project
384
- when :'user-install'
385
- cmd << 'install' << '--user-install'
386
386
  else
387
387
  cmd << flag
388
388
  end
389
- list = OPT_GEM[flag == :'user-install' ? :install : flag] + OPT_GEM[:common]
389
+ list = OPT_GEM[flag] + OPT_GEM[:common]
390
+ from = :"gem:#{flag}"
390
391
  case flag
391
- when :install, :'user-install', :update
392
- list += OPT_GEM[:shared]
393
- 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]
394
398
  first = true
395
399
  when :pristine
396
400
  first = true
397
401
  end
398
- opts, pat = option_sanitize(opts, list, no: no, first: first)
399
- out = []
400
- err = []
401
- opts.each do |opt|
402
- if opt =~ pat
402
+ cmd.merge(preopts)
403
+ op = OptionPartition.new(opts, list, cmd, project: self, no: no, first: first)
404
+ op.each do |opt|
405
+ if opt =~ op.values
403
406
  case $1
404
407
  when 'g', 'gem'
405
- 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)))
406
409
  end
407
- elsif opt.match?(/^\w+=/) && !%i[outdated build push exec].include?(flag)
408
- err << opt
410
+ elsif opt.include?('=') && !%i[outdated build push exec].include?(flag)
411
+ op.errors << opt
409
412
  else
410
- out << opt
413
+ op.found << opt
411
414
  end
412
415
  end
413
- from = :"gem:#{flag == :'user-install' ? 'install' : flag}"
416
+ op.swap
414
417
  case flag
415
418
  when :outdated
416
419
  log.info cmd.to_s
417
- option_clear out
420
+ op.clear
418
421
  on :first, from
419
422
  print_item format_banner(cmd.to_s)
420
423
  pwd_set(pass: !pwd.nil?, from: from) do
@@ -491,39 +494,39 @@ module Squared
491
494
  on :last, from
492
495
  return
493
496
  when :build, :push
494
- if !out.empty?
495
- if flag == :build && out.size == 1
496
- cmd << shell_quote(basepath(out.first))
497
+ if !op.empty?
498
+ if flag == :build && op.size == 1
499
+ op << shell_quote(basepath(op.first))
497
500
  else
498
- raise_error("unknown args: #{out.join(', ')}", hint: flag)
501
+ raise_error("unknown args: #{op.join(', ')}", hint: flag)
499
502
  end
500
503
  elsif flag == :build
501
- 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) })
502
506
  end
503
507
  when :exec
504
- raise_error('no command given', hint: flag) if out.empty?
505
- cmd << project << out.join(' ')
508
+ raise_error('missing command', hint: flag) if op.empty?
509
+ op << project << op.join(' ')
506
510
  else
507
- 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')
508
512
  if flag == :pristine
509
- if session_arg?('all')
510
- append_repeat 'skip', out
511
- out.clear
512
- elsif (n = out.first.index('@'))
513
- 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
514
518
  if n == 0
515
- cmd << project
519
+ op << project
516
520
  ver = name[1..-1]
517
521
  else
518
- cmd << shell_escape(name[0, n])
522
+ op << shell_escape(name[0, n])
519
523
  ver = name[n + 1..-1]
520
524
  end
521
- cmd << shell_option('version', ver)
522
- out.clear
525
+ op << shell_option('version', ver)
526
+ op.clear
523
527
  end
524
528
  end
525
- append_value(out, escape: true)
526
- option_clear err
529
+ op.append.clear(errors: true)
527
530
  end
528
531
  run_rb(from: from)
529
532
  end
@@ -532,13 +535,14 @@ module Squared
532
535
  cmd = bundle_session flag
533
536
  args = case flag
534
537
  when 'exec', 'cache', 'check'
535
- 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
536
540
  else
537
541
  args.flatten
538
542
  end
539
543
  case flag
540
544
  when 'exec', 'config'
541
- raise_error('no command given', hint: flag) if args.empty?
545
+ raise_error('no command args', hint: flag) if args.empty?
542
546
  cmd.merge(args)
543
547
  else
544
548
  option_clear args
@@ -547,24 +551,23 @@ module Squared
547
551
  end
548
552
 
549
553
  def rake(*args, opts: [])
550
- target = [quote_option('f', rakefile)]
551
- 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)
552
556
  if args.empty?
553
557
  args << nil
554
558
  else
555
559
  args.flatten!
556
560
  end
557
- cmd = rake_output(*target)
561
+ cmd = rake_output(*op.to_a)
558
562
  args.map! { |val| cmd.temp(val) }
559
563
  run_s(args, banner: false, from: :rake)
560
564
  end
561
565
 
562
566
  def irb(name, opts = [], path: basepath('lib'))
563
- cmd = session 'irb'
564
- args = option_sanitize(opts, OPT_RUBY[:irb], first: true).first
565
- as_a(name).each { |val| cmd << shell_option('r', val) }
566
- as_a(path).each { |val| cmd << quote_option('I', val) }
567
- 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)
568
571
  run(banner: false)
569
572
  end
570
573
 
@@ -590,7 +593,7 @@ module Squared
590
593
  if @version
591
594
  pwd = gempwd
592
595
  pwd_set(pass: !pwd.nil?) do
593
- out = `#{gem_output(pwd, 'list', '--local', '-d', project)}`
596
+ out = `#{gem_output(pwd, 'list --local -d', project)}`
594
597
  if out =~ /#{Regexp.escape(project)} \(([^)]+)\)/
595
598
  ver = $1.split(/\s*,\s*/)
596
599
  ver.unshift(@version).uniq!
@@ -639,32 +642,41 @@ module Squared
639
642
  end
640
643
 
641
644
  def append_bundle(opts, list, target: @session, append: nil)
642
- out = option_sanitize(opts, list, target: target).first
645
+ op = OptionPartition.new(opts, list, target, project: self)
643
646
  if append
644
647
  if append.is_a?(Regexp)
645
- out, err = out.partition { |val| !val.match?(append) }
646
- 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)
647
656
  end
648
- append_value(out, target: target, escape: true)
657
+ op.append(escape: true)
649
658
  else
650
- option_clear(out, target: target)
659
+ op.clear
651
660
  end
652
661
  end
653
662
 
654
663
  def gem_session(*cmd, **kwargs)
655
664
  ret = session('gem', *cmd, **kwargs)
656
- ret << '--no-verbose' unless verbose
657
- ret
665
+ return ret if cmd.empty?
666
+
667
+ ret.merge(preopts)
658
668
  end
659
669
 
660
670
  def bundle_session(*cmd, **kwargs)
661
671
  ret = session('bundle', *cmd, **kwargs)
672
+ return ret if cmd.empty?
673
+
662
674
  append_nocolor
663
- ret
675
+ ret.merge(preopts)
664
676
  end
665
677
 
666
678
  def rake_session(*cmd, **kwargs)
667
- session('rake', *cmd, **kwargs)
679
+ session('rake', *preopts, *cmd, **kwargs)
668
680
  end
669
681
 
670
682
  def gem_output(*cmd, **kwargs)
@@ -694,6 +706,10 @@ module Squared
694
706
  @rakelist = ret
695
707
  end
696
708
 
709
+ def preopts
710
+ verbosetype > 1 && !session_arg?('quiet') ? ['--verbose'] : []
711
+ end
712
+
697
713
  def gemdir?
698
714
  @gemdir.exist? && !@gemdir.empty?
699
715
  end
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Squared
6
+ module Workspace
7
+ module Project
8
+ module Support
9
+ class OptionPartition
10
+ include Common::Shell
11
+ extend Forwardable
12
+
13
+ class << self
14
+ include Common::Format
15
+ include Shell
16
+ include Prompt
17
+
18
+ def append(target, *args, delim: false, escape: false, quote: true)
19
+ return if args.empty?
20
+
21
+ target << '--' if delim && !target.include?('--')
22
+ ret = args.flatten.map { |val| escape ? shell_escape(val, quote: quote) : shell_quote(val) }
23
+ if target.is_a?(Set)
24
+ target.merge(ret)
25
+ else
26
+ target.concat(ret)
27
+ end
28
+ ret
29
+ end
30
+
31
+ def clear(target, opts, pass: true, styles: nil, **kwargs)
32
+ return if opts.empty?
33
+
34
+ kwargs[:subject] ||= stripext(target.first)
35
+ kwargs[:hint] ||= 'unrecognized'
36
+ append(target, opts, delim: true) if kwargs.delete(:append)
37
+ warn log_message(Logger::WARN, opts.join(', '), pass: true, **kwargs)
38
+ return if pass || confirm("Run? [#{sub_style(target, styles: styles)}] [y/N] ", 'N', timeout: 30)
39
+
40
+ raise_error 'user cancelled'
41
+ end
42
+
43
+ def arg?(target, *args, value: false)
44
+ r, s = args.partition { |val| val.is_a?(Regexp) }
45
+ unless s.empty?
46
+ s.map! { |val| Regexp.escape(shell_option(val)) }
47
+ r << /\A(?:#{s.join('|')})#{value ? '[ =].' : '(?: |=|\z)'}/
48
+ end
49
+ target.any? { |opt| r.any? { |val| opt.match?(val) } }
50
+ end
51
+ end
52
+
53
+ attr_reader :target, :extras, :found, :errors, :values, :project, :path
54
+
55
+ def_delegators :@target, :+, :-, :<<, :any?, :none?, :include?, :add, :add?, :find, :find_all, :find_index,
56
+ :merge, :delete, :delete?, :grep, :inspect, :to_a, :to_s
57
+ def_delegators :@extras, :empty?, :each, :each_with_index, :partition, :first, :last, :shift, :pop, :push,
58
+ :join, :map, :map!, :dup, :size
59
+
60
+ def initialize(opts, list, target = Set.new, project: nil, path: nil, **kwargs, &blk)
61
+ @target = target.is_a?(Set) ? target : Set.new(target)
62
+ @project = project
63
+ @path = path || project&.path
64
+ @errors = []
65
+ @found = []
66
+ parse(list, opts, **kwargs, &blk)
67
+ end
68
+
69
+ def parse(list, opts = extras, no: nil, single: nil, args: false, first: false, pass: ['='], &blk)
70
+ @extras = []
71
+ @values = []
72
+ bare = []
73
+ e = []
74
+ b = []
75
+ m = []
76
+ p = []
77
+ q = []
78
+ qq = []
79
+ i = []
80
+ f = []
81
+ si = []
82
+ list.map do |val|
83
+ x, y = val.split('|')
84
+ if y
85
+ if (n = val.index('='))
86
+ x += val[n..-1]
87
+ end
88
+ [x, y]
89
+ else
90
+ x
91
+ end
92
+ end
93
+ .flatten
94
+ .each do |val|
95
+ if (n = val.index('='))
96
+ flag = val[0, n]
97
+ case val[n + 1]
98
+ when 'e'
99
+ e << flag
100
+ when 'b'
101
+ b << flag
102
+ when 'm'
103
+ m << flag
104
+ when 'q'
105
+ qq << flag if val[n + 2] == 'q'
106
+ q << flag
107
+ when 'p'
108
+ p << flag
109
+ when 'i'
110
+ i << flag
111
+ when 'f'
112
+ f << flag
113
+ when 'n'
114
+ si << flag
115
+ when 'v'
116
+ @values << Regexp.escape(flag)
117
+ else
118
+ next
119
+ end
120
+ bare << flag if val.end_with?('?')
121
+ else
122
+ bare << val
123
+ end
124
+ end
125
+ no = (no || []).map { |val| (n = val.index('=')) ? val[0, n] : val }
126
+ bare.concat(no)
127
+ skip = false
128
+ opts.each do |opt|
129
+ next @extras << opt if skip
130
+
131
+ if single&.match?(opt)
132
+ target << "-#{opt}"
133
+ elsif bare.include?(opt)
134
+ target << (opt.size == 1 ? "-#{opt}" : "--#{opt}")
135
+ elsif opt.start_with?('no-') && no.include?(name = opt[3..-1])
136
+ target << "--no-#{name}"
137
+ else
138
+ if opt =~ /\A([^=]+)=(.+)\z/
139
+ key = $1
140
+ val = $2
141
+ match = ->(flag, pat) { flag.include?(key) && pat.match?(val) }
142
+ if e.include?(key)
143
+ target << shell_option(key, val)
144
+ elsif q.include?(key)
145
+ target << quote_option(key, val, double: qq.include?(key))
146
+ elsif p.include?(key) && path
147
+ target << quote_option(key, path.join(val))
148
+ elsif m.include?(key)
149
+ target << basic_option(key, val, merge: true)
150
+ elsif b.include?(key) || match.(i, /^\d+$/) || match.(f, /^\d*(?:\.\d+)?$/) || match.(si, /^-?\d+$/)
151
+ target << basic_option(key, val)
152
+ else
153
+ @extras << opt
154
+ end
155
+ opt = key
156
+ else
157
+ @extras << opt
158
+ skip = true if args
159
+ end
160
+ skip = true if first && pass.none? { |s| opt.include?(s) }
161
+ end
162
+ end
163
+ @values = @values.empty? ? /\A\s+\z/ : /\A(#{@values.join('|')})=(.+)\z/
164
+ @extras.each_with_index(&blk) if block_given?
165
+ self
166
+ end
167
+
168
+ def swap(opts = nil)
169
+ unless opts
170
+ opts = found
171
+ @found = []
172
+ end
173
+ @extras = opts
174
+ self
175
+ end
176
+
177
+ def append(*args, **kwargs)
178
+ OptionPartition.append(target, *(args.empty? ? extras : args), **kwargs)
179
+ self
180
+ end
181
+
182
+ def clear(opts = nil, **kwargs)
183
+ opts ||= (kwargs[:errors] ? errors : extras)
184
+ styles = project.theme[:inline] if project
185
+ OptionPartition.clear(target, opts.reject { |val| found.include?(val) }, styles: styles, **kwargs)
186
+ opts.clear
187
+ self
188
+ end
189
+
190
+ def arg?(*args, **kwargs)
191
+ OptionPartition.arg?(target, *args, **kwargs)
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'support/class'
@@ -22,5 +22,6 @@ module Squared
22
22
  end
23
23
  end
24
24
 
25
+ require_relative 'project/support'
25
26
  require_relative 'project/base'
26
27
  require_relative 'project/git'
@@ -135,7 +135,7 @@ module Squared
135
135
  task_desc(val, name: key)
136
136
  task key => items
137
137
  end
138
- @multiple += sync
138
+ @multiple.concat(sync)
139
139
  end
140
140
 
141
141
  def name_get(key)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
@@ -97,6 +97,8 @@ files:
97
97
  - lib/squared/workspace/project/node.rb
98
98
  - lib/squared/workspace/project/python.rb
99
99
  - lib/squared/workspace/project/ruby.rb
100
+ - lib/squared/workspace/project/support.rb
101
+ - lib/squared/workspace/project/support/class.rb
100
102
  - lib/squared/workspace/repo.rb
101
103
  - lib/squared/workspace/series.rb
102
104
  - squared.gemspec
@@ -121,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
123
  - !ruby/object:Gem::Version
122
124
  version: '0'
123
125
  requirements: []
124
- rubygems_version: 3.6.7
126
+ rubygems_version: 3.6.8
125
127
  specification_version: 4
126
128
  summary: Rake task generator for managing multi-language workspaces.
127
129
  test_files: []