squared 0.0.12 → 0.1.1

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.
@@ -38,6 +38,7 @@ module Squared
38
38
  install: %i[force frozen dedupe].freeze,
39
39
  outdated: %i[major minor patch].freeze,
40
40
  bump: %i[major minor patch].freeze,
41
+ update: nil,
41
42
  run: nil
42
43
  }.freeze
43
44
 
@@ -74,7 +75,7 @@ module Squared
74
75
  else
75
76
  cmd = guard_params(action, 'command', args: args.to_a)
76
77
  cmd.each do |val|
77
- if (data = indexdata(val))
78
+ if (data = indexitem(val))
78
79
  n, opts = data
79
80
  list = read_scripts
80
81
  if (item = list[n - 1])
@@ -89,6 +90,11 @@ module Squared
89
90
  end
90
91
  end
91
92
  end
93
+ when :update
94
+ desc format_desc(action, nil, 'packages*')
95
+ task action, [:packages] do |_, args|
96
+ update args.to_a
97
+ end
92
98
  end
93
99
  else
94
100
  namespace action do
@@ -117,52 +123,85 @@ module Squared
117
123
  end
118
124
  end
119
125
 
120
- def copy(from: 'build', glob: nil, into: 'node_modules', scope: nil, also: nil, override: false)
126
+ def copy(from: 'build', into: 'node_modules', workspace: false, include: nil, exclude: nil, scope: nil,
127
+ also: nil, create: nil, override: false)
121
128
  return if @copy == false
122
129
 
123
130
  if @copy && !override
124
131
  return super if runnable?(@copy)
125
132
 
126
133
  from = @copy[:from] if @copy.key?(:from)
127
- glob = @copy[:glob] if @copy.key?(:glob)
128
134
  into = @copy[:into] if @copy.key?(:into)
129
- scope = @copy[:scope] if @copy.key?(:scope)
130
- also = @copy[:also] if @copy.key?(:also)
135
+ workspace = @copy[:workspace] if @copy.key?(:workspace)
136
+ glob = @copy[:include]
137
+ exclude = @copy[:exclude]
138
+ scope = @copy[:scope]
139
+ also = @copy[:also]
140
+ create = @copy[:create]
131
141
  end
132
- items = [path != workspace.home && workspace.home? ? workspace.home : nil]
142
+ items = []
143
+ items << @workspace.home if build? && path != @workspace.home && @workspace.home?
133
144
  items += as_a(also) if also
134
- items.each_with_index do |dir, i|
135
- if i == 0
136
- next unless dev? && build?
145
+ return if items.empty?
137
146
 
147
+ print_item unless @output[0] || !verbose || task_invoked?(/^copy(?::#{Node.ref}|$)/)
148
+ items.each do |dir|
149
+ case dir
150
+ when Pathname
138
151
  dest = dir
152
+ when String
153
+ dest = @workspace.rootpath(dir)
154
+ when Symbol
155
+ dest = @workspace.find(name: dir)&.path
156
+ log.warn message("copy project :#{dir}", hint: 'not found') unless dest
157
+ when Hash
158
+ glob = dir[:include]
159
+ exclude = dir[:exclude]
160
+ from = dir[:from] if dir.key?(:from)
161
+ into = dir[:into] if dir.key?(:into)
162
+ scope = dir[:scope] if dir.key?(:scope)
163
+ dest = dir[:target]
164
+ create = dir[:create]
165
+ workspace = dir[:workspace]
166
+ dest = items.first unless dest && dest != true
167
+ when Project::Base
168
+ dest = dir.path
139
169
  else
140
- case dir
141
- when ::String
142
- dest = workspace.rootpath(dir)
143
- when ::Symbol
144
- dest = workspace.find(name: dir)&.path
145
- log.warn message("copy project :#{dir}", hint: 'not found') unless dest
146
- when ::Hash
147
- missing = ->(val) { log.warn message("copy attr :#{val}", hint: 'missing') }
148
- glob = dir[:glob]
149
- into = dir[:into] if dir.key?(:into)
150
- scope = dir[:scope]
151
- missing.('target') unless (dest = dir[:target])
152
- missing.('from') unless (from = dir[:from])
153
- when Project::Base
154
- dest = dir.path
155
- else
156
- raise_error("given: #{dir}", hint: 'unknown')
157
- end
170
+ raise_error("given: #{dir}", hint: 'unknown')
158
171
  end
159
172
  next unless from && dest&.directory?
160
173
 
161
174
  from = basepath(from)
162
- dest = dest.join(into, scope || project)
163
175
  glob = as_a(glob || '**/*')
164
- glob.each { |val| log.info "cp #{from.join(val)} #{dest}" }
165
- copy_d(from, dest, glob: glob, verbose: verbose)
176
+ target = []
177
+ if workspace
178
+ Dir.glob(from.join('*')).each do |path|
179
+ next unless (path = Pathname.new(path)).directory?
180
+
181
+ sub = if (proj = @workspace.find(path))
182
+ proj.packagename
183
+ elsif (file = path.join('package.json')).exist?
184
+ begin
185
+ doc = JSON.parse(file.read)
186
+ doc['name']
187
+ rescue StandardError => e
188
+ log.error e
189
+ raise if exception
190
+ end
191
+ end
192
+ if sub
193
+ target << [path, dest.join(into, sub)]
194
+ else
195
+ log.debug message("package.json in \"#{path}\"", hint: 'not found')
196
+ end
197
+ end
198
+ else
199
+ target << [from, dest.join(into, scope || project)]
200
+ end
201
+ target.each do |src, to|
202
+ glob.each { |val| log.info "cp #{from.join(val)} #{to}" }
203
+ copy_d(src, to, glob: glob, create: create, pass: exclude, verbose: verbose)
204
+ end
166
205
  end
167
206
  end
168
207
 
@@ -229,33 +268,42 @@ module Squared
229
268
  end
230
269
  end
231
270
 
232
- def outdated(rev = nil, opts: [])
271
+ def outdated(rev = nil, opts: [], sync: invoked_sync?('outdated', rev))
233
272
  dryrun = opts.include?('dry-run')
234
273
  if pnpm? && read_packagemanager(version: '7.15')
235
274
  cmd = 'pnpm outdated'
236
- dryrun ||= !option('dry-run', prefix: 'pnpm').nil?
275
+ dryrun ||= dryrun?('pnpm')
237
276
  else
238
277
  cmd = 'npm outdated'
239
- dryrun ||= !option('dry-run', prefix: 'npm').nil?
278
+ dryrun ||= dryrun?('npm')
240
279
  end
241
280
  log.info cmd
242
281
  banner = format_banner("#{cmd}#{dryrun ? ' --dry-run' : ''}")
243
- if invoked_sync?('outdated', rev)
282
+ if sync
244
283
  print_item banner
245
284
  banner = nil
246
285
  end
247
- data = nil
248
- pwd_set { data = `#{cmd} --json --loglevel=error` }
249
- json = JSON.parse(doc = dependfile.read)
250
- dep1 = json['dependencies'] || {}
251
- dep2 = json['devDependencies'] || {}
286
+ begin
287
+ data = pwd_set { `#{cmd} --json --loglevel=error` }
288
+ json = JSON.parse(doc = dependfile.read)
289
+ rescue StandardError => e
290
+ log.error e
291
+ raise if exception
292
+
293
+ warn log_message(Logger::WARN, e) if warning?
294
+ return
295
+ else
296
+ dep1 = json['dependencies'] || {}
297
+ dep2 = json['devDependencies'] || {}
298
+ target = json['name']
299
+ end
252
300
  found = []
253
301
  avail = []
254
302
  rev ||= (prod? ? :patch : :minor)
255
303
  inter = opts.include?('interactive')
256
304
  unless data.empty?
257
305
  JSON.parse(data).each_pair do |key, val|
258
- val = val.find { |obj| obj['dependent'] == json['name'] } if val.is_a?(::Array)
306
+ val = val.find { |obj| obj['dependent'] == target } if val.is_a?(Array)
259
307
  next unless val && (file = dep1[key] || dep2[key]) && file != '*'
260
308
 
261
309
  latest = val['latest']
@@ -271,8 +319,8 @@ module Squared
271
319
  want = rev == :major && (ver = latest.match(SEM_VER)) && !ver[6] ? latest : val['wanted']
272
320
  next unless (val['current'] != want || file != want) && (want.match?(SEM_VER) || !file.match?(SEM_VER))
273
321
 
274
- f = semver(semscan(file))
275
- w = semver(semscan(want))
322
+ f = semscan(file)
323
+ w = semscan(want)
276
324
  a = f[0]
277
325
  b = f[2]
278
326
  c = w[0]
@@ -356,9 +404,9 @@ module Squared
356
404
  if dryrun || (modified == 0 && pending > 0)
357
405
  footer.(modified)
358
406
  elsif modified > 0
359
- File.write(dependfile, doc)
360
407
  modified = -1
361
408
  footer.()
409
+ File.write(dependfile, doc)
362
410
  commit(:add, ['package.json'], pass: true)
363
411
  install if opts.include?('prune')
364
412
  end
@@ -384,30 +432,10 @@ module Squared
384
432
  end
385
433
  end
386
434
 
387
- def compose(opts, flags = nil, script: false)
388
- return unless opts && script
389
-
390
- ret = session (if yarn?
391
- 'yarn'
392
- else
393
- pnpm? ? 'pnpm' : 'npm'
394
- end), 'run', flags
395
- append_loglevel
396
- case opts
397
- when ::Enumerable
398
- ret += opts.to_a
399
- when ::String
400
- ret << opts
401
- else
402
- raise_error("#{ret.first} script name", hint: opts.nil? ? 'missing' : 'invalid')
403
- end
404
- ret
405
- end
406
-
407
- def bump(flag)
435
+ def bump(flag = nil)
408
436
  return unless (ver = version)
409
437
 
410
- seg = semscan(ver)
438
+ seg = semscan(ver, fill: false)
411
439
  case flag
412
440
  when :major
413
441
  if seg[0] != '0' || seg[2].nil?
@@ -421,45 +449,74 @@ module Squared
421
449
  else
422
450
  seg[2] = seg[2].succ
423
451
  end
424
- when :patch
452
+ else
425
453
  seg[4] &&= seg[4].succ
426
454
  end
427
- unless (out = seg.join) == ver
428
- begin
429
- doc = dependfile.read
430
- if doc.sub!(/"version"\s*:\s*"#{ver}"/, "\"version\": \"#{out}\"")
455
+ return if (out = seg.join) == ver
456
+
457
+ begin
458
+ doc = dependfile.read
459
+ if doc.sub!(/"version"\s*:\s*"#{ver}"/, "\"version\": \"#{out}\"")
460
+ unless dryrun?
431
461
  dependfile.write(doc)
432
462
  log.info "bump version #{ver} to #{out} (#{flag})"
433
- if verbose
434
- major = flag == :major
435
- emphasize("version: #{out}", title: name, border: borderstyle, sub: [
436
- headerstyle,
437
- { pat: /^(version:)( )(\S+)(.*)$/, styles: color(major ? :green : :yellow), index: 3 },
438
- { pat: /^(version:)(.*)$/, styles: theme[major ? :major : :active] }
439
- ])
440
- elsif stdin?
441
- puts out
442
- end
443
- else
444
- raise_error('not found', hint: 'version')
445
463
  end
446
- rescue StandardError => e
447
- log.debug e
448
- raise
464
+ if verbose
465
+ major = flag == :major
466
+ emphasize("version: #{out}", title: name, border: borderstyle, sub: [
467
+ headerstyle,
468
+ { pat: /^(version:)( )(\S+)(.*)$/, styles: color(major ? :green : :yellow), index: 3 },
469
+ { pat: /^(version:)(.*)$/, styles: theme[major ? :major : :active] }
470
+ ])
471
+ elsif stdin?
472
+ puts out
473
+ end
474
+ else
475
+ raise_error('not found', hint: 'version')
449
476
  end
477
+ rescue StandardError => e
478
+ log.debug e
479
+ raise if exception
450
480
  end
451
481
  end
452
482
 
453
- def version
454
- read_packagemanager
455
- @pm[:version]
483
+ def update(pkgs = [])
484
+ if (yarn = dependtype(:yarn)) > 0
485
+ cmd = session 'yarn'
486
+ if yarn > 1
487
+ cmd << 'up'
488
+ else
489
+ cmd << 'upgrade'
490
+ cmd << '--ignore-engines' unless option('ignore-engines', equals: '0')
491
+ end
492
+ elsif pnpm?
493
+ cmd = session 'pnpm', 'update'
494
+ cmd << '--prod' if prod?
495
+ append_nocolor option('no-color')
496
+ else
497
+ cmd = session 'npm', 'update'
498
+ cmd << '--omit=dev' if prod?
499
+ append_nocolor option('no-color')
500
+ end
501
+ append_loglevel
502
+ append_value pkgs
503
+ run
456
504
  end
457
505
 
458
- def dependtype(prog)
459
- return @pm[prog] if @pm.key?(prog)
506
+ def compose(opts, flags = nil, script: false)
507
+ return unless opts && script
460
508
 
461
- meth = :"#{prog}?"
462
- respond_to?(meth) && __send__(meth) ? @pm[prog] : 0
509
+ ret = session dependbin, 'run', flags
510
+ append_loglevel
511
+ case opts
512
+ when Enumerable
513
+ ret += opts.to_a
514
+ when String
515
+ ret << opts
516
+ else
517
+ raise_error("#{ret.first} script name", hint: opts.nil? ? 'missing' : 'invalid')
518
+ end
519
+ ret
463
520
  end
464
521
 
465
522
  def depend?
@@ -467,7 +524,7 @@ module Squared
467
524
  end
468
525
 
469
526
  def copy?
470
- super || @copy.is_a?(::Hash)
527
+ super || @copy.is_a?(Hash)
471
528
  end
472
529
 
473
530
  def outdated?
@@ -475,8 +532,8 @@ module Squared
475
532
  end
476
533
 
477
534
  def yarn?
478
- (@pm[:yarn] ||= if basepath('yarn.lock', ascend: find_package).exist?
479
- if (rc = basepath('.yarnrc.yml', ascend: find_package)).exist?
535
+ (@pm[:yarn] ||= if basepath('yarn.lock', ascend: dependext).exist?
536
+ if (rc = basepath('.yarnrc.yml', ascend: dependext)).exist?
480
537
  begin
481
538
  require 'yaml'
482
539
  doc = YAML.load_file(rc)
@@ -495,10 +552,10 @@ module Squared
495
552
  end
496
553
 
497
554
  def pnpm?
498
- (@pm[:pnpm] ||= if basepath('pnpm-lock.yaml', ascend: find_package).exist?
555
+ (@pm[:pnpm] ||= if basepath('pnpm-lock.yaml', ascend: dependext).exist?
499
556
  begin
500
557
  require 'yaml'
501
- doc = YAML.load_file(basepath('node_modules/.modules.yaml', ascend: find_package))
558
+ doc = YAML.load_file(basepath('node_modules/.modules.yaml', ascend: dependext))
502
559
  @pm[:_] = doc['packageManager']
503
560
  case doc['nodeLinker']
504
561
  when 'hoisted'
@@ -521,24 +578,42 @@ module Squared
521
578
  basepath('pnpm-workspace.yaml').exist?
522
579
  else
523
580
  read_packagemanager
524
- @pm[:workspaces].is_a?(::Array)
581
+ @pm[:workspaces].is_a?(Array)
525
582
  end
526
583
  end
527
584
 
528
585
  def dev?
529
- !Node.prod? && super
586
+ super && (!Node.prod? || (@dev == true && !prod?))
530
587
  end
531
588
 
532
589
  def prod?
533
590
  @prod != false && (Node.prod? || super)
534
591
  end
535
592
 
593
+ def dependtype(prog)
594
+ return @pm[prog] if @pm.key?(prog)
595
+
596
+ meth = :"#{prog}?"
597
+ respond_to?(meth) && __send__(meth) ? @pm[prog] : 0
598
+ end
599
+
600
+ def version
601
+ read_packagemanager
602
+ @pm[:version]
603
+ end
604
+
605
+ def packagename
606
+ read_packagemanager
607
+ @pm[:name]
608
+ end
609
+
536
610
  private
537
611
 
538
612
  def read_packagemanager(version: nil)
539
613
  if @pm[:_].nil?
540
614
  doc = JSON.parse(dependfile.read)
541
615
  @pm[:_] = (val = doc['packageManager']) ? val[0..(val.index('+') || 0) - 1] : false
616
+ @pm[:name] = doc['name']
542
617
  @pm[:scripts] = doc['scripts']
543
618
  @pm[:version] = doc['version']
544
619
  @pm[:workspaces] = doc['workspaces']
@@ -560,7 +635,7 @@ module Squared
560
635
 
561
636
  def read_scripts
562
637
  read_packagemanager
563
- @pm[:scripts].is_a?(::Hash) ? @pm[:scripts].to_a : []
638
+ @pm[:scripts].is_a?(Hash) ? @pm[:scripts].to_a : []
564
639
  end
565
640
 
566
641
  def append_loglevel
@@ -605,12 +680,24 @@ module Squared
605
680
  'PATCH'
606
681
  end, styles: theme[:header])
607
682
  b = sub_style("#{pkg} #{ver}", styles: theme[:inline])
608
- c, d = rev == 1 || lock ? %w[y/N N] : %w[Y/n Y]
683
+ c, d = rev == 1 || lock ? ['y/N', 'N'] : ['Y/n', 'Y']
609
684
  e = lock ? " #{sub_style('(locked)', styles: color(:red))}" : ''
610
685
  Common::Prompt.confirm("Upgrade to #{a}? #{b}#{e} [#{c}] ", d, timeout: 60)
611
686
  end
612
687
 
613
- def find_package
688
+ def dryrun?(prefix = dependbin)
689
+ !option('dry-run', prefix: prefix).nil?
690
+ end
691
+
692
+ def dependbin
693
+ if yarn?
694
+ 'yarn'
695
+ else
696
+ pnpm? ? 'pnpm' : 'npm'
697
+ end
698
+ end
699
+
700
+ def dependext
614
701
  'package.json' if parent&.has?('outdated', Node.ref)
615
702
  end
616
703
  end
@@ -6,7 +6,7 @@ module Squared
6
6
  class Python < Git
7
7
  REQUIREMENTS = %w[requirements.txt pyproject.toml setup.py].freeze
8
8
  OPT_USER = %w[pre dry-run].freeze
9
- OPT_FORCE = [*OPT_USER, 'user'].freeze
9
+ OPT_FORCE = (OPT_USER + ['user']).freeze
10
10
  OPT_GENERAL = %w{venv isolated no-cache-dir [v]erbose}.freeze
11
11
  private_constant :REQUIREMENTS, :OPT_USER, :OPT_FORCE, :OPT_GENERAL
12
12
 
@@ -116,6 +116,8 @@ module Squared
116
116
  when :force
117
117
  cmd << '--force-reinstall'
118
118
  append_pip opts, OPT_FORCE
119
+ else
120
+ append_pip
119
121
  end
120
122
  cmd << (type == 1 ? '-r requirements.txt' : '.')
121
123
  run(sync: sync)
@@ -125,9 +127,10 @@ module Squared
125
127
  end
126
128
  end
127
129
 
128
- def outdated(*)
130
+ def outdated(*, sync: invoked_sync?('outdated'))
129
131
  pip_session 'list', '--outdated'
130
- run
132
+ append_pip
133
+ run(sync: sync)
131
134
  end
132
135
 
133
136
  def variable_set(key, *val, **)
@@ -159,7 +162,7 @@ module Squared
159
162
  session('pip', *cmd)
160
163
  end
161
164
 
162
- def append_pip(opts, list = [])
165
+ def append_pip(opts = [], list = [])
163
166
  opts.each do |opt|
164
167
  next unless list.include?(opt) || OPT_GENERAL.include?(opt) || (v = opt.match(/^v+$/))
165
168
 
@@ -170,14 +173,13 @@ module Squared
170
173
  (v ? "-#{v[0]}" : "--#{opt}")
171
174
  end
172
175
  end
173
- @session << '--user' if option('user')
174
- @session << '--no-input' if option('no-input')
175
176
  if (val = option('proxy', ignore: false))
176
177
  @session << "--proxy=#{shell_escape(val, quote: true)}"
177
178
  end
178
- if (val = option('log', ignore: false))
179
- @session << "--log=#{shell_escape(basepath(val), quote: true)}"
180
- end
179
+ @session << "--python=#{shell_escape(basepath(val), quote: true)}" if (val = option('python', ignore: false))
180
+ @session << "--log=#{shell_escape(basepath(val), quote: true)}" if (val = option('log', ignore: false))
181
+ @session << '--user' if option('user')
182
+ @session << '--no-input' if option('no-input')
181
183
  append_nocolor option('no-color')
182
184
  end
183
185
 
@@ -6,7 +6,7 @@ module Squared
6
6
  class Ruby < Git
7
7
  VAR_SET = %i[version autodetect].freeze
8
8
  GEMFILE = %w[Gemfile Gemfile.lock gem.deps.rb Isolate].freeze
9
- RUBY_DIR = [*GEMFILE, *::Rake::Application::DEFAULT_RAKEFILES, 'README.rdoc'].freeze
9
+ RUBY_DIR = (GEMFILE + Rake::Application::DEFAULT_RAKEFILES + ['README.rdoc']).freeze
10
10
  OPT_INSTALL = %w[no-cache force].freeze
11
11
  OPT_UPDATE = %w[redownload local strict conservative group=s].freeze
12
12
  OPT_OUTDATED = %w[local strict pre only-explicit group=s].freeze
@@ -95,7 +95,7 @@ module Squared
95
95
  if args.command == '#'
96
96
  format_list(read_rakefile, 'rake[^N]', 'tasks', grep: args.extras, from: rakefile.to_s,
97
97
  each: ->(val) { val[0] + val[1].to_s })
98
- elsif (data = indexdata(args.command))
98
+ elsif (data = indexitem(args.command))
99
99
  n, opts = data
100
100
  list = read_rakefile
101
101
  if (item = list[n - 1])
@@ -206,35 +206,36 @@ module Squared
206
206
  end
207
207
  end
208
208
 
209
- def copy(from: 'lib', glob: nil, into: @gemdir, override: false)
209
+ def copy(from: 'lib', include: nil, exclude: nil, into: @gemdir, override: false)
210
210
  if @copy && !override
211
211
  return super if runnable?(@copy)
212
212
 
213
213
  from = @copy[:from] if @copy.key?(:from)
214
- glob = @copy[:glob] if @copy.key?(:glob)
214
+ glob = @copy[:include] if @copy.key?(:include)
215
+ exclude = @copy[:exclude] if @copy.key?(:exclude)
215
216
  into = @copy[:into] if @copy.key?(:into)
216
217
  end
217
218
  return unless into
218
219
 
219
220
  dest = Pathname.new(into).realpath
220
- print_item unless @output[0]
221
+ print_item unless @output[0] || task_invoked?(/^copy(?::#{Ruby.ref}|$)/)
221
222
  glob = as_a(glob || '**/*')
222
223
  as_a(from).each_with_index do |val, i|
223
224
  a = basepath(val)
224
225
  b = dest.join(val)
225
226
  c = glob[i] || glob[0]
226
227
  log.info "cp #{a.join(c)} #{b}"
227
- copy_d(a, b, glob: c, verbose: verbose)
228
+ copy_d(a, b, glob: c, pass: exclude, verbose: verbose)
228
229
  end
229
230
  end
230
231
 
231
- def outdated(rev = nil, opts: [])
232
+ def outdated(rev = nil, opts: [], sync: invoked_sync?('outdated', rev))
232
233
  cmd = bundle_session 'outdated', rev && "--#{rev}"
233
234
  append_bundle opts, OPT_OUTDATED
234
235
  cmd = session_done(cmd)
235
236
  log.info cmd
236
237
  banner = format_banner(cmd)
237
- if invoked_sync?('outdated', rev)
238
+ if sync
238
239
  print_item banner
239
240
  banner = nil
240
241
  end
@@ -363,10 +364,11 @@ module Squared
363
364
  end
364
365
 
365
366
  def rake(*cmd)
367
+ file = shell_quote(Rake.application.rakefile)
366
368
  if cmd.empty?
367
- run_s 'rake'
369
+ run_s("rake --rakefile=#{file}", chdir: workspace.pwd)
368
370
  else
369
- run_s(*cmd.map { |val| "rake #{val}" }, banner: false)
371
+ run_s(*cmd.map { |val| "rake --rakefile=#{file} #{val}" }, chdir: workspace.pwd, banner: false)
370
372
  end
371
373
  end
372
374
 
@@ -375,7 +377,7 @@ module Squared
375
377
  end
376
378
 
377
379
  def copy?
378
- return true if super || (@copy.is_a?(::Hash) && copy.fetch(:into, nil))
380
+ return true if super || (@copy.is_a?(Hash) && copy.fetch(:into, nil))
379
381
  return gemdir? if @gemdir
380
382
 
381
383
  if @version && (val = ENV['GEM_HOME'])
@@ -385,9 +387,8 @@ module Squared
385
387
  return false unless @autodetect
386
388
 
387
389
  unsafe = ->(hint) { raise_error('failed to parse', hint: hint) }
388
- out = `gem -C #{shell_quote(path)} list --local -d #{project}`
389
- data = /#{Regexp.escape(project)} \(([^)]+)\)/.match(out)
390
- unsafe.('version') unless data
390
+ out = pwd_set { `gem list --local -d #{project}` }
391
+ unsafe.('version') unless (data = /#{Regexp.escape(project)} \(([^)]+)\)/.match(out))
391
392
  ver = data[1].split(/\s*,\s*/)
392
393
  ver.unshift(@version).uniq! if @version
393
394
  ver.each do |v|
@@ -414,11 +415,6 @@ module Squared
414
415
 
415
416
  private
416
417
 
417
- def variables
418
- ret = super + VAR_SET
419
- ret.freeze
420
- end
421
-
422
418
  def run_rb(sync: true)
423
419
  run(sync: sync, banner: !@session.include?('--quiet'))
424
420
  end
@@ -457,26 +453,34 @@ module Squared
457
453
  return @rakelist if @rakelist
458
454
 
459
455
  ret = []
460
- IO.popen("rake -C #{shell_quote(path)} -AT").each do |line|
461
- next unless (data = /^rake ((?:[^\[: ]+:?)+)(\[[^\]]+\])?/.match(line))
456
+ pass = Rake::VERSION >= '13.0.4'
457
+ pwd_set(pass: pass) do
458
+ IO.popen("rake#{pass ? " -C #{shell_quote(path)}" : ''} -AT").each do |line|
459
+ next unless (data = /^rake ((?:[^\[: ]+:?)+)(\[[^\]]+\])?/.match(line))
462
460
 
463
- ret << [data[1], data[2]]
461
+ ret << [data[1], data[2]]
462
+ end
464
463
  end
465
464
  @rakelist = ret
466
465
  end
467
466
 
467
+ def gemdir?
468
+ @gemdir.exist? && !@gemdir.empty?
469
+ end
470
+
471
+ def variables
472
+ ret = super + VAR_SET
473
+ ret.freeze
474
+ end
475
+
468
476
  def rakefile
469
- file = ::Rake::Application::DEFAULT_RAKEFILES.find { |val| basepath(val).exist? }
477
+ file = Rake::Application::DEFAULT_RAKEFILES.find { |val| basepath(val).exist? }
470
478
  basepath(file) if file
471
479
  end
472
480
 
473
481
  def gempath
474
482
  File.join('gems', "#{project}-#{@version}")
475
483
  end
476
-
477
- def gemdir?
478
- @gemdir.exist? && !@gemdir.empty?
479
- end
480
484
  end
481
485
 
482
486
  Application.implement Ruby