squared 0.6.4 → 0.6.6

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.
@@ -21,7 +21,21 @@ module Squared
21
21
  nomultiline noprompt noscript nosingleline noverbose regexp-completor sample-book-mode script
22
22
  simple-prompt single-irb singleline tracer truncate-echo-on-assignment type-completor verbose
23
23
  back-trace-limit=i context-mode=i prompt=b prompt-mode=b].freeze,
24
- rbs: %w[I=pm r=bm no-stdlib no-collection collection=p log-level=b log-output=p repo=p].freeze
24
+ rbs: %w[I=pm r=bm no-stdlib no-collection collection=p log-level=b log-output=p repo=p].freeze,
25
+ rubocop: %w[D P r=bm auto-gen-config a|autocorrect A|autocorrect-all d|debug disable-pending-cops
26
+ display-only-correctable display-only-fail-level-offenses display-only-failed
27
+ display-only-safe-correctable S|display-style-guide display-time editor-mode enable-pending-cops
28
+ E|extra-details F|fail-fast force-default-config force-exclusion x|fix-layout
29
+ ignore-disable-comments ignore-parent-exclusion ignore-unrecognized-cops init l|lint
30
+ L|list-target-files lsp memory no-detach only-guide-cops only-recognized-file-types
31
+ no-exclude-limit profile raise-cop-error regenerate-todo restart-server safe server-status
32
+ start-server stderr stop-server C|cache=b cache-root=p config=p exclude-limit=i fail-level=b
33
+ f|format=b except=q only=q o|out=p plugin=p require=p show-cops=q show-docs-url=q
34
+ s|stdin=p].freeze,
35
+ no: {
36
+ rubocop: %w[auto-gen-enforced-style auto-gen-only-exclude auto-gen-timestamp color display-cop-names
37
+ offense-counts parallel server].freeze
38
+ }
25
39
  }.freeze
26
40
  OPT_BUNDLE = {
27
41
  common: %w[no-color V|verbose r|retry=i].freeze,
@@ -122,10 +136,11 @@ module Squared
122
136
  }.freeze
123
137
  }.freeze
124
138
  PASS_RUBY = {
125
- ruby: %w[I disable enable dump r s].freeze,
139
+ ruby: %w[e I disable enable dump r s].freeze,
126
140
  rake: %w[I libdir r require].freeze,
127
141
  irb: %w[I r].freeze,
128
142
  rbs: %w[I r repo].freeze,
143
+ rubocop: %w[format plugin r require].freeze,
129
144
  gem: {
130
145
  contents: %w[s spec-dir].freeze,
131
146
  dependency: %w[s source].freeze,
@@ -146,7 +161,7 @@ module Squared
146
161
  end
147
162
 
148
163
  def bannerargs
149
- %i[dependfile gemname].freeze
164
+ %i[dependfile gemname gemdir].freeze
150
165
  end
151
166
 
152
167
  def config?(val)
@@ -161,12 +176,16 @@ module Squared
161
176
  'ruby' => %i[file script version].freeze,
162
177
  'gem' => %i[install uninstall outdated update pristine build push exec command].freeze,
163
178
  'bundle' => %i[install update cache exec config reinstall command].freeze,
164
- 'rbs' => nil,
165
179
  'rake' => nil,
166
- 'irb' => nil
180
+ 'irb' => nil,
181
+ 'rbs' => nil,
182
+ 'rubocop' => nil
167
183
  })
168
184
 
169
- def initialize(*, autodetect: false, gemspec: nil, steep: 'Steepfile', asdf: 'ruby', **kwargs)
185
+ attr_reader :gemdir
186
+
187
+ def initialize(*, autodetect: false, gemspec: nil, steep: 'Steepfile', rubocop: '.rubocop.yml', asdf: 'ruby',
188
+ **kwargs)
170
189
  super
171
190
  if @pass.include?(Ruby.ref)
172
191
  initialize_ref Ruby.ref
@@ -182,7 +201,8 @@ module Squared
182
201
  elsif gemspec
183
202
  basepath(gemspec.include?('.') ? gemspec : "#{gemspec}.gemspec")
184
203
  end
185
- @steepfile = basepath(steep).yield_self { |file| file if file.exist? }
204
+ @steepfile = basepath! steep if steep
205
+ @rubocopfile = Pathname.new(rubocop).realpath rescue basepath!(Dir.home, '.rubocop.yml') if rubocop
186
206
  return unless rakefile && @output[0].nil? && @copy.nil? && !version && !@autodetect
187
207
 
188
208
  begin
@@ -200,6 +220,14 @@ module Squared
200
220
  end
201
221
  end
202
222
 
223
+ def gemdir=(val)
224
+ @gemdir = if val.is_a?(Pathname)
225
+ val
226
+ else
227
+ Pathname.new(val).realdirpath rescue nil
228
+ end
229
+ end
230
+
203
231
  def ref
204
232
  Ruby.ref
205
233
  end
@@ -287,40 +315,41 @@ module Squared
287
315
  format_desc action, key, 'sig?,path*'
288
316
  task key do |_, args|
289
317
  args = args.to_a
290
- list = []
291
- lib.each do |val|
292
- val = File.join(val, '**/*.rb') unless val.include?('*') || val.end_with?('.rb')
293
- list.concat(Dir.glob(val, base: path))
318
+ list = lib.flat_map do |val|
319
+ val = File.join(val, '**/*.rb') unless val.include?('*') || val.match?(/\.[a-z\d]+$/i)
320
+ Dir.glob(val, base: path)
294
321
  end
295
- if args.empty?
296
- files = choice_index('Select files', list, multiple: true, force: true, series: true,
322
+ files = if args.empty?
323
+ choice_index('Select files', list, multiple: true, series: true,
297
324
  accept: [accept_y('Generate?')])
298
- else
299
- files = []
300
- args.each do |val|
301
- if val.include?('*')
302
- files.concat(Dir.glob(val, base: path))
303
- elsif !(file = basepath(val)).exist?
304
- print_error(val, hint: 'not found')
305
- elsif file.directory?
306
- files.concat(file.glob('**/*.rb'))
307
- else
308
- files << val
309
- end
310
- end
311
- list.map! { |val| basepath(val).to_s }
312
- files = files.select { |val| list.include?(basepath(val).to_s) }
313
- if files.empty?
314
- print_error('steep', 'no files matched', hint: "#{key}:check")
315
- exit 1
316
- end
317
- files.uniq!
318
- end
325
+ else
326
+ list.map! { |val| basepath(val).to_s }
327
+ [].tap do |out|
328
+ ret = []
329
+ args.each do |val|
330
+ if val.include?('*')
331
+ ret.concat(Dir.glob(val, base: path))
332
+ elsif !(file = basepath!(val))
333
+ print_error(val, hint: 'not found')
334
+ elsif file.directory?
335
+ ret.concat(file.glob('**/*.rb'))
336
+ else
337
+ ret << val
338
+ end
339
+ end
340
+ ret = ret.select { |val| list.include?(basepath(val).to_s) }
341
+ if ret.empty?
342
+ print_error('steep', 'no files matched', hint: "#{key}:check")
343
+ exit 1
344
+ end
345
+ out.replace(ret.uniq)
346
+ end
347
+ end
319
348
  sig = if (n = sig.index(args.first))
320
349
  args.shift
321
350
  sig[n]
322
351
  elsif sig.size > 1
323
- choice_index('Select a sig', sig, force: true, series: true)
352
+ choice_index('Select a sig', sig, series: true)
324
353
  else
325
354
  sig.first
326
355
  end
@@ -328,6 +357,24 @@ module Squared
328
357
  end
329
358
  end
330
359
  end
360
+ when 'rubocop'
361
+ next unless @rubocopfile
362
+
363
+ format_desc action, nil, 'opts*,path*/:'
364
+ task action do |_, args|
365
+ opts, args = args.to_a.partition do |val|
366
+ next true if val.match?(/\A(?:(?:[A-Z]|[a-z-]+)=.|[a-z]+(?:-[a-z]+)*\Z)/)
367
+
368
+ !val.include?('*') && !val.end_with?('/')
369
+ end
370
+ if opts.delete(':')
371
+ args << (Dir.exist?('lib') ? 'lib/' : '**/*.rb') if args.empty?
372
+ list = args.map! { |val| val.end_with?('/') || Dir.exist?(val) ? File.join(val, '**/*.rb') : val }
373
+ .flat_map { |val| Dir.glob(val, base: path) }
374
+ args = choice_index('Select files', list, multiple: true)
375
+ end
376
+ rubocop(*args, opts: opts, banner: true)
377
+ end
331
378
  end
332
379
  else
333
380
  namespace action do
@@ -400,7 +447,7 @@ module Squared
400
447
  task flag do |_, args|
401
448
  opts = args.to_a
402
449
  opts << 'redownload' if has_value!(opts, 'f', 'force')
403
- if (lock = basepath('Gemfile.lock')).exist?
450
+ if (lock = basepath!('Gemfile.lock'))
404
451
  config = basepath '.bundle', 'config'
405
452
  if config.exist? && config.read.match?(/\bBUNDLE_FROZEN:\s+"true"/)
406
453
  if opts.include?('redownload')
@@ -432,7 +479,7 @@ module Squared
432
479
  else
433
480
  a, b, c = choice_index('Select a file', Dir.glob(file || '*.rb', base: path),
434
481
  values: (file ? [] : ['Options']).push('Arguments'),
435
- force: true, series: true)
482
+ series: true)
436
483
  if file
437
484
  file = a
438
485
  b
@@ -442,18 +489,18 @@ module Squared
442
489
  c
443
490
  end
444
491
  end)
445
- ruby(*args, flag: flag, opts: opts, file: file)
492
+ ruby(flag, *args, opts: opts, file: file)
446
493
  end
447
494
  when :script
448
495
  format_desc action, flag, 'opts*'
449
496
  task flag do |_, args|
450
497
  command = ENV['RUBY_E'] || readline('Enter script', force: true, multiline: %w[## ;])
451
- ruby(flag: flag, opts: args.to_a, command: command)
498
+ ruby(flag, opts: args.to_a, command: command)
452
499
  end
453
500
  when :version
454
501
  format_desc action, flag
455
502
  task flag do
456
- ruby(flag: flag)
503
+ ruby flag
457
504
  end
458
505
  end
459
506
  end
@@ -470,21 +517,38 @@ module Squared
470
517
  elsif outdated?
471
518
  workspace.rev_clear(name, sync: sync)
472
519
  cmd = bundle_session 'install'
520
+ option('binstubs') do |val|
521
+ next if val == '0' || val == 'false'
522
+
523
+ run(bundle_output('binstubs --all', case val
524
+ when '1', 'true'
525
+ nil
526
+ else
527
+ if val.start_with?('~')
528
+ val = File.join(Dir.home, val == '~' ? '.bundle' : val[1..-1])
529
+ if prod?
530
+ config_set('binstubs', shell_quote(val), global: true)
531
+ val = nil
532
+ end
533
+ else
534
+ val = basepath val
535
+ end
536
+ quote_option('path', val) if val
537
+ end), exception: false, banner: false, series: true)
538
+ end
473
539
  if prod? && !config_get('without')
474
- if RUBY_VERSION > '3'
540
+ if semgte?('3')
475
541
  config_set 'without', 'development'
476
542
  else
477
543
  cmd << '--without=development'
478
544
  end
479
545
  end
480
- if (n = option('jobs')).to_i > 0
481
- cmd << "-j#{n}"
482
- end
546
+ option('jobs') { |n| cmd << "-j#{n}" if n.to_i > 0 }
483
547
  run_rb(from: :depend, sync: sync)
484
548
  end
485
549
  end
486
550
 
487
- def copy(from: gemlib, into: @gemdir, override: false, **kwargs)
551
+ def copy(from: gemlib, into: gemdir, override: false, **kwargs)
488
552
  return if @copy == false
489
553
 
490
554
  glob = kwargs[:include]
@@ -530,6 +594,14 @@ module Squared
530
594
  end
531
595
  OptionPartition.new(opts, bundleopts(:outdated), cmd << "--#{flag}", project: self)
532
596
  .clear
597
+ elsif (up = option('u', 'update', prefix: 'bundle'))
598
+ flag = case up
599
+ when 'major', 'minor'
600
+ up.to_sym
601
+ else
602
+ :patch
603
+ end
604
+ items = []
533
605
  end
534
606
  dryrun ||= dryrun?(prefix: 'bundle')
535
607
  log.info cmd.to_s
@@ -544,12 +616,11 @@ module Squared
544
616
  col = 0
545
617
  buffer = []
546
618
  out = ->(val) { sync ? puts(val) : buffer << val }
547
- IO.popen(cmd.temp('--no-color')).each do |line|
548
- line.chomp!
619
+ IO.popen(cmd.temp('--no-color')).readlines(chomp: true).each do |line|
549
620
  if start > 0
550
621
  n = line.size
551
622
  unless stdin?
552
- line = line[0...col] if col > 0
623
+ line = line[0, col] if col > 0
553
624
  data = line.scan(SEM_VER)
554
625
  next unless (cur = data.shift) && (lat = data.shift)
555
626
 
@@ -655,16 +726,21 @@ module Squared
655
726
  end
656
727
  end
657
728
  begin
658
- status = if gems
659
- "#{gems.size} packages were updated"
660
- elsif dependfile.read =~ /\b(?:source\s+(["'])((?~\1))\1|remote:\s+(\S+))/
661
- right = true
662
- ($2 || $3).chomp('/')
663
- end
729
+ status = nil
730
+ if gems
731
+ status = "#{gems.size} packages were updated"
732
+ else
733
+ File.foreach(dependfile) do |line|
734
+ next unless line =~ /\b(?:source\s+(["'])((?~\1))\1|remote:\s+(\S+))/
735
+
736
+ status = ($2 || $3).chomp('/')
737
+ break
738
+ end
739
+ end
664
740
  rescue StandardError => e
665
741
  log.debug e
666
742
  end
667
- puts print_footer(status || 'Updates are available', right: right)
743
+ puts print_footer(status || 'Updates are available', right: status.include?('/'))
668
744
  elsif start == 0 && banner
669
745
  puts 'No updates were found'
670
746
  end
@@ -673,6 +749,7 @@ module Squared
673
749
  end
674
750
 
675
751
  def ruby(*args, flag: nil, sync: true, banner: verbose?, with: nil, pass: PASS_RUBY[:ruby], **kwargs)
752
+ flag = args.shift if !flag && args.first.is_a?(Symbol)
676
753
  if flag == :version
677
754
  pwd_set do
678
755
  out = []
@@ -782,30 +859,36 @@ module Squared
782
859
  end
783
860
  return
784
861
  end
785
- op = OptionPartition.new(session_opts(with, args: args, kwargs: kwargs, pass: pass), OPT_RUBY[:ruby],
786
- ruby_session, project: self, args: true)
787
- if (val = kwargs[:file])
788
- op.unshift(shell_quote(basepath(val)))
789
- elsif (val = kwargs[:command])
790
- op << quote_option('e', val)
791
- end
792
- append = lambda do |file|
793
- op.concat(args)
794
- unless op.empty?
795
- op.exist?(add: true) if file
796
- op.append(delim: true, escape: false, quote: false)
862
+ opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
863
+ op = OptionPartition.new(opts, OPT_RUBY[:ruby], ruby_session, project: self, multiple: [/^-e/], args: true,
864
+ stdin: true)
865
+ if kwargs[:command]
866
+ op << quote_option('e', kwargs[:command])
867
+ elsif kwargs[:file]
868
+ if op.include?('-')
869
+ op.add_path(kwargs[:file])
870
+ else
871
+ op.unshift(basepath(kwargs[:file]))
797
872
  end
798
873
  end
799
- case flag
800
- when :file
801
- append.call(false)
802
- when :script
803
- op.clear
874
+ op.concat(args)
875
+ if op.include?('-')
876
+ op.exist?(add: true)
804
877
  else
805
- append.call(true)
806
- print_run(op, banner, **kwargs)
878
+ op.append_any { |val| OptionPartition.parse_arg!('e', val) }
879
+ if op.arg?('e')
880
+ op.clear
881
+ else
882
+ op.append(delim: true, escape: kwargs.fetch(:escape, false), quote: kwargs.fetch(:quote, false))
883
+ end
807
884
  end
808
- run_rb(sync: sync, banner: banner, from: flag.is_a?(Symbol) ? :"ruby:#{flag}" : :ruby)
885
+ from = if flag
886
+ :"ruby:#{flag}"
887
+ else
888
+ print_run(op, banner, **kwargs)
889
+ :ruby
890
+ end
891
+ run_rb(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: from)
809
892
  end
810
893
 
811
894
  def gem(flag, *args, sync: true, banner: verbose?, with: nil, pass: nil, **kwargs)
@@ -1038,7 +1121,7 @@ module Squared
1038
1121
  file = basepath(if !n && (spec = gemspec)
1039
1122
  "#{spec.name}-#{spec.version}.gem"
1040
1123
  else
1041
- choice_index('Select a file', Dir.glob('*.gem', base: path), force: true)
1124
+ choice_index 'Select a file', Dir.glob('*.gem', base: path)
1042
1125
  end)
1043
1126
  else
1044
1127
  file = basepath(op.shift.yield_self { |val| val.include?('.') ? val : "#{val}.gem" })
@@ -1097,7 +1180,7 @@ module Squared
1097
1180
  else
1098
1181
  [name[0, n], name[n.succ..-1]]
1099
1182
  end
1100
- op.adjoin(pre, shell_option('version', ver))
1183
+ op.adjoin(pre, basic_option('version', ver))
1101
1184
  .clear
1102
1185
  end
1103
1186
  if flag == :install
@@ -1105,7 +1188,7 @@ module Squared
1105
1188
  else
1106
1189
  op.append
1107
1190
  end
1108
- op << '--' << post if post
1191
+ op.delim << post if post
1109
1192
  when :check, :cleanup, :contents, :fetch, :list, :lock, :rdoc
1110
1193
  op.append
1111
1194
  when :dependency, :info, :search
@@ -1143,7 +1226,7 @@ module Squared
1143
1226
  end
1144
1227
  op.clear(errors: true) if gems
1145
1228
  print_run(op, banner, **kwargs)
1146
- run_rb(sync: sync, banner: banner, from: from)
1229
+ run_rb(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: from)
1147
1230
  end
1148
1231
 
1149
1232
  def bundle(flag, *args, sync: true, banner: verbose?, with: nil, pass: nil, **kwargs)
@@ -1242,7 +1325,8 @@ module Squared
1242
1325
  op.clear
1243
1326
  end
1244
1327
  print_run(op, banner, **kwargs)
1245
- run(sync: sync, banner: banner, from: :"bundle:#{flag}").tap { |ret| success?(ret, banner, output) }
1328
+ run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: :"bundle:#{flag}")
1329
+ .tap { |ret| success?(ret, banner, output) }
1246
1330
  end
1247
1331
 
1248
1332
  def rake(*args, sync: true, banner: verbose?, with: nil, pass: PASS_RUBY[:rake], **kwargs)
@@ -1252,7 +1336,8 @@ module Squared
1252
1336
  op.concat(args)
1253
1337
  op.append(escape: true)
1254
1338
  print_run(op, banner, **kwargs)
1255
- run(op, ({ 'BANNER' => '0' } unless banner), sync: sync, banner: false, from: :rake)
1339
+ var = { 'BANNER' => '0' } unless banner
1340
+ run(op, var, sync: sync, banner: false, exception: kwargs.fetch(:exception, exception), from: :rake)
1256
1341
  end
1257
1342
 
1258
1343
  def irb(*args, banner: verbose?, with: nil, pass: PASS_RUBY[:irb], **kwargs)
@@ -1266,7 +1351,7 @@ module Squared
1266
1351
  op.concat(args)
1267
1352
  op.append(delim: true)
1268
1353
  print_run(op, banner, **kwargs)
1269
- run(banner: false, from: :irb)
1354
+ run(banner: false, exception: kwargs.fetch(:exception, exception), from: :irb)
1270
1355
  end
1271
1356
 
1272
1357
  def rbs(flag, *args, banner: verbose?, with: nil, pass: nil, **kwargs)
@@ -1284,11 +1369,11 @@ module Squared
1284
1369
  sig = args.shift
1285
1370
  y = option('y', ignore: false)
1286
1371
  i = 1
1287
- args.map { |val| basepath(val).relative_path_from(path) }.each do |file|
1372
+ args.map! { |val| basepath(val).relative_path_from(path) }.each do |file|
1288
1373
  dir = basepath sig, file.dirname
1289
1374
  dir.mkpath unless dir.exist?
1290
1375
  base = file.basename.to_s
1291
- rbs = dir.join("#{base.stripext}.rbs")
1376
+ rbs = dir + "#{base.stripext}.rbs"
1292
1377
  status = if rbs.exist?
1293
1378
  case y
1294
1379
  when '0', 'false'
@@ -1315,14 +1400,36 @@ module Squared
1315
1400
  op.clear
1316
1401
  .append(*args)
1317
1402
  print_run(op, banner, **kwargs)
1318
- run(banner: false, from: :"rbs:#{flag}")
1403
+ run(banner: false, exception: kwargs.fetch(:exception, exception), from: :"rbs:#{flag}")
1319
1404
  end
1320
1405
  end
1321
1406
 
1322
- def gemspec
1323
- return @gemspec || nil unless @gemspec.nil?
1407
+ def rubocop(*args, sync: true, banner: verbose?, with: nil, pass: PASS_RUBY[:rubocop], **kwargs)
1408
+ opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
1409
+ op = OptionPartition.new(opts, OPT_RUBY[:rubocop], session('rubocop'), project: self,
1410
+ no: OPT_RUBY[:no][:rubocop])
1411
+ if @rubocopfile && !op.arg?('c', 'config') && !rootpath('.rubocop.yml', ascend: true).exist?
1412
+ op.add_path(@rubocopfile, option: 'c')
1413
+ end
1414
+ op.concat(args)
1415
+ op.each do |val|
1416
+ if basepath(val).file?
1417
+ op.found << val
1418
+ else
1419
+ op.errors << val
1420
+ end
1421
+ end
1422
+ op.swap
1423
+ .map! { |val| basepath(val).relative_path_from(path) }
1424
+ op.append(delim: true)
1425
+ .clear(errors: true)
1426
+ print_run(op, banner, **kwargs)
1427
+ run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: :rubocop)
1428
+ end
1324
1429
 
1325
- @gemspec = gemfile && Gem::Specification.load(gemfile.to_s) rescue false
1430
+ def gemspec
1431
+ @gemspec = !gemfile.nil? && Gem::Specification.load(gemfile.to_s) rescue false if @gemspec.nil?
1432
+ @gemspec || nil
1326
1433
  end
1327
1434
 
1328
1435
  def gemname
@@ -1335,7 +1442,7 @@ module Squared
1335
1442
 
1336
1443
  def copy?
1337
1444
  return true if @copy.is_a?(Hash) ? copy[:into] : super
1338
- return gemdir? if @gemdir
1445
+ return gemdir? if gemdir
1339
1446
 
1340
1447
  if version
1341
1448
  begin
@@ -1351,8 +1458,8 @@ module Squared
1351
1458
  val =~ /(\d\.\d)\.[^.]+$/ && File.join(val, 'lib/ruby/gems', "#{$1}.0")
1352
1459
  end
1353
1460
  when /bundler?/
1354
- pwd_set { `bundle env` }[/^\s+Gem Home\s+(.+)$/, 1]
1355
- end.tap { |val| @gemdir = Pathname.new(val) if val }
1461
+ pwd_set { `bundle env` }[/^\s+Gem Path\s+([^#{File::PATH_SEPARATOR}]+)/, 1]
1462
+ end.tap { |val| self.gemdir = val if val }
1356
1463
  rescue StandardError => e
1357
1464
  log.debug e
1358
1465
  end
@@ -1361,11 +1468,14 @@ module Squared
1361
1468
  return false unless @autodetect
1362
1469
 
1363
1470
  set = lambda do |val, path|
1471
+ dir = Pathname.new(path.strip) + gempath
1472
+ return false unless dir.writable?
1473
+
1364
1474
  if (ver = version) && ver != val
1365
1475
  log.warn "using version #{val}".subhint("given #{ver}")
1366
1476
  end
1367
1477
  self.version = val
1368
- @gemdir = Pathname.new(path.strip) + gempath
1478
+ self.gemdir = dir
1369
1479
  end
1370
1480
  if version
1371
1481
  opt = gempwd
@@ -1380,30 +1490,30 @@ module Squared
1380
1490
  next unless out =~ /\(#{Regexp.escape(val)}[^)]*\):([^\n]+)/
1381
1491
 
1382
1492
  set.call(val, $1)
1383
- return gemdir? if @gemdir
1493
+ return gemdir? if gemdir
1384
1494
  end
1385
1495
  end
1386
- @gemdir = Pathname.new(Gem.dir) + gempath
1496
+ self.gemdir = Pathname.new(Gem.dir) + gempath
1387
1497
  else
1388
1498
  parse = lambda do |path|
1389
- next unless path
1499
+ return false unless path
1390
1500
 
1391
- lib = Regexp.new(['', 'gems', "#{gemname}-([^#{File::SEPARATOR}]+)", ''].join(File::SEPARATOR))
1392
- if (ver = path[lib, 1]) && (val = path[/\A(.+)#{gempath(ver[1])}/, 1])
1501
+ ver = path[Regexp.new(['', 'gems', "#{gemname}-([^#{File::SEPARATOR}]+)", ''].join(File::SEPARATOR)), 1]
1502
+ if ver && (val = path[/\A(.+)#{Regexp.escape(gempath(ver))}/, 1])
1393
1503
  set.call(ver, val)
1394
1504
  end
1395
1505
  end
1396
- if RUBY_VERSION >= '2.6'
1506
+ if semgte?('2.6')
1397
1507
  target = RUBY_VERSION.start_with?('2.6') ? RubyVM : $LOAD_PATH
1398
1508
  parse.call(target.resolve_feature_path(gemname)&.last)
1399
1509
  end
1400
- unless @gemdir || pwd_set { parse.call(`#{bundle_output('show', gemname)}`) }
1510
+ unless gemdir || pwd_set { parse.call(`#{bundle_output('show', gemname)}`) }
1401
1511
  raise_error Errno::ENOENT, 'gems home'
1402
1512
  end
1403
1513
  end
1404
1514
  rescue StandardError => e
1405
1515
  log.error e
1406
- @version = nil
1516
+ self.version = nil
1407
1517
  @gemdir = nil
1408
1518
  @autodetect = false
1409
1519
  else
@@ -1477,8 +1587,8 @@ module Squared
1477
1587
  end
1478
1588
  end
1479
1589
 
1480
- def config_set(key, *val)
1481
- run(bundle_output('config set', key, *val), banner: false, series: true)
1590
+ def config_set(key, *val, global: false)
1591
+ run(bundle_output('config', ('--global' if global), 'set', key, *val), banner: false, series: true)
1482
1592
  end
1483
1593
 
1484
1594
  def preopts
@@ -1490,10 +1600,11 @@ module Squared
1490
1600
  end
1491
1601
 
1492
1602
  def rakefile
1493
- return @rakefile || nil unless @rakefile.nil?
1494
-
1495
- file = Rake::Application::DEFAULT_RAKEFILES.find { |val| exist?(val) }
1496
- @rakefile = file ? basepath(file) : false
1603
+ if @rakefile.nil?
1604
+ file = Rake::Application::DEFAULT_RAKEFILES.find { |val| exist?(val) }
1605
+ @rakefile = !file.nil? && basepath(file)
1606
+ end
1607
+ @rakefile || nil
1497
1608
  end
1498
1609
 
1499
1610
  def rakepwd
@@ -1554,11 +1665,12 @@ module Squared
1554
1665
  end
1555
1666
 
1556
1667
  def gemfile
1557
- return @gemfile || nil unless @gemfile.nil?
1558
-
1559
- @gemfile = [project, name].map! { |val| basepath("#{val}.gemspec") }
1560
- .concat(path.glob('*.gemspec'))
1561
- .find(&:exist?) || false
1668
+ if @gemfile.nil?
1669
+ @gemfile = [project, name].map! { |val| basepath("#{val}.gemspec") }
1670
+ .concat(path.glob('*.gemspec'))
1671
+ .find(&:exist?) || false
1672
+ end
1673
+ @gemfile || nil
1562
1674
  end
1563
1675
 
1564
1676
  def gemlib
@@ -1575,9 +1687,9 @@ module Squared
1575
1687
  end
1576
1688
 
1577
1689
  def gemdir?
1578
- return false unless @gemdir
1690
+ return false unless gemdir
1579
1691
 
1580
- @gemdir.exist? && !@gemdir.empty?
1692
+ gemdir.exist? && !gemdir.empty? && gemdir.writable?
1581
1693
  end
1582
1694
  end
1583
1695