squared 0.4.9 → 0.4.11
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 +34 -0
- data/README.md +15 -17
- data/README.ruby.md +12 -6
- data/lib/squared/common/prompt.rb +32 -11
- data/lib/squared/common/system.rb +4 -4
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +3 -2
- data/lib/squared/workspace/project/base.rb +7 -7
- data/lib/squared/workspace/project/docker.rb +91 -52
- data/lib/squared/workspace/project/git.rb +93 -64
- data/lib/squared/workspace/project/node.rb +27 -25
- data/lib/squared/workspace/project/python.rb +4 -4
- data/lib/squared/workspace/project/ruby.rb +12 -5
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa16edc572cc39bb0bef0b2b5ba04419f2994e824923b354182f9e60b6aee1b2
|
4
|
+
data.tar.gz: 75a6b805d236d45f09b331bf62cbfcc5f9b043632d194474511763c7fc7fbf64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 510b7807e4e2be74dfe8ba5202115e3b5cefbd27d94cb14af169007bcdedde7f8c8516679c1bc614cb633eb1a904a6309403346f7c0c8490ad13fa208f2bd1f0
|
7
|
+
data.tar.gz: 3a124f06b78467a4eda6a1f34c2a80f6bb9f78867c5daefbcb0f628d9eb6a4bfbf0193e0d5509f38000e7e6ce6c8c3f4d112f0c0146260d30664692cda495186
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,37 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.4.11] - 2025-05-09
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Docker command build action bake is interactive.
|
8
|
+
|
9
|
+
### Fixed
|
10
|
+
|
11
|
+
- Docker build command was not functional.
|
12
|
+
|
13
|
+
## [0.4.10] - 2025-05-08
|
14
|
+
|
15
|
+
### Added
|
16
|
+
|
17
|
+
- Git command pull and fetch action remote is interactive.
|
18
|
+
- Ruby command script uses multiline input when available.
|
19
|
+
- Ruby command file is interactive.
|
20
|
+
- Node command publish can accept access option levels.
|
21
|
+
- Docker command image action rm when called empty is interactive.
|
22
|
+
|
23
|
+
### Fixed
|
24
|
+
|
25
|
+
- Disabled batch and alias tasks were not hidden.
|
26
|
+
- Docker tags from ENV were appended twice.
|
27
|
+
- Git events were not always registered.
|
28
|
+
- Git revbuild did not write lock data file with parallel tasks.
|
29
|
+
|
30
|
+
### Changed
|
31
|
+
|
32
|
+
- Choice selection default was set to no timeout.
|
33
|
+
- Git command add can accept a file search pattern.
|
34
|
+
|
3
35
|
## [0.4.9] - 2025-04-27
|
4
36
|
|
5
37
|
### Added
|
@@ -633,6 +665,8 @@
|
|
633
665
|
|
634
666
|
- Changelog was created.
|
635
667
|
|
668
|
+
[0.4.11]: https://github.com/anpham6/squared/releases/tag/v0.4.11-ruby
|
669
|
+
[0.4.10]: https://github.com/anpham6/squared/releases/tag/v0.4.10-ruby
|
636
670
|
[0.4.9]: https://github.com/anpham6/squared/releases/tag/v0.4.9-ruby
|
637
671
|
[0.4.8]: https://github.com/anpham6/squared/releases/tag/v0.4.8-ruby
|
638
672
|
[0.4.7]: https://github.com/anpham6/squared/releases/tag/v0.4.7-ruby
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# squared 5.
|
1
|
+
# squared 5.5
|
2
2
|
|
3
3
|
## Documentation
|
4
4
|
|
@@ -15,10 +15,11 @@
|
|
15
15
|
* [squared-express](https://github.com/anpham6/squared-express#readme)
|
16
16
|
* [E-mc](https://github.com/anpham6/e-mc#readme)
|
17
17
|
* [Pi-r](https://github.com/anpham6/pi-r#readme)
|
18
|
+
* [Pi-r2](https://github.com/anpham6/pi-r2#readme)
|
18
19
|
|
19
20
|
## Installation
|
20
21
|
|
21
|
-
* NodeJS
|
22
|
+
* NodeJS 18
|
22
23
|
|
23
24
|
### NPX
|
24
25
|
|
@@ -131,26 +132,22 @@ rake clone # node + docs
|
|
131
132
|
|
132
133
|
```sh
|
133
134
|
# NODE_TAG=latest
|
134
|
-
# RUBY_VERSION=2.4.0-3.
|
135
|
-
# MANIFEST=nightly,
|
135
|
+
# RUBY_VERSION=2.4.0-3.4.0
|
136
|
+
# MANIFEST=nightly,prod,latest,android
|
136
137
|
# BUILD={dev,prod}
|
137
138
|
# DEV={0,1,local}
|
138
139
|
# DOCS=any
|
139
140
|
# PIPE_FAIL={0,1}
|
140
141
|
# PORT=3000
|
141
|
-
docker build -t squared --build-arg MANIFEST=prod --build-arg
|
142
|
-
docker build -t node --build-arg NODE_TAG=
|
143
|
-
docker buildx bake node
|
142
|
+
docker build -t squared --build-arg MANIFEST=prod --build-arg NODE_ENV=production .
|
143
|
+
docker build -t node --build-arg NODE_TAG=22 --build-arg NODE_INSTALL=pnpm -f Dockerfile.slim .
|
144
|
+
NODE=22 docker buildx bake node
|
144
145
|
# OR
|
145
|
-
|
146
|
-
|
147
|
-
docker build -t ruby --build-arg RUBY_TAG=3.0.0 --build-arg NODE_VERSION=20.x --build-arg PIPE_FAIL=0 -f Dockerfile.ruby .
|
148
|
-
docker buildx bake ruby
|
146
|
+
docker build -t ruby --build-arg RUBY_TAG=3.4.0 --build-arg NODE_VERSION=22 --build-arg PIPE_FAIL=0 -f Dockerfile.ruby .
|
147
|
+
RUBY=3.4.0 docker buildx bake ruby
|
149
148
|
# OR
|
150
|
-
|
151
|
-
|
152
|
-
docker build -t nginx --build-arg NGINX_VERSION=1.27 --build-arg PORT=3000 --build-arg NODE_VERSION=18.x -f Dockerfile.nginx .
|
153
|
-
docker buildx bake nginx
|
149
|
+
docker build -t nginx --build-arg NGINX_VERSION=1.27 --build-arg PORT=3000 --build-arg NODE_VERSION=20 -f Dockerfile.nginx .
|
150
|
+
NGINX=1.27 docker buildx bake nginx
|
154
151
|
|
155
152
|
# Express
|
156
153
|
docker run -it --name express --rm -p 3000:3000 \
|
@@ -521,6 +518,7 @@ squared.settings = {
|
|
521
518
|
],
|
522
519
|
compressImages: false, // TinyPNG API Key <https://tinypng.com/developers>
|
523
520
|
compressImages: "****************", // API key
|
521
|
+
compressImages: [{ plugin: "imagemin-pngquant", format: "png", options: { quality: [0.6, 0.8] } }], // v5.5
|
524
522
|
convertImages: "", // png | jpeg | webp | gif | bmp
|
525
523
|
showAttributes: true,
|
526
524
|
showAttributes: {
|
@@ -541,7 +539,7 @@ squared.settings = {
|
|
541
539
|
showErrorMessages: false,
|
542
540
|
convertPixels: "dp", // "sp" | "pt" | "in" | "mm"
|
543
541
|
convertLineHeight: "sp", // "dp" | "pt" | "in" | "mm"
|
544
|
-
convertEntities: ["numeric"],
|
542
|
+
convertEntities: ["numeric"],
|
545
543
|
convertEntities: ["codepoints", {/* JSON (last) */}], // https://html.spec.whatwg.org/entities.json
|
546
544
|
insertSpaces: 4,
|
547
545
|
outputDocumentHandler: "android",
|
@@ -1361,4 +1359,4 @@ NOTE: Defining an element "**id**" will prevent it from being removed during the
|
|
1361
1359
|
|
1362
1360
|
## LICENSE
|
1363
1361
|
|
1364
|
-
BSD 3-Clause
|
1362
|
+
BSD 3-Clause
|
data/README.ruby.md
CHANGED
@@ -98,6 +98,9 @@ Workspace::Application
|
|
98
98
|
with(exclude: [:base]) { add("publish/*", "packages") } # rake packages:sqd-serve:build
|
99
99
|
# OR
|
100
100
|
add(["publish/sqd-cli", "publish/sqd-serve"], true, exclude: [:base]) # rake squared:sqd-serve:build
|
101
|
+
|
102
|
+
# Git
|
103
|
+
revbuild(include: %w[src/ framework/ types/]) # Synchronous is recommended
|
101
104
|
end
|
102
105
|
.add("squared/sqd", exclude: :git, pass: [:node, "checkout", "bump"]) do # Skip initialize(:node) + squared:checkout:* + squared:bump:*
|
103
106
|
variable_set :script, "build:sqd" # Override detection
|
@@ -116,9 +119,9 @@ Workspace::Application
|
|
116
119
|
end
|
117
120
|
end
|
118
121
|
end
|
119
|
-
.pass("pull", group: "default") { test? || doc? } # pathname:pull | optparse:pull
|
122
|
+
.pass("pull", group: "default") { test? || doc? } # rake pathname:pull | rake optparse:pull
|
120
123
|
.style("banner", 255.255) # 256 colors (fg | fg.bg | -0.bg)
|
121
|
-
.build(default: "build", parallel: ["pull", "fetch", "rebase", "archive", "
|
124
|
+
.build(default: "build", parallel: ["pull", "fetch", "rebase", "archive", "clean", /^outdated:/], pass: ["publish"]) do |workspace|
|
122
125
|
workspace
|
123
126
|
.enable_aixterm
|
124
127
|
.style({
|
@@ -194,9 +197,9 @@ Workspace::Application
|
|
194
197
|
"pir": { # rake pir:clone
|
195
198
|
uri: "https://github.com/anpham6/pi-r", #
|
196
199
|
options: { #
|
197
|
-
"origin": "github", # --origin=
|
200
|
+
"origin": "github", # --origin=github
|
198
201
|
"recurse-submodules": false, # --no-recurse-submodules
|
199
|
-
"shallow-exclude": ["v0.0.1", "v0.0.2"] # --shallow-exclude=
|
202
|
+
"shallow-exclude": ["v0.0.1", "v0.0.2"] # --shallow-exclude=v0.0.1 --shallow-exclude=v0.0.2
|
200
203
|
}
|
201
204
|
}
|
202
205
|
)
|
@@ -238,7 +241,7 @@ Workspace::Application
|
|
238
241
|
.new(main: "squared")
|
239
242
|
.graph(["depend"], ref: :git) # Optional
|
240
243
|
.with(:python) do
|
241
|
-
doc(windows? ?
|
244
|
+
doc(windows? ? ".\make.bat html" : "make html") # rake android-docs:doc | rake doc:python
|
242
245
|
add("android-docs", "android", venv: "/home/user/.venv") # rake android-docs:depend
|
243
246
|
add("chrome-docs", "chrome", graph: "android", venv: ".venv") do # /workspaces/chrome-docs/.venv
|
244
247
|
variable_set :dependindex, 2 # Use Poetry for dependencies (optional)
|
@@ -490,7 +493,7 @@ rake squared:log:view[H1,HEAD^5,all,lib,./H12345] # git log --all @~1 @^5 -- 'l
|
|
490
493
|
All project binary programs can have their executable path set to a non-global alias.
|
491
494
|
|
492
495
|
```ruby
|
493
|
-
Common::PATH.
|
496
|
+
Common::PATH.update({
|
494
497
|
GIT: "/usr/bin/git", # PATH_GIT=/usr/bin/git
|
495
498
|
TAR: "/opt/archivers/tar", # PATH_TAR=/opt/archivers/tar
|
496
499
|
UNZIP: "/opt/archivers/unzip",
|
@@ -593,6 +596,7 @@ GIT_AUTOSTASH_${NAME}=0 # rebase (project only)
|
|
593
596
|
| log | * | PATHSPEC=s |
|
594
597
|
| pull | rebase | AUTOSTASH |
|
595
598
|
| pull | remote | REFSPEC=s |
|
599
|
+
| pull | -remote | ALL |
|
596
600
|
| pull | * | REBASE=0,1 FORCE RECURSE_SUBMODULES=0,1,s |
|
597
601
|
| rebase | branch | HEAD=s |
|
598
602
|
| rebase | onto | INTERACTIVE I HEAD=s |
|
@@ -621,6 +625,7 @@ DOCKER_OPTIONS_${NAME}=v,no-cache=false # project only (override)
|
|
621
625
|
DOCKER_TAG=latest # all
|
622
626
|
DOCKER_TAG_${NAME}=v0.1.0 # project only (override)
|
623
627
|
DOCKER_ALL=1 # list every image/container
|
628
|
+
DOCKER_Y=1 # confirm all
|
624
629
|
```
|
625
630
|
|
626
631
|
| Command | Flag | ENV |
|
@@ -629,6 +634,7 @@ DOCKER_ALL=1 # list every image/container
|
|
629
634
|
| buildx | bake | SERVICE=s |
|
630
635
|
| compose | build | TARGET=s |
|
631
636
|
| container | commit | REGISTRY=s PLATFORM=s DISABLE_CONTENT_TRUST=0,1 |
|
637
|
+
| image | rm | Y=0,1 |
|
632
638
|
| image | push | TAG=s REGISTRY=s |
|
633
639
|
|
634
640
|
### Repo
|
@@ -8,8 +8,8 @@ module Squared
|
|
8
8
|
def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 30)
|
9
9
|
require 'readline'
|
10
10
|
require 'timeout'
|
11
|
-
agree = /^#{agree}$/i if agree.is_a?(::String)
|
12
|
-
cancel = /^#{cancel}$/i if cancel.is_a?(::String)
|
11
|
+
agree = /^#{Regexp.escape(agree)}$/i if agree.is_a?(::String)
|
12
|
+
cancel = /^#{Regexp.escape(cancel)}$/i if cancel.is_a?(::String)
|
13
13
|
Timeout.timeout(timeout) do
|
14
14
|
begin
|
15
15
|
while (ch = Readline.readline(msg))
|
@@ -32,24 +32,28 @@ module Squared
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
def choice(msg, list = nil, min: 1, max: 1, multiple: false,
|
35
|
+
def choice(msg, list = nil, min: 1, max: 1, multiple: false, force: true, grep: nil, auto: true,
|
36
|
+
attempts: 5, timeout: 0)
|
36
37
|
require 'readline'
|
37
38
|
require 'timeout'
|
38
39
|
if list
|
40
|
+
grep &&= (grep.is_a?(::Enumerable) ? grep : [grep]).map { |val| Regexp.new(val) }
|
39
41
|
items = []
|
40
|
-
list.
|
41
|
-
|
42
|
+
list.each do |val|
|
43
|
+
next if grep&.none? { |pat| pat.match?(line) }
|
44
|
+
|
42
45
|
items << val.chomp
|
46
|
+
puts "#{items.size.to_s.rjust(2)}. #{val}"
|
43
47
|
end
|
44
48
|
max = items.size
|
49
|
+
raise_error 'empty selection list' if max == 0
|
50
|
+
min = [min, max].min
|
45
51
|
if auto
|
46
52
|
msg = "#{msg}: [1-#{max}#{if multiple
|
47
53
|
"|,#{multiple.is_a?(Numeric) ? "{#{multiple}}" : ''}"
|
48
54
|
end}] "
|
49
55
|
end
|
50
56
|
end
|
51
|
-
return unless max >= min
|
52
|
-
|
53
57
|
valid = ->(s) { s.match?(/^-?\d+$/) && s.to_i.between?(min, max) }
|
54
58
|
Timeout.timeout(timeout) do
|
55
59
|
begin
|
@@ -82,16 +86,33 @@ module Squared
|
|
82
86
|
end
|
83
87
|
end
|
84
88
|
|
85
|
-
def readline(msg, history = false, force: nil)
|
89
|
+
def readline(msg, history = false, force: nil, multiline: nil, &blk)
|
86
90
|
require 'readline'
|
91
|
+
multiline = if multiline && Readline.respond_to?(:readmultiline)
|
92
|
+
multiline.is_a?(::Enumerable) || block_given? ? multiline : [multiline.to_s]
|
93
|
+
end
|
94
|
+
prompt = lambda do
|
95
|
+
if !multiline
|
96
|
+
Readline.readline(msg, history)
|
97
|
+
elsif block_given?
|
98
|
+
Readline.readmultiline(msg, history, &blk)
|
99
|
+
else
|
100
|
+
Readline.readmultiline(msg, history) { |line| multiline.any? { |val| line.split.last.end_with?(val) } }
|
101
|
+
end
|
102
|
+
end
|
87
103
|
case force
|
88
104
|
when ::TrueClass, ::FalseClass
|
89
|
-
msg = "#{msg}
|
90
|
-
|
105
|
+
msg = "#{msg} %s " % if multiline
|
106
|
+
multiline.is_a?(::Enumerable) ? "{#{multiline.join('|')}}" : multiline
|
107
|
+
else
|
108
|
+
"(#{force ? 'required' : 'optional'}):"
|
109
|
+
end
|
110
|
+
ret = (prompt.call || '').strip
|
111
|
+
multiline.each { |val| break if ret.delete_suffix!(val) } if multiline.is_a?(::Enumerable)
|
91
112
|
raise_error 'user cancelled' if force && ret.empty?
|
92
113
|
ret
|
93
114
|
else
|
94
|
-
|
115
|
+
prompt.call
|
95
116
|
end
|
96
117
|
end
|
97
118
|
end
|
@@ -29,10 +29,10 @@ module Squared
|
|
29
29
|
dest.mkpath if create
|
30
30
|
if pass
|
31
31
|
exclude = []
|
32
|
-
pass = [pass] unless pass.is_a?(::
|
32
|
+
pass = [pass] unless pass.is_a?(::Enumerable)
|
33
33
|
pass.each { |val| exclude.concat(Dir.glob(src + val)) }
|
34
34
|
end
|
35
|
-
(glob.is_a?(::
|
35
|
+
(glob.is_a?(::Enumerable) ? glob : [glob]).each do |val|
|
36
36
|
Dir.glob(src + val) do |path|
|
37
37
|
next if exclude&.include?(path) || (path = Pathname.new(path)).directory?
|
38
38
|
|
@@ -79,7 +79,7 @@ module Squared
|
|
79
79
|
def copy_guard(src, dest, link: nil, force: false, verbose: true)
|
80
80
|
unless force
|
81
81
|
if (path = Pathname.new(dest)).directory?
|
82
|
-
src = [src] unless src.is_a?(::
|
82
|
+
src = [src] unless src.is_a?(::Enumerable)
|
83
83
|
src = src.reject { |val| path.join(File.basename(val)).exist? }
|
84
84
|
return if src.empty?
|
85
85
|
elsif path.exist?
|
@@ -89,7 +89,7 @@ module Squared
|
|
89
89
|
case link
|
90
90
|
when 'hard', 1
|
91
91
|
FileUtils.ln(src, dest, force: force, verbose: verbose)
|
92
|
-
when TrueClass, 'soft', 0
|
92
|
+
when ::TrueClass, 'soft', 0
|
93
93
|
FileUtils.ln_s(src, dest, force: force, verbose: verbose)
|
94
94
|
else
|
95
95
|
FileUtils.cp(src, dest, verbose: verbose)
|
data/lib/squared/version.rb
CHANGED
@@ -463,7 +463,7 @@ module Squared
|
|
463
463
|
tasks << key if obj.has?(key, baseref)
|
464
464
|
elsif (batch = series.batch_get(key))
|
465
465
|
obj.allref.each do |ref|
|
466
|
-
next unless (data = batch[ref])
|
466
|
+
next unless obj.has?(key, ref) && (data = batch[ref])
|
467
467
|
|
468
468
|
data.each do |val|
|
469
469
|
if (items = task_resolve(obj, val)).empty?
|
@@ -482,7 +482,7 @@ module Squared
|
|
482
482
|
return [] if (base && !obj.ref?(baseref)) || !(data = series.alias_get(key))
|
483
483
|
|
484
484
|
obj.allref.each do |ref|
|
485
|
-
next unless (alt = data[ref])
|
485
|
+
next unless obj.has?(key, ref) && (alt = data[ref])
|
486
486
|
|
487
487
|
ret = task_resolve(obj, alt)
|
488
488
|
break unless ret.empty?
|
@@ -602,6 +602,7 @@ module Squared
|
|
602
602
|
end
|
603
603
|
|
604
604
|
def powershell?
|
605
|
+
return true if ENV['SHELL']&.end_with?(File.join('', 'pwsh'))
|
605
606
|
return false unless windows?
|
606
607
|
|
607
608
|
case ENV['TERM_PROGRAM']
|
@@ -1505,11 +1505,11 @@ module Squared
|
|
1505
1505
|
confirm("Upgrade to #{a}? #{b + e} [#{c}] ", d)
|
1506
1506
|
end
|
1507
1507
|
|
1508
|
-
def choice_index(msg, list, values: nil,
|
1509
|
-
|
1508
|
+
def choice_index(msg, list, values: nil, accept: nil, series: false, trim: nil, column: nil,
|
1509
|
+
multiple: false, force: true, **kwargs)
|
1510
1510
|
puts if !series && @@print_order > 0
|
1511
1511
|
msg = "#{msg} (optional)" unless force
|
1512
|
-
unless (ret = choice(msg, list, multiple: multiple, force: force,
|
1512
|
+
unless (ret = choice(msg, list, multiple: multiple, force: force, **kwargs)) || !force
|
1513
1513
|
raise_error 'user cancelled'
|
1514
1514
|
end
|
1515
1515
|
if ret.nil? || ret.empty?
|
@@ -1855,14 +1855,14 @@ module Squared
|
|
1855
1855
|
end
|
1856
1856
|
|
1857
1857
|
def has_value?(data, val)
|
1858
|
-
return data.value?(val) if data.is_a?(
|
1859
|
-
return data.is_a?(
|
1858
|
+
return data.value?(val) if data.is_a?(Hash)
|
1859
|
+
return data.is_a?(Enumerable) && data.to_a.include?(val) if !val.is_a?(Enumerable) || val.is_a?(Hash)
|
1860
1860
|
|
1861
1861
|
val.to_a.any? do |obj|
|
1862
1862
|
case data
|
1863
|
-
when
|
1863
|
+
when Hash
|
1864
1864
|
data.value?(obj)
|
1865
|
-
when
|
1865
|
+
when Enumerable
|
1866
1866
|
data.to_a.include?(obj)
|
1867
1867
|
end
|
1868
1868
|
end
|
@@ -138,10 +138,14 @@ module Squared
|
|
138
138
|
buildx(:build, args.extras, "#{flag}": param)
|
139
139
|
end
|
140
140
|
when :bake
|
141
|
-
format_desc action, flag, 'opts*,target*,context?'
|
141
|
+
format_desc action, flag, ':?,opts*,target*,context?'
|
142
142
|
task flag do |_, args|
|
143
|
-
args =
|
144
|
-
|
143
|
+
args = args.to_a
|
144
|
+
if args.first == ':'
|
145
|
+
choice_command :bake
|
146
|
+
else
|
147
|
+
buildx flag, args
|
148
|
+
end
|
145
149
|
end
|
146
150
|
end
|
147
151
|
when 'compose'
|
@@ -196,7 +200,12 @@ module Squared
|
|
196
200
|
when :list, :rm
|
197
201
|
format_desc(action, flag, flag == :rm ? 'id*,opts*' : 'opts*,args*')
|
198
202
|
task flag do |_, args|
|
199
|
-
|
203
|
+
args = args.to_a
|
204
|
+
if flag == :rm && args.empty?
|
205
|
+
choice_command :rm
|
206
|
+
else
|
207
|
+
image flag, args
|
208
|
+
end
|
200
209
|
end
|
201
210
|
end
|
202
211
|
when 'network'
|
@@ -221,11 +230,11 @@ module Squared
|
|
221
230
|
image(:rm, sync: sync)
|
222
231
|
end
|
223
232
|
|
224
|
-
def compose(opts, flags = nil, script: false, args: nil, from: :
|
233
|
+
def compose(opts, flags = nil, script: false, args: nil, from: :run, **)
|
225
234
|
return opts if script == false
|
226
235
|
|
227
236
|
ret = docker_session
|
228
|
-
if from == :
|
237
|
+
if from == :run
|
229
238
|
case (n = filetype)
|
230
239
|
when 1, 2
|
231
240
|
ret << 'buildx' << 'bake'
|
@@ -249,14 +258,16 @@ module Squared
|
|
249
258
|
when Enumerable
|
250
259
|
ret.merge(opts.to_a)
|
251
260
|
end
|
252
|
-
[args, flags].each_with_index do |target, index|
|
253
|
-
next unless target
|
254
261
|
|
255
|
-
|
256
|
-
|
262
|
+
[args, flags].each_with_index do |target, index|
|
263
|
+
if target.is_a?(String)
|
264
|
+
ret << target
|
265
|
+
elsif (target = append_any(target, target: []))
|
266
|
+
ret.merge(target.map { |arg| index == 0 ? fill_option(arg) : quote_option('build-arg', arg) })
|
267
|
+
end
|
257
268
|
end
|
258
269
|
case from
|
259
|
-
when :
|
270
|
+
when :run
|
260
271
|
case @secrets
|
261
272
|
when String
|
262
273
|
ret << quote_option('secret', @secrets, double: true)
|
@@ -271,7 +282,6 @@ module Squared
|
|
271
282
|
end
|
272
283
|
if (val = option('tag', ignore: false))
|
273
284
|
append_tag val
|
274
|
-
ret << basic_option('tag', tagname(val))
|
275
285
|
elsif !session_arg?('t', 'tag')
|
276
286
|
append_tag tag
|
277
287
|
end
|
@@ -331,7 +341,7 @@ module Squared
|
|
331
341
|
def container(flag, opts = [], id: nil)
|
332
342
|
cmd, opts = docker_session('container', flag, opts: opts)
|
333
343
|
list = OPT_DOCKER[:container].fetch(flag, [])
|
334
|
-
list
|
344
|
+
list += OPT_DOCKER[:container][:update] if flag == :run
|
335
345
|
op = OptionPartition.new(opts, list, cmd, project: self, args: flag == :run || flag == :exec)
|
336
346
|
from = :"container:#{flag}"
|
337
347
|
case flag
|
@@ -433,6 +443,8 @@ module Squared
|
|
433
443
|
def image(flag, opts = [], sync: true, id: nil, registry: nil)
|
434
444
|
cmd, opts = docker_session('image', flag, opts: opts)
|
435
445
|
op = OptionPartition.new(opts, OPT_DOCKER[:image][flag], cmd, project: self)
|
446
|
+
exception = @exception
|
447
|
+
banner = true
|
436
448
|
from = :"image:#{flag}"
|
437
449
|
case flag
|
438
450
|
when :list
|
@@ -455,6 +467,10 @@ module Squared
|
|
455
467
|
when :rm
|
456
468
|
if id
|
457
469
|
op << id
|
470
|
+
if option('y')
|
471
|
+
exception = false
|
472
|
+
banner = false
|
473
|
+
end
|
458
474
|
else
|
459
475
|
if op.empty?
|
460
476
|
list_image(flag, docker_output('image ls -a'), from: from) do |val|
|
@@ -476,9 +492,12 @@ module Squared
|
|
476
492
|
img = docker_output 'image', 'tag', id, uri
|
477
493
|
return unless confirm_command(img.to_s, cmd.to_s, target: id, as: registry, title: from)
|
478
494
|
|
479
|
-
|
495
|
+
cmd = img
|
496
|
+
sync = false
|
497
|
+
exception = true
|
498
|
+
banner = false
|
480
499
|
end
|
481
|
-
run(sync: sync, from: from)
|
500
|
+
run(cmd, sync: sync, exception: exception, banner: banner, from: from)
|
482
501
|
end
|
483
502
|
|
484
503
|
def network(flag, opts = [], target: nil)
|
@@ -535,8 +554,12 @@ module Squared
|
|
535
554
|
case flag
|
536
555
|
when :run
|
537
556
|
unless session_arg?('name', target: target)
|
538
|
-
|
539
|
-
|
557
|
+
target << basic_option('name', dnsname("#{name}_%s" % if RUBY_VERSION >= '3.1'
|
558
|
+
require 'random/formatter'
|
559
|
+
Random.new.alphanumeric(6)
|
560
|
+
else
|
561
|
+
(0...6).map { rand(97..122).chr }.join
|
562
|
+
end))
|
540
563
|
end
|
541
564
|
when :exec
|
542
565
|
raise_error('no command args', hint: from) if list.empty?
|
@@ -583,6 +606,8 @@ module Squared
|
|
583
606
|
pwd_set do
|
584
607
|
found = false
|
585
608
|
index = 0
|
609
|
+
all = option('all', prefix: 'docker')
|
610
|
+
y = from == :'image:rm' && option('y', prefix: 'docker')
|
586
611
|
pat = /^(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})(?:[_.,:-]|$)/
|
587
612
|
IO.popen(session_done(cmd << '--format=json')).each do |line|
|
588
613
|
data = JSON.parse(line)
|
@@ -596,41 +621,43 @@ module Squared
|
|
596
621
|
id
|
597
622
|
end)
|
598
623
|
ee = data['Image'] || rt || aa
|
599
|
-
next unless
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
624
|
+
next unless all || ee.match?(pat) || aa.match?(pat)
|
625
|
+
|
626
|
+
unless y
|
627
|
+
bb = index.succ.to_s
|
628
|
+
cc = bb.size + 1
|
629
|
+
a = sub_style(ee, styles: theme[:inline])
|
630
|
+
b = "Execute #{sub_style(flag, styles: theme[:active])} on #{a}#{ee == id ? '' : " (#{id})"}"
|
631
|
+
c, d = no ? ['y/N', 'N'] : ['Y/n', 'Y']
|
632
|
+
e = time_format(time_since(data['CreatedAt']), pass: ['ms'])
|
633
|
+
f = sub_style(ARG[:BORDER][0], styles: theme[:inline])
|
634
|
+
g = ' ' * (cc + 1)
|
635
|
+
h = "#{sub_style(bb.rjust(cc), styles: theme[:current])} #{f} "
|
636
|
+
puts unless index == 0
|
637
|
+
puts "#{h + sub_style(aa, styles: theme[:subject])} (created #{e} ago)"
|
638
|
+
cols = %w[Tag Status Ports]
|
639
|
+
cols << case flag
|
640
|
+
when :connect, :disconnect
|
641
|
+
'Networks'
|
642
|
+
else
|
643
|
+
'Size'
|
644
|
+
end
|
645
|
+
cols.each do |key|
|
646
|
+
next if (key == 'Tag' && !dd) || (key == 'Size' && data[key] == '0B')
|
621
647
|
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
648
|
+
puts "#{g + f} #{key}: #{as_a(data[key]).join(', ')}" unless data[key].to_s.empty?
|
649
|
+
end
|
650
|
+
w = 9 + flag.to_s.size + 4 + ee.size
|
651
|
+
puts g + sub_style(ARG[:BORDER][6] + (ARG[:BORDER][1] * w), styles: theme[:inline])
|
652
|
+
found = true
|
653
|
+
index += 1
|
654
|
+
next unless confirm("#{h + b}? [#{c}] ", d, timeout: 60)
|
629
655
|
|
630
|
-
|
656
|
+
puts if @@print_order == 0
|
657
|
+
end
|
631
658
|
yield id
|
632
659
|
end
|
633
|
-
puts log_message(Logger::INFO, 'none detected', subject: "#{name}:#{from}", hint: hint) unless found
|
660
|
+
puts log_message(Logger::INFO, 'none detected', subject: "#{name}:#{from}", hint: hint) unless found || y
|
634
661
|
end
|
635
662
|
rescue StandardError => e
|
636
663
|
log.error e
|
@@ -658,10 +685,12 @@ module Squared
|
|
658
685
|
|
659
686
|
def choice_command(flag)
|
660
687
|
msg, cmd, index = case flag
|
661
|
-
when :run
|
688
|
+
when :run, :rm
|
662
689
|
['Choose an image', 'images -a', 2]
|
663
690
|
when :exec
|
664
691
|
['Choose a container', 'ps -a', 0]
|
692
|
+
when :bake
|
693
|
+
['Choose a target', 'buildx bake --list=type=targets', 0]
|
665
694
|
else
|
666
695
|
['Choose a network', 'network ls', 0]
|
667
696
|
end
|
@@ -671,16 +700,26 @@ module Squared
|
|
671
700
|
puts log_message(Logger::INFO, 'none found', subject: name, hint: "docker #{cmd}")
|
672
701
|
else
|
673
702
|
puts " # #{header}"
|
703
|
+
multiple = false
|
704
|
+
parse = ->(val) { val.split(/\s+/)[index] }
|
674
705
|
case flag
|
675
706
|
when :run, :exec
|
676
707
|
values = [['Options', flag == :run], ['Arguments', flag == :exec]]
|
677
708
|
cmd = flag.to_s
|
709
|
+
when :rm, :bake
|
710
|
+
values = ['Options']
|
711
|
+
multiple = true
|
712
|
+
cmd = flag == :rm ? 'image rm' : "buildx bake -f #{shell_quote(dockerfile)}"
|
678
713
|
else
|
679
|
-
values = [
|
714
|
+
values = ['Options', ['Container', true]]
|
680
715
|
cmd = "network #{flag}"
|
681
716
|
end
|
682
|
-
out, opts, args = choice_index(msg, lines, values: values)
|
683
|
-
ret = run docker_output(cmd, opts, '--', out.
|
717
|
+
out, opts, args = choice_index(msg, lines, multiple: multiple, values: values)
|
718
|
+
ret = run docker_output(cmd, opts, '--', *(if out.is_a?(Array)
|
719
|
+
out.map! { |val| parse.call(val) }
|
720
|
+
else
|
721
|
+
[parse.call(out)]
|
722
|
+
end), args)
|
684
723
|
print_success if success?(ret && cmd.start_with?('network'))
|
685
724
|
end
|
686
725
|
end
|
@@ -111,21 +111,30 @@ module Squared
|
|
111
111
|
time_format(epoch, clock: clock)
|
112
112
|
end
|
113
113
|
|
114
|
-
def rev_clear(name)
|
114
|
+
def rev_clear(name, sync: true)
|
115
115
|
if Dir.exist?(name) && (proj = find(name))
|
116
116
|
name = proj.name
|
117
117
|
end
|
118
|
-
rev_write if rev_entry(name, 'revision', val: '', create: false)
|
118
|
+
rev_write(sync: sync) if rev_entry(name, 'revision', val: '', create: false)
|
119
119
|
end
|
120
120
|
|
121
|
-
def rev_write(name = nil, data = nil, utc: nil)
|
121
|
+
def rev_write(name = nil, data = nil, sync: true, utc: nil)
|
122
122
|
return unless @revfile
|
123
123
|
|
124
124
|
if name
|
125
125
|
data&.each { |key, val| rev_entry(name, key, val: val) }
|
126
126
|
rev_timeutc(name, utc) if utc
|
127
127
|
end
|
128
|
-
|
128
|
+
sleep 0 while !sync && @revlock
|
129
|
+
begin
|
130
|
+
@revlock = true
|
131
|
+
File.write(@revfile, JSON.pretty_generate(@revdoc))
|
132
|
+
rescue StandardError => e
|
133
|
+
log&.debug e
|
134
|
+
warn log_message(Logger::WARN, e, pass: true) if warning?
|
135
|
+
ensure
|
136
|
+
@revlock = false
|
137
|
+
end
|
129
138
|
end
|
130
139
|
|
131
140
|
def git_clone?(path, name = nil)
|
@@ -279,17 +288,20 @@ module Squared
|
|
279
288
|
namespace(name = ws.task_name('git')) do
|
280
289
|
all = ws.task_join(name, 'all')
|
281
290
|
|
282
|
-
ws.format_desc(all,
|
291
|
+
ws.format_desc(all, 'stash|rebase|autostash?,depend?')
|
283
292
|
task 'all' do |_, args|
|
284
|
-
|
285
|
-
cmd = if
|
286
|
-
[
|
287
|
-
elsif
|
288
|
-
[
|
293
|
+
args = args.to_a
|
294
|
+
cmd = if args.include?('stash')
|
295
|
+
['stash', 'pull']
|
296
|
+
elsif args.include?('rebase')
|
297
|
+
['rebase']
|
298
|
+
elsif args.include?('autostash')
|
299
|
+
['autostash']
|
289
300
|
else
|
290
|
-
[
|
301
|
+
['pull']
|
291
302
|
end
|
292
|
-
cmd
|
303
|
+
cmd.map! { |val| ws.task_sync(val) }
|
304
|
+
cmd << ws.task_sync('depend') if args.include?('depend') && !ws.series.exclude?(:depend, true)
|
293
305
|
cmd << ws.task_sync('build')
|
294
306
|
Common::Utils.task_invoke(*cmd, **ws.invokeargs)
|
295
307
|
end
|
@@ -355,8 +367,13 @@ module Squared
|
|
355
367
|
if flag == :remote
|
356
368
|
format_desc action, flag, 'remote,opts*'
|
357
369
|
task flag, [:remote] do |_, args|
|
358
|
-
remote =
|
359
|
-
|
370
|
+
if (remote = args.remote)
|
371
|
+
args = args.extras
|
372
|
+
else
|
373
|
+
remote = choice_remote
|
374
|
+
args = args.to_a.drop(1)
|
375
|
+
end
|
376
|
+
__send__(action, flag, args, remote: remote)
|
360
377
|
end
|
361
378
|
else
|
362
379
|
format_desc action, flag, 'opts*'
|
@@ -845,12 +862,10 @@ module Squared
|
|
845
862
|
args = args.to_a
|
846
863
|
if args.empty? || args.last == ':'
|
847
864
|
files = []
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
when 'A', 'M'
|
853
|
-
files << $3
|
865
|
+
status_data.each do |line|
|
866
|
+
case (flag == :staged ? line[2] : line[1])
|
867
|
+
when /[AMDRTC]/
|
868
|
+
files << line[0]
|
854
869
|
end
|
855
870
|
end
|
856
871
|
unless files.empty?
|
@@ -867,12 +882,11 @@ module Squared
|
|
867
882
|
end
|
868
883
|
when 'git'
|
869
884
|
before = case flag
|
870
|
-
when :
|
885
|
+
when :mv then 'source+,destination'
|
871
886
|
when :revert then 'commit+' end
|
872
887
|
format_desc(action, flag, 'opts*', before: before, after: case flag
|
873
|
-
when :add
|
874
|
-
|
875
|
-
end)
|
888
|
+
when :add then 'pathspec*|:pattern:*'
|
889
|
+
when :clean, :rm then 'pathspec*' end)
|
876
890
|
task flag do |_, args|
|
877
891
|
git flag, args.to_a
|
878
892
|
end
|
@@ -888,13 +902,13 @@ module Squared
|
|
888
902
|
super
|
889
903
|
end
|
890
904
|
|
891
|
-
def depend(*, **)
|
892
|
-
workspace.rev_clear(name)
|
905
|
+
def depend(*, sync: invoked_sync?('depend'), **)
|
906
|
+
workspace.rev_clear(name, sync: sync)
|
893
907
|
super
|
894
908
|
end
|
895
909
|
|
896
|
-
def clean(*, **)
|
897
|
-
workspace.rev_clear(name)
|
910
|
+
def clean(*, sync: invoked_sync?('clean'), **)
|
911
|
+
workspace.rev_clear(name, sync: sync)
|
898
912
|
super
|
899
913
|
end
|
900
914
|
|
@@ -915,7 +929,7 @@ module Squared
|
|
915
929
|
end
|
916
930
|
end
|
917
931
|
append_pull(opts, OPT_GIT[:pull] + OPT_GIT[:fetch][:pull],
|
918
|
-
no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull], remote: remote, flag: flag)
|
932
|
+
no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull], remote: remote, flag: flag, from: :pull)
|
919
933
|
source(sync: sync, sub: if verbose
|
920
934
|
[
|
921
935
|
{ pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: color(:red), index: 4 },
|
@@ -957,11 +971,9 @@ module Squared
|
|
957
971
|
end
|
958
972
|
|
959
973
|
def fetch(flag = nil, opts = [], sync: invoked_sync?('fetch', flag), remote: nil)
|
960
|
-
|
961
|
-
append_pull(opts, collect_hash(OPT_GIT[:fetch]), no: collect_hash(OPT_GIT[:no][:fetch]),
|
962
|
-
flag: flag)
|
963
|
-
cmd << '--all' if !remote && !session_arg?('multiple') && option('all')
|
964
|
-
cmd << '--verbose' if verbose && !session_arg?('quiet')
|
974
|
+
opts = git_session('fetch', opts: opts).last
|
975
|
+
append_pull(opts, collect_hash(OPT_GIT[:fetch]), no: collect_hash(OPT_GIT[:no][:fetch]),
|
976
|
+
remote: remote, flag: flag, from: :fetch)
|
965
977
|
source(sync: sync, **threadargs)
|
966
978
|
end
|
967
979
|
|
@@ -980,7 +992,7 @@ module Squared
|
|
980
992
|
opts[:origin] = val if (val = option('origin', ignore: false))
|
981
993
|
opts[:branch] = val if (val = option('branch', strict: true))
|
982
994
|
opts[:local] = val != '0' if (val = option('local', strict: true))
|
983
|
-
opts.delete(:'recurse-submodules') || opts.delete(:'no-recurse-submodules') if append_submodules(:clone)
|
995
|
+
opts.delete(:'recurse-submodules') || opts.delete(:'no-recurse-submodules') if append_submodules(from: :clone)
|
984
996
|
append_hash opts
|
985
997
|
cmd << '--quiet' unless verbose
|
986
998
|
append_value(data[0], path, delim: true)
|
@@ -1112,7 +1124,8 @@ module Squared
|
|
1112
1124
|
msg = sub_style('completed', styles: theme[:active])
|
1113
1125
|
puts log_message(Logger::INFO, name, msg, subject: 'revbuild', hint: time_format(epochtime - start))
|
1114
1126
|
end
|
1115
|
-
workspace.rev_write(name, { 'revision' => sha, 'files' => status_digest(*args, **kwargs) },
|
1127
|
+
workspace.rev_write(name, { 'revision' => sha, 'files' => status_digest(*args, **kwargs) },
|
1128
|
+
sync: sync, utc: 'build')
|
1116
1129
|
end
|
1117
1130
|
|
1118
1131
|
def reset(flag, opts = [], refs: nil, ref: nil, mode: nil, commit: nil)
|
@@ -1600,17 +1613,25 @@ module Squared
|
|
1600
1613
|
append_commit(*op.extras)
|
1601
1614
|
end
|
1602
1615
|
when :add, :clean
|
1603
|
-
if flag == :add &&
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1616
|
+
if flag == :add && !op.arg?('pathspec-from-file')
|
1617
|
+
grep, list = op.extras.partition { |val| val.start_with?(':') && val.end_with?(':') }
|
1618
|
+
if list.empty? || !grep.empty?
|
1619
|
+
red = color(:red)
|
1620
|
+
grep.map! { |val| Regexp.new(val[1..-2]) }
|
1621
|
+
files = status_data.map! do |a, b|
|
1622
|
+
next unless grep.empty? || grep.any? { |pat| pat.match?(a) }
|
1623
|
+
|
1624
|
+
"#{sub_style(b, styles: red)} #{a}"
|
1625
|
+
end
|
1626
|
+
.compact
|
1627
|
+
unless files.empty?
|
1628
|
+
files = choice_index('Select files', files, multiple: true, force: true, trim: /^\S+\s/,
|
1629
|
+
accept: 'Add?')
|
1630
|
+
end
|
1631
|
+
op.swap(list + files)
|
1610
1632
|
end
|
1611
|
-
files = choice_index('Select files', files, multiple: true, force: true, trim: /^\S+\s/, accept: 'Add?')
|
1612
1633
|
end
|
1613
|
-
append_pathspec(
|
1634
|
+
append_pathspec(op.extras)
|
1614
1635
|
verbose = flag == :add && !op.arg?('verbose')
|
1615
1636
|
print_success if success?(source) && verbose
|
1616
1637
|
return
|
@@ -1619,7 +1640,7 @@ module Squared
|
|
1619
1640
|
raise_error 'no source/destination' unless refs.size > 1
|
1620
1641
|
op.merge(refs)
|
1621
1642
|
when :rm
|
1622
|
-
append_pathspec(op.extras, expect:
|
1643
|
+
append_pathspec(op.extras, expect: true)
|
1623
1644
|
end
|
1624
1645
|
source(sync: false, stderr: true)
|
1625
1646
|
end
|
@@ -1639,13 +1660,13 @@ module Squared
|
|
1639
1660
|
private
|
1640
1661
|
|
1641
1662
|
def source(cmd = @session, exception: true, io: false, sync: true, stdout: false, stderr: false, banner: true,
|
1642
|
-
multiple: false,
|
1663
|
+
multiple: false, **kwargs)
|
1643
1664
|
cmd = cmd.target if cmd.is_a?(OptionPartition)
|
1644
1665
|
banner = nil if multiple && banner
|
1645
1666
|
if cmd.respond_to?(:done)
|
1646
1667
|
if io && banner == false
|
1647
1668
|
from = nil
|
1648
|
-
elsif !from && (from = cmd.drop(1).find { |val| val.match?(/\A[a-z][a-z\-]
|
1669
|
+
elsif !from && (from = cmd.drop(1).find { |val| val.match?(/\A[a-z]{1,2}[a-z\-]*\z/) })
|
1649
1670
|
from = :"git:#{from}"
|
1650
1671
|
end
|
1651
1672
|
banner &&= cmd.temp { |val| val.start_with?('--work-tree') || val.start_with?('--git-dir') }
|
@@ -1677,7 +1698,7 @@ module Squared
|
|
1677
1698
|
require 'open3'
|
1678
1699
|
if stderr
|
1679
1700
|
Open3.popen3(cmd) do |_, out, err|
|
1680
|
-
n = write_lines(out, banner: banner,
|
1701
|
+
n = write_lines(out, banner: banner, pass: true, **kwargs)
|
1681
1702
|
if n == 0
|
1682
1703
|
n = write_lines(err, banner: banner)
|
1683
1704
|
print_success if success?(n == 0 && !banner.nil?)
|
@@ -1686,7 +1707,7 @@ module Squared
|
|
1686
1707
|
end
|
1687
1708
|
end
|
1688
1709
|
else
|
1689
|
-
Open3.popen2e(cmd) { |_, out| write_lines(out, banner: banner) }
|
1710
|
+
Open3.popen2e(cmd) { |_, out| write_lines(out, banner: banner, **kwargs) }
|
1690
1711
|
end
|
1691
1712
|
end
|
1692
1713
|
rescue StandardError => e
|
@@ -1703,13 +1724,8 @@ module Squared
|
|
1703
1724
|
end
|
1704
1725
|
|
1705
1726
|
def write_lines(data, banner: nil, loglevel: nil, grep: nil, sub: nil, pass: false, first: false)
|
1706
|
-
grep
|
1707
|
-
|
1708
|
-
|
1709
|
-
Regexp.new(val == '*' ? '.+' : val.to_s)
|
1710
|
-
end
|
1711
|
-
grep = nil if grep.empty?
|
1712
|
-
sub = nil if stdin?
|
1727
|
+
grep &&= as_a(grep).yield_self { |a| a.empty? || a.include?('*') ? nil : a.map { |val| Regexp.new(val) } }
|
1728
|
+
sub &&= stdin? ? nil : as_a(sub)
|
1713
1729
|
ret = 0
|
1714
1730
|
out = []
|
1715
1731
|
data.each do |line|
|
@@ -1739,7 +1755,7 @@ module Squared
|
|
1739
1755
|
styles = theme.fetch(:banner, []).reject { |s| s.to_s.end_with?('!') }
|
1740
1756
|
styles << :bold if styles.size <= 1
|
1741
1757
|
puts print_footer("#{size} #{size == 1 ? type.sub(/(?:(?<!l)e)?s\z/, '') : type}",
|
1742
|
-
sub: { pat:
|
1758
|
+
sub: { pat: /^(\d+)(.+)$/, styles: styles })
|
1743
1759
|
else
|
1744
1760
|
puts empty_status("No #{type} were #{action}", 'grep', grep.is_a?(Array) ? case grep.size
|
1745
1761
|
when 0
|
@@ -1786,8 +1802,8 @@ module Squared
|
|
1786
1802
|
glob = kwargs.fetch(:include, [])
|
1787
1803
|
pass = kwargs.fetch(:exclude, [])
|
1788
1804
|
ret = {}
|
1789
|
-
|
1790
|
-
|
1805
|
+
status_data(*args).each do |line|
|
1806
|
+
file = line.first
|
1791
1807
|
next if !glob.empty? && glob.none? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1792
1808
|
next if !pass.empty? && pass.any? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
1793
1809
|
|
@@ -1796,9 +1812,19 @@ module Squared
|
|
1796
1812
|
ret
|
1797
1813
|
end
|
1798
1814
|
|
1799
|
-
def
|
1815
|
+
def status_data(*args)
|
1816
|
+
ret = []
|
1817
|
+
git_spawn('status -z -uall', *args).split("\x0").each do |line|
|
1818
|
+
next unless line =~ /^(.)(.) (.+)$/
|
1819
|
+
|
1820
|
+
ret << [$3, $2, $1]
|
1821
|
+
end
|
1822
|
+
ret
|
1823
|
+
end
|
1824
|
+
|
1825
|
+
def append_pull(opts, list, target: @session, flag: nil, no: nil, remote: nil, from: nil)
|
1800
1826
|
target << '--force' if option('force', target: target)
|
1801
|
-
append_submodules(target: target)
|
1827
|
+
append_submodules(target: target, from: from)
|
1802
1828
|
return if !remote && opts.empty?
|
1803
1829
|
|
1804
1830
|
refspec = []
|
@@ -1823,6 +1849,7 @@ module Squared
|
|
1823
1849
|
op.errors << opt
|
1824
1850
|
end
|
1825
1851
|
end
|
1852
|
+
op << '--verbose' if (flag || from == :fetch) && verbose && !op.arg?('quiet')
|
1826
1853
|
if remote
|
1827
1854
|
op.append(remote, delim: true)
|
1828
1855
|
if (val = option('refspec', target: target, strict: true))
|
@@ -1834,6 +1861,8 @@ module Squared
|
|
1834
1861
|
elsif op.arg?('--multiple')
|
1835
1862
|
op.swap.merge(op.map! { |opt| shell_escape(opt, quote: true) })
|
1836
1863
|
return
|
1864
|
+
elsif option('all')
|
1865
|
+
cmd << '--all'
|
1837
1866
|
end
|
1838
1867
|
op.clear(errors: true, subject: flag.to_s) if flag
|
1839
1868
|
end
|
@@ -1874,7 +1903,7 @@ module Squared
|
|
1874
1903
|
append_first('head', 'tree-ish', 'object', target: target, flag: false, ignore: false)
|
1875
1904
|
end
|
1876
1905
|
|
1877
|
-
def append_submodules(
|
1906
|
+
def append_submodules(target: @session, from: nil)
|
1878
1907
|
return unless (val = option('recurse-submodules', target: target, ignore: false))
|
1879
1908
|
|
1880
1909
|
if from == :clone
|
@@ -1928,7 +1957,7 @@ module Squared
|
|
1928
1957
|
target.include?('--dry-run') || !option('dry-run', target: target).nil?
|
1929
1958
|
end
|
1930
1959
|
|
1931
|
-
def quiet?(target: @session)
|
1960
|
+
def quiet?(*, target: @session, **)
|
1932
1961
|
return false unless target
|
1933
1962
|
|
1934
1963
|
target.include?('--quiet') || (target.include?('-q') && stripext(target.first) == 'git')
|
@@ -191,22 +191,21 @@ module Squared
|
|
191
191
|
end
|
192
192
|
end
|
193
193
|
when 'publish'
|
194
|
-
format_desc(action, flag, 'otp?,dry-run
|
194
|
+
format_desc(action, flag, 'otp?,dry-run?,public|restricted?', before: flag == :tag ? 'tag' : nil)
|
195
195
|
task flag do |_, args|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
196
|
+
args = args.to_a
|
197
|
+
dryrun = true if args.delete('dry-run') || args.delete('true') || args.delete('d')
|
198
|
+
if args.delete('public') || args.delete('p')
|
199
|
+
access = 'public'
|
200
|
+
elsif args.delete('restricted') || args.delete('r')
|
201
|
+
access = 'restricted'
|
201
202
|
end
|
202
|
-
|
203
|
-
|
204
|
-
dryrun = true
|
205
|
-
otp = nil
|
203
|
+
if flag == :latest
|
204
|
+
otp = args.first
|
206
205
|
else
|
207
|
-
|
206
|
+
tag, otp = param_guard(action, flag, args: args)
|
208
207
|
end
|
209
|
-
publish(flag, otp: otp, tag: tag, dryrun: dryrun)
|
208
|
+
publish(flag, otp: otp, tag: tag, dryrun: dryrun, access: access)
|
210
209
|
end
|
211
210
|
end
|
212
211
|
end
|
@@ -217,7 +216,7 @@ module Squared
|
|
217
216
|
end
|
218
217
|
|
219
218
|
def copy(from: 'build', into: 'node_modules', scope: nil, also: nil, create: nil, workspace: false,
|
220
|
-
link: false, force: false, override: false, **kwargs)
|
219
|
+
link: false, force: false, override: false, sync: invoked_sync?('copy'), **kwargs)
|
221
220
|
glob = kwargs[:include]
|
222
221
|
pass = kwargs[:exclude]
|
223
222
|
if @copy && !override
|
@@ -239,7 +238,7 @@ module Squared
|
|
239
238
|
items = []
|
240
239
|
if build? && path != @workspace.home && @workspace.home?
|
241
240
|
items << @workspace.home
|
242
|
-
@workspace.rev_clear(@workspace.find(@workspace.home).name)
|
241
|
+
@workspace.rev_clear(@workspace.find(@workspace.home).name, sync: sync)
|
243
242
|
end
|
244
243
|
items.concat(as_a(also)) if also
|
245
244
|
return if items.empty?
|
@@ -250,13 +249,13 @@ module Squared
|
|
250
249
|
case dir
|
251
250
|
when Pathname
|
252
251
|
dest = dir
|
253
|
-
@workspace.rev_clear(dest)
|
252
|
+
@workspace.rev_clear(dest, sync: sync)
|
254
253
|
when String
|
255
254
|
dest = @workspace.root + dir
|
256
|
-
@workspace.rev_clear(dest)
|
255
|
+
@workspace.rev_clear(dest, sync: sync)
|
257
256
|
when Symbol
|
258
257
|
if (proj = @workspace.find(name: dir))
|
259
|
-
@workspace.rev_clear(proj.name)
|
258
|
+
@workspace.rev_clear(proj.name, sync: sync)
|
260
259
|
dest = proj.path
|
261
260
|
else
|
262
261
|
log.warn message("copy project :#{dir}", hint: 'not found')
|
@@ -274,10 +273,10 @@ module Squared
|
|
274
273
|
glob = dir[:include]
|
275
274
|
pass = dir[:exclude]
|
276
275
|
dest = items.first unless dest && dest != true
|
277
|
-
@workspace.rev_clear(dest) unless dest == true
|
276
|
+
@workspace.rev_clear(dest, sync: sync) unless dest == true
|
278
277
|
when Project::Base
|
279
278
|
dest = dir.path
|
280
|
-
@workspace.rev_clear(dir.name)
|
279
|
+
@workspace.rev_clear(dir.name, sync: sync)
|
281
280
|
else
|
282
281
|
raise_error "copy: given #{dir}"
|
283
282
|
end
|
@@ -329,7 +328,7 @@ module Squared
|
|
329
328
|
if @depend && !flag
|
330
329
|
super
|
331
330
|
elsif outdated?
|
332
|
-
workspace.rev_clear(name)
|
331
|
+
workspace.rev_clear(name, sync: sync)
|
333
332
|
return update if !flag && env('NODE_UPDATE')
|
334
333
|
|
335
334
|
if (yarn = dependtype(:yarn)) > 0
|
@@ -548,7 +547,7 @@ module Squared
|
|
548
547
|
package 'update'
|
549
548
|
end
|
550
549
|
|
551
|
-
def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, dryrun: nil,
|
550
|
+
def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, dryrun: nil, access: nil)
|
552
551
|
if read_packagemanager(:private)
|
553
552
|
if warning?
|
554
553
|
warn log_message(Logger::WARN, 'invalid task "publish"', subject: name, hint: 'private', pass: true)
|
@@ -558,11 +557,10 @@ module Squared
|
|
558
557
|
return unless version
|
559
558
|
|
560
559
|
cmd = session 'npm', 'publish'
|
561
|
-
otp = option('otp') if otp.nil?
|
562
|
-
tag = option('tag') if tag.nil?
|
563
560
|
dryrun = dryrun?('npm') if dryrun.nil?
|
564
|
-
cmd << basic_option('otp', otp) if otp
|
565
|
-
cmd <<
|
561
|
+
cmd << basic_option('otp', otp) if otp ||= option('otp')
|
562
|
+
cmd << basic_option('tag', tag) if tag ||= option('tag')
|
563
|
+
cmd << basic_option('access', access) if access ||= option('access')
|
566
564
|
if verbose
|
567
565
|
if dryrun
|
568
566
|
cmd << '--dry-run'
|
@@ -760,6 +758,10 @@ module Squared
|
|
760
758
|
outdated?
|
761
759
|
end
|
762
760
|
|
761
|
+
def refresh?
|
762
|
+
!Node.prod?
|
763
|
+
end
|
764
|
+
|
763
765
|
def yarn?
|
764
766
|
(@pm[:yarn] ||= if rootpath('yarn.lock', ascend: dependext).exist?
|
765
767
|
if (rc = rootpath('.yarnrc.yml', ascend: dependext)).exist?
|
@@ -184,12 +184,12 @@ module Squared
|
|
184
184
|
task flag, [:strategy] do |_, args|
|
185
185
|
case (strategy = args.strategy)
|
186
186
|
when 'eager', 'only-if-needed'
|
187
|
-
|
187
|
+
args = args.extras
|
188
188
|
else
|
189
|
-
|
189
|
+
args = args.to_a
|
190
190
|
strategy = nil
|
191
191
|
end
|
192
|
-
install(flag,
|
192
|
+
install(flag, args, strategy: strategy)
|
193
193
|
end
|
194
194
|
when :target
|
195
195
|
task flag, [:dir] do |_, args|
|
@@ -229,7 +229,7 @@ module Squared
|
|
229
229
|
super
|
230
230
|
elsif outdated?
|
231
231
|
venv_init
|
232
|
-
workspace.rev_clear(name)
|
232
|
+
workspace.rev_clear(name, sync: sync)
|
233
233
|
if !flag && dependtype == 1
|
234
234
|
cmd = poetry_session 'install', '-n'
|
235
235
|
cmd << '--no-root' if option('no-root')
|
@@ -219,13 +219,20 @@ module Squared
|
|
219
219
|
when :file
|
220
220
|
format_desc action, flag, 'path,opts*,args*'
|
221
221
|
task flag, [:rb] do |_, args|
|
222
|
-
file =
|
223
|
-
|
222
|
+
if (file = args.rb)
|
223
|
+
args = args.to_a.drop(1)
|
224
|
+
else
|
225
|
+
file, opts, extra = choice_index('Select a file', Dir.glob('*.rb', base: path),
|
226
|
+
values: %w[Options Arguments], force: true, series: true)
|
227
|
+
args = OptionPartition.strip(opts)
|
228
|
+
ENV['RUBY_ARGS'] = extra if extra
|
229
|
+
end
|
230
|
+
ruby(flag, args, file: file)
|
224
231
|
end
|
225
232
|
when :script
|
226
|
-
format_desc action, flag, '
|
233
|
+
format_desc action, flag, 'opts*,args*'
|
227
234
|
task flag do |_, args|
|
228
|
-
command = ENV['RUBY_E'] || readline('Enter script', force: true)
|
235
|
+
command = ENV['RUBY_E'] || readline('Enter script', force: true, multiline: ['##', ';'])
|
229
236
|
ruby(flag, args.to_a, command: command)
|
230
237
|
end
|
231
238
|
when :version
|
@@ -246,7 +253,7 @@ module Squared
|
|
246
253
|
if @depend
|
247
254
|
super
|
248
255
|
elsif outdated?
|
249
|
-
workspace.rev_clear(name)
|
256
|
+
workspace.rev_clear(name, sync: sync)
|
250
257
|
cmd = bundle_session 'install'
|
251
258
|
cmd << '--without=development' if prod?
|
252
259
|
if (n = option('jobs')).to_i > 0
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: squared
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- An Pham
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rake
|
@@ -123,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
requirements: []
|
126
|
-
rubygems_version: 3.6.
|
126
|
+
rubygems_version: 3.6.7
|
127
127
|
specification_version: 4
|
128
128
|
summary: Rake task generator for managing multi-language workspaces.
|
129
129
|
test_files: []
|