squared 0.5.2 → 0.5.4

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.
@@ -98,7 +98,7 @@ module Squared
98
98
  'pack' => nil
99
99
  })
100
100
 
101
- def initialize(*, **kwargs)
101
+ def initialize(*, init: nil, **kwargs)
102
102
  super
103
103
  if @pass.include?(Node.ref)
104
104
  initialize_ref Node.ref
@@ -108,7 +108,7 @@ module Squared
108
108
  initialize_env(**kwargs)
109
109
  end
110
110
  @dependfile = @path + 'package.json'
111
- @pm = {}
111
+ @pm = { __: init }
112
112
  end
113
113
 
114
114
  def ref
@@ -117,11 +117,11 @@ module Squared
117
117
 
118
118
  def populate(*, **)
119
119
  super
120
- return unless outdated? && ref?(Node.ref)
120
+ return unless (outdated? && ref?(Node.ref)) || @only
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
@@ -129,10 +129,7 @@ module Squared
129
129
  format_desc action, nil, 'save?=prod|dev|optional|peer,name+'
130
130
  task action, [:save] do |_, args|
131
131
  save = param_guard(action, 'save', args: args, key: :save)
132
- if save.start_with?('=')
133
- exact = true
134
- save = save[1..-1]
135
- end
132
+ exact = true if save.delete_prefix!('=')
136
133
  case save
137
134
  when 'prod', 'dev', 'optional', 'peer'
138
135
  packages = args.extras
@@ -269,6 +266,11 @@ module Squared
269
266
  otp = args.first
270
267
  else
271
268
  tag, otp = param_guard(action, flag, args: args)
269
+ unless SEM_VER.match?(tag)
270
+ a = sub_style(project, styles: theme[:active])
271
+ b = sub_style(tag, styles: theme[:inline])
272
+ exit 1 unless confirm("Publish #{a}@#{b}?", 'N')
273
+ end
272
274
  end
273
275
  publish(flag, otp: otp, tag: tag, dryrun: dryrun, access: access)
274
276
  end
@@ -280,7 +282,7 @@ module Squared
280
282
  end
281
283
  end
282
284
 
283
- def copy(from: 'build', into: 'node_modules', scope: nil, also: nil, create: nil, workspace: false,
285
+ def copy(from: 'build', into: 'node_modules', scope: nil, also: nil, create: nil, files: nil, workspace: false,
284
286
  link: false, force: false, override: false, sync: invoked_sync?('copy'), **kwargs)
285
287
  glob = kwargs[:include]
286
288
  pass = kwargs[:exclude]
@@ -289,6 +291,7 @@ module Squared
289
291
 
290
292
  from = @copy[:from] if @copy.key?(:from)
291
293
  into = @copy[:into] if @copy.key?(:into)
294
+ files = @copy[:files] if @copy.key?(:files)
292
295
  workspace = @copy[:workspace] if @copy.key?(:workspace)
293
296
  link = @copy[:link] if @copy.key?(:link)
294
297
  force = @copy[:force] if @copy.key?(:force)
@@ -310,6 +313,7 @@ module Squared
310
313
 
311
314
  on :first, :copy
312
315
  print_item unless @output[0] || !verbose || task_invoked?(/^copy(?::#{Node.ref}|$)/)
316
+ packed = false
313
317
  items.each do |dir|
314
318
  case dir
315
319
  when Pathname
@@ -347,9 +351,49 @@ module Squared
347
351
  end
348
352
  next unless from && dest&.directory?
349
353
 
350
- from = path + from
354
+ if from == :npm
355
+ begin
356
+ unless packed
357
+ require 'open3'
358
+ files = pwd_set do
359
+ Open3.capture2e(session_output('npm', 'pack --dry-run --no-color', npmname).to_s)
360
+ .first
361
+ .scan(/^npm notice \d+(?:\.\d+)?[a-z]+ (.+)$/i)
362
+ .map { |item| Pathname.new(item.first) }
363
+ .select(&:exist?)
364
+ end
365
+ .concat(Array(files))
366
+ packed = true
367
+ end
368
+ to = dest.join(into, npmname)
369
+ to.mkpath
370
+ log.info "cp npm:#{npmname} #{to}"
371
+ subdir = []
372
+ errors = 0
373
+ files.each do |file|
374
+ s, d = file.is_a?(Array) ? file : [file, file]
375
+ dest = to + d
376
+ unless subdir.include?((target = dest.dirname).to_s)
377
+ target.mkpath
378
+ subdir << target.to_s
379
+ end
380
+ begin
381
+ FileUtils.cp(path + s, dest, verbose: verbose.is_a?(Numeric) && verbose > 0)
382
+ rescue StandardError => e
383
+ print_error e
384
+ errors += 1
385
+ end
386
+ end
387
+ rescue StandardError => e
388
+ on_error e, :copy
389
+ else
390
+ puts message(to, subdir.size, files.size - errors) if verbose
391
+ end
392
+ next
393
+ end
351
394
  glob = Array(glob || '**/*')
352
395
  target = []
396
+ from = path + from
353
397
  if workspace
354
398
  from.glob('*').each do |entry|
355
399
  next unless entry.directory?
@@ -373,16 +417,14 @@ module Squared
373
417
  end
374
418
  end
375
419
  else
376
- target << [from, dest.join(into, scope || project)]
420
+ target << [from, dest.join(into, scope || npmname)]
377
421
  end
378
422
  target.each do |src, to|
379
423
  glob.each { |val| log.info "cp #{from + val} #{to}" }
380
424
  begin
381
425
  copy_dir(src, to, glob, create: create, link: link, force: force, pass: pass, verbose: verbose)
382
426
  rescue StandardError => e
383
- log.error e
384
- ret = on :error, :copy, e
385
- raise if exception && ret != true
427
+ on_error e, :copy
386
428
  end
387
429
  end
388
430
  end
@@ -396,7 +438,19 @@ module Squared
396
438
  workspace.rev_clear(name, sync: sync)
397
439
  return update if !flag && env('NODE_UPDATE')
398
440
 
399
- if (yarn = dependtype(:yarn)) > 0
441
+ pnpm = pnpm?
442
+ yarn = pnpm ? 0 : dependtype(:yarn)
443
+ if @pm[:__] && !pnpm && yarn == 0
444
+ case @pm[:__]
445
+ when 'pnpm'
446
+ pnpm = true
447
+ when 'yarn'
448
+ yarn = 1
449
+ when 'berry'
450
+ yarn = 2
451
+ end
452
+ end
453
+ if yarn > 0
400
454
  cmd = session 'yarn'
401
455
  if flag == :add
402
456
  cmd << 'add'
@@ -406,7 +460,7 @@ module Squared
406
460
  cmd << 'install'
407
461
  cmd << '--ignore-engines' if yarn == 1 && !option('ignore-engines', equals: '0')
408
462
  end
409
- elsif pnpm?
463
+ elsif pnpm
410
464
  cmd = session 'pnpm'
411
465
  if flag == :add
412
466
  cmd << 'add' << "--save-#{save}"
@@ -448,19 +502,14 @@ module Squared
448
502
  log.info cmd.to_s
449
503
  on :first, :outdated
450
504
  end
451
- banner = format_banner(cmd.temp(dryrun ? ' --dry-run' : nil))
505
+ banner = format_banner(cmd.temp(dryrun ? '--dry-run' : nil))
452
506
  print_item banner if sync
453
507
  begin
454
- data = pwd_set { `#{cmd.temp('--json', '--loglevel=error')}` }
508
+ data = pwd_set(dryrun: dryrun) { `#{cmd.temp('--json', '--loglevel=error')}` }
455
509
  doc = dependfile.read
456
510
  json = JSON.parse(doc)
457
511
  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?
512
+ on_error(e, :outdated, dryrun: dryrun)
464
513
  return
465
514
  else
466
515
  dep1 = json['dependencies'] || {}
@@ -611,7 +660,7 @@ module Squared
611
660
  package('update', from: :update)
612
661
  end
613
662
 
614
- def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, dryrun: nil, access: nil)
663
+ def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, access: nil, dryrun: nil)
615
664
  if !version || read_packagemanager(:private)
616
665
  warn log_message(Logger::WARN, 'invalid task "publish"', subject: name, hint: version ? 'private' : nil)
617
666
  return
@@ -620,7 +669,7 @@ module Squared
620
669
  cmd << basic_option('otp', otp) if otp ||= option('otp')
621
670
  cmd << basic_option('tag', tag) if tag ||= option('tag')
622
671
  cmd << basic_option('access', access) if access ||= option('access')
623
- dryrun = dryrun?('npm') if dryrun.nil?
672
+ dryrun ||= dryrun?('npm')
624
673
  if dryrun
625
674
  cmd << '--dry-run'
626
675
  else
@@ -628,10 +677,10 @@ module Squared
628
677
  log.info cmd.to_s
629
678
  end
630
679
  if sync
631
- run(from: from, sync: sync, interactive: !dryrun && "Publish #{sub_style(project, styles: theme[:active])}")
680
+ run(from: from, sync: sync, interactive: !dryrun && "Publish #{sub_style(npmname, styles: theme[:active])}")
632
681
  else
633
682
  on :first, from
634
- pwd_set(from: from) do
683
+ pwd_set(from: from, dryrun: dryrun) do
635
684
  require 'open3'
636
685
  banner = format_banner cmd.to_s
637
686
  Open3.popen2e(cmd.done) do |_, out|
@@ -708,21 +757,23 @@ module Squared
708
757
  when :major
709
758
  if seg[0] != '0' || seg[2].nil?
710
759
  seg[0] = seg[0].succ
760
+ seg[2] = '0'
711
761
  else
712
762
  seg[2] = seg[2].succ
713
763
  end
764
+ seg[4] = '0'
714
765
  when :minor
715
766
  if seg[0] == '0'
716
767
  seg[4] &&= seg[4].succ
717
768
  else
718
769
  seg[2] = seg[2].succ
719
770
  end
771
+ seg[4] = '0'
720
772
  when :patch
721
773
  seg[4] &&= seg[4].succ
722
774
  end
723
775
  return if (val = seg.join) == cur
724
776
  end
725
-
726
777
  begin
727
778
  doc = dependfile.read
728
779
  if doc.sub!(/"version"\s*:\s*"#{cur}"/, "\"version\": \"#{val}\"")
@@ -746,9 +797,7 @@ module Squared
746
797
  raise_error('version not found', hint: dependfile)
747
798
  end
748
799
  rescue StandardError => e
749
- log.debug e
750
- ret = on :error, :bump, e
751
- raise if exception && ret != true
800
+ on_error e, :bump
752
801
  end
753
802
  end
754
803
 
@@ -887,7 +936,7 @@ module Squared
887
936
  end
888
937
 
889
938
  def version
890
- super || (@version = read_packagemanager(:version))
939
+ @version ||= read_packagemanager(:version)
891
940
  end
892
941
 
893
942
  def packagename
@@ -913,7 +962,7 @@ module Squared
913
962
  else
914
963
  if key
915
964
  @pm[key]
916
- elsif (ret = @pm[:_]) && !(version && ret[(ret.index('@') + 1)..-1] < version)
965
+ elsif (ret = @pm[:_]) && (!version || semgte?(ret[(ret.index('@') + 1)..-1], version))
917
966
  ret
918
967
  end
919
968
  end
@@ -978,6 +1027,10 @@ module Squared
978
1027
  'package.json' if parent&.has?('outdated', Node.ref)
979
1028
  end
980
1029
 
1030
+ def npmname
1031
+ packagename || project
1032
+ end
1033
+
981
1034
  def npmnotice
982
1035
  [
983
1036
  { pat: /^(npm error )(code|\d+)(.+)$/, styles: color(:cyan), index: 2 },
@@ -87,7 +87,6 @@ module Squared
87
87
  initialize_build(Python.ref, **kwargs)
88
88
  initialize_env(**kwargs)
89
89
  end
90
- @verbose = verbose.size if verbose.is_a?(String) && verbose.match?(/\Av+\z/)
91
90
  dependfile_set DEP_PYTHON
92
91
  editable_set editable
93
92
  venv_set kwargs[:venv]
@@ -95,7 +94,7 @@ module Squared
95
94
 
96
95
  subtasks({
97
96
  'venv' => %i[exec create remove show].freeze,
98
- 'pip' => %i[uninstall freeze].freeze,
97
+ 'pip' => %i[upgrade uninstall freeze].freeze,
99
98
  'install' => %i[user force upgrade target editable].freeze,
100
99
  'outdated' => %i[major minor patch].freeze,
101
100
  'build' => %i[python poetry pdm hatch].freeze,
@@ -104,17 +103,26 @@ module Squared
104
103
  'exec' => nil
105
104
  })
106
105
 
106
+ def verbose=(val)
107
+ case val
108
+ when /\Av+\z/
109
+ @verbose = val.size
110
+ else
111
+ super
112
+ end
113
+ end
114
+
107
115
  def ref
108
116
  Python.ref
109
117
  end
110
118
 
111
119
  def populate(*, **)
112
120
  super
113
- return unless outdated? && ref?(Python.ref)
121
+ return unless (outdated? && ref?(Python.ref)) || @only
114
122
 
115
123
  namespace name do
116
124
  Python.subtasks do |action, flags|
117
- next if @pass.include?(action)
125
+ next if task_pass?(action)
118
126
 
119
127
  if flags.nil?
120
128
  case action
@@ -159,7 +167,7 @@ module Squared
159
167
  found |= 1
160
168
  run(pdm_session('run', val), from: :run)
161
169
  else
162
- raise_error("script: #{val}", hint: 'unknown') if exception
170
+ raise_error "script: #{val}" if exception
163
171
  found |= 2
164
172
  log.warn "run script \"#{val}\" (not indexed)"
165
173
  end
@@ -183,7 +191,7 @@ module Squared
183
191
  elsif i || args.empty?
184
192
  readline('Enter command', force: true)
185
193
  else
186
- if (val = command_args(args, prefix: 'python'))
194
+ if (val = command_args(args, min: 1, prefix: 'python'))
187
195
  args << val
188
196
  end
189
197
  args.join(' ')
@@ -234,6 +242,14 @@ module Squared
234
242
  end
235
243
  when 'pip'
236
244
  case flag
245
+ when :upgrade
246
+ format_desc action, flag, 'opts*'
247
+ task flag do |_, args|
248
+ args = args.to_a
249
+ args.prepend('upgrade')
250
+ args.append('pip')
251
+ install flag, args
252
+ end
237
253
  when :freeze
238
254
  format_desc action, flag, "file?=#{DEP_PYTHON[4]},opts*"
239
255
  task flag do |_, args|
@@ -287,7 +303,7 @@ module Squared
287
303
  when 'build'
288
304
  case flag
289
305
  when :poetry
290
- next unless build_backend == 'poetry.core.masonry.api'
306
+ next unless poetry?
291
307
  when :pdm
292
308
  next unless build_backend == 'pdm.backend'
293
309
  when :hatch
@@ -325,8 +341,8 @@ module Squared
325
341
  elsif outdated?
326
342
  venv_init
327
343
  workspace.rev_clear(name, sync: sync)
328
- if !flag && dependtype == 1
329
- cmd = poetry_session 'install', '-n'
344
+ if !flag && poetry?
345
+ cmd = poetry_session 'install -n'
330
346
  cmd << '--no-root' if option('no-root')
331
347
  else
332
348
  cmd = pip_session 'install'
@@ -351,7 +367,7 @@ module Squared
351
367
  end
352
368
 
353
369
  def outdated(flag = nil, opts = [], sync: invoked_sync?('outdated'))
354
- cmd = pip_session 'list', '--outdated'
370
+ cmd = pip_session 'list --outdated'
355
371
  append_global
356
372
  cmd = session_done cmd
357
373
  log.info cmd
@@ -366,7 +382,11 @@ module Squared
366
382
  pwd_set(from: :outdated) do
367
383
  buffer = []
368
384
  out = ->(val) { sync ? puts(val) : buffer << val }
369
- IO.popen(runenv || {}, cmd).each do |line|
385
+ if workspace.windows?
386
+ (venv ? command(runenv, cmd) : `#{cmd}`).lines
387
+ else
388
+ IO.popen(runenv || {}, cmd)
389
+ end.each do |line|
370
390
  next if line.match?(/^[ -]+$/)
371
391
 
372
392
  if start > 0
@@ -454,6 +474,11 @@ module Squared
454
474
  cmd << '--user' if user
455
475
  cmd << basic_option('upgrade-strategy', strategy) if strategy
456
476
  append_value out
477
+ if workspace.windows?
478
+ pip = cmd.to_a.drop(1)
479
+ cmd = python_session '-m pip'
480
+ cmd.merge(pip)
481
+ end
457
482
  end
458
483
  run(from: :install)
459
484
  end
@@ -488,7 +513,7 @@ module Squared
488
513
  if srcdir
489
514
  args = flag == :pdm ? ['d', 'dest'] : ['o', 'output']
490
515
  if op.arg?(*args)
491
- op.extras << srcdir
516
+ op.push(srcdir)
492
517
  else
493
518
  op << quote_option(args.last, path + srcdir)
494
519
  end
@@ -502,7 +527,7 @@ module Squared
502
527
  end
503
528
  op << basic_option('p', project) unless ENV['HATCH_PROJECT'] || op.arg?('p', 'project')
504
529
  end
505
- op << shell_quote(path + srcdir) if srcdir
530
+ op.add_path(srcdir) if srcdir
506
531
  op.clear
507
532
  run(from: :"#{flag}:build")
508
533
  end
@@ -531,7 +556,7 @@ module Squared
531
556
  case flag
532
557
  when :hatch, :twine
533
558
  if op.empty?
534
- op.extras << "#{dist.call}/*"
559
+ op.push("#{dist.call}/*")
535
560
  else
536
561
  op.map! { |val| path + val }
537
562
  end
@@ -548,7 +573,7 @@ module Squared
548
573
  out = append_pip(nil, opts, from: flag)
549
574
  case flag
550
575
  when :uninstall
551
- raise_error('no packages listed', hint: 'uninstall') if out.empty?
576
+ raise_error('no packages listed', hint: flag) if out.empty?
552
577
  cmd.merge(out)
553
578
  when :freeze
554
579
  venv_init
@@ -653,9 +678,9 @@ module Squared
653
678
  end
654
679
  op.swap
655
680
  if edit
656
- edit = path + edit unless %r{^[a-z]+(?:\+[a-z]+)?://}i.match?(edit)
681
+ edit = path + edit unless %r{\A[a-z]+(?:\+[a-z]+)?://}i.match?(edit)
657
682
  if flag == :editable
658
- op.extras << edit
683
+ op.push(edit)
659
684
  else
660
685
  target << quote_option('e', edit)
661
686
  end
@@ -851,21 +876,29 @@ module Squared
851
876
  return if !venv || (venvbin.directory? && !venvbin.empty?)
852
877
 
853
878
  puts log_message(Logger::INFO, venv, subject: 'venv', hint: 'init')
854
- @venvopts &&= @venvopts.map { |val| OptionPartition.strip(val) }.flatten
855
- venv_create(venv, @venvopts || ["prompt=#{name}", 'upgrade-deps'], env: false, banner: false)
879
+ opts = @venvopts&.map { |val| OptionPartition.strip(val) }&.flatten
880
+ venv_create(venv, opts || ["prompt=#{name}", 'upgrade-deps'], env: false, banner: false)
856
881
  puts log_message(Logger::INFO, venv, subject: 'venv', hint: 'created')
857
882
  end
858
883
 
859
884
  def venv_create(dir, opts = [], env: nil, banner: true)
860
885
  cmd, opts = python_session('-m venv', opts: opts)
861
886
  op = OptionPartition.new(opts, OPT_PYTHON[:venv], cmd, project: self)
862
- op.append(dir, delim: true)
863
- .clear(pass: false)
864
- status = op.arg?(/\A-v+\z/, 'verbose')
887
+ status = op.append(dir, delim: true)
888
+ .clear(pass: false)
889
+ .arg?(/\A-v+\z/, 'verbose')
865
890
  run(op, env, exception: true, banner: banner)
866
891
  puts(dir.directory? ? "Success: #{dir}" : 'Failed') if banner && !status
867
892
  end
868
893
 
894
+ def setuptools?
895
+ build_backend ? build_backend == 'setuptools.build_meta' : dependtype == 2 || dependtype == 4
896
+ end
897
+
898
+ def poetry?
899
+ build_backend ? build_backend == 'poetry.core.masonry.api' : dependtype == 1
900
+ end
901
+
869
902
  def requirements?
870
903
  dependtype == 5
871
904
  end