squared 0.5.2 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -0
- data/README.ruby.md +4 -2
- data/lib/squared/common/format.rb +6 -4
- data/lib/squared/common/prompt.rb +3 -3
- data/lib/squared/common/shell.rb +1 -2
- data/lib/squared/common/utils.rb +9 -0
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +14 -10
- data/lib/squared/workspace/project/base.rb +157 -113
- data/lib/squared/workspace/project/docker.rb +21 -24
- data/lib/squared/workspace/project/git.rb +25 -27
- data/lib/squared/workspace/project/node.rb +63 -21
- data/lib/squared/workspace/project/python.rb +15 -11
- data/lib/squared/workspace/project/ruby.rb +83 -48
- data/lib/squared/workspace/project/support/class.rb +2 -4
- data/lib/squared/workspace/series.rb +4 -4
- data/lib/squared/workspace/support/base.rb +17 -0
- data/lib/squared/workspace/support.rb +1 -0
- data/lib/squared/workspace.rb +0 -8
- data/squared.gemspec +2 -2
- metadata +3 -2
@@ -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
|
|
@@ -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
|
370
|
+
next if task_pass?(action)
|
367
371
|
|
368
372
|
namespace action do
|
369
373
|
flags.each do |flag|
|
@@ -862,19 +866,14 @@ module Squared
|
|
862
866
|
args = args.to_a
|
863
867
|
if args.empty? || args.last == ':'
|
864
868
|
files = []
|
865
|
-
status_data.each
|
866
|
-
case (flag == :staged ? line[2] : line[1])
|
867
|
-
when /[AMDRTC]/
|
868
|
-
files << line[0]
|
869
|
-
end
|
870
|
-
end
|
869
|
+
status_data.each { |row| files << row[0] if row[flag == :staged ? 2 : 1].match?(/[AMDRTC]/) }
|
871
870
|
unless files.empty?
|
872
871
|
files = choice_index('Select a file', files, multiple: true, force: false,
|
873
872
|
accept: 'Restore?')
|
874
873
|
end
|
875
874
|
args.pop
|
876
875
|
args, glob = args.partition { |val| val.match?(/^(?:[a-z-]+=|[^*]+$)/) }
|
877
|
-
|
876
|
+
files.concat(glob)
|
878
877
|
next if args.empty? && files.empty?
|
879
878
|
end
|
880
879
|
restore(flag, args, files: files)
|
@@ -882,10 +881,11 @@ module Squared
|
|
882
881
|
end
|
883
882
|
when 'git'
|
884
883
|
before = case flag
|
884
|
+
when :blame then 'file'
|
885
885
|
when :mv then 'source+,destination'
|
886
886
|
when :revert then 'commit+' end
|
887
887
|
format_desc(action, flag, 'opts*', before: before, after: case flag
|
888
|
-
when :add then 'pathspec
|
888
|
+
when :add then 'pathspec*,:pattern:*'
|
889
889
|
when :clean, :rm then 'pathspec*' end)
|
890
890
|
task flag do |_, args|
|
891
891
|
git flag, args.to_a
|
@@ -1146,10 +1146,7 @@ module Squared
|
|
1146
1146
|
rescue StandardError => e
|
1147
1147
|
warn log_message(Logger::WARN, e, pass: true) if warning?
|
1148
1148
|
else
|
1149
|
-
|
1150
|
-
msg = sub_style('completed', styles: theme[:active])
|
1151
|
-
puts log_message(Logger::INFO, name, msg, subject: 'revbuild', hint: time_format(epochtime - start))
|
1152
|
-
end
|
1149
|
+
print_status(name, subject: 'revbuild', start: start, from: :completed)
|
1153
1150
|
workspace.rev_write(name, { 'revision' => sha, 'files' => status_digest(*args, **kwargs) },
|
1154
1151
|
sync: sync, utc: 'build')
|
1155
1152
|
end
|
@@ -1627,10 +1624,16 @@ module Squared
|
|
1627
1624
|
|
1628
1625
|
def git(flag, opts = [])
|
1629
1626
|
cmd, opts = git_session(flag, opts: opts)
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
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)
|
1633
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
|
1634
1637
|
when :revert
|
1635
1638
|
if VAL_GIT[:rebase][:send].any? { |val| op.arg?(val) }
|
1636
1639
|
op.clear
|
@@ -1641,14 +1644,13 @@ module Squared
|
|
1641
1644
|
end
|
1642
1645
|
when :add, :clean
|
1643
1646
|
if flag == :add && !op.arg?('pathspec-from-file')
|
1644
|
-
grep, list = op.
|
1645
|
-
|
1646
|
-
red = color(:red)
|
1647
|
+
grep, list = op.partition { |val| val.start_with?(':') && val.end_with?(':') }
|
1648
|
+
unless grep.empty? && !list.empty?
|
1647
1649
|
grep.map! { |val| Regexp.new(val[1..-2]) }
|
1648
1650
|
files = status_data.map! do |a, b|
|
1649
1651
|
next if b.strip.empty? || (!grep.empty? && grep.none? { |pat| pat.match?(a) })
|
1650
1652
|
|
1651
|
-
"#{sub_style(b, styles: red)} #{a}"
|
1653
|
+
"#{sub_style(b, styles: color(:red))} #{a}"
|
1652
1654
|
end
|
1653
1655
|
.compact
|
1654
1656
|
unless files.empty?
|
@@ -1745,11 +1747,7 @@ module Squared
|
|
1745
1747
|
end
|
1746
1748
|
end
|
1747
1749
|
rescue StandardError => e
|
1748
|
-
|
1749
|
-
ret = on :error, from, e
|
1750
|
-
raise if exception && ret != true
|
1751
|
-
|
1752
|
-
warn log_message(Logger::WARN, e, pass: true) if warning?
|
1750
|
+
on_error(e, from, pass: true)
|
1753
1751
|
nil
|
1754
1752
|
else
|
1755
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
|
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
|
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 ||
|
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
|
-
|
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 ? '
|
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
|
-
|
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,
|
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(
|
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
|
-
|
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
|
-
|
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]
|
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
|
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(' ')
|
@@ -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
|
-
|
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
|
@@ -488,7 +492,7 @@ module Squared
|
|
488
492
|
if srcdir
|
489
493
|
args = flag == :pdm ? ['d', 'dest'] : ['o', 'output']
|
490
494
|
if op.arg?(*args)
|
491
|
-
op.
|
495
|
+
op.push(srcdir)
|
492
496
|
else
|
493
497
|
op << quote_option(args.last, path + srcdir)
|
494
498
|
end
|
@@ -531,7 +535,7 @@ module Squared
|
|
531
535
|
case flag
|
532
536
|
when :hatch, :twine
|
533
537
|
if op.empty?
|
534
|
-
op.
|
538
|
+
op.push("#{dist.call}/*")
|
535
539
|
else
|
536
540
|
op.map! { |val| path + val }
|
537
541
|
end
|
@@ -655,7 +659,7 @@ module Squared
|
|
655
659
|
if edit
|
656
660
|
edit = path + edit unless %r{^[a-z]+(?:\+[a-z]+)?://}i.match?(edit)
|
657
661
|
if flag == :editable
|
658
|
-
op.
|
662
|
+
op.push(edit)
|
659
663
|
else
|
660
664
|
target << quote_option('e', edit)
|
661
665
|
end
|
@@ -851,17 +855,17 @@ module Squared
|
|
851
855
|
return if !venv || (venvbin.directory? && !venvbin.empty?)
|
852
856
|
|
853
857
|
puts log_message(Logger::INFO, venv, subject: 'venv', hint: 'init')
|
854
|
-
|
855
|
-
venv_create(venv,
|
858
|
+
opts = @venvopts&.map { |val| OptionPartition.strip(val) }&.flatten
|
859
|
+
venv_create(venv, opts || ["prompt=#{name}", 'upgrade-deps'], env: false, banner: false)
|
856
860
|
puts log_message(Logger::INFO, venv, subject: 'venv', hint: 'created')
|
857
861
|
end
|
858
862
|
|
859
863
|
def venv_create(dir, opts = [], env: nil, banner: true)
|
860
864
|
cmd, opts = python_session('-m venv', opts: opts)
|
861
865
|
op = OptionPartition.new(opts, OPT_PYTHON[:venv], cmd, project: self)
|
862
|
-
op.append(dir, delim: true)
|
863
|
-
|
864
|
-
|
866
|
+
status = op.append(dir, delim: true)
|
867
|
+
.clear(pass: false)
|
868
|
+
.arg?(/\A-v+\z/, 'verbose')
|
865
869
|
run(op, env, exception: true, banner: banner)
|
866
870
|
puts(dir.directory? ? "Success: #{dir}" : 'Failed') if banner && !status
|
867
871
|
end
|