squared 0.8.6 → 0.9.0.pre2
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 +45 -1
- data/README.md +155 -114
- data/exe/sqd +219 -0
- data/lib/squared/common/base.rb +7 -3
- data/lib/squared/common/format.rb +8 -3
- data/lib/squared/common/prompt.rb +66 -32
- data/lib/squared/common/shell.rb +3 -1
- data/lib/squared/common/system.rb +2 -9
- data/lib/squared/config.rb +3 -3
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +24 -13
- data/lib/squared/workspace/project/base.rb +105 -46
- data/lib/squared/workspace/project/docker.rb +93 -44
- data/lib/squared/workspace/project/git.rb +60 -86
- data/lib/squared/workspace/project/node.rb +86 -66
- data/lib/squared/workspace/project/python.rb +62 -23
- data/lib/squared/workspace/project/ruby.rb +52 -37
- data/lib/squared/workspace/project/support/class.rb +1 -1
- data/lib/squared/workspace/project/support/optionpartition.rb +15 -14
- data/lib/squared/workspace/repo.rb +5 -5
- data/lib/squared/workspace/series.rb +4 -2
- data/squared.gemspec +7 -5
- metadata +20 -4
|
@@ -102,7 +102,7 @@ module Squared
|
|
|
102
102
|
|
|
103
103
|
@@tasks = {}
|
|
104
104
|
@@graph = { _: [] }
|
|
105
|
-
@@asdf = Pathname.new(ENV['ASDF_DIR'] || "#{Dir.home}/.asdf").
|
|
105
|
+
@@asdf = Pathname.new(ENV['ASDF_DIR'] || "#{Dir.home}/.asdf").then do |path|
|
|
106
106
|
version = if path.join('asdf.sh').exist?
|
|
107
107
|
15
|
|
108
108
|
elsif ENV['ASDF_DATA_DIR'] && (path = Pathname.new(ENV['ASDF_DATA_DIR'])).exist?
|
|
@@ -640,7 +640,7 @@ module Squared
|
|
|
640
640
|
end
|
|
641
641
|
env('GRAPH', suffix: 'PASS') { |val| pass.concat(split_escape(val)) }
|
|
642
642
|
start, neg = start.partition { |name| !name.start_with?('-') }
|
|
643
|
-
data = graph_collect(self, start, pass: neg.map { |name| name[1
|
|
643
|
+
data = graph_collect(self, start, pass: neg.map { |name| name[1..] })
|
|
644
644
|
unless out
|
|
645
645
|
data[name] << self
|
|
646
646
|
on :first, :graph
|
|
@@ -700,7 +700,7 @@ module Squared
|
|
|
700
700
|
headers = headers.is_a?(Hash) ? headers.merge(data) : data
|
|
701
701
|
end
|
|
702
702
|
if file
|
|
703
|
-
ext ||= File.extname(file)[1
|
|
703
|
+
ext ||= File.extname(file)[1..]
|
|
704
704
|
else
|
|
705
705
|
require 'open-uri'
|
|
706
706
|
data = nil
|
|
@@ -876,7 +876,7 @@ module Squared
|
|
|
876
876
|
return
|
|
877
877
|
end
|
|
878
878
|
cmd = cmd.target if cmd.is_a?(OptionPartition)
|
|
879
|
-
if interactive && sync && (
|
|
879
|
+
if interactive && sync && !(@session && option('y'))
|
|
880
880
|
print_item(series: true)
|
|
881
881
|
msg, y, h = case interactive
|
|
882
882
|
when Array
|
|
@@ -924,9 +924,9 @@ module Squared
|
|
|
924
924
|
end
|
|
925
925
|
end
|
|
926
926
|
|
|
927
|
-
def scope(
|
|
927
|
+
def scope(...)
|
|
928
928
|
namespace name do
|
|
929
|
-
task(
|
|
929
|
+
task(...)
|
|
930
930
|
end
|
|
931
931
|
end
|
|
932
932
|
|
|
@@ -1298,26 +1298,25 @@ module Squared
|
|
|
1298
1298
|
file = if (val = env('LOG_FILE'))
|
|
1299
1299
|
Time.now.strftime(val)
|
|
1300
1300
|
elsif (val = env('LOG_AUTO'))
|
|
1301
|
-
|
|
1301
|
+
d = Time.now
|
|
1302
1302
|
"#{@name}-%s.log" % [case val
|
|
1303
1303
|
when 'y', 'year'
|
|
1304
|
-
|
|
1304
|
+
d.year
|
|
1305
1305
|
when 'm', 'month'
|
|
1306
|
-
|
|
1306
|
+
d.strftime('%Y-%m')
|
|
1307
1307
|
when 'd', 'day', '1'
|
|
1308
|
-
|
|
1308
|
+
d.strftime('%Y-%m-%d')
|
|
1309
1309
|
else
|
|
1310
|
-
val.include?('%') ?
|
|
1310
|
+
val.include?('%') ? d.strftime(val) : d.strftime('%FT%T%:z')
|
|
1311
1311
|
end]
|
|
1312
1312
|
elsif (val = log[:file])
|
|
1313
1313
|
if val.is_a?(String)
|
|
1314
1314
|
Time.now.strftime(val)
|
|
1315
1315
|
else
|
|
1316
|
-
|
|
1317
|
-
"#{@name}-#{Date.today}.log"
|
|
1316
|
+
"#{@name}-#{Time.now.strftime('%Y-%m-%d')}.log"
|
|
1318
1317
|
end
|
|
1319
1318
|
end
|
|
1320
|
-
.
|
|
1319
|
+
.then do |path|
|
|
1321
1320
|
next unless path
|
|
1322
1321
|
|
|
1323
1322
|
@workspace.home.join(env('LOG_DIR', ''), path).realdirpath
|
|
@@ -1476,7 +1475,7 @@ module Squared
|
|
|
1476
1475
|
|
|
1477
1476
|
t = uniq.call(name = proj.name)
|
|
1478
1477
|
j = if out
|
|
1479
|
-
if i == items.size.pred || (post = items[i.succ
|
|
1478
|
+
if i == items.size.pred || (post = items[i.succ..] - done).empty?
|
|
1480
1479
|
true
|
|
1481
1480
|
elsif !t.empty? && depth > 0
|
|
1482
1481
|
(post - t).empty?
|
|
@@ -1582,14 +1581,18 @@ module Squared
|
|
|
1582
1581
|
end
|
|
1583
1582
|
|
|
1584
1583
|
def env(key, default = nil, suffix: nil, strict: false, ignore: nil, **kwargs, &blk)
|
|
1585
|
-
name = "#{key}_#{envname_get}"
|
|
1584
|
+
name = suffix == false ? key : "#{key}_#{envname_get}"
|
|
1586
1585
|
ret = if suffix
|
|
1587
1586
|
ENV["#{name}_#{suffix}"] || (ignore == false && ENV["#{key}_#{suffix}"]) || ''
|
|
1588
1587
|
elsif strict
|
|
1589
1588
|
ENV[name].to_s
|
|
1590
1589
|
else
|
|
1591
1590
|
ignore = ['0'].freeze if ignore.nil?
|
|
1592
|
-
|
|
1591
|
+
if key =~ /^(.+)_(FORCE|YES|Y)$/ && !(ret = __arg__($2 == 'Y' ? 'YES' : $2, $1)).nil?
|
|
1592
|
+
ret
|
|
1593
|
+
else
|
|
1594
|
+
ENV[name] || ENV.fetch(key, '')
|
|
1595
|
+
end
|
|
1593
1596
|
end
|
|
1594
1597
|
env_yield(ret, default, ignore: ignore, **kwargs, &blk)
|
|
1595
1598
|
end
|
|
@@ -1693,19 +1696,38 @@ module Squared
|
|
|
1693
1696
|
**kwargs)
|
|
1694
1697
|
return unless prefix
|
|
1695
1698
|
|
|
1699
|
+
getarg = ->(key) { ARG[key][s = prefix.downcase] || ARG[key][s.to_sym] }
|
|
1696
1700
|
args.each do |key|
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1701
|
+
ret = case key.downcase
|
|
1702
|
+
when 'force'
|
|
1703
|
+
getarg.call(:FORCE)
|
|
1704
|
+
when 'y'
|
|
1705
|
+
getarg.call(:YES)
|
|
1706
|
+
end
|
|
1707
|
+
return yield(ret) if !ret.nil? && block_given?
|
|
1708
|
+
|
|
1709
|
+
case ret.to_s
|
|
1710
|
+
when '0'
|
|
1711
|
+
next
|
|
1712
|
+
when 'true'
|
|
1713
|
+
return true
|
|
1714
|
+
when 'false'
|
|
1715
|
+
return false
|
|
1716
|
+
else
|
|
1717
|
+
ret ||= env(env_key(prefix.to_s.stripext, key), **kwargs)
|
|
1718
|
+
next unless ret && (!pat || ret.match?(pat))
|
|
1719
|
+
|
|
1720
|
+
if target
|
|
1721
|
+
if path
|
|
1722
|
+
target << quote_option(key, basepath(ret))
|
|
1723
|
+
elsif quote
|
|
1724
|
+
target << quote_option(key, ret)
|
|
1725
|
+
elsif escape
|
|
1726
|
+
target << shell_option(key, ret)
|
|
1727
|
+
end
|
|
1706
1728
|
end
|
|
1729
|
+
return block_given? ? yield(ret) : ret
|
|
1707
1730
|
end
|
|
1708
|
-
return block_given? ? yield(ret) : ret
|
|
1709
1731
|
end
|
|
1710
1732
|
nil
|
|
1711
1733
|
end
|
|
@@ -1818,6 +1840,8 @@ module Squared
|
|
|
1818
1840
|
|
|
1819
1841
|
case from
|
|
1820
1842
|
when :outdated
|
|
1843
|
+
return if ENV['BANNER'] == 'false'
|
|
1844
|
+
|
|
1821
1845
|
out = print_footer("major #{args[0]} / minor #{args[1]} / patch #{args[2]}", right: true).split("\n")
|
|
1822
1846
|
sub_style!(out[1], **opt_style(theme[:major], /^( +major )(\d+)(.+)$/, 2))
|
|
1823
1847
|
sub_style!(out[1], **opt_style(theme[:active], /^(.+)(minor )(\d+)(.+)$/, 3))
|
|
@@ -2040,27 +2064,27 @@ module Squared
|
|
|
2040
2064
|
val
|
|
2041
2065
|
end
|
|
2042
2066
|
end
|
|
2043
|
-
base.update(data)
|
|
2044
|
-
.update(ret)
|
|
2067
|
+
base.update(data, ret)
|
|
2045
2068
|
end
|
|
2046
2069
|
|
|
2047
2070
|
def merge_opts(base, data)
|
|
2071
|
+
s = '%s %s'
|
|
2048
2072
|
case data
|
|
2049
2073
|
when String
|
|
2050
2074
|
case base
|
|
2051
2075
|
when String
|
|
2052
|
-
|
|
2076
|
+
s % [base, data]
|
|
2053
2077
|
when Hash
|
|
2054
|
-
|
|
2078
|
+
s % [append_hash(base, target: []).join(' '), data]
|
|
2055
2079
|
when Enumerable
|
|
2056
|
-
|
|
2080
|
+
s % [base.to_a.join(' '), data]
|
|
2057
2081
|
else
|
|
2058
2082
|
data
|
|
2059
2083
|
end
|
|
2060
2084
|
when Hash
|
|
2061
2085
|
case base
|
|
2062
2086
|
when String
|
|
2063
|
-
|
|
2087
|
+
s % [base, append_hash(data, target: []).join(' ')]
|
|
2064
2088
|
when Hash
|
|
2065
2089
|
base.merge(data)
|
|
2066
2090
|
when Enumerable
|
|
@@ -2071,9 +2095,9 @@ module Squared
|
|
|
2071
2095
|
when Enumerable
|
|
2072
2096
|
case base
|
|
2073
2097
|
when String
|
|
2074
|
-
|
|
2098
|
+
s % [base, data.to_a.join(' ')]
|
|
2075
2099
|
when Hash
|
|
2076
|
-
|
|
2100
|
+
s % [append_hash(base, target: []).join(' '), data.to_a.join(' ')]
|
|
2077
2101
|
when Enumerable
|
|
2078
2102
|
Set.new(base.to_a + data.to_a).to_a
|
|
2079
2103
|
else
|
|
@@ -2107,8 +2131,23 @@ module Squared
|
|
|
2107
2131
|
end || []
|
|
2108
2132
|
end
|
|
2109
2133
|
|
|
2134
|
+
def parse_select(kwargs = {})
|
|
2135
|
+
pa, ch = ENV.fetch('SELECT', '0:0').split(':').map(&:to_i)
|
|
2136
|
+
if pa > 0
|
|
2137
|
+
kwargs[:page] = pa
|
|
2138
|
+
elsif !kwargs.key?(:page)
|
|
2139
|
+
kwargs[:page] = ARG[:PAGE]
|
|
2140
|
+
end
|
|
2141
|
+
kwargs[:max] = ch if ch > 0
|
|
2142
|
+
kwargs
|
|
2143
|
+
end
|
|
2144
|
+
|
|
2110
2145
|
def param_guard(action, flag, args:, key: nil, pat: nil, values: nil)
|
|
2111
2146
|
if args && key
|
|
2147
|
+
if key.is_a?(Array)
|
|
2148
|
+
return key.map { |val| param_guard(action, flag, args: args, key: val, pat: pat, values: values) }
|
|
2149
|
+
end
|
|
2150
|
+
|
|
2112
2151
|
val = args.fetch(key, nil)
|
|
2113
2152
|
return val unless val.nil? || (pat && !val.match?(pat)) || (values && !values.include?(val))
|
|
2114
2153
|
|
|
@@ -2140,9 +2179,9 @@ module Squared
|
|
|
2140
2179
|
end
|
|
2141
2180
|
|
|
2142
2181
|
def choice_index(msg, list, values: nil, accept: nil, series: false, trim: nil, column: nil, multiple: false,
|
|
2143
|
-
force: true, **kwargs)
|
|
2182
|
+
force: true, pipe: self.pipe, **kwargs)
|
|
2144
2183
|
puts unless series || printfirst?
|
|
2145
|
-
ret = choice(msg, list, multiple: multiple, force: force, **kwargs)
|
|
2184
|
+
ret = choice(msg, list, multiple: multiple, force: force, pipe: pipe, **parse_select(kwargs))
|
|
2146
2185
|
unless ret && !ret.empty?
|
|
2147
2186
|
exit 1 if force
|
|
2148
2187
|
return
|
|
@@ -2226,12 +2265,12 @@ module Squared
|
|
|
2226
2265
|
end
|
|
2227
2266
|
|
|
2228
2267
|
def relativepath(*list, all: false)
|
|
2229
|
-
list.
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2268
|
+
list.filter_map do |val|
|
|
2269
|
+
next unless projectpath?(file = Pathname.new(val))
|
|
2270
|
+
|
|
2271
|
+
out = (file.absolute? ? file.relative_path_from(path) : file.cleanpath).to_s
|
|
2272
|
+
all && file.to_s.end_with?('/') ? "#{out}/*" : out
|
|
2273
|
+
end
|
|
2235
2274
|
end
|
|
2236
2275
|
|
|
2237
2276
|
def projectmap(files, resolve: true, parent: false, pass: true)
|
|
@@ -2334,6 +2373,19 @@ module Squared
|
|
|
2334
2373
|
cur[2] == lat[2] ? 3 : 2
|
|
2335
2374
|
end
|
|
2336
2375
|
|
|
2376
|
+
def semapp(name, *args, minor: true, patch: true, pre: false, env: false)
|
|
2377
|
+
if args.empty?
|
|
2378
|
+
args << '--version'
|
|
2379
|
+
else
|
|
2380
|
+
args.map! { |s| shell_quote(s, force: false) }
|
|
2381
|
+
end
|
|
2382
|
+
n = minor ? patch ? pre ? -1 : 4 : 2 : 0
|
|
2383
|
+
IO.popen([shell_bin(name, env: env), *args], chdir: path, &:read).scan(SEM_VER).first
|
|
2384
|
+
&.slice(0..n)&.join or raise
|
|
2385
|
+
rescue
|
|
2386
|
+
'0.0.0'
|
|
2387
|
+
end
|
|
2388
|
+
|
|
2337
2389
|
def semmajor?(cur, want)
|
|
2338
2390
|
(cur[0] == '0' && want[0] == '0' ? cur[2] != want[2] : cur[0] != want[0]) && !want[6]
|
|
2339
2391
|
end
|
|
@@ -2347,7 +2399,7 @@ module Squared
|
|
|
2347
2399
|
end
|
|
2348
2400
|
|
|
2349
2401
|
def indexitem(val)
|
|
2350
|
-
[$1.to_i, $2 && $2[1
|
|
2402
|
+
[$1.to_i, $2 && $2[1..]] if val =~ /\A[=^#{indexchar}](\d+)(:.+)?\z/
|
|
2351
2403
|
end
|
|
2352
2404
|
|
|
2353
2405
|
def indexerror(val, list = nil)
|
|
@@ -2451,7 +2503,6 @@ module Squared
|
|
|
2451
2503
|
def pwd_set(cmd = nil, pass: false, timeout: nil, from: @on[:from].last, **kwargs, &blk)
|
|
2452
2504
|
return if from == false
|
|
2453
2505
|
|
|
2454
|
-
require 'timeout'
|
|
2455
2506
|
unless (path.to_s == Dir.pwd || pass) && (mri? || !windows?)
|
|
2456
2507
|
pwd = Dir.pwd
|
|
2457
2508
|
Dir.chdir(path)
|
|
@@ -2748,7 +2799,15 @@ module Squared
|
|
|
2748
2799
|
end
|
|
2749
2800
|
|
|
2750
2801
|
def dryrun?(target: @session, prefix: target&.first, **)
|
|
2751
|
-
|
|
2802
|
+
val = ENV['DRY_RUN'] if (val = option('dry-run', target: target, prefix: prefix)).nil?
|
|
2803
|
+
case val.to_s
|
|
2804
|
+
when '0' then nil
|
|
2805
|
+
when 'false'
|
|
2806
|
+
return false
|
|
2807
|
+
else
|
|
2808
|
+
return true if val
|
|
2809
|
+
end
|
|
2810
|
+
Array(target).include?('--dry-run')
|
|
2752
2811
|
end
|
|
2753
2812
|
|
|
2754
2813
|
def pwd?
|
|
@@ -128,6 +128,7 @@ module Squared
|
|
|
128
128
|
'image' => %i[ls rm pull push tag save inspect history].freeze,
|
|
129
129
|
'container' => %i[attach commit create diff exec inspect kill logs pause restart rm run start stats stop top
|
|
130
130
|
unpause update].freeze,
|
|
131
|
+
'run' => %i[rmi rmd mount volume entrypoint].freeze,
|
|
131
132
|
'network' => %i[connect disconnect create rm].freeze,
|
|
132
133
|
'ls' => nil
|
|
133
134
|
})
|
|
@@ -303,13 +304,22 @@ module Squared
|
|
|
303
304
|
end
|
|
304
305
|
end
|
|
305
306
|
else
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
307
|
+
single = %i[logs diff attach top].freeze
|
|
308
|
+
format_desc action, flag, "opts*,id/name#{if flag == :stats
|
|
309
|
+
'*'
|
|
310
|
+
elsif !single.include?(flag)
|
|
311
|
+
'+'
|
|
312
|
+
end}|:"
|
|
311
313
|
task flag do |_, args|
|
|
312
|
-
|
|
314
|
+
args = args.to_a
|
|
315
|
+
if choice!(args, first: false)
|
|
316
|
+
args.concat(Array(choice_command(:container, multiple: !single.include?(flag))))
|
|
317
|
+
if flag == :rm
|
|
318
|
+
stop = filter_ps(:stop, column: 'ID').select { |id| args.include?(id) }
|
|
319
|
+
container :stop, stop if !stop.empty? && confirm_basic('Stop?', stop.join(', '))
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
container flag, args
|
|
313
323
|
end
|
|
314
324
|
end
|
|
315
325
|
when 'image'
|
|
@@ -358,18 +368,47 @@ module Squared
|
|
|
358
368
|
end
|
|
359
369
|
end
|
|
360
370
|
end
|
|
371
|
+
when 'run'
|
|
372
|
+
format_desc action, flag, 'id|:,opts*'
|
|
373
|
+
task flag, [:id] do |_, args|
|
|
374
|
+
id = if args.id == ':'
|
|
375
|
+
choice_command(:image, multiple: false)
|
|
376
|
+
else
|
|
377
|
+
param_guard(action, flag, args: args, key: :id)
|
|
378
|
+
end
|
|
379
|
+
args = case flag
|
|
380
|
+
when :mount
|
|
381
|
+
mount = []
|
|
382
|
+
loop do
|
|
383
|
+
s = readline("Enter mount ##{mount.size.succ}", force: false)
|
|
384
|
+
break if s.empty?
|
|
385
|
+
|
|
386
|
+
mount << (s.include?('type=') ? s : "type=bind,#{s}")
|
|
387
|
+
end
|
|
388
|
+
mount.map { |val| quote_option('mount', val, double: true) }
|
|
389
|
+
when :volume
|
|
390
|
+
choice_command(:volume, multiple: true, series: true).map do |val|
|
|
391
|
+
basic_option 'volume', val
|
|
392
|
+
end
|
|
393
|
+
when :entrypoint
|
|
394
|
+
["entrypoint=#{shell_quote(readline('Entrypoint', force: true), double: true)}"]
|
|
395
|
+
when :rmi
|
|
396
|
+
%w[rm i t]
|
|
397
|
+
when :rmd
|
|
398
|
+
%w[rm d]
|
|
399
|
+
end + args.extras
|
|
400
|
+
container(:run, args.uniq, id: id)
|
|
401
|
+
end
|
|
361
402
|
when 'network'
|
|
362
403
|
format_desc action, flag, 'name,opts*'
|
|
363
404
|
task flag, [:name] do |_, args|
|
|
364
|
-
name =
|
|
365
|
-
param_guard(action, flag, args: args, key: :name)
|
|
366
|
-
else
|
|
367
|
-
args.name
|
|
368
|
-
end
|
|
405
|
+
name = flag == :create ? param_guard(action, flag, args: args, key: :name) : args.name
|
|
369
406
|
if name
|
|
370
407
|
network(flag, args.extras, name: name)
|
|
408
|
+
elsif flag == :rm
|
|
409
|
+
choice_command :'network:rm'
|
|
371
410
|
else
|
|
372
|
-
choice_command
|
|
411
|
+
choice_command(flag, id: choice_command(:container, force: false), series: true)
|
|
373
412
|
end
|
|
374
413
|
end
|
|
375
414
|
end
|
|
@@ -501,7 +540,7 @@ module Squared
|
|
|
501
540
|
if flag == :publish
|
|
502
541
|
id ||= option('tag', ignore: false) || op.shift || tagmain
|
|
503
542
|
registry ||= option('registry') || op.shift || @oci
|
|
504
|
-
|
|
543
|
+
op.clear(strict: true)
|
|
505
544
|
op << shell_quote(tagjoin(registry, id))
|
|
506
545
|
return unless confirm_command(op.to_s, title: from, target: id)
|
|
507
546
|
else
|
|
@@ -516,10 +555,10 @@ module Squared
|
|
|
516
555
|
if multiple
|
|
517
556
|
op.concat(service) if service
|
|
518
557
|
op.append(delim: true, escape: true, strip: ':')
|
|
519
|
-
|
|
520
|
-
raise ArgumentError, message('no service was selected', hint: flag) unless service
|
|
521
|
-
|
|
558
|
+
elsif service
|
|
522
559
|
append_command(flag, service, op.extras, prompt: '::')
|
|
560
|
+
else
|
|
561
|
+
raise ArgumentError, message('no service was selected', hint: flag)
|
|
523
562
|
end
|
|
524
563
|
end
|
|
525
564
|
end
|
|
@@ -668,7 +707,7 @@ module Squared
|
|
|
668
707
|
args = if name
|
|
669
708
|
index += 1
|
|
670
709
|
opts.dup << "name=#{index == 0 ? name : "#{name}-#{index}"}"
|
|
671
|
-
elsif choice!(opts, only: true)
|
|
710
|
+
elsif choice!(opts, empty: true, only: true)
|
|
672
711
|
OptionPartition.strip(readline('Enter arguments', force: false))
|
|
673
712
|
else
|
|
674
713
|
opts
|
|
@@ -720,9 +759,9 @@ module Squared
|
|
|
720
759
|
when :push
|
|
721
760
|
id ||= option('tag', ignore: false) || op.shift || tagmain
|
|
722
761
|
registry ||= option('registry') || op.shift || self.registry
|
|
723
|
-
emptyargs op, flag
|
|
724
762
|
raise ArgumentError, message('username/registry not specified', hint: flag) unless registry
|
|
725
763
|
|
|
764
|
+
op.clear(strict: true)
|
|
726
765
|
uri = shell_quote tagjoin(registry, id)
|
|
727
766
|
op << uri
|
|
728
767
|
img = docker_output 'image tag', id, uri
|
|
@@ -745,7 +784,7 @@ module Squared
|
|
|
745
784
|
success?(run(sync: sync, exception: exception, banner: banner, from: from), status)
|
|
746
785
|
end
|
|
747
786
|
|
|
748
|
-
def network(flag, opts = [],
|
|
787
|
+
def network(flag, opts = [], name: nil)
|
|
749
788
|
cmd, opts = docker_session('network', flag, opts: opts)
|
|
750
789
|
op = OptionPartition.new(opts, OPT_DOCKER[:network].fetch(flag, []), cmd, **dockerinit)
|
|
751
790
|
.clear
|
|
@@ -891,7 +930,7 @@ module Squared
|
|
|
891
930
|
target
|
|
892
931
|
end
|
|
893
932
|
|
|
894
|
-
def filter_ps(flag,
|
|
933
|
+
def filter_ps(flag, column: nil, from: :'container:ps')
|
|
895
934
|
no = false
|
|
896
935
|
status = case flag.to_sym
|
|
897
936
|
when :start
|
|
@@ -927,7 +966,7 @@ module Squared
|
|
|
927
966
|
pwd_set(from: from) do
|
|
928
967
|
index = 1
|
|
929
968
|
all = option('all', prefix: 'docker')
|
|
930
|
-
y = from
|
|
969
|
+
y = from == :'image:rm' && option('y', prefix: 'docker')
|
|
931
970
|
filter = env('DOCKER_FILTER', filter).to_s
|
|
932
971
|
pat = if OptionPartition.pattern?(filter)
|
|
933
972
|
Regexp.new(filter)
|
|
@@ -1009,18 +1048,22 @@ module Squared
|
|
|
1009
1048
|
confirm "#{s} #{sub_style(target, theme[:subject])}#{" as #{sub_style(as, theme[:inline])}" if as}?", 'N'
|
|
1010
1049
|
end
|
|
1011
1050
|
|
|
1012
|
-
def choice_command(flag, *action)
|
|
1051
|
+
def choice_command(flag, *action, id: nil, multiple: nil, series: false, force: true)
|
|
1013
1052
|
msg, cmd = case flag
|
|
1014
|
-
when :exec
|
|
1053
|
+
when :exec, :container
|
|
1015
1054
|
['Choose a container', 'ps -a']
|
|
1016
1055
|
when :bake
|
|
1017
1056
|
['Choose a target', 'buildx bake --list=type=targets']
|
|
1018
|
-
when :connect, :disconnect
|
|
1057
|
+
when :connect, :disconnect, :'network:rm'
|
|
1019
1058
|
['Choose a network', 'network ls']
|
|
1020
1059
|
when :service
|
|
1021
1060
|
['Choose a service',
|
|
1022
1061
|
'compose ps -a ' \
|
|
1023
1062
|
'--format="table {{.Service}}\t{{.Name}}\t{{.Image}}\t{{.Command}}\t{{.Status}}\t{{.Ports}}"']
|
|
1063
|
+
when :volume
|
|
1064
|
+
['Choose a volume',
|
|
1065
|
+
'volume ls ' \
|
|
1066
|
+
'--format="table {{.Name}}\t{{.Driver}}\t{{.Mountpoint}}"']
|
|
1024
1067
|
else
|
|
1025
1068
|
['Choose an image',
|
|
1026
1069
|
'images -a ' \
|
|
@@ -1031,28 +1074,40 @@ module Squared
|
|
|
1031
1074
|
puts log_message('none found', subject: name, hint: "docker #{cmd.split(' ', 3)[0, 2].join(' ')}")
|
|
1032
1075
|
return
|
|
1033
1076
|
end
|
|
1034
|
-
|
|
1035
|
-
|
|
1077
|
+
parse = lambda do |list|
|
|
1078
|
+
ret = Array(list).map { |val| val.split(/\s+/, 2).first }.reject(&:empty?)
|
|
1079
|
+
return ret.first if multiple == false
|
|
1080
|
+
|
|
1081
|
+
ret unless ret.empty?
|
|
1082
|
+
end
|
|
1083
|
+
puts "#{"\n" if id && !printfirst?} # #{lines.shift}"
|
|
1036
1084
|
ctx = flag.to_s
|
|
1037
1085
|
case flag
|
|
1038
1086
|
when :run, :exec
|
|
1039
1087
|
values = [['Options', flag == :run], ['Arguments', flag == :exec]]
|
|
1040
1088
|
when :rm, :bake
|
|
1041
1089
|
values = ['Options']
|
|
1042
|
-
multiple = true
|
|
1090
|
+
multiple = true if multiple.nil?
|
|
1043
1091
|
ctx = flag == :rm ? 'image rm' : "buildx bake -f #{shell_quote(dockerfile)}"
|
|
1044
1092
|
when :save
|
|
1045
1093
|
values = [['Output', true], 'Platform']
|
|
1046
|
-
multiple = true
|
|
1094
|
+
multiple = true if multiple.nil?
|
|
1047
1095
|
when :service
|
|
1048
|
-
values = []
|
|
1049
|
-
multiple = true
|
|
1096
|
+
values = ['Options']
|
|
1097
|
+
multiple = true if multiple.nil?
|
|
1050
1098
|
ctx = 'compose'
|
|
1051
1099
|
when :connect, :disconnect
|
|
1052
|
-
values = ['Options', ['Container', true]]
|
|
1100
|
+
values = id ? ['Options'] : ['Options', ['Container', true]]
|
|
1053
1101
|
ctx = "network #{flag}"
|
|
1102
|
+
when :'network:rm'
|
|
1103
|
+
values = ['Options']
|
|
1104
|
+
multiple = true if multiple.nil?
|
|
1105
|
+
ctx = 'network rm'
|
|
1106
|
+
when :container, :image, :volume
|
|
1107
|
+
return parse.call(choice_index(msg, lines, multiple: multiple, series: series, force: force,
|
|
1108
|
+
attempts: force ? 3 : 1))
|
|
1054
1109
|
end
|
|
1055
|
-
out, opts, args = choice_index(msg, lines, multiple: multiple,
|
|
1110
|
+
out, opts, args = choice_index(msg, lines, values: values, multiple: multiple, series: series)
|
|
1056
1111
|
cmd = docker_output(ctx, *action)
|
|
1057
1112
|
case flag
|
|
1058
1113
|
when :tag
|
|
@@ -1067,8 +1122,10 @@ module Squared
|
|
|
1067
1122
|
else
|
|
1068
1123
|
cmd << opts << '--'
|
|
1069
1124
|
end
|
|
1070
|
-
cmd.merge(
|
|
1071
|
-
|
|
1125
|
+
cmd.merge(parse.call(out))
|
|
1126
|
+
cmd << args
|
|
1127
|
+
cmd.merge(Array(id)) if id
|
|
1128
|
+
success?(run(cmd, { 'NO_COLOR' => 'true' }), ctx.start_with?('network', 'tag', 'save'))
|
|
1072
1129
|
end
|
|
1073
1130
|
|
|
1074
1131
|
def filetype(val = dockerfile)
|
|
@@ -1108,14 +1165,14 @@ module Squared
|
|
|
1108
1165
|
s = val.join(':')
|
|
1109
1166
|
return s unless s.size > max
|
|
1110
1167
|
end
|
|
1111
|
-
ret[
|
|
1168
|
+
ret[...max]
|
|
1112
1169
|
end
|
|
1113
1170
|
|
|
1114
1171
|
def dnsname(val, max: 63, char: nil)
|
|
1115
1172
|
ret = val.sub(/^[^a-z]+/i, '')
|
|
1116
1173
|
.sub(/[^a-z\d]+$/i, '')
|
|
1117
1174
|
.gsub(/[^a-z\d#{char}]+/i, '-')
|
|
1118
|
-
.gsub(/-{2,}/, '-')[
|
|
1175
|
+
.gsub(/-{2,}/, '-')[...max]
|
|
1119
1176
|
char ? ret : ret.downcase
|
|
1120
1177
|
end
|
|
1121
1178
|
|
|
@@ -1123,10 +1180,6 @@ module Squared
|
|
|
1123
1180
|
dnsname(val, max: 128, char: '.').gsub(/\.{2,}/, '.')
|
|
1124
1181
|
end
|
|
1125
1182
|
|
|
1126
|
-
def charname(val)
|
|
1127
|
-
val.gsub(/[^\w.-]+/, '_')
|
|
1128
|
-
end
|
|
1129
|
-
|
|
1130
1183
|
def tagmain
|
|
1131
1184
|
tag.is_a?(Array) ? tag.first : tag
|
|
1132
1185
|
end
|
|
@@ -1135,10 +1188,6 @@ module Squared
|
|
|
1135
1188
|
{ project: self, strict: strict?, explicit: '=', bool: %w[1 0 true false] }
|
|
1136
1189
|
end
|
|
1137
1190
|
|
|
1138
|
-
def emptyargs(list, hint = nil)
|
|
1139
|
-
raise ArgumentError, message('unrecognized args', list.join(', '), hint: hint) unless list.empty?
|
|
1140
|
-
end
|
|
1141
|
-
|
|
1142
1191
|
def anypath?(*args)
|
|
1143
1192
|
args.any? { |val| basepath!(val) }
|
|
1144
1193
|
end
|