squared 0.6.11 → 0.6.13

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: e9559cf340c4a95816cc2853417bfb3c43053cf59cdd4e4b38fac0c074f41264
4
- data.tar.gz: 60d6c5b20aa58e9606402745283948393253363ed38d5f15322be5d7cbfde7d5
3
+ metadata.gz: 94097556aa9d578868291a94e79b77bb4c647f25a732c18168af747ef159d176
4
+ data.tar.gz: c5546efd99a127548fe59d3c43b19fe44c0328470b89549ad6c094898ca60599
5
5
  SHA512:
6
- metadata.gz: 0b34a0a55c607060040c027b19bc16b5ad93ba1403d753c45a75edadb3086f179b1e533b4d5058787b544012e0eda60d5e1b70ed9ff26c5fda65d55fd74b5513
7
- data.tar.gz: 65478734cb5d093f3abb96022479ba3aec90b7b08741f0f924c348b06466dedb0a8db9d19e7d78e2d0f7cd26c874f7ff56d387323b943baa969097f2c97f37c5
6
+ metadata.gz: 03f8156021daa593832a7366a4cca5e3c62451bbdba1c4c2138cde0549c3fa9f4f584fc6ab7a89f3dd0abb5fb618b0e87a8f01bbab44202b320e17062379deb4
7
+ data.tar.gz: eab421c80afe78291ec52442e26fd9e99467ee934d76afa9d04843e5670cd9e67720e5e63247f625a17889fb2ef0fffa1699ae4d733b28ef12b694960bd8c6f4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.13] - 2026-05-04
4
+
5
+ ### Added
6
+
7
+ - Application project commands can be defined without a reference.
8
+
9
+ ### Fixed
10
+
11
+ - Application methods log and exclude were non-functional.
12
+ - Project base tasks did not detect build scripts using Arrays.
13
+
14
+ ## [0.6.12] - 2026-04-29
15
+
16
+ ### Fixed
17
+
18
+ - Application dynamic Project loader assumed class would be found.
19
+ - Git command grep did not add patterns with "--" pathspec separator.
20
+
21
+ ## [0.5.23] - 2026-04-29
22
+
23
+ ### Fixed
24
+
25
+ - See `0.4.37`.
26
+
27
+ ## [0.4.37] - 2026-04-29
28
+
29
+ ### Changed
30
+
31
+ - Project base method dependindex replaces private instance variable.
32
+
33
+ ### Fixed
34
+
35
+ - Ruby command version did not abort asdf "Not installed" error.
36
+ - Git command pull action all did not pass option flags to branches.
37
+ - Python command exec did not activate virtual environment.
38
+ - Docker command bake did not reinsert failed check for context directory.
39
+ - Common method shell_quote argument preserve did not bypass requoting.
40
+
3
41
  ## [0.6.11] - 2026-03-11
4
42
 
5
43
  ### Changed
@@ -8,6 +46,8 @@
8
46
 
9
47
  ## [0.5.22] - 2026-03-11
10
48
 
49
+ ### Fixed
50
+
11
51
  - Project base run command was not covered due to lack of type checking.
12
52
 
13
53
  ## [0.4.36] - 2026-03-11
@@ -1635,6 +1675,8 @@
1635
1675
 
1636
1676
  - Changelog was created.
1637
1677
 
1678
+ [0.6.13]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.13
1679
+ [0.6.12]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.12
1638
1680
  [0.6.11]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.11
1639
1681
  [0.6.10]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.10
1640
1682
  [0.6.9]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.9
@@ -1647,6 +1689,7 @@
1647
1689
  [0.6.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.2
1648
1690
  [0.6.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.1
1649
1691
  [0.6.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.0
1692
+ [0.5.23]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.23
1650
1693
  [0.5.22]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.22
1651
1694
  [0.5.21]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.21
1652
1695
  [0.5.20]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.20
@@ -1670,6 +1713,7 @@
1670
1713
  [0.5.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.2-ruby
1671
1714
  [0.5.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.1-ruby
1672
1715
  [0.5.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.0-ruby
1716
+ [0.4.37]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.37
1673
1717
  [0.4.36]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.36
1674
1718
  [0.4.35]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.35
1675
1719
  [0.4.34]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.34
@@ -51,7 +51,7 @@ module Squared
51
51
  end
52
52
  end
53
53
 
54
- def shell_quote(val, option: true, force: true, double: false, preserve: true, override: false)
54
+ def shell_quote(val, option: true, force: true, double: false, preserve: true, pass: false, override: false)
55
55
  val = val.to_s
56
56
  return val if (!force && !val.include?(' ')) || val.empty?
57
57
 
@@ -59,16 +59,16 @@ module Squared
59
59
  pat = /\A(?:-[^=\s-](?:=|\s+)?|(--)?[^=\s-][^=\s]*(?(1)(?:=|\s+)|=))(["']).+\2\z/m
60
60
  return val if val.match?(pat)
61
61
  end
62
- q = ->(s) { s.gsub("'\\\\''", "'") }
63
62
  if val =~ QUOTE_VALUE
64
- return val if $1 == '"' && Rake::Win32.windows? && val.match?(/(?:[#{File::SEPARATOR} ]|\\")/o)
63
+ return val if pass || ($1 == '"' && Rake::Win32.windows? && val.match?(/(?:[#{File::SEPARATOR} ]|\\")/o))
65
64
 
66
65
  base = $2 unless preserve
67
66
  end
67
+ q = -> { (base || val).gsub("'\\\\''", "'") }
68
68
  if double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
69
- "\"#{q.call(base || val).gsub(/(?<!\\)"/, '\\"')}\""
69
+ "\"#{q.call.gsub(/(?<!\\)"/, '\\"')}\""
70
70
  else
71
- base ? val : "'#{q.call(val).gsub("'", "'\\\\''")}'"
71
+ "'#{q.call.gsub("'", "'\\\\''")}'"
72
72
  end
73
73
  end
74
74
 
@@ -28,6 +28,7 @@ module Squared
28
28
  module_function
29
29
 
30
30
  def shell(*args, name: :system, **kwargs)
31
+ kwargs.delete(:exception) unless name == :system
31
32
  if RUBY_ENGINE == 'jruby' && Rake::Win32.windows?
32
33
  e = kwargs[:exception]
33
34
  if (dir = kwargs[:chdir]) && ((pwd = Dir.pwd) != dir)
@@ -43,7 +44,7 @@ module Squared
43
44
  else
44
45
  return Kernel.send(name, *args, **kwargs)
45
46
  end
46
- return ret unless e && !ret && name == :system
47
+ return ret unless e && !ret
47
48
 
48
49
  raise $?.to_s
49
50
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.6.11'
4
+ VERSION = '0.6.13'
5
5
  end
@@ -867,7 +867,7 @@ module Squared
867
867
  log_console(*args, pipe: kwargs[:pipe] || pipe)
868
868
  end
869
869
 
870
- def script_command(task, val, group, ref, on, &blk)
870
+ def script_command(task, val, group, ref, on = nil, &blk)
871
871
  if block_given?
872
872
  val = Struct::RunData.new(val, blk)
873
873
  elsif !val
@@ -878,7 +878,7 @@ module Squared
878
878
  as_a group, :to_sym
879
879
  else
880
880
  label = :ref
881
- as_a ref, :to_sym
881
+ as_a(ref || :_, :to_sym)
882
882
  end.each do |name|
883
883
  @script[label][name][task] = val
884
884
  @events[label][name][task] = on if on.is_a?(Hash)
@@ -910,6 +910,8 @@ module Squared
910
910
  nil
911
911
  elsif ref && target[:ref].key?(ref)
912
912
  target[:ref][ref]
913
+ else
914
+ target[:ref][:_]
913
915
  end
914
916
  end
915
917
 
@@ -923,6 +925,7 @@ module Squared
923
925
  require_relative rb
924
926
  break
925
927
  end
928
+ nil
926
929
  end
927
930
 
928
931
  def root?(path, pass: [])
@@ -918,7 +918,7 @@ module Squared
918
918
  end
919
919
 
920
920
  def run(cmd = @session, var = nil, exception: self.exception, sync: true, banner: true, from: nil, chdir: path,
921
- interactive: nil, hint: nil, series: false, **)
921
+ interactive: nil, hint: nil, series: false, send: :system, **)
922
922
  unless cmd
923
923
  print_error('no command session started', subject: project, hint: from, pass: true)
924
924
  return
@@ -956,7 +956,7 @@ module Squared
956
956
  end
957
957
  end
958
958
  args = var.is_a?(Hash) ? [var, cmd] : [cmd]
959
- ret = shell(*args, chdir: chdir, exception: exception)
959
+ ret = shell(*args, name: send, chdir: chdir, exception: exception)
960
960
  end
961
961
  rescue StandardError => e
962
962
  on_error(e, from, exception: true)
@@ -1008,7 +1008,7 @@ module Squared
1008
1008
  run_set(output[0], *args, **kwargs)
1009
1009
  when :dependfile
1010
1010
  @dependindex = nil
1011
- @dependfile = val.nil? ? nil : basepath(*args)
1011
+ @dependfile = (basepath(*args) if val)
1012
1012
  else
1013
1013
  instance_variable_set(:"@#{key}", val)
1014
1014
  end
@@ -1116,7 +1116,7 @@ module Squared
1116
1116
  end
1117
1117
 
1118
1118
  def dependtype(*)
1119
- @dependindex ? @dependindex.succ : 0
1119
+ dependindex&.succ || 0
1120
1120
  end
1121
1121
 
1122
1122
  def dependname
@@ -1249,7 +1249,7 @@ module Squared
1249
1249
  else
1250
1250
  if series?(obj)
1251
1251
  obj.each(&:call)
1252
- elsif obj.is_a?(Array) && obj.any? { |val| !val.is_a?(String) }
1252
+ elsif obj.is_a?(Array) && obj.any? { |val| val.nil? || !val.is_a?(String) }
1253
1253
  build(*obj, **kwargs)
1254
1254
  elsif obj
1255
1255
  run_s(*Array(obj), **kwargs)
@@ -2369,13 +2369,19 @@ module Squared
2369
2369
  end
2370
2370
  end
2371
2371
 
2372
- def dependfile_set(list)
2372
+ def dependfile_set(list, default: 0)
2373
2373
  @dependindex = if @dependname
2374
2374
  @dependfile = basepath @dependname
2375
2375
  list.index(@dependname)
2376
2376
  else
2377
- list.index { |file| exist?(file) }.tap { |i: 0| @dependfile = basepath(list[i]) }
2378
- end
2377
+ list.index { |file| exist?(file) }.tap { |i| @dependfile = basepath(list[i || default]) }
2378
+ end || (list unless enabled?)
2379
+ end
2380
+
2381
+ def dependindex
2382
+ dependfile_set @dependindex if @dependindex.is_a?(Array)
2383
+
2384
+ @dependindex unless @dependindex.is_a?(Array)
2379
2385
  end
2380
2386
 
2381
2387
  def as_get(val, from)
@@ -20,7 +20,7 @@ module Squared
20
20
  sbom=q].freeze
21
21
  }.freeze,
22
22
  compose: {
23
- common: %w[all-resources ansi|b compatibility dry-run env-file=p f|file=p parallel=n profile=b progress=b
23
+ common: %w[all-resources ansi=b compatibility dry-run env-file=p f|file=p parallel=n profile=b progress=b
24
24
  project-directory=p p|project-name=e].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,
@@ -400,7 +400,7 @@ module Squared
400
400
  if projectpath?(val = args.pop)
401
401
  context = val
402
402
  else
403
- op.push(val)
403
+ args << val
404
404
  end
405
405
  end
406
406
  op.append(args, escape: true, strip: /^:/)
@@ -875,11 +875,11 @@ module Squared
875
875
  when :service
876
876
  ['Choose a service',
877
877
  'compose ps -a ' \
878
- "--format='table {{.Service}}\t{{.Name}}\t{{.Image}}\t{{.Command}}\t{{.Status}}\t{{.Ports}}'"]
878
+ '--format="table {{.Service}}\t{{.Name}}\t{{.Image}}\t{{.Command}}\t{{.Status}}\t{{.Ports}}"']
879
879
  else
880
880
  ['Choose an image',
881
881
  'images -a ' \
882
- "--format='table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.CreatedSince}}\t{{.Size}}'"]
882
+ '--format="table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.CreatedSince}}\t{{.Size}}"']
883
883
  end
884
884
  lines = `#{docker_output(cmd)}`.lines
885
885
  if lines.size <= 1
@@ -169,22 +169,22 @@ module Squared
169
169
  }.freeze,
170
170
  fetch: {
171
171
  base: %w[multiple porcelain progress P|prune-tags refetch stdin u|update-head-ok
172
- recurse-submodules-default=b].freeze,
172
+ recurse-submodules-default=b?].freeze,
173
173
  pull: %w[4 6 n t a|append atomic dry-run f|force k|keep negotiate-only prefetch p|prune q|quiet set-upstream
174
174
  unshallow update-shallow v|verbose deepen=i depth=i j|jobs=i negotiation-tip=q recurse-submodules=v
175
175
  refmap=q o|server-option=q shallow-exclude=b shallow-since=v upload-pack=q].freeze
176
176
  }.freeze,
177
177
  git: {
178
- add: %w[N|intent-to-add refresh].freeze,
178
+ add: %w[N|intent-to-add].freeze,
179
179
  blame: %w[b c l s t w C=im? L=q M=im? S=p color-by-age color-lines first-parent incremental line-porcelain
180
180
  p|porcelain root score-debug f|show-name e|show-email n|show-number show-stats abbrev=i contents=p
181
- date=q encoding=b ignore-rev=b ignore-revs-file=p reverse=q].freeze,
181
+ date=q diff-algorithm=b encoding=b ignore-rev=b ignore-revs-file=p reverse=q].freeze,
182
182
  clean: %w[d x X f|force n|dry-run i|interactive q|quiet e|exclude=q].freeze,
183
183
  grep: %w[e f=p h H I O=bm r all-match and G|basic-regexp break cached column c|count E|extended-regexp
184
184
  l|files-with-matches L|files-without-match F|fixed-strings full-name W|function-context heading
185
185
  i|ignore-case v|invert-match n|line-number name-only no-index not z|null o|only-matching or
186
186
  P|perl-regexp q|quiet recurse-submodules p|show-function a|text untracked w|word-regexp
187
- A|after-context=i B|before-context=i color=b C|context=i m|max-count=n max-depth=i
187
+ A|after-context=i B|before-context=i color=b C|context=i m|max-count=n max-depth=n
188
188
  open-files-in-pager=b threads=n].freeze,
189
189
  mv: %w[k f|force n|dry-run v|verbose].freeze,
190
190
  revert: %w[e S=bm? n|no-commit reference cleanup=b gpg-sign=b? m|mainline=i s|signoff strategy=b
@@ -254,7 +254,7 @@ module Squared
254
254
  submodule: {
255
255
  status: %w[cached recursive].freeze,
256
256
  update: %w[checkout f|force init merge N|no-fetch no-recommend-shallow no-single-branch recommend-shallow
257
- rebase recursive remote single-branch depth=i filter=q jobs=i reference=b ref-format=q].freeze,
257
+ rebase recursive remote single-branch depth=i filter=q jobs=i reference=q ref-format=q].freeze,
258
258
  branch: %w[b|branch d|default].freeze,
259
259
  sync: %w[recursive].freeze
260
260
  }.freeze,
@@ -1009,12 +1009,8 @@ module Squared
1009
1009
  printsucc
1010
1010
  end
1011
1011
  op = OptionPartition.new(opts, OPT_GIT[:pull], cmd, project: self, no: OPT_GIT[:no][:pull])
1012
- reg = if op.empty?
1013
- []
1014
- else
1015
- opts = op.uniq(opts)
1016
- matchmap op
1017
- end
1012
+ opts -= op.extras
1013
+ reg = matchmap op
1018
1014
  session_done op.target
1019
1015
  heads = []
1020
1016
  cur = nil
@@ -1849,10 +1845,15 @@ module Squared
1849
1845
  when :rm, :clean
1850
1846
  append_pathspec(op.extras, expect: flag == :rm)
1851
1847
  when :grep
1848
+ delim = false
1852
1849
  op.each do |val|
1853
- if op.include?('--')
1850
+ if val == '--'
1851
+ delim = true
1852
+ op.delim
1853
+ elsif delim
1854
1854
  op.add_path(val)
1855
1855
  elsif op.exist?(val, glob: true)
1856
+ delim = true
1856
1857
  op.delim
1857
1858
  .add_path(val)
1858
1859
  else
@@ -508,6 +508,7 @@ module Squared
508
508
  end
509
509
  save, exact, omit = save if save.is_a?(Array)
510
510
  ws = env('NODE_WORKSPACES', equals: '0')
511
+ ci = option('ci')
511
512
  om = lambda do |cmd|
512
513
  if omit
513
514
  save = case save
@@ -544,7 +545,7 @@ module Squared
544
545
  end
545
546
  if nolockfile?('yarn')
546
547
  cmd << '--no-lockfile'
547
- elsif option('ci')
548
+ elsif ci
548
549
  if yarn == 1
549
550
  cmd << '--frozen-lockfile'
550
551
  elsif !flag
@@ -580,15 +581,15 @@ module Squared
580
581
  '--force'
581
582
  elsif nolockfile?('pnpm')
582
583
  '--no-lockfile'
583
- elsif option('ci')
584
+ elsif ci
584
585
  '--frozen-lockfile'
585
586
  end
586
587
  cmd << '--ignore-scripts' if option('ignore-scripts')
587
588
  cmd << '--dangerously-allow-all-builds' if option('approve-builds')
588
589
  else
589
- cmd = session 'npm'
590
- cmd << (ci = option('ci') ? 'ci' : 'install')
590
+ cmd = session('npm', ci ? 'ci' : 'install')
591
591
  cmd << '--workspaces=false' if ws
592
+ cmd << '--force' if option('force')
592
593
  append_nocolor
593
594
  append_loglevel
594
595
  if omit
@@ -856,13 +857,18 @@ module Squared
856
857
  package(:update, from: :update)
857
858
  end
858
859
 
859
- def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, access: nil, dryrun: nil)
860
+ def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, access: nil, dryrun: nil,
861
+ workspace: false)
860
862
  if read_package('private')
863
+ return if workspace
864
+
861
865
  ws = children.select { |proj| proj.ref?(Node.ref) }
862
866
  if ws.empty?
863
867
  print_error('nothing to publish', subject: name, hint: 'private')
864
868
  elsif confirm_basic('Publish workspace?', ws.map(&:name).join(', '), 'N')
865
- ws.each { |proj| proj.publish(flag, sync: sync, otp: otp, tag: tag, access: access, dryrun: dryrun) }
869
+ ws.each do |proj|
870
+ proj.publish(flag, sync: sync, otp: otp, tag: tag, access: access, dryrun: dryrun, workspace: true)
871
+ end
866
872
  end
867
873
  return
868
874
  end
@@ -113,7 +113,7 @@ module Squared
113
113
  initialize_build(Python.ref, **kwargs)
114
114
  initialize_env(**kwargs)
115
115
  end
116
- dependfile_set DEP_PYTHON
116
+ dependfile_set(DEP_PYTHON, default: 2)
117
117
  editable_set editable
118
118
  venv_set kwargs[:venv]
119
119
  end
@@ -204,12 +204,12 @@ module Squared
204
204
  end
205
205
  next if found.anybits?(1)
206
206
 
207
- puts log_message(found == 0 ? Logger::INFO : Logger.WARN,
207
+ puts log_message(found == 0 ? Logger::INFO : Logger::WARN,
208
208
  "no scripts #{found == 0 ? 'found' : 'executed'}",
209
209
  subject: name, hint: pyprojectfile)
210
210
  end
211
211
  when 'exec'
212
- format_desc action, nil, ':|command,args*'
212
+ format_desc action, nil, 'command|:,args*'
213
213
  task action do |_, args|
214
214
  args = args.to_a
215
215
  cmd = if (i = args.delete(':')) && !workspace.windows?
@@ -219,7 +219,7 @@ module Squared
219
219
  else
220
220
  (args << command_args(args, min: 1, prefix: 'python')).compact.join(' ')
221
221
  end
222
- shell(cmd, name: :exec, chdir: path)
222
+ run(cmd, send: :exec, banner: false)
223
223
  end
224
224
  end
225
225
  else
@@ -710,7 +710,9 @@ module Squared
710
710
  when :freeze
711
711
  venv_init
712
712
  op << '>'
713
- op.add_quote(ret = basepath(op.detect { |val| op.exist?(val) } || DEP_PYTHON[4]))
713
+ file = op.detect { |val| op.exist?(val) }
714
+ op.remove(file) if file
715
+ op.add_quote(ret = basepath(file || DEP_PYTHON[4]))
714
716
  .clear
715
717
  when :cache
716
718
  op.concat(args)
@@ -822,7 +822,8 @@ module Squared
822
822
  ver = '.tool-versions'
823
823
  opt = [@asdf.first]
824
824
  opt.unshift('--no-header') unless @@asdf.version == 15
825
- `asdf current #{opt.join(' ')}`[/^\S+\s+\S+/, 0].sub(/\s+/, ' ')
825
+ exit 1 unless (cur = `asdf current #{opt.join(' ')}`[/^\S+\s+\S+/, 0])
826
+ cur.sub(/\s+/, ' ')
826
827
  else
827
828
  ver = nil
828
829
  `ruby --version`
@@ -9,7 +9,7 @@ module Squared
9
9
  attr_reader :manifest_url, :manifest
10
10
 
11
11
  def repo(url, manifest = 'latest', install: nil, run: nil, script: nil, args: nil, dev: nil, prod: nil,
12
- ref: @ref, group: @group)
12
+ ref: @ref, group: @group, **)
13
13
  @home = if (val = env('REPO_HOME'))
14
14
  path = Pathname.new(val)
15
15
  if main == path.basename.to_s
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.6.11
4
+ version: 0.6.13
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.3
127
+ rubygems_version: 4.0.11
128
128
  specification_version: 4
129
129
  summary: Rake task generator for managing multi-language workspaces.
130
130
  test_files: []