squared 0.7.10 → 0.7.11

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: bf477ce6ea561419bddfea1572f95762934d01c5d5e94bd3cd65e027a96bdcc8
4
- data.tar.gz: ffbdcaea4e1a2dc293b75fe99c8e121baa444c8784175aa6117134921fb59e46
3
+ metadata.gz: b2815cc0583f2f21107460840d1e73cbb74b7013d77c9f1ae65e6b4cd72bfe07
4
+ data.tar.gz: c321afc376c0b219967d6318650143588099f0d734461c470970919bc03cf00b
5
5
  SHA512:
6
- metadata.gz: e86f20679d0f906ed3ae080963014c88f2b747dd5570d3e8bf0037f7f0d4670ce257dc6720b13d94fc8f044f16e89a535f09634f7cee8bc5d7061a2f8d2b7485
7
- data.tar.gz: 41c08e924735c9626889f6075a3eb3b5a00bf8f9e9b487ccf29f9de161a3b93702ee1658ea9a73d323bceea31671ea08ab74f58ad83151a5e5bd2929351c6c60
6
+ metadata.gz: 76adacb4694911e5b587c0f9871d8adc8cab9770cf9173d82452d58ad142e171b2a284f93f35769869b42a43f374e005daa595a6698537c07b74847a46e99df2
7
+ data.tar.gz: 92f875447ab1969fb3374a686ec5766e0980f6536fa3859737d16207e763f6e68db07ad350419b85d53846e65e3f87aed29546eb182066ab27be9bd09f4f34cc
data/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.11] - 2026-09-04
4
+
5
+ ### Added
6
+
7
+ - Node command package action [approve|deny] is interactive.
8
+
9
+ ### Fixed
10
+
11
+ - Docker container commands [run|exec] did not sanitize input prompt.
12
+
13
+ ## [0.6.18]
14
+
15
+ ### Added
16
+
17
+ - Docker command bake action buildx with first arg "-" inherits base args.
18
+
19
+ ### Fixed
20
+
21
+ - Git action grep did not recognize format and max-count.
22
+ - Node command nvm did not quote executable path.
23
+
24
+ ## [0.5.26]
25
+
26
+ ### Fixed
27
+
28
+ - Node command nvm did not quote executable path.
29
+
30
+ ## [0.4.41]
31
+
32
+ ### Added
33
+
34
+ - Common base argument SUCCESS for command confirmation was created.
35
+
36
+ ### Changed
37
+
38
+ - Program options prefer using quotes instead of escape.
39
+ - Docker container run arguments with a leading dash are concatenated.
40
+
41
+ ### Fixed
42
+
43
+ - Common prompt method choice did not grep list items.
44
+ - OptionPartition static method strip did not parse flags with dashes.
45
+ - Project base method choice_index did not support multiple selections.
46
+
3
47
  ## [0.7.10] - 2026-08-06
4
48
 
5
49
  ### Fixed
@@ -1947,6 +1991,7 @@
1947
1991
 
1948
1992
  - Changelog was created.
1949
1993
 
1994
+ [0.7.11]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.11
1950
1995
  [0.7.10]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.10
1951
1996
  [0.7.9]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.9
1952
1997
  [0.7.8]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.8
@@ -1958,6 +2003,7 @@
1958
2003
  [0.7.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.2
1959
2004
  [0.7.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.1
1960
2005
  [0.7.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.0
2006
+ [0.6.18]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.18
1961
2007
  [0.6.17]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.17
1962
2008
  [0.6.16]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.16
1963
2009
  [0.6.15]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.15
@@ -1976,6 +2022,7 @@
1976
2022
  [0.6.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.2
1977
2023
  [0.6.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.1
1978
2024
  [0.6.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.0
2025
+ [0.5.26]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.26
1979
2026
  [0.5.25]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.25
1980
2027
  [0.5.24]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.24
1981
2028
  [0.5.23]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.23
@@ -2002,6 +2049,7 @@
2002
2049
  [0.5.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.2-ruby
2003
2050
  [0.5.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.1-ruby
2004
2051
  [0.5.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.0-ruby
2052
+ [0.4.41]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.41
2005
2053
  [0.4.40]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.40
2006
2054
  [0.4.39]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.39
2007
2055
  [0.4.38]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.38
@@ -15,6 +15,7 @@ module Squared
15
15
  CHOICE: 25,
16
16
  QUOTE: "'",
17
17
  SPACE: ' => ',
18
+ SUCCESS: 'Success',
18
19
  GRAPH: %w[| - | \\ -].freeze,
19
20
  BORDER: %w[| - - - - - | | - -].freeze,
20
21
  VIEW: 'view',
@@ -56,10 +56,11 @@ module Squared
56
56
  def choice(msg, list = nil, min: 1, max: 1, multiple: false, index: false, grep: nil, border: nil, auto: true,
57
57
  force: true, attempts: 3, timeout: 0)
58
58
  require 'timeout'
59
+ multiple = Array(multiple) if multiple.is_a?(::Numeric)
59
60
  if list
60
61
  grep &&= Array(grep).map { |val| Regexp.new(val) }
61
62
  items = list.each_with_object([]) do |val, out|
62
- next if grep&.none? { |pat| pat.match?(line) }
63
+ next if grep&.none? { |pat| pat.match?(val) }
63
64
 
64
65
  out << val.to_s.chomp
65
66
  puts '%2d. %s' % [out.size, val]
@@ -76,7 +77,7 @@ module Squared
76
77
  puts print_footer(border: border)
77
78
  end
78
79
  msg = "#{msg + (force ? ':' : '?')} [#{min}-#{max}#{if (n = multiple)
79
- "|,#{n.is_a?(::Numeric) ? "{#{n}}" : '*'}"
80
+ "|,#{n.is_a?(::Array) ? "{#{n.join(',')}}" : '*'}"
80
81
  end}] "
81
82
  end
82
83
  end
@@ -105,7 +106,7 @@ module Squared
105
106
  unless k.include?(nil)
106
107
  k.uniq!
107
108
  k.sort!
108
- unless multiple.is_a?(::Numeric) && multiple != k.size
109
+ unless multiple.is_a?(::Array) && !multiple.include?(k.size)
109
110
  return index || !items ? k : k.map { |i| items[i.pred] }
110
111
  end
111
112
  end
@@ -140,7 +140,7 @@ module Squared
140
140
  end
141
141
 
142
142
  def env_key(*val)
143
- val.join('_').gsub(/\W+/, '_').upcase
143
+ val.join('_').sub(/\A\d+\W*/, '__').gsub(/\W+/, '_').upcase
144
144
  end
145
145
 
146
146
  def env_bool(key, default = false, index: false, **kwargs)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.7.10'
4
+ VERSION = '0.7.11'
5
5
  end
@@ -1703,7 +1703,7 @@ module Squared
1703
1703
  end
1704
1704
 
1705
1705
  def print_success
1706
- puts 'Success'
1706
+ puts ARG[:SUCCESS]
1707
1707
  end
1708
1708
 
1709
1709
  def print_error(*args, loglevel: Logger::WARN, **kwargs)
@@ -2121,7 +2121,10 @@ module Squared
2121
2121
  if accept
2122
2122
  hint = Array(ret).map { |val| sub_style(val.to_s, theme[:inline]) }.join(', ')
2123
2123
  accept = Array(accept).map { |val| Array(val) }
2124
- ret = Array(ret) if accept.any? { |val| val[1] == true }
2124
+ if accept.any? { |val| val[1] == true }
2125
+ ret = [ret]
2126
+ multiple = -1
2127
+ end
2125
2128
  begin
2126
2129
  item = accept.shift
2127
2130
  c = confirm("#{item[0]}#{" [#{hint}]" if hint}", item[2] ? 'Y' : 'N')
@@ -2134,7 +2137,7 @@ module Squared
2134
2137
  end until accept.empty?
2135
2138
  end
2136
2139
  if values
2137
- ret = Array(ret)
2140
+ ret = [ret] unless accept && multiple == -1
2138
2141
  Array(values).each do |val|
2139
2142
  if val.is_a?(Array)
2140
2143
  val, force = val
@@ -21,14 +21,14 @@ module Squared
21
21
  }.freeze,
22
22
  compose: {
23
23
  common: %w[all-resources ansi=b compatibility dry-run env-file=p f|file=p parallel=n profile=b progress=b
24
- project-directory=p p|project-name=e].freeze,
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
- exec: %w[d|detach privileged e|env=qq index=i T|no-TTY=b? user=e w|workdir=q].freeze,
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
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=b? p|publish=q pull=b u|user=e v|volume=q w|workdir=q].freeze,
31
+ T|no-tty=!? 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
@@ -38,9 +38,9 @@ module Squared
38
38
  }.freeze,
39
39
  container: {
40
40
  create: %w[init i|interactive no-healthcheck oom-kill-disable privileged P|publish-all q|quiet read-only
41
- rm t|tty use-api-socket add-host=q annotation=q a|attach=b blkio-weight=i blkio-weight-device=i
42
- cap-add=b cap-drop=b cgroup-parent=b cgroupns=b cidfile=p device=q device-cgroup-rule=q
43
- device-read-bps=q device-read-iops=q device-write-bps=q device-write-iops=q
41
+ rm t|tty=!? use-api-socket add-host=q annotation=q a|attach=b blkio-weight=i
42
+ blkio-weight-device=i cap-add=b cap-drop=b cgroup-parent=b cgroupns=b cidfile=p device=q
43
+ device-cgroup-rule=q device-read-bps=q device-read-iops=q device-write-bps=q device-write-iops=q
44
44
  dns=q dns-option=q dns-search=q domainname=b entrypoint=q e|env=qq env-file=p expose=q gpus=q
45
45
  group-add=b health-cmd=q health-interval=b health-retries=i health-start-interval=q
46
46
  health-start-period=q health-timeout=q hostname=q io-maxbandwidth=b io-maxiops=b ip=b ip6=q ipc=b
@@ -48,13 +48,14 @@ module Squared
48
48
  m|memory=b memory-reservation=b memory-swap=n memory-swappiness=n mount=qq name=b network=b
49
49
  network-alias=b oom-score-adj=b pid=b pids-limit=n platform=q p|publish=q pull=b restart=b
50
50
  runtime=b security-opt=q shm-size=b stop-signal=b stop-timeout=i storage-opt=q sysctl=q tmpfs=q
51
- ulimit=q u|user=b userns=b uts=b v|volume=q volume-driver=b volumes-from=b w|workdir=q].freeze,
51
+ ulimit=q u|user=b userns=b uts=b v|volume=qq volume-driver=b volumes-from=b w|workdir=q].freeze,
52
52
  run: %w[d|detach detach-keys=q sig-proxy=b?].freeze,
53
53
  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
54
54
  cpuset-cpus=b cpuset-mems=b m|memory=b memory-reservation=b memory-swap=n pids-limit=n
55
55
  restart=q].freeze,
56
- exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p u|user=e
56
+ exec: %w[d|detach i|interactive privileged t|tty=!? detach-keys=q e|env=qq env-file=p u|user=b
57
57
  w|workdir=q].freeze,
58
+ rm: %w[f|force l|link v|volumes].freeze,
58
59
  commit: %w[no-pause a|author=q c|change=q m|message=q pause=b?].freeze,
59
60
  inspect: %w[s|size f|format=q].freeze,
60
61
  start: %w[a|attach i|interactive detach-keys=q].freeze,
@@ -405,15 +406,15 @@ module Squared
405
406
  end
406
407
 
407
408
  def buildx(flag, opts = [], tag: nil, context: nil, from: nil)
409
+ bx = OPT_DOCKER[:buildx]
408
410
  if flag == :bake && context&.match?(%r{^["']?(https?|git)://}i)
409
- shared = data[:shared].dup.push('f|file=q')
411
+ shared = bx[:shared].dup.push('f|file=q')
410
412
  shared.delete('f|file=p')
411
413
  end
412
414
  cmd, opts = docker_session('buildx', opts: opts)
413
- data = OPT_DOCKER[:buildx]
414
- op = OptionPartition.new(opts, data[:common], cmd, project: self, strict: strict?)
415
+ op = OptionPartition.new(opts, bx[:common], cmd, project: self, strict: strict?)
415
416
  op.append(flag, quote: false)
416
- .parse(data[flag == :bake ? :bake : :build] + (shared || data[:shared]))
417
+ .parse(bx[flag == :bake ? :bake : :build] + (shared || bx[:shared]))
417
418
  case flag
418
419
  when :build, :context
419
420
  append_tag(tag || option('tag', ignore: false) || self.tag)
@@ -424,6 +425,10 @@ module Squared
424
425
  end
425
426
  when :bake
426
427
  append_file(0, index: 3) unless from || op.arg?('f', 'file') || !anypath?(*COMPOSEFILE)
428
+ if op.first == '-'
429
+ op.shift
430
+ op << @output[4] if @output[4]
431
+ end
427
432
  unless op.empty?
428
433
  if !context && op.size > 1 && exist?(op.last, type: 'd')
429
434
  pat = /\btarget\s+"#{Regexp.escape(op.last)}"/
@@ -454,10 +459,11 @@ module Squared
454
459
  docker_session('compose', command, '--', *service)
455
460
  else
456
461
  cmd, opts = docker_session('compose', opts: opts)
457
- op = OptionPartition.new(opts, OPT_DOCKER[:compose][:common], cmd, project: self, strict: strict?)
462
+ cp = OPT_DOCKER[:compose]
463
+ op = OptionPartition.new(opts, cp[:common], cmd, project: self, strict: strict?)
458
464
  append_file(filetype, force: flag == :publish) unless op.arg?('f', 'file')
459
465
  op << flag
460
- op.parse(OPT_DOCKER[:compose].fetch(flag, []))
466
+ op.parse(cp.fetch(flag, []))
461
467
  if flag == :publish
462
468
  id ||= option('tag', ignore: false) || op.shift || tagmain
463
469
  registry ||= option('registry') || op.shift || @oci
@@ -488,10 +494,11 @@ module Squared
488
494
 
489
495
  def container(flag, opts = [], id: nil)
490
496
  cmd, opts = docker_session('container', flag, opts: opts)
491
- data = OPT_DOCKER[:container]
492
- list = data.fetch(flag, [])
493
- list += data[:create] if (rc = flag == :run)
494
- list += data[:update] if rc ||= flag == :create
497
+ rc = flag == :run
498
+ ct = OPT_DOCKER[:container]
499
+ list = ct.fetch(flag, [])
500
+ list += ct[:create] if rc
501
+ list += ct[:update] if rc ||= flag == :create
495
502
  op = OptionPartition.new(opts, list, cmd, project: self, strict: strict?, args: rc || flag == :exec)
496
503
  from = symjoin 'container', flag
497
504
  case flag
@@ -645,7 +652,7 @@ module Squared
645
652
  raise_error ArgumentError, 'username/registry not specified', hint: flag unless registry
646
653
  uri = shell_quote tagjoin(registry, id)
647
654
  op << uri
648
- img = docker_output 'image', 'tag', id, uri
655
+ img = docker_output 'image tag', id, uri
649
656
  return unless confirm_command(img.to_s, cmd.to_s, target: id, as: registry, title: from)
650
657
 
651
658
  @session = img
@@ -736,12 +743,12 @@ module Squared
736
743
  session('docker', *cmd, main: false, options: false, **kwargs)
737
744
  end
738
745
 
739
- def append_command(flag, val, list, target: @session, prompt: ':')
740
- list << if list.delete(prompt)
741
- readline('Enter command [args]', force: flag == :exec)
742
- else
743
- env('DOCKER_ARGS')
744
- end
746
+ def append_command(flag, id, list, target: @session, prompt: ':')
747
+ if list.delete(prompt)
748
+ list << readline('Enter command [args]', force: flag == :exec)
749
+ elsif (val = env('DOCKER_ARGS'))
750
+ list << val
751
+ end
745
752
  case flag
746
753
  when :run
747
754
  unless session_arg?('name', target: target)
@@ -750,8 +757,22 @@ module Squared
750
757
  when :exec
751
758
  raise_error ArgumentError, 'nothing to execute', hint: flag if list.empty?
752
759
  end
753
- target << val << list.shift
754
- target << list.join(' && ') unless list.empty?
760
+ target << id
761
+ case list.first
762
+ when '--'
763
+ target.merge(list.drop(1))
764
+ when /\A(--|&&)(\s|\z)/
765
+ target.merge(list)
766
+ else
767
+ target << list.shift
768
+ unless list.empty?
769
+ if list.first.start_with?('-')
770
+ target.merge(list)
771
+ else
772
+ target << list.join(' && ')
773
+ end
774
+ end
775
+ end
755
776
  end
756
777
 
757
778
  def append_file(type, target: @session, index: 2, force: false)
@@ -822,7 +843,7 @@ module Squared
822
843
  pwd_set(from: from) do
823
844
  index = 1
824
845
  all = option('all', prefix: 'docker')
825
- y = from == :'image:rm' && option('y', prefix: 'docker')
846
+ y = from.to_s.end_with?(':rm') && option('y', prefix: 'docker')
826
847
  filter = env('DOCKER_FILTER', filter).to_s
827
848
  pat = if OptionPartition.pattern?(filter)
828
849
  Regexp.new(filter)
@@ -963,7 +984,7 @@ module Squared
963
984
  end
964
985
  cmd.merge(Array(out).map { |val| val.split(/\s+/, 2).first })
965
986
  cmd << args
966
- success?(run(cmd), ctx.start_with?('network', 'tag', 'save'))
987
+ success?(run(cmd, { 'NO_COLOR' => 'true' }), ctx.start_with?('network', 'tag', 'save'))
967
988
  end
968
989
 
969
990
  def filetype(val = dockerfile)
@@ -169,9 +169,10 @@ module Squared
169
169
  fetch: {
170
170
  base: %w[multiple porcelain progress P|prune-tags refetch stdin u|update-head-ok
171
171
  recurse-submodules-default=b?].freeze,
172
- pull: %w[4 6 n t a|append atomic dry-run f|force k|keep negotiate-only prefetch p|prune q|quiet set-upstream
173
- unshallow update-shallow v|verbose deepen=i depth=i j|jobs=i negotiation-tip=q recurse-submodules=v
174
- refmap=q o|server-option=q shallow-exclude=b shallow-since=v upload-pack=q].freeze
172
+ pull: %w[n t 4|ipv4 6|ipv6 a|append atomic dry-run f|force k|keep negotiate-only prefetch p|prune q|quiet
173
+ set-upstream unshallow update-shallow v|verbose deepen=i depth=i j|jobs=i negotiation-tip=q
174
+ recurse-submodules=v refmap=q o|server-option=q shallow-exclude=b shallow-since=v
175
+ upload-pack=q].freeze
175
176
  }.freeze,
176
177
  git: {
177
178
  add: %w[N|intent-to-add].freeze,
@@ -211,7 +212,7 @@ module Squared
211
212
  graph ita-invisible-in-index minimal name-only name-status no-color-moved-ws no-prefix no-renames
212
213
  numstat patch-with-raw patch-with-stat patience pickaxe-all pickaxe-regex raw shortstat summary
213
214
  a|text abbrev=i? anchored=q break-rewrites=b? color=b color-moved=b color-moved-ws=b color-words=q?
214
- diff-algorithm=b diff-filter=e? X|dirstat=b? dirstat-by-file=b? dst-prefix=q find-copies=i?
215
+ diff-algorithm=b diff-filter=q? X|dirstat=b? dirstat-by-file=b? dst-prefix=q find-copies=i?
215
216
  find-object=b find-renames=b? ignore-matching-lines=q ignore-submodules=b? line-prefix=q
216
217
  max-depth=n output=p output-indicator-context=q output-indicator-new=q output-indicator-old=q
217
218
  relative=p rotate-to=p skip-to=p src-prefix=q stat=b? stat-count=i stat-width=i stat-name-width=i
@@ -276,7 +277,7 @@ module Squared
276
277
  checkout: %w[overwrite-ignore guess overlay progress recurse-submodules track].freeze,
277
278
  fetch: {
278
279
  base: %w[auto-gc auto-maintenance write-commit-graph write-fetch-head].freeze,
279
- pull: %w[all ipv4 ipv6 recurse-submodules show-forced-updates tags].freeze
280
+ pull: %w[all recurse-submodules show-forced-updates tags].freeze
280
281
  },
281
282
  grep: %w[color exclude-standard recursive textconv].freeze,
282
283
  log: {
@@ -309,7 +310,7 @@ module Squared
309
310
  }.freeze,
310
311
  rebase: {
311
312
  send: %w[continue skip abort quit].freeze,
312
- value: %w[true false merges interactive].freeze
313
+ value: %w[false true merges interactive].freeze
313
314
  }.freeze,
314
315
  reset: %w[soft mixed hard merge keep recurse-submodules no-recurse-submodules].freeze,
315
316
  revbuild: %w[untracked-files ignore-submodules ignored].freeze
@@ -600,10 +601,10 @@ module Squared
600
601
  when 'i', 'E', 'F', 'P'
601
602
  opts << last
602
603
  else
603
- if last =~ /^(f(-ormat)?)=(.+)$/
604
+ if last =~ /^f(?:-ormat)?=(.+)$/
604
605
  opts.shift
605
606
  opts << "format=#{$1}"
606
- elsif last =~ /^(max(-count)?)=(\d+)$/
607
+ elsif last =~ /^max(?:-count)?=(\d+)$/
607
608
  opts << "max-count=#{$1}"
608
609
  else
609
610
  grep << last
@@ -1200,7 +1201,11 @@ module Squared
1200
1201
  first: (matchpathspec if flag == :push))
1201
1202
  case flag
1202
1203
  when :push
1203
- op.readline('Enter message', option: 'message', quote: true) if op.remove(':')
1204
+ if op.remove(':')
1205
+ op.readline('Enter message', option: 'message', quote: true)
1206
+ else
1207
+ append_message
1208
+ end
1204
1209
  append_pathspec op.extras
1205
1210
  when :pop, :apply, :drop, :branch
1206
1211
  if op.remove(':')
@@ -1885,7 +1890,7 @@ module Squared
1885
1890
  op.add_quote(remote) if remote
1886
1891
  out, banner, from = source(io: true)
1887
1892
  print_item banner
1888
- ret = write_lines(out, grep: op.extras, prefix: "refs/#{flag}/")
1893
+ ret = write_lines(out, grep: op.extras)
1889
1894
  list_result(ret, flag.to_s, grep: op.extras, banner: banner, from: from)
1890
1895
  end
1891
1896
 
@@ -2185,9 +2190,9 @@ module Squared
2185
2190
  end
2186
2191
  end
2187
2192
 
2188
- def append_pathspec(files = [], target: @session, expect: false, **kwargs)
2193
+ def append_pathspec(files = [], target: @session, expect: false, strict: strict?, **kwargs)
2189
2194
  if session_arg?('pathspec-from-file', target: target)
2190
- OptionPartition.clear(target, files, styles: theme[:inline])
2195
+ OptionPartition.clear(target, files, strict: strict, styles: theme[:inline])
2191
2196
  true
2192
2197
  else
2193
2198
  option('pathspec', target: target) { |val| files = split_escape(val) } if files.empty?
@@ -18,6 +18,7 @@ module Squared
18
18
  pack: %w[ignore-scripts=!? json=!? pack-destination=p].freeze,
19
19
  rebuild: %w[bin-links=! foreground-scripts=!? global=!? ignore-scripts=!? install-links=!?].freeze,
20
20
  'approve-scripts': %w[a|all allow-scripts-pending allow-scripts-pin=!? no-allow-scripts-pin json].freeze,
21
+ 'deny-scripts': %w[a|all json].freeze,
21
22
  no: {
22
23
  install: %w[audit bin-links fund package-lock].freeze
23
24
  }.freeze
@@ -285,7 +286,7 @@ module Squared
285
286
 
286
287
  format_desc action, nil, 'version?,args*'
287
288
  task action, [:version] do |_, args|
288
- path = ->(s) { File.join(ENV['NVM_DIR'], s) }
289
+ path = ->(s) { shell_quote(File.join(ENV['NVM_DIR'], s)) }
289
290
  unless (version = args.version)
290
291
  cmd = ". #{path.call('nvm.sh')} && nvm list --no-colors --no-alias"
291
292
  version = pwd_set(from: :nvm) do
@@ -313,13 +314,41 @@ module Squared
313
314
  outdated flag, args.to_a
314
315
  end
315
316
  when 'package'
316
- format_desc(action, flag, 'opts*', before: case flag
317
- when :dedupe, :rebuild then nil
318
- when :reinstall then 'f/orce?'
319
- else 'name*'
320
- end)
321
- task flag do |_, args|
322
- package flag, args.to_a
317
+ case flag
318
+ when :approve, :deny
319
+ format_desc action, flag, 'name*|:,opts*'
320
+ task flag do |_, args|
321
+ args = args.to_a
322
+ if args.first == ':'
323
+ args.shift
324
+ pwd_set do
325
+ pad = 0
326
+ list = IO.popen(npm_output('approve-scripts --allow-scripts-pending').to_s)
327
+ .each_with_object([]) do |line, out|
328
+ next unless line =~ /^\s+([a-z\d@][^@]*)@(\S+)/
329
+
330
+ pad = [pad, $1.size].max
331
+ out << [$1, $2]
332
+ end
333
+ .map { |name, ver| name.ljust(pad + 4) + ver }
334
+ if list.empty?
335
+ puts log_message('no packages to review', subject: name, hint: "#{flag}-scripts")
336
+ exit 0
337
+ end
338
+ args.concat(choice_index('Select packages', list, multiple: true, column: /^(\S+)/))
339
+ end
340
+ end
341
+ package flag, args
342
+ end
343
+ else
344
+ format_desc(action, flag, 'opts*', before: case flag
345
+ when :dedupe, :rebuild then nil
346
+ when :reinstall then 'f/orce?'
347
+ else 'name*'
348
+ end)
349
+ task flag do |_, args|
350
+ package flag, args.to_a
351
+ end
323
352
  end
324
353
  when 'bump'
325
354
  break unless version
@@ -726,7 +726,7 @@ module Squared
726
726
  op.clear(pass: false)
727
727
  else
728
728
  if op.empty?
729
- op << "#{dist.call}/*"
729
+ op.add_path(dist.call, '*')
730
730
  else
731
731
  op.add_path
732
732
  end
@@ -87,8 +87,25 @@ module Squared
87
87
 
88
88
  def strip(val)
89
89
  val = shell_split val if val.is_a?(String)
90
- Array(val).map { |s| s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2').sub(OPT_NAME, '\2') }
91
- .reject(&:empty?)
90
+ ret = []
91
+ pass = -1
92
+ (args = Array(val)).each_with_index do |s, i|
93
+ next if s.empty? || pass == i
94
+
95
+ if s == '--'
96
+ ret << s << args[i.succ..-1].join(' ')
97
+ break
98
+ end
99
+ next ret << s unless s.start_with?('-')
100
+
101
+ if !s.include?('=') && (j = args[i.succ]) && !j.start_with?('-')
102
+ ret << "#{s.sub(/^-{1,2}/, '')}=#{j}"
103
+ pass = i.succ
104
+ else
105
+ ret << s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2').sub(OPT_NAME, '\2')
106
+ end
107
+ end
108
+ ret
92
109
  end
93
110
 
94
111
  def select(list, bare: true, no: true, single: false, double: false)
@@ -152,8 +169,11 @@ module Squared
152
169
  end
153
170
 
154
171
  def pattern?(val)
172
+ Regexp.new(val)
155
173
  val.start_with?('\A', '^') || val.end_with?('\z', '$') ||
156
174
  val.match?(/[.)][*+?]|\(\?[:=!><]|\\[dsw\d]|\[.+\]|\{\d+,?\d*\}/i)
175
+ rescue RegexpError
176
+ false
157
177
  end
158
178
 
159
179
  private
@@ -251,13 +271,13 @@ module Squared
251
271
  else
252
272
  [flag]
253
273
  end
274
+ bare.concat(mod) if val.chomp!('?')
275
+ m.concat(mod) if val.chomp!('m')
254
276
  case val[n.succ]
255
277
  when 'e'
256
278
  e.concat(mod)
257
279
  when 'b'
258
280
  b.concat(mod)
259
- when 'm'
260
- m.concat(mod)
261
281
  when 'q'
262
282
  qq.concat(mod) if val[n + 2] == 'q'
263
283
  q.concat(mod)
@@ -276,11 +296,7 @@ module Squared
276
296
  when '+'
277
297
  ml.concat(mod)
278
298
  bare.concat(mod)
279
- else
280
- next
281
299
  end
282
- m.concat(mod) if val[n + 2] == 'm'
283
- bare.concat(mod) if val.end_with?('?')
284
300
  else
285
301
  bare << val
286
302
  mod = [val]
@@ -315,7 +331,7 @@ module Squared
315
331
  end
316
332
  numtype = [
317
333
  [i, /\A\d+\z/],
318
- [f, /\A\d*(?:\.\d+)?\z/],
334
+ [f, /\A(\d+(\.\d*)?|\d*\.\d+)\z/],
319
335
  [si, /\A-?\d+\z/]
320
336
  ].freeze
321
337
  numcheck = ->(k, v) { numtype.any? { |flag, pat| flag.include?(k) && v.match?(pat) } }
@@ -360,8 +376,8 @@ module Squared
360
376
  elsif has.call(q)
361
377
  add quote_option(key, val, double: has.call(qq), **kwargs)
362
378
  elsif has.call(p)
363
- if val.match?(/\A(["']).+\1\z/)
364
- add shell_option(key, val, escape: false, **kwargs)
379
+ if val =~ /\A(["']).+\1\z/
380
+ add shell_option(key, val, double: $1 == '"', escape: false, **kwargs)
365
381
  elsif path
366
382
  add quote_option(key, path + val, **kwargs)
367
383
  else
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.7.10
4
+ version: 0.7.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
@@ -125,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
125
  - !ruby/object:Gem::Version
126
126
  version: '0'
127
127
  requirements: []
128
- rubygems_version: 4.0.15
128
+ rubygems_version: 4.0.19
129
129
  specification_version: 4
130
130
  summary: Rake task generator for managing multi-language workspaces.
131
131
  test_files: []