squared 0.4.7 → 0.4.8

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.
@@ -4,7 +4,6 @@ require 'json'
4
4
  require 'date'
5
5
  require 'time'
6
6
  require 'logger'
7
- require 'digest'
8
7
 
9
8
  module Squared
10
9
  module Workspace
@@ -22,7 +21,8 @@ module Squared
22
21
  BLK_SET = %i[run depend doc lint test copy clean].freeze
23
22
  SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?\b/.freeze
24
23
  URI_SCHEME = %r{^([a-z][a-z\d+-.]*)://[^@:\[\]\\^<>|\s]}i.freeze
25
- private_constant :VAR_SET, :BLK_SET, :SEM_VER, :URI_SCHEME
24
+ TASK_METADATA = Rake::TaskManager.record_task_metadata
25
+ private_constant :VAR_SET, :BLK_SET, :SEM_VER, :URI_SCHEME, :TASK_METADATA
26
26
 
27
27
  class << self
28
28
  def populate(*); end
@@ -47,7 +47,9 @@ module Squared
47
47
  @ref ||= to_s.downcase.to_sym
48
48
  end
49
49
 
50
- def subtasks(val)
50
+ def subtasks(val = nil, &blk)
51
+ return @@tasks[val || ref].each(&blk) if block_given?
52
+
51
53
  @@tasks[ref] = val.freeze
52
54
  end
53
55
 
@@ -61,12 +63,11 @@ module Squared
61
63
  end
62
64
 
63
65
  @@tasks = {}
64
- @@task_desc = Rake::TaskManager.record_task_metadata
65
66
  @@print_order = 0
66
67
 
67
68
  subtasks({
68
69
  'graph' => %i[run print].freeze,
69
- 'unpack' => %i[zip tar ext].freeze
70
+ 'unpack' => %i[zip tar gem ext].freeze
70
71
  })
71
72
 
72
73
  attr_reader :name, :project, :workspace, :path, :theme, :exception, :pipe, :verbose,
@@ -97,7 +98,7 @@ module Squared
97
98
  @exception = env_bool(kwargs[:exception], workspace.exception, strict: true)
98
99
  @pipe = env_pipe(kwargs[:pipe], workspace.pipe, strict: true)
99
100
  @verbose = case verbose
100
- when nil
101
+ when NilClass
101
102
  workspace.verbose
102
103
  when String
103
104
  env_bool(verbose, workspace.verbose, strict: true, index: true)
@@ -267,7 +268,7 @@ module Squared
267
268
  return unless ref?(Base.ref)
268
269
 
269
270
  namespace name do
270
- @@tasks[Base.ref].each do |action, flags|
271
+ Base.subtasks do |action, flags|
271
272
  next if @pass.include?(action)
272
273
 
273
274
  namespace action do
@@ -300,17 +301,21 @@ module Squared
300
301
  end
301
302
  end
302
303
  when 'unpack'
303
- format_desc(action, flag, 'tag/url,dir,digest?,f/force?', before: flag == :ext ? 'ext' : nil)
304
+ format_desc(action, flag, 'tag/url,dir,digest?,f|force?', before: flag == :ext ? 'ext' : nil)
304
305
  params = %i[tag dir digest force]
305
306
  params.unshift(:ext) if flag == :ext
306
307
  task flag, params do |_, args|
307
- ext = param_guard(action, flag, args: args, key: :ext).downcase if flag == :ext
308
+ ext = flag == :ext ? param_guard(action, flag, args: args, key: :ext) : flag.to_s
308
309
  tag = param_guard(action, flag, args: args, key: :tag)
309
310
  dir = param_guard(action, flag, args: args, key: :dir)
310
311
  unless tag.match?(URI_SCHEME)
311
- raise_error 'no base uri' unless @release
312
-
313
- tag = "#{@release.include?('??') ? @release.sub('??', tag) : @release + tag}.#{flag}"
312
+ if flag == :gem
313
+ tag = "https://rubygems.org/downloads/#{File.basename(tag, '.gem')}.gem"
314
+ elsif @release
315
+ tag = "%s.#{ext}" % [@release.include?('??') ? @release.sub('??', tag) : @release + tag]
316
+ else
317
+ raise_error("no base uri: #{tag}", hint: ext)
318
+ end
314
319
  end
315
320
  case (digest = args.digest)
316
321
  when 'f', 'force'
@@ -319,7 +324,7 @@ module Squared
319
324
  else
320
325
  force = args.fetch(:force, false)
321
326
  end
322
- unpack(basepath(dir), uri: tag, digest: digest, ext: ext || flag.to_s, force: force)
327
+ unpack(basepath(dir), uri: tag, digest: digest, ext: ext, force: force)
323
328
  end
324
329
  end
325
330
  end
@@ -351,15 +356,15 @@ module Squared
351
356
  end
352
357
  end
353
358
  if path.is_a?(String) && (seg = path[%r{^(.+)[\\/]\*+$}, 1])
354
- return self unless checkdir.(path = basepath(seg))
359
+ return self unless checkdir.call(path = basepath(seg))
355
360
 
356
- path = path.children.select { |val| checkdir.(val) }
361
+ path = path.children.select { |val| checkdir.call(val) }
357
362
  end
358
363
  if path.is_a?(Array)
359
364
  name = @name if name == true
360
365
  path.each { |val| add(val, name && task_join(name, File.basename(val)), **kwargs, &blk) }
361
366
  return self
362
- elsif !projectpath?(path = basepath(path)) || !checkdir.(path)
367
+ elsif !projectpath?(path = basepath(path)) || !checkdir.call(path)
363
368
  return self
364
369
  elsif name.is_a?(Symbol)
365
370
  name = name.to_s
@@ -405,10 +410,17 @@ module Squared
405
410
  args = @output
406
411
  banner = verbosetype > 1 if task_invoked?('build', 'build:sync', 'default')
407
412
  end
413
+ if args.first.is_a?(Struct)
414
+ f, blk = args.first.to_a
415
+ args[0] = instance_eval(&blk) || f
416
+ return unless args[0]
417
+ end
408
418
  if args.all? { |val| val.is_a?(Array) }
409
419
  cmd = []
410
420
  var = {}
411
421
  args.each do |val|
422
+ next instance_exec(*val[1..-1], &val[0]) if val.first.is_a?(Proc)
423
+
412
424
  a, b, c, d, e = val
413
425
  case b
414
426
  when Hash
@@ -479,11 +491,18 @@ module Squared
479
491
  run_b(@copy, sync: sync, from: :copy)
480
492
  end
481
493
 
482
- def clean(*, sync: invoked_sync?('clean'), **)
494
+ def clean(*args, sync: invoked_sync?('clean'), pass: false, **kwargs)
483
495
  return unless @clean
484
496
 
485
- on :first, :clean
497
+ on :first, :clean unless pass
486
498
  case @clean
499
+ when Struct
500
+ if (any = instance_eval(&@clean.block) || @clean.run)
501
+ temp = @clean
502
+ @clean = any
503
+ clean(*args, sync: sync, pass: true, **kwargs)
504
+ @clean = temp
505
+ end
487
506
  when String
488
507
  run_s(@clean, sync: sync)
489
508
  when Hash
@@ -518,7 +537,7 @@ module Squared
518
537
  run_b(@clean, sync: sync)
519
538
  end
520
539
  end
521
- on :last, :clean
540
+ on :last, :clean unless pass
522
541
  end
523
542
 
524
543
  def graph(start = [], tasks = nil, sync: invoked_sync?('graph'), pass: [], out: nil)
@@ -561,8 +580,11 @@ module Squared
561
580
  elsif !target.empty?
562
581
  raise_error('directory not empty', hint: target) unless force || env('UNPACK_FORCE')
563
582
  create = true
583
+ elsif !uri
584
+ raise_error('no download uri', hint: target)
564
585
  end
565
586
  if digest
587
+ require 'digest'
566
588
  if (n = digest.index(':').to_i) > 0
567
589
  size = digest[0, n].downcase
568
590
  digest = digest[n + 1..-1]
@@ -616,13 +638,19 @@ module Squared
616
638
  raise_error('no content', hint: url)
617
639
  end
618
640
  end
619
- ext ||= URI.parse(uri).path[/\.(\w+)(\?|$)/i, 1]
620
- if (n = env("#{ext == 'zip' || ext == '7z' ? ext.upcase : 'TAR'}_DEPTH", ignore: false))
621
- depth = n.to_i
641
+ raise_error('no content type', hint: uri) unless ext ||= URI.parse(uri).path[/\.(\w+)(\?|$)/i, 1]
642
+ ext = ext.downcase
643
+ if (val = env("#{%w[zip 7z gem].include?(ext) ? ext.upcase : 'TAR'}_DEPTH", ignore: false))
644
+ depth = val.to_i
622
645
  end
623
646
  begin
624
- require 'tempfile'
625
- file = Tempfile.new("#{name}-")
647
+ if ext == 'gem'
648
+ dir = Dir.mktmpdir
649
+ file = File.new(File.join(dir, File.basename(uri)), 'w')
650
+ else
651
+ require 'tempfile'
652
+ file = Tempfile.new("#{name}-")
653
+ end
626
654
  file.write(data)
627
655
  file.close
628
656
  if create
@@ -630,7 +658,7 @@ module Squared
630
658
  target.rmtree
631
659
  target.mkpath
632
660
  end
633
- case ext.downcase
661
+ case ext
634
662
  when 'zip', 'aar'
635
663
  session 'unzip', shell_quote(file.path), quote_option('d', target)
636
664
  when 'tar', 'tgz', 'tar.gz', 'tar.xz', 'gz', 'xz'
@@ -645,6 +673,9 @@ module Squared
645
673
  depth = 0
646
674
  when '7z'
647
675
  session '7z', 'x', shell_quote(file.path), "-o#{shell_quote(target)}"
676
+ when 'gem'
677
+ session 'gem', 'unpack', shell_quote(file.path), quote_option('target', target)
678
+ depth = 0 unless val
648
679
  else
649
680
  raise_error("unsupported format: #{ext}", hint: uri)
650
681
  end
@@ -653,15 +684,22 @@ module Squared
653
684
  entry = target.children.first
654
685
  break unless entry.directory?
655
686
 
656
- dest = target.join(File.basename(file.path))
657
- mv(entry, dest)
658
- dest.children.each { |child| mv(child, target) }
687
+ i = 0
688
+ while (dest = target.join("#{File.basename(file.path)}-#{i}")).exist?
689
+ i += 1
690
+ end
691
+ FileUtils.mv(entry, dest)
692
+ dest.children.each { |child| FileUtils.mv(child, target) }
659
693
  dest.rmdir
660
694
  target = entry
661
695
  depth -= 1
662
696
  end
663
697
  ensure
664
- file&.unlink
698
+ if dir
699
+ remove_entry dir
700
+ elsif file
701
+ file.unlink
702
+ end
665
703
  end
666
704
  end
667
705
 
@@ -721,7 +759,7 @@ module Squared
721
759
  @parent = val if (val = val.first).is_a?(Project::Base)
722
760
  when :graph
723
761
  @graph = case val.first
724
- when nil, false
762
+ when NilClass, FalseClass
725
763
  nil
726
764
  else
727
765
  val.flatten.map!(&:to_s).freeze
@@ -924,7 +962,13 @@ module Squared
924
962
 
925
963
  def run_b(obj, from: nil, sync: true)
926
964
  case obj
927
- when Proc, Method
965
+ when Struct
966
+ if (any = instance_eval(&obj.block) || obj.run)
967
+ run_b(any, from: from, sync: sync)
968
+ end
969
+ when Proc
970
+ instance_eval(&obj)
971
+ when Method
928
972
  obj.call
929
973
  else
930
974
  if series?(obj)
@@ -953,14 +997,14 @@ module Squared
953
997
  end
954
998
  start = target.name
955
999
  if depth == 0
956
- items = check.(dedupe.(start))
1000
+ items = check.call(dedupe.call(start))
957
1001
  single = items.size == 1
958
1002
  else
959
- items = check.(data[start])
1003
+ items = check.call(data[start])
960
1004
  end
961
1005
  if out
962
1006
  a, b, c, d, e = ARG[:GRAPH]
963
- f = tag.(target)
1007
+ f = tag.call(target)
964
1008
  out << case depth
965
1009
  when 0
966
1010
  f
@@ -977,15 +1021,15 @@ module Squared
977
1021
  items.each_with_index do |proj, i|
978
1022
  next if done.include?(proj)
979
1023
 
980
- t = dedupe.(proj.name)
1024
+ t = dedupe.call(proj.name)
981
1025
  j = if out
982
- if i == items.size - 1 || check.(post = items[i + 1..-1]).empty?
1026
+ if i == items.size - 1 || check.call(post = items[i + 1..-1]).empty?
983
1027
  true
984
1028
  elsif !t.empty? && depth > 0
985
1029
  post.reject { |pr| t.include?(pr) }.empty?
986
1030
  end
987
1031
  end
988
- unless start == proj.name || (none = check.(t).empty?)
1032
+ unless start == proj.name || (none = check.call(t).empty?)
989
1033
  graph_branch(proj, data, tasks, out, sync: sync, pass: pass, done: done, depth: depth.succ,
990
1034
  single: single, last: j == true, context: target)
991
1035
  end
@@ -1011,7 +1055,7 @@ module Squared
1011
1055
  elsif none
1012
1056
  a, b, c, d = ARG[:GRAPH]
1013
1057
  out << if depth == 0
1014
- "#{i == items.size - 1 ? d : c}#{b * 4} #{tag.(proj)}"
1058
+ "#{i == items.size - 1 ? d : c}#{b * 4} #{tag.call(proj)}"
1015
1059
  else
1016
1060
  s = ''.dup
1017
1061
  k = 0
@@ -1021,7 +1065,7 @@ module Squared
1021
1065
  s += "#{indent || (last && data[final].last == context) ? ' ' : a} "
1022
1066
  k += 1
1023
1067
  end
1024
- s + "#{j ? d : c}#{b * 3} #{tag.(proj)}"
1068
+ s + "#{j ? d : c}#{b * 3} #{tag.call(proj)}"
1025
1069
  end
1026
1070
  end
1027
1071
  done << proj
@@ -1172,7 +1216,7 @@ module Squared
1172
1216
  end
1173
1217
 
1174
1218
  def format_desc(action, flag, opts = nil, **kwargs)
1175
- return unless @@task_desc
1219
+ return unless TASK_METADATA
1176
1220
 
1177
1221
  ret = [@desc, action]
1178
1222
  ret << flag if flag
@@ -1232,7 +1276,7 @@ module Squared
1232
1276
  items.each_with_index do |val, i|
1233
1277
  next unless reg.empty? || reg.any? { |pat| val[0].match?(pat) }
1234
1278
 
1235
- out << "#{i.succ.to_s.rjust(pad)}. #{each ? each.(val) : val[0]}"
1279
+ out << "#{i.succ.to_s.rjust(pad)}. #{each ? each.call(val) : val[0]}"
1236
1280
  end
1237
1281
  end
1238
1282
  sub = [headerstyle]
@@ -1287,7 +1331,7 @@ module Squared
1287
1331
  append_repeat(key, val, target: target)
1288
1332
  when Numeric
1289
1333
  target << basic_option(key, val)
1290
- when false
1334
+ when FalseClass
1291
1335
  target << shell_option(key).sub(/^--(?!no-)/, '--no-')
1292
1336
  else
1293
1337
  target << shell_option(key, val.is_a?(String) ? val : nil)
@@ -1441,6 +1485,39 @@ module Squared
1441
1485
  args
1442
1486
  end
1443
1487
 
1488
+ def confirm_outdated(pkg, ver, rev, lock: false)
1489
+ a = sub_style(case rev
1490
+ when 1
1491
+ 'MAJOR'
1492
+ when 2
1493
+ 'MINOR'
1494
+ else
1495
+ 'PATCH'
1496
+ end, styles: theme[:header])
1497
+ b = sub_style("#{pkg} #{ver}", styles: theme[:inline])
1498
+ c, d = rev == 1 || lock ? ['y/N', 'N'] : ['Y/n', 'Y']
1499
+ e = lock ? " #{sub_style('(locked)', styles: color(:red))}" : ''
1500
+ confirm("Upgrade to #{a}? #{b + e} [#{c}] ", d, timeout: 60)
1501
+ end
1502
+
1503
+ def choice_index(msg, list, values: nil, multiple: false, accept: nil, trim: nil)
1504
+ puts if @@print_order > 0
1505
+ raise_error 'user cancelled' unless (ret = choice(msg, list, multiple: multiple))
1506
+ ret = multiple ? ret.map! { |val| val.sub(trim, '') } : ret.sub(trim, '') if trim
1507
+ exit 1 if accept && !confirm("#{accept} [#{ret.join(', ')}] [y/N] ", 'N', timeout: 60)
1508
+ if values
1509
+ ret = [ret]
1510
+ values.each do |val|
1511
+ val, req = val if val.is_a?(Array)
1512
+ val = Readline.readline("#{val} (#{req ? 'required' : 'optional'}): ", true).strip
1513
+ raise_error 'user cancelled' if req && val.empty?
1514
+ ret << (val.empty? ? nil : val)
1515
+ end
1516
+ end
1517
+ @@print_order += 1
1518
+ ret
1519
+ end
1520
+
1444
1521
  def runenv
1445
1522
  nil
1446
1523
  end
@@ -1515,7 +1592,7 @@ module Squared
1515
1592
 
1516
1593
  def verbosetype
1517
1594
  case verbose
1518
- when true
1595
+ when TrueClasss
1519
1596
  1
1520
1597
  when Numeric
1521
1598
  verbose.succ
@@ -1546,15 +1623,15 @@ module Squared
1546
1623
  end
1547
1624
  end
1548
1625
 
1549
- def pwd_set(done = nil, pass: false, from: nil, dryrun: false, &blk)
1626
+ def pwd_set(done = nil, pass: false, from: nil, dryrun: false)
1550
1627
  pwd = Pathname.pwd
1551
1628
  if block_given?
1552
1629
  begin
1553
1630
  if path == pwd || pass == true || (pass.is_a?(String) && semscan(pass).join >= RUBY_VERSION)
1554
- ret = instance_eval(&blk)
1631
+ ret = yield
1555
1632
  else
1556
1633
  Dir.chdir(path)
1557
- ret = instance_eval(&blk)
1634
+ ret = yield
1558
1635
  Dir.chdir(pwd)
1559
1636
  end
1560
1637
  rescue StandardError => e
@@ -1605,13 +1682,13 @@ module Squared
1605
1682
  @output = if cmd.all? { |data| data.is_a?(Hash) }
1606
1683
  diso = false
1607
1684
  dise = false
1608
- cmd.map { |data| parse.(data) }
1685
+ cmd.map { |data| parse.call(data) }
1609
1686
  else
1610
1687
  cmd.dup
1611
1688
  end
1612
1689
  return
1613
1690
  when Hash
1614
- @output = parse.(data)
1691
+ @output = parse.call(data)
1615
1692
  else
1616
1693
  @output[0] = cmd
1617
1694
  end
@@ -125,7 +125,7 @@ module Squared
125
125
  return unless ref?(Docker.ref)
126
126
 
127
127
  namespace name do
128
- @@tasks[Docker.ref].each do |action, flags|
128
+ Docker.subtasks do |action, flags|
129
129
  next if @pass.include?(action)
130
130
 
131
131
  namespace action do
@@ -151,31 +151,38 @@ module Squared
151
151
  when :build, :up
152
152
  format_desc action, flag, 'opts*,service*'
153
153
  task flag do |_, args|
154
- composex flag, args.to_a
154
+ compose! flag, args.to_a
155
155
  end
156
156
  when :exec, :run
157
157
  format_desc action, flag, "service,command#{flag == :exec ? '' : '?'},args*,opts*"
158
158
  task flag, [:service] do |_, args|
159
159
  service = param_guard(action, flag, args: args, key: :service)
160
- composex(flag, args.extras, service: service)
160
+ compose!(flag, args.extras, service: service)
161
161
  end
162
162
  end
163
163
  when 'container'
164
164
  case flag
165
165
  when :exec, :commit
166
- format_desc(action, flag, 'id/name,opts*', after: flag == :exec ? 'args+' : 'tag?')
166
+ format_desc(action, flag, flag == :exec ? 'id/name?,opts*,args+' : 'id/name,tag?,opts*')
167
167
  task flag, [:id] do |_, args|
168
- id = param_guard(action, flag, args: args, key: :id)
169
- container(flag, args.extras, id: id)
168
+ if flag == :exec && !args.id
169
+ choice_command flag
170
+ else
171
+ id = param_guard(action, flag, args: args, key: :id)
172
+ container(flag, args.extras, id: id)
173
+ end
170
174
  end
171
175
  when :run
172
- format_desc action, flag, 'image,opts*,args*'
176
+ format_desc action, flag, 'image?,opts*,args*'
173
177
  task flag, [:image] do |_, args|
174
- image = param_guard(action, flag, args: args, key: :image)
175
- container(flag, args.extras, id: image)
178
+ if args.image
179
+ container(flag, args.extras, id: args.image)
180
+ else
181
+ choice_command flag
182
+ end
176
183
  end
177
184
  else
178
- format_desc(action, flag, 'opts*', after: "id/name#{flag == :update ? '+' : '*'}")
185
+ format_desc(action, flag, 'opts*,id/name', after: flag == :update ? '+' : '*')
179
186
  task flag do |_, args|
180
187
  container flag, args.to_a
181
188
  end
@@ -188,7 +195,7 @@ module Squared
188
195
  tag = param_guard(action, flag, args: args, key: :tag)
189
196
  image(flag, args.extras, id: tag)
190
197
  end
191
- else
198
+ when :list, :rm
192
199
  format_desc(action, flag, flag == :rm ? 'id*,opts*' : 'opts*,args*')
193
200
  task flag do |_, args|
194
201
  image flag, args.to_a
@@ -197,8 +204,11 @@ module Squared
197
204
  when 'network'
198
205
  format_desc action, flag, 'target,opts*'
199
206
  task flag, [:target] do |_, args|
200
- target = param_guard(action, flag, args: args, key: :target)
201
- network(flag, args.extras, target: target)
207
+ if (target = args.target)
208
+ network(flag, args.extras, target: target)
209
+ else
210
+ choice_command flag
211
+ end
202
212
  end
203
213
  end
204
214
  end
@@ -251,13 +261,13 @@ module Squared
251
261
  when :build
252
262
  case @secrets
253
263
  when String
254
- quote_option('secret', @secrets, double: true)
264
+ ret << quote_option('secret', @secrets, double: true)
255
265
  when Hash
256
266
  append = lambda do |type|
257
267
  as_a(@secrets[type]).each { |arg| ret << quote_option('secret', "type=#{type},#{arg}", double: true) }
258
268
  end
259
- append.(:file)
260
- append.(:env)
269
+ append.call(:file)
270
+ append.call(:env)
261
271
  else
262
272
  as_a(@secrets).each { |arg| ret << quote_option('secret', arg) }
263
273
  end
@@ -304,7 +314,7 @@ module Squared
304
314
  run(from: :"buildx:#{flag}")
305
315
  end
306
316
 
307
- def composex(flag, opts = [], service: nil)
317
+ def compose!(flag, opts = [], service: nil)
308
318
  cmd, opts = docker_session('compose', opts: opts)
309
319
  op = OptionPartition.new(opts, OPT_DOCKER[:compose][:common], cmd, project: self)
310
320
  append_file filetype unless op.arg?('f', 'file')
@@ -449,8 +459,7 @@ module Squared
449
459
  op << id
450
460
  else
451
461
  if op.empty?
452
- list_image(flag, docker_output('image', 'ls', '-a'), from: from) do |val|
453
- puts val
462
+ list_image(flag, docker_output('image ls -a'), from: from) do |val|
454
463
  image(:rm, opts, sync: sync, id: val)
455
464
  end
456
465
  else
@@ -522,6 +531,9 @@ module Squared
522
531
  end
523
532
 
524
533
  def append_command(flag, val, list, target: @session, from: nil)
534
+ if (args = env('DOCKER_ARGS'))
535
+ list << args
536
+ end
525
537
  case flag
526
538
  when :run
527
539
  unless session_arg?('name', target: target)
@@ -532,7 +544,7 @@ module Squared
532
544
  raise_error('no command args', hint: from) if list.empty?
533
545
  end
534
546
  target << val << list.shift
535
- target << shell_quote(list.join(' && '), double: true, option: false) unless list.empty?
547
+ target << list.join(' && ') unless list.empty?
536
548
  end
537
549
 
538
550
  def append_file(type, target: @session)
@@ -569,7 +581,7 @@ module Squared
569
581
  end
570
582
  end
571
583
 
572
- def list_image(flag, cmd, hint: nil, from: nil, no: true, &blk)
584
+ def list_image(flag, cmd, hint: nil, from: nil, no: true)
573
585
  pwd_set do
574
586
  found = false
575
587
  index = 0
@@ -586,7 +598,7 @@ module Squared
586
598
  id
587
599
  end)
588
600
  ee = data['Image'] || rt || aa
589
- next unless ee.match?(pat) || aa.match?(pat)
601
+ next unless option('all') || ee.match?(pat) || aa.match?(pat)
590
602
 
591
603
  bb = index.succ.to_s
592
604
  cc = bb.size + 1
@@ -618,7 +630,7 @@ module Squared
618
630
  next unless confirm("#{h + b}? [#{c}] ", d, timeout: 60)
619
631
 
620
632
  puts if @@print_order == 0
621
- blk.call id
633
+ yield id
622
634
  end
623
635
  puts log_message(Logger::INFO, 'none detected', subject: "#{name}:#{from}", hint: hint) unless found
624
636
  end
@@ -646,6 +658,35 @@ module Squared
646
658
  confirm("#{a} #{b}#{c ? " as #{c}" : ''}? [y/N] ", 'N', timeout: 60)
647
659
  end
648
660
 
661
+ def choice_command(flag)
662
+ msg, cmd, index = case flag
663
+ when :run
664
+ ['Choose an image', 'images -a', 2]
665
+ when :exec
666
+ ['Choose a container', 'ps -a', 0]
667
+ else
668
+ ['Choose a network', 'network ls', 0]
669
+ end
670
+ lines = `#{docker_output(cmd)}`.lines
671
+ header = lines.shift
672
+ if lines.empty?
673
+ puts log_message(Logger::INFO, 'none found', subject: name, hint: "docker #{cmd}")
674
+ else
675
+ puts " # #{header}"
676
+ case flag
677
+ when :run, :exec
678
+ values = [['Options', flag == :run], ['Command arguments', flag == :exec]]
679
+ cmd = flag.to_s
680
+ else
681
+ values = [['Options', false], ['Container', true]]
682
+ cmd = "network #{flag}"
683
+ end
684
+ out, opts, args = choice_index(msg, lines, values: values)
685
+ ret = run docker_output(cmd, opts, '--', out.split(/\s+/)[index], args)
686
+ puts 'Success' if ret && cmd.start_with?('network')
687
+ end
688
+ end
689
+
649
690
  def filetype(val = dockerfile)
650
691
  case File.extname(val)
651
692
  when '.hcl', '.json'