squared 0.5.3 → 0.5.5

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.
@@ -19,10 +19,10 @@ module Squared
19
19
  include ::Comparable
20
20
 
21
21
  VAR_SET = %i[parent global script index envname desc dependfile dependindex theme archive env dev prod graph
22
- pass only exclude].freeze
22
+ pass only exclude asdf].freeze
23
23
  BLK_SET = %i[run depend doc lint test copy clean].freeze
24
- SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?\b/.freeze
25
- URI_SCHEME = %r{^([a-z][a-z\d+-.]*)://[^@:\[\]\\^<>|\s]}i.freeze
24
+ SEM_VER = /\b(\d+)(?:(\.)(\d+))?(?:(\.)(\d+))?[-.]?(\S+)?\b/.freeze
25
+ URI_SCHEME = %r{\A([a-z][a-z\d+-.]*)://[^@:\[\]\\^<>|\s]}i.freeze
26
26
  TASK_METADATA = Rake::TaskManager.record_task_metadata
27
27
  private_constant :VAR_SET, :BLK_SET, :SEM_VER, :URI_SCHEME, :TASK_METADATA
28
28
 
@@ -66,11 +66,17 @@ module Squared
66
66
 
67
67
  @@tasks = {}
68
68
  @@graph = { _: [] }
69
+ @@asdf = if File.exist?("#{Dir.home}/.asdf/asdf.sh")
70
+ [Pathname.new("#{Dir.home}/.asdf"), 15]
71
+ elsif ENV['ASDF_DATA_DIR']
72
+ [Pathname.new(ENV['ASDF_DATA_DIR']), 16]
73
+ end
69
74
  @@print_order = 0
70
75
 
71
76
  subtasks({
72
77
  'graph' => %i[run print].freeze,
73
- 'unpack' => %i[zip tar gem ext].freeze
78
+ 'unpack' => %i[zip tar gem ext].freeze,
79
+ 'asdf' => %i[set exec current]
74
80
  })
75
81
 
76
82
  attr_reader :name, :project, :workspace, :path, :theme, :group, :parent, :dependfile,
@@ -114,6 +120,7 @@ module Squared
114
120
  only_set kwargs[:only]
115
121
  exclude_set kwargs[:exclude]
116
122
  archive_set kwargs[:archive]
123
+ asdf_set kwargs[:asdf]
117
124
  theme_set common
118
125
  initialize_ref Base.ref
119
126
  end
@@ -213,7 +220,7 @@ module Squared
213
220
  def initialize_env(dev: nil, prod: nil, **)
214
221
  @dev = env_match('BUILD', dev, suffix: 'DEV', strict: true)
215
222
  @prod = env_match('BUILD', prod, suffix: 'PROD', strict: true)
216
- if @output[2] != false && (val = env('BUILD', suffix: 'ENV'))
223
+ unless @output[2] == false || !(val = env('BUILD', suffix: 'ENV'))
217
224
  @output[2] = parse_json(val, hint: "BUILD_#{@envname}_ENV") || @output[2]
218
225
  end
219
226
  unless @output[0] == false || @output[0].is_a?(Array)
@@ -318,7 +325,7 @@ module Squared
318
325
  flags.each do |flag|
319
326
  case action
320
327
  when 'graph'
321
- next unless graph?
328
+ break unless graph?
322
329
 
323
330
  format_desc action, flag, '(-)project*'
324
331
  task flag do |_, args|
@@ -369,6 +376,32 @@ module Squared
369
376
  end
370
377
  unpack(path + dir, uri: tag, digest: digest, ext: ext, force: force)
371
378
  end
379
+ when 'asdf'
380
+ break unless @asdf
381
+
382
+ case flag
383
+ when :set
384
+ format_desc action, flag, 'version,opts*=u|home,p|parent'
385
+ task flag, [:version] do |_, args|
386
+ args = if (version = args.version)
387
+ args.extras
388
+ else
389
+ version, opts = choice_index('Select a version',
390
+ @asdf[1].children.map(&:basename).push('latest'),
391
+ force: true, accept: [['Confirm?', false, true]],
392
+ values: ['Options'])
393
+ OptionPartition.strip(opts)
394
+ end
395
+ asdf(flag, args, version: version)
396
+ end
397
+ else
398
+ format_desc(action, flag, flag == :exec ? 'command' : nil)
399
+ task flag do |_, args|
400
+ args = args.to_a
401
+ args << readline('Enter command', force: true) if args.empty? && flag == :exec
402
+ asdf flag, args
403
+ end
404
+ end
372
405
  end
373
406
  end
374
407
  end
@@ -451,13 +484,13 @@ module Squared
451
484
  if args.first.is_a?(Struct)
452
485
  f, blk = args.first.to_a
453
486
  args[0] = instance_eval(&blk) || f
454
- return unless args[0]
487
+ return unless args.first
455
488
  end
456
489
  if args.all? { |val| val.is_a?(Array) }
457
490
  cmd = []
458
491
  var = {}
459
492
  args.each do |val|
460
- next instance_exec(*val[1..-1], &val[0]) if val.first.is_a?(Proc)
493
+ next instance_exec(*val[1..-1], &val.first) if val.first.is_a?(Proc)
461
494
 
462
495
  a, b, c, d, e = val
463
496
  case b
@@ -658,7 +691,7 @@ module Squared
658
691
  when 128, 'sha512'
659
692
  Digest::SHA512
660
693
  else
661
- raise_error("invalid checksum: #{digest}", hint: name)
694
+ raise_error "invalid checksum: #{digest}"
662
695
  end
663
696
  end
664
697
  if (val = env('HEADERS')) && (val = parse_json(val, hint: "HEADERS_#{@envname}"))
@@ -761,6 +794,33 @@ module Squared
761
794
  end
762
795
  end
763
796
 
797
+ def asdf(flag, opts = [], version: nil)
798
+ return unless @asdf
799
+
800
+ cmd = session 'asdf', flag
801
+ name = @asdf.first
802
+ legacy = @@asdf[1] == 15
803
+ case flag
804
+ when :set
805
+ u = has_value?(opts, %w[u home])
806
+ cmd << if legacy
807
+ cmd.delete(flag)
808
+ u ? 'global' : 'local'
809
+ elsif has_value?(opts, %w[p parent])
810
+ '--parent'
811
+ elsif u
812
+ '--home'
813
+ end
814
+ cmd << name << version
815
+ when :exec
816
+ cmd.merge(opts)
817
+ when :current
818
+ cmd << '--no-header' unless legacy
819
+ cmd << name
820
+ end
821
+ print_success if success?(run(from: :"asdf:#{flag}")) && flag == :set
822
+ end
823
+
764
824
  def first(key, *args, **kwargs, &blk)
765
825
  event(:first, key, *args, **kwargs, &blk)
766
826
  end
@@ -836,6 +896,8 @@ module Squared
836
896
  parent_set val
837
897
  when :archive
838
898
  archive_set val
899
+ when :asdf
900
+ asdf_set val
839
901
  when :run
840
902
  run_set(*args, **kwargs)
841
903
  when :script
@@ -945,7 +1007,7 @@ module Squared
945
1007
  def log
946
1008
  return @log unless @log.is_a?(Array)
947
1009
 
948
- @log = Logger.new(enabled? ? @log[0] : nil, **@log[1])
1010
+ @log = Logger.new(enabled? ? @log.first : nil, **@log.last)
949
1011
  end
950
1012
 
951
1013
  def allref
@@ -986,20 +1048,18 @@ module Squared
986
1048
 
987
1049
  private
988
1050
 
989
- def puts(*args)
990
- puts_oe(*args, pipe: pipe)
1051
+ def puts(*args, **kwargs)
1052
+ log_console(*args, pipe: kwargs[:pipe] || pipe)
991
1053
  end
992
1054
 
993
1055
  def run(cmd = @session, var = nil, exception: self.exception, sync: true, from: nil, banner: true, chdir: path,
994
- interactive: nil, **)
1056
+ interactive: nil, hint: nil, **)
995
1057
  unless cmd
996
1058
  warn log_message(Logger::WARN, 'no command given', subject: project, hint: from || 'unknown', pass: true)
997
1059
  return
998
1060
  end
999
- i = interactive && !(@session && option('y'))
1000
1061
  cmd = cmd.target if cmd.is_a?(OptionPartition)
1001
- cmd = session_done cmd
1002
- if i
1062
+ if interactive && (!@session || !option('y'))
1003
1063
  title, y = case interactive
1004
1064
  when Array
1005
1065
  interactive
@@ -1008,8 +1068,9 @@ module Squared
1008
1068
  else
1009
1069
  ['Run', 'Y']
1010
1070
  end
1011
- exit 1 unless confirm("#{title}? [#{sub_style(cmd, styles: theme[:inline])}]", y)
1071
+ exit 1 unless confirm("#{title}? [#{sub_style(cmd.to_s, styles: theme[:inline])}]", y)
1012
1072
  end
1073
+ cmd = session_done cmd
1013
1074
  log&.info cmd
1014
1075
  on :first, from
1015
1076
  begin
@@ -1017,7 +1078,7 @@ module Squared
1017
1078
  log&.warn "ENV discarded: #{var}" if var
1018
1079
  task_invoke(cmd, exception: exception, warning: warning?)
1019
1080
  else
1020
- print_item format_banner(cmd, banner: banner) if sync
1081
+ print_item format_banner(hint ? "#{cmd} (#{hint})" : cmd, banner: banner) if sync
1021
1082
  if var != false && (pre = runenv)
1022
1083
  case pre
1023
1084
  when Hash
@@ -1226,12 +1287,12 @@ module Squared
1226
1287
  end
1227
1288
 
1228
1289
  def session(*cmd, prefix: cmd.first, main: true, path: true, options: true)
1229
- prefix = stripext(prefix.to_s).upcase
1230
- if path && (val = ENV["PATH_#{prefix}"] || PATH[prefix] || PATH[prefix.to_sym])
1290
+ prefix = stripext prefix.to_s
1291
+ if path && (val = shell_bin(prefix))
1231
1292
  cmd[0] = shell_quote(val, force: false)
1232
1293
  end
1233
1294
  ret = JoinSet.new(cmd.flatten(1))
1234
- if options && (val = env("#{prefix}_OPTIONS"))
1295
+ if options && (val = env("#{prefix.upcase}_OPTIONS"))
1235
1296
  split_escape(val).each { |opt| ret.last(fill_option(opt), /\A(--?[^ =]+)[ =].+\z/m) }
1236
1297
  end
1237
1298
  main ? @session = ret : ret
@@ -1256,7 +1317,7 @@ module Squared
1256
1317
  def session_done(cmd)
1257
1318
  return cmd unless cmd.respond_to?(:done)
1258
1319
 
1259
- raise_error('no args added', hint: cmd.first || name) unless cmd.size > 1
1320
+ raise_error('no args added', hint: cmd.first) unless cmd.size > 1
1260
1321
  @session = nil if cmd == @session
1261
1322
  cmd.done
1262
1323
  end
@@ -1410,9 +1471,9 @@ module Squared
1410
1471
  unless items.empty?
1411
1472
  pad = items.size.to_s.size
1412
1473
  items.each_with_index do |val, i|
1413
- next unless reg.empty? || reg.any? { |pat| val[0].match?(pat) }
1474
+ next unless matchany?(val.first, reg)
1414
1475
 
1415
- out << ('%*d. %s' % [pad, i.succ, each ? each.call(val) : val[0]])
1476
+ out << ('%*d. %s' % [pad, i.succ, each ? each.call(val) : val.first])
1416
1477
  end
1417
1478
  end
1418
1479
  sub = [headerstyle]
@@ -1513,11 +1574,11 @@ module Squared
1513
1574
  list.flatten.each do |opt|
1514
1575
  next unless (val = option(opt, **kwargs))
1515
1576
 
1516
- return target << (if flag
1517
- shell_option(opt, equals ? val : nil, quote: quote, escape: escape, force: force)
1518
- else
1519
- shell_quote val
1520
- end)
1577
+ return target << if flag
1578
+ shell_option(opt, equals ? val : nil, quote: quote, escape: escape, force: force)
1579
+ else
1580
+ shell_quote val
1581
+ end
1521
1582
  end
1522
1583
  nil
1523
1584
  end
@@ -1726,6 +1787,17 @@ module Squared
1726
1787
  files.map { |val| val == '.' ? '.' : shell_quote(path + val) }
1727
1788
  end
1728
1789
 
1790
+ def matchmap(list, prefix = nil)
1791
+ list.map do |val|
1792
+ if val.is_a?(Regexp)
1793
+ val
1794
+ else
1795
+ val = ".*#{val}" if prefix && !val.sub!(/\A(\^|\\A)/, '')
1796
+ Regexp.new("#{prefix}#{val == '*' ? '.+' : val}")
1797
+ end
1798
+ end
1799
+ end
1800
+
1729
1801
  def semver(val)
1730
1802
  return val if val[3]
1731
1803
 
@@ -1743,12 +1815,20 @@ module Squared
1743
1815
  end
1744
1816
 
1745
1817
  def semcmp(val, other)
1746
- a, b = [val, other].map! { |ver| ver.match(SEM_VER) }
1747
- return 1 unless a
1748
- return -1 unless b
1749
- return 0 if a[0] == b[0]
1818
+ return 0 if val == other
1819
+
1820
+ a, b = [val, other].map! { |ver| ver.scan(SEM_VER) }
1821
+ return -1 if b.empty?
1822
+ return 1 if a.empty?
1750
1823
 
1751
- a, b = [a, b].map! { |c| [c[1], c[3], c[5] || '0'] }
1824
+ a, b = [a.first, b.first].map! do |c|
1825
+ begin
1826
+ d = Integer(c[5]).to_s
1827
+ rescue StandardError
1828
+ d = c[5] ? '-1' : '0'
1829
+ end
1830
+ [c[0], c[2], c[4] || '0', d]
1831
+ end
1752
1832
  a.each_with_index do |c, index|
1753
1833
  next if c == (d = b[index])
1754
1834
 
@@ -1757,6 +1837,10 @@ module Squared
1757
1837
  0
1758
1838
  end
1759
1839
 
1840
+ def semgte?(val, other)
1841
+ semcmp(val, other) != 1
1842
+ end
1843
+
1760
1844
  def indexitem(val)
1761
1845
  [$1.to_i, $2 && $2[1..-1]] if val =~ /\A[=^#{indexchar}](\d+)(:.+)?\z/
1762
1846
  end
@@ -1800,7 +1884,7 @@ module Squared
1800
1884
  def on(event, from, *args, **kwargs)
1801
1885
  return unless from && @events.key?(event)
1802
1886
 
1803
- @events[event][from]&.each do |obj|
1887
+ Array(@events[event][from]).each do |obj|
1804
1888
  target, opts = if obj.is_a?(Array) && obj[1].is_a?(Hash)
1805
1889
  [obj[0], kwargs.empty? ? obj[1] : obj[1].merge(kwargs)]
1806
1890
  else
@@ -1826,25 +1910,22 @@ module Squared
1826
1910
  print_error(err, pass: pass) unless ret
1827
1911
  end
1828
1912
 
1829
- def pwd_set(pass: false, from: nil)
1830
- pass = semscan(pass).join <= RUBY_VERSION if pass.is_a?(String)
1913
+ def pwd_set(pass: false, dryrun: false, from: nil)
1831
1914
  pwd = Dir.pwd
1832
- if (path.to_s == pwd || pass == true) && (workspace.mri? || !workspace.windows?)
1833
- ret = yield
1834
- else
1835
- Dir.chdir(path)
1836
- ret = yield
1837
- Dir.chdir(pwd)
1838
- end
1915
+ return yield if (path.to_s == pwd || pass == true) && (workspace.mri? || !workspace.windows?)
1916
+
1917
+ Dir.chdir path
1918
+ ret = yield
1919
+ Dir.chdir pwd
1839
1920
  rescue StandardError => e
1840
- on_error e, from
1921
+ on_error(e, from, dryrun: dryrun)
1841
1922
  else
1842
1923
  ret
1843
1924
  end
1844
1925
 
1845
1926
  def run_set(cmd, val = nil, opts: nil, **)
1846
- diso = @output[1] == false && !@output[0].nil?
1847
- dise = @output[2] == false
1927
+ noopt = @output[1] == false && !@output[0].nil?
1928
+ noenv = @output[2] == false
1848
1929
  parse = lambda do |data|
1849
1930
  ret = []
1850
1931
  if data[:command]
@@ -1864,8 +1945,8 @@ module Squared
1864
1945
  case cmd
1865
1946
  when Array
1866
1947
  @output = if cmd.all? { |data| data.is_a?(Hash) }
1867
- diso = false
1868
- dise = false
1948
+ noopt = false
1949
+ noenv = false
1869
1950
  cmd.map { |data| parse.call(data) }
1870
1951
  else
1871
1952
  cmd.dup
@@ -1876,14 +1957,14 @@ module Squared
1876
1957
  else
1877
1958
  @output[0] = cmd
1878
1959
  end
1879
- unless diso
1960
+ unless noopt
1880
1961
  if opts == false
1881
1962
  @output[1] = false
1882
1963
  elsif opts && opts != true
1883
1964
  @output[1] = opts
1884
1965
  end
1885
1966
  end
1886
- return if dise
1967
+ return if noenv
1887
1968
 
1888
1969
  if val.is_a?(Hash)
1889
1970
  @output[2] = val
@@ -1939,6 +2020,13 @@ module Squared
1939
2020
  end
1940
2021
  end
1941
2022
 
2023
+ def asdf_set(val)
2024
+ @asdf = if @@asdf && val
2025
+ dir = @@asdf[0].join('installs', val)
2026
+ [val, dir] if dir.exist? && !dir.empty?
2027
+ end
2028
+ end
2029
+
1942
2030
  def theme_set(common)
1943
2031
  @theme = if !verbose
1944
2032
  {}
@@ -1986,6 +2074,10 @@ module Squared
1986
2074
  @only ? !@only.include?(key) : @pass.include?(key)
1987
2075
  end
1988
2076
 
2077
+ def matchany?(val, list, empty: true)
2078
+ list.empty? ? empty : list.any? { |pat| val.match?(pat) }
2079
+ end
2080
+
1989
2081
  def projectpath?(val)
1990
2082
  Pathname.new(val).cleanpath.yield_self do |file|
1991
2083
  file.absolute? ? file.to_s.start_with?(File.join(path, '')) : !file.to_s.start_with?(File.join('..', ''))
@@ -55,15 +55,15 @@ module Squared
55
55
  commit: %w[a|author=q c|change=q m|message=q pause=b?].freeze,
56
56
  inspect: %w[s|size f|format=q].freeze,
57
57
  start: %w[a|attach i|interactive detach-keys=q].freeze,
58
- stop: %w[s|signal=b t|time=i].freeze,
59
- restart: %w[s|signal=b t|time=i].freeze,
58
+ stop: %w[s|signal=b t|time=i t|timeout=i].freeze,
59
+ restart: %w[s|signal=b t|time=i t|timeout=i].freeze,
60
60
  kill: %w[s|signal=b].freeze,
61
61
  stats: %w[no-trunc format|q].freeze
62
62
  }.freeze,
63
63
  image: {
64
64
  list: %w[a|all digests no-trunc f|filter=q format=q].freeze,
65
65
  push: %w[a|all-tags disable-content-trust=b? platform=b q|quiet].freeze,
66
- rm: %w[f|force no-prune].freeze,
66
+ rm: %w[f|force no-prune platform=b].freeze,
67
67
  save: %w[o|output=p platform=b].freeze
68
68
  }.freeze,
69
69
  network: {
@@ -73,8 +73,11 @@ module Squared
73
73
  }.freeze
74
74
  VAL_DOCKER = {
75
75
  run: {
76
- bind: %w[type source src destination dst target readonly ro bind-propagation].freeze,
77
- tmpfs: %w[type destination dst target tmpfs-size tmpfs-mode].freeze
76
+ common: %w[source src destination dst target readonly ro].freeze,
77
+ bind: %w[bind-propagation].freeze,
78
+ volume: %w[volume-subpath volume-nocopy volume-opt].freeze,
79
+ tmpfs: %w[tmpfs-size tmpfs-mode].freeze,
80
+ image: %w[image-path].freeze
78
81
  }.freeze
79
82
  }.freeze
80
83
  private_constant :COMPOSEFILE, :BAKEFILE, :OPT_DOCKER, :VAL_DOCKER
@@ -92,7 +95,7 @@ module Squared
92
95
  end
93
96
 
94
97
  subtasks({
95
- 'build' => %i[tag context bake].freeze,
98
+ 'build' => %i[tag context].freeze,
96
99
  'compose' => %i[build run exec up].freeze,
97
100
  'bake' => %i[build check].freeze,
98
101
  'image' => %i[list rm push tag save].freeze,
@@ -125,7 +128,7 @@ module Squared
125
128
 
126
129
  def populate(*, **)
127
130
  super
128
- return unless ref?(Docker.ref)
131
+ return unless ref?(Docker.ref) || @only
129
132
 
130
133
  namespace name do
131
134
  Docker.subtasks do |action, flags|
@@ -134,7 +137,7 @@ module Squared
134
137
  namespace action do
135
138
  flags.each do |flag|
136
139
  case action
137
- when 'build', 'bake'
140
+ when 'build'
138
141
  case flag
139
142
  when :tag, :context
140
143
  format_desc(action, flag, 'opts*', before: flag == :tag ? 'name' : 'dir')
@@ -142,9 +145,12 @@ module Squared
142
145
  param = param_guard(action, flag, args: args, key: flag)
143
146
  buildx(:build, args.extras, "#{flag}": param)
144
147
  end
145
- when :bake, :build
146
- next unless bake?
148
+ end
149
+ when 'bake'
150
+ break unless bake?
147
151
 
152
+ case flag
153
+ when :build
148
154
  format_desc action, flag, ':?,opts*,target*,context?'
149
155
  task flag do |_, args|
150
156
  args = args.to_a
@@ -155,8 +161,6 @@ module Squared
155
161
  end
156
162
  end
157
163
  when :check
158
- next unless bake?
159
-
160
164
  format_desc action, flag, 'target'
161
165
  task flag, [:target] do |_, args|
162
166
  target = param_guard(action, flag, args: args, key: :target)
@@ -164,6 +168,8 @@ module Squared
164
168
  end
165
169
  end
166
170
  when 'compose'
171
+ break unless compose?
172
+
167
173
  case flag
168
174
  when :build, :up
169
175
  format_desc action, flag, 'opts*,service*'
@@ -348,7 +354,7 @@ module Squared
348
354
  when :build, :up
349
355
  op.append(escape: true)
350
356
  when :exec, :run
351
- append_command(flag, service, op.extras, from: from)
357
+ append_command flag, service, op.extras
352
358
  end
353
359
  run(from: from)
354
360
  end
@@ -365,44 +371,54 @@ module Squared
365
371
  when :run, :create, :exec
366
372
  if rc && !op.arg?('mount')
367
373
  run = VAL_DOCKER[:run]
368
- both = run[:bind] + run[:tmpfs]
369
- diff = run[:bind].reject { |val| run[:tmpfs].include?(val) }
370
- delim = Regexp.new(",\\s*(?=#{both.join('|')})")
374
+ all = collect_hash VAL_DOCKER[:run]
375
+ delim = Regexp.new(",\\s*(?=#{all.join('|')})")
371
376
  Array(@mounts).each do |val|
372
377
  args = []
373
- tmpfs = true
378
+ type = nil
374
379
  val.split(delim).each do |opt|
375
380
  k, v, q = split_option opt
376
- next unless both.include?(k)
377
-
378
381
  if k == 'type'
379
- tmpfs = false if v == 'bind'
380
- next
381
- elsif diff.include?(k)
382
- tmpfs = false
383
- end
384
- case k
385
- when 'readonly', 'ro'
386
- args << k
387
- next
388
- when 'source', 'src', 'destination', 'dst', 'target'
389
- v = path + v
390
- v = shell_quote(v, option: false, force: false) if q == ''
391
- tmpfs = false if k[0] == 's'
382
+ case v
383
+ when 'bind', 'volume', 'image', 'tmpfs'
384
+ type = v
385
+ else
386
+ raise_error("unknown type: #{v}", hint: flag)
387
+ end
388
+ elsif all.include?(k)
389
+ unless type
390
+ run.each_pair do |key, val|
391
+ if val.include?(k)
392
+ type = key.to_s unless key == :common
393
+ break
394
+ end
395
+ end
396
+ end
397
+ case k
398
+ when 'readonly', 'ro'
399
+ args << k
400
+ next
401
+ when 'source', 'src', 'destination', 'dst', 'target', 'volume-subpath', 'image-path'
402
+ v = path + v
403
+ v = shell_quote(v, option: false, force: false) if q == ''
404
+ end
405
+ args << "#{k}=#{q + v + q}"
406
+ elsif verbose
407
+ log_message(Logger::INFO, 'unrecognized option', subject: from, hint: k)
392
408
  end
393
- args << "#{k}=#{q + v + q}"
394
409
  end
395
- cmd << "--mount type=#{tmpfs ? 'tmpfs' : 'bind'},#{args.join(',')}"
410
+ raise_error('missing type', hint: flag) unless type
411
+ cmd << "--mount type=#{type},#{args.join(',')}"
396
412
  end
397
413
  end
398
- append_command(flag, id || tagmain, op.extras, from: from)
414
+ append_command(flag, id || tagmain, op.extras)
399
415
  when :update
400
- raise_error('missing container', hint: from) if op.empty?
416
+ raise_error('missing container', hint: flag) if op.empty?
401
417
  op.append(escape: true)
402
418
  when :commit
403
419
  latest = op.shift || tagmain
404
420
  cmd << id << latest
405
- raise_error("unknown args: #{op.join(', ')}", hint: from) unless op.empty?
421
+ raise_error("unknown args: #{op.join(', ')}", hint: flag) unless op.empty?
406
422
  return unless confirm_command(cmd.to_s, title: from, target: id, as: latest)
407
423
 
408
424
  registry = option('registry') || @registry
@@ -445,7 +461,7 @@ module Squared
445
461
  when :rm
446
462
  status = %w[created exited dead]
447
463
  end
448
- ps = docker_output('ps -a', *status.map { |s| "--filter=\"status=#{s}\"" })
464
+ ps = docker_output('ps -a', *status.map { |s| quote_option('filter', "status=#{s}") })
449
465
  list_image(flag, ps, no: no, hint: "status: #{status.join(', ')}", from: from) do |img|
450
466
  run(cmd.temp(img), from: from)
451
467
  end
@@ -509,8 +525,8 @@ module Squared
509
525
  when :push
510
526
  id ||= option('tag', ignore: false) || tagmain
511
527
  registry ||= op.shift || option('registry') || @registry
512
- raise_error(id ? "unknown args: #{op.join(', ')}" : 'no id/tag given', hint: from) unless id && op.empty?
513
- raise_error('username/registry not provided', hint: from) unless registry
528
+ raise_error(id ? "unknown args: #{op.join(', ')}" : 'no id/tag given', hint: flag) unless id && op.empty?
529
+ raise_error('username/registry not provided', hint: flag) unless registry
514
530
  registry.chomp!('/')
515
531
  uri = shell_quote "#{registry}/#{id}"
516
532
  op << uri
@@ -544,6 +560,14 @@ module Squared
544
560
  super || dockerfile.exist?
545
561
  end
546
562
 
563
+ def compose?(file = dockerfile)
564
+ COMPOSEFILE.include?(File.basename(file))
565
+ end
566
+
567
+ def bake?(file = dockerfile)
568
+ BAKEFILE.include?(File.basename(file))
569
+ end
570
+
547
571
  def dockerfile(val = nil)
548
572
  if val == 'Dockerfile'
549
573
  @file = false
@@ -573,7 +597,7 @@ module Squared
573
597
  session('docker', *cmd, main: false, options: false, **kwargs)
574
598
  end
575
599
 
576
- def append_command(flag, val, list, target: @session, from: nil)
600
+ def append_command(flag, val, list, target: @session)
577
601
  if list.delete(':')
578
602
  list << readline('Enter command [args]', force: true)
579
603
  elsif (args = env('DOCKER_ARGS'))
@@ -585,7 +609,7 @@ module Squared
585
609
  target << basic_option('name', dnsname("#{name}_%s" % rand_s(6)))
586
610
  end
587
611
  when :exec
588
- raise_error('no command args', hint: from) if list.empty?
612
+ raise_error('no command args', hint: flag) if list.empty?
589
613
  end
590
614
  target << val << list.shift
591
615
  target << list.join(' && ') unless list.empty?
@@ -633,7 +657,7 @@ module Squared
633
657
  index = 0
634
658
  all = option('all', prefix: 'docker')
635
659
  y = from == :'image:rm' && option('y', prefix: 'docker')
636
- pat = /^(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})(?:[_.,:-]|$)/
660
+ pat = /\b(?:#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})\b/
637
661
  IO.popen(session_done(cmd << '--format=json')).each do |line|
638
662
  data = JSON.parse(line)
639
663
  id = data['ID']
@@ -681,7 +705,7 @@ module Squared
681
705
  end
682
706
  yield id
683
707
  end
684
- puts log_message(Logger::INFO, 'none detected', subject: "#{name}:#{from}", hint: hint) if found || y
708
+ puts log_message(Logger::INFO, 'none detected', subject: name, hint: hint || from) if !found && !y
685
709
  end
686
710
  rescue StandardError => e
687
711
  on_error e, from
@@ -801,14 +825,6 @@ module Squared
801
825
  def tagmain
802
826
  tag.is_a?(Array) ? tag.first : tag
803
827
  end
804
-
805
- def compose?(file = dockerfile)
806
- COMPOSEFILE.include?(File.basename(file))
807
- end
808
-
809
- def bake?(file = dockerfile)
810
- BAKEFILE.include?(File.basename(file))
811
- end
812
828
  end
813
829
 
814
830
  Application.implement Docker