squared 0.2.11 → 0.2.12
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 +4 -4
- data/CHANGELOG.md +24 -0
- data/lib/squared/common/base.rb +5 -2
- data/lib/squared/common/system.rb +21 -14
- data/lib/squared/config.rb +2 -0
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +9 -1
- data/lib/squared/workspace/project/base.rb +12 -9
- data/lib/squared/workspace/project/git.rb +21 -17
- data/lib/squared/workspace/project/node.rb +6 -6
- data/lib/squared/workspace/project/ruby.rb +5 -5
- data/lib/squared/workspace/repo.rb +1 -1
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c4f586dc4eb61a4952f9093d90f52b07bd95b920ddeb2f3f10df67c5d32a936
|
4
|
+
data.tar.gz: d2c688164ad5033e3d662fda16b63809cc2c6f1020b963d7ef15b3f61571f457
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cebf94bb4963e7b8c2515df1c2a02e3c7a919a702eea06f66840c73cfd87cdaf3069c8dece4487385ecc421bb858934a87f320ecfeedec89964971147a3810d
|
7
|
+
data.tar.gz: d0917560fbe4c49c70269b1f4cfbe1f63b1c460eb9d1658046b9c23b1764182007533556d2fceb174b452424d835928a67815ba22927a435f872aeb5c8611772
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,27 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.2.12] - 2025-07-05
|
4
|
+
|
5
|
+
### Fixed
|
6
|
+
|
7
|
+
- See `0.1.9`.
|
8
|
+
|
9
|
+
## [0.1.9] - 2025-07-05
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- Initial support for using JRuby.
|
14
|
+
- Config viewer theme color for boolean was implemented.
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
|
18
|
+
- Workspace did not add prefix to duplicate project names.
|
19
|
+
- Project output divider was not printed when not verbose.
|
20
|
+
- Directory context was not threaded using JRuby.
|
21
|
+
- Index character was not captured on Windows.
|
22
|
+
- Common method is used for Kernel shell commands.
|
23
|
+
- Git did not highlight output for single commands.
|
24
|
+
|
3
25
|
## [0.2.11] - 2025-05-15
|
4
26
|
|
5
27
|
### Fixed
|
@@ -285,6 +307,7 @@
|
|
285
307
|
|
286
308
|
- Changelog was created.
|
287
309
|
|
310
|
+
[0.2.12]: https://github.com/anpham6/squared/releases/tag/v0.2.12-ruby
|
288
311
|
[0.2.11]: https://github.com/anpham6/squared/releases/tag/v0.2.11-ruby
|
289
312
|
[0.2.10]: https://github.com/anpham6/squared/releases/tag/v0.2.10-ruby
|
290
313
|
[0.2.9]: https://github.com/anpham6/squared/releases/tag/v0.2.9-ruby
|
@@ -297,6 +320,7 @@
|
|
297
320
|
[0.2.2]: https://github.com/anpham6/squared/releases/tag/v0.2.2-ruby
|
298
321
|
[0.2.1]: https://github.com/anpham6/squared/releases/tag/v0.2.1-ruby
|
299
322
|
[0.2.0]: https://github.com/anpham6/squared/releases/tag/v0.2.0-ruby
|
323
|
+
[0.1.9]: https://github.com/anpham6/squared/releases/tag/v0.1.9-ruby
|
300
324
|
[0.1.8]: https://github.com/anpham6/squared/releases/tag/v0.1.8-ruby
|
301
325
|
[0.1.7]: https://github.com/anpham6/squared/releases/tag/v0.1.7-ruby
|
302
326
|
[0.1.6]: https://github.com/anpham6/squared/releases/tag/v0.1.6-ruby
|
data/lib/squared/common/base.rb
CHANGED
@@ -53,6 +53,7 @@ module Squared
|
|
53
53
|
hash: %i[green black!],
|
54
54
|
array: %i[blue black!],
|
55
55
|
number: [:magenta],
|
56
|
+
boolean: [:magenta],
|
56
57
|
undefined: %i[red italic]
|
57
58
|
},
|
58
59
|
logger: {
|
@@ -93,13 +94,15 @@ module Squared
|
|
93
94
|
return [] if obj.nil?
|
94
95
|
|
95
96
|
unless obj.is_a?(::Array)
|
96
|
-
obj = if obj.respond_to?(:
|
97
|
+
obj = if obj.respond_to?(:to_ary)
|
98
|
+
obj.to_ary
|
99
|
+
elsif obj.respond_to?(:to_a) && !obj.is_a?(::Hash) && (val = obj.to_a).is_a?(::Array)
|
97
100
|
val
|
98
101
|
else
|
99
102
|
[obj]
|
100
103
|
end
|
101
104
|
end
|
102
|
-
obj =
|
105
|
+
obj = flat.is_a?(::Numeric) ? obj.flatten(flat) : obj.flatten if flat
|
103
106
|
obj = obj.compact if compact
|
104
107
|
obj = obj.map(&meth) if meth
|
105
108
|
block_given? ? obj.select(&blk) : obj
|
@@ -1,23 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'pathname'
|
4
|
-
require '
|
4
|
+
require 'rake'
|
5
5
|
|
6
6
|
module Squared
|
7
7
|
module Common
|
8
8
|
module System
|
9
9
|
module_function
|
10
10
|
|
11
|
-
def shell(*args, **kwargs)
|
12
|
-
if
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
def shell(*args, name: :system, **kwargs)
|
12
|
+
if RUBY_ENGINE == 'jruby' && Rake::Win32.windows?
|
13
|
+
e = kwargs[:exception]
|
14
|
+
if (dir = kwargs[:chdir]) && ((pwd = Dir.pwd) != dir)
|
15
|
+
Dir.chdir(dir)
|
16
|
+
ret = Kernel.send(name, *args)
|
17
|
+
Dir.chdir(pwd)
|
18
|
+
else
|
19
|
+
ret = Kernel.send(name, *args)
|
20
|
+
end
|
21
|
+
elsif RUBY_VERSION < '2.6'
|
22
|
+
e = kwargs.delete(:exception)
|
23
|
+
ret = Kernel.send(name, *args, **kwargs)
|
18
24
|
else
|
19
|
-
|
25
|
+
return Kernel.send(name, *args, **kwargs)
|
20
26
|
end
|
27
|
+
return ret if ret || !e
|
28
|
+
|
29
|
+
raise $?.to_s
|
21
30
|
end
|
22
31
|
|
23
32
|
def copy_dir(src, dest, glob = ['**/*'], create: false, link: nil, force: false, pass: nil, verbose: true)
|
@@ -29,10 +38,9 @@ module Squared
|
|
29
38
|
dest.mkpath if create
|
30
39
|
if pass
|
31
40
|
exclude = []
|
32
|
-
pass
|
33
|
-
pass.each { |val| exclude += Dir.glob(src.join(val)) }
|
41
|
+
Array(pass).each { |val| exclude += Dir.glob(src.join(val)) }
|
34
42
|
end
|
35
|
-
(glob
|
43
|
+
Array(glob).each do |val|
|
36
44
|
Dir.glob(src.join(val)) do |path|
|
37
45
|
next if exclude&.include?(path) || (path = Pathname.new(path)).directory?
|
38
46
|
|
@@ -79,8 +87,7 @@ module Squared
|
|
79
87
|
def copy_guard(src, dest, link: nil, force: false, verbose: true)
|
80
88
|
unless force
|
81
89
|
if (path = Pathname.new(dest)).directory?
|
82
|
-
src =
|
83
|
-
src = src.reject { |val| path.join(File.basename(val)).exist? }
|
90
|
+
src = Array(src).reject { |val| path.join(File.basename(val)).exist? }
|
84
91
|
return if src.empty?
|
85
92
|
elsif path.exist?
|
86
93
|
return
|
data/lib/squared/config.rb
CHANGED
@@ -249,6 +249,8 @@ module Squared
|
|
249
249
|
{ pat: /\A(.+ : ")(.+)("\s*)\z/m, styles: theme[:string], index: 2 },
|
250
250
|
{ pat: /\A(.+ : \{)(.+)(\}\s*)\z/m, styles: theme[:hash], index: 2 },
|
251
251
|
{ pat: /\A(.+ : \[)(.+)(\]\s*)\z/m, styles: theme[:array], index: 2 },
|
252
|
+
{ pat: /\A(.+ : )(true|false)(\s*)\z/m, styles: theme[:boolean],
|
253
|
+
index: 2 },
|
252
254
|
{ pat: /\A(.+ : (?!undefined))([^"\[{].*)\z/m, styles: theme[:value],
|
253
255
|
index: 2 }
|
254
256
|
]
|
data/lib/squared/version.rb
CHANGED
@@ -268,7 +268,7 @@ module Squared
|
|
268
268
|
index = 0
|
269
269
|
while @project[name]
|
270
270
|
index += 1
|
271
|
-
name = "#{project}-#{index}"
|
271
|
+
name = task_name "#{project}-#{index}"
|
272
272
|
end
|
273
273
|
proj = ((if !ref.is_a?(Class)
|
274
274
|
Application.find(ref, path: path)
|
@@ -548,6 +548,14 @@ module Squared
|
|
548
548
|
Rake::Win32.windows?
|
549
549
|
end
|
550
550
|
|
551
|
+
def jruby?
|
552
|
+
RUBY_ENGINE == 'jruby'
|
553
|
+
end
|
554
|
+
|
555
|
+
def jruby_win?
|
556
|
+
jruby? && windows?
|
557
|
+
end
|
558
|
+
|
551
559
|
def rootpath(*args)
|
552
560
|
root.join(*args)
|
553
561
|
end
|
@@ -703,7 +703,7 @@ module Squared
|
|
703
703
|
|
704
704
|
t = dedupe.(proj.name)
|
705
705
|
j = if out
|
706
|
-
if i == items.size - 1 || check.(post = items[i + 1..-1]).empty?
|
706
|
+
if i == items.size - 1 || check.(post = items[(i + 1)..-1]).empty?
|
707
707
|
true
|
708
708
|
elsif !t.empty? && depth > 0
|
709
709
|
post.reject { |pr| t.include?(pr) }.empty?
|
@@ -820,11 +820,11 @@ module Squared
|
|
820
820
|
reg, list = list.partition do |val|
|
821
821
|
next unless (n = val.index('='))
|
822
822
|
|
823
|
-
bare << val[0..n - 1] if val.end_with?('?')
|
823
|
+
bare << val[0..(n - 1)] if val.end_with?('?')
|
824
824
|
true
|
825
825
|
end
|
826
826
|
list += bare
|
827
|
-
no = no.map { |val| (n = val.index('=')) ? val[0..n - 1] : val }
|
827
|
+
no = no.map { |val| (n = val.index('=')) ? val[0..(n - 1)] : val }
|
828
828
|
found = false
|
829
829
|
opts.each do |opt|
|
830
830
|
next out << opt if found
|
@@ -838,7 +838,7 @@ module Squared
|
|
838
838
|
found = true if first && pass.none? { |val| opt.include?(val) }
|
839
839
|
end
|
840
840
|
end
|
841
|
-
pat = Regexp.new("^(#{reg.map { |val| val[0..val.index('=') - 1] }.join('|')})=(.+)$")
|
841
|
+
pat = Regexp.new("^(#{reg.map { |val| val[0..(val.index('=') - 1)] }.join('|')})=(.+)$")
|
842
842
|
[out, pat]
|
843
843
|
end
|
844
844
|
|
@@ -851,7 +851,7 @@ module Squared
|
|
851
851
|
end
|
852
852
|
|
853
853
|
def print_item(*val)
|
854
|
-
puts if @@print_order > 0
|
854
|
+
puts if @@print_order > 0
|
855
855
|
@@print_order += 1
|
856
856
|
puts val unless val.empty? || (val.size == 1 && val.first.nil?)
|
857
857
|
end
|
@@ -1077,15 +1077,17 @@ module Squared
|
|
1077
1077
|
end
|
1078
1078
|
|
1079
1079
|
def indexitem(val)
|
1080
|
-
|
1081
|
-
|
1082
|
-
[data[1].to_i, data[2] ? data[2][1..-1] : nil]
|
1080
|
+
[$1.to_i, $2 && $2[1..-1]] if val =~ /\A#{Regexp.escape(indexchar)}(\d+)(:.+)?\z/
|
1083
1081
|
end
|
1084
1082
|
|
1085
1083
|
def indexerror(val, list = nil)
|
1086
1084
|
raise_error("requested index #{val}", hint: list && "of #{list.size}")
|
1087
1085
|
end
|
1088
1086
|
|
1087
|
+
def indexchar
|
1088
|
+
workspace.windows? ? '+' : '^'
|
1089
|
+
end
|
1090
|
+
|
1089
1091
|
def color(val)
|
1090
1092
|
ret = theme[val]
|
1091
1093
|
ret && !ret.empty? ? ret : [val]
|
@@ -1119,7 +1121,8 @@ module Squared
|
|
1119
1121
|
pwd = Pathname.pwd
|
1120
1122
|
if block_given?
|
1121
1123
|
begin
|
1122
|
-
|
1124
|
+
pass = semscan(pass).join <= RUBY_VERSION if pass.is_a?(String)
|
1125
|
+
if (path == pwd || pass == true) && !workspace.jruby_win?
|
1123
1126
|
ret = instance_eval(&blk)
|
1124
1127
|
else
|
1125
1128
|
Dir.chdir(path)
|
@@ -460,7 +460,7 @@ module Squared
|
|
460
460
|
source(sync: sync, sub: if verbose
|
461
461
|
[
|
462
462
|
{ pat: /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, styles: :red, index: 4 },
|
463
|
-
{ pat: /^(.+)(\|\s+\d+\s+)(\++)(
|
463
|
+
{ pat: /^(.+)(\|\s+\d+\s+)(\++)(.*)$/, styles: :green, index: 3 }
|
464
464
|
]
|
465
465
|
end, **threadargs)
|
466
466
|
end
|
@@ -732,7 +732,8 @@ module Squared
|
|
732
732
|
origin = nil
|
733
733
|
source(git_output('fetch --no-tags --quiet'), io: true, banner: false, stdout: true)
|
734
734
|
cmd = git_output("for-each-ref --format=\"#{format}\" refs/heads")
|
735
|
-
source(cmd, io: true, banner: false).first
|
735
|
+
out = source(cmd, io: true, stdout: workspace.windows?, banner: false).first
|
736
|
+
(workspace.windows? ? out.lines : out).each do |line|
|
736
737
|
next if (line = line.chomp).empty?
|
737
738
|
|
738
739
|
branch, origin, hint = line.split('...')
|
@@ -746,8 +747,8 @@ module Squared
|
|
746
747
|
break
|
747
748
|
end
|
748
749
|
i = origin.index('/')
|
749
|
-
branch = "#{branch}:#{origin[i + 1..-1]}" unless origin.end_with?("/#{branch}")
|
750
|
-
origin = origin[0..i - 1]
|
750
|
+
branch = "#{branch}:#{origin[(i + 1)..-1]}" unless origin.end_with?("/#{branch}")
|
751
|
+
origin = origin[0..(i - 1)]
|
751
752
|
cmd = git_session('commit', option('dry-run') && '--dry-run', options: false)
|
752
753
|
cmd << '--amend' if amend
|
753
754
|
if message
|
@@ -934,9 +935,14 @@ module Squared
|
|
934
935
|
format_banner((banner.is_a?(String) ? banner : cmd).gsub(File.join(path, ''), ''), banner: true)
|
935
936
|
end
|
936
937
|
begin
|
937
|
-
|
938
|
-
|
939
|
-
|
938
|
+
if io
|
939
|
+
ret = if stdout
|
940
|
+
[`#{cmd}`]
|
941
|
+
else
|
942
|
+
[IO.popen(cmd), banner, from]
|
943
|
+
end
|
944
|
+
return ret
|
945
|
+
elsif stdin? ? sync : stdout
|
940
946
|
print_item banner unless multiple
|
941
947
|
ret = `#{cmd}`
|
942
948
|
if !ret.empty?
|
@@ -944,7 +950,7 @@ module Squared
|
|
944
950
|
elsif banner && stdout && !stdin?
|
945
951
|
puts 'Success'
|
946
952
|
end
|
947
|
-
elsif sync || (!exception && !stderr)
|
953
|
+
elsif !sub && (sync || (!exception && !stderr))
|
948
954
|
print_item banner unless multiple
|
949
955
|
shell(cmd, exception: exception)
|
950
956
|
else
|
@@ -999,15 +1005,13 @@ module Squared
|
|
999
1005
|
end
|
1000
1006
|
|
1001
1007
|
def list_result(size, type, from: nil, action: 'found', grep: nil)
|
1002
|
-
if
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
puts empty_status("No #{type} were #{action}", 'grep', grep)
|
1010
|
-
end
|
1008
|
+
if size == 0
|
1009
|
+
puts empty_status("No #{type} were #{action}", 'grep', grep)
|
1010
|
+
elsif verbose
|
1011
|
+
styles = theme.fetch(:banner, []).reject { |s| s.to_s.end_with?('!') }
|
1012
|
+
styles << :bold if styles.size <= 1
|
1013
|
+
puts print_footer("#{size} #{size == 1 ? type.sub(/(?:(?<!l)e)?s\z/, '') : type}",
|
1014
|
+
sub: { pat: /\A(\d+)(.+)\z/, styles: styles })
|
1011
1015
|
end
|
1012
1016
|
on :last, from if from
|
1013
1017
|
end
|
@@ -72,7 +72,7 @@ module Squared
|
|
72
72
|
case action
|
73
73
|
when 'add'
|
74
74
|
format_desc action, nil, 'save?=prod|dev|optional|peer,name+'
|
75
|
-
task action, [:save
|
75
|
+
task action, [:save] do |_, args|
|
76
76
|
save = param_guard(action, 'save', args: args, key: :save)
|
77
77
|
if save.start_with?('=')
|
78
78
|
exact = true
|
@@ -80,7 +80,7 @@ module Squared
|
|
80
80
|
end
|
81
81
|
case save
|
82
82
|
when 'prod', 'dev', 'optional', 'peer'
|
83
|
-
name = param_guard(action, 'name', args: args.
|
83
|
+
name = param_guard(action, 'name', args: args.extras)
|
84
84
|
else
|
85
85
|
save = 'prod'
|
86
86
|
name = param_guard(action, 'name', args: args.to_a)
|
@@ -90,10 +90,10 @@ module Squared
|
|
90
90
|
when 'run'
|
91
91
|
next if (list = read_scripts).empty?
|
92
92
|
|
93
|
-
format_desc action, nil,
|
93
|
+
format_desc action, nil, "command+|#{indexchar}index|#,pattern*"
|
94
94
|
task action, [:command] do |_, args|
|
95
95
|
if args.command == '#'
|
96
|
-
format_list(list,
|
96
|
+
format_list(list, "run[#{indexchar}N]", 'scripts', grep: args.extras, from: dependfile.to_s)
|
97
97
|
else
|
98
98
|
cmd = param_guard(action, 'command', args: args.to_a)
|
99
99
|
cmd.each do |val|
|
@@ -690,7 +690,7 @@ module Squared
|
|
690
690
|
def read_packagemanager(key = nil, version: nil, update: false)
|
691
691
|
if @pm[:_].nil? || update
|
692
692
|
doc = JSON.parse(dependfile.read)
|
693
|
-
@pm[:_] = (val = doc['packageManager']) ? val[0..(val.index('+') || 0) - 1] : false
|
693
|
+
@pm[:_] = (val = doc['packageManager']) ? val[0..((val.index('+') || 0) - 1)] : false
|
694
694
|
@pm[:name] = doc['name']
|
695
695
|
@pm[:scripts] = doc['scripts']
|
696
696
|
@pm[:version] = doc['version']
|
@@ -703,7 +703,7 @@ module Squared
|
|
703
703
|
else
|
704
704
|
return @pm[key] if key
|
705
705
|
|
706
|
-
!(ret = @pm[:_]) || (version && ret[ret.index('@') + 1..-1] < version) ? nil : ret
|
706
|
+
!(ret = @pm[:_]) || (version && ret[(ret.index('@') + 1)..-1] < version) ? nil : ret
|
707
707
|
end
|
708
708
|
|
709
709
|
def read_install
|
@@ -110,11 +110,11 @@ module Squared
|
|
110
110
|
when 'rake'
|
111
111
|
next unless rakefile
|
112
112
|
|
113
|
-
format_desc action, nil,
|
113
|
+
format_desc action, nil, "command*|#{indexchar}index,args*|#,pattern*"
|
114
114
|
task action, [:command] do |_, args|
|
115
115
|
if args.command == '#'
|
116
|
-
format_list(read_rakefile,
|
117
|
-
|
116
|
+
format_list(read_rakefile, "rake[#{indexchar}N]", 'tasks', grep: args.extras, from: rakefile.to_s,
|
117
|
+
each: ->(val) { val[0] + val[1].to_s })
|
118
118
|
elsif (data = indexitem(args.command))
|
119
119
|
n, opts = data
|
120
120
|
list = read_rakefile
|
@@ -470,8 +470,8 @@ module Squared
|
|
470
470
|
cmd << shell_escape(project)
|
471
471
|
version = name[1..-1]
|
472
472
|
else
|
473
|
-
cmd << shell_escape(name[0..n - 1])
|
474
|
-
version = name[n + 1..-1]
|
473
|
+
cmd << shell_escape(name[0..(n - 1)])
|
474
|
+
version = name[(n + 1)..-1]
|
475
475
|
end
|
476
476
|
cmd << shell_option('version', version)
|
477
477
|
out.clear
|
@@ -172,7 +172,7 @@ module Squared
|
|
172
172
|
parse_opts.(args)
|
173
173
|
stage = 'init'
|
174
174
|
puts if newline
|
175
|
-
|
175
|
+
Common::System.shell("repo init -u #{manifest_url} -m #{args.manifest || target}.xml", chdir: root)
|
176
176
|
repo['all'].invoke
|
177
177
|
end
|
178
178
|
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: squared
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- An Pham
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: rake
|
@@ -107,7 +106,6 @@ metadata:
|
|
107
106
|
homepage_uri: https://github.com/anpham6/squared
|
108
107
|
source_code_uri: https://github.com/anpham6/squared
|
109
108
|
documentation_uri: https://squared.readthedocs.io
|
110
|
-
post_install_message:
|
111
109
|
rdoc_options: []
|
112
110
|
require_paths:
|
113
111
|
- lib
|
@@ -122,8 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
120
|
- !ruby/object:Gem::Version
|
123
121
|
version: '0'
|
124
122
|
requirements: []
|
125
|
-
rubygems_version: 3.
|
126
|
-
signing_key:
|
123
|
+
rubygems_version: 3.6.7
|
127
124
|
specification_version: 4
|
128
125
|
summary: Rake task generator for managing multi-language workspaces.
|
129
126
|
test_files: []
|