squared 0.0.12 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,32 +9,31 @@ module Squared
9
9
  private_constant :OPT_PULL, :OPT_FETCH
10
10
 
11
11
  class << self
12
- include ::Rake::DSL
12
+ include Rake::DSL
13
13
 
14
14
  def populate(ws, **)
15
15
  return if ws.series[:pull].empty?
16
16
 
17
- name = ws.task_name('all')
18
- desc ws.task_name('all[git?=rebase|stash]', desc: true)
19
- task name, [:git] do |_, args|
20
- sync = lambda do |key|
21
- key = ws.task_name(key)
22
- ws.task_defined?(ret = ws.task_join(key, 'sync')) ? ret : key
17
+ namespace(name = ws.task_name('git')) do
18
+ all = ws.task_join(name, 'all')
19
+
20
+ desc ws.task_name("#{all}[git?=rebase|stash,depend?]", desc: true)
21
+ task 'all', [:git, :depend] do |_, args|
22
+ cmd = case args.git
23
+ when 'rebase'
24
+ [ws.task_sync('rebase')]
25
+ when 'stash'
26
+ [ws.task_sync('stash'), ws.task_sync('pull')]
27
+ else
28
+ [ws.task_sync('pull')]
29
+ end
30
+ cmd << ws.task_sync('depend') if args.depend && !ws.series[:depend].empty?
31
+ cmd << ws.task_sync('build')
32
+ Common::Utils.task_invoke(*cmd, **ws.invokeargs)
23
33
  end
24
- cmd = [case args.git
25
- when 'rebase'
26
- sync.('rebase')
27
- when 'stash'
28
- invoke(sync.('stash'), **ws.invokeargs)
29
- sync.('pull')
30
- else
31
- sync.('pull')
32
- end]
33
- cmd << ws.task_name('build')
34
- Common::Utils.task_invoke(*cmd, **ws.invokeargs)
34
+ ws.series.sync << all
35
+ ws.series.multiple << all
35
36
  end
36
- ws.series.sync << name
37
- ws.series.multiple << name
38
37
  end
39
38
 
40
39
  def tasks
@@ -63,7 +62,8 @@ module Squared
63
62
  refs: %i[heads tags].freeze,
64
63
  reset: %i[head soft mixed hard merge keep submodules].freeze,
65
64
  restore: %i[worktree staged overlay].freeze,
66
- rev: %i[commit branch].freeze
65
+ rev: %i[commit branch].freeze,
66
+ show: %i[oneline pretty format].freeze
67
67
  }.freeze
68
68
 
69
69
  def initialize(*, **)
@@ -200,6 +200,21 @@ module Squared
200
200
  reset(flag, ref: args.ref)
201
201
  end
202
202
  end
203
+ when :show
204
+ if flag == :oneline
205
+ desc format_desc(action, flag, 'object+')
206
+ task flag, [:object] do |_, args|
207
+ objs = guard_params(action, flag, args: args.to_a)
208
+ show(objs, pretty: 'oneline', abbrev: true)
209
+ end
210
+ else
211
+ desc format_desc(action, flag, 'format,object+')
212
+ task flag, [:format, :object] do |_, args|
213
+ format = guard_params(action, flag, args: args, key: :format)
214
+ objs = guard_params(action, flag, args: args.to_a[1..-1] || [])
215
+ show(objs, "#{flag}": format)
216
+ end
217
+ end
203
218
  end
204
219
  end
205
220
  end
@@ -220,7 +235,13 @@ module Squared
220
235
  cmd << '--commit'
221
236
  end
222
237
  append_pull opts, OPT_PULL, flag
223
- source(sync: sync, **threadargs)
238
+ sub = if verbose
239
+ [
240
+ { pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: :red, index: 4 },
241
+ { pat: /^(.+)(\|\s+\d+\s+)(\++)(-*)(.*)$/, styles: :green, index: 3 }
242
+ ]
243
+ end
244
+ source(sync: sync, sub: sub, **threadargs)
224
245
  end
225
246
 
226
247
  def rebase
@@ -399,17 +420,17 @@ module Squared
399
420
  raise_error('commit', 'pathspec', hint: 'missing') if (files = projectmap(files)).empty?
400
421
  "-- #{files.join(' ')}"
401
422
  end
402
- unless push?
403
- source('git branch -vv --list', io: true, banner: false).first.each do |val|
404
- origin = %r{^\* [^\[]+(?<= )\[([\w.-/]+?)/([\w.-]+)\] }.match(val)
405
- next unless origin
406
-
407
- @origin = origin[1]
408
- @branch = origin[2]
409
- break
410
- end
423
+ origin = nil
424
+ branch = nil
425
+ source('git fetch --no-tags --quiet', io: true, banner: false)
426
+ source('git branch -vv --list', io: true, banner: false).first.each do |val|
427
+ next unless (data = %r{^\* [^\[]+(?<= )\[([\w.-/]+?)/([\w.-]+)\] }.match(val))
428
+
429
+ origin = data[1]
430
+ branch = data[2]
431
+ break
411
432
  end
412
- raise_error('commit', 'work tree is not usable') unless push?
433
+ raise_error('commit', 'work tree is not usable') unless origin && branch
413
434
  cmd = git_session 'commit'
414
435
  cmd << '--dry-run' if option('dry-run')
415
436
  if amend
@@ -433,7 +454,7 @@ module Squared
433
454
  b << @origin << @branch
434
455
  puts if pass
435
456
  source a.join(' ')
436
- source
457
+ source cmd
437
458
  source b.join(' ')
438
459
  end
439
460
 
@@ -444,9 +465,31 @@ module Squared
444
465
  source(stdout: true)
445
466
  end
446
467
 
468
+ def show(objs, pretty: nil, format: nil, abbrev: nil)
469
+ cmd = git_session 'show'
470
+ case (flag = pretty&.downcase)
471
+ when 'oneline', 'short', 'medium', 'full', 'fuller', 'reference', 'email', 'raw'
472
+ cmd << "--pretty=#{flag}"
473
+ else
474
+ if pretty
475
+ cmd << "--pretty=#{shell_escape("tformat:#{pretty}", quote: true)}"
476
+ elsif format
477
+ cmd << "--format=#{shell_escape(format, quote: true)}"
478
+ end
479
+ end
480
+ if (abbrev ||= option('abbrev')) == true
481
+ cmd << '--abbrev-commit'
482
+ elsif abbrev.to_i > 0
483
+ cmd << "--abbrev=#{abbrev}"
484
+ end
485
+ append_value objs
486
+ source(exception: false)
487
+ end
488
+
447
489
  private
448
490
 
449
- def source(cmd = @session, exception: true, io: false, sync: true, stdout: false, stderr: false, banner: true)
491
+ def source(cmd = @session, exception: true, io: false, sync: true, stdout: false, stderr: false, banner: true,
492
+ sub: nil)
450
493
  cmd = session_done(cmd)
451
494
  log.info cmd
452
495
  banner = format_banner(cmd.gsub(File.join(path, ''), ''), banner: banner)
@@ -469,11 +512,12 @@ module Squared
469
512
  require 'open3'
470
513
  if stderr
471
514
  Open3.popen3(cmd) do |_, out, err|
472
- ret = write_lines(out, banner: banner, pass: true)
515
+ ret = write_lines(out, banner: banner, sub: sub, pass: true)
473
516
  if ret == 0
474
- write_lines(err, banner: banner)
517
+ ret = write_lines(err, banner: banner)
518
+ puts 'Success' if ret == 0 && banner && !stdin?
475
519
  else
476
- write_lines(err, loglevel: ::Logger::DEBUG)
520
+ write_lines(err, loglevel: Logger::DEBUG)
477
521
  end
478
522
  end
479
523
  else
@@ -484,15 +528,15 @@ module Squared
484
528
  log.error e
485
529
  raise if exception
486
530
 
487
- warn log_message(::Logger::WARN, e) if warning?
531
+ warn log_message(Logger::WARN, e) if warning?
488
532
  end
489
533
  end
490
534
 
491
535
  def write_lines(data, banner: nil, loglevel: nil, grep: nil, sub: nil, pass: false)
492
- grep = Regexp.new(grep == '*' ? '.+' : grep) if grep.is_a?(::String)
536
+ grep = Regexp.new(grep == '*' ? '.+' : grep) if grep.is_a?(String)
493
537
  sub = nil if stdin?
494
538
  ret = 0
495
- lines = []
539
+ out = []
496
540
  data.each do |line|
497
541
  next if grep && !line.match?(grep)
498
542
 
@@ -501,14 +545,14 @@ module Squared
501
545
  else
502
546
  sub&.each { |h| line = sub_style(line, **h) }
503
547
  if banner
504
- lines << line
548
+ out << line
505
549
  else
506
550
  puts line
507
551
  end
508
552
  end
509
553
  ret += 1
510
554
  end
511
- print_item banner, lines if banner && (ret > 0 || !pass)
555
+ print_item banner, out if banner && (ret > 0 || !pass)
512
556
  ret
513
557
  end
514
558
 
@@ -577,26 +621,18 @@ module Squared
577
621
  end
578
622
  end
579
623
 
580
- def append_option(list)
581
- list.each { |val| @session << "--#{val}" if option(val) }
582
- end
583
-
584
624
  def git_session(*cmd)
585
625
  session('git', *cmd)
586
626
  end
587
627
 
588
- def gitpath
589
- basepath('.git')
590
- end
591
-
592
- def push?
593
- !@origin.nil? && !@branch.nil?
594
- end
595
-
596
628
  def dry_run?
597
629
  @session.include?('--dry-run')
598
630
  end
599
631
 
632
+ def gitpath
633
+ basepath('.git')
634
+ end
635
+
600
636
  def threadargs
601
637
  { stderr: true, exception: exception || !workspace.series.multiple? }
602
638
  end
@@ -74,7 +74,7 @@ module Squared
74
74
  else
75
75
  cmd = guard_params(action, 'command', args: args.to_a)
76
76
  cmd.each do |val|
77
- if (data = indexdata(val))
77
+ if (data = indexitem(val))
78
78
  n, opts = data
79
79
  list = read_scripts
80
80
  if (item = list[n - 1])
@@ -117,52 +117,85 @@ module Squared
117
117
  end
118
118
  end
119
119
 
120
- def copy(from: 'build', glob: nil, into: 'node_modules', scope: nil, also: nil, override: false)
120
+ def copy(from: 'build', into: 'node_modules', workspace: false, include: nil, exclude: nil, scope: nil,
121
+ also: nil, create: nil, override: false)
121
122
  return if @copy == false
122
123
 
123
124
  if @copy && !override
124
125
  return super if runnable?(@copy)
125
126
 
126
127
  from = @copy[:from] if @copy.key?(:from)
127
- glob = @copy[:glob] if @copy.key?(:glob)
128
128
  into = @copy[:into] if @copy.key?(:into)
129
- scope = @copy[:scope] if @copy.key?(:scope)
130
- also = @copy[:also] if @copy.key?(:also)
129
+ workspace = @copy[:workspace] if @copy.key?(:workspace)
130
+ glob = @copy[:include]
131
+ pass = @copy[:exclude]
132
+ scope = @copy[:scope]
133
+ also = @copy[:also]
134
+ create = @copy[:create]
131
135
  end
132
- items = [path != workspace.home && workspace.home? ? workspace.home : nil]
136
+ items = []
137
+ items << @workspace.home if build? && path != @workspace.home && @workspace.home?
133
138
  items += as_a(also) if also
134
- items.each_with_index do |dir, i|
135
- if i == 0
136
- next unless dev? && build?
139
+ return if items.empty?
137
140
 
141
+ print_item unless @output[0] || !verbose || task_invoked?(/^copy(?::#{Node.ref}|$)/)
142
+ items.each do |dir|
143
+ case dir
144
+ when Pathname
138
145
  dest = dir
146
+ when String
147
+ dest = @workspace.rootpath(dir)
148
+ when Symbol
149
+ dest = @workspace.find(name: dir)&.path
150
+ log.warn message("copy project :#{dir}", hint: 'not found') unless dest
151
+ when Hash
152
+ glob = dir[:include]
153
+ pass = dir[:exclude]
154
+ from = dir[:from] if dir.key?(:from)
155
+ into = dir[:into] if dir.key?(:into)
156
+ scope = dir[:scope] if dir.key?(:scope)
157
+ dest = dir[:target]
158
+ create = dir[:create]
159
+ workspace = dir[:workspace]
160
+ dest = items.first unless dest && dest != true
161
+ when Project::Base
162
+ dest = dir.path
139
163
  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
164
+ raise_error("given: #{dir}", hint: 'unknown')
158
165
  end
159
166
  next unless from && dest&.directory?
160
167
 
161
168
  from = basepath(from)
162
- dest = dest.join(into, scope || project)
163
169
  glob = as_a(glob || '**/*')
164
- glob.each { |val| log.info "cp #{from.join(val)} #{dest}" }
165
- copy_d(from, dest, glob: glob, verbose: verbose)
170
+ target = []
171
+ if workspace
172
+ Dir.glob(from.join('*')).each do |path|
173
+ next unless (path = Pathname.new(path)).directory?
174
+
175
+ sub = if (proj = @workspace.find(path))
176
+ proj.packagename
177
+ elsif (file = path.join('package.json')).exist?
178
+ begin
179
+ doc = JSON.parse(file.read)
180
+ doc['name']
181
+ rescue StandardError => e
182
+ log.warn e
183
+ raise if exception
184
+ end
185
+ end
186
+ if sub
187
+ target << [path, dest.join(into, sub)]
188
+ else
189
+ log.debug message("package.json in \"#{path}\"", hint: 'not found')
190
+ end
191
+ end
192
+ else
193
+ target << [from, dest.join(into, scope || project)]
194
+ end
195
+ target.each do |src, to|
196
+ glob.each { |val| log.info "cp #{from.join(val)} #{to}" }
197
+ copy_d(src, to, glob: glob, create: create, pass: pass, verbose: verbose)
198
+ end
166
199
  end
167
200
  end
168
201
 
@@ -233,10 +266,10 @@ module Squared
233
266
  dryrun = opts.include?('dry-run')
234
267
  if pnpm? && read_packagemanager(version: '7.15')
235
268
  cmd = 'pnpm outdated'
236
- dryrun ||= !option('dry-run', prefix: 'pnpm').nil?
269
+ dryrun ||= dryrun?('pnpm')
237
270
  else
238
271
  cmd = 'npm outdated'
239
- dryrun ||= !option('dry-run', prefix: 'npm').nil?
272
+ dryrun ||= dryrun?('npm')
240
273
  end
241
274
  log.info cmd
242
275
  banner = format_banner("#{cmd}#{dryrun ? ' --dry-run' : ''}")
@@ -255,7 +288,7 @@ module Squared
255
288
  inter = opts.include?('interactive')
256
289
  unless data.empty?
257
290
  JSON.parse(data).each_pair do |key, val|
258
- val = val.find { |obj| obj['dependent'] == json['name'] } if val.is_a?(::Array)
291
+ val = val.find { |obj| obj['dependent'] == json['name'] } if val.is_a?(Array)
259
292
  next unless val && (file = dep1[key] || dep2[key]) && file != '*'
260
293
 
261
294
  latest = val['latest']
@@ -271,8 +304,8 @@ module Squared
271
304
  want = rev == :major && (ver = latest.match(SEM_VER)) && !ver[6] ? latest : val['wanted']
272
305
  next unless (val['current'] != want || file != want) && (want.match?(SEM_VER) || !file.match?(SEM_VER))
273
306
 
274
- f = semver(semscan(file))
275
- w = semver(semscan(want))
307
+ f = semscan(file)
308
+ w = semscan(want)
276
309
  a = f[0]
277
310
  b = f[2]
278
311
  c = w[0]
@@ -356,9 +389,9 @@ module Squared
356
389
  if dryrun || (modified == 0 && pending > 0)
357
390
  footer.(modified)
358
391
  elsif modified > 0
359
- File.write(dependfile, doc)
360
392
  modified = -1
361
393
  footer.()
394
+ File.write(dependfile, doc)
362
395
  commit(:add, ['package.json'], pass: true)
363
396
  install if opts.include?('prune')
364
397
  end
@@ -384,30 +417,10 @@ module Squared
384
417
  end
385
418
  end
386
419
 
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)
420
+ def bump(flag = nil, sync: invoked_sync?('bump', flag))
408
421
  return unless (ver = version)
409
422
 
410
- seg = semscan(ver)
423
+ seg = semscan(ver, fill: false)
411
424
  case flag
412
425
  when :major
413
426
  if seg[0] != '0' || seg[2].nil?
@@ -421,45 +434,51 @@ module Squared
421
434
  else
422
435
  seg[2] = seg[2].succ
423
436
  end
424
- when :patch
437
+ else
425
438
  seg[4] &&= seg[4].succ
426
439
  end
427
- unless (out = seg.join) == ver
428
- begin
429
- doc = dependfile.read
430
- if doc.sub!(/"version"\s*:\s*"#{ver}"/, "\"version\": \"#{out}\"")
440
+ return if (out = seg.join) == ver
441
+
442
+ begin
443
+ doc = dependfile.read
444
+ if doc.sub!(/"version"\s*:\s*"#{ver}"/, "\"version\": \"#{out}\"")
445
+ unless dryrun?
431
446
  dependfile.write(doc)
432
447
  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
448
  end
446
- rescue StandardError => e
447
- log.debug e
448
- raise
449
+ if verbose
450
+ major = flag == :major
451
+ emphasize("version: #{out}", title: name, border: borderstyle, sub: [
452
+ headerstyle,
453
+ { pat: /^(version:)( )(\S+)(.*)$/, styles: color(major ? :green : :yellow), index: 3 },
454
+ { pat: /^(version:)(.*)$/, styles: theme[major ? :major : :active] }
455
+ ])
456
+ elsif stdin?
457
+ puts out
458
+ end
459
+ else
460
+ raise_error('not found', hint: 'version')
449
461
  end
462
+ rescue StandardError => e
463
+ log.debug e
464
+ raise if sync
450
465
  end
451
466
  end
452
467
 
453
- def version
454
- read_packagemanager
455
- @pm[:version]
456
- end
457
-
458
- def dependtype(prog)
459
- return @pm[prog] if @pm.key?(prog)
468
+ def compose(opts, flags = nil, script: false)
469
+ return unless opts && script
460
470
 
461
- meth = :"#{prog}?"
462
- respond_to?(meth) && __send__(meth) ? @pm[prog] : 0
471
+ ret = session dependbin, 'run', flags
472
+ append_loglevel
473
+ case opts
474
+ when Enumerable
475
+ ret += opts.to_a
476
+ when String
477
+ ret << opts
478
+ else
479
+ raise_error("#{ret.first} script name", hint: opts.nil? ? 'missing' : 'invalid')
480
+ end
481
+ ret
463
482
  end
464
483
 
465
484
  def depend?
@@ -467,7 +486,7 @@ module Squared
467
486
  end
468
487
 
469
488
  def copy?
470
- super || @copy.is_a?(::Hash)
489
+ super || @copy.is_a?(Hash)
471
490
  end
472
491
 
473
492
  def outdated?
@@ -475,8 +494,8 @@ module Squared
475
494
  end
476
495
 
477
496
  def yarn?
478
- (@pm[:yarn] ||= if basepath('yarn.lock', ascend: find_package).exist?
479
- if (rc = basepath('.yarnrc.yml', ascend: find_package)).exist?
497
+ (@pm[:yarn] ||= if basepath('yarn.lock', ascend: dependext).exist?
498
+ if (rc = basepath('.yarnrc.yml', ascend: dependext)).exist?
480
499
  begin
481
500
  require 'yaml'
482
501
  doc = YAML.load_file(rc)
@@ -495,10 +514,10 @@ module Squared
495
514
  end
496
515
 
497
516
  def pnpm?
498
- (@pm[:pnpm] ||= if basepath('pnpm-lock.yaml', ascend: find_package).exist?
517
+ (@pm[:pnpm] ||= if basepath('pnpm-lock.yaml', ascend: dependext).exist?
499
518
  begin
500
519
  require 'yaml'
501
- doc = YAML.load_file(basepath('node_modules/.modules.yaml', ascend: find_package))
520
+ doc = YAML.load_file(basepath('node_modules/.modules.yaml', ascend: dependext))
502
521
  @pm[:_] = doc['packageManager']
503
522
  case doc['nodeLinker']
504
523
  when 'hoisted'
@@ -521,24 +540,42 @@ module Squared
521
540
  basepath('pnpm-workspace.yaml').exist?
522
541
  else
523
542
  read_packagemanager
524
- @pm[:workspaces].is_a?(::Array)
543
+ @pm[:workspaces].is_a?(Array)
525
544
  end
526
545
  end
527
546
 
528
547
  def dev?
529
- !Node.prod? && super
548
+ super && (!Node.prod? || (@dev == true && !prod?))
530
549
  end
531
550
 
532
551
  def prod?
533
552
  @prod != false && (Node.prod? || super)
534
553
  end
535
554
 
555
+ def dependtype(prog)
556
+ return @pm[prog] if @pm.key?(prog)
557
+
558
+ meth = :"#{prog}?"
559
+ respond_to?(meth) && __send__(meth) ? @pm[prog] : 0
560
+ end
561
+
562
+ def version
563
+ read_packagemanager
564
+ @pm[:version]
565
+ end
566
+
567
+ def packagename
568
+ read_packagemanager
569
+ @pm[:name]
570
+ end
571
+
536
572
  private
537
573
 
538
574
  def read_packagemanager(version: nil)
539
575
  if @pm[:_].nil?
540
576
  doc = JSON.parse(dependfile.read)
541
577
  @pm[:_] = (val = doc['packageManager']) ? val[0..(val.index('+') || 0) - 1] : false
578
+ @pm[:name] = doc['name']
542
579
  @pm[:scripts] = doc['scripts']
543
580
  @pm[:version] = doc['version']
544
581
  @pm[:workspaces] = doc['workspaces']
@@ -560,7 +597,7 @@ module Squared
560
597
 
561
598
  def read_scripts
562
599
  read_packagemanager
563
- @pm[:scripts].is_a?(::Hash) ? @pm[:scripts].to_a : []
600
+ @pm[:scripts].is_a?(Hash) ? @pm[:scripts].to_a : []
564
601
  end
565
602
 
566
603
  def append_loglevel
@@ -605,12 +642,24 @@ module Squared
605
642
  'PATCH'
606
643
  end, styles: theme[:header])
607
644
  b = sub_style("#{pkg} #{ver}", styles: theme[:inline])
608
- c, d = rev == 1 || lock ? %w[y/N N] : %w[Y/n Y]
645
+ c, d = rev == 1 || lock ? ['y/N', 'N'] : ['Y/n', 'Y']
609
646
  e = lock ? " #{sub_style('(locked)', styles: color(:red))}" : ''
610
647
  Common::Prompt.confirm("Upgrade to #{a}? #{b}#{e} [#{c}] ", d, timeout: 60)
611
648
  end
612
649
 
613
- def find_package
650
+ def dryrun?(prefix = dependbin)
651
+ !option('dry-run', prefix: prefix).nil?
652
+ end
653
+
654
+ def dependbin
655
+ if yarn?
656
+ 'yarn'
657
+ else
658
+ pnpm? ? 'pnpm' : 'npm'
659
+ end
660
+ end
661
+
662
+ def dependext
614
663
  'package.json' if parent&.has?('outdated', Node.ref)
615
664
  end
616
665
  end