squared 0.5.1 → 0.5.3

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.
@@ -94,6 +94,7 @@ module Squared
94
94
  subtasks({
95
95
  'build' => %i[tag context bake].freeze,
96
96
  'compose' => %i[build run exec up].freeze,
97
+ 'bake' => %i[build check].freeze,
97
98
  'image' => %i[list rm push tag save].freeze,
98
99
  'container' => %i[run create exec update commit inspect diff start stop restart pause unpause top stats kill
99
100
  rm].freeze,
@@ -112,7 +113,6 @@ module Squared
112
113
  @mounts = mounts
113
114
  @secrets = secrets
114
115
  @registry = tagjoin registry, kwargs[:username]
115
- @file = nil
116
116
  initialize_ref Docker.ref
117
117
  initialize_logger(**kwargs)
118
118
  initialize_env(**kwargs)
@@ -129,12 +129,12 @@ module Squared
129
129
 
130
130
  namespace name do
131
131
  Docker.subtasks do |action, flags|
132
- next if @pass.include?(action)
132
+ next if task_pass?(action)
133
133
 
134
134
  namespace action do
135
135
  flags.each do |flag|
136
136
  case action
137
- when 'build'
137
+ when 'build', 'bake'
138
138
  case flag
139
139
  when :tag, :context
140
140
  format_desc(action, flag, 'opts*', before: flag == :tag ? 'name' : 'dir')
@@ -142,16 +142,26 @@ module Squared
142
142
  param = param_guard(action, flag, args: args, key: flag)
143
143
  buildx(:build, args.extras, "#{flag}": param)
144
144
  end
145
- when :bake
145
+ when :bake, :build
146
+ next unless bake?
147
+
146
148
  format_desc action, flag, ':?,opts*,target*,context?'
147
149
  task flag do |_, args|
148
150
  args = args.to_a
149
151
  if args.first == ':'
150
152
  choice_command :bake
151
153
  else
152
- buildx flag, args
154
+ buildx :bake, args
153
155
  end
154
156
  end
157
+ when :check
158
+ next unless bake?
159
+
160
+ format_desc action, flag, 'target'
161
+ task flag, [:target] do |_, args|
162
+ target = param_guard(action, flag, args: args, key: :target)
163
+ buildx :bake, ['allow=fs.read=*', 'call=check', target]
164
+ end
155
165
  end
156
166
  when 'compose'
157
167
  case flag
@@ -266,7 +276,6 @@ module Squared
266
276
  when Enumerable
267
277
  ret.merge(opts.to_a)
268
278
  end
269
-
270
279
  [args, flags].each_with_index do |target, index|
271
280
  if (data = append_any(target, target: []))
272
281
  ret.merge(data.map { |arg| index == 0 ? fill_option(arg) : quote_option('build-arg', arg) })
@@ -307,7 +316,7 @@ module Squared
307
316
  op.parse(OPT_DOCKER[:buildx][flag == :bake ? :bake : :build] + OPT_DOCKER[:buildx][:shared])
308
317
  case flag
309
318
  when :build, :context
310
- append_tag(tag || option('tag', ignore: false) || @tag)
319
+ append_tag(tag || option('tag', ignore: false) || self.tag)
311
320
  append_context context
312
321
  when :bake
313
322
  unless op.empty?
@@ -317,7 +326,7 @@ module Squared
317
326
  if projectpath?(val = args.pop)
318
327
  context = val
319
328
  else
320
- op.extras << val
329
+ op.push(val)
321
330
  end
322
331
  end
323
332
  op.append(args, escape: true)
@@ -573,12 +582,7 @@ module Squared
573
582
  case flag
574
583
  when :run
575
584
  unless session_arg?('name', target: target)
576
- target << basic_option('name', dnsname("#{name}_%s" % if RUBY_VERSION >= '3.1'
577
- require 'random/formatter'
578
- Random.new.alphanumeric(6)
579
- else
580
- (0...6).map { rand(97..122).chr }.join
581
- end))
585
+ target << basic_option('name', dnsname("#{name}_%s" % rand_s(6)))
582
586
  end
583
587
  when :exec
584
588
  raise_error('no command args', hint: from) if list.empty?
@@ -680,11 +684,7 @@ module Squared
680
684
  puts log_message(Logger::INFO, 'none detected', subject: "#{name}:#{from}", hint: hint) if found || y
681
685
  end
682
686
  rescue StandardError => e
683
- log.error e
684
- ret = on :error, from, e
685
- raise if exception && ret != true
686
-
687
- warn log_message(Logger::WARN, e, pass: true) if warning?
687
+ on_error e, from
688
688
  end
689
689
 
690
690
  def confirm_command(*args, title: nil, target: nil, as: nil)
@@ -741,7 +741,7 @@ module Squared
741
741
  cmd = docker_output ctx
742
742
  case flag
743
743
  when :tag
744
- args = tagjoin @registry, @tag
744
+ args = tagjoin @registry, tag
745
745
  when :save
746
746
  opts = "#{opts}.tar" unless opts.end_with?('.tar')
747
747
  cmd << quote_option('output', File.expand_path(opts))
@@ -752,11 +752,7 @@ module Squared
752
752
  else
753
753
  cmd << opts << '--'
754
754
  end
755
- cmd.merge(if out.is_a?(Array)
756
- out.map! { |val| parse.call(val) }
757
- else
758
- [parse.call(out)]
759
- end)
755
+ cmd.merge(Array(out).map! { |val| parse.call(val) })
760
756
  cmd << args
761
757
  print_success if success?(run(cmd)) && ctx.start_with?(/(?:network|tag|save)/)
762
758
  end
@@ -3,7 +3,7 @@
3
3
  module Squared
4
4
  module Workspace
5
5
  module Git
6
- GIT_REPO = {}
6
+ GIT_REPO = Support.hashobj
7
7
  GIT_PROTO = %r{^(?:https?|ssh|git|file)://}i.freeze
8
8
  private_constant :GIT_REPO, :GIT_PROTO
9
9
 
@@ -58,8 +58,8 @@ module Squared
58
58
  end
59
59
  end
60
60
  key = task_name key
61
- (GIT_REPO[main] ||= {})[key] = [uri.to_s, opts]
62
- (@kind[key] ||= []) << Project::Git
61
+ GIT_REPO[main][key] = [uri.to_s, opts]
62
+ @kind[key] << Project::Git
63
63
  end
64
64
  if cache == true
65
65
  revbuild
@@ -181,6 +181,9 @@ module Squared
181
181
  }.freeze,
182
182
  git: {
183
183
  add: %w[N|intent-to-add refresh].freeze,
184
+ blame: %w[b c l s t w C=im? L=q M=im? S=p color-by-age color-lines first-parent incremental line-porcelain
185
+ p|porcelain root score-debug f|show-name e|show-email n|show-number show-stats abbrev=i
186
+ contents=p date=q encoding=b ignore-rev=b ignore-revs-file=p reverse=q].freeze,
184
187
  clean: %w[d x X f|force n|dry-run i|interactive q|quiet e|exclude=q].freeze,
185
188
  mv: %w[k f|force n|dry-run v|verbose].freeze,
186
189
  revert: %w[e S=bm? abort continue n|no-commit quit reference skip cleanup=b gpg-sign=b? m|mainline=i
@@ -248,6 +251,7 @@ module Squared
248
251
  tag: %w[n=im cleanup=b create-reflog i|ignore-case omit-empty color=b? column=b contains=b? format=q merged=b?
249
252
  no-contains=b? no-merged=b? points-at=q sort=q trailer=q].freeze,
250
253
  no: {
254
+ blame: %w[progress].freeze,
251
255
  branch: %w[color color-moved column track].freeze,
252
256
  checkout: %w[overwrite-ignore guess overlay progress recurse-submodules track].freeze,
253
257
  fetch: {
@@ -333,7 +337,7 @@ module Squared
333
337
  'diff' => %i[head branch files view between contain].freeze,
334
338
  'fetch' => %i[origin remote].freeze,
335
339
  'files' => %i[cached modified deleted others].freeze,
336
- 'git' => %i[add clean mv revert rm].freeze,
340
+ 'git' => %i[add blame clean mv revert rm].freeze,
337
341
  'log' => %i[view between contain].freeze,
338
342
  'merge' => %i[commit no-commit send].freeze,
339
343
  'pull' => %i[origin remote].freeze,
@@ -363,7 +367,7 @@ module Squared
363
367
 
364
368
  namespace name do
365
369
  Git.subtasks do |action, flags|
366
- next if @pass.include?(action)
370
+ next if task_pass?(action)
367
371
 
368
372
  namespace action do
369
373
  flags.each do |flag|
@@ -399,12 +403,12 @@ module Squared
399
403
  if flag == :fixup
400
404
  ref, squash, pick = choice_commit(accept: [['Auto squash?', true]], reflog: false,
401
405
  values: ['Pick [amend|reword]'])
402
- pick = case pick&.downcase
403
- when 'a', 'amend'
404
- 'amend'
405
- when 'r', 'reword'
406
- 'reword'
407
- end
406
+ pick &&= case pick.downcase
407
+ when 'a', 'amend'
408
+ 'amend'
409
+ when 'r', 'reword'
410
+ 'reword'
411
+ end
408
412
  if squash
409
413
  found = false
410
414
  git_spawn(git_output('log --format=%h'), stdout: false).each do |val|
@@ -416,12 +420,14 @@ module Squared
416
420
  end
417
421
  end
418
422
  end
419
- refs = pick == 'reword' ? [] : param_guard(action, flag, args: args.to_a)
420
- if flag == :add
421
- opts = refs
422
- refs = []
423
- else
424
- opts = []
423
+ opts = []
424
+ refs = []
425
+ unless pick == 'reword'
426
+ if flag == :add
427
+ opts = param_guard(action, flag, args: args.to_a)
428
+ elsif (refs = args.to_a).empty?
429
+ refs = readline('Enter file patterns', force: true).shellsplit
430
+ end
425
431
  end
426
432
  commit(flag, opts, refs: refs, ref: ref, squash: squash, pick: pick)
427
433
  end
@@ -860,19 +866,14 @@ module Squared
860
866
  args = args.to_a
861
867
  if args.empty? || args.last == ':'
862
868
  files = []
863
- status_data.each do |line|
864
- case (flag == :staged ? line[2] : line[1])
865
- when /[AMDRTC]/
866
- files << line[0]
867
- end
868
- end
869
+ status_data.each { |row| files << row[0] if row[flag == :staged ? 2 : 1].match?(/[AMDRTC]/) }
869
870
  unless files.empty?
870
871
  files = choice_index('Select a file', files, multiple: true, force: false,
871
872
  accept: 'Restore?')
872
873
  end
873
874
  args.pop
874
875
  args, glob = args.partition { |val| val.match?(/^(?:[a-z-]+=|[^*]+$)/) }
875
- (files ||= []).concat(glob)
876
+ files.concat(glob)
876
877
  next if args.empty? && files.empty?
877
878
  end
878
879
  restore(flag, args, files: files)
@@ -880,10 +881,11 @@ module Squared
880
881
  end
881
882
  when 'git'
882
883
  before = case flag
884
+ when :blame then 'file'
883
885
  when :mv then 'source+,destination'
884
886
  when :revert then 'commit+' end
885
887
  format_desc(action, flag, 'opts*', before: before, after: case flag
886
- when :add then 'pathspec*|:pattern:*'
888
+ when :add then 'pathspec*,:pattern:*'
887
889
  when :clean, :rm then 'pathspec*' end)
888
890
  task flag do |_, args|
889
891
  git flag, args.to_a
@@ -1144,10 +1146,7 @@ module Squared
1144
1146
  rescue StandardError => e
1145
1147
  warn log_message(Logger::WARN, e, pass: true) if warning?
1146
1148
  else
1147
- if verbose
1148
- msg = sub_style('completed', styles: theme[:active])
1149
- puts log_message(Logger::INFO, name, msg, subject: 'revbuild', hint: time_format(epochtime - start))
1150
- end
1149
+ print_status(name, subject: 'revbuild', start: start, from: :completed)
1151
1150
  workspace.rev_write(name, { 'revision' => sha, 'files' => status_digest(*args, **kwargs) },
1152
1151
  sync: sync, utc: 'build')
1153
1152
  end
@@ -1625,10 +1624,16 @@ module Squared
1625
1624
 
1626
1625
  def git(flag, opts = [])
1627
1626
  cmd, opts = git_session(flag, opts: opts)
1628
- list = OPT_GIT[:git].fetch(flag, []) + OPT_GIT.fetch(flag, [])
1629
- op = OptionPartition.new(opts, list, cmd, project: self, no: OPT_GIT[:no][flag],
1630
- first: flag == :revert ? nil : matchpathspec)
1627
+ op = OptionPartition.new(opts, OPT_GIT[:git].fetch(flag, []) + OPT_GIT.fetch(flag, []), cmd,
1628
+ project: self, no: OPT_GIT[:no][flag], first: case flag
1629
+ when :blame, :revert
1630
+ nil
1631
+ else matchpathspec end)
1631
1632
  case flag
1633
+ when :blame
1634
+ raise_error 'no file found' unless (n = op.index { |s| (path + s).file? })
1635
+ op << '--' << shell_quote(path + op.delete_at(n))
1636
+ op.clear
1632
1637
  when :revert
1633
1638
  if VAL_GIT[:rebase][:send].any? { |val| op.arg?(val) }
1634
1639
  op.clear
@@ -1639,14 +1644,13 @@ module Squared
1639
1644
  end
1640
1645
  when :add, :clean
1641
1646
  if flag == :add && !op.arg?('pathspec-from-file')
1642
- grep, list = op.extras.partition { |val| val.start_with?(':') && val.end_with?(':') }
1643
- if list.empty? || !grep.empty?
1644
- red = color(:red)
1647
+ grep, list = op.partition { |val| val.start_with?(':') && val.end_with?(':') }
1648
+ unless grep.empty? && !list.empty?
1645
1649
  grep.map! { |val| Regexp.new(val[1..-2]) }
1646
1650
  files = status_data.map! do |a, b|
1647
1651
  next if b.strip.empty? || (!grep.empty? && grep.none? { |pat| pat.match?(a) })
1648
1652
 
1649
- "#{sub_style(b, styles: red)} #{a}"
1653
+ "#{sub_style(b, styles: color(:red))} #{a}"
1650
1654
  end
1651
1655
  .compact
1652
1656
  unless files.empty?
@@ -1743,11 +1747,7 @@ module Squared
1743
1747
  end
1744
1748
  end
1745
1749
  rescue StandardError => e
1746
- log&.error e
1747
- ret = on :error, from, e
1748
- raise if exception && ret != true
1749
-
1750
- warn log_message(Logger::WARN, e, pass: true) if warning?
1750
+ on_error(e, from, pass: true)
1751
1751
  nil
1752
1752
  else
1753
1753
  on :last, from
@@ -121,7 +121,7 @@ module Squared
121
121
 
122
122
  namespace name do
123
123
  Node.subtasks do |action, flags|
124
- next if @pass.include?(action)
124
+ next if task_pass?(action)
125
125
 
126
126
  if flags.nil?
127
127
  case action
@@ -269,6 +269,11 @@ module Squared
269
269
  otp = args.first
270
270
  else
271
271
  tag, otp = param_guard(action, flag, args: args)
272
+ unless SEM_VER.match?(tag)
273
+ a = sub_style(project, styles: theme[:active])
274
+ b = sub_style(tag, styles: theme[:inline])
275
+ exit 1 unless confirm("Publish #{a}@#{b}?", 'N')
276
+ end
272
277
  end
273
278
  publish(flag, otp: otp, tag: tag, dryrun: dryrun, access: access)
274
279
  end
@@ -280,7 +285,7 @@ module Squared
280
285
  end
281
286
  end
282
287
 
283
- def copy(from: 'build', into: 'node_modules', scope: nil, also: nil, create: nil, workspace: false,
288
+ def copy(from: 'build', into: 'node_modules', scope: nil, also: nil, create: nil, files: nil, workspace: false,
284
289
  link: false, force: false, override: false, sync: invoked_sync?('copy'), **kwargs)
285
290
  glob = kwargs[:include]
286
291
  pass = kwargs[:exclude]
@@ -289,6 +294,7 @@ module Squared
289
294
 
290
295
  from = @copy[:from] if @copy.key?(:from)
291
296
  into = @copy[:into] if @copy.key?(:into)
297
+ files = @copy[:files] if @copy.key?(:files)
292
298
  workspace = @copy[:workspace] if @copy.key?(:workspace)
293
299
  link = @copy[:link] if @copy.key?(:link)
294
300
  force = @copy[:force] if @copy.key?(:force)
@@ -310,6 +316,7 @@ module Squared
310
316
 
311
317
  on :first, :copy
312
318
  print_item unless @output[0] || !verbose || task_invoked?(/^copy(?::#{Node.ref}|$)/)
319
+ packed = false
313
320
  items.each do |dir|
314
321
  case dir
315
322
  when Pathname
@@ -347,9 +354,49 @@ module Squared
347
354
  end
348
355
  next unless from && dest&.directory?
349
356
 
350
- from = path + from
357
+ if from == :npm
358
+ begin
359
+ unless packed
360
+ require 'open3'
361
+ files = pwd_set do
362
+ Open3.capture2e(session_output('npm', 'pack --dry-run --no-color', npmname).to_s)
363
+ .first
364
+ .scan(/^npm notice \d+(?:\.\d+)?[a-z]+ (.+)$/i)
365
+ .map { |item| Pathname.new(item.first) }
366
+ .select(&:exist?)
367
+ end
368
+ .concat(Array(files))
369
+ packed = true
370
+ end
371
+ to = dest.join(into, npmname)
372
+ to.mkpath
373
+ log.info "cp npm:#{npmname} #{to}"
374
+ subdir = []
375
+ errors = 0
376
+ files.each do |file|
377
+ s, d = file.is_a?(Array) ? file : [file, file]
378
+ dest = to + d
379
+ unless subdir.include?((target = dest.dirname).to_s)
380
+ target.mkpath
381
+ subdir << target.to_s
382
+ end
383
+ begin
384
+ FileUtils.cp(path + s, dest, verbose: verbose.is_a?(Numeric) && verbose > 0)
385
+ rescue StandardError => e
386
+ print_error e
387
+ errors += 1
388
+ end
389
+ end
390
+ rescue StandardError => e
391
+ on_error e, :copy
392
+ else
393
+ puts message(to, subdir.size, files.size - errors) if verbose
394
+ end
395
+ next
396
+ end
351
397
  glob = Array(glob || '**/*')
352
398
  target = []
399
+ from = path + from
353
400
  if workspace
354
401
  from.glob('*').each do |entry|
355
402
  next unless entry.directory?
@@ -373,16 +420,14 @@ module Squared
373
420
  end
374
421
  end
375
422
  else
376
- target << [from, dest.join(into, scope || project)]
423
+ target << [from, dest.join(into, scope || npmname)]
377
424
  end
378
425
  target.each do |src, to|
379
426
  glob.each { |val| log.info "cp #{from + val} #{to}" }
380
427
  begin
381
428
  copy_dir(src, to, glob, create: create, link: link, force: force, pass: pass, verbose: verbose)
382
429
  rescue StandardError => e
383
- log.error e
384
- ret = on :error, :copy, e
385
- raise if exception && ret != true
430
+ on_error e, :copy
386
431
  end
387
432
  end
388
433
  end
@@ -448,19 +493,14 @@ module Squared
448
493
  log.info cmd.to_s
449
494
  on :first, :outdated
450
495
  end
451
- banner = format_banner(cmd.temp(dryrun ? ' --dry-run' : nil))
496
+ banner = format_banner(cmd.temp(dryrun ? '--dry-run' : nil))
452
497
  print_item banner if sync
453
498
  begin
454
499
  data = pwd_set { `#{cmd.temp('--json', '--loglevel=error')}` }
455
500
  doc = dependfile.read
456
501
  json = JSON.parse(doc)
457
502
  rescue StandardError => e
458
- log.error e
459
- unless dryrun
460
- ret = on :error, :outdated, e
461
- raise if exception && ret != true
462
- end
463
- warn log_message(Logger::WARN, e) if warning?
503
+ on_error(e, :outdated, dryrun: dryrun)
464
504
  return
465
505
  else
466
506
  dep1 = json['dependencies'] || {}
@@ -611,7 +651,7 @@ module Squared
611
651
  package('update', from: :update)
612
652
  end
613
653
 
614
- def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, dryrun: nil, access: nil)
654
+ def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, access: nil, dryrun: nil)
615
655
  if !version || read_packagemanager(:private)
616
656
  warn log_message(Logger::WARN, 'invalid task "publish"', subject: name, hint: version ? 'private' : nil)
617
657
  return
@@ -628,7 +668,7 @@ module Squared
628
668
  log.info cmd.to_s
629
669
  end
630
670
  if sync
631
- run(from: from, sync: sync, interactive: !dryrun && "Publish #{sub_style(project, styles: theme[:active])}")
671
+ run(from: from, sync: sync, interactive: !dryrun && "Publish #{sub_style(npmname, styles: theme[:active])}")
632
672
  else
633
673
  on :first, from
634
674
  pwd_set(from: from) do
@@ -746,9 +786,7 @@ module Squared
746
786
  raise_error('version not found', hint: dependfile)
747
787
  end
748
788
  rescue StandardError => e
749
- log.debug e
750
- ret = on :error, :bump, e
751
- raise if exception && ret != true
789
+ on_error e, :bump
752
790
  end
753
791
  end
754
792
 
@@ -887,7 +925,7 @@ module Squared
887
925
  end
888
926
 
889
927
  def version
890
- super || (@version = read_packagemanager(:version))
928
+ @version ||= read_packagemanager(:version)
891
929
  end
892
930
 
893
931
  def packagename
@@ -913,7 +951,7 @@ module Squared
913
951
  else
914
952
  if key
915
953
  @pm[key]
916
- elsif (ret = @pm[:_]) && !(version && ret[(ret.index('@') + 1)..-1] < version)
954
+ elsif (ret = @pm[:_]) && !(version && semcmp(ret[(ret.index('@') + 1)..-1], version) == 1)
917
955
  ret
918
956
  end
919
957
  end
@@ -978,6 +1016,10 @@ module Squared
978
1016
  'package.json' if parent&.has?('outdated', Node.ref)
979
1017
  end
980
1018
 
1019
+ def npmname
1020
+ packagename || project
1021
+ end
1022
+
981
1023
  def npmnotice
982
1024
  [
983
1025
  { pat: /^(npm error )(code|\d+)(.+)$/, styles: color(:cyan), index: 2 },
@@ -114,7 +114,7 @@ module Squared
114
114
 
115
115
  namespace name do
116
116
  Python.subtasks do |action, flags|
117
- next if @pass.include?(action)
117
+ next if task_pass?(action)
118
118
 
119
119
  if flags.nil?
120
120
  case action
@@ -183,7 +183,7 @@ module Squared
183
183
  elsif i || args.empty?
184
184
  readline('Enter command', force: true)
185
185
  else
186
- if (val = command_args(args, prefix: 'python'))
186
+ if (val = command_args(args, min: 1, prefix: 'python'))
187
187
  args << val
188
188
  end
189
189
  args.join(' ')
@@ -280,7 +280,7 @@ module Squared
280
280
  end
281
281
  end
282
282
  when 'outdated'
283
- format_desc action, flag, 'eager?'
283
+ format_desc action, flag, 'eager?,user?'
284
284
  task flag do |_, args|
285
285
  outdated flag, args.to_a
286
286
  end
@@ -366,7 +366,11 @@ module Squared
366
366
  pwd_set(from: :outdated) do
367
367
  buffer = []
368
368
  out = ->(val) { sync ? puts(val) : buffer << val }
369
- IO.popen(runenv || {}, cmd).each do |line|
369
+ if workspace.windows?
370
+ (venv ? command(runenv, cmd) : `#{cmd}`).lines
371
+ else
372
+ IO.popen(runenv || {}, cmd)
373
+ end.each do |line|
370
374
  next if line.match?(/^[ -]+$/)
371
375
 
372
376
  if start > 0
@@ -431,7 +435,9 @@ module Squared
431
435
  when :patch
432
436
  patch
433
437
  end
434
- install(:upgrade, pkg, strategy: opts.include?('eager') ? 'eager' : nil) unless !pkg || pkg.empty?
438
+ unless !pkg || pkg.empty?
439
+ install(:upgrade, pkg, strategy: opts.include?('eager') ? 'eager' : nil, user: opts.include?('user'))
440
+ end
435
441
  elsif start == 0
436
442
  puts 'No updates were found'
437
443
  end
@@ -439,7 +445,7 @@ module Squared
439
445
  on :last, :outdated
440
446
  end
441
447
 
442
- def install(flag, opts = [], strategy: nil)
448
+ def install(flag, opts = [], strategy: nil, user: nil)
443
449
  cmd = pip_session 'install'
444
450
  out = append_pip(flag, opts, from: :install)
445
451
  case flag
@@ -449,6 +455,7 @@ module Squared
449
455
  when :upgrade
450
456
  raise_error('no packages listed', hint: flag) if out.empty?
451
457
  cmd << '--upgrade'
458
+ cmd << '--user' if user
452
459
  cmd << basic_option('upgrade-strategy', strategy) if strategy
453
460
  append_value out
454
461
  end
@@ -485,7 +492,7 @@ module Squared
485
492
  if srcdir
486
493
  args = flag == :pdm ? ['d', 'dest'] : ['o', 'output']
487
494
  if op.arg?(*args)
488
- op.extras << srcdir
495
+ op.push(srcdir)
489
496
  else
490
497
  op << quote_option(args.last, path + srcdir)
491
498
  end
@@ -528,7 +535,7 @@ module Squared
528
535
  case flag
529
536
  when :hatch, :twine
530
537
  if op.empty?
531
- op.extras << "#{dist.call}/*"
538
+ op.push("#{dist.call}/*")
532
539
  else
533
540
  op.map! { |val| path + val }
534
541
  end
@@ -652,7 +659,7 @@ module Squared
652
659
  if edit
653
660
  edit = path + edit unless %r{^[a-z]+(?:\+[a-z]+)?://}i.match?(edit)
654
661
  if flag == :editable
655
- op.extras << edit
662
+ op.push(edit)
656
663
  else
657
664
  target << quote_option('e', edit)
658
665
  end
@@ -848,17 +855,17 @@ module Squared
848
855
  return if !venv || (venvbin.directory? && !venvbin.empty?)
849
856
 
850
857
  puts log_message(Logger::INFO, venv, subject: 'venv', hint: 'init')
851
- @venvopts &&= @venvopts.map { |val| OptionPartition.strip(val) }.flatten
852
- venv_create(venv, @venvopts || ["prompt=#{name}", 'upgrade-deps'], env: false, banner: false)
858
+ opts = @venvopts&.map { |val| OptionPartition.strip(val) }&.flatten
859
+ venv_create(venv, opts || ["prompt=#{name}", 'upgrade-deps'], env: false, banner: false)
853
860
  puts log_message(Logger::INFO, venv, subject: 'venv', hint: 'created')
854
861
  end
855
862
 
856
863
  def venv_create(dir, opts = [], env: nil, banner: true)
857
864
  cmd, opts = python_session('-m venv', opts: opts)
858
865
  op = OptionPartition.new(opts, OPT_PYTHON[:venv], cmd, project: self)
859
- op.append(dir, delim: true)
860
- .clear(pass: false)
861
- status = op.arg?(/\A-v+\z/, 'verbose')
866
+ status = op.append(dir, delim: true)
867
+ .clear(pass: false)
868
+ .arg?(/\A-v+\z/, 'verbose')
862
869
  run(op, env, exception: true, banner: banner)
863
870
  puts(dir.directory? ? "Success: #{dir}" : 'Failed') if banner && !status
864
871
  end