squared 0.4.20 → 0.4.22

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1b0859a60110d19550ba8436a184dbf5475d9103cc844d4bcab7850f2065dc5
4
- data.tar.gz: 887a31b94a66e59b0981f6dcbe64544e1f721b07cb5d82d9a71b8bbbc209820e
3
+ metadata.gz: 4f67ab37dd0b66feaeb78631ac257ba860df78acba313f2e5fe2ffeb01136acf
4
+ data.tar.gz: 8d0570c44cbdf41ba282b5c2fd9a0196b4c5678d595ca5774393b442b88eb854
5
5
  SHA512:
6
- metadata.gz: 5936f90594961c71af2f1420607ed9c739bd0f182a440aff4c2d474a8bcc9bbb3e0db1c2bfa6ba27052823414d2f6db981f4251a32c09769595b89a561ecfc84
7
- data.tar.gz: 19cc6e69dda54b8d0a3f2cb43606bfb23e25f1f20c071b8e47421156af30d5763162f4a5b14df5f8787a465e53bbabf18b0a9943e7a3c809c31a9825e885e32a
6
+ metadata.gz: 01b00bf5afdd80a370ef363c0d546f76d8f2533474b25029fc37c9bb0bfb1b2104ea4aa78c38cb044cf8d2f194630496b6d1b48ad4d94e8be284b28dd5dfa03c
7
+ data.tar.gz: 3968c3a15796f1c41939b95b4e50c8a8830f7f95fb6570a193c24c0043e259c82c6ac28571bd4cdbcddd2b77d6b47f38b55a963c3e567bad6e8e949a41ba8698
data/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.22] - 2025-10-08
4
+
5
+ ### Added
6
+
7
+ - Node package managers support ENV platform options.
8
+
9
+ ### Changed
10
+
11
+ - User installed Ruby is detected before system installed Ruby.
12
+
13
+ ### Fixed
14
+
15
+ - Yarn classic package installs did not recognize dedupe flag.
16
+ - Node command outdated option prune called undefined method.
17
+ - OptionPartition method exist? called undefined method.
18
+ - Ruby method copy? did not perform Hash property override check.
19
+ - OptionPartition static method arg? did not detect single values.
20
+
21
+ ## [0.4.21] - 2025-10-01
22
+
23
+ ### Added
24
+
25
+ - Project base method variable_set was aliased to the name apply.
26
+
27
+ ### Changed
28
+
29
+ - Project base method run visibility was changed to public.
30
+ - OptionPartition method uniq! returns self or nil.
31
+
32
+ ### Fixed
33
+
34
+ - Docker attribute file did not search for nearest config.
35
+ - Project task run did not accept Proc or Method definitions.
36
+ - Gem command options were revalidated to 3.7.2.
37
+ - Bundler command options were revalidated to 2.7.2.
38
+ - Ruby class method bundle did not pass through commands.
39
+ - Ruby task ruby did not separate options and arguments.
40
+ - Pip commands uninstall and freeze did not filter options.
41
+ - Ruby command gem action update did not append packages.
42
+ - OptionPartition did not detect short options with a merged value.
43
+ - Gem commands option version did not use quotes.
44
+ - Git command pull action all used undefined delete_prefix! method.
45
+ - OptionPartition did not delete added values from extras.
46
+ - Python editable projects can override requirements detection.
47
+ - Project session method did delete short options with a merged value.
48
+ - Gem command install did not try to resolve local paths.
49
+ - Ruby commands did not always check for file target exists.
50
+
3
51
  ## [0.4.20] - 2025-09-14
4
52
 
5
53
  ### Changed
@@ -962,6 +1010,8 @@
962
1010
 
963
1011
  - Changelog was created.
964
1012
 
1013
+ [0.4.22]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.22
1014
+ [0.4.21]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.21
965
1015
  [0.4.20]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.20
966
1016
  [0.4.19]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.19
967
1017
  [0.4.18]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.18
data/README.md CHANGED
@@ -105,9 +105,9 @@ Workspace::Application
105
105
  revbuild(include: %w[src/ framework/ types/]) # Synchronous is recommended
106
106
  end
107
107
  .add("squared/sqd", exclude: :git, pass: [:node, "checkout", "bump"]) do # Skip initialize(:node) + squared:checkout:* + squared:bump:*
108
- variable_set :script, "build:sqd" # Override detection
109
- variable_set :depend, false
110
- variable_set :clean, ["build/sqd/"]
108
+ apply :script, "build:sqd" # Override detection
109
+ apply :depend, false #
110
+ apply :clean, ["build/sqd/"] # variable_set (alias)
111
111
  end
112
112
  .with(:docker, only: ["build", "compose"]) do
113
113
  .add("squared", "docker", file: "Dockerfile", context: ".", tag: "latest", registry: "localhost:5000", username: "squared",
@@ -303,7 +303,7 @@ Workspace::Application
303
303
  doc(windows? ? ".\make.bat html" : "make html") # rake android-docs:doc | rake doc:python
304
304
  add("android-docs", "android", venv: "/home/user/.venv") # rake android-docs:depend
305
305
  add("chrome-docs", "chrome", graph: "android", venv: %w[.venv --clear]) do # /workspaces/chrome-docs/.venv
306
- variable_set :dependindex, 1 # Use Poetry for dependencies (optional)
306
+ apply :dependindex, 1 # Use Poetry for dependencies (optional)
307
307
  end
308
308
  end
309
309
  .with(:node) do
@@ -495,22 +495,23 @@ Most project classes will inherit from `Git` which enables these tasks:
495
495
 
496
496
  | Task | Git | Command |
497
497
  | :--------- | :--------------- | :-------------------------------------------- |
498
- | branch | branch | create set delete move copy list edit current |
498
+ | branch | branch | create track delete move copy list current |
499
499
  | checkout | checkout | commit branch track detach path |
500
500
  | commit | commit | add all amend amend-orig fixup |
501
- | diff | diff | head cached branch files between contain |
501
+ | diff | diff | head branch files view between contain |
502
502
  | fetch | fetch | origin remote all |
503
503
  | files | ls-files | cached modified deleted others |
504
- | git | | add blame clean mv rm revert status |
504
+ | git | | add blame clean mv revert rm status |
505
+ | log | log | view between contain |
505
506
  | merge | merge | commit no-commit send |
506
507
  | pull | pull | origin remote all |
507
508
  | rebase | rebase | branch onto send |
508
509
  | refs | ls-remote --refs | heads tags remote |
509
- | reset | reset | commit index patch mode |
510
- | restore | restore | staged worktree |
511
- | rev | rev | commit output |
512
- | show | show | format oneline |
513
- | stash | stash | push pop apply branch drop clear list all |
510
+ | reset | reset | commit index patch mode undo |
511
+ | restore | restore | source staged worktree |
512
+ | rev | rev | commit build output |
513
+ | show | show | format oneline textconv |
514
+ | stash | stash | push pop apply branch drop clear list |
514
515
  | submodule | submodule | status update branch url sync |
515
516
  | switch | switch | branch create detach |
516
517
  | tag | tag | add sign delete list |
@@ -597,6 +598,9 @@ BUILD_${NAME}_VERSION=0.1.0 # publish + detection
597
598
  BANNER=0 # hide banner
598
599
  BANNER_${NAME}=0 #
599
600
 
601
+ VERBOSE=0 # console output level
602
+ VERBOSE_${NAME}=0 # 0,1,2,n
603
+
600
604
  REVBUILD_FORCE=1 # Rebuild all targets
601
605
  REVBUILD_FORCE_${NAME}=1 # Rebuild project
602
606
 
@@ -639,7 +643,7 @@ GIT_AUTOSTASH_${NAME}=0 # rebase (project only)
639
643
  | :--------- | :---------------- | :-------------------------------------------------------------------- |
640
644
  | branch | create | TRACK=0,1,s F|FORCE |
641
645
  | branch | move copy | F|FORCE |
642
- | branch | set delete | COUNT=n |
646
+ | branch | delete | COUNT=n |
643
647
  | branch | global | SYNC |
644
648
  | checkout | branch | DETACH TRACK=s COUNT=n |
645
649
  | checkout | detach | REFLOG=1 |
@@ -189,7 +189,7 @@ module Squared
189
189
  emphasize(args, title: title + (subject ? " #{subject}" : ''), sub: sub, pipe: -1)
190
190
  else
191
191
  msg = [log_title(level, color: color)]
192
- msg << (color ? sub_style(subject, styles: (@theme && @theme[:subject]) || :bold) : subject) if subject
192
+ msg << (color ? sub_style(subject.to_s, styles: (@theme && @theme[:subject]) || :bold) : subject) if subject
193
193
  msg << args.shift if msg.size == 1
194
194
  message(msg.join(' '), *args, hint: hint)
195
195
  end
@@ -223,12 +223,8 @@ module Squared
223
223
  def emphasize(val, title: nil, footer: nil, right: false, cols: nil, sub: nil, pipe: nil,
224
224
  border: @theme && @theme[:border])
225
225
  n = 0
226
- max = ->(v) { n = [n, v.max_by(&:size).size].max }
227
- set = lambda do |v|
228
- ret = as_a(v, :to_s)
229
- max.call(ret)
230
- ret
231
- end
226
+ max = ->(a) { n = [n, a.max_by(&:size).size].max }
227
+ set = ->(s) { Array(s).map(&:to_s).tap { |a| max.call(a) } }
232
228
  title &&= set.call(title)
233
229
  footer &&= set.call(footer)
234
230
  if val.is_a?(::Array)
@@ -213,7 +213,7 @@ module Squared
213
213
  ext[0] = mime
214
214
  elsif file
215
215
  keys.unshift(file)
216
- alt = basepath("#{main}.{#{ext.join(',')}}")
216
+ alt = basepath "#{main}.{#{ext.join(',')}}"
217
217
  file = Dir[alt].first
218
218
  else
219
219
  alt = main
@@ -346,8 +346,8 @@ module Squared
346
346
  basepath(file = main + @ext).to_s rescue file
347
347
  end
348
348
 
349
- def basepath(file)
350
- project ? project.basepath(file) : Pathname.new(file).realdirpath
349
+ def basepath(*args)
350
+ project ? project.basepath(*args) : Pathname.pwd.join(*args)
351
351
  end
352
352
  end
353
353
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.4.20'
4
+ VERSION = '0.4.22'
5
5
  end
@@ -629,7 +629,9 @@ module Squared
629
629
  end
630
630
 
631
631
  def home?
632
- !(proj = find(home)).nil? && proj.enabled?
632
+ return false unless (proj = find(home))
633
+
634
+ proj.enabled?
633
635
  end
634
636
 
635
637
  def windows?
@@ -9,6 +9,7 @@ module Squared
9
9
  module Workspace
10
10
  module Project
11
11
  class Base
12
+ include Comparable
12
13
  include Common::Format
13
14
  include System
14
15
  include Shell
@@ -16,7 +17,6 @@ module Squared
16
17
  include Utils
17
18
  include Support
18
19
  include Rake::DSL
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
22
  pass only exclude].freeze
@@ -83,6 +83,7 @@ module Squared
83
83
  @name = name.to_s.freeze
84
84
  @project = @path.basename.to_s.freeze
85
85
  @group = group&.to_s.freeze
86
+ @envname = env_key(@name).freeze
86
87
  @depend = kwargs[:depend]
87
88
  @doc = kwargs[:doc]
88
89
  @lint = kwargs[:lint]
@@ -99,7 +100,6 @@ module Squared
99
100
  @children = []
100
101
  @events = hashobj.update({ first: first, last: last, error: error })
101
102
  @as = hashobj
102
- @envname = env_key(@name).freeze
103
103
  @desc = (@name.include?(':') ? @name.split(':').join(ARG[:SPACE]) : @name).freeze
104
104
  @parent = nil
105
105
  @global = false
@@ -196,7 +196,7 @@ module Squared
196
196
  file &&= @workspace.home.join(env('LOG_DIR', ''), file).realdirpath
197
197
  rescue StandardError => e
198
198
  file = nil
199
- warn log_message(Logger::WARN, e) if warning?
199
+ print_error e
200
200
  end
201
201
  log[:progname] ||= @name
202
202
  if (val = env('LOG_LEVEL', ignore: false))
@@ -288,7 +288,7 @@ module Squared
288
288
  end
289
289
 
290
290
  def verbose=(val)
291
- @verbose = case val
291
+ @verbose = case (val = env('VERBOSE', val))
292
292
  when NilClass
293
293
  workspace.verbose
294
294
  when String
@@ -363,7 +363,7 @@ module Squared
363
363
  else
364
364
  force = args.fetch(:force, false)
365
365
  end
366
- unpack(path + dir, uri: tag, digest: digest, ext: ext, force: force)
366
+ unpack(basepath(dir), uri: tag, digest: digest, ext: ext, force: force)
367
367
  end
368
368
  end
369
369
  end
@@ -411,7 +411,6 @@ module Squared
411
411
  kwargs[:group] = group unless kwargs.key?(:group)
412
412
  kwargs[:ref] = ref unless kwargs.key?(:ref)
413
413
  parent = self
414
- proj = nil
415
414
  name = case name
416
415
  when String, Symbol
417
416
  name.to_s
@@ -420,10 +419,9 @@ module Squared
420
419
  end
421
420
  workspace.add(path, name, **kwargs) do
422
421
  __send__ :parent_set, parent
423
- proj = self
422
+ @children << self
423
+ instance_eval(&blk) if block_given?
424
424
  end
425
- @children << proj
426
- proj.instance_eval(&blk) if block_given?
427
425
  self
428
426
  end
429
427
 
@@ -437,7 +435,7 @@ module Squared
437
435
 
438
436
  out = obj.link(self, *args, **kwargs, &blk) if obj.respond_to?(:link)
439
437
  if !out
440
- warn log_message(Logger::WARN, 'link not compatible', subject: obj.to_s, hint: name)
438
+ print_error('link not compatible', subject: obj, hint: name)
441
439
  elsif out.respond_to?(:build)
442
440
  out.build
443
441
  end
@@ -485,6 +483,10 @@ module Squared
485
483
  else
486
484
  cmd, opts, var, flags, extra = args
487
485
  end
486
+ if cmd.is_a?(Proc) || cmd.is_a?(Method)
487
+ run_b(cmd, sync: sync, from: from)
488
+ return
489
+ end
488
490
  if cmd
489
491
  cmd = as_get(cmd, from)
490
492
  opts = compose(opts, script: false) if opts && respond_to?(:compose)
@@ -528,7 +530,7 @@ module Squared
528
530
  on_error(:prereqs, e, exception: true)
529
531
  end
530
532
  end
531
- warn log_message(Logger::WARN, name, 'method not found', subject: 'prereqs', hint: meth)
533
+ print_error(name, 'method not found', subject: 'prereqs', hint: meth)
532
534
  end
533
535
  elsif proj.build?
534
536
  proj.build(sync: sync)
@@ -583,7 +585,7 @@ module Squared
583
585
  else
584
586
  if @clean.is_a?(Enumerable) && !series?(@clean)
585
587
  @clean.each do |val|
586
- entry = path + (val = val.to_s)
588
+ entry = basepath(val = val.to_s)
587
589
  if entry.directory? && val.match?(%r{[\\/]\z})
588
590
  log&.warn "rm -rf #{entry}"
589
591
  rm_rf(entry, verbose: verbose)
@@ -716,7 +718,7 @@ module Squared
716
718
  delete = true
717
719
  end
718
720
  if create
719
- warn log_message(Logger::WARN, 'force remove', subject: name, hint: target)
721
+ print_error('force remove', subject: name, hint: target)
720
722
  target.rmtree
721
723
  target.mkpath
722
724
  end
@@ -807,6 +809,56 @@ module Squared
807
809
  self
808
810
  end
809
811
 
812
+ def run(cmd = @session, var = nil, exception: self.exception, sync: true, from: nil, banner: true, chdir: path,
813
+ interactive: nil, hint: nil, **)
814
+ unless cmd
815
+ print_error('no command given', subject: project, hint: from || 'unknown', pass: true)
816
+ return
817
+ end
818
+ cmd = cmd.target if cmd.is_a?(OptionPartition)
819
+ if interactive && (!@session || !option('y'))
820
+ title, y = case interactive
821
+ when Array
822
+ interactive
823
+ when String
824
+ [interactive, 'N']
825
+ else
826
+ ['Run', 'Y']
827
+ end
828
+ yn = y == 'Y' ? 'Y/n' : 'y/N'
829
+ exit 1 unless confirm("#{title}? [#{sub_style(cmd.to_s, styles: theme[:inline])}] [#{yn}] ", y)
830
+ end
831
+ cmd = session_done cmd
832
+ log&.info cmd
833
+ on :first, from
834
+ begin
835
+ if cmd.match?(/\A[^:]+:[^:]/) && workspace.task_defined?(cmd)
836
+ log&.warn "ENV discarded: #{var}" if var
837
+ task_invoke(cmd, exception: exception, warning: warning?)
838
+ else
839
+ print_item format_banner(hint ? "#{cmd} (#{hint})" : cmd, banner: banner) if sync
840
+ if var != false && (pre = runenv)
841
+ case pre
842
+ when Hash
843
+ var = var.is_a?(Hash) ? pre.merge(var) : pre
844
+ when Enumerable
845
+ cmd = command(*pre.to_a, cmd)
846
+ else
847
+ cmd = command(pre, cmd)
848
+ end
849
+ end
850
+ args = var.is_a?(Hash) ? [var, cmd] : [cmd]
851
+ ret = shell(*args, chdir: chdir, exception: exception)
852
+ end
853
+ rescue StandardError => e
854
+ on_error(from, e, exception: true)
855
+ false
856
+ else
857
+ on :last, from
858
+ ret
859
+ end
860
+ end
861
+
810
862
  def variable_set(key, *args, **kwargs, &blk)
811
863
  if variables.include?(key) || blocks.include?(key)
812
864
  val = case args.size
@@ -856,6 +908,8 @@ module Squared
856
908
  self
857
909
  end
858
910
 
911
+ alias apply variable_set
912
+
859
913
  def enabled?(ref = nil, **)
860
914
  return false if ref && !ref?(ref)
861
915
 
@@ -966,7 +1020,7 @@ module Squared
966
1020
  path.parent.ascend.each do |dir|
967
1021
  target = dir.join(*args)
968
1022
  return target if target.exist?
969
- break if (ascend.is_a?(String) && dir.join(ascend).exist?) || workspace.root == dir || parent&.path == dir
1023
+ break if (ascend && dir.join(ascend).exist?) || workspace.root == dir || parent&.path == dir
970
1024
  end
971
1025
  ret
972
1026
  end
@@ -993,56 +1047,6 @@ module Squared
993
1047
  log_console(*args, pipe: kwargs[:pipe] || pipe)
994
1048
  end
995
1049
 
996
- def run(cmd = @session, var = nil, exception: self.exception, sync: true, from: nil, banner: true, chdir: path,
997
- interactive: nil, hint: nil, **)
998
- unless cmd
999
- warn log_message(Logger::WARN, 'no command given', subject: project, hint: from || 'unknown', pass: true)
1000
- return
1001
- end
1002
- cmd = cmd.target if cmd.is_a?(OptionPartition)
1003
- if interactive && (!@session || !option('y'))
1004
- title, y = case interactive
1005
- when Array
1006
- interactive
1007
- when String
1008
- [interactive, 'N']
1009
- else
1010
- ['Run', 'Y']
1011
- end
1012
- yn = y == 'Y' ? 'Y/n' : 'y/N'
1013
- exit 1 unless confirm("#{title}? [#{sub_style(cmd.to_s, styles: theme[:inline])}] [#{yn}] ", y)
1014
- end
1015
- cmd = session_done cmd
1016
- log&.info cmd
1017
- on :first, from
1018
- begin
1019
- if cmd.match?(/\A[^:]+:[^:]/) && workspace.task_defined?(cmd)
1020
- log&.warn "ENV discarded: #{var}" if var
1021
- task_invoke(cmd, exception: exception, warning: warning?)
1022
- else
1023
- print_item format_banner(hint ? "#{cmd} (#{hint})" : cmd, banner: banner) if sync
1024
- if var != false && (pre = runenv)
1025
- case pre
1026
- when Hash
1027
- var = var.is_a?(Hash) ? pre.merge(var) : pre
1028
- when Enumerable
1029
- cmd = command(*pre.to_a, cmd)
1030
- else
1031
- cmd = command(pre, cmd)
1032
- end
1033
- end
1034
- args = var.is_a?(Hash) ? [var, cmd] : [cmd]
1035
- ret = shell(*args, chdir: chdir, exception: exception)
1036
- end
1037
- rescue StandardError => e
1038
- on_error(from, e, exception: true)
1039
- false
1040
- else
1041
- on :last, from
1042
- ret
1043
- end
1044
- end
1045
-
1046
1050
  def run_s(*cmd, env: nil, sync: true, from: nil, banner: verbose != false, **kwargs)
1047
1051
  on :first, from
1048
1052
  begin
@@ -1241,15 +1245,7 @@ module Squared
1241
1245
  end
1242
1246
 
1243
1247
  def session_delete(*args, target: @session)
1244
- ret = []
1245
- args.each do |val|
1246
- pat = /\A#{Regexp.escape(shell_option(val))}(?: |=|\z)/
1247
- if (key = target.find { |opt| opt.match?(pat) })
1248
- target.delete(key)
1249
- ret << key
1250
- end
1251
- end
1252
- ret
1248
+ OptionPartition.delete(target, *args)
1253
1249
  end
1254
1250
 
1255
1251
  def session_output(*cmd, **kwargs)
@@ -1295,8 +1291,8 @@ module Squared
1295
1291
  puts 'Success'
1296
1292
  end
1297
1293
 
1298
- def print_error(err, loglevel: Logger::WARN, pass: false)
1299
- warn log_message(loglevel, err, pass: pass) if warning?
1294
+ def print_error(*args, loglevel: Logger::WARN, **kwargs)
1295
+ warn log_message(loglevel, *args, **kwargs) if warning?
1300
1296
  end
1301
1297
 
1302
1298
  def print_item(*val)
@@ -1305,7 +1301,7 @@ module Squared
1305
1301
  puts val unless val.empty? || (val.size == 1 && val.first.nil?)
1306
1302
  end
1307
1303
 
1308
- def print_banner(*lines, styles: theme[:banner], border: borderstyle, client: false)
1304
+ def print_banner(*lines, client: false, styles: theme[:banner], border: borderstyle, **)
1309
1305
  pad = 0
1310
1306
  if styles
1311
1307
  if styles.any? { |s| s.to_s.end_with?('!') }
@@ -1329,14 +1325,14 @@ module Squared
1329
1325
  (lines << sub_style(ARG[:BORDER][1] * n, styles: border)).join("\n")
1330
1326
  end
1331
1327
 
1332
- def print_footer(*lines, sub: nil, reverse: false, right: false, **kwargs)
1328
+ def print_footer(*lines, sub: nil, reverse: false, right: false, border: borderstyle, **)
1333
1329
  n = Project.max_width(lines)
1334
1330
  lines.map! do |val|
1335
1331
  s = right ? val.rjust(n) : val.ljust(n)
1336
1332
  sub&.each { |h| s = sub_style(s, **h) }
1337
1333
  s
1338
1334
  end
1339
- ret = [sub_style(ARG[:BORDER][1] * n, styles: kwargs.key?(:border) ? kwargs[:border] : borderstyle), *lines]
1335
+ ret = [sub_style(ARG[:BORDER][1] * n, styles: border), *lines]
1340
1336
  ret.reverse! if reverse
1341
1337
  ret.join("\n")
1342
1338
  end
@@ -1467,7 +1463,7 @@ module Squared
1467
1463
  next if (key = key.to_s).start_with?('__')
1468
1464
 
1469
1465
  if val.nil? || extra || session_arg?(key, target: target)
1470
- session_delete(key, target: target)
1466
+ OptionPartition.delete_key(target, key)
1471
1467
  next if val.nil?
1472
1468
  end
1473
1469
  case val
@@ -1601,7 +1597,7 @@ module Squared
1601
1597
  raise_error("invalid JSON #{kind.name}", val, hint: hint) if kind && !ret.is_a?(kind)
1602
1598
  rescue StandardError => e
1603
1599
  log&.warn e
1604
- warn log_message(Logger::WARN, e, subject: name) if warning?
1600
+ print_error(e, subject: name)
1605
1601
  else
1606
1602
  ret
1607
1603
  end
@@ -1739,7 +1735,7 @@ module Squared
1739
1735
  raise_error 'pathspec not within worktree' unless pass || files.size == proj.size
1740
1736
  files = proj
1741
1737
  end
1742
- files.map { |val| val == '.' ? '.' : shell_quote(path + val) }
1738
+ files.map { |val| val == '.' ? '.' : shell_quote(basepath(val)) }
1743
1739
  end
1744
1740
 
1745
1741
  def matchmap(list, prefix = nil)
@@ -2006,7 +2002,7 @@ module Squared
2006
2002
 
2007
2003
  def dependfile_set(list)
2008
2004
  @dependindex = list.index { |file| basepath(file).exist? }.tap do |index|
2009
- @dependfile = @path + list[index || 0]
2005
+ @dependfile = basepath(list[index || 0])
2010
2006
  end
2011
2007
  end
2012
2008
 
@@ -6,7 +6,7 @@ module Squared
6
6
  class Docker < Base
7
7
  COMPOSEFILE = %w[compose.yaml compose.yml docker-compose.yaml docker-compose.yml].freeze
8
8
  BAKEFILE = %w[docker-bake.json docker-bake.hcl docker-bake.override.json docker-bake.override.hcl].freeze
9
- DIR_DOCKER = (COMPOSEFILE + BAKEFILE).freeze
9
+ DIR_DOCKER = (COMPOSEFILE + BAKEFILE + ['Dockerfile']).freeze
10
10
  OPT_DOCKER = {
11
11
  common: %w[tls tlsverify config=p c|context=b D|debug H|host=q l|log-level=b tlscacert=p tlscert=p
12
12
  tlskey=p].freeze,
@@ -91,7 +91,7 @@ module Squared
91
91
  def config?(val)
92
92
  return false unless (val = as_path(val))
93
93
 
94
- val.join('Dockerfile').exist? || DIR_DOCKER.any? { |file| val.join(file).exist? }
94
+ DIR_DOCKER.any? { |file| val.join(file).exist? }
95
95
  end
96
96
  end
97
97
 
@@ -251,9 +251,11 @@ module Squared
251
251
  end
252
252
 
253
253
  def clean(*, sync: invoked_sync?('clean'), **)
254
- return super unless @clean.nil?
255
-
256
- image(:rm, sync: sync)
254
+ if runnable?(@clean)
255
+ super
256
+ else
257
+ image(:rm, sync: sync)
258
+ end
257
259
  end
258
260
 
259
261
  def compose(opts, flags = nil, script: false, args: nil, from: :run, **)
@@ -312,7 +314,7 @@ module Squared
312
314
  append_context
313
315
  when :bake, :compose
314
316
  if (val = option(from == :bake ? 'target' : 'service', ignore: false))
315
- ret.merge(split_escape(val).map! { |s| shell_escape(s) })
317
+ ret.merge(split_escape(val).map! { |s| shell_quote(s) })
316
318
  end
317
319
  end
318
320
  ret
@@ -401,7 +403,7 @@ module Squared
401
403
  args << k
402
404
  next
403
405
  when 'source', 'src', 'destination', 'dst', 'target', 'volume-subpath', 'image-path'
404
- v = path + v
406
+ v = basepath v
405
407
  v = shell_quote(v, option: false, force: false) if q == ''
406
408
  end
407
409
  args << "#{k}=#{q + v + q}"
@@ -575,16 +577,15 @@ module Squared
575
577
  end
576
578
 
577
579
  def dockerfile(val = nil)
578
- if val == 'Dockerfile'
579
- @file = false
580
- elsif val
580
+ if val
581
581
  @file = if val.is_a?(Array)
582
582
  val = val.select { |file| basepath(file).exist? }
583
583
  val.size > 1 ? val : val.first
584
- else
585
- val || DIR_DOCKER.find { |file| basepath(file).exist? }
584
+ elsif val == true
585
+ DIR_DOCKER.find { |file| basepath(file).exist? }
586
+ elsif val != 'Dockerfile'
587
+ val
586
588
  end
587
- @file ||= false
588
589
  end
589
590
  basepath((@file.is_a?(Array) ? @file.first : @file) || 'Dockerfile')
590
591
  end
@@ -622,17 +623,17 @@ module Squared
622
623
  end
623
624
 
624
625
  def append_file(type, target: @session)
625
- return if ENV['COMPOSE_FILE'] && compose?(type)
626
+ return if !@file || (ENV['COMPOSE_FILE'] && compose?(type))
626
627
 
627
628
  unless @file.is_a?(Array)
628
629
  case type
629
630
  when 2, 4
630
631
  return
631
632
  when 3
632
- return unless COMPOSEFILE.map { |val| path + val }.select(&:exist?).size > 1
633
+ return unless COMPOSEFILE.map { |val| basepath(val) }.select(&:exist?).size > 1
633
634
  end
634
635
  end
635
- files = Array(@file).map { |val| quote_option('file', path + val) }
636
+ files = Array(@file).map { |val| quote_option('file', basepath(val)) }
636
637
  if target.is_a?(Set)
637
638
  opts = target.to_a.insert(2, *files)
638
639
  target.clear.merge(opts)
@@ -812,7 +813,7 @@ module Squared
812
813
  end
813
814
 
814
815
  def contextdir(val = nil)
815
- val && projectpath?(val) ? shell_quote(path + val) : '.'
816
+ val && projectpath?(val) ? shell_quote(basepath(val)) : '.'
816
817
  end
817
818
 
818
819
  def tagjoin(*args, char: '/')