squared 0.5.5 → 0.5.7

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: e2f535f6c08d8ee1abce8aeefe9f0bd9ead9af0c6ef8cf3925561b1235606017
4
- data.tar.gz: 2517079e95af88ddcb835c564b7c4e0d429823ca1bde22a403afa54e2cba56fd
3
+ metadata.gz: a2f2ae101197ffdfdc4f744db59b842e2d1d7f333f9fd2f450ea94aa89a57dcd
4
+ data.tar.gz: b935b9e2787c79ea413e3449df1ba53e524928f0f1a48e90639147c91a945e43
5
5
  SHA512:
6
- metadata.gz: 07da4a2cb18fdf2a2aef060a60e03a1dba007937ae4300abb29aee8708b9be5d16472f09a6e9762aead5ad99de66ef1724c8be3842a4039b94ed73eacfa1ada4
7
- data.tar.gz: 86c0b904ce9aa176a3aa1a7950e44a5b4e178adac6387a3aa25773ed680c07d567249ed593b4389376598aca05800e5bfce304d02b1c7ff858e4abb8733d5320
6
+ metadata.gz: 982f19b327aa713258196aeaa3514edbc685840f838cc25eef01c7fef812807c9ac089b67d0145e6d6ee70ee1f57620b5254b9fe23bf6315a40a8d8dfa9a9816
7
+ data.tar.gz: 59ba49e317403c120081d842afb0e9747a63b79669bd852fa064e09da51176a3bdcbad973b7c64b771a1ccb8ac58654918d830719c8700610c5de07fb7096d07
data/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.7] - 2025-09-14
4
+
5
+ ### Fixed
6
+
7
+ - See `0.4.20`.
8
+
9
+ ## [0.4.20] - 2025-09-14
10
+
11
+ ### Changed
12
+
13
+ - Project banners when requested return consistent arguments.
14
+
15
+ ### Fixed
16
+
17
+ - Workspace global as command alias used undefined parameter.
18
+ - Python did not separate dependency manager and build backend.
19
+ - Gem command build did not validate gemspec was located.
20
+ - Project class Ruby used glob methods not available in Ruby 2.4.
21
+ - Shell options support using boolean as values.
22
+ - Git command merge action commit failed when using interactive menu.
23
+ - NPM command line options did not support boolean flags.
24
+
25
+ ## [0.5.6] - 2025-08-30
26
+
27
+ ### Added
28
+
29
+ - Docker command compose parameter services is interactive.
30
+ - Workspace with public method has conditional pass parameter.
31
+
32
+ ## [0.4.19] - 2025-08-30
33
+
34
+ ### Added
35
+
36
+ - Docker command options were updated to 28.3.
37
+ - Docker command compose action down was implemented.
38
+ - Docker containers conflicting with options can be prefixed with colon.
39
+ - Git command stash action push option message is interactive.
40
+ - Repo commands init and sync inherit any positional options.
41
+
42
+ ### Fixed
43
+
44
+ - Docker did not ignore pre-defined file with COMPOSE_FILE.
45
+ - Docker did not support multiple config files.
46
+ - Repo did not transfer arguments to supplement tasks.
47
+ - Node public method version caused a recursive loop.
48
+ - Node command bump action minor without major was revised.
49
+
3
50
  ## [0.5.5] - 2025-08-23
4
51
 
5
52
  ### Added
@@ -17,7 +64,7 @@
17
64
 
18
65
  - Git command commit did not check for pushes with nothing staged.
19
66
  - Git command submodule did not include name of command.
20
- - Shellwords method shellsplit was missing from String class.
67
+ - Shellwords method shellsplit was missing from String class.
21
68
 
22
69
  ## [0.4.18] - 2025-08-23
23
70
 
@@ -33,7 +80,7 @@
33
80
  - Workspace pipe and verbose interprets $DEBUG AND $VERBOSE modes.
34
81
  - Git response status did not check for STDIN stream.
35
82
  - Common format method puts_oe was renamed log_console.
36
- - Global task git:all is disabled for single project workspaces.
83
+ - Global task git:all is disabled for single project workspaces.
37
84
 
38
85
  ## [0.3.14] - 2025-08-23
39
86
 
@@ -1000,12 +1047,17 @@
1000
1047
 
1001
1048
  - Changelog was created.
1002
1049
 
1050
+ [0.5.7]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.7
1051
+ [0.5.6]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.6
1003
1052
  [0.5.5]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.5
1004
1053
  [0.5.4]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.4-ruby
1005
1054
  [0.5.3]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.3-ruby
1006
1055
  [0.5.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.2-ruby
1007
1056
  [0.5.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.1-ruby
1008
1057
  [0.5.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.0-ruby
1058
+ [0.4.20]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.20
1059
+ [0.4.19]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.19
1060
+ [0.4.18]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.18
1009
1061
  [0.4.17]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.17-ruby
1010
1062
  [0.4.16]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.16-ruby
1011
1063
  [0.4.15]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.15-ruby
@@ -159,7 +159,8 @@ module Squared
159
159
  when Logger::WARN then :warn
160
160
  when Logger::ERROR then :error
161
161
  when Logger::FATAL then :fatal
162
- else :unknown end
162
+ else :unknown
163
+ end
163
164
  else
164
165
  level.to_s.downcase.to_sym
165
166
  end
@@ -78,7 +78,7 @@ module Squared
78
78
  a = '--'
79
79
  b = '='
80
80
  end
81
- "#{a}#{flag}#{if val
81
+ "#{a}#{flag}#{unless val.nil?
82
82
  "#{b}#{if escape
83
83
  shell_escape(val, quote: quote, double: double, override: override)
84
84
  elsif quote
@@ -98,8 +98,8 @@ module Squared
98
98
 
99
99
  def shell_bin(name, env: true)
100
100
  key = name.upcase
101
- shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name,
102
- option: false, force: false)
101
+ shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name, option: false, force: false,
102
+ double: true)
103
103
  end
104
104
 
105
105
  def line_width(lines)
@@ -63,10 +63,9 @@ module Squared
63
63
  files.clear
64
64
  items.each do |file|
65
65
  if file.exist?
66
- if file.symlink?
67
- next unless force
68
- else
66
+ if !file.symlink?
69
67
  files << file
68
+ elsif !force
70
69
  next
71
70
  end
72
71
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.5.5'
4
+ VERSION = '0.5.7'
5
5
  end
@@ -179,7 +179,9 @@ module Squared
179
179
  self
180
180
  end
181
181
 
182
- def with(*val, group: nil, **kwargs, &blk)
182
+ def with(*val, pass: false, group: nil, **kwargs, &blk)
183
+ return self if pass == true || (pass && Array(pass).map(&:to_s).any? { |s| respond_to?(s) && __send__(s) })
184
+
183
185
  @group = nil
184
186
  @ref = nil
185
187
  @withargs = kwargs.empty? ? nil : kwargs
@@ -104,6 +104,7 @@ module Squared
104
104
  @ref = []
105
105
  @children = []
106
106
  @events = hashobj.update({ first: first, last: last, error: error })
107
+ @as = hashobj
107
108
  @envname = env_key(@name).freeze
108
109
  @desc = (@name.include?(':') ? @name.split(':').join(ARG[:SPACE]) : @name).freeze
109
110
  @parent = nil
@@ -274,9 +275,9 @@ module Squared
274
275
  -1
275
276
  elsif h.any? { |val| e.include?(val) }
276
277
  1
277
- elsif e.any? { |val| f.include?(val) }
278
+ elsif e.any? { |val| f.include?(val) } # rubocop:disable Lint/DuplicateBranch
278
279
  -1
279
- elsif f.any? { |val| e.include?(val) }
280
+ elsif f.any? { |val| e.include?(val) } # rubocop:disable Lint/DuplicateBranch
280
281
  1
281
282
  elsif @index >= 0 && (i = other.instance_variable_get(:@index)) >= 0
282
283
  @index <=> i
@@ -336,10 +337,10 @@ module Squared
336
337
  out, done = graph(args, out: [])
337
338
  out.map! do |val|
338
339
  done.each_with_index do |proj, i|
339
- if val.match?(/ #{Regexp.escape(proj.name)}(?:@\d|\z)/)
340
- val += " (#{i.succ})"
341
- break
342
- end
340
+ next unless val.match?(/ #{Regexp.escape(proj.name)}(?:@\d|\z)/)
341
+
342
+ val += " (#{i.succ})"
343
+ break
343
344
  end
344
345
  val
345
346
  end
@@ -387,7 +388,9 @@ module Squared
387
388
  args.extras
388
389
  else
389
390
  version, opts = choice_index('Select a version',
390
- @asdf[1].children.map(&:basename).push('latest'),
391
+ @asdf[1].children
392
+ .map(&:basename)
393
+ .append('latest', 'system'),
391
394
  force: true, accept: [['Confirm?', false, true]],
392
395
  values: ['Options'])
393
396
  OptionPartition.strip(opts)
@@ -505,7 +508,7 @@ module Squared
505
508
  else
506
509
  next unless respond_to?(:compose)
507
510
 
508
- cmd << a if (a = compose(as_get(b), d, script: true, args: e, from: from))
511
+ cmd << a if (a = compose(as_get(b, from), d, script: true, args: e, from: from))
509
512
  end
510
513
  var.update(c) if c.is_a?(Hash)
511
514
  end
@@ -514,7 +517,7 @@ module Squared
514
517
  cmd, opts, var, flags, extra = args
515
518
  end
516
519
  if cmd
517
- cmd = as_get cmd
520
+ cmd = as_get(cmd, from)
518
521
  opts = compose(opts, script: false) if opts && respond_to?(:compose)
519
522
  flags = append_hash(flags).join(' ') if flags.is_a?(Hash)
520
523
  case opts
@@ -531,7 +534,7 @@ module Squared
531
534
  else
532
535
  return unless (opts || extra) && respond_to?(:compose)
533
536
 
534
- cmd = compose(as_get(opts), flags, script: true, args: extra, from: from)
537
+ cmd = compose(as_get(opts, from), flags, script: true, args: extra, from: from)
535
538
  from = :script if from == :run && script?
536
539
  end
537
540
  run(cmd, var, sync: sync, from: from, banner: banner)
@@ -845,9 +848,8 @@ module Squared
845
848
  end
846
849
 
847
850
  def as(cmd, script, to = nil)
848
- script = { "#{script}": to } if to
849
- data = (@as ||= {})[cmd.to_sym] ||= {}
850
- script.each { |key, val| data[key.to_s] = val }
851
+ data = @as[cmd.to_sym]
852
+ (to ? [[script, to]] : script).each { |key, val| data[key.to_s] = val }
851
853
  self
852
854
  end
853
855
 
@@ -2043,10 +2045,8 @@ module Squared
2043
2045
  end
2044
2046
  end
2045
2047
 
2046
- def as_get(val)
2047
- return unless val
2048
-
2049
- @global && (ret = @as && @as[from] && @as[from][val]) ? ret : val
2048
+ def as_get(val, from)
2049
+ (@global && @as[from][val]) || val
2050
2050
  end
2051
2051
 
2052
2052
  def task_build(keys)
@@ -2136,8 +2136,8 @@ module Squared
2136
2136
  workspace.series.name_get(action).yield_self { |name| name != action && invoked_sync?(name) }
2137
2137
  end
2138
2138
 
2139
- def success?(ret)
2140
- ret == true && stdout? && banner?
2139
+ def success?(ret, display = true)
2140
+ ret == true && display && stdout? && banner?
2141
2141
  end
2142
2142
 
2143
2143
  def banner?
@@ -4,7 +4,7 @@ module Squared
4
4
  module Workspace
5
5
  module Project
6
6
  class Docker < Base
7
- COMPOSEFILE = %w[compose.yaml compose.yml docker-compose.yaml compose.yml docker-compose.yml].freeze
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
9
  DIR_DOCKER = (COMPOSEFILE + BAKEFILE).freeze
10
10
  OPT_DOCKER = {
@@ -12,56 +12,57 @@ module Squared
12
12
  tlskey=p].freeze,
13
13
  buildx: {
14
14
  common: %w[builder=b D|debug],
15
- build: %w[load pull push add-host=q annotation=q attest=q build-arg=qq ent=q iidfile=p label=q a-file=p
16
- network=b no-cache-filter=b o|output=q platform=b q|quiet secret=qq shm-size=b ssh=qq t|tag=b
17
- target=b ulimit=q].freeze,
18
- bake: %w[load print pull push list=q metadata-file=p set=q].freeze,
19
- shared: %w[check no-cache allow=q call=b? f|file=p progress=b provenance=q sbom=q].freeze
15
+ build: %w[add-host=q annotation=q attest=q build-arg=qq build-context=qq cache-from=q cache-to=q
16
+ cgroup-parent=b ent=q iidfile=p label=q a-file=p network=b no-cache-filter=b o|output=q platform=b
17
+ q|quiet secret=qq shm-size=b ssh=qq t|tag=b target=b ulimit=q].freeze,
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
20
21
  }.freeze,
21
22
  compose: {
22
- common: %w[all-resources compatibility dry-run ansi|b env-file=p f|file=p parallel=b profile=b progress=b
23
+ common: %w[all-resources compatibility dry-run ansi|b env-file=p f|file=p parallel=n profile=b progress=b
23
24
  project-directory=p p|project-name=e].freeze,
24
- build: %w[check no-cache pull push with-dependencies q|quiet build-arg=qq builder=b m|memory=b
25
- ssh=qq].freeze,
26
- exec: %w[dry-run privileged d|detach e|env=qq index=i T|no-TTY=b? user=e w|workdir=q].freeze,
27
- run: %w[build dry-run no-deps quiet-pull remove-orphans rm P|service-ports use-aliases cap-add=b cap-drop=b
28
- d|detach entrypoint=q e|env=qq i|interactive=b? l|label=q name=b T|no-TTY=b? p|publish=e pull=b
29
- u|user=e v|volume=q w|workdir=q].freeze,
30
- up: %w[y abort-on-container-exit abort-on-container-failure always-recreate-deps attach-dependencies build
31
- d|detach dry-run force-recreate menu no-build no-color no-deps no-log-prefix no-recreate no-start
32
- quiet-pull remove-orphans V|renew-anon-volumes timestamps wait w|watch attach=b exit-code-from=b
33
- no-attach=b pull=b scale=i t|timeout=i wait-timeout=i].freeze
25
+ build: %w[check no-cache print pull push with-dependencies q|quiet build-arg=qq builder=b m|memory=b
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,
28
+ run: %w[build d|detach no-deps q|quiet quiet-build quiet-pull remove-orphans rm P|service-ports use-aliases
29
+ cap-add=b cap-drop=b q e|env=qq env-from-file=p i|interactive=b? l|label=q name=b T|no-TTY=b?
30
+ p|publish=e pull=b u|user=e v|volume=q w|workdir=q].freeze,
31
+ up: %w[abort-on-container-exit abort-on-container-failure always-recreate-deps attach-dependencies build
32
+ d|detach force-recreate menu no-build no-color no-deps no-log-prefix no-recreate no-start quiet-build
33
+ quiet-pull remove-orphans V|renew-anon-volumes timestamps wait w|watch y|yes attach=b
34
+ exit-code-from=b no-attach=b pull=b scale=i t|timeout=i wait-timeout=i].freeze,
35
+ down: %w[remove-orphans v|volumes rmi=b t|timeout=i].freeze
34
36
  }.freeze,
35
37
  container: {
36
38
  create: %w[init i|interactive no-healthcheck oom-kill-disable privileged P|publish-all q|quiet read-only
37
- rm runtime t|tty use-api-socket io-maxbandwidth=b io-maxiops=b add-host=q annotation=q
38
- a|attach=b blkio-weight=i blkio-weight-device=i cap-add=b cap-drop=b cgroup-parent=b cgroupns=b
39
- cidfile=p device=q device-cgroup-rule=q device-read-bps=q device-read-iops=q device-write-bps=q
39
+ rm runtime t|tty use-api-socket io-maxbandwidth=b io-maxiops=b add-host=q annotation=q a|attach=b
40
+ blkio-weight=i blkio-weight-device=i cap-add=b cap-drop=b cgroup-parent=b cgroupns=b cidfile=p
41
+ device=q device-cgroup-rule=q device-read-bps=q device-read-iops=q device-write-bps=q
40
42
  device-write-iops=q disable-content-trust=b? dns=e dns-option=e dns-search=e domainname=b
41
- entrypoint=q e|env=qq env-file=p expose=e gpus=q group-add=b health-cmd=q health-interval=b
42
- health-retries=i health-start-interval=b health-start-period=b health-timeout=b h|hostname=e ip=b
43
- ip6=e ipc=b isolation=b kernel-memory=b l|label=q label-file=p link=b link-local-ip=b
44
- log-driver=b log-opt=q mac-address=e m|memory=b memory-reservation=b memory-swap=n
45
- memory-swappiness=n mount=qq name=b network=b network-alias=b oom-score-adj=b pid=b pids-limit=n
46
- platform=b p|publish=e pull=b restart=b runtime=b security-opt=q shm-size=b stop-signal=b
47
- stop-timeout=i storage-opt=q sysctl=q tmpfs=q ulimit=q u|user=b userns=b uts=b v|volume=q
48
- volume-driver=b volumes-from=b w|workdir=q].freeze,
43
+ entrypoint=q e|env=qq env-file=p expose=e gpus=q group-add=b health-cmd=q health-interval=b ip6=e
44
+ ipc=b isolation=b kernel-memory=b l|label=q label-file=p link=b link-local-ip=b log-driver=b
45
+ log-opt=q mac-address=e m|memory=b memory-reservation=b memory-swap=n memory-swappiness=n
46
+ mount=qq name=b network=b network-alias=b oom-score-adj=b pid=b pids-limit=n platform=b
47
+ p|publish=e pull=b restart=b runtime=b security-opt=q shm-size=b stop-signal=b stop-timeout=i
48
+ storage-opt=q sysctl=q tmpfs=q ulimit=q u|user=b userns=b uts=b v|volume=q volume-driver=b
49
+ volumes-from=b w|workdir=q].freeze,
49
50
  run: %w[d|detach detach-keys=q sig-proxy=b?].freeze,
50
- exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p user=e
51
- w|workdir=q].freeze,
52
51
  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
52
  cpuset-cpus=b cpuset-mems=b m|memory=b memory-reservation=b memory-swap=b pids-limit=n
54
53
  restart=q].freeze,
54
+ exec: %w[d|detach i|interactive privileged t|tty detach-keys=q e|env=qq env-file=p user=e
55
+ w|workdir=q].freeze,
55
56
  commit: %w[a|author=q c|change=q m|message=q pause=b?].freeze,
56
57
  inspect: %w[s|size f|format=q].freeze,
57
58
  start: %w[a|attach i|interactive detach-keys=q].freeze,
58
59
  stop: %w[s|signal=b t|time=i t|timeout=i].freeze,
59
60
  restart: %w[s|signal=b t|time=i t|timeout=i].freeze,
60
61
  kill: %w[s|signal=b].freeze,
61
- stats: %w[no-trunc format|q].freeze
62
+ stats: %w[a|all no-stream no-trunc format|q].freeze
62
63
  }.freeze,
63
64
  image: {
64
- list: %w[a|all digests no-trunc f|filter=q format=q].freeze,
65
+ list: %w[a|all q|quiet digests no-trunc tree f|filter=q format=q].freeze,
65
66
  push: %w[a|all-tags disable-content-trust=b? platform=b q|quiet].freeze,
66
67
  rm: %w[f|force no-prune platform=b].freeze,
67
68
  save: %w[o|output=p platform=b].freeze
@@ -96,7 +97,7 @@ module Squared
96
97
 
97
98
  subtasks({
98
99
  'build' => %i[tag context].freeze,
99
- 'compose' => %i[build run exec up].freeze,
100
+ 'compose' => %i[build run exec up down].freeze,
100
101
  'bake' => %i[build check].freeze,
101
102
  'image' => %i[list rm push tag save].freeze,
102
103
  'container' => %i[run create exec update commit inspect diff start stop restart pause unpause top stats kill
@@ -151,7 +152,7 @@ module Squared
151
152
 
152
153
  case flag
153
154
  when :build
154
- format_desc action, flag, ':?,opts*,target*,context?'
155
+ format_desc action, flag, 'opts*,target*,context?|:'
155
156
  task flag do |_, args|
156
157
  args = args.to_a
157
158
  if args.first == ':'
@@ -171,13 +172,13 @@ module Squared
171
172
  break unless compose?
172
173
 
173
174
  case flag
174
- when :build, :up
175
- format_desc action, flag, 'opts*,service*'
175
+ when :build, :up, :down
176
+ format_desc action, flag, 'opts*,service*|:'
176
177
  task flag do |_, args|
177
178
  compose! flag, args.to_a
178
179
  end
179
180
  when :exec, :run
180
- format_desc action, flag, "service,command#{flag == :exec ? '' : '?'}|:,args*,opts*"
181
+ format_desc action, flag, "service|:,command#{flag == :exec ? '' : '?'}|::,args*,opts*"
181
182
  task flag, [:service] do |_, args|
182
183
  service = param_guard(action, flag, args: args, key: :service)
183
184
  compose!(flag, args.extras, service: service)
@@ -186,7 +187,7 @@ module Squared
186
187
  when 'container'
187
188
  case flag
188
189
  when :exec, :commit
189
- format_desc(action, flag, flag == :exec ? 'id/name,opts*,args+' : 'id/name,tag?,opts*')
190
+ format_desc(action, flag, flag == :exec ? 'id/name,opts*,args+|:' : 'id/name,tag?,opts*')
190
191
  task flag, [:id] do |_, args|
191
192
  if flag == :exec && !args.id
192
193
  choice_command flag
@@ -196,7 +197,7 @@ module Squared
196
197
  end
197
198
  end
198
199
  when :run, :create
199
- format_desc action, flag, 'image,opts*,args*'
200
+ format_desc action, flag, 'image,opts*,args*|:'
200
201
  task flag, [:image] do |_, args|
201
202
  if args.image
202
203
  container(flag, args.extras, id: args.image)
@@ -222,7 +223,8 @@ module Squared
222
223
  format_desc(action, flag, case flag
223
224
  when :rm, :save then 'id*,opts*'
224
225
  when :tag then 'version?'
225
- else 'opts*,args*' end)
226
+ else 'opts*,args*'
227
+ end)
226
228
  task flag do |_, args|
227
229
  args = args.to_a
228
230
  if args.empty? && flag != :list
@@ -259,12 +261,11 @@ module Squared
259
261
 
260
262
  ret = docker_session
261
263
  if from == :run
262
- case (n = filetype)
263
- when 1, 2
264
+ if bake?(n = filetype)
264
265
  ret << 'buildx' << 'bake'
265
266
  append_file n
266
267
  from = :bake
267
- when 3, 4
268
+ elsif compose?(n)
268
269
  ret << 'compose' << 'build'
269
270
  append_file n
270
271
  from = :compose
@@ -335,7 +336,7 @@ module Squared
335
336
  op.push(val)
336
337
  end
337
338
  end
338
- op.append(args, escape: true)
339
+ op.append(args, escape: true, strip: /^:/)
339
340
  contextdir context if context
340
341
  end
341
342
  end
@@ -348,15 +349,27 @@ module Squared
348
349
  op = OptionPartition.new(opts, OPT_DOCKER[:compose][:common], cmd, project: self)
349
350
  append_file filetype unless op.arg?('f', 'file')
350
351
  op << flag
351
- op.parse(OPT_DOCKER[:compose][flag])
352
- from = :"compose:#{flag}"
353
- case flag
354
- when :build, :up
355
- op.append(escape: true)
356
- when :exec, :run
357
- append_command flag, service, op.extras
352
+ op.parse(OPT_DOCKER[:compose].fetch(flag, []))
353
+ multiple = case flag
354
+ when :build, :up, :down then true
355
+ else false
356
+ end
357
+ if op.remove(':') || service == ':'
358
+ keys = Set.new
359
+ read_composefile('services', target: op.values_of('f', 'file')) { |data| keys.merge(data.keys) }
360
+ service = unless keys.empty?
361
+ choice_index('Add services', keys, multiple: multiple, force: !multiple,
362
+ attempts: multiple ? 1 : 5)
363
+ end
358
364
  end
359
- run(from: from)
365
+ if multiple
366
+ op.concat(service) if service
367
+ op.append(delim: true, escape: true, strip: /^:/)
368
+ else
369
+ raise_error('no services were found', hint: flag) unless service
370
+ append_command(flag, service, op.extras, prompt: '::')
371
+ end
372
+ run(from: :"compose:#{flag}")
360
373
  end
361
374
 
362
375
  def container(flag, opts = [], id: nil)
@@ -388,10 +401,10 @@ module Squared
388
401
  elsif all.include?(k)
389
402
  unless type
390
403
  run.each_pair do |key, val|
391
- if val.include?(k)
392
- type = key.to_s unless key == :common
393
- break
394
- end
404
+ next unless val.include?(k)
405
+
406
+ type = key.to_s unless key == :common
407
+ break
395
408
  end
396
409
  end
397
410
  case k
@@ -414,7 +427,7 @@ module Squared
414
427
  append_command(flag, id || tagmain, op.extras)
415
428
  when :update
416
429
  raise_error('missing container', hint: flag) if op.empty?
417
- op.append(escape: true)
430
+ op.append(escape: true, strip: /^:/)
418
431
  when :commit
419
432
  latest = op.shift || tagmain
420
433
  cmd << id << latest
@@ -467,7 +480,7 @@ module Squared
467
480
  end
468
481
  return
469
482
  else
470
- op.append(escape: true)
483
+ op.append(escape: true, strip: /^:/)
471
484
  end
472
485
  end
473
486
  run(from: from)
@@ -518,7 +531,7 @@ module Squared
518
531
  list_image(flag, docker_output('image ls -a'), from: from) do |val|
519
532
  op << val
520
533
  if flag == :tag
521
- op << tagname("#{@project}:#{op.extras.first}")
534
+ op << tagname("#{@project}:#{op.first}")
522
535
  break
523
536
  end
524
537
  end
@@ -544,7 +557,7 @@ module Squared
544
557
 
545
558
  def network(flag, opts = [], target: nil)
546
559
  cmd, opts = docker_session('network', flag, opts: opts)
547
- op = OptionPartition.new(opts, OPT_DOCKER[:network][flag], cmd, project: self)
560
+ op = OptionPartition.new(opts, OPT_DOCKER[:network].fetch(flag, []), cmd, project: self)
548
561
  op.clear
549
562
  from = :"network:#{flag}"
550
563
  list_image(flag, docker_output('ps -a'), from: from) do |img|
@@ -561,10 +574,14 @@ module Squared
561
574
  end
562
575
 
563
576
  def compose?(file = dockerfile)
577
+ return file == 3 || file == 4 if file.is_a?(Numeric)
578
+
564
579
  COMPOSEFILE.include?(File.basename(file))
565
580
  end
566
581
 
567
582
  def bake?(file = dockerfile)
583
+ return file == 1 || file == 2 if file.is_a?(Numeric)
584
+
568
585
  BAKEFILE.include?(File.basename(file))
569
586
  end
570
587
 
@@ -585,6 +602,21 @@ module Squared
585
602
 
586
603
  private
587
604
 
605
+ def read_composefile(*keys, target: nil)
606
+ require 'yaml'
607
+ target = ENV['COMPOSE_FILE']&.split(workspace.windows? ? ';' : ':') if !target || target.empty?
608
+ Array(target || dockerfile).each do |val|
609
+ doc = YAML.load_file(path + val)
610
+ if keys.empty?
611
+ yield doc
612
+ elsif (data = doc.dig(*keys))
613
+ yield data
614
+ end
615
+ rescue StandardError => e
616
+ log.debug e
617
+ end
618
+ end
619
+
588
620
  def docker_session(*cmd, opts: nil)
589
621
  return session('docker', *cmd) unless opts
590
622
 
@@ -597,9 +629,9 @@ module Squared
597
629
  session('docker', *cmd, main: false, options: false, **kwargs)
598
630
  end
599
631
 
600
- def append_command(flag, val, list, target: @session)
601
- if list.delete(':')
602
- list << readline('Enter command [args]', force: true)
632
+ def append_command(flag, val, list, target: @session, prompt: ':')
633
+ if list.delete(prompt)
634
+ list << readline('Enter command [args]', force: flag == :exec)
603
635
  elsif (args = env('DOCKER_ARGS'))
604
636
  list << args
605
637
  end
@@ -616,13 +648,22 @@ module Squared
616
648
  end
617
649
 
618
650
  def append_file(type, target: @session)
619
- return unless type == 2 || type == 4 || @file.is_a?(Array)
651
+ return if ENV['COMPOSE_FILE'] && compose?(type)
620
652
 
653
+ unless @file.is_a?(Array)
654
+ case type
655
+ when 2, 4
656
+ return
657
+ when 3
658
+ return unless COMPOSEFILE.map { |val| path + val }.select(&:exist?).size > 1
659
+ end
660
+ end
621
661
  files = Array(@file).map { |val| quote_option('file', path + val) }
622
662
  if target.is_a?(Set)
623
- target.merge(files)
663
+ opts = target.to_a.insert(2, *files)
664
+ target.clear.merge(opts)
624
665
  else
625
- target.concat(files)
666
+ target.insert(2, *files)
626
667
  end
627
668
  end
628
669
 
@@ -788,7 +829,7 @@ module Squared
788
829
  bake?(val) ? 1 : 2
789
830
  when '.yml', '.yaml'
790
831
  if compose?(val)
791
- path.children.any? { |file| bake?(file) } ? 1 : 3
832
+ @only&.include?('compose') || path.children.none? { |file| bake?(file) } ? 3 : 1
792
833
  else
793
834
  4
794
835
  end
@@ -503,10 +503,11 @@ module Squared
503
503
  end
504
504
  when 'stash'
505
505
  format_desc(action, flag, 'opts*', after: case flag
506
- when :push then 'pathspec*'
506
+ when :push then 'pathspec*,:'
507
507
  when :branch then 'name,stash?|:'
508
508
  when :clear, :list, :all then nil
509
- else 'stash?|:' end)
509
+ else 'stash?|:'
510
+ end)
510
511
  task flag do |_, args|
511
512
  stash flag, args.to_a
512
513
  end
@@ -544,7 +545,7 @@ module Squared
544
545
  commit1 = commithead args.commit1
545
546
  if commit1
546
547
  commit2 = commithead param_guard(action, flag, args: args, key: :commit2)
547
- args = args.extras.to_a
548
+ args = args.extras
548
549
  range = [commit1, commit2]
549
550
  else
550
551
  range, opts, refs = choice_commit(multiple: view ? true : 2, values: %w[Options Pathspec])
@@ -751,11 +752,12 @@ module Squared
751
752
  args = args.extras
752
753
  else
753
754
  commit, mode = choice_commit(values: ['Mode [mixed|soft|hard|N]'])
754
- args = args.extras.to_a.concat(case mode&.downcase
755
- when 'h', 'hard' then ['hard']
756
- when 's', 'soft' then ['soft']
757
- when 'n', 'N' then ['mixed', 'N']
758
- else ['mixed'] end)
755
+ args = args.extras.concat(case mode&.downcase
756
+ when 'h', 'hard' then ['hard']
757
+ when 's', 'soft' then ['soft']
758
+ when 'n', 'N' then ['mixed', 'N']
759
+ else ['mixed']
760
+ end)
759
761
  end
760
762
  print_success if success?(reset(flag, args, commit: commit))
761
763
  end
@@ -921,7 +923,8 @@ module Squared
921
923
  before = case flag
922
924
  when :blame then 'file'
923
925
  when :mv then 'source+,destination'
924
- when :revert then 'commit+' end
926
+ when :revert then 'commit+'
927
+ end
925
928
  format_desc(action, flag, 'opts*', before: before, after: case flag
926
929
  when :add
927
930
  'pathspec*,pattern*'
@@ -975,6 +978,7 @@ module Squared
975
978
  elsif !(force = confirm('Force checkout?', 'N'))
976
979
  return
977
980
  end
981
+ printsucc
978
982
  end
979
983
  op = OptionPartition.new(opts, OPT_GIT[:pull], cmd, project: self, no: OPT_GIT[:no][:pull])
980
984
  reg = if op.empty?
@@ -1024,7 +1028,7 @@ module Squared
1024
1028
  return unless upstream
1025
1029
 
1026
1030
  op = OptionPartition.new(opts, OPT_GIT[:rebase], cmd, project: self, no: OPT_GIT[:no][:rebase])
1027
- cmd << upstream
1031
+ op << upstream
1028
1032
  append_head op.shift
1029
1033
  op.clear(pass: false)
1030
1034
  when :onto
@@ -1105,6 +1109,7 @@ module Squared
1105
1109
  op = OptionPartition.new(opts, list, cmd, project: self, no: no, first: flag == :push ? matchpathspec : nil)
1106
1110
  case flag
1107
1111
  when :push
1112
+ op.append?('message', readline('Enter message', force: true), force: true) if op.remove(':')
1108
1113
  append_pathspec op.extras
1109
1114
  when :pop, :apply, :drop, :branch
1110
1115
  if op.remove(':')
@@ -1112,7 +1117,7 @@ module Squared
1112
1117
  if op.empty?
1113
1118
  values = [['Branch name', true]]
1114
1119
  else
1115
- op << op.pop
1120
+ op << op.shift
1116
1121
  end
1117
1122
  end
1118
1123
  out = choice_index('Choose a stash', git_spawn('stash list', stdout: false),
@@ -1123,7 +1128,7 @@ module Squared
1123
1128
  op << out
1124
1129
  end
1125
1130
  elsif !op.empty?
1126
- op << op.pop
1131
+ op << op.shift
1127
1132
  elsif flag == :branch
1128
1133
  raise_error 'no branch name'
1129
1134
  end
@@ -1265,7 +1270,6 @@ module Squared
1265
1270
  end
1266
1271
  when :patch
1267
1272
  cmd << '--patch'
1268
- append_pathspec(refs, pass: false)
1269
1273
  when :undo
1270
1274
  cmd << '--hard HEAD@{1}'
1271
1275
  ref = false
@@ -1481,15 +1485,16 @@ module Squared
1481
1485
 
1482
1486
  def merge(flag, opts = [], command: nil, branch: nil)
1483
1487
  cmd, opts = git_session('merge', opts: opts)
1488
+ display = false
1484
1489
  case flag
1485
1490
  when :commit, :'no-commit'
1486
1491
  op = OptionPartition.new(opts, OPT_GIT[:merge], cmd, project: self, no: OPT_GIT[:no][:merge])
1487
- raise_error 'no branch/commit' if op.empty?
1488
1492
  op << "--#{flag}" << '--'
1489
1493
  if branch
1490
1494
  op << branch
1491
1495
  op.clear(pass: false)
1492
1496
  else
1497
+ raise_error 'no branch/commit' if op.empty?
1493
1498
  append_commit(*op.extras)
1494
1499
  end
1495
1500
  else
@@ -1500,8 +1505,9 @@ module Squared
1500
1505
  return unless VAL_GIT[:merge][:send].include?(command)
1501
1506
 
1502
1507
  cmd << "--#{command}"
1508
+ display = command == 'abort'
1503
1509
  end
1504
- source
1510
+ print_success if success?(source, display)
1505
1511
  end
1506
1512
 
1507
1513
  def branch(flag = nil, opts = [], refs: [], ref: nil, target: nil, remote: nil)
@@ -1736,7 +1742,8 @@ module Squared
1736
1742
  project: self, no: OPT_GIT[:no][flag], first: case flag
1737
1743
  when :blame, :revert
1738
1744
  nil
1739
- else matchpathspec end)
1745
+ else matchpathspec
1746
+ end)
1740
1747
  case flag
1741
1748
  when :blame
1742
1749
  raise_error 'no file found' unless (n = op.index { |s| (path + s).file? })
@@ -1771,8 +1778,7 @@ module Squared
1771
1778
  end
1772
1779
  return source(git_session('status -s'), banner: false) unless append_pathspec(op.extras)
1773
1780
 
1774
- verbose = flag == :add && !op.arg?('verbose')
1775
- print_success if success?(source) && verbose
1781
+ print_success if success?(source, flag == :add && !op.arg?('verbose'))
1776
1782
  return
1777
1783
  when :mv
1778
1784
  refs = projectmap op.extras
@@ -1805,9 +1811,12 @@ module Squared
1805
1811
  from = nil
1806
1812
  banner = nil
1807
1813
  else
1808
- banner = nil if banner && (multiple || !banner?)
1814
+ if banner
1815
+ banner = nil unless banner? && !multiple
1816
+ args = true
1817
+ end
1809
1818
  if cmd.respond_to?(:done)
1810
- if from.nil? && (from = cmd.drop(1).find { |val| val.match?(/\A[a-z]{1,2}[a-z\-]*\z/) })
1819
+ if from.nil? && (from = cmd.drop(1).find { |val| val.match?(/\A[a-z]{1,2}[a-z-]*\z/) })
1811
1820
  from = :"git:#{from}"
1812
1821
  end
1813
1822
  banner &&= cmd.temp { |val| val.start_with?(/--(?:work-tree|git-dir)/) }
@@ -1818,17 +1827,14 @@ module Squared
1818
1827
  log&.info cmd
1819
1828
  banner = if banner
1820
1829
  banner = (banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), '')
1821
- format_banner(hint ? "#{banner} (#{hint})" : banner, banner: true)
1830
+ format_banner(hint ? "#{banner} (#{hint})" : banner)
1822
1831
  end
1823
1832
  on :first, from
1824
1833
  begin
1825
1834
  if io
1826
- ret = if stdout
1827
- `#{cmd}`
1828
- else
1829
- banner ? [IO.popen(cmd), banner, from] : IO.popen(cmd)
1830
- end
1831
- return ret
1835
+ return `#{cmd}` if stdout
1836
+
1837
+ return args ? [IO.popen(cmd), banner || '', from] : IO.popen(cmd)
1832
1838
  elsif stdin? ? sync : stdout
1833
1839
  print_item banner unless multiple
1834
1840
  ret = `#{cmd}`
@@ -5,15 +5,17 @@ module Squared
5
5
  module Project
6
6
  class Node < Git
7
7
  OPT_NPM = {
8
- common: %w[dry-run include-workspace-root workspaces=b? w|workspace=v].freeze,
9
- install: %w[prefer-dedupe package-lock-only cpu=b libc=b os=b].freeze,
10
- install_base: %w[ignore-scripts install-links strict-peer-deps include=b omit=b install-strategy=b].freeze,
8
+ common: %w[dry-run=!? include-workspace-root=!? workspaces=!? w|workspace=v].freeze,
9
+ install: %w[prefer-dedupe=!? package-lock-only=!? audit=! bin-links=! cpu=b fund=! libc=b os=b
10
+ package-lock=!].freeze,
11
+ install_base: %w[ignore-scripts=!? install-links=!? strict-peer-deps=!? include=b omit=b
12
+ install-strategy=b].freeze,
11
13
  install_no: %w[audit bin-links fund package-lock].freeze,
12
- install_as: %w[foreground-scripts g|global no-save save save-bundle save-dev E|save-exact save-optional
13
- save-peer S|save-prod].freeze,
14
- run: %w[foreground-scripts if-present ignore-scripts script-shell=p].freeze,
14
+ install_as: %w[no-save save-bundle save-dev save-optional save-peer save-prod foreground-scripts=!?
15
+ g|global=!? S|save=!? E|save-exact=!?].freeze,
16
+ run: %w[foreground-scripts=!? if-present=!? ignore-scripts=!? script-shell=p].freeze,
15
17
  exec: %w[c|call=q package=b].freeze,
16
- pack: %w[json ignore-scripts pack-destination=p].freeze
18
+ pack: %w[json=!? pack-destination=p].freeze
17
19
  }.freeze
18
20
  OPT_PNPM = {
19
21
  common: %w[aggregate-output color no-color stream use-stderr C|dir=p loglevel=b w|workspace-root].freeze,
@@ -679,13 +681,13 @@ module Squared
679
681
  if sync
680
682
  run(from: from, sync: sync, interactive: !dryrun && "Publish #{sub_style(npmname, styles: theme[:active])}")
681
683
  else
684
+ require 'open3'
682
685
  on :first, from
683
686
  pwd_set(from: from, dryrun: dryrun) do
684
- require 'open3'
685
- banner = format_banner cmd.to_s
686
- Open3.popen2e(cmd.done) do |_, out|
687
- write_lines(out, sub: npmnotice + [pat: /^(.+)(Tarball .+)$/, styles: color(:blue), index: 2],
688
- banner: banner)
687
+ cmd = session_done cmd
688
+ Open3.popen2e(cmd) do |_, out|
689
+ write_lines(out, banner: format_banner(cmd),
690
+ sub: npmnotice + [pat: /^(.+)(Tarball .+)$/, styles: color(:bright_blue), index: 2])
689
691
  end
690
692
  end
691
693
  on :last, from
@@ -767,8 +769,8 @@ module Squared
767
769
  seg[4] &&= seg[4].succ
768
770
  else
769
771
  seg[2] = seg[2].succ
772
+ seg[4] &&= '0'
770
773
  end
771
- seg[4] = '0'
772
774
  when :patch
773
775
  seg[4] &&= seg[4].succ
774
776
  end
@@ -936,7 +938,7 @@ module Squared
936
938
  end
937
939
 
938
940
  def version
939
- self.version ||= read_packagemanager(:version)
941
+ @version ||= read_packagemanager(:version)
940
942
  end
941
943
 
942
944
  def packagename
@@ -1028,9 +1030,9 @@ module Squared
1028
1030
 
1029
1031
  def npmnotice
1030
1032
  [
1031
- { pat: /^(npm error )(code|\d+)(.+)$/, styles: color(:cyan), index: 2 },
1032
- { pat: /^(npm )(error)(.*)$/, styles: color(:red), index: 2 },
1033
- { pat: /^(npm )(notice)(.*)$/, styles: color(:cyan), index: 2 },
1033
+ { pat: /^(npm error )(code|\d+)(.+)$/, styles: color(:bright_cyan), index: 2 },
1034
+ { pat: /^(npm )(error)(.*)$/, styles: color(:bright_red), index: 2 },
1035
+ { pat: /^(npm )(notice)(.*)$/, styles: color(:bright_cyan), index: 2 },
1034
1036
  { pat: /^(npm )(.+)$/, styles: :bold }
1035
1037
  ]
1036
1038
  end
@@ -37,8 +37,8 @@ module Squared
37
37
  common: %w[I|ignore-python no-cache n|non-interactive].freeze,
38
38
  build: %w[C=bm no-clean no-isolation no-sdist no-wheel quiet verbose config-setting=q d|dest=p p|project=p
39
39
  k|skip=b].freeze,
40
- publish: %w[no-build no-very-ssl quiet S|sign skip-existing verbose ca-certs=p c|comment=q d|dest=p identity=b
41
- p|password=q p|project=p r|repository=q k|skip=b u|username=b].freeze
40
+ publish: %w[no-build no-very-ssl quiet S|sign skip-existing verbose ca-certs=p c|comment=q d|dest=p
41
+ i|identity=b P|password=q p|project=p r|repository=q k|skip=b u|username=b].freeze
42
42
  }.freeze
43
43
  OPT_HATCH = {
44
44
  common: %w[color interactive no-color no-interactive cache-dir=p config=p data-dir=p e|env=b p|project=b
@@ -306,7 +306,7 @@ module Squared
306
306
  when 'build'
307
307
  case flag
308
308
  when :poetry
309
- next unless poetry?
309
+ next unless build_backend == 'poetry.core.masonry.api'
310
310
  when :pdm
311
311
  next unless build_backend == 'pdm.backend'
312
312
  when :hatch
@@ -909,11 +909,11 @@ module Squared
909
909
  end
910
910
 
911
911
  def setuptools?
912
- build_backend ? build_backend == 'setuptools.build_meta' : dependtype == 2 || dependtype == 4
912
+ dependtype == 2 || dependtype == 4
913
913
  end
914
914
 
915
915
  def poetry?
916
- build_backend ? build_backend == 'poetry.core.masonry.api' : dependtype == 1
916
+ dependtype == 1
917
917
  end
918
918
 
919
919
  def requirements?
@@ -183,7 +183,8 @@ module Squared
183
183
  else
184
184
  format_desc(action, nil, 'opts*', before: case action
185
185
  when 'cache', 'check' then nil
186
- else 'command+' end)
186
+ else 'command+'
187
+ end)
187
188
  task action do |_, args|
188
189
  bundle(action, *args.to_a)
189
190
  end
@@ -448,7 +449,7 @@ module Squared
448
449
  def update(flag, opts = [])
449
450
  bundle_session 'update', "--#{flag}"
450
451
  append_bundle(opts, OPT_BUNDLE[:install_base] + OPT_BUNDLE[:update] + OPT_BUNDLE[:common],
451
- append: flag == :all ? nil : /\A[a-z\-]+=/)
452
+ append: flag == :all ? nil : /\A[a-z-]+=/)
452
453
  run_rb(from: :update)
453
454
  end
454
455
 
@@ -502,7 +503,7 @@ module Squared
502
503
  c < d ? -1 : 1
503
504
  end
504
505
  end
505
- .push('')
506
+ .append('')
506
507
  .each do |val|
507
508
  next unless val.empty? || File.exist?(val.sub('$HOME', Dir.home))
508
509
 
@@ -732,6 +733,7 @@ module Squared
732
733
  return
733
734
  when :build
734
735
  if op.empty?
736
+ raise_error('gemspec not found', hint: project) unless gemfile
735
737
  op.add_path(gemfile)
736
738
  else
737
739
  op.add_path(op.shift)
@@ -784,9 +786,8 @@ module Squared
784
786
  else
785
787
  op.clear
786
788
  end
787
- elsif (n = op.extras.find_index { |val| val.match?(/(\A|[a-z])@\d/) })
788
- items = op.extras.to_a
789
- name = items.delete_at(n)
789
+ elsif (n = op.index { |val| val.match?(/(\A|[a-z])@\d/) })
790
+ name = op.delete_at(n)
790
791
  if (n = name.index('@')) == 0
791
792
  pre = gemname
792
793
  ver = name[1..-1]
@@ -795,8 +796,7 @@ module Squared
795
796
  ver = name[(n + 1)..-1]
796
797
  end
797
798
  op.adjoin(pre, shell_option('version', ver))
798
- .clear(items)
799
- .reset
799
+ .clear
800
800
  elsif flag != :install
801
801
  op.adjoin
802
802
  end
@@ -861,8 +861,8 @@ module Squared
861
861
  def gemspec
862
862
  return @gemspec unless @gemspec.nil?
863
863
 
864
- @gemspec = if (file = gemfile)
865
- Gem::Specification.load(file.to_s) rescue false
864
+ @gemspec = if gemfile
865
+ Gem::Specification.load(gemfile.to_s) rescue false
866
866
  else
867
867
  false
868
868
  end
@@ -18,10 +18,14 @@ module Squared
18
18
  include Shell
19
19
  include Prompt
20
20
 
21
- def append(target, *args, delim: false, escape: false, quote: true, **)
21
+ def append(target, *args, delim: false, escape: false, quote: true, strip: nil, **)
22
22
  return if (ret = args.flatten).empty?
23
23
 
24
24
  target << '--' if delim && !target.include?('--')
25
+ if strip
26
+ pat, s = Array(strip)
27
+ ret.map! { |val| val.gsub(pat, s || '') }
28
+ end
25
29
  ret.map! { |val| escape ? shell_escape(val, quote: quote) : shell_quote(val) } if escape || quote
26
30
  if target.is_a?(Set)
27
31
  target.merge(ret)
@@ -77,9 +81,10 @@ module Squared
77
81
  def_delegators :@target, :+, :-, :<<, :any?, :none?, :include?, :add, :add?, :find, :find_all, :find_index,
78
82
  :merge, :delete, :delete?, :delete_if, :grep, :grep_v, :inspect, :to_a, :to_s
79
83
  def_delegators :@extras, :empty?, :each, :each_with_index, :partition, :dup, :first, :last, :shift, :unshift,
80
- :pop, :push, :concat, :index, :delete_at, :join, :map, :map!, :select, :reject, :size
84
+ :pop, :push, :concat, :index, :delete_at, :join, :map, :map!, :select, :select!, :reject, :size
81
85
 
82
86
  def_delegator :@extras, :delete, :remove
87
+ def_delegator :@extras, :delete_at, :remove_at
83
88
  def_delegator :@extras, :delete_if, :remove_if
84
89
 
85
90
  def initialize(opts, list, target = Set.new, project: nil, path: nil, **kwargs, &blk)
@@ -104,6 +109,7 @@ module Squared
104
109
  i = []
105
110
  f = []
106
111
  si = []
112
+ bl = []
107
113
  list.flat_map do |val|
108
114
  x, y = val.split('|', 2)
109
115
  if y
@@ -138,6 +144,8 @@ module Squared
138
144
  si << flag
139
145
  when 'v'
140
146
  @values << Regexp.escape(flag)
147
+ when '!'
148
+ bl << flag
141
149
  else
142
150
  next
143
151
  end
@@ -177,7 +185,7 @@ module Squared
177
185
  add quote_option(key, val, double: qq.include?(key), merge: merge)
178
186
  elsif p.include?(key) && path
179
187
  add quote_option(key, path + val, merge: merge)
180
- elsif b.include?(key) || numcheck.call(key, val)
188
+ elsif b.include?(key) || (bl.include?(key) && %w[true false].include?(val)) || numcheck.call(key, val)
181
189
  add basic_option(key, val, merge: merge)
182
190
  elsif merge
183
191
  add basic_option(key, val, merge: true)
@@ -212,6 +220,36 @@ module Squared
212
220
  self
213
221
  end
214
222
 
223
+ def values_of(*args, strict: true, first: false, last: false)
224
+ eq, s = strict ? ['=', '[^ ]+'] : ['(?:=| +)', '[^-][^ ]*']
225
+ grp = ["\"((?:[^\"]|(?<=\\\\)\"(?!$#{Rake::Win32.windows? ? '| ' : ''}))*)\""]
226
+ grp << "'((?:[^']|'\\\\'')*)'" unless Rake::Win32.windows?
227
+ grp << "(#{s})"
228
+ args.map! do |opt|
229
+ if opt.size == 1
230
+ /(?:\A| )-#{opt} ?([^ ]+)/
231
+ else
232
+ /(?:\A| )--#{opt + eq}(?:#{grp.join('|')})/
233
+ end
234
+ end
235
+ ret = []
236
+ target.each do |opt|
237
+ args.each do |pat|
238
+ next unless opt =~ pat
239
+
240
+ ret << ($1 || $2 || $3)
241
+ break
242
+ end
243
+ end
244
+ return ret unless first || last
245
+
246
+ if last
247
+ last.is_a?(Numeric) ? ret.last(last) : ret.last
248
+ else
249
+ first.is_a?(Numeric) ? ret.first(first) : ret.first
250
+ end
251
+ end
252
+
215
253
  def uniq(list)
216
254
  items = map { |val| nameonly(val) }
217
255
  list.reject do |val|
@@ -304,30 +342,30 @@ module Squared
304
342
  self
305
343
  end
306
344
 
307
- def append?(key, val = nil, type: nil, **kwargs)
308
- return false if arg?(key)
345
+ def reset(errors: false)
346
+ extras.clear
347
+ clear(errors: true) if errors
348
+ self
349
+ end
350
+
351
+ def append?(key, val = nil, type: nil, force: false, **kwargs)
352
+ return false unless force || !arg?(key)
309
353
 
310
354
  val = yield self if block_given?
311
355
  return false unless val
312
356
 
313
357
  type ||= :quote if kwargs.empty?
314
- op << case type
315
- when :quote
316
- quote_option(key, val)
317
- when :basic
318
- basic_option(key, val)
319
- else
320
- shell_option(key, val, **kwargs)
321
- end
358
+ add case type
359
+ when :quote
360
+ quote_option(key, val)
361
+ when :basic
362
+ basic_option(key, val)
363
+ else
364
+ shell_option(key, val, **kwargs)
365
+ end
322
366
  true
323
367
  end
324
368
 
325
- def reset(errors: false)
326
- extras.clear
327
- clear(errors: true) if errors
328
- self
329
- end
330
-
331
369
  def arg?(*args, **kwargs)
332
370
  OptionPartition.arg?(target, *args, **kwargs)
333
371
  end
@@ -117,10 +117,8 @@ module Squared
117
117
  path = ns.scope.path
118
118
  branch = env('REPO_MANIFEST') || Repo.read_manifest(root)
119
119
  target = branch || manifest
120
- cmd = nil
121
120
  stage = nil
122
121
  opts = %w[force rebase detach submodules fail no-update gc]
123
- newline = ARGV.any?(/^repo:/)
124
122
  desc = lambda do |val, alt = nil|
125
123
  if (ver = branch || alt)
126
124
  val = val.sub('{0}', "opts*=#{opts.join(',')}")
@@ -132,9 +130,8 @@ module Squared
132
130
 
133
131
  desc.call('all[{0}]')
134
132
  task 'all' do |_, args|
135
- cmd ||= repo_opts args
136
133
  stage ||= 'all'
137
- ns['sync'].invoke
134
+ ns['sync'].invoke(*args.to_a)
138
135
  next if env('REPO_STAGE', equals: '1')
139
136
 
140
137
  @project.select do |_, proj|
@@ -162,39 +159,53 @@ module Squared
162
159
  args = args.to_a
163
160
  u = env('REPO_URL') || manifest_url
164
161
  m = args.first && !opts.include?(args.first) ? args.shift : target
165
- g = case (g = env('REPO_GROUPS'))
162
+ g = args.first && !opts.include?(args.first) ? args.shift : nil
163
+ g = case (val = env('REPO_GROUPS'))
164
+ when '', NilClass
165
+ g
166
166
  when '0', 'false'
167
167
  nil
168
168
  else
169
- g || (args.first && !opts.include?(args.first) ? args.shift : nil)
170
- end
171
- cmd = repo_opts args
172
- s = case (s = env('REPO_SUBMODULES'))
173
- when '0', 'false'
174
- false
175
- else
176
- s ? true : cmd.include?('--fetch-submodules')
169
+ val
177
170
  end
178
171
  stage = 'init'
179
- puts if newline
180
- args = ["-u #{u}", "-m #{m}.xml"]
181
- args << "-g #{g}" if g
182
- args << '--submodules' if s
183
- Common::System.shell("#{repo_bin} init #{args.join(' ')}", chdir: root)
172
+ opts = repo_opts "-u #{u}", "-m #{m}.xml"
173
+ opts << "-g #{g}" if g
174
+ opts << '--submodules' if repo_submodules?(args.include?('submodules'))
175
+ repo_run "#{repo_bin} init #{opts.uniq.join(' ')}"
184
176
  next if env('REPO_STAGE', equals: '0')
185
177
 
186
- ns['all'].invoke
178
+ ns['all'].invoke(*args)
187
179
  end
188
180
 
189
181
  desc.call('sync[{0}]')
190
182
  task 'sync' do |t, args|
191
- raise_error 'repo not initialized' unless branch || stage == 'init'
192
- cmd ||= repo_opts args
193
- cmd << "-j#{ENV.fetch('REPO_JOBS', Rake::CpuCounter.count)}"
194
- puts unless !newline || stage == 'init'
183
+ opts = if stage == 'init'
184
+ []
185
+ else
186
+ raise_error 'repo not initialized' unless branch
187
+ repo_opts
188
+ end
189
+ args.to_a.each do |val|
190
+ case val
191
+ when 'force'
192
+ opts << '--force-checkout'
193
+ when 'rebase', 'detach'
194
+ opts << "--#{val}"
195
+ when 'submodules'
196
+ opts << '--fetch-submodules' if repo_submodules?(true)
197
+ when 'fail'
198
+ opts << '--fail-fast'
199
+ when 'no-update'
200
+ opts << '--no-manifest-update'
201
+ when 'gc'
202
+ opts << '--auto-gc'
203
+ end
204
+ end
205
+ opts << "-j#{ENV.fetch('REPO_JOBS', Rake::CpuCounter.count)}" unless opts.any?(/^--?j(?:obs)?/)
206
+ opts << '--fetch-submodules' if repo_submodules?
195
207
  begin
196
- Common::System.shell("#{repo_bin} sync #{cmd.join(' ')}", chdir: root,
197
- exception: cmd.include?('--fail-fast'))
208
+ repo_run("#{repo_bin} sync #{opts.uniq.join(' ')}", exception: opts.include?('--fail-fast'))
198
209
  rescue Errno::ENOENT => e
199
210
  emphasize(e, title: root)
200
211
  raise
@@ -223,35 +234,34 @@ module Squared
223
234
  )
224
235
  end
225
236
 
226
- def repo_opts(args)
227
- ret = []
228
- args.to_a.each do |val|
229
- case val
230
- when 'force'
231
- ret << '--force-checkout'
232
- when 'rebase', 'detach'
233
- ret << "--#{val}"
234
- when 'submodules'
235
- ret << '--fetch-submodules'
236
- when 'fail'
237
- ret << '--fail-fast'
238
- when 'no-update'
239
- ret << '--no-manifest-update'
240
- when 'gc'
241
- ret << '--auto-gc'
242
- end
243
- end
244
- ret
237
+ def repo_run(cmd, exception: false)
238
+ puts log_message(Logger::INFO, cmd, subject: main, hint: root) if verbose
239
+ Common::System.shell(cmd, chdir: root, exception: exception)
245
240
  end
246
241
 
247
242
  def repo_bin
248
- Common::System.shell_bin('repo')
243
+ Common::Shell.shell_bin('repo')
244
+ end
245
+
246
+ def repo_opts(*args)
247
+ return args unless (n = ARGV.index('--'))
248
+
249
+ ARGV[(n + 1)..-1].concat(args)
249
250
  end
250
251
 
251
252
  def repo?
252
253
  !manifest_url.nil? && (repo_install? || @repo_override == true)
253
254
  end
254
255
 
256
+ def repo_submodules?(val = false)
257
+ case (s = env('REPO_SUBMODULES'))
258
+ when '0', 'false'
259
+ false
260
+ else
261
+ s ? true : val
262
+ end
263
+ end
264
+
255
265
  def repo_install?(dir = root, parent: false)
256
266
  return true if root?(dir, pass: ['.repo']) || dir.join('.repo').directory?
257
267
 
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.5
4
+ version: 0.5.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham