squared 0.6.5 → 0.6.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.
@@ -41,6 +41,7 @@ module Squared
41
41
  common: %w[no-color V|verbose r|retry=i].freeze,
42
42
  common_all: %w[all all-platforms path=p].freeze,
43
43
  common_git: %w[branch=q git=q path=p ref=q].freeze,
44
+ common_version: %w[local major minor patch pre strict].freeze,
44
45
  add: %w[optimistic quiet skip-install strict github=q glob=q g|group=q require=q s|source=q
45
46
  v|version=q].freeze,
46
47
  binstubs: %w[force standalone shebang=q].freeze,
@@ -48,25 +49,27 @@ module Squared
48
49
  check: %w[dry-run gemfile=p path=p].freeze,
49
50
  clean: %w[dry-run force].freeze,
50
51
  config: %w[global local].freeze,
51
- doctor: %w[quiet gemfile=p].freeze,
52
+ doctor: %w[quiet ssl gemfile=p].freeze,
53
+ doctor_ssl: %w[host=q tls-version=b verify-mode=b].freeze,
52
54
  exec: %w[gemfile=p].freeze,
53
55
  gem: %w[b|bin git no-exe rubocop ci=b e|edit=p? ext=b github-username=q linter=b t|test=b?].freeze,
54
56
  init: %w[gemfile=p gemspec=p].freeze,
55
57
  install: %w[frozen no-cache no-prune system binstubs=p? path=p standalone=q? target-rbconfig=p trust-policy=b
56
58
  with=q without=q].freeze,
57
- install_a: %w[force full-index quiet redownload gemfile=p j|jobs=i].freeze,
58
- lock: %w[add-checksums conservative full-index local major minor normalize-platforms patch pre print strict
59
- add-platform=q bundler=b? gemfile=p lockfile=p remove-platform=p update=q?].freeze,
59
+ install_a: %w[force full-index local quiet redownload gemfile=p j|jobs=i].freeze,
60
+ lock: %w[add-checksums conservative full-index normalize-platforms print add-platform=q bundler=b? gemfile=p
61
+ lockfile=p remove-platform=p update=q?].freeze,
60
62
  open: %w[path=p].freeze,
61
- outdated: %w[filter-major filter-minor filter-patch groups local parseable pre only-explicit strict
63
+ outdated: %w[filter-major filter-minor filter-patch filter-strict groups parseable porcelain only-explicit
62
64
  update-strict group=q source=q].freeze,
63
65
  platform: %w[ruby].freeze,
64
66
  plugin: %w[source=q version=q].freeze,
67
+ plugin_uninstall: %w[all].freeze,
65
68
  remove: %w[install].freeze,
66
69
  show: %w[outdated paths].freeze,
67
70
  update: %w[all conservative local major minor patch pre ruby strict bundler=b? g|group=q source=q].freeze,
68
71
  no: {
69
- gem: %w[changelog ci coc linter mit test].freeze
72
+ gem: %w[changelog ci coc exe linter mit test].freeze
70
73
  }.freeze
71
74
  }.freeze
72
75
  OPT_GEM = {
@@ -79,8 +82,8 @@ module Squared
79
82
  cert: %w[a|add=p b|build=q C|certificate=p d|days=i l|list=q A|key-algorithm=b K|private-key=p r|remove=q
80
83
  R|re-sign s|sign=p].freeze,
81
84
  check: %w[a v|version=q].freeze,
82
- cleanup: %w[n d|dry-run].freeze,
83
- contents: %w[l all s|spec-dir=p v|version=q].freeze,
85
+ cleanup: %w[D n d|dry-run].freeze,
86
+ contents: %w[l all s|spec-dir=q v|version=q].freeze,
84
87
  dependency: %w[R pipe platform=q v|version=q].freeze,
85
88
  exec: %w[conservative g|gem=b v|version=q].freeze,
86
89
  fetch: %w[clear-sources platform=q v|version=q].freeze,
@@ -89,11 +92,11 @@ module Squared
89
92
  install: %w[v|version=q].freeze,
90
93
  install_a: %w[E f w conservative default development development-all explain ignore-dependencies N|no-document
91
94
  vendor n|bindir=p build-root=p document=b? g|file=p? i|install-dir=p platform=q
92
- target-rbconfig=p? P|trust-policy=b without=b].freeze,
95
+ target-rbconfig=p? P|trust-policy=b without=q].freeze,
93
96
  list: %w[d i I].freeze,
94
97
  lock: %w[s].freeze,
95
98
  open: %w[e|editor=p v|version=q].freeze,
96
- outdated: %w[C=p platform=q].freeze,
99
+ outdated: %w[platform=q].freeze,
97
100
  owner: %w[a|add=q r|remove=q p|http-proxy=q?].freeze,
98
101
  pristine: %w[E all only-executables only-missing-extensions only-plugins n|bindir=p i|install-dir=p skip=b
99
102
  v|version=q].freeze,
@@ -113,7 +116,7 @@ module Squared
113
116
  check: %w[alien doctor dry-run gems].freeze,
114
117
  cleanup: %w[check-development user-install].freeze,
115
118
  contents: %w[lib-only prefix show-install-dir].freeze,
116
- dependency: %w[http-proxy reverse-dependencies].freeze,
119
+ dependency: %w[http-proxy prerelease reverse-dependencies].freeze,
117
120
  exec: %w[prerelease].freeze,
118
121
  fetch: %w[http-proxy prerelease suggestions].freeze,
119
122
  generate_index: %w[compact modern].freeze,
@@ -136,7 +139,7 @@ module Squared
136
139
  }.freeze
137
140
  }.freeze
138
141
  PASS_RUBY = {
139
- ruby: %w[I disable enable dump r s].freeze,
142
+ ruby: %w[e I disable enable dump r s].freeze,
140
143
  rake: %w[I libdir r require].freeze,
141
144
  irb: %w[I r].freeze,
142
145
  rbs: %w[I r repo].freeze,
@@ -161,7 +164,7 @@ module Squared
161
164
  end
162
165
 
163
166
  def bannerargs
164
- %i[dependfile gemname].freeze
167
+ %i[dependfile gemname gemdir].freeze
165
168
  end
166
169
 
167
170
  def config?(val)
@@ -182,6 +185,8 @@ module Squared
182
185
  'rubocop' => nil
183
186
  })
184
187
 
188
+ attr_reader :gemdir
189
+
185
190
  def initialize(*, autodetect: false, gemspec: nil, steep: 'Steepfile', rubocop: '.rubocop.yml', asdf: 'ruby',
186
191
  **kwargs)
187
192
  super
@@ -199,8 +204,8 @@ module Squared
199
204
  elsif gemspec
200
205
  basepath(gemspec.include?('.') ? gemspec : "#{gemspec}.gemspec")
201
206
  end
202
- @steepfile = basepath! steep
203
- @rubocopfile = basepath!(rubocop) || basepath!(Dir.home, '.rubocop.yml')
207
+ @steepfile = basepath! steep if steep
208
+ @rubocopfile = Pathname.new(rubocop).realpath rescue basepath!(Dir.home, '.rubocop.yml') if rubocop
204
209
  return unless rakefile && @output[0].nil? && @copy.nil? && !version && !@autodetect
205
210
 
206
211
  begin
@@ -218,6 +223,14 @@ module Squared
218
223
  end
219
224
  end
220
225
 
226
+ def gemdir=(val)
227
+ @gemdir = if val.is_a?(Pathname)
228
+ val
229
+ else
230
+ Pathname.new(val).realdirpath rescue nil
231
+ end
232
+ end
233
+
221
234
  def ref
222
235
  Ruby.ref
223
236
  end
@@ -305,40 +318,41 @@ module Squared
305
318
  format_desc action, key, 'sig?,path*'
306
319
  task key do |_, args|
307
320
  args = args.to_a
308
- list = []
309
- lib.each do |val|
310
- val = File.join(val, '**/*.rb') unless val.include?('*') || val.end_with?('.rb')
311
- list.concat(Dir.glob(val, base: path))
321
+ list = lib.flat_map do |val|
322
+ val = File.join(val, '**/*.rb') unless val.include?('*') || val.match?(/\.[a-z\d]+$/i)
323
+ Dir.glob(val, base: path)
312
324
  end
313
- if args.empty?
314
- files = choice_index('Select files', list, multiple: true, force: true, series: true,
325
+ files = if args.empty?
326
+ choice_index('Select files', list, multiple: true, series: true,
315
327
  accept: [accept_y('Generate?')])
316
- else
317
- files = []
318
- args.each do |val|
319
- if val.include?('*')
320
- files.concat(Dir.glob(val, base: path))
321
- elsif !(file = basepath!(val))
322
- print_error(val, hint: 'not found')
323
- elsif file.directory?
324
- files.concat(file.glob('**/*.rb'))
325
- else
326
- files << val
327
- end
328
- end
329
- list.map! { |val| basepath(val).to_s }
330
- files = files.select { |val| list.include?(basepath(val).to_s) }
331
- if files.empty?
332
- print_error('steep', 'no files matched', hint: "#{key}:check")
333
- exit 1
334
- end
335
- files.uniq!
336
- end
328
+ else
329
+ list.map! { |val| basepath(val).to_s }
330
+ [].tap do |out|
331
+ ret = []
332
+ args.each do |val|
333
+ if val.include?('*')
334
+ ret.concat(Dir.glob(val, base: path))
335
+ elsif !(file = basepath!(val))
336
+ print_error(val, hint: 'not found')
337
+ elsif file.directory?
338
+ ret.concat(file.glob('**/*.rb'))
339
+ else
340
+ ret << val
341
+ end
342
+ end
343
+ ret = ret.select { |val| list.include?(basepath(val).to_s) }
344
+ if ret.empty?
345
+ print_error('steep', 'no files matched', hint: "#{key}:check")
346
+ exit 1
347
+ end
348
+ out.replace(ret.uniq)
349
+ end
350
+ end
337
351
  sig = if (n = sig.index(args.first))
338
352
  args.shift
339
353
  sig[n]
340
354
  elsif sig.size > 1
341
- choice_index('Select a sig', sig, force: true, series: true)
355
+ choice_index('Select a sig', sig, series: true)
342
356
  else
343
357
  sig.first
344
358
  end
@@ -356,9 +370,9 @@ module Squared
356
370
 
357
371
  !val.include?('*') && !val.end_with?('/')
358
372
  end
359
- if opts.delete(':') || !args.empty?
360
- args << 'lib/' if args.empty?
361
- list = args.map { |val| val.end_with?('/') ? "#{val}**/*.rb" : val }
373
+ if opts.delete(':')
374
+ args << (Dir.exist?('lib') ? 'lib/' : '**/*.rb') if args.empty?
375
+ list = args.map! { |val| val.end_with?('/') || Dir.exist?(val) ? File.join(val, '**/*.rb') : val }
362
376
  .flat_map { |val| Dir.glob(val, base: path) }
363
377
  args = choice_index('Select files', list, multiple: true)
364
378
  end
@@ -370,7 +384,7 @@ module Squared
370
384
  flags.each do |flag|
371
385
  case action
372
386
  when 'outdated'
373
- format_desc action, flag, "#{shortname('i', 's', 'u', 'd')},opts*"
387
+ format_desc action, flag, "#{shortname('i', 's', 'u', 'd')},e/xplicit,opts*"
374
388
  task flag do |_, args|
375
389
  outdated flag, args.to_a
376
390
  end
@@ -468,7 +482,7 @@ module Squared
468
482
  else
469
483
  a, b, c = choice_index('Select a file', Dir.glob(file || '*.rb', base: path),
470
484
  values: (file ? [] : ['Options']).push('Arguments'),
471
- force: true, series: true)
485
+ series: true)
472
486
  if file
473
487
  file = a
474
488
  b
@@ -478,18 +492,18 @@ module Squared
478
492
  c
479
493
  end
480
494
  end)
481
- ruby(*args, flag: flag, opts: opts, file: file)
495
+ ruby(flag, *args, opts: opts, file: file)
482
496
  end
483
497
  when :script
484
498
  format_desc action, flag, 'opts*'
485
499
  task flag do |_, args|
486
500
  command = ENV['RUBY_E'] || readline('Enter script', force: true, multiline: %w[## ;])
487
- ruby(flag: flag, opts: args.to_a, command: command)
501
+ ruby(flag, opts: args.to_a, command: command)
488
502
  end
489
503
  when :version
490
504
  format_desc action, flag
491
505
  task flag do
492
- ruby(flag: flag)
506
+ ruby flag
493
507
  end
494
508
  end
495
509
  end
@@ -506,8 +520,27 @@ module Squared
506
520
  elsif outdated?
507
521
  workspace.rev_clear(name, sync: sync)
508
522
  cmd = bundle_session 'install'
523
+ option('binstubs') do |val|
524
+ next if val == '0' || val == 'false'
525
+
526
+ run(bundle_output('binstubs --all', case val
527
+ when '1', 'true'
528
+ nil
529
+ else
530
+ if val.start_with?('~')
531
+ val = File.join(Dir.home, val == '~' ? '.bundle' : val[1..-1])
532
+ if prod?
533
+ config_set('binstubs', shell_quote(val), global: true)
534
+ val = nil
535
+ end
536
+ else
537
+ val = basepath val
538
+ end
539
+ quote_option('path', val) if val
540
+ end), exception: false, banner: false, series: true)
541
+ end
509
542
  if prod? && !config_get('without')
510
- if RUBY_VERSION > '3'
543
+ if semgte?('3')
511
544
  config_set 'without', 'development'
512
545
  else
513
546
  cmd << '--without=development'
@@ -518,7 +551,7 @@ module Squared
518
551
  end
519
552
  end
520
553
 
521
- def copy(from: gemlib, into: @gemdir, override: false, **kwargs)
554
+ def copy(from: gemlib, into: gemdir, override: false, **kwargs)
522
555
  return if @copy == false
523
556
 
524
557
  glob = kwargs[:include]
@@ -555,6 +588,7 @@ module Squared
555
588
  se = has_value!(opts, 's', 'select')
556
589
  ia = has_value!(opts, 'i', 'interactive') && !se
557
590
  up = has_value!(opts, 'u', 'update')
591
+ opts << 'only-explicit' if has_value!(opts, 'e', 'explicit')
558
592
  dryrun = has_value!(opts, 'd', 'dry-run')
559
593
  if !sync || stdin?
560
594
  se = false
@@ -564,7 +598,7 @@ module Squared
564
598
  end
565
599
  OptionPartition.new(opts, bundleopts(:outdated), cmd << "--#{flag}", project: self)
566
600
  .clear
567
- elsif (up = option('u', 'update'))
601
+ elsif (up = option('u', 'update', prefix: 'bundle'))
568
602
  flag = case up
569
603
  when 'major', 'minor'
570
604
  up.to_sym
@@ -573,6 +607,7 @@ module Squared
573
607
  end
574
608
  items = []
575
609
  end
610
+ cmd << '--only-explicit' if option('only-explicit', prefix: 'bundle')
576
611
  dryrun ||= dryrun?(prefix: 'bundle')
577
612
  log.info cmd.to_s
578
613
  on :first, :outdated
@@ -586,12 +621,11 @@ module Squared
586
621
  col = 0
587
622
  buffer = []
588
623
  out = ->(val) { sync ? puts(val) : buffer << val }
589
- IO.popen(cmd.temp('--no-color')).each do |line|
590
- line.chomp!
624
+ IO.popen(cmd.temp('--no-color')).readlines(chomp: true).each do |line|
591
625
  if start > 0
592
626
  n = line.size
593
627
  unless stdin?
594
- line = line[0...col] if col > 0
628
+ line = line[0, col] if col > 0
595
629
  data = line.scan(SEM_VER)
596
630
  next unless (cur = data.shift) && (lat = data.shift)
597
631
 
@@ -720,6 +754,7 @@ module Squared
720
754
  end
721
755
 
722
756
  def ruby(*args, flag: nil, sync: true, banner: verbose?, with: nil, pass: PASS_RUBY[:ruby], **kwargs)
757
+ flag = args.shift if !flag && args.first.is_a?(Symbol)
723
758
  if flag == :version
724
759
  pwd_set do
725
760
  out = []
@@ -829,30 +864,36 @@ module Squared
829
864
  end
830
865
  return
831
866
  end
832
- op = OptionPartition.new(session_opts(with, args: args, kwargs: kwargs, pass: pass), OPT_RUBY[:ruby],
833
- ruby_session, project: self, args: true)
834
- if (val = kwargs[:file])
835
- op.unshift(shell_quote(basepath(val)))
836
- elsif (val = kwargs[:command])
837
- op << quote_option('e', val)
838
- end
839
- append = lambda do |file|
840
- op.concat(args)
841
- unless op.empty?
842
- op.exist?(add: true) if file
843
- op.append(delim: true, escape: false, quote: false)
867
+ opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
868
+ op = OptionPartition.new(opts, OPT_RUBY[:ruby], ruby_session, project: self, multiple: [/^-e/], args: true,
869
+ stdin: true)
870
+ if kwargs[:command]
871
+ op << quote_option('e', kwargs[:command])
872
+ elsif kwargs[:file]
873
+ if op.include?('-')
874
+ op.add_path(kwargs[:file])
875
+ else
876
+ op.unshift(basepath(kwargs[:file]))
844
877
  end
845
878
  end
846
- case flag
847
- when :file
848
- append.call(false)
849
- when :script
850
- op.clear
879
+ op.concat(args)
880
+ if op.include?('-')
881
+ op.exist?(add: true)
851
882
  else
852
- append.call(true)
853
- print_run(op, banner, **kwargs)
883
+ op.append_any { |val| OptionPartition.parse_arg!('e', val) }
884
+ if op.arg?('e')
885
+ op.clear
886
+ else
887
+ op.append(delim: true, escape: kwargs.fetch(:escape, false), quote: kwargs.fetch(:quote, false))
888
+ end
854
889
  end
855
- run_rb(sync: sync, banner: banner, from: flag.is_a?(Symbol) ? :"ruby:#{flag}" : :ruby)
890
+ from = if flag
891
+ :"ruby:#{flag}"
892
+ else
893
+ print_run(op, banner, **kwargs)
894
+ :ruby
895
+ end
896
+ run_rb(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: from)
856
897
  end
857
898
 
858
899
  def gem(flag, *args, sync: true, banner: verbose?, with: nil, pass: nil, **kwargs)
@@ -872,7 +913,8 @@ module Squared
872
913
  when :build, :cert, :generate_index, :mirror, :outdated, :push, :server, :signin, :signout, :sources, :stale
873
914
  opts.concat(args)
874
915
  end
875
- op = OptionPartition.new(opts, gemopts(flag), gem_session(flag), project: self, no: OPT_GEM[:no][flag])
916
+ op = OptionPartition.new(opts, gemopts(flag), gem_session(flag),
917
+ project: self, no: OPT_GEM[:no][flag == :update ? :install : flag])
876
918
  from = :"gem:#{flag}"
877
919
  if flag == :outdated
878
920
  op.adjoin(gempwd, start: 0) if gempwd
@@ -1085,7 +1127,7 @@ module Squared
1085
1127
  file = basepath(if !n && (spec = gemspec)
1086
1128
  "#{spec.name}-#{spec.version}.gem"
1087
1129
  else
1088
- choice_index('Select a file', Dir.glob('*.gem', base: path), force: true)
1130
+ choice_index 'Select a file', Dir.glob('*.gem', base: path)
1089
1131
  end)
1090
1132
  else
1091
1133
  file = basepath(op.shift.yield_self { |val| val.include?('.') ? val : "#{val}.gem" })
@@ -1144,7 +1186,7 @@ module Squared
1144
1186
  else
1145
1187
  [name[0, n], name[n.succ..-1]]
1146
1188
  end
1147
- op.adjoin(pre, shell_option('version', ver))
1189
+ op.adjoin(pre, basic_option('version', ver))
1148
1190
  .clear
1149
1191
  end
1150
1192
  if flag == :install
@@ -1152,7 +1194,7 @@ module Squared
1152
1194
  else
1153
1195
  op.append
1154
1196
  end
1155
- op << '--' << post if post
1197
+ op.delim << post if post
1156
1198
  when :check, :cleanup, :contents, :fetch, :list, :lock, :rdoc
1157
1199
  op.append
1158
1200
  when :dependency, :info, :search
@@ -1190,7 +1232,7 @@ module Squared
1190
1232
  end
1191
1233
  op.clear(errors: true) if gems
1192
1234
  print_run(op, banner, **kwargs)
1193
- run_rb(sync: sync, banner: banner, from: from)
1235
+ run_rb(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: from)
1194
1236
  end
1195
1237
 
1196
1238
  def bundle(flag, *args, sync: true, banner: verbose?, with: nil, pass: nil, **kwargs)
@@ -1204,13 +1246,41 @@ module Squared
1204
1246
  end
1205
1247
  end
1206
1248
  opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
1249
+ invalid = ->(a) { raise_error ArgumentError, "unrecognized args: #{a.join(', ')}", hint: flag }
1250
+ cmd = bundle_session(flag)
1207
1251
  case flag
1208
- when :cache, :check, :clean, :doctor, :init, :install, :lock, :pack, :package, :platform
1252
+ when :cache, :check, :clean, :init, :install, :lock, :pack, :package, :platform
1209
1253
  pre = true
1210
1254
  opts.concat(args)
1255
+ when :doctor
1256
+ case (pre = (val = args.shift) || opts.shift)
1257
+ when 'diagnose', 'ssl'
1258
+ cmd << pre
1259
+ else
1260
+ if val
1261
+ args << val
1262
+ elsif pre
1263
+ opts << pre
1264
+ end
1265
+ pre = true
1266
+ end
1267
+ opts.concat(args)
1268
+ when :plugin
1269
+ case (plu = args.shift || opts.shift)
1270
+ when 'install', 'uninstall', 'help', 'list'
1271
+ cmd << plu
1272
+ else
1273
+ invalid.call(plu)
1274
+ end
1211
1275
  end
1212
- op = OptionPartition.new(opts, bundleopts(flag), bundle_session(flag),
1213
- project: self, no: OPT_BUNDLE[:no][flag], args: flag == :exec)
1276
+ op = OptionPartition.new(opts, bundleopts(if pre == 'ssl'
1277
+ :doctor_ssl
1278
+ elsif plu
1279
+ plu == 'install' ? :plugin : :"plugin_#{plu}"
1280
+ else
1281
+ flag
1282
+ end),
1283
+ cmd, proect: self, no: OPT_BUNDLE[:no][flag], args: flag == :exec)
1214
1284
  op.concat(args) unless pre
1215
1285
  output = false
1216
1286
  invalid = ->(a) { raise_error ArgumentError, "unrecognized args: #{a.join(', ')}", hint: flag }
@@ -1260,16 +1330,12 @@ module Squared
1260
1330
  op.clear
1261
1331
  end
1262
1332
  when :plugin
1263
- a = op.dup
1264
- case (b = op.shift)
1333
+ case plu
1265
1334
  when 'install', 'uninstall', 'help'
1266
1335
  op.append
1267
- when 'list'
1268
- op.clear
1269
1336
  else
1270
- invalid.call(a)
1337
+ op.clear
1271
1338
  end
1272
- op.adjoin(b, with: 'plugin')
1273
1339
  when :exec
1274
1340
  if op.empty? || (op.delete(':') && op.append(quote: false))
1275
1341
  op << readline('Enter arguments', force: true)
@@ -1289,7 +1355,8 @@ module Squared
1289
1355
  op.clear
1290
1356
  end
1291
1357
  print_run(op, banner, **kwargs)
1292
- run(sync: sync, banner: banner, from: :"bundle:#{flag}").tap { |ret| success?(ret, banner, output) }
1358
+ run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: :"bundle:#{flag}")
1359
+ .tap { |ret| success?(ret, banner, output) }
1293
1360
  end
1294
1361
 
1295
1362
  def rake(*args, sync: true, banner: verbose?, with: nil, pass: PASS_RUBY[:rake], **kwargs)
@@ -1299,7 +1366,8 @@ module Squared
1299
1366
  op.concat(args)
1300
1367
  op.append(escape: true)
1301
1368
  print_run(op, banner, **kwargs)
1302
- run(op, ({ 'BANNER' => '0' } unless banner), sync: sync, banner: false, from: :rake)
1369
+ var = { 'BANNER' => '0' } unless banner
1370
+ run(op, var, sync: sync, banner: false, exception: kwargs.fetch(:exception, exception), from: :rake)
1303
1371
  end
1304
1372
 
1305
1373
  def irb(*args, banner: verbose?, with: nil, pass: PASS_RUBY[:irb], **kwargs)
@@ -1313,7 +1381,7 @@ module Squared
1313
1381
  op.concat(args)
1314
1382
  op.append(delim: true)
1315
1383
  print_run(op, banner, **kwargs)
1316
- run(banner: false, from: :irb)
1384
+ run(banner: false, exception: kwargs.fetch(:exception, exception), from: :irb)
1317
1385
  end
1318
1386
 
1319
1387
  def rbs(flag, *args, banner: verbose?, with: nil, pass: nil, **kwargs)
@@ -1331,11 +1399,11 @@ module Squared
1331
1399
  sig = args.shift
1332
1400
  y = option('y', ignore: false)
1333
1401
  i = 1
1334
- args.map { |val| basepath(val).relative_path_from(path) }.each do |file|
1402
+ args.map! { |val| basepath(val).relative_path_from(path) }.each do |file|
1335
1403
  dir = basepath sig, file.dirname
1336
1404
  dir.mkpath unless dir.exist?
1337
1405
  base = file.basename.to_s
1338
- rbs = dir.join("#{base.stripext}.rbs")
1406
+ rbs = dir + "#{base.stripext}.rbs"
1339
1407
  status = if rbs.exist?
1340
1408
  case y
1341
1409
  when '0', 'false'
@@ -1362,7 +1430,7 @@ module Squared
1362
1430
  op.clear
1363
1431
  .append(*args)
1364
1432
  print_run(op, banner, **kwargs)
1365
- run(banner: false, from: :"rbs:#{flag}")
1433
+ run(banner: false, exception: kwargs.fetch(:exception, exception), from: :"rbs:#{flag}")
1366
1434
  end
1367
1435
  end
1368
1436
 
@@ -1370,6 +1438,9 @@ module Squared
1370
1438
  opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
1371
1439
  op = OptionPartition.new(opts, OPT_RUBY[:rubocop], session('rubocop'), project: self,
1372
1440
  no: OPT_RUBY[:no][:rubocop])
1441
+ if @rubocopfile && !op.arg?('c', 'config') && !rootpath('.rubocop.yml', ascend: true).exist?
1442
+ op.add_path(@rubocopfile, option: 'c')
1443
+ end
1373
1444
  op.concat(args)
1374
1445
  op.each do |val|
1375
1446
  if basepath(val).file?
@@ -1383,13 +1454,12 @@ module Squared
1383
1454
  op.append(delim: true)
1384
1455
  .clear(errors: true)
1385
1456
  print_run(op, banner, **kwargs)
1386
- run(sync: sync, banner: banner, from: :rubocop)
1457
+ run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: :rubocop)
1387
1458
  end
1388
1459
 
1389
1460
  def gemspec
1390
- return @gemspec || nil unless @gemspec.nil?
1391
-
1392
- @gemspec = gemfile && Gem::Specification.load(gemfile.to_s) rescue false
1461
+ @gemspec = !gemfile.nil? && Gem::Specification.load(gemfile.to_s) rescue false if @gemspec.nil?
1462
+ @gemspec || nil
1393
1463
  end
1394
1464
 
1395
1465
  def gemname
@@ -1402,7 +1472,7 @@ module Squared
1402
1472
 
1403
1473
  def copy?
1404
1474
  return true if @copy.is_a?(Hash) ? copy[:into] : super
1405
- return gemdir? if @gemdir
1475
+ return gemdir? if gemdir
1406
1476
 
1407
1477
  if version
1408
1478
  begin
@@ -1418,8 +1488,8 @@ module Squared
1418
1488
  val =~ /(\d\.\d)\.[^.]+$/ && File.join(val, 'lib/ruby/gems', "#{$1}.0")
1419
1489
  end
1420
1490
  when /bundler?/
1421
- pwd_set { `bundle env` }[/^\s+Gem Home\s+(.+)$/, 1]
1422
- end.tap { |val| @gemdir = Pathname.new(val) if val }
1491
+ pwd_set { `bundle env` }[/^\s+Gem Path\s+([^#{File::PATH_SEPARATOR}]+)/, 1]
1492
+ end.tap { |val| self.gemdir = val if val }
1423
1493
  rescue StandardError => e
1424
1494
  log.debug e
1425
1495
  end
@@ -1428,11 +1498,14 @@ module Squared
1428
1498
  return false unless @autodetect
1429
1499
 
1430
1500
  set = lambda do |val, path|
1501
+ dir = Pathname.new(path.strip) + gempath
1502
+ return false unless dir.writable?
1503
+
1431
1504
  if (ver = version) && ver != val
1432
1505
  log.warn "using version #{val}".subhint("given #{ver}")
1433
1506
  end
1434
1507
  self.version = val
1435
- @gemdir = Pathname.new(path.strip) + gempath
1508
+ self.gemdir = dir
1436
1509
  end
1437
1510
  if version
1438
1511
  opt = gempwd
@@ -1447,30 +1520,30 @@ module Squared
1447
1520
  next unless out =~ /\(#{Regexp.escape(val)}[^)]*\):([^\n]+)/
1448
1521
 
1449
1522
  set.call(val, $1)
1450
- return gemdir? if @gemdir
1523
+ return gemdir? if gemdir
1451
1524
  end
1452
1525
  end
1453
- @gemdir = Pathname.new(Gem.dir) + gempath
1526
+ self.gemdir = Pathname.new(Gem.dir) + gempath
1454
1527
  else
1455
1528
  parse = lambda do |path|
1456
- next unless path
1529
+ return false unless path
1457
1530
 
1458
- lib = Regexp.new(['', 'gems', "#{gemname}-([^#{File::SEPARATOR}]+)", ''].join(File::SEPARATOR))
1459
- if (ver = path[lib, 1]) && (val = path[/\A(.+)#{gempath(ver[1])}/, 1])
1531
+ ver = path[Regexp.new(['', 'gems', "#{gemname}-([^#{File::SEPARATOR}]+)", ''].join(File::SEPARATOR)), 1]
1532
+ if ver && (val = path[/\A(.+)#{Regexp.escape(gempath(ver))}/, 1])
1460
1533
  set.call(ver, val)
1461
1534
  end
1462
1535
  end
1463
- if RUBY_VERSION >= '2.6'
1536
+ if semgte?('2.6')
1464
1537
  target = RUBY_VERSION.start_with?('2.6') ? RubyVM : $LOAD_PATH
1465
1538
  parse.call(target.resolve_feature_path(gemname)&.last)
1466
1539
  end
1467
- unless @gemdir || pwd_set { parse.call(`#{bundle_output('show', gemname)}`) }
1540
+ unless gemdir || pwd_set { parse.call(`#{bundle_output('show', gemname)}`) }
1468
1541
  raise_error Errno::ENOENT, 'gems home'
1469
1542
  end
1470
1543
  end
1471
1544
  rescue StandardError => e
1472
1545
  log.error e
1473
- @version = nil
1546
+ self.version = nil
1474
1547
  @gemdir = nil
1475
1548
  @autodetect = false
1476
1549
  else
@@ -1544,8 +1617,8 @@ module Squared
1544
1617
  end
1545
1618
  end
1546
1619
 
1547
- def config_set(key, *val)
1548
- run(bundle_output('config set', key, *val), banner: false, series: true)
1620
+ def config_set(key, *val, global: false)
1621
+ run(bundle_output('config', ('--global' if global), 'set', key, *val), banner: false, series: true)
1549
1622
  end
1550
1623
 
1551
1624
  def preopts
@@ -1557,10 +1630,11 @@ module Squared
1557
1630
  end
1558
1631
 
1559
1632
  def rakefile
1560
- return @rakefile || nil unless @rakefile.nil?
1561
-
1562
- file = Rake::Application::DEFAULT_RAKEFILES.find { |val| exist?(val) }
1563
- @rakefile = file ? basepath(file) : false
1633
+ if @rakefile.nil?
1634
+ file = Rake::Application::DEFAULT_RAKEFILES.find { |val| exist?(val) }
1635
+ @rakefile = !file.nil? && basepath(file)
1636
+ end
1637
+ @rakefile || nil
1564
1638
  end
1565
1639
 
1566
1640
  def rakepwd
@@ -1590,6 +1664,8 @@ module Squared
1590
1664
  args << :common_git
1591
1665
  when :binstubs, :cache
1592
1666
  args << :common_all
1667
+ when :lock, :outdated
1668
+ args << :common_version
1593
1669
  end
1594
1670
  OPT_BUNDLE[:common] + args.flat_map { |name| OPT_BUNDLE.fetch(name, []) }
1595
1671
  end
@@ -1621,11 +1697,12 @@ module Squared
1621
1697
  end
1622
1698
 
1623
1699
  def gemfile
1624
- return @gemfile || nil unless @gemfile.nil?
1625
-
1626
- @gemfile = [project, name].map! { |val| basepath("#{val}.gemspec") }
1627
- .concat(path.glob('*.gemspec'))
1628
- .find(&:exist?) || false
1700
+ if @gemfile.nil?
1701
+ @gemfile = [project, name].map! { |val| basepath("#{val}.gemspec") }
1702
+ .concat(path.glob('*.gemspec'))
1703
+ .find(&:exist?) || false
1704
+ end
1705
+ @gemfile || nil
1629
1706
  end
1630
1707
 
1631
1708
  def gemlib
@@ -1642,9 +1719,9 @@ module Squared
1642
1719
  end
1643
1720
 
1644
1721
  def gemdir?
1645
- return false unless @gemdir
1722
+ return false unless gemdir
1646
1723
 
1647
- @gemdir.exist? && !@gemdir.empty?
1724
+ gemdir.exist? && !gemdir.empty? && gemdir.writable?
1648
1725
  end
1649
1726
  end
1650
1727