squared 0.5.25 → 0.5.27

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: e0cd4ff3d9faafb78e2d7f13560866b4db396f766f06c4dd0def6e228fbb3b28
4
- data.tar.gz: 8e30a7002e81361a7554a232cee8483f1ecc99e4920431dc60242595ff4b8a15
3
+ metadata.gz: c5c24126ebda5ad3652471df73d84a2a9cfee4869aec8d9d51866f6187c5bc2c
4
+ data.tar.gz: 7dbd9b710b61222cd52feadcbf3a275452c0a0c7bcc780588442a79cb255c1c3
5
5
  SHA512:
6
- metadata.gz: 3f7a5569c684260af71ced323cc90a4574b291e38c42cd6118811f2f1cbc7c6b6ce3880217260721de122bd742feedc986ff0f147cc248b5b16eb38c6df25f7a
7
- data.tar.gz: a42bf79be7e6d83776e97c67cef06cdb7a5183db8b788a69fc489e2156d7d366644433ea8ad677126e7ae191d33631b242f96ed0bdf179885e9e15b0462baa70
6
+ metadata.gz: 4bac4146c0083dc1783ae55e87026c1bdd4c3f8eb93f9e3adf0ce3cb8c2967ff96808972daa66c3bdbecb2dc59f83c7739ba03297f6e4b17b77bfd18dc249ae2
7
+ data.tar.gz: '044758d7290a4487c4db1f7beb0aeb3a1597e6f0b25b1f7e64fc148ca864cfc2dad30aa661ce0eba5bc7cb004b0088cf963367bb19e2abe983dbc4b9c9cf8c72'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.27] - 2026-09-23
4
+
5
+ ### Fixed
6
+
7
+ - See `0.4.42`.
8
+
9
+ ## [0.4.42] - 2026-09-23
10
+
11
+ ### Fixed
12
+
13
+ - OptionPartition did not strip pre-existing quotes when parsing options.
14
+ - Node command outdated did not strip styling from semver in package.json.
15
+ - Git command show did not recognize object names.
16
+ - Docker destination mounts that are not absolute are treated as errors.
17
+ - Docker source mounts for any named volumes or images were inoperable.
18
+
19
+ ## [0.5.26] - 2026-09-04
20
+
21
+ ### Fixed
22
+
23
+ - Node command nvm did not quote executable path.
24
+
25
+ ## [0.4.41] - 2026-09-04
26
+
27
+ ### Added
28
+
29
+ - Common base argument SUCCESS for command confirmation was created.
30
+
31
+ ### Changed
32
+
33
+ - Program options prefer using quotes instead of escape.
34
+ - Docker container run arguments with a leading dash are concatenated.
35
+
36
+ ### Fixed
37
+
38
+ - Common prompt method choice did not grep list items.
39
+ - OptionPartition static method strip did not parse flags with dashes.
40
+ - Project base method choice_index did not support multiple selections.
41
+
3
42
  ## [0.5.25] - 2026-07-04
4
43
 
5
44
  ### Fixed
@@ -1437,6 +1476,8 @@
1437
1476
 
1438
1477
  - Changelog was created.
1439
1478
 
1479
+ [0.5.27]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.27
1480
+ [0.5.26]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.26
1440
1481
  [0.5.25]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.25
1441
1482
  [0.5.24]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.24
1442
1483
  [0.5.23]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.23
@@ -1463,6 +1504,9 @@
1463
1504
  [0.5.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.2-ruby
1464
1505
  [0.5.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.1-ruby
1465
1506
  [0.5.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.0-ruby
1507
+ [0.4.42]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.42
1508
+ [0.4.41]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.41
1509
+ [0.4.40]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.40
1466
1510
  [0.4.39]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.39
1467
1511
  [0.4.38]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.38
1468
1512
  [0.4.37]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.37
@@ -14,6 +14,7 @@ module Squared
14
14
  CHOICE: 25,
15
15
  QUOTE: "'",
16
16
  SPACE: ' => ',
17
+ SUCCESS: 'Success',
17
18
  GRAPH: ['|', '-', '|', '\\', '-'].freeze,
18
19
  BORDER: ['|', '-', '-', '-', '-', '-', '|', '|', '-', '-'].freeze,
19
20
  VIEW: 'view',
@@ -90,6 +91,13 @@ module Squared
90
91
  VAR[key.is_a?(::String) ? key.to_sym : key] = val
91
92
  end
92
93
 
94
+ def __arg__(key, name = nil, &blk)
95
+ ret = ARG[key.to_sym]
96
+ return ret unless name && ret.is_a?(::Hash)
97
+
98
+ ret[name = name.downcase] || (block_given? ? ret.fetch(name.to_sym, &blk) : ret[name.to_sym])
99
+ end
100
+
93
101
  def __freeze__
94
102
  PATH.freeze
95
103
  ARG.freeze
@@ -60,7 +60,7 @@ module Squared
60
60
  end}] "
61
61
  end
62
62
  end
63
- valid = ->(s) { s.match?(/^\d+$/) && s.to_i.between?(min, max) }
63
+ valid = ->(s) { s.match?(/^-?\d+$/) && s.to_i.between?(min, max <= min ? Float::INFINITY : max) }
64
64
  Timeout.timeout(timeout) do
65
65
  while (ch = Readline.readline(msg))
66
66
  unless (ch = ch.strip).empty?
@@ -113,7 +113,7 @@ module Squared
113
113
  end
114
114
 
115
115
  def env_key(*val)
116
- val.join('_').gsub(/\W+/, '_').upcase
116
+ val.join('_').sub(/\A\d+\W*/, '__').gsub(/\W+/, '_').upcase
117
117
  end
118
118
 
119
119
  def env_value(key, default = '', suffix: nil, strict: false)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.5.25'
4
+ VERSION = '0.5.27'
5
5
  end
@@ -1303,7 +1303,7 @@ module Squared
1303
1303
  def env(key, default = nil, suffix: nil, equals: nil, ignore: nil, strict: false)
1304
1304
  a = "#{key}_#{@envname}"
1305
1305
  ret = if suffix
1306
- ENV.fetch("#{a}_#{suffix}", '')
1306
+ ENV["#{a}_#{suffix}"] || (ignore == false && ENV["#{key}_#{suffix}"]) || ''
1307
1307
  elsif strict
1308
1308
  ENV[a].to_s
1309
1309
  else
@@ -1367,7 +1367,7 @@ module Squared
1367
1367
  end
1368
1368
 
1369
1369
  def print_success(*)
1370
- puts 'Success'
1370
+ puts ARG[:SUCCESS]
1371
1371
  end
1372
1372
 
1373
1373
  def print_error(*args, loglevel: Logger::WARN, **kwargs)
@@ -1531,7 +1531,7 @@ module Squared
1531
1531
  end
1532
1532
 
1533
1533
  def append_hash(data, target: @session || [], build: false)
1534
- if build && (type = env('BUILD', suffix: 'TYPE') || ENV['BUILD_TYPE'])
1534
+ if build && (type = env('BUILD', suffix: 'TYPE', ignore: false))
1535
1535
  type = "__#{type}__"
1536
1536
  if (extra = data[type] || data[type.to_sym]).is_a?(Hash)
1537
1537
  data = data.merge(extra)
@@ -1740,7 +1740,10 @@ module Squared
1740
1740
  if accept
1741
1741
  hint = Array(ret).map { |val| sub_style(val, styles: theme[:inline]) }.join(', ')
1742
1742
  accept = Array(accept).map { |val| Array(val) }
1743
- ret = Array(ret) if accept.any? { |val| val[1] == true }
1743
+ if accept.any? { |val| val[1] == true }
1744
+ ret = [ret]
1745
+ multiple = -1
1746
+ end
1744
1747
  loop do
1745
1748
  item = accept.first
1746
1749
  c = confirm("#{item[0]}#{hint ? " [#{hint}]" : ''}", item[2] ? 'Y' : 'N', timeout: 60)
@@ -1756,7 +1759,7 @@ module Squared
1756
1759
  exit 1 unless accept.empty?
1757
1760
  end
1758
1761
  if values
1759
- ret = Array(ret)
1762
+ ret = [ret] unless accept && multiple == -1
1760
1763
  Array(values).each do |val|
1761
1764
  if val.is_a?(Array)
1762
1765
  val, force = val
@@ -16,18 +16,18 @@ module Squared
16
16
  cgroup-parent=b iidfile=p label=q network=b no-cache-filter=b o|output=q platform=q
17
17
  q|quiet secret=qq shm-size=b ssh=qq t|tag=b target=b ulimit=q].freeze,
18
18
  bake: %w[print list=q set=q].freeze,
19
- shared: %w[check load no-cache pull push allow=q call=b? f|file=p metadata-file=p progress=b provenance=q
20
- sbom=q].freeze
19
+ shared: %w[check load no-cache pull push allow=qq call=b? f|file=p metadata-file=p progress=b provenance=b?
20
+ sbom=b?].freeze
21
21
  }.freeze,
22
22
  compose: {
23
- common: %w[all-resources compatibility dry-run ansi=b env-file=p f|file=p parallel=n profile=b progress=b
24
- project-directory=p p|project-name=e].freeze,
23
+ common: %w[1 all-resources compatibility dry-run ansi=b env-file=p f|file=p parallel=n profile=b progress=b
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
- exec: %w[d|detach privileged e|env=qq index=i T|no-TTY=b? user=e w|workdir=q].freeze,
27
+ exec: %w[d|detach privileged e|env=qq index=i T|no-tty=!? user=b w|workdir=q].freeze,
28
28
  run: %w[build d|detach no-deps q|quiet quiet-build quiet-pull remove-orphans rm P|service-ports use-aliases
29
29
  cap-add=b cap-drop=b entrypoint=q e|env=qq env-from-file=p i|interactive=b? l|label=q name=b
30
- T|no-TTY=b? p|publish=q pull=b u|user=e v|volume=q w|workdir=q].freeze,
30
+ T|no-tty=!? p|publish=q pull=b u|user=b v|volume=qq w|workdir=q].freeze,
31
31
  up: %w[abort-on-container-exit abort-on-container-failure always-recreate-deps attach-dependencies build
32
32
  d|detach force-recreate menu no-build no-color no-deps no-log-prefix no-recreate no-start quiet-build
33
33
  quiet-pull remove-orphans V|renew-anon-volumes timestamps wait w|watch y|yes attach=b
@@ -36,9 +36,9 @@ module Squared
36
36
  }.freeze,
37
37
  container: {
38
38
  create: %w[init i|interactive no-healthcheck oom-kill-disable privileged P|publish-all q|quiet read-only
39
- rm t|tty use-api-socket add-host=q annotation=q a|attach=b blkio-weight=i blkio-weight-device=i
40
- cap-add=b cap-drop=b cgroup-parent=b cgroupns=b cidfile=p device=q device-cgroup-rule=q
41
- device-read-bps=q device-read-iops=q device-write-bps=q device-write-iops=q
39
+ rm t|tty=!? use-api-socket add-host=q annotation=q a|attach=b blkio-weight=i
40
+ blkio-weight-device=i cap-add=b cap-drop=b cgroup-parent=b cgroupns=b cidfile=p device=q
41
+ device-cgroup-rule=q device-read-bps=q device-read-iops=q device-write-bps=q device-write-iops=q
42
42
  disable-content-trust=b? dns=q dns-option=q dns-search=q domainname=b entrypoint=q e|env=qq
43
43
  env-file=p expose=q gpus=q group-add=b health-cmd=q health-interval=b health-retries=i
44
44
  health-start-interval=q health-start-period=q health-timeout=q hostname=q io-maxbandwidth=b
@@ -47,13 +47,14 @@ module Squared
47
47
  memory-swap=n memory-swappiness=n mount=qq name=b network=b network-alias=b oom-score-adj=b
48
48
  pid=b pids-limit=n platform=q p|publish=q pull=b restart=b runtime=b security-opt=q shm-size=b
49
49
  stop-signal=b stop-timeout=i storage-opt=q sysctl=q tmpfs=q ulimit=q u|user=b userns=b uts=b
50
- v|volume=q volume-driver=b volumes-from=b w|workdir=q].freeze,
50
+ v|volume=qq volume-driver=b volumes-from=b w|workdir=q].freeze,
51
51
  run: %w[d|detach detach-keys=q sig-proxy=b?].freeze,
52
52
  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
53
53
  cpuset-cpus=b cpuset-mems=b m|memory=b memory-reservation=b memory-swap=b pids-limit=n
54
54
  restart=q].freeze,
55
- exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p user=e
55
+ exec: %w[d|detach i|interactive privileged t|tty=!? detach-keys=q e|env=qq env-file=p user=b
56
56
  w|workdir=q].freeze,
57
+ rm: %w[f|force l|link v|volumes].freeze,
57
58
  commit: %w[a|author=q c|change=q m|message=q pause=b?].freeze,
58
59
  inspect: %w[s|size f|format=q type=b].freeze,
59
60
  start: %w[a|attach i|interactive detach-keys=q].freeze,
@@ -76,10 +77,10 @@ module Squared
76
77
  VAL_DOCKER = {
77
78
  run: {
78
79
  common: %w[source src destination dst target readonly ro].freeze,
79
- bind: %w[bind-propagation].freeze,
80
+ bind: %w[bind-create-src bind-propagation].freeze,
80
81
  volume: %w[volume-subpath volume-nocopy volume-opt].freeze,
81
82
  tmpfs: %w[tmpfs-size tmpfs-mode].freeze,
82
- image: %w[image-path].freeze
83
+ image: %w[image-subpath].freeze
83
84
  }.freeze
84
85
  }.freeze
85
86
  private_constant :COMPOSEFILE, :BAKEFILE, :OPT_DOCKER, :VAL_DOCKER
@@ -399,20 +400,30 @@ module Squared
399
400
  end
400
401
  end
401
402
  case k
402
- when 'readonly', 'ro'
403
- args << k
403
+ when 'readonly', 'ro', 'volume-nocopy', 'bind-create-src'
404
+ args << k if %w[bind volume].include?(type)
404
405
  next
405
- when 'source', 'src', 'destination', 'dst', 'target', 'volume-subpath', 'image-path'
406
- v = basepath v
406
+ when 'source', 'src', 'destination', 'dst', 'target', 'volume-subpath', 'image-subpath'
407
+ raise_error ArgumentError, "no path value: #{k}", hint: flag unless v
408
+ case k
409
+ when 'source', 'src'
410
+ if type == 'bind'
411
+ v = basepath v
412
+ elsif type == 'tmpfs'
413
+ next
414
+ end
415
+ when 'destination', 'dst', 'target'
416
+ puts log_message("path is not absolute: #{v}", subject: from, hint: k) unless v.start_with?('/')
417
+ end
407
418
  v = shell_quote(v, option: false, force: false) if q == ''
408
419
  end
409
420
  args << "#{k}=#{q + v + q}"
410
421
  elsif verbose
411
- log_message(Logger::INFO, 'unrecognized option', subject: from, hint: k)
422
+ puts log_message(Logger::INFO, 'unrecognized option', subject: from, hint: k)
412
423
  end
413
424
  end
414
425
  raise_error('missing type', hint: flag) unless type
415
- cmd << "--mount type=#{type},#{args.join(',')}"
426
+ op << "--mount type=#{type},#{args.join(',')}"
416
427
  end
417
428
  end
418
429
  append_command(flag, id || tagmain, op.extras)
@@ -421,7 +432,7 @@ module Squared
421
432
  op.append(escape: true, strip: /^:/)
422
433
  when :commit
423
434
  latest = op.shift || tagmain
424
- cmd << id << latest
435
+ op << id << latest
425
436
  raise_error("unknown args: #{op.join(', ')}", hint: flag) unless op.empty?
426
437
  return unless confirm_command(cmd.to_s, title: from, target: id, as: latest)
427
438
 
@@ -633,8 +644,22 @@ module Squared
633
644
  when :exec
634
645
  raise_error('no command args', hint: flag) if list.empty?
635
646
  end
636
- target << val << list.shift
637
- target << list.join(' && ') unless list.empty?
647
+ target << val
648
+ case list.first
649
+ when '--'
650
+ target.merge(list.drop(1))
651
+ when /\A(--|&&)(\s|\z)/
652
+ target.merge(list)
653
+ else
654
+ target << list.shift
655
+ unless list.empty?
656
+ if list.first.start_with?('-')
657
+ target.merge(list)
658
+ else
659
+ target << list.join(' && ')
660
+ end
661
+ end
662
+ end
638
663
  end
639
664
 
640
665
  def append_file(type, target: @session, index: 2)
@@ -810,7 +835,7 @@ module Squared
810
835
  end
811
836
  cmd.merge(Array(out).map! { |val| parse.call(val) })
812
837
  cmd << args
813
- print_success if success?(run(cmd), ctx.start_with?(/network|tag|save/))
838
+ print_success if success?(run(cmd, { 'NO_COLOR' => 'true' }), ctx.start_with?(/network|tag|save/))
814
839
  end
815
840
  end
816
841
 
@@ -133,7 +133,6 @@ module Squared
133
133
  end
134
134
  File.write(@revfile, JSON.pretty_generate(@revdoc))
135
135
  rescue StandardError => e
136
- log&.debug e
137
136
  warn log_message(Logger::WARN, e, pass: true) if warning
138
137
  ensure
139
138
  @revlock = false
@@ -174,7 +173,7 @@ module Squared
174
173
  fetch: {
175
174
  base: %w[multiple porcelain progress P|prune-tags refetch stdin u|update-head-ok
176
175
  recurse-submodules-default=b].freeze,
177
- pull: %w[4 6 n t a|append atomic dry-run f|force k|keep negotiate-only prefetch p|prune q|quiet
176
+ pull: %w[n t 4|ipv4 6|ipv6 a|append atomic dry-run f|force k|keep negotiate-only prefetch p|prune q|quiet
178
177
  set-upstream unshallow update-shallow v|verbose deepen=i depth=i j|jobs=i negotiation-tip=q
179
178
  recurse-submodules=v refmap=q o|server-option=q shallow-exclude=b shallow-since=v
180
179
  upload-pack=q].freeze
@@ -210,7 +209,7 @@ module Squared
210
209
  ita-invisible-in-index minimal name-only name-status no-color-moved-ws no-prefix no-renames numstat
211
210
  patch-with-raw patch-with-stat patience pickaxe-all pickaxe-regex raw shortstat summary a|text
212
211
  abbrev=i? anchored=q break-rewrites=b? color=b color-moved=b color-moved-ws=b color-words=q?
213
- diff-algorithm=b diff-filter=e? X|dirstat=b? dirstat-by-file=b? dst-prefix=q find-copies=i?
212
+ diff-algorithm=b diff-filter=q? X|dirstat=b? dirstat-by-file=b? dst-prefix=q find-copies=i?
214
213
  find-object=b find-renames=b? ignore-matching-lines=q ignore-submodules=b? inter-hunk-context=i
215
214
  line-prefix=q output=p output-indicator-context=q output-indicator-new=q output-indicator-old=q
216
215
  relative=p rotate-to=p skip-to=p src-prefix=q stat=b? stat-count=i stat-width=i stat-name-width=i
@@ -266,7 +265,7 @@ module Squared
266
265
  checkout: %w[overwrite-ignore guess overlay progress recurse-submodules track].freeze,
267
266
  fetch: {
268
267
  base: %w[auto-gc auto-maintenance write-commit-graph write-fetch-head].freeze,
269
- pull: %w[all ipv4 ipv6 recurse-submodules show-forced-updates tags].freeze
268
+ pull: %w[all recurse-submodules show-forced-updates tags].freeze
270
269
  },
271
270
  log: {
272
271
  base: %w[decorate mailmap merges use-mailmap].freeze,
@@ -1674,7 +1673,7 @@ module Squared
1674
1673
  cmd << '--textconv'
1675
1674
  append_value(files.flat_map { |val| Dir[val] }
1676
1675
  .select { |val| projectpath?(val) }
1677
- .map! { |val| shell_quote("HEAD:#{val}") })
1676
+ .map! { |val| "HEAD:#{val}" })
1678
1677
  source(banner: false)
1679
1678
  return
1680
1679
  when :oneline
@@ -1688,10 +1687,11 @@ module Squared
1688
1687
  else
1689
1688
  opts << format if format
1690
1689
  end
1691
- op = OptionPartition.new(opts, OPT_GIT[:show] + OPT_GIT[:diff][:show] + OPT_GIT[:log][:diff], cmd,
1690
+ list = OPT_GIT[:show] + OPT_GIT[:diff][:show] + collect_hash(OPT_GIT[:log], pass: [:base])
1691
+ op = OptionPartition.new(opts, list, cmd,
1692
1692
  project: self,
1693
1693
  no: OPT_GIT[:no][:show] + collect_hash(OPT_GIT[:no][:log], pass: [:base]))
1694
- op.append(delim: true)
1694
+ op.append
1695
1695
  source(exception: false, banner: flag != :oneline)
1696
1696
  end
1697
1697
 
@@ -1723,7 +1723,7 @@ module Squared
1723
1723
  op.add_quote(remote) if remote
1724
1724
  out, banner, from = source(io: true)
1725
1725
  print_item banner
1726
- ret = write_lines(out, grep: op.extras, prefix: "refs/#{flag}/")
1726
+ ret = write_lines(out, grep: op.extras)
1727
1727
  list_result(ret, flag.to_s, grep: op.extras, banner: banner, from: from)
1728
1728
  end
1729
1729
 
@@ -220,7 +220,7 @@ module Squared
220
220
  version = param_guard(action, 'version', args: args, key: :version)
221
221
  args = args.extras
222
222
  args << readline('Enter command', force: true) if args.empty?
223
- args.unshift(File.join(ENV['NVM_DIR'], 'nvm-exec'))
223
+ args.unshift(shell_quote(File.join(ENV['NVM_DIR'], 'nvm-exec')))
224
224
  run(args.join(' '), { 'NODE_VERSION' => version }, banner: false, from: :nvm)
225
225
  end
226
226
  when 'pack'
@@ -611,7 +611,7 @@ module Squared
611
611
  capture
612
612
  else
613
613
  modified += 1
614
- "#{$1}\"#{$2 || (d == 1 && e ? '^' : '')}#{c}\""
614
+ "#{$1}\"#{$2 || (d == 1 && e ? '^' : '')}#{strip_style(c)}\""
615
615
  end
616
616
  end
617
617
  end
@@ -159,7 +159,7 @@ module Squared
159
159
  log.warn "run script #{n} of #{list.size} (out of range)"
160
160
  end
161
161
  else
162
- case index
162
+ case (index > 1 && poetry? ? 0 : index)
163
163
  when 0
164
164
  found |= 1
165
165
  run(session_output('poetry', 'run', val), from: :run)
@@ -558,7 +558,7 @@ module Squared
558
558
  case flag
559
559
  when :hatch, :twine
560
560
  if op.empty?
561
- op.push("#{dist.call}/*")
561
+ op.push(dist.call.join('*'))
562
562
  else
563
563
  op.map! { |val| basepath(val) }
564
564
  end
@@ -74,7 +74,25 @@ module Squared
74
74
  return [] unless val
75
75
 
76
76
  val = shell_split val if val.is_a?(String)
77
- val.map { |s| s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2').sub(OPT_NAME, '\2') }.reject(&:empty?)
77
+ ret = []
78
+ pass = -1
79
+ (args = Array(val)).each_with_index do |s, i|
80
+ next if s.empty? || pass == i
81
+
82
+ if s == '--'
83
+ ret << s << args[i.succ..-1].join(' ')
84
+ break
85
+ end
86
+ next ret << s unless s.start_with?('-')
87
+
88
+ if !s.include?('=') && (j = args[i.succ]) && !j.start_with?('-')
89
+ ret << "#{s.sub(/^-{1,2}/, '')}=#{j}"
90
+ pass = i.succ
91
+ else
92
+ ret << s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2').sub(OPT_NAME, '\2')
93
+ end
94
+ end
95
+ ret
78
96
  end
79
97
 
80
98
  def select(list, bare: true, no: true, single: false, double: false)
@@ -103,7 +121,11 @@ module Squared
103
121
  end
104
122
 
105
123
  def pattern?(val)
106
- val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*})/)
124
+ Regexp.new(val)
125
+ val.start_with?('\A', '^') || val.end_with?('\z', '$') ||
126
+ val.match?(/[.)][*+?]|\(\?[:=!><]|\\[dsw\d]|\[.+\]|\{\d+,?\d*\}/i)
127
+ rescue RegexpError
128
+ false
107
129
  end
108
130
 
109
131
  private
@@ -233,7 +255,7 @@ module Squared
233
255
  end
234
256
  numtype = [
235
257
  [i, /\A\d+\z/],
236
- [f, /\A\d*(?:\.\d+)?\z/],
258
+ [f, /\A(\d+(\.\d*)?|\d*\.\d+)\z/],
237
259
  [si, /\A-?\d+\z/]
238
260
  ].freeze
239
261
  numcheck = ->(k, v) { numtype.any? { |flag, pat| flag.include?(k) && pat.match?(v) } }
@@ -252,23 +274,27 @@ module Squared
252
274
  if opt =~ OPT_VALUE
253
275
  key = $1
254
276
  val = $2
277
+ if val =~ /\A(["'])(.+)\1\z/
278
+ val = $2
279
+ double = $1 == '"'
280
+ end
255
281
  merge = m.include?(key)
256
282
  if e.include?(key)
257
- add shell_option(key, val, merge: merge)
283
+ add shell_option(key, val, double: double, merge: merge)
258
284
  elsif q.include?(key)
259
- add quote_option(key, val, double: qq.include?(key), merge: merge)
285
+ add quote_option(key, val, double: double || qq.include?(key), merge: merge)
260
286
  elsif p.include?(key)
261
- if val.match?(/\A(["']).+\1\z/)
262
- add shell_option(key, val, escape: false, merge: merge)
287
+ if !double.nil?
288
+ add shell_option(key, val, double: double, merge: merge, escape: false)
263
289
  elsif path
264
290
  add quote_option(key, path + val, merge: merge)
265
291
  else
266
292
  push opt
267
293
  end
268
294
  elsif b.include?(key) || (bl.include?(key) && %w[true false].include?(val)) || numcheck.call(key, val)
269
- add basic_option(key, val, merge: merge)
295
+ add basic_option(key, val, double: double, merge: merge)
270
296
  elsif merge
271
- add basic_option(key, val, merge: true)
297
+ add basic_option(key, val, double: double, merge: true)
272
298
  else
273
299
  push opt
274
300
  end
@@ -236,7 +236,7 @@ module Squared
236
236
 
237
237
  def repo_run(cmd, exception: false)
238
238
  puts log_message(Logger::INFO, cmd, subject: main, hint: root) if verbose
239
- Common::System.shell(cmd, chdir: root, exception: exception)
239
+ Common::System.shell(cmd, chdir: root, exception: exception || %w[1 true].include?(env('REPO_FAIL')))
240
240
  end
241
241
 
242
242
  def repo_bin
@@ -235,8 +235,9 @@ module Squared
235
235
  already_invoked? parallel, val
236
236
  end
237
237
 
238
- def exclude?(key, empty = false)
239
- @exclude.include?(key) || (empty && (!@data.key?(key) || @data[key].empty?))
238
+ def exclude?(key, fallback = false, empty: nil)
239
+ fallback = empty unless empty.nil?
240
+ @exclude.include?(key) || (fallback && (!@data.key?(key) || @data[key].empty?))
240
241
  end
241
242
 
242
243
  private
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.5.25
4
+ version: 0.5.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
126
  requirements: []
127
- rubygems_version: 4.0.10
127
+ rubygems_version: 4.0.21
128
128
  specification_version: 4
129
129
  summary: Rake task generator for managing multi-language workspaces.
130
130
  test_files: []