cog 0.0.15 → 0.0.16
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/cog +31 -32
- data/lib/cog/generator.rb +44 -15
- data/lib/cog/spec_helpers.rb +7 -2
- data/lib/cog/spec_helpers/matchers.rb +17 -7
- data/lib/cog/spec_helpers/matchers/match_maker.rb +12 -3
- data/lib/cog/spec_helpers/runner.rb +11 -5
- data/lib/cog/tool.rb +45 -20
- data/lib/cog/version.rb +1 -1
- metadata +35 -7
data/bin/cog
CHANGED
@@ -4,12 +4,15 @@ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
|
4
4
|
require 'cog'
|
5
5
|
require 'active_support/core_ext'
|
6
6
|
require 'fileutils'
|
7
|
+
require 'rainbow'
|
7
8
|
|
8
9
|
include GLI::App
|
9
10
|
|
10
11
|
program_desc 'This is a utility to help you write code generators.'
|
11
12
|
|
12
13
|
# version Cog::VERSION
|
14
|
+
desc 'Output more detailed information when running a command'
|
15
|
+
switch :v
|
13
16
|
|
14
17
|
desc 'Add cog to the project in the present working directory'
|
15
18
|
skips_pre
|
@@ -22,7 +25,7 @@ end
|
|
22
25
|
|
23
26
|
desc 'Create a generator (or leave name blank to list project generators)'
|
24
27
|
arg_name 'name'
|
25
|
-
command :generator do |c|
|
28
|
+
command [:generator, :gen] do |c|
|
26
29
|
|
27
30
|
c.desc 'which tool to use to create the generator'
|
28
31
|
c.arg_name 'tool_name'
|
@@ -32,14 +35,12 @@ command :generator do |c|
|
|
32
35
|
c.action do |global_options, options, args|
|
33
36
|
if args.empty?
|
34
37
|
# List
|
35
|
-
x = Cog::Generator.list
|
36
|
-
puts x.
|
38
|
+
x = Cog::Generator.list global_options[:v]
|
39
|
+
puts x.join "\n" unless x.empty?
|
37
40
|
else
|
38
41
|
# Create
|
39
42
|
args.each do |name|
|
40
|
-
|
41
|
-
puts "Failed to create generator #{name}"
|
42
|
-
end
|
43
|
+
Cog::Generator.create name, :tool => options[:tool], :verbose => global_options[:v]
|
43
44
|
end
|
44
45
|
end
|
45
46
|
end
|
@@ -52,47 +53,39 @@ command :tool do |c|
|
|
52
53
|
|
53
54
|
c.action do |global_options, options, args|
|
54
55
|
if args.empty?
|
55
|
-
|
56
|
-
|
56
|
+
# List
|
57
|
+
x = Cog::Tool.list global_options[:v]
|
58
|
+
puts x.join "\n" unless x.empty?
|
57
59
|
else
|
60
|
+
# Create
|
58
61
|
args.each do |name|
|
59
|
-
|
60
|
-
Cog::Tool.create name
|
61
|
-
else
|
62
|
-
puts "Could not create tool for '#{name}', a file or directory already exists with that name"
|
63
|
-
end
|
62
|
+
Cog::Tool.create name
|
64
63
|
end
|
65
64
|
end
|
66
65
|
end
|
67
66
|
end
|
68
67
|
|
69
|
-
desc 'List supported languages'
|
70
|
-
skips_pre
|
71
|
-
command :languages do |c|
|
72
|
-
|
73
|
-
c.action do
|
74
|
-
puts 'c++'
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
68
|
desc 'Run generators in the current project'
|
79
69
|
arg_name 'generator_name'
|
80
70
|
command :run do |c|
|
81
71
|
|
82
72
|
c.action do |global_options, options, args|
|
83
73
|
args = Cog::Generator.list if args.empty?
|
84
|
-
args.each do |
|
85
|
-
|
86
|
-
if File.exists? filename
|
87
|
-
puts "Running generator #{gen}"
|
88
|
-
require filename
|
89
|
-
else
|
90
|
-
puts "No such generator #{gen}"
|
91
|
-
end
|
74
|
+
args.each do |name|
|
75
|
+
Cog::Generator.run name, :verbose => global_options[:v]
|
92
76
|
end
|
93
77
|
end
|
94
78
|
end
|
95
79
|
|
80
|
+
desc 'List supported languages'
|
81
|
+
skips_pre
|
82
|
+
command :languages do |c|
|
83
|
+
|
84
|
+
c.action do
|
85
|
+
puts 'c++'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
96
89
|
pre do |global_options, command, options, args|
|
97
90
|
# Pre logic here
|
98
91
|
# Return true to proceed; false to abort and not call the
|
@@ -100,7 +93,8 @@ pre do |global_options, command, options, args|
|
|
100
93
|
# Use skips_pre before a command to skip this block
|
101
94
|
# on that command only
|
102
95
|
unless Cog::Config.instance.project?
|
103
|
-
|
96
|
+
STDERR.write "No Cogfile could be found\n".color(:red)
|
97
|
+
STDOUT.write "Run `cog init` to prepare a project for use with cog\n"
|
104
98
|
false
|
105
99
|
else
|
106
100
|
true
|
@@ -119,4 +113,9 @@ on_error do |exception|
|
|
119
113
|
true
|
120
114
|
end
|
121
115
|
|
122
|
-
|
116
|
+
begin
|
117
|
+
exit run(ARGV)
|
118
|
+
rescue
|
119
|
+
# Don't show stack traces during normal use
|
120
|
+
raise unless ENV['COG_DEBUG'].nil? || /^(|0|false|no|off)$/i =~ ENV['COG_DEBUG']
|
121
|
+
end
|
data/lib/cog/generator.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'cog/config'
|
2
2
|
require 'cog/errors'
|
3
3
|
require 'erb'
|
4
|
+
require 'rainbow'
|
4
5
|
|
5
6
|
module Cog
|
6
7
|
|
@@ -12,11 +13,10 @@ module Cog
|
|
12
13
|
module Generator
|
13
14
|
|
14
15
|
# A list of available project generators
|
15
|
-
def self.list
|
16
|
+
def self.list(verbose=false)
|
16
17
|
if Config.instance.project?
|
17
|
-
Dir.glob(File.join Config.instance.project_generators_path, '*.rb')
|
18
|
-
|
19
|
-
end
|
18
|
+
x = Dir.glob(File.join Config.instance.project_generators_path, '*.rb')
|
19
|
+
verbose ? x : (x.collect {|path| File.basename(path).slice(0..-4)})
|
20
20
|
else
|
21
21
|
[]
|
22
22
|
end
|
@@ -37,15 +37,43 @@ module Cog
|
|
37
37
|
return false unless Config.instance.project?
|
38
38
|
gen_name = File.join Config.instance.project_generators_path, "#{name}.rb"
|
39
39
|
template_name = File.join Config.instance.project_templates_path, "#{name}.txt.erb"
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
40
|
+
if File.exists? gen_name
|
41
|
+
STDERR.write "Generator '#{gen_name}' already exists\n".color(:red)
|
42
|
+
false
|
43
|
+
elsif File.exists? template_name
|
44
|
+
STDERR.write "Template '#{template_name}' already exists\n".color(:red)
|
45
|
+
false
|
46
|
+
else
|
47
|
+
Object.new.instance_eval do
|
48
|
+
extend Generator
|
49
|
+
@name = name
|
50
|
+
@class_name = name.to_s.camelize
|
51
|
+
stamp 'cog/generator/basic.rb', gen_name, :absolute_destination => true
|
52
|
+
stamp 'cog/generator/basic-template.txt.erb', template_name, :absolute_destination => true
|
53
|
+
end
|
54
|
+
true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Run the generator with the given name
|
59
|
+
#
|
60
|
+
# ==== Arguments
|
61
|
+
# * +name+ - the name of the generator
|
62
|
+
#
|
63
|
+
# ==== Returns
|
64
|
+
# Whether or not the generator could be found
|
65
|
+
def self.run(name, opt={})
|
66
|
+
filename = File.join Cog::Config.instance.project_generators_path, "#{name}.rb"
|
67
|
+
if File.exists? filename
|
68
|
+
require filename
|
69
|
+
return true
|
47
70
|
end
|
48
|
-
|
71
|
+
STDERR.write "No such generator '#{name}'\n".color(:red)
|
72
|
+
false
|
73
|
+
rescue => e
|
74
|
+
trace = opt[:verbose] ? "\n#{e.backtrace.join "\n"}" : ''
|
75
|
+
STDERR.write "Generator '#{name}' failed: #{e}#{trace}\n".color(:red)
|
76
|
+
false
|
49
77
|
end
|
50
78
|
|
51
79
|
# Get the template with the given name.
|
@@ -93,8 +121,9 @@ module Cog
|
|
93
121
|
if same? dest, scratch
|
94
122
|
FileUtils.rm scratch
|
95
123
|
else
|
96
|
-
|
124
|
+
updated = File.exists? dest
|
97
125
|
FileUtils.mv scratch, dest
|
126
|
+
STDOUT.write "#{updated ? :Updated : :Created} #{dest}\n".color(updated ? :white : :green)
|
98
127
|
end
|
99
128
|
nil
|
100
129
|
end
|
@@ -103,7 +132,7 @@ module Cog
|
|
103
132
|
def copy_if_missing(src, dest)
|
104
133
|
unless File.exists? dest
|
105
134
|
FileUtils.cp src, dest
|
106
|
-
|
135
|
+
STDOUT.write "Created #{dest}".color(:white)
|
107
136
|
end
|
108
137
|
end
|
109
138
|
|
@@ -112,7 +141,7 @@ module Cog
|
|
112
141
|
path = File.join path_components
|
113
142
|
unless File.exists? path
|
114
143
|
FileUtils.mkdir_p path
|
115
|
-
|
144
|
+
STDOUT.write "Created #{path}".color(:white)
|
116
145
|
end
|
117
146
|
end
|
118
147
|
|
data/lib/cog/spec_helpers.rb
CHANGED
@@ -48,7 +48,12 @@ module Cog
|
|
48
48
|
|
49
49
|
# Path to the generator with the given name
|
50
50
|
def generator(name)
|
51
|
-
File.join
|
51
|
+
File.expand_path File.join(active_fixture_dir, 'cog', 'generators', "#{name}.rb")
|
52
|
+
end
|
53
|
+
|
54
|
+
# Path to the test tool with the given name
|
55
|
+
def tool(name)
|
56
|
+
File.expand_path File.join(spec_root, 'tools', name.to_s)
|
52
57
|
end
|
53
58
|
|
54
59
|
# The next cog spec will execute in a fresh copy of the given fixture directory.
|
@@ -56,7 +61,7 @@ module Cog
|
|
56
61
|
def use_fixture(name)
|
57
62
|
path = File.join spec_root, 'fixtures', name.to_s
|
58
63
|
if File.exists?(path) && File.directory?(path)
|
59
|
-
FileUtils.
|
64
|
+
FileUtils.rm_rf active_fixture_dir if File.exists? active_fixture_dir
|
60
65
|
FileUtils.cp_r path, active_fixture_dir
|
61
66
|
Dir.chdir active_fixture_dir
|
62
67
|
else
|
@@ -8,18 +8,18 @@ module Cog
|
|
8
8
|
# Check out #match_maker for help writing new matchers.
|
9
9
|
module Matchers
|
10
10
|
|
11
|
-
# The target Invocation should
|
12
|
-
def
|
11
|
+
# The target Invocation should write something to STDERR, indicating an error
|
12
|
+
def complain
|
13
13
|
match_maker do
|
14
|
-
message { "to [
|
15
|
-
test {
|
14
|
+
message { "to [write something|not write anything] to STDERR" }
|
15
|
+
test { !error.empty? }
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
# The target Invocation should create a +Cogfile+ where none existed before
|
20
20
|
def make(path)
|
21
21
|
match_maker do
|
22
|
-
message { "to [create|not create] #{path}
|
22
|
+
message { "to [create|not create] #{path}" }
|
23
23
|
before do
|
24
24
|
@existed = File.exists? path
|
25
25
|
end
|
@@ -32,15 +32,25 @@ module Cog
|
|
32
32
|
# The target Invocation should do something, as determined by standard output
|
33
33
|
def do_something
|
34
34
|
match_maker do
|
35
|
-
message { "to [write something|not write anything] to
|
35
|
+
message { "to [write something|not write anything] to STDOUT" }
|
36
36
|
test { !lines.empty? }
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
+
# The target Invocation should write the given list of lines to standard output
|
41
|
+
def output(x)
|
42
|
+
match_maker do
|
43
|
+
message { "to [write|not write] #{x.join "\n"} to STDOUT"}
|
44
|
+
test do
|
45
|
+
lines.zip(x).all? {|a, b| a.strip == b.to_s.strip}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
40
50
|
# The target Invocation should output the default help text
|
41
51
|
def show_help
|
42
52
|
match_maker do
|
43
|
-
message { "to [show|not show] the default help text, got #{lines.first.inspect}
|
53
|
+
message { "to [show|not show] the default help text, got #{lines.first.inspect}" }
|
44
54
|
test { (/help.*code gen/ =~ lines[1]) }
|
45
55
|
end
|
46
56
|
end
|
@@ -5,9 +5,13 @@ module Cog
|
|
5
5
|
# Within Matchers#match_maker blocks, +self+ is set to an instance of this
|
6
6
|
# class.
|
7
7
|
class MatchMaker
|
8
|
-
|
8
|
+
|
9
|
+
# A list of lines read from STDOUT after executing the Invocation
|
9
10
|
attr_reader :lines
|
10
11
|
|
12
|
+
# A list of lines read from STDERR after executing the Invocation
|
13
|
+
attr_reader :error
|
14
|
+
|
11
15
|
# Define a block which runs after a test fails and should return
|
12
16
|
# a failure message template.
|
13
17
|
#
|
@@ -44,18 +48,23 @@ module Cog
|
|
44
48
|
instance_eval &@before_block unless @before_block.nil?
|
45
49
|
@runner.exec do |input, output, error|
|
46
50
|
@lines = output.readlines
|
51
|
+
@error = error.readlines
|
47
52
|
end
|
48
53
|
instance_eval &@test_block
|
49
54
|
end
|
50
55
|
def failure_message # :nodoc:
|
51
56
|
msg = instance_eval &@msg_block
|
52
57
|
msg = msg.gsub /\[([^\|\]]*)(?:\|([^\]]*)\])?/, '\1'
|
53
|
-
"expected #{@runner} #{msg}"
|
58
|
+
"expected #{@runner} #{msg}\n#{trace}"
|
54
59
|
end
|
55
60
|
def negative_failure_message # :nodoc:
|
56
61
|
msg = instance_eval &@msg_block
|
57
62
|
msg = msg.gsub /\[([^\|\]]*)(?:\|([^\]]*)\])?/, '\2'
|
58
|
-
"expected #{@runner} #{msg}"
|
63
|
+
"expected #{@runner} #{msg}\n#{trace}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def trace # :nodoc
|
67
|
+
"STDOUT:\n#{@lines.join "\n"}\nSTDERR:\n#{@error.join "\n"}"
|
59
68
|
end
|
60
69
|
end
|
61
70
|
|
@@ -6,8 +6,12 @@ module Cog
|
|
6
6
|
# Points to the +cog+ command-line app
|
7
7
|
class Runner
|
8
8
|
|
9
|
+
# Value of the COG_TOOLS environment variable for invocations returned from #run
|
10
|
+
attr_accessor :tools
|
11
|
+
|
9
12
|
def initialize(path_to_cl_app)
|
10
13
|
@cog = File.expand_path path_to_cl_app
|
14
|
+
@tools = []
|
11
15
|
end
|
12
16
|
|
13
17
|
# Run cog with the given arguments
|
@@ -16,8 +20,8 @@ module Cog
|
|
16
20
|
# An instance of Invocation configured with the arguments. Use should and
|
17
21
|
# should_not with the custom Matchers
|
18
22
|
def run(*args)
|
19
|
-
args = [
|
20
|
-
Invocation.new(args.collect {|x| x.to_s})
|
23
|
+
args = [@cog] + args
|
24
|
+
Invocation.new(args.collect {|x| x.to_s}, :tools => @tools)
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
@@ -26,19 +30,21 @@ module Cog
|
|
26
30
|
# object returned by Runner#run.
|
27
31
|
class Invocation
|
28
32
|
|
29
|
-
def initialize(cmd) # :nodoc:
|
33
|
+
def initialize(cmd, opt={}) # :nodoc:
|
30
34
|
@cmd = cmd
|
35
|
+
@tools = opt[:tools].join ':'
|
31
36
|
end
|
32
37
|
|
33
38
|
def exec(*args, &block) # :nodoc:
|
34
|
-
@
|
39
|
+
@cmd = ['bundle', 'exec'] + @cmd
|
40
|
+
ENV['COG_TOOLS'] = @tools
|
35
41
|
Open3.popen3 *@cmd do |i,o,e,t|
|
36
42
|
block.call i,o,e
|
37
43
|
end
|
38
44
|
end
|
39
45
|
|
40
46
|
def to_s # :nodoc:
|
41
|
-
"
|
47
|
+
"`COG_TOOLS=#{@tools} #{@cmd.compact.join ' '}`"
|
42
48
|
end
|
43
49
|
end
|
44
50
|
|
data/lib/cog/tool.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'cog/config'
|
2
2
|
require 'cog/generator'
|
3
|
+
require 'rainbow'
|
3
4
|
|
4
5
|
module Cog
|
5
6
|
|
@@ -7,30 +8,54 @@ module Cog
|
|
7
8
|
class Tool
|
8
9
|
|
9
10
|
# A list of available tools
|
10
|
-
def self.list
|
11
|
-
|
12
|
-
|
11
|
+
def self.list(verbose=false)
|
12
|
+
x = (ENV['COG_TOOLS'] || '').split ':'
|
13
|
+
if x.all? {|path| File.exists?(path) && File.directory?(path)}
|
14
|
+
if verbose
|
15
|
+
x.collect {|path| File.expand_path path}
|
16
|
+
else
|
17
|
+
x.collect {|path| File.basename path}
|
18
|
+
end
|
19
|
+
else
|
20
|
+
x.each do |path|
|
21
|
+
if !File.exists? path
|
22
|
+
STDERR.write "No such cog tool at path '#{path}'\n".color(:red)
|
23
|
+
elsif !File.directory? path
|
24
|
+
STDERR.write "Not a cog tool at path '#{path}'\n".color(:red)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
[]
|
28
|
+
end
|
13
29
|
end
|
14
30
|
|
15
31
|
# Generate a new tool with the given name
|
32
|
+
#
|
33
|
+
# ==== Returns
|
34
|
+
# Whether or not the generator was created successfully
|
16
35
|
def self.create(name)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
if File.exists? name
|
37
|
+
STDERR.write "A #{File.directory?(name) ? :directory : :file} named '#{name}' already exists\n".color(:red)
|
38
|
+
false
|
39
|
+
else
|
40
|
+
Object.new.instance_eval do
|
41
|
+
extend Generator
|
42
|
+
@name = name.to_s.downcase
|
43
|
+
@module_name = name.to_s.capitalize
|
44
|
+
@author = '<Your name goes here>'
|
45
|
+
@email = 'youremail@...'
|
46
|
+
@description = 'A one-liner'
|
47
|
+
@cog_version = Cog::VERSION
|
48
|
+
stamp 'cog/tool/tool.rb', "#{@name}/lib/#{@name}.rb", :absolute_destination => true
|
49
|
+
stamp 'cog/tool/version.rb', "#{@name}/lib/#{@name}/version.rb", :absolute_destination => true
|
50
|
+
stamp 'cog/tool/generator.rb', "#{@name}/cog/templates/#{@name}/generator.rb.erb", :absolute_destination => true
|
51
|
+
stamp 'cog/tool/Gemfile', "#{@name}/Gemfile", :absolute_destination => true
|
52
|
+
stamp 'cog/tool/Rakefile', "#{@name}/Rakefile", :absolute_destination => true
|
53
|
+
stamp 'cog/tool/tool.gemspec', "#{@name}/#{@name}.gemspec", :absolute_destination => true
|
54
|
+
stamp 'cog/tool/API.rdoc', "#{@name}/API.rdoc", :absolute_destination => true
|
55
|
+
stamp 'cog/tool/LICENSE', "#{@name}/LICENSE", :absolute_destination => true
|
56
|
+
stamp 'cog/tool/README.markdown', "#{@name}/README.markdown", :absolute_destination => true
|
57
|
+
end
|
58
|
+
true
|
34
59
|
end
|
35
60
|
end
|
36
61
|
end
|
data/lib/cog/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 63
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 16
|
10
|
+
version: 0.0.16
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kevin Tonon
|
@@ -18,7 +18,7 @@ cert_chain: []
|
|
18
18
|
date: 2012-11-04 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: gli
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
none: false
|
@@ -29,10 +29,10 @@ dependencies:
|
|
29
29
|
segments:
|
30
30
|
- 0
|
31
31
|
version: "0"
|
32
|
-
type: :
|
32
|
+
type: :runtime
|
33
33
|
version_requirements: *id001
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
|
-
name:
|
35
|
+
name: rainbow
|
36
36
|
prerelease: false
|
37
37
|
requirement: &id002 !ruby/object:Gem::Requirement
|
38
38
|
none: false
|
@@ -43,8 +43,36 @@ dependencies:
|
|
43
43
|
segments:
|
44
44
|
- 0
|
45
45
|
version: "0"
|
46
|
-
type: :
|
46
|
+
type: :runtime
|
47
47
|
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rake
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rdoc
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
type: :development
|
75
|
+
version_requirements: *id004
|
48
76
|
description:
|
49
77
|
email: kevin@betweenconcepts.com
|
50
78
|
executables:
|