squared 0.8.5 → 0.9.0.pre1
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 +43 -1
- data/README.md +157 -116
- data/exe/sqd +224 -0
- data/lib/squared/common/base.rb +7 -3
- data/lib/squared/common/format.rb +8 -3
- data/lib/squared/common/prompt.rb +64 -30
- 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 +101 -46
- data/lib/squared/workspace/project/docker.rb +93 -44
- data/lib/squared/workspace/project/git.rb +53 -76
- data/lib/squared/workspace/project/node.rb +13 -11
- data/lib/squared/workspace/project/python.rb +58 -19
- data/lib/squared/workspace/project/ruby.rb +39 -28
- 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
|
|
|
@@ -1288,26 +1288,25 @@ module Squared
|
|
|
1288
1288
|
file = if (val = env('LOG_FILE'))
|
|
1289
1289
|
Time.now.strftime(val)
|
|
1290
1290
|
elsif (val = env('LOG_AUTO'))
|
|
1291
|
-
|
|
1291
|
+
d = Time.now
|
|
1292
1292
|
"#{@name}-%s.log" % [case val
|
|
1293
1293
|
when 'y', 'year'
|
|
1294
|
-
|
|
1294
|
+
d.year
|
|
1295
1295
|
when 'm', 'month'
|
|
1296
|
-
|
|
1296
|
+
d.strftime('%Y-%m')
|
|
1297
1297
|
when 'd', 'day', '1'
|
|
1298
|
-
|
|
1298
|
+
d.strftime('%Y-%m-%d')
|
|
1299
1299
|
else
|
|
1300
|
-
val.include?('%') ?
|
|
1300
|
+
val.include?('%') ? d.strftime(val) : d.strftime('%FT%T%:z')
|
|
1301
1301
|
end]
|
|
1302
1302
|
elsif (val = log[:file])
|
|
1303
1303
|
if val.is_a?(String)
|
|
1304
1304
|
Time.now.strftime(val)
|
|
1305
1305
|
else
|
|
1306
|
-
|
|
1307
|
-
"#{@name}-#{Date.today}.log"
|
|
1306
|
+
"#{@name}-#{Time.now.strftime('%Y-%m-%d')}.log"
|
|
1308
1307
|
end
|
|
1309
1308
|
end
|
|
1310
|
-
.
|
|
1309
|
+
.then do |path|
|
|
1311
1310
|
next unless path
|
|
1312
1311
|
|
|
1313
1312
|
@workspace.home.join(env('LOG_DIR', ''), path).realdirpath
|
|
@@ -1466,7 +1465,7 @@ module Squared
|
|
|
1466
1465
|
|
|
1467
1466
|
t = uniq.call(name = proj.name)
|
|
1468
1467
|
j = if out
|
|
1469
|
-
if i == items.size.pred || (post = items[i.succ
|
|
1468
|
+
if i == items.size.pred || (post = items[i.succ..] - done).empty?
|
|
1470
1469
|
true
|
|
1471
1470
|
elsif !t.empty? && depth > 0
|
|
1472
1471
|
(post - t).empty?
|
|
@@ -1572,14 +1571,18 @@ module Squared
|
|
|
1572
1571
|
end
|
|
1573
1572
|
|
|
1574
1573
|
def env(key, default = nil, suffix: nil, strict: false, ignore: nil, **kwargs, &blk)
|
|
1575
|
-
name = "#{key}_#{envname_get}"
|
|
1574
|
+
name = suffix == false ? key : "#{key}_#{envname_get}"
|
|
1576
1575
|
ret = if suffix
|
|
1577
1576
|
ENV["#{name}_#{suffix}"] || (ignore == false && ENV["#{key}_#{suffix}"]) || ''
|
|
1578
1577
|
elsif strict
|
|
1579
1578
|
ENV[name].to_s
|
|
1580
1579
|
else
|
|
1581
1580
|
ignore = ['0'].freeze if ignore.nil?
|
|
1582
|
-
|
|
1581
|
+
if key =~ /^(.+)_(FORCE|YES|Y)$/ && !(ret = __arg__($2 == 'Y' ? 'YES' : $2, $1)).nil?
|
|
1582
|
+
ret
|
|
1583
|
+
else
|
|
1584
|
+
ENV[name] || ENV.fetch(key, '')
|
|
1585
|
+
end
|
|
1583
1586
|
end
|
|
1584
1587
|
env_yield(ret, default, ignore: ignore, **kwargs, &blk)
|
|
1585
1588
|
end
|
|
@@ -1683,19 +1686,38 @@ module Squared
|
|
|
1683
1686
|
**kwargs)
|
|
1684
1687
|
return unless prefix
|
|
1685
1688
|
|
|
1689
|
+
getarg = ->(key) { ARG[key][s = prefix.downcase] || ARG[key][s.to_sym] }
|
|
1686
1690
|
args.each do |key|
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1691
|
+
ret = case key.downcase
|
|
1692
|
+
when 'force'
|
|
1693
|
+
getarg.call(:FORCE)
|
|
1694
|
+
when 'y'
|
|
1695
|
+
getarg.call(:YES)
|
|
1696
|
+
end
|
|
1697
|
+
return yield(ret) if !ret.nil? && block_given?
|
|
1698
|
+
|
|
1699
|
+
case ret.to_s
|
|
1700
|
+
when '0'
|
|
1701
|
+
next
|
|
1702
|
+
when 'true'
|
|
1703
|
+
return true
|
|
1704
|
+
when 'false'
|
|
1705
|
+
return false
|
|
1706
|
+
else
|
|
1707
|
+
ret ||= env(env_key(prefix.to_s.stripext, key), **kwargs)
|
|
1708
|
+
next unless ret && (!pat || ret.match?(pat))
|
|
1709
|
+
|
|
1710
|
+
if target
|
|
1711
|
+
if path
|
|
1712
|
+
target << quote_option(key, basepath(ret))
|
|
1713
|
+
elsif quote
|
|
1714
|
+
target << quote_option(key, ret)
|
|
1715
|
+
elsif escape
|
|
1716
|
+
target << shell_option(key, ret)
|
|
1717
|
+
end
|
|
1696
1718
|
end
|
|
1719
|
+
return block_given? ? yield(ret) : ret
|
|
1697
1720
|
end
|
|
1698
|
-
return block_given? ? yield(ret) : ret
|
|
1699
1721
|
end
|
|
1700
1722
|
nil
|
|
1701
1723
|
end
|
|
@@ -1808,6 +1830,8 @@ module Squared
|
|
|
1808
1830
|
|
|
1809
1831
|
case from
|
|
1810
1832
|
when :outdated
|
|
1833
|
+
return if ENV['BANNER'] == 'false'
|
|
1834
|
+
|
|
1811
1835
|
out = print_footer("major #{args[0]} / minor #{args[1]} / patch #{args[2]}", right: true).split("\n")
|
|
1812
1836
|
sub_style!(out[1], **opt_style(theme[:major], /^( +major )(\d+)(.+)$/, 2))
|
|
1813
1837
|
sub_style!(out[1], **opt_style(theme[:active], /^(.+)(minor )(\d+)(.+)$/, 3))
|
|
@@ -2030,27 +2054,27 @@ module Squared
|
|
|
2030
2054
|
val
|
|
2031
2055
|
end
|
|
2032
2056
|
end
|
|
2033
|
-
base.update(data)
|
|
2034
|
-
.update(ret)
|
|
2057
|
+
base.update(data, ret)
|
|
2035
2058
|
end
|
|
2036
2059
|
|
|
2037
2060
|
def merge_opts(base, data)
|
|
2061
|
+
s = '%s %s'
|
|
2038
2062
|
case data
|
|
2039
2063
|
when String
|
|
2040
2064
|
case base
|
|
2041
2065
|
when String
|
|
2042
|
-
|
|
2066
|
+
s % [base, data]
|
|
2043
2067
|
when Hash
|
|
2044
|
-
|
|
2068
|
+
s % [append_hash(base, target: []).join(' '), data]
|
|
2045
2069
|
when Enumerable
|
|
2046
|
-
|
|
2070
|
+
s % [base.to_a.join(' '), data]
|
|
2047
2071
|
else
|
|
2048
2072
|
data
|
|
2049
2073
|
end
|
|
2050
2074
|
when Hash
|
|
2051
2075
|
case base
|
|
2052
2076
|
when String
|
|
2053
|
-
|
|
2077
|
+
s % [base, append_hash(data, target: []).join(' ')]
|
|
2054
2078
|
when Hash
|
|
2055
2079
|
base.merge(data)
|
|
2056
2080
|
when Enumerable
|
|
@@ -2061,9 +2085,9 @@ module Squared
|
|
|
2061
2085
|
when Enumerable
|
|
2062
2086
|
case base
|
|
2063
2087
|
when String
|
|
2064
|
-
|
|
2088
|
+
s % [base, data.to_a.join(' ')]
|
|
2065
2089
|
when Hash
|
|
2066
|
-
|
|
2090
|
+
s % [append_hash(base, target: []).join(' '), data.to_a.join(' ')]
|
|
2067
2091
|
when Enumerable
|
|
2068
2092
|
Set.new(base.to_a + data.to_a).to_a
|
|
2069
2093
|
else
|
|
@@ -2097,6 +2121,17 @@ module Squared
|
|
|
2097
2121
|
end || []
|
|
2098
2122
|
end
|
|
2099
2123
|
|
|
2124
|
+
def parse_select(kwargs = {})
|
|
2125
|
+
pa, ch = ENV.fetch('SELECT', '0:0').split(':').map(&:to_i)
|
|
2126
|
+
if pa > 0
|
|
2127
|
+
kwargs[:page] = pa
|
|
2128
|
+
elsif !kwargs.key?(:page)
|
|
2129
|
+
kwargs[:page] = ARG[:PAGE]
|
|
2130
|
+
end
|
|
2131
|
+
kwargs[:max] = ch if ch > 0
|
|
2132
|
+
kwargs
|
|
2133
|
+
end
|
|
2134
|
+
|
|
2100
2135
|
def param_guard(action, flag, args:, key: nil, pat: nil, values: nil)
|
|
2101
2136
|
if args && key
|
|
2102
2137
|
val = args.fetch(key, nil)
|
|
@@ -2130,9 +2165,9 @@ module Squared
|
|
|
2130
2165
|
end
|
|
2131
2166
|
|
|
2132
2167
|
def choice_index(msg, list, values: nil, accept: nil, series: false, trim: nil, column: nil, multiple: false,
|
|
2133
|
-
force: true, **kwargs)
|
|
2168
|
+
force: true, pipe: self.pipe, **kwargs)
|
|
2134
2169
|
puts unless series || printfirst?
|
|
2135
|
-
ret = choice(msg, list, multiple: multiple, force: force, **kwargs)
|
|
2170
|
+
ret = choice(msg, list, multiple: multiple, force: force, pipe: pipe, **parse_select(kwargs))
|
|
2136
2171
|
unless ret && !ret.empty?
|
|
2137
2172
|
exit 1 if force
|
|
2138
2173
|
return
|
|
@@ -2216,12 +2251,12 @@ module Squared
|
|
|
2216
2251
|
end
|
|
2217
2252
|
|
|
2218
2253
|
def relativepath(*list, all: false)
|
|
2219
|
-
list.
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2254
|
+
list.filter_map do |val|
|
|
2255
|
+
next unless projectpath?(file = Pathname.new(val))
|
|
2256
|
+
|
|
2257
|
+
out = (file.absolute? ? file.relative_path_from(path) : file.cleanpath).to_s
|
|
2258
|
+
all && file.to_s.end_with?('/') ? "#{out}/*" : out
|
|
2259
|
+
end
|
|
2225
2260
|
end
|
|
2226
2261
|
|
|
2227
2262
|
def projectmap(files, resolve: true, parent: false, pass: true)
|
|
@@ -2324,6 +2359,19 @@ module Squared
|
|
|
2324
2359
|
cur[2] == lat[2] ? 3 : 2
|
|
2325
2360
|
end
|
|
2326
2361
|
|
|
2362
|
+
def semapp(name, *args, minor: true, patch: true, pre: false, env: false)
|
|
2363
|
+
if args.empty?
|
|
2364
|
+
args << '--version'
|
|
2365
|
+
else
|
|
2366
|
+
args.map! { |s| shell_quote(s, force: false) }
|
|
2367
|
+
end
|
|
2368
|
+
n = minor ? patch ? pre ? -1 : 4 : 2 : 0
|
|
2369
|
+
IO.popen([shell_bin(name, env: env), *args], chdir: path, &:read).scan(SEM_VER).first
|
|
2370
|
+
&.slice(0..n)&.join or raise
|
|
2371
|
+
rescue
|
|
2372
|
+
'0.0.0'
|
|
2373
|
+
end
|
|
2374
|
+
|
|
2327
2375
|
def semmajor?(cur, want)
|
|
2328
2376
|
(cur[0] == '0' && want[0] == '0' ? cur[2] != want[2] : cur[0] != want[0]) && !want[6]
|
|
2329
2377
|
end
|
|
@@ -2337,7 +2385,7 @@ module Squared
|
|
|
2337
2385
|
end
|
|
2338
2386
|
|
|
2339
2387
|
def indexitem(val)
|
|
2340
|
-
[$1.to_i, $2 && $2[1
|
|
2388
|
+
[$1.to_i, $2 && $2[1..]] if val =~ /\A[=^#{indexchar}](\d+)(:.+)?\z/
|
|
2341
2389
|
end
|
|
2342
2390
|
|
|
2343
2391
|
def indexerror(val, list = nil)
|
|
@@ -2441,7 +2489,6 @@ module Squared
|
|
|
2441
2489
|
def pwd_set(cmd = nil, pass: false, timeout: nil, from: @on[:from].last, **kwargs, &blk)
|
|
2442
2490
|
return if from == false
|
|
2443
2491
|
|
|
2444
|
-
require 'timeout'
|
|
2445
2492
|
unless (path.to_s == Dir.pwd || pass) && (mri? || !windows?)
|
|
2446
2493
|
pwd = Dir.pwd
|
|
2447
2494
|
Dir.chdir(path)
|
|
@@ -2738,7 +2785,15 @@ module Squared
|
|
|
2738
2785
|
end
|
|
2739
2786
|
|
|
2740
2787
|
def dryrun?(target: @session, prefix: target&.first, **)
|
|
2741
|
-
|
|
2788
|
+
val = ENV['DRY_RUN'] if (val = option('dry-run', target: target, prefix: prefix)).nil?
|
|
2789
|
+
case val.to_s
|
|
2790
|
+
when '0' then nil
|
|
2791
|
+
when 'false'
|
|
2792
|
+
return false
|
|
2793
|
+
else
|
|
2794
|
+
return true if val
|
|
2795
|
+
end
|
|
2796
|
+
Array(target).include?('--dry-run')
|
|
2742
2797
|
end
|
|
2743
2798
|
|
|
2744
2799
|
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
|