squared 0.0.12 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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