squared 0.8.4 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8864164b082f5ec20e4e23ec0cea81a0d2ad0cde6977a0d484b113e72058421a
4
- data.tar.gz: 2b46eca82d45c97c5a5e3ee5881e40429967916e2d569a6cf16271a0d0851a94
3
+ metadata.gz: e486fab218bc18e8b6e3921184c1d4a9aeaf155e2d19f70b62062b279606714d
4
+ data.tar.gz: c5d1cf6cabf110cce2befee1fc6d34dcb9f437d5c84b6dc552bd304b3f7af304
5
5
  SHA512:
6
- metadata.gz: 0d03eca41b747dc5fe16d9767870b83733cf475e60df90358631aed94fe4fa1dbc07b00fe6bfea7e845d9b6cf361e028504c3e6302e17564fcbad5e5c3ea7a80
7
- data.tar.gz: 20e7c2931780199d66ac670a4fa5b74e6a3a2b71215b1edb32cd48d0c1ca0c0622ee7bdabca21291d10add12231540092936f1e9aa3ffd8f065170ad3c65630f
6
+ metadata.gz: ba4f0d602d818ad424fc9fc940954f1c7a8d4fc138fd98e8ebb6f4b7d98baa45188a3f0476f4a7de0512c60e06d74f965da7f4a54a34cdcda76d7baec525e2d1
7
+ data.tar.gz: 52f518b0aaeb168633399c34f62cf19cb14fc1ed463047cf795b527e82d9439e5c2266c3d0f0709777f6bdafdf40cd88f76bbb118e1236f4b8e8ca9a81741a16
data/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.5] - 2026-09-23
4
+
5
+ ### Added
6
+
7
+ - Docker command network action rm was implemented.
8
+ - Git command options were updated to version 2.56.
9
+
10
+ ### Changed
11
+
12
+ - Node package managers will check for a lock file when in CI.
13
+ - Docker method network param target was renamed to name.
14
+
15
+ ## [0.7.12]
16
+
17
+ ### Fixed
18
+
19
+ - See `0.4.42`.
20
+
21
+ ## [0.6.19]
22
+
23
+ ### Fixed
24
+
25
+ - See `0.4.42`.
26
+
27
+ ## [0.5.27]
28
+
29
+ ### Fixed
30
+
31
+ - See `0.4.42`.
32
+
33
+ ## [0.4.42]
34
+
35
+ ### Fixed
36
+
37
+ - OptionPartition did not strip pre-existing quotes when parsing options.
38
+ - Node command outdated did not strip styling from semver in package.json.
39
+ - Git command show did not recognize object names.
40
+ - Docker destination mounts that are not absolute are treated as errors.
41
+ - Docker source mounts for any named volumes or images were inoperable.
42
+
3
43
  ## [0.8.4] - 2026-09-04
4
44
 
5
45
  ### Added
@@ -38,7 +78,6 @@
38
78
  ### Fixed
39
79
 
40
80
  - Git action grep did not recognize format and max-count.
41
- - Node command nvm did not quote executable path.
42
81
 
43
82
  ## [0.5.26]
44
83
 
@@ -59,7 +98,6 @@
59
98
 
60
99
  ### Fixed
61
100
 
62
- - Common prompt method choice did not grep list items.
63
101
  - OptionPartition static method strip did not parse flags with dashes.
64
102
  - Project base method choice_index did not support multiple selections.
65
103
 
@@ -113,7 +151,6 @@
113
151
  ### Changed
114
152
 
115
153
  - OptionPartition method uniq! parameter pass was converted into keyword.
116
- - Project global ENV for BANNER and STRICT can accept boolean values.
117
154
  - Series method exclude? parameter empty was converted into keyword.
118
155
 
119
156
  ## [0.7.9] - 2026-07-04
@@ -621,7 +658,7 @@
621
658
 
622
659
  ### Fixed
623
660
 
624
- - See `0.5.18`.
661
+ - See `0.4.32`.
625
662
 
626
663
  ## [0.4.32]
627
664
 
@@ -2087,11 +2124,13 @@
2087
2124
 
2088
2125
  - Changelog was created.
2089
2126
 
2127
+ [0.8.5]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.5
2090
2128
  [0.8.4]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.4
2091
2129
  [0.8.3]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.3
2092
2130
  [0.8.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.2
2093
2131
  [0.8.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.1
2094
2132
  [0.8.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.0
2133
+ [0.7.12]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.12
2095
2134
  [0.7.11]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.11
2096
2135
  [0.7.10]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.10
2097
2136
  [0.7.9]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.9
@@ -2104,6 +2143,7 @@
2104
2143
  [0.7.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.2
2105
2144
  [0.7.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.1
2106
2145
  [0.7.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.0
2146
+ [0.6.19]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.19
2107
2147
  [0.6.18]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.18
2108
2148
  [0.6.17]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.17
2109
2149
  [0.6.16]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.16
@@ -2123,6 +2163,7 @@
2123
2163
  [0.6.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.2
2124
2164
  [0.6.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.1
2125
2165
  [0.6.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.0
2166
+ [0.5.27]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.27
2126
2167
  [0.5.26]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.26
2127
2168
  [0.5.25]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.25
2128
2169
  [0.5.24]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.24
@@ -2150,6 +2191,7 @@
2150
2191
  [0.5.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.2-ruby
2151
2192
  [0.5.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.1-ruby
2152
2193
  [0.5.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.0-ruby
2194
+ [0.4.42]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.42
2153
2195
  [0.4.41]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.41
2154
2196
  [0.4.40]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.40
2155
2197
  [0.4.39]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.39
data/README.md CHANGED
@@ -678,7 +678,7 @@ LOG_LEVEL # See gem "logger"
678
678
 
679
679
  ### Git
680
680
 
681
- * Version: [2.54](https://github.com/git/git/blob/v2.54.0/Documentation/RelNotes/2.54.0.adoc)
681
+ * Version: [2.56](https://github.com/git/git/blob/v2.56.0/Documentation/RelNotes/2.56.0.adoc)
682
682
 
683
683
  ```sh
684
684
  GIT_OPTIONS=q,strategy=ort # all
@@ -759,6 +759,7 @@ docker build --no-cache --label=v1 --build-arg="NODE_TAG=24" --build-arg="RUBY_V
759
759
  | compose | run | VERSION=s |
760
760
  | compose | publish | TAG=s REGISTRY=s |
761
761
  | container | commit | REGISTRY=s PLATFORM=s DISABLE_CONTENT_TRUST=0,1 |
762
+ | container | run | ENTRYPOINT=s |
762
763
  | container | -run -create -exec | ALL=1 FILTER=s |
763
764
  | | -update -commit | |
764
765
  | image | rm | Y=1 |
@@ -19,6 +19,10 @@ module Squared
19
19
  !Dir['/.dockerenv', '/docker-*.{sh,d}'].empty?
20
20
  end
21
21
 
22
+ def ci?
23
+ ENV['CI'] == 'true' || ENV.key?('BUILD_NUMBER')
24
+ end
25
+
22
26
  def powershell?
23
27
  return true if ENV['SHELL']&.end_with?(File.join('', 'pwsh'))
24
28
  return false unless windows?
@@ -157,7 +157,7 @@ module Squared
157
157
  [multiline || (force ? ':' : '?'), '']
158
158
  end
159
159
  end} "
160
- ret = (read.call || '').strip
160
+ ret = read.call.to_s.strip
161
161
  multiline.each { |val| break if ret.delete_suffix!(val.to_s) } if multiline.is_a?(::Enumerable)
162
162
  exit 1 if force && ret.empty?
163
163
  ret
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.8.4'
4
+ VERSION = '0.8.5'
5
5
  end
@@ -824,7 +824,7 @@ module Squared
824
824
  cmd << name
825
825
  banner = false if flag == :latest || flag == :where
826
826
  end
827
- success?(run(banner: banner, from: symjoin('asdf', flag)), banner, flag == :set || flag == :reshim)
827
+ success?(run(banner: banner, from: symjoin('asdf', flag)), banner, %i[set reshim].include?(flag))
828
828
  end
829
829
 
830
830
  def first(key, *args, **kwargs, &blk)
@@ -913,7 +913,7 @@ module Squared
913
913
  ret = shell_t(*args, name: send, chdir: chdir, exception: exception, timeout: timeout || 0)
914
914
  end
915
915
  rescue Timeout::Error => e
916
- print_error(Logger::ERROR, cmd, subject: name, hint: e)
916
+ print_error(Logger::ERROR, e, subject: name, hint: cmd)
917
917
  exit 1 unless exception?(Logger::DEBUG, Logger::INFO)
918
918
  rescue => e
919
919
  on_error(e, exception: true)
@@ -16,19 +16,19 @@ module Squared
16
16
  cgroup-parent=b iidfile=p label=q network=b no-cache-filter=b o|output=q platform=q q|quiet
17
17
  resource=q secret=qq shm-size=b ssh=qq t|tag=b target=b ulimit=q].freeze,
18
18
  bake: %w[print list=q set=qq var=qq].freeze,
19
- shared: %w[check load no-cache pull push allow=q call=b? f|file=p metadata-file=p policy=q progress=b
20
- provenance=q sbom=q].freeze
19
+ shared: %w[check load no-cache provenance pull push sbom allow=qq call=b? f|file=p metadata-file=p policy=q
20
+ progress=b].freeze
21
21
  }.freeze,
22
22
  compose: {
23
- common: %w[all-resources ansi=b compatibility dry-run env-file=p f|file=p parallel=n profile=b progress=b
23
+ common: %w[1 all-resources compatibility dry-run ansi=b env-file=p f|file=p parallel=n profile=b progress=b
24
24
  project-directory=p p|project-name=b].freeze,
25
25
  build: %w[check no-cache print pull push with-dependencies q|quiet build-arg=qq builder=b m|memory=b
26
26
  provenance=q sbom=q ssh=qq].freeze,
27
27
  create: %w[build force-recreate no-build no-recreate quiet-pull remove-orphans y|yes pull=b scale=i].freeze,
28
28
  exec: %w[d|detach privileged e|env=qq index=i T|no-tty user=b w|workdir=q].freeze,
29
29
  run: %w[build d|detach no-deps q|quiet quiet-build quiet-pull remove-orphans rm P|service-ports use-aliases
30
- cap-add=b cap-drop=b entrypoint=q e|env=qq env-from-file=p i|interactive=b? l|label=q name=b
31
- T|no-tty p|publish=q pull=b u|user=b v|volume=qq w|workdir=q].freeze,
30
+ cap-add=b cap-drop=b entrypoint=q e|env=qq env-from-file=p i|interactive l|label=q name=b T|no-tty
31
+ p|publish=q pull=b u|user=b v|volume=qq w|workdir=q].freeze,
32
32
  up: %w[abort-on-container-exit abort-on-container-failure always-recreate-deps attach-dependencies build
33
33
  d|detach force-recreate menu no-build no-color no-deps no-log-prefix no-recreate no-start quiet-build
34
34
  quiet-pull remove-orphans V|renew-anon-volumes timestamps wait w|watch y|yes attach=b
@@ -50,7 +50,7 @@ module Squared
50
50
  network-alias=b oom-score-adj=b pid=b pids-limit=n platform=q p|publish=q pull=b restart=b
51
51
  runtime=b security-opt=q shm-size=b stop-signal=b stop-timeout=i storage-opt=q sysctl=q tmpfs=q
52
52
  ulimit=q u|user=b userns=b uts=b v|volume=qq volume-driver=b volumes-from=b w|workdir=q].freeze,
53
- run: %w[d|detach detach-keys=q sig-proxy=b?].freeze,
53
+ run: %w[d|detach detach-keys=q sig-proxy].freeze,
54
54
  update: %w[blkio-weight=i cpu-period=i cpu-quota=i cpu-rt-period=i cpu-rt-runtime=i c|cpu-shares=i cpus=f
55
55
  cpuset-cpus=b cpuset-mems=b m|memory=b memory-reservation=b memory-swap=n pids-limit=n
56
56
  restart=q].freeze,
@@ -81,16 +81,17 @@ module Squared
81
81
  connect: %w[alias=b driver-opt=q gw-priority=n ip=b ip6=q link=b link-local-ip=q].freeze,
82
82
  create: %w[attachable config-only gateway=q ingress internal ipv4 ipv6 aux-address=q config-from=b
83
83
  d|driver=b ip-range=q ipam-driver=b ipam-opt=q label=q o|opt=q scope=b subnet=q].freeze,
84
- disconnect: %w[f|force].freeze
84
+ disconnect: %w[f|force].freeze,
85
+ rm: %w[f|force].freeze
85
86
  }.freeze
86
87
  }.freeze
87
88
  VAL_DOCKER = {
88
89
  run: {
89
90
  common: %w[source src destination dst target readonly ro].freeze,
90
- bind: %w[bind-propagation].freeze,
91
+ bind: %w[bind-create-src bind-propagation].freeze,
91
92
  volume: %w[volume-subpath volume-nocopy volume-opt].freeze,
92
93
  tmpfs: %w[tmpfs-size tmpfs-mode].freeze,
93
- image: %w[image-path].freeze
94
+ image: %w[image-subpath].freeze
94
95
  }.freeze,
95
96
  ls: {
96
97
  compose: %w[Name Image Command Service RunningFor Status Ports CreatedAt ExitCode Health ID Labels
@@ -127,7 +128,7 @@ module Squared
127
128
  'image' => %i[ls rm pull push tag save inspect history].freeze,
128
129
  'container' => %i[attach commit create diff exec inspect kill logs pause restart rm run start stats stop top
129
130
  unpause update].freeze,
130
- 'network' => %i[connect disconnect create].freeze,
131
+ 'network' => %i[connect disconnect create rm].freeze,
131
132
  'ls' => nil
132
133
  })
133
134
 
@@ -139,8 +140,7 @@ module Squared
139
140
  self.global = nil
140
141
  return unless dockerfile(kwargs[:file]).exist?
141
142
 
142
- @tag = env('TAG', strict: true,
143
- ignore: false) || kwargs[:tag] || tagname(@project, @version || 'latest')
143
+ @tag = env('TAG', strict: true, ignore: false) || kwargs[:tag] || tagname(@project, @version || 'latest')
144
144
  @context = kwargs[:context]
145
145
  @client = kwargs[:client]&.each_with_object([]) do |(key, val), out|
146
146
  val = case (key = key.to_s)
@@ -149,7 +149,7 @@ module Squared
149
149
  when 'tlscacert', 'tlscert', 'tlskey'
150
150
  basepath!(val, type: 'f')
151
151
  when 'context', 'host', 'log-level'
152
- quote_option(key, val)
152
+ quote_option key, val
153
153
  when 'debug', 'tls', 'tlsverify'
154
154
  out << key
155
155
  next
@@ -158,7 +158,7 @@ module Squared
158
158
  end
159
159
  @mounts = Array(kwargs[:mounts])
160
160
  @secrets = kwargs[:secrets]
161
- self.registry = tagjoin kwargs[:registry], kwargs[:username]
161
+ @registry = tagjoin kwargs[:registry], kwargs[:username]
162
162
  @oci = tagjoin kwargs[:oci], kwargs[:username]
163
163
  initialize_ref Docker.ref
164
164
  initialize_logger kwargs[:log]
@@ -359,11 +359,15 @@ module Squared
359
359
  end
360
360
  end
361
361
  when 'network'
362
- format_desc action, flag, 'target,opts*'
363
- task flag, [:target] do |_, args|
364
- target = flag == :create ? param_guard(action, flag, args: args, key: :target) : args.target
365
- if target
366
- network(flag, args.extras, target: target)
362
+ format_desc action, flag, 'name,opts*'
363
+ task flag, [:name] do |_, args|
364
+ name = if flag == :create || flag == :rm
365
+ param_guard(action, flag, args: args, key: :name)
366
+ else
367
+ args.name
368
+ end
369
+ if name
370
+ network(flag, args.extras, name: name)
367
371
  else
368
372
  choice_command flag
369
373
  end
@@ -530,6 +534,7 @@ module Squared
530
534
  list += ct[:create] if rc
531
535
  list += ct[:update] if rc ||= flag == :create
532
536
  op = OptionPartition.new(opts, list, cmd, args: rc || flag == :exec, **dockerinit)
537
+ option('entrypoint') { |val| op.add_option('entrypoint', val, escape: false, double: true) } if flag == :run
533
538
  from = symjoin 'container', flag
534
539
  case flag
535
540
  when :run, :create, :exec
@@ -557,23 +562,35 @@ module Squared
557
562
  end
558
563
  end
559
564
  case k
560
- when 'readonly', 'ro'
561
- out << k
565
+ when 'readonly', 'ro', 'volume-nocopy', 'bind-create-src'
566
+ out << k if %w[bind volume].include?(type)
562
567
  next
563
- when 'source', 'src', 'destination', 'dst', 'target', 'volume-subpath', 'image-path'
568
+ when 'source', 'src', 'destination', 'dst', 'target', 'volume-subpath', 'image-subpath'
564
569
  raise ArgumentError, message('no path value', k, hint: flag) unless v
565
570
 
566
- v = basepath v
571
+ case k
572
+ when 'source', 'src'
573
+ if type == 'bind'
574
+ v = basepath v
575
+ elsif type == 'tmpfs'
576
+ next
577
+ end
578
+ when 'destination', 'dst', 'target'
579
+ unless v.start_with?('/')
580
+ print_error(Logger::ERROR, "path is not absolute: #{v}", subject: from, hint: k)
581
+ next
582
+ end
583
+ end
567
584
  v = shell_quote(v, option: false, force: false) if q == ''
568
585
  end
569
586
  out << "#{k}=#{q}#{v}#{q}"
570
587
  elsif !silent?
571
- log_message('unrecognized option', subject: from, hint: k)
588
+ puts log_message('unrecognized option', subject: from, hint: k)
572
589
  end
573
590
  end
574
591
  raise TypeError, message('none specified', hint: flag) unless type
575
592
 
576
- cmd << "--mount type=#{type},#{args.join(',')}"
593
+ op << "--mount type=#{type},#{args.join(',')}"
577
594
  end
578
595
  end
579
596
  append_command(flag, id || tagmain, op.extras)
@@ -583,7 +600,7 @@ module Squared
583
600
  op.append(escape: true, strip: ':')
584
601
  when :commit
585
602
  latest = op.shift || tagmain
586
- cmd << id << latest
603
+ op << id << latest
587
604
  raise ArgumentError, message('unrecognized args', op.join(', '), hint: flag) unless op.empty?
588
605
  return unless confirm_command(cmd.to_s, title: from, target: id, as: latest)
589
606
 
@@ -604,7 +621,7 @@ module Squared
604
621
  else
605
622
  if op.empty?
606
623
  ps, status, no = filter_ps(flag, from: from)
607
- cmd << '--no-stream' if flag == :stats
624
+ op << '--no-stream' if flag == :stats
608
625
  list_image(flag, ps, no: no, hint: status, multiple: flag != :attach, from: from) do |img|
609
626
  run(cmd.temp(img), from: from)
610
627
  end
@@ -633,11 +650,12 @@ module Squared
633
650
  op = OptionPartition.new(opts, list, cmd, **dockerinit)
634
651
  exception = exception?
635
652
  banner = true
653
+ status = false
636
654
  from = symjoin 'image', flag
637
655
  case flag
638
656
  when :ls
639
657
  if opts.size == op.size
640
- index = 0
658
+ index = -1
641
659
  name = nil
642
660
  opts.reverse_each do |val|
643
661
  next unless (arg = OptionPartition.parse_arg!('name', val))
@@ -648,6 +666,7 @@ module Squared
648
666
  end
649
667
  list_image(:run, filter: filter, from: from) do |val|
650
668
  args = if name
669
+ index += 1
651
670
  opts.dup << "name=#{index == 0 ? name : "#{name}-#{index}"}"
652
671
  elsif choice!(opts, only: true)
653
672
  OptionPartition.strip(readline('Enter arguments', force: false))
@@ -659,7 +678,6 @@ module Squared
659
678
  break
660
679
  end
661
680
  container(:run, args, id: val)
662
- index += 1
663
681
  end
664
682
  return
665
683
  end
@@ -679,16 +697,15 @@ module Squared
679
697
  banner = false
680
698
  end
681
699
  when :tag, :save
682
- found = false
683
700
  list_image(flag, filter: filter, from: from) do |val|
684
701
  op << val
685
- found = true
702
+ status = true
686
703
  if flag == :tag
687
704
  op << tagname(project, op.first)
688
705
  break
689
706
  end
690
707
  end
691
- raise ArgumentError, message('target not specified', hint: flag) unless found
708
+ raise ArgumentError, message('target not specified', hint: flag) unless status
692
709
  when :pull
693
710
  if !id
694
711
  id = tagmain
@@ -699,7 +716,7 @@ module Squared
699
716
  registry = op.shift
700
717
  registry ||= option('registry') || self.registry unless id.include?('/')
701
718
  end
702
- cmd << shell_quote(tagjoin(registry, id))
719
+ op << shell_quote(tagjoin(registry, id))
703
720
  when :push
704
721
  id ||= option('tag', ignore: false) || op.shift || tagmain
705
722
  registry ||= option('registry') || op.shift || self.registry
@@ -725,16 +742,17 @@ module Squared
725
742
  op.append(escape: true, strip: ':')
726
743
  end
727
744
  end
728
- success?(run(sync: sync, exception: exception, banner: banner, from: from), flag == :tag || flag == :save)
745
+ success?(run(sync: sync, exception: exception, banner: banner, from: from), status)
729
746
  end
730
747
 
731
- def network(flag, opts = [], target: nil)
748
+ def network(flag, opts = [], target: nil, name: target)
732
749
  cmd, opts = docker_session('network', flag, opts: opts)
733
750
  op = OptionPartition.new(opts, OPT_DOCKER[:network].fetch(flag, []), cmd, **dockerinit)
734
751
  .clear
735
752
  from = symjoin 'network', flag
736
- if flag == :create
737
- op.add_quote(target)
753
+ case flag
754
+ when :create, :rm
755
+ op.add_quote(name)
738
756
  run(from: from)
739
757
  else
740
758
  list_image(flag, docker_output('ps -a'), from: from) do |id|
@@ -752,13 +770,13 @@ module Squared
752
770
  end
753
771
 
754
772
  def compose?(file = dockerfile)
755
- return file == 3 || file == 4 if file.is_a?(Numeric)
773
+ return file.between?(3, 4) if file.is_a?(Numeric)
756
774
 
757
775
  COMPOSEFILE.include?(File.basename(file))
758
776
  end
759
777
 
760
778
  def bake?(file = dockerfile)
761
- return file == 1 || file == 2 if file.is_a?(Numeric)
779
+ return file.between?(1, 2) if file.is_a?(Numeric)
762
780
 
763
781
  BAKEFILE.include?(File.basename(file))
764
782
  end
@@ -770,11 +788,11 @@ module Squared
770
788
  val.size > 1 ? val : val.first
771
789
  elsif val == true
772
790
  DIR_DOCKER.find { |file| exist?(file) }
773
- elsif val != 'Dockerfile'
791
+ elsif val != DIR_DOCKER.last
774
792
  val
775
793
  end
776
794
  end
777
- basepath((@file.is_a?(Array) ? @file.first : @file) || 'Dockerfile')
795
+ basepath((@file.is_a?(Array) ? @file.first : @file) || DIR_DOCKER.last)
778
796
  end
779
797
 
780
798
  private
@@ -790,7 +808,7 @@ module Squared
790
808
  yield data
791
809
  end
792
810
  rescue => e
793
- log.debug e
811
+ print_error(e, subject: name, hint: 'compose')
794
812
  end
795
813
  end
796
814
 
@@ -873,7 +891,7 @@ module Squared
873
891
  target
874
892
  end
875
893
 
876
- def filter_ps(flag, meth = nil, from: meth || :'container:ps')
894
+ def filter_ps(flag, meth = nil, column: nil, from: meth || :'container:ps')
877
895
  no = false
878
896
  status = case flag.to_sym
879
897
  when :start
@@ -899,6 +917,8 @@ module Squared
899
917
  end
900
918
  cmd = docker_output("#{from.to_s.split(':').first} ps -a",
901
919
  *status.map { |s| quote_option('filter', "status=#{s}") })
920
+ return IO.popen(cmd.temp("--format=\"{{.#{column}}}\"")).map(&:chomp) if column
921
+
902
922
  [cmd, status, no]
903
923
  end
904
924
 
@@ -914,8 +934,8 @@ module Squared
914
934
  elsif filter.match?(/[:_-]$/)
915
935
  /\b#{Regexp.escape(filter)}/
916
936
  else
917
- filter = filter.empty? ? '([:_-]|$)' : "[:_-]#{filter}"
918
- /\b(#{dnsname(name)}|#{tagname(project)}|#{tagmain.split(':', 2).first})#{filter}/
937
+ names = [dnsname(name), subdomainname(name), tagname(project), tagmain.split(':').first]
938
+ /\b(#{names.join('|')})#{filter.empty? ? '([:_-]|$)' : "[:_-]#{filter}"}/
919
939
  end
920
940
  IO.popen(cmd.temp('--format=json')).each do |line|
921
941
  data = JSON.parse(line)
@@ -1079,7 +1099,7 @@ module Squared
1079
1099
  val = val.compact
1080
1100
  .join(':')
1081
1101
  .split(':')
1082
- .map { |s| charname(s.sub(/^\W+/, '')) }
1102
+ .map { |s| subdomainname(s) }
1083
1103
  ret = val.join(':')
1084
1104
  return ret unless ret.size > max
1085
1105
 
@@ -1091,8 +1111,16 @@ module Squared
1091
1111
  ret[0...max]
1092
1112
  end
1093
1113
 
1094
- def dnsname(val)
1095
- charname(val[/^[^a-z\d]*(.*?)[^a-z\d]*$/i, 1].gsub(/-{2,}/, '-'))[0..62].downcase
1114
+ def dnsname(val, max: 63, char: nil)
1115
+ ret = val.sub(/^[^a-z]+/i, '')
1116
+ .sub(/[^a-z\d]+$/i, '')
1117
+ .gsub(/[^a-z\d#{char}]+/i, '-')
1118
+ .gsub(/-{2,}/, '-')[0...max]
1119
+ char ? ret : ret.downcase
1120
+ end
1121
+
1122
+ def subdomainname(val)
1123
+ dnsname(val, max: 128, char: '.').gsub(/\.{2,}/, '.')
1096
1124
  end
1097
1125
 
1098
1126
  def charname(val)
@@ -1104,7 +1132,7 @@ module Squared
1104
1132
  end
1105
1133
 
1106
1134
  def dockerinit
1107
- { project: self, strict: strict?, explicit: '=', bool: %w[true false 1 0] }
1135
+ { project: self, strict: strict?, explicit: '=', bool: %w[1 0 true false] }
1108
1136
  end
1109
1137
 
1110
1138
  def emptyargs(list, hint = nil)
@@ -158,10 +158,10 @@ module Squared
158
158
  no-replace-objects noglob-pathspecs paginate attr-source=b config-env=q exec-path=p
159
159
  namespace=p].freeze,
160
160
  add: %w[A e|edit f|force ignore-errors ignore-missing i|interactive n|dry-run p|patch pathspec-file-nul
161
- refresh renormalize sparse u|update v|verbose chmod=b pathspec-from-file=p].freeze,
162
- branch: %w[a|all create-reflog i|ignore-case omit-empty q|quiet r|remotes v|verbose=+ abbrev=i color=b
163
- column=b contains=b format=q merged=b no-contains=b no-merged=b points-at=b u|set-upstream-to=b
164
- sort=q t|track=b].freeze,
161
+ refresh renormalize resolved sparse u|update v|verbose chmod=b pathspec-from-file=p].freeze,
162
+ branch: %w[a|all create-reflog dry-run i|ignore-case omit-empty q|quiet r|remotes v|verbose=+ abbrev=i color=b
163
+ column=b contains=b delete-merged=q forked=q format=q merged=b no-contains=b no-merged=b
164
+ points-at=b u|set-upstream-to=b sort=q t|track=b].freeze,
165
165
  checkout: %w[l d|detach f|force ignore-other-worktrees ignore-skip-worktree-bits m|merge p|patch
166
166
  pathspec-file-nul q|quiet ours theirs conflict=b orphan=b pathspec-from-file=p t|track=b].freeze,
167
167
  clone: %w[also-filter-submodules bare dissociate l|local mirror no-hardlinks n|no-checkout no-tags o|origin=b
@@ -214,8 +214,9 @@ module Squared
214
214
  i|regexp-ignore-case remove-empty reverse right-only simplify-by-decoration simplify-merges
215
215
  single-worktree show-pulls source sparse stdin topo-order g|walk-reflogs after=q ancestry-path=b?
216
216
  author=q before=q branches=q? committer=q decorate=b decorate-refs=q decorate-refs-exclude=q
217
- exclude=q exclude-hidden=b glob=q grep=q grep-reflog=q n|max-count=i max-parents=i min-parents=i
218
- no-walk=b? remotes=q? since=q since-as-filter=q skip=i tags=q? until=q].freeze,
217
+ exclude=q exclude-hidden=b glob=q grep=q grep-reflog=q n|max-count=i max-count-oldest=i
218
+ max-parents=i min-parents=i no-walk=b? remotes=q? since=q since-as-filter=q skip=i tags=q?
219
+ until=q].freeze,
219
220
  format: %w[t children combined-all-paths dd oneline left-right no-diff-merges parents relative-date
220
221
  show-notes-by-default show-signature date=q diff-merges=b encoding=b expand-tabs=i format=q
221
222
  notes=b pretty=q? show-linear-break=q?].freeze,
@@ -280,7 +281,7 @@ module Squared
280
281
  push: %w[a|all u|include-untracked k|keep-index no-keep-index no-include-untracked pathspec-file-nul p|patch
281
282
  S|staged m|message=q pathspec-from-file=p].freeze,
282
283
  pop: %w[index].freeze,
283
- apply: %w[index].freeze
284
+ apply: %w[index label-base=b label-ours=b label-theirs=b].freeze
284
285
  }.freeze,
285
286
  status: %w[z u=bm? b|branch long s|short show-stash v|verbose=+ column=b find-renames=i? ignore-submodules=b?
286
287
  ignored=b? porcelain=b? untracked-files=b?].freeze,
@@ -1511,7 +1512,7 @@ module Squared
1511
1512
  else
1512
1513
  args = parse_env('GIT_OPTIONS')
1513
1514
  .grep(/\A--#{Regexp.union(*VAL_GIT[:revbuild])}/)
1514
- .concat(VAL_GIT[:revbuild].map { |key| option(key, prefix: 'git') { |val| basic_option(key, val) } })
1515
+ .concat(VAL_GIT[:revbuild].map { |key| option(key, prefix: 'git') { |val| basic_option key, val } })
1515
1516
  .compact
1516
1517
  OptionPartition.uniq!(args)
1517
1518
  end
@@ -1532,7 +1533,7 @@ module Squared
1532
1533
  start = time_epoch
1533
1534
  ret = build(*@output, sync: sync, from: from)
1534
1535
  rescue => e
1535
- print_error(e, pass: true)
1536
+ print_error(e, subject: name, pass: true)
1536
1537
  else
1537
1538
  if ret == false && !kwargs[:pass]
1538
1539
  print_status('revbuild', subject: name, start: start, loglevel: Logger::WARN, from: :failed)
@@ -1995,7 +1996,7 @@ module Squared
1995
1996
  end
1996
1997
  on :last, from
1997
1998
  end
1998
- print_error(name, 'no ref found', subject: 'branch', hint: 'head', pass: true) if ret == 0
1999
+ print_error('no ref found', subject: name, hint: 'branch: head', pass: true) if ret == 0
1999
2000
  return
2000
2001
  end
2001
2002
  return unless success?(source(stdout: stdout), !ref && flag == :create) && !ref && remote && target
@@ -2059,7 +2060,7 @@ module Squared
2059
2060
  cmd << '--textconv'
2060
2061
  append_value(files.flat_map { |val| Dir[val] }
2061
2062
  .select { |val| projectpath?(val) }
2062
- .map { |val| shell_quote("HEAD:#{val}") })
2063
+ .map { |val| "HEAD:#{val}" })
2063
2064
  source(banner: false)
2064
2065
  return
2065
2066
  when :oneline
@@ -2073,11 +2074,11 @@ module Squared
2073
2074
  else
2074
2075
  opts << format if format
2075
2076
  end
2076
- list = OPT_GIT[:show] + OPT_GIT[:diff][:show] + OPT_GIT[:log][:diff] + OPT_GIT[:log][:diff_context]
2077
+ list = OPT_GIT[:show] + OPT_GIT[:diff][:show] + collect_hash(OPT_GIT[:log], pass: [:base])
2077
2078
  op = OptionPartition.new(opts, list, cmd,
2078
2079
  project: self, strict: strict?,
2079
2080
  no: OPT_GIT[:no][:show] + collect_hash(OPT_GIT[:no][:log], pass: [:base]))
2080
- op.append(delim: true)
2081
+ op.append
2081
2082
  source(exception: false, banner: flag != :oneline)
2082
2083
  end
2083
2084
 
@@ -2153,8 +2154,7 @@ module Squared
2153
2154
  when :'sparse-checkout'
2154
2155
  cmd << 'set'
2155
2156
  end
2156
- op = OptionPartition.new(opts, list, cmd, project: self, strict: strict?,
2157
- no: OPT_GIT[:no][flag], single: /\A\d+\z/,
2157
+ op = OptionPartition.new(opts, list, cmd, project: self, strict: strict?, no: OPT_GIT[:no][flag],
2158
2158
  first: case flag
2159
2159
  when :blame, :revert, :'sparse-checkout' then nil
2160
2160
  else matchpathspec
@@ -2303,7 +2303,7 @@ module Squared
2303
2303
  run_e(cmd, stderr: stderr, banner: banner, **kwargs)
2304
2304
  end
2305
2305
  rescue Timeout::Error => e
2306
- print_error(Logger::ERROR, cmd, subject: name, hint: e)
2306
+ print_error(Logger::ERROR, e, subject: name, hint: cmd)
2307
2307
  exit 1 unless exception?(Logger::DEBUG, Logger::INFO)
2308
2308
  rescue => e
2309
2309
  on_error(e, pass: true)
@@ -394,7 +394,7 @@ module Squared
394
394
  elsif has_value!(args, 'p', 'public')
395
395
  'public'
396
396
  end
397
- dryrun = has_value!(args, 'd', 'dry-run')
397
+ dryrun = has_value! args, 'd', 'dry-run'
398
398
  end
399
399
  case flag
400
400
  when :stage
@@ -411,7 +411,7 @@ module Squared
411
411
  [ver, tag, item['id'], item['actor']]
412
412
  end
413
413
  if data.empty?
414
- print_error('no staged releases', loglevel: Logger::INFO, subject: npmname)
414
+ print_error(Logger::INFO, 'no staged releases', subject: npmname)
415
415
  exit 1
416
416
  end
417
417
  data.each do |item|
@@ -456,7 +456,7 @@ module Squared
456
456
  @tsfile
457
457
  end
458
458
  end
459
- watch = has_value!(args, 'w', 'watch')
459
+ watch = has_value! args, 'w', 'watch'
460
460
  tsc(*args, banner: true, project: project, build: flag == :build, watch: !watch.nil?)
461
461
  end
462
462
  end
@@ -662,7 +662,7 @@ module Squared
662
662
  end
663
663
  if nolockfile?(prefix: 'yarn')
664
664
  cmd << '--no-lockfile'
665
- elsif option('ci')
665
+ elsif option('ci') || (ci? && exist?('yarn.lock'))
666
666
  if yarn == 1
667
667
  cmd << '--frozen-lockfile'
668
668
  elsif !flag
@@ -698,13 +698,14 @@ module Squared
698
698
  '--force'
699
699
  elsif nolockfile?(prefix: 'pnpm')
700
700
  '--no-lockfile'
701
- elsif option('ci')
701
+ elsif option('ci') || (ci? && exist?('pnpm-lock.yaml'))
702
702
  '--frozen-lockfile'
703
703
  end
704
704
  cmd << '--ignore-scripts' if option('ignore-scripts')
705
705
  cmd << '--dangerously-allow-all-builds' if option('approve-builds')
706
706
  else
707
- cmd = session('npm', (ci = option('ci', prefix: 'npm')) ? 'ci' : 'install')
707
+ ci = option('ci', prefix: 'npm') || (ci? && exist?('package-lock.json'))
708
+ cmd = session('npm', ci ? 'ci' : 'install')
708
709
  option('approve-scripts') do |val|
709
710
  cmd = npm_output 'approve-scripts'
710
711
  cmd << case val
@@ -873,7 +874,7 @@ module Squared
873
874
  pending = 0
874
875
  modified = 0
875
876
  width = ->(a, i) { a.map { |aa| aa[i] }.max_by(&:size).size }
876
- pad = ->(val, ord) { val.succ.to_s.rjust([ord.size.to_s.size, 2].max) }
877
+ pad = ->(a, n) { n.succ.to_s.rjust([a.size.to_s.size, 2].max) }
877
878
  footer = lambda do |val, size|
878
879
  return unless verbose
879
880
 
@@ -889,7 +890,7 @@ module Squared
889
890
  if !found.empty?
890
891
  col1 = width.call(found, 0) + 4
891
892
  col2 = width.call(found, 1) + 4
892
- col3 = pad.call(found.size, found).size + 2 + col1 + col2 + width.call(found, 2)
893
+ col3 = pad.call(found, found.size).size + 2 + col1 + col2 + width.call(found, 2)
893
894
  packages = []
894
895
  pat = ->(a) { /("#{Regexp.escape(a[0])}"\s*:\s*)"([~^])#{'?' if a[4]}#{Regexp.escape(a[1])}"/ }
895
896
  edit = lambda do |a, pkg, mod|
@@ -911,21 +912,21 @@ module Squared
911
912
  end
912
913
  a = a.ljust(col1)
913
914
  b = b.ljust(col2)
914
- sub_style! b, theme[:current] if theme[:current] && !stdin?
915
+ b = sub_style b, theme[:current] if theme[:current] && !stdin?
915
916
  if cur == -1
916
917
  c = 'SKIP'
917
918
  elsif modified == cur
918
919
  c = 'FAIL'
919
920
  elsif !stdin?
920
921
  if d == 1
921
- sub_style! a, theme[:major]
922
- sub_style! c, :bold, color(:green)
922
+ a = sub_style a, theme[:major]
923
+ c = sub_style c, :bold, color(:green)
923
924
  else
924
- sub_style!(c, **opt_style(color(d == 3 ? :green : :yellow), SEM_VER, d))
925
+ c = sub_style(c, **opt_style(color(d == 3 ? :green : :yellow), SEM_VER, d))
925
926
  end
926
927
  g = item
927
928
  end
928
- s = "#{pad.call(i, found)}. #{a}#{b}#{c}"
929
+ s = "#{pad.call(found, i)}. #{a}#{b}#{c}"
929
930
  if se
930
931
  items << [s, g]
931
932
  next
@@ -994,11 +995,11 @@ module Squared
994
995
  b = sub_style b.ljust(col2), color(d ? :red : :yellow)
995
996
  c = c.ljust(col3)
996
997
  unless d
997
- sub_style! a, theme[:active]
998
- sub_style! c, color(:green)
998
+ a = sub_style a, theme[:active]
999
+ c = sub_style c, color(:green)
999
1000
  pending += 1
1000
1001
  end
1001
- puts "#{pad.call(i, avail)}. #{(a + c + b).subhint(d ? 'locked' : 'latest')}"
1002
+ puts "#{pad.call(avail, i)}. #{(a + c + b).subhint(d ? 'locked' : 'latest')}"
1002
1003
  end
1003
1004
  footer.call(0, avail.size)
1004
1005
  else
@@ -1621,10 +1622,10 @@ module Squared
1621
1622
  modules.rmtree
1622
1623
  rescue Timeout::Error => e
1623
1624
  puts
1624
- print_error(e, hint: modules, pass: true)
1625
+ print_error(e, subject: name, hint: modules, pass: true)
1625
1626
  exit 1
1626
1627
  rescue => e
1627
- print_error(e, pass: true)
1628
+ print_error(e, subject: name, pass: true)
1628
1629
  false
1629
1630
  else
1630
1631
  true
@@ -565,7 +565,7 @@ module Squared
565
565
  task flag do |_, args|
566
566
  args = args.to_a
567
567
  multiline = case args.first
568
- when ';', '#'
568
+ when ';', /^#+$/
569
569
  args.shift
570
570
  else
571
571
  %w[## ;]
@@ -844,11 +844,11 @@ module Squared
844
844
  def outdated(flag = nil, opts = [], sync: invoked_sync?('outdated', flag))
845
845
  cmd = bundle_output 'outdated'
846
846
  if flag
847
- se = has_value!(opts, 's', 'select')
847
+ se = has_value! opts, 's', 'select'
848
848
  ia = has_value!(opts, 'i', 'interactive') && !se
849
- up = has_value!(opts, 'u', 'update')
849
+ up = has_value! opts, 'u', 'update'
850
850
  opts << 'only-explicit' if has_value!(opts, 'e', 'explicit')
851
- dryrun = has_value!(opts, 'd', 'dry-run')
851
+ dryrun = has_value! opts, 'd', 'dry-run'
852
852
  if !sync || stdin?
853
853
  se = false
854
854
  ia = false
@@ -1672,7 +1672,7 @@ module Squared
1672
1672
  def serve(root, *, bind: nil, port: 3000, **kwargs)
1673
1673
  require 'webrick'
1674
1674
  rescue LoadError => e
1675
- print_error(e, pass: true)
1675
+ print_error(e, subject: name, hint: 'webrick', pass: true)
1676
1676
  else
1677
1677
  config = kwargs.merge({ DocumentRoot: root })
1678
1678
  config[:BindAddress] = bind if bind
@@ -408,17 +408,23 @@ module Squared
408
408
  if opt =~ OPT_VALUE
409
409
  key = $1
410
410
  val = $2
411
+ if val =~ QUOTE_VALUE
412
+ val = $2
413
+ double = $1 == '"'
414
+ end
411
415
  get = ->(h) { h[key] || h.find { |k,| k.end_with?(':*') }.last }
412
416
  kwargs = { sep: se[key] || sep, merge: has.call(m, key), switch: sw[key] }
417
+ kwargs[:double] = double unless double.nil?
413
418
  if has.call(e, key) || (has.call(bl, key) && bool.include?(val))
414
419
  add shell_option(key, val, **kwargs)
415
420
  elsif has.call(ex, key) && bool.include?(val)
416
421
  add shell_option(key, val, explicit: explicit, **kwargs)
417
422
  elsif has.call(q, key)
418
- add quote_option(key, val, double: has.call(qq, key), **kwargs)
423
+ kwargs[:double] = true if has.call(qq, key)
424
+ add quote_option(key, val, **kwargs)
419
425
  elsif has.call(p, key)
420
- if val =~ QUOTE_VALUE
421
- add shell_option(key, val, double: $1 == '"', escape: false, **kwargs)
426
+ if !double.nil?
427
+ add shell_option(key, val, escape: false, **kwargs)
422
428
  elsif path
423
429
  add quote_option(key, path + val, **kwargs)
424
430
  else
@@ -449,7 +455,7 @@ module Squared
449
455
  end
450
456
  opt = key unless opt == last
451
457
  elsif has.call(m, key = opt[0]) && opt[1..-1] =~ QUOTE_VALUE
452
- add basic_option(key, $2, double: $1 == '"', **kwargs, merge: true)
458
+ add basic_option(key, $2, double: $1 == '"' || has.call(qq, key), **kwargs, merge: true)
453
459
  opt = key
454
460
  else
455
461
  push opt
@@ -281,7 +281,7 @@ module Squared
281
281
  env('REPO_OPTIONS', **kwargs) { |val| cmd << val } if options
282
282
  cmd = cmd.join(' ')
283
283
  puts log_message(cmd, subject: main, hint: root) if verbose
284
- Common::System.shell(cmd, chdir: root, exception: exception)
284
+ Common::System.shell(cmd, chdir: root, exception: exception || env('REPO_FAIL', equals: %w[1 true]))
285
285
  end
286
286
 
287
287
  def repo_bin
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.4
4
+ version: 0.8.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  - !ruby/object:Gem::Version
127
127
  version: '0'
128
128
  requirements: []
129
- rubygems_version: 4.0.19
129
+ rubygems_version: 4.0.21
130
130
  specification_version: 4
131
131
  summary: Rake task generator for managing multi-language workspaces.
132
132
  test_files: []