squared 0.5.0 → 0.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +81 -0
- data/README.ruby.md +1 -1
- data/lib/squared/common/base.rb +5 -2
- data/lib/squared/common/format.rb +8 -2
- data/lib/squared/common/prompt.rb +10 -2
- data/lib/squared/common/system.rb +21 -14
- data/lib/squared/common/utils.rb +7 -3
- data/lib/squared/config.rb +7 -6
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +21 -13
- data/lib/squared/workspace/project/base.rb +89 -56
- data/lib/squared/workspace/project/docker.rb +15 -13
- data/lib/squared/workspace/project/git.rb +73 -46
- data/lib/squared/workspace/project/node.rb +40 -44
- data/lib/squared/workspace/project/python.rb +244 -46
- data/lib/squared/workspace/project/ruby.rb +124 -104
- data/lib/squared/workspace/project/support/class.rb +38 -2
- data/lib/squared/workspace/repo.rb +3 -2
- data/lib/squared/workspace/support/data.rb +3 -3
- metadata +1 -1
@@ -8,7 +8,7 @@ module Squared
|
|
8
8
|
DIR_PYTHON = (DEP_PYTHON + %w[README.rst]).freeze
|
9
9
|
OPT_PYTHON = {
|
10
10
|
common: %w[b B d E h i I O OO P q s S u v x c=q m=b W=b X=q check-hash-based-pycs=b].freeze,
|
11
|
-
build: %w[n|no-isolation s|sdist v|verbose w|wheel
|
11
|
+
build: %w[n|no-isolation s|sdist x|skip-dependency-check v|verbose w|wheel C|config-setting=q installer=b
|
12
12
|
o|outdir=p].freeze,
|
13
13
|
venv: %w[clear copies symlinks system-site-packages upgrade upgrade-deps without-scm-ignore-files without-pip
|
14
14
|
prompt=q].freeze
|
@@ -28,11 +28,18 @@ module Squared
|
|
28
28
|
freeze: %w[all exclude-editable l|local user exclude=b path=p r|requirement=p].freeze
|
29
29
|
}.freeze
|
30
30
|
OPT_POETRY = {
|
31
|
-
common: %w[ansi no-ansi no-cache n|no-interaction no-plugins
|
31
|
+
common: %w[ansi no-ansi no-cache n|no-interaction no-plugins q|quiet v|verbose P|project=p].freeze,
|
32
32
|
build: %w[clean config-settings=qq f|format=b o|output=p].freeze,
|
33
|
-
publish: %w[build dry-run
|
33
|
+
publish: %w[build dry-run skip-existing cert=p client-cert=p dist-dir=p p|password=b r|repository=b
|
34
34
|
u|username=b].freeze
|
35
35
|
}.freeze
|
36
|
+
OPT_PDM = {
|
37
|
+
common: %w[I|ignore-python no-cache n|non-interactive].freeze,
|
38
|
+
build: %w[C=bm no-clean no-isolation no-sdist no-wheel quiet verbose config-setting=q d|dest=p p|project=p
|
39
|
+
k|skip=b].freeze,
|
40
|
+
publish: %w[no-build no-very-ssl quiet S|sign skip-existing verbose ca-certs=p c|comment=q d|dest=p identity=b
|
41
|
+
p|password=q p|project=p r|repository=q k|skip=b u|username=b].freeze
|
42
|
+
}.freeze
|
36
43
|
OPT_HATCH = {
|
37
44
|
common: %w[color interactive no-color no-interactive cache-dir=p config=p data-dir=p e|env=b p|project=b
|
38
45
|
q|quiet v|verbose].freeze,
|
@@ -41,11 +48,11 @@ module Squared
|
|
41
48
|
p|publisher=b r|repo=b u|user=q].freeze
|
42
49
|
}.freeze
|
43
50
|
OPT_TWINE = {
|
44
|
-
publish: %w[attestations disable-progress-bar non-interactive skip-existing verbose
|
45
|
-
|
51
|
+
publish: %w[attestations disable-progress-bar non-interactive s|sign skip-existing verbose cert=p
|
52
|
+
client-cert=p c|comment=q config-file=p i|identity=b p|password=q r|repository=b repository-url=q
|
46
53
|
sign-with=b u|username=q].freeze
|
47
54
|
}.freeze
|
48
|
-
private_constant :DEP_PYTHON, :DIR_PYTHON, :OPT_PYTHON, :OPT_PIP, :OPT_POETRY, :OPT_HATCH, :OPT_TWINE
|
55
|
+
private_constant :DEP_PYTHON, :DIR_PYTHON, :OPT_PYTHON, :OPT_PIP, :OPT_POETRY, :OPT_PDM, :OPT_HATCH, :OPT_TWINE
|
49
56
|
|
50
57
|
class << self
|
51
58
|
def populate(*); end
|
@@ -71,7 +78,7 @@ module Squared
|
|
71
78
|
|
72
79
|
attr_reader :venv, :editable
|
73
80
|
|
74
|
-
def initialize(*,
|
81
|
+
def initialize(*, editable: '.', verbose: nil, **kwargs)
|
75
82
|
super
|
76
83
|
if @pass.include?(Python.ref)
|
77
84
|
initialize_ref Python.ref
|
@@ -80,18 +87,20 @@ module Squared
|
|
80
87
|
initialize_build(Python.ref, **kwargs)
|
81
88
|
initialize_env(**kwargs)
|
82
89
|
end
|
83
|
-
dependfile_set DEP_PYTHON
|
84
90
|
@verbose = verbose.size if verbose.is_a?(String) && verbose.match?(/\Av+\z/)
|
91
|
+
dependfile_set DEP_PYTHON
|
85
92
|
editable_set editable
|
86
|
-
venv_set venv
|
93
|
+
venv_set kwargs[:venv]
|
87
94
|
end
|
88
95
|
|
89
96
|
subtasks({
|
90
97
|
'venv' => %i[exec create remove show].freeze,
|
91
98
|
'pip' => %i[uninstall freeze].freeze,
|
92
99
|
'install' => %i[user force upgrade target editable].freeze,
|
93
|
-
'
|
94
|
-
'
|
100
|
+
'outdated' => %i[major minor patch].freeze,
|
101
|
+
'build' => %i[python poetry pdm hatch].freeze,
|
102
|
+
'publish' => %i[poetry pdm hatch twine].freeze,
|
103
|
+
'run' => nil,
|
95
104
|
'exec' => nil
|
96
105
|
})
|
97
106
|
|
@@ -109,6 +118,62 @@ module Squared
|
|
109
118
|
|
110
119
|
if flags.nil?
|
111
120
|
case action
|
121
|
+
when 'run'
|
122
|
+
next unless pyprojectfile
|
123
|
+
|
124
|
+
format_desc action, nil, "script+|#{indexchar}index+|#,pattern*"
|
125
|
+
task action, [:command] do |_, args|
|
126
|
+
found = 0
|
127
|
+
['tool.poetry.scripts', 'tool.pdm.scripts', 'project.scripts'].each_with_index do |table, index|
|
128
|
+
next if (list = read_pyproject(table)).empty?
|
129
|
+
|
130
|
+
if args.command == '#'
|
131
|
+
format_list(list, "run[#{indexchar}N]", 'scripts', grep: args.extras, from: pyprojectfile)
|
132
|
+
found |= 1
|
133
|
+
else
|
134
|
+
args.to_a.each do |val|
|
135
|
+
if (n, = indexitem(val))
|
136
|
+
if (script, = list[n - 1])
|
137
|
+
case index
|
138
|
+
when 0
|
139
|
+
script = session_output 'poetry', 'run', script
|
140
|
+
when 1
|
141
|
+
script = pdm_session 'run', script
|
142
|
+
else
|
143
|
+
venv_init
|
144
|
+
end
|
145
|
+
found |= 1
|
146
|
+
run(script, from: :run)
|
147
|
+
elsif exception
|
148
|
+
indexerror n, list
|
149
|
+
else
|
150
|
+
found |= 2
|
151
|
+
log.warn "run script #{n} of #{list.size} (out of range)"
|
152
|
+
end
|
153
|
+
else
|
154
|
+
case index
|
155
|
+
when 0
|
156
|
+
found |= 1
|
157
|
+
run(session_output('poetry', 'run', val), from: :run)
|
158
|
+
when 1
|
159
|
+
found |= 1
|
160
|
+
run(pdm_session('run', val), from: :run)
|
161
|
+
else
|
162
|
+
raise_error("script: #{val}", hint: 'unknown') if exception
|
163
|
+
found |= 2
|
164
|
+
log.warn "run script \"#{val}\" (not indexed)"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
break
|
170
|
+
end
|
171
|
+
unless found.anybits?(1)
|
172
|
+
puts log_message(found == 0 ? Logger::INFO : Logger.WARN,
|
173
|
+
"no scripts #{found == 0 ? 'found' : 'executed'}",
|
174
|
+
subject: name, hint: pyprojectfile)
|
175
|
+
end
|
176
|
+
end
|
112
177
|
when 'exec'
|
113
178
|
format_desc action, nil, 'command|:,args*'
|
114
179
|
task action do |_, args|
|
@@ -123,7 +188,7 @@ module Squared
|
|
123
188
|
end
|
124
189
|
args.join(' ')
|
125
190
|
end
|
126
|
-
|
191
|
+
shell(cmd, name: :exec, chdir: path)
|
127
192
|
end
|
128
193
|
end
|
129
194
|
else
|
@@ -214,14 +279,30 @@ module Squared
|
|
214
279
|
depend flag, args.to_a
|
215
280
|
end
|
216
281
|
end
|
282
|
+
when 'outdated'
|
283
|
+
format_desc action, flag, 'eager?'
|
284
|
+
task flag do |_, args|
|
285
|
+
outdated flag, args.to_a
|
286
|
+
end
|
217
287
|
when 'build'
|
288
|
+
case flag
|
289
|
+
when :poetry
|
290
|
+
next unless build_backend == 'poetry.core.masonry.api'
|
291
|
+
when :pdm
|
292
|
+
next unless build_backend == 'pdm.backend'
|
293
|
+
when :hatch
|
294
|
+
next unless build_backend == 'hatchling.build'
|
295
|
+
end
|
218
296
|
format_desc(action, flag, 'opts*', after: case flag
|
219
297
|
when :python then 'srcdir?'
|
298
|
+
when :poetry then 'output?'
|
299
|
+
when :pdm then 'dest?'
|
220
300
|
when :hatch then 'location?'
|
221
301
|
end)
|
222
302
|
task flag do |_, args|
|
223
303
|
build! flag, args.to_a
|
224
304
|
end
|
305
|
+
break unless flag == :python
|
225
306
|
when 'publish'
|
226
307
|
format_desc(action, flag, 'opts*', after: case flag
|
227
308
|
when :hatch then 'artifacts?'
|
@@ -269,7 +350,7 @@ module Squared
|
|
269
350
|
end
|
270
351
|
end
|
271
352
|
|
272
|
-
def outdated(
|
353
|
+
def outdated(flag = nil, opts = [], sync: invoked_sync?('outdated'))
|
273
354
|
cmd = pip_session 'list', '--outdated'
|
274
355
|
append_global
|
275
356
|
cmd = session_done cmd
|
@@ -279,28 +360,35 @@ module Squared
|
|
279
360
|
print_item banner if sync
|
280
361
|
start = 0
|
281
362
|
found = 0
|
282
|
-
major =
|
363
|
+
major = []
|
364
|
+
minor = []
|
365
|
+
patch = []
|
283
366
|
pwd_set(from: :outdated) do
|
284
367
|
buffer = []
|
285
368
|
out = ->(val) { sync ? puts(val) : buffer << val }
|
286
369
|
IO.popen(runenv || {}, cmd).each do |line|
|
287
|
-
next if line.match?(/^[
|
370
|
+
next if line.match?(/^[ -]+$/)
|
288
371
|
|
289
372
|
if start > 0
|
290
373
|
unless stdin?
|
291
|
-
|
292
|
-
next unless
|
374
|
+
cur, lat = line.scan(SEM_VER)
|
375
|
+
next unless cur && lat
|
293
376
|
|
294
377
|
latest = lat.join
|
295
378
|
current = cur.join
|
296
379
|
semver cur
|
297
380
|
semver lat
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
381
|
+
name = line.split(' ', 2).first
|
382
|
+
type = if semmajor?(cur, lat)
|
383
|
+
major << name
|
384
|
+
2
|
385
|
+
elsif cur[2] == lat[2]
|
386
|
+
patch << name
|
387
|
+
0
|
388
|
+
else
|
389
|
+
minor << name
|
390
|
+
1
|
391
|
+
end
|
304
392
|
if type == 0
|
305
393
|
styles = color(:yellow)
|
306
394
|
else
|
@@ -334,7 +422,16 @@ module Squared
|
|
334
422
|
puts buffer
|
335
423
|
end
|
336
424
|
if found > 0
|
337
|
-
|
425
|
+
print_status(major.size, minor.size, patch.size, from: :outdated)
|
426
|
+
pkg = case flag
|
427
|
+
when :major
|
428
|
+
major + minor + patch
|
429
|
+
when :minor
|
430
|
+
minor + patch
|
431
|
+
when :patch
|
432
|
+
patch
|
433
|
+
end
|
434
|
+
install(:upgrade, pkg, strategy: opts.include?('eager') ? 'eager' : nil) unless !pkg || pkg.empty?
|
338
435
|
elsif start == 0
|
339
436
|
puts 'No updates were found'
|
340
437
|
end
|
@@ -366,6 +463,9 @@ module Squared
|
|
366
463
|
when :poetry
|
367
464
|
cmd = poetry_session 'build'
|
368
465
|
list = OPT_POETRY[:build] + OPT_POETRY[:common]
|
466
|
+
when :pdm
|
467
|
+
cmd, opts = pdm_session('build', opts: opts)
|
468
|
+
list = OPT_PDM[:build]
|
369
469
|
when :hatch
|
370
470
|
cmd, opts = hatch_session('build', opts: opts)
|
371
471
|
list = OPT_HATCH[:build]
|
@@ -373,7 +473,7 @@ module Squared
|
|
373
473
|
srcdir = nil
|
374
474
|
op = OptionPartition.new(opts, list, cmd, project: self, single: singleopt(flag))
|
375
475
|
op.each do |opt|
|
376
|
-
if !srcdir && basepath(opt).exist? && projectpath?(opt)
|
476
|
+
if !srcdir && basepath(opt.chomp('*')).exist? && projectpath?(opt.chomp('*'))
|
377
477
|
srcdir = opt
|
378
478
|
else
|
379
479
|
op.found << opt
|
@@ -381,12 +481,13 @@ module Squared
|
|
381
481
|
end
|
382
482
|
op.swap
|
383
483
|
case flag
|
384
|
-
when :poetry
|
484
|
+
when :poetry, :pdm
|
385
485
|
if srcdir
|
386
|
-
|
486
|
+
args = flag == :pdm ? ['d', 'dest'] : ['o', 'output']
|
487
|
+
if op.arg?(*args)
|
387
488
|
op.extras << srcdir
|
388
489
|
else
|
389
|
-
op << quote_option(
|
490
|
+
op << quote_option(args.last, path + srcdir)
|
390
491
|
end
|
391
492
|
srcdir = nil
|
392
493
|
end
|
@@ -408,21 +509,35 @@ module Squared
|
|
408
509
|
when :poetry
|
409
510
|
poetry_session 'publish'
|
410
511
|
list = OPT_POETRY[:publish] + OPT_POETRY[:common]
|
411
|
-
when :
|
412
|
-
|
413
|
-
list =
|
512
|
+
when :pdm
|
513
|
+
opts = pdm_session('publish', opts: opts).last
|
514
|
+
list = OPT_PDM[:publish]
|
414
515
|
when :hatch
|
415
516
|
opts = hatch_session('publish', opts: opts).last
|
416
517
|
list = OPT_HATCH[:publish]
|
518
|
+
when :twine
|
519
|
+
session 'twine', 'upload'
|
520
|
+
list = OPT_TWINE[:publish]
|
417
521
|
end
|
418
522
|
op = OptionPartition.new(opts, list, @session, project: self, single: singleopt(flag))
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
523
|
+
dist = lambda do
|
524
|
+
(path + 'dist').tap do |dir|
|
525
|
+
raise_error('no source files found', hint: dir) unless dir.directory? && !dir.empty?
|
526
|
+
end
|
423
527
|
end
|
424
|
-
|
425
|
-
|
528
|
+
case flag
|
529
|
+
when :hatch, :twine
|
530
|
+
if op.empty?
|
531
|
+
op.extras << "#{dist.call}/*"
|
532
|
+
else
|
533
|
+
op.map! { |val| path + val }
|
534
|
+
end
|
535
|
+
op.append
|
536
|
+
else
|
537
|
+
dist.call unless op.arg?(*(flag == :poetry ? ['dist-dir'] : ['d', 'dest']))
|
538
|
+
op.clear(pass: false)
|
539
|
+
end
|
540
|
+
run(from: :"#{flag}:publish", interactive: "Publish #{sub_style(project, styles: theme[:active])}")
|
426
541
|
end
|
427
542
|
|
428
543
|
def pip(flag, opts = [])
|
@@ -495,11 +610,19 @@ module Squared
|
|
495
610
|
ret
|
496
611
|
end
|
497
612
|
|
613
|
+
def pdm_session(*cmd, opts: nil)
|
614
|
+
create_session(*cmd, name: 'pdm', common: OPT_PDM[:common], opts: opts)
|
615
|
+
end
|
616
|
+
|
498
617
|
def hatch_session(*cmd, opts: nil)
|
499
|
-
|
618
|
+
create_session(*cmd, name: 'hatch', common: OPT_HATCH[:common], opts: opts)
|
619
|
+
end
|
620
|
+
|
621
|
+
def create_session(*cmd, name:, common:, opts: nil)
|
622
|
+
return session(name, *preopts, *cmd, path: venv.nil?) unless opts
|
500
623
|
|
501
|
-
op = OptionPartition.new(opts,
|
502
|
-
ret = session(
|
624
|
+
op = OptionPartition.new(opts, common, project: self, single: singleopt)
|
625
|
+
ret = session(name, *op.to_a, *cmd, path: venv.nil?)
|
503
626
|
[ret, op.extras]
|
504
627
|
end
|
505
628
|
|
@@ -577,13 +700,77 @@ module Squared
|
|
577
700
|
append_nocolor(target: target)
|
578
701
|
end
|
579
702
|
|
580
|
-
def
|
581
|
-
@
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
703
|
+
def build_backend
|
704
|
+
@build_backend ||= read_pyproject('build-system', 'build-backend') || ''
|
705
|
+
end
|
706
|
+
|
707
|
+
def read_pyproject(table, key = nil)
|
708
|
+
return [] unless (file = pyprojectfile)
|
709
|
+
|
710
|
+
unless (ret = (@pyproject ||= {})[table])
|
711
|
+
ret = []
|
712
|
+
start = /^\s*\[#{Regexp.escape(table)}\]\s*$/
|
713
|
+
ch = nil
|
714
|
+
found = false
|
715
|
+
File.foreach(file) do |line|
|
716
|
+
if found
|
717
|
+
break if line.match?(/^\s*\[[\w.-]+\]\s*$/)
|
718
|
+
|
719
|
+
if ch
|
720
|
+
val = line.rstrip
|
721
|
+
case ch
|
722
|
+
when '}', ']'
|
723
|
+
ch = nil if val.end_with?(ch)
|
724
|
+
val = "\n#{val}"
|
725
|
+
else
|
726
|
+
if val.chomp!(ch)
|
727
|
+
ch = nil
|
728
|
+
else
|
729
|
+
val = line
|
730
|
+
end
|
731
|
+
end
|
732
|
+
ret.last[1] += val
|
733
|
+
elsif (data = line.match(/^\s*(\S+)\s*=\s*([+-]?[\d.]+|true|false|("""|'''|["'\[{])(.*?))\s*$/))
|
734
|
+
if (val = data[4])
|
735
|
+
case (ch = data[3])
|
736
|
+
when '{', '['
|
737
|
+
val = "#{ch}#{val}"
|
738
|
+
ch = ch == '{' ? '}' : ']'
|
739
|
+
ch = nil if val.end_with?(ch)
|
740
|
+
else
|
741
|
+
if val.chomp!(ch)
|
742
|
+
ch = nil
|
743
|
+
elsif ch.size == 1
|
744
|
+
next
|
586
745
|
end
|
746
|
+
end
|
747
|
+
else
|
748
|
+
val = case (val = data[2])
|
749
|
+
when 'true'
|
750
|
+
true
|
751
|
+
when 'false'
|
752
|
+
false
|
753
|
+
else
|
754
|
+
val.include?('.') ? val.to_f : val.to_i
|
755
|
+
end
|
756
|
+
end
|
757
|
+
ret << [data[1], val]
|
758
|
+
end
|
759
|
+
else
|
760
|
+
found = line.match?(start)
|
761
|
+
end
|
762
|
+
end
|
763
|
+
@pyproject[table] = ret
|
764
|
+
end
|
765
|
+
return ret.find { |val| val[0] == key }&.last if key
|
766
|
+
|
767
|
+
ret
|
768
|
+
end
|
769
|
+
|
770
|
+
def pyprojectfile
|
771
|
+
return unless (ret = basepath(DEP_PYTHON[2])).exist?
|
772
|
+
|
773
|
+
ret
|
587
774
|
end
|
588
775
|
|
589
776
|
def singleopt(flag = nil)
|
@@ -626,7 +813,18 @@ module Squared
|
|
626
813
|
@venv&.join(workspace.windows? ? 'Scripts' : 'bin')
|
627
814
|
end
|
628
815
|
|
816
|
+
def editable_set(val)
|
817
|
+
@editable = case val
|
818
|
+
when '.', Pathname
|
819
|
+
val
|
820
|
+
when String
|
821
|
+
Pathname.new(editable)
|
822
|
+
end
|
823
|
+
end
|
824
|
+
|
629
825
|
def venv_set(val)
|
826
|
+
return unless val
|
827
|
+
|
630
828
|
if val.is_a?(Array)
|
631
829
|
val, *opts = val
|
632
830
|
@venvopts = opts
|