cog 0.0.15 → 0.0.16
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.
- 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:
|