cuki 0.0.6 → 0.0.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.
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/VERSION +1 -1
- data/cucumber.yml +2 -0
- data/cuki.gemspec +8 -2
- data/features/pull/pull.feature +3 -3
- data/features/pull/pull_single.feature +1 -1
- data/features/pull/splitting.feature +67 -0
- data/features/pull/tables.feature +2 -2
- data/features/pull/tags.feature +2 -2
- data/features/pull/textile.feature +2 -2
- data/features/push/push.feature +1 -1
- data/features/step_defs/pull_steps.rb +1 -1
- data/lib/cuki.rb +85 -17
- data/lib/string_utils.rb +9 -0
- metadata +29 -12
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.7
|
data/cucumber.yml
ADDED
data/cuki.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "cuki"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Andy Waite"]
|
12
|
-
s.date = "2011-10-
|
12
|
+
s.date = "2011-10-17"
|
13
13
|
s.description = ""
|
14
14
|
s.email = "andy@andywaite.com"
|
15
15
|
s.executables = ["cuki"]
|
@@ -28,10 +28,12 @@ Gem::Specification.new do |s|
|
|
28
28
|
"Rakefile",
|
29
29
|
"VERSION",
|
30
30
|
"bin/cuki",
|
31
|
+
"cucumber.yml",
|
31
32
|
"cuki.gemspec",
|
32
33
|
"cuki.yaml.sample",
|
33
34
|
"features/pull/pull.feature",
|
34
35
|
"features/pull/pull_single.feature",
|
36
|
+
"features/pull/splitting.feature",
|
35
37
|
"features/pull/tables.feature",
|
36
38
|
"features/pull/tags.feature",
|
37
39
|
"features/pull/textile.feature",
|
@@ -43,6 +45,7 @@ Gem::Specification.new do |s|
|
|
43
45
|
"features/support/env.rb",
|
44
46
|
"lib/cuki.rb",
|
45
47
|
"lib/pusher.rb",
|
48
|
+
"lib/string_utils.rb",
|
46
49
|
"spec/cuki_spec.rb",
|
47
50
|
"spec/spec_helper.rb"
|
48
51
|
]
|
@@ -58,6 +61,7 @@ Gem::Specification.new do |s|
|
|
58
61
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
62
|
s.add_runtime_dependency(%q<httpclient>, [">= 0"])
|
60
63
|
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
64
|
+
s.add_runtime_dependency(%q<parallel>, [">= 0"])
|
61
65
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
62
66
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
63
67
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
@@ -66,6 +70,7 @@ Gem::Specification.new do |s|
|
|
66
70
|
else
|
67
71
|
s.add_dependency(%q<httpclient>, [">= 0"])
|
68
72
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
73
|
+
s.add_dependency(%q<parallel>, [">= 0"])
|
69
74
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
70
75
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
71
76
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
@@ -75,6 +80,7 @@ Gem::Specification.new do |s|
|
|
75
80
|
else
|
76
81
|
s.add_dependency(%q<httpclient>, [">= 0"])
|
77
82
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
83
|
+
s.add_dependency(%q<parallel>, [">= 0"])
|
78
84
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
79
85
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
80
86
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
data/features/pull/pull.feature
CHANGED
@@ -38,12 +38,12 @@ Feature: Pull
|
|
38
38
|
This feature describes removing a product
|
39
39
|
</div>
|
40
40
|
"""
|
41
|
-
When I run `cuki pull`
|
41
|
+
When I run `cuki pull --skip-autoformat --skip-header`
|
42
42
|
Then the file "features/products/add_product.feature" should contain exactly:
|
43
43
|
"""
|
44
44
|
Feature: Add Product
|
45
45
|
|
46
|
-
http://example.com/pages/
|
46
|
+
http://example.com/pages/viewpage.action?pageId=123
|
47
47
|
|
48
48
|
|
49
49
|
This feature describes adding a product
|
@@ -53,7 +53,7 @@ Feature: Pull
|
|
53
53
|
"""
|
54
54
|
Feature: Remove Product
|
55
55
|
|
56
|
-
http://example.com/pages/
|
56
|
+
http://example.com/pages/viewpage.action?pageId=456
|
57
57
|
|
58
58
|
|
59
59
|
This feature describes removing a product
|
@@ -23,7 +23,7 @@ Feature: Pull single
|
|
23
23
|
This feature describes removing a product
|
24
24
|
</div>
|
25
25
|
"""
|
26
|
-
When I run `cuki pull features/products/add_product.feature`
|
26
|
+
When I run `cuki pull features/products/add_product.feature --skip-autoformat --skip-header`
|
27
27
|
Then a file named "features/products/add_product.feature" should exist
|
28
28
|
But the file "features/products/remove_product.feature" should not exist
|
29
29
|
|
@@ -0,0 +1,67 @@
|
|
1
|
+
Feature: Splitting
|
2
|
+
|
3
|
+
Instead of association one wiki page per feature file, you can split a wiki file across multiple feature files.
|
4
|
+
|
5
|
+
@announce
|
6
|
+
Scenario: Pull all features
|
7
|
+
Given a file named "config/cuki.yaml" with:
|
8
|
+
"""
|
9
|
+
---
|
10
|
+
host: http://example.com
|
11
|
+
container: !ruby/regexp '/h1\. Acceptance Criteria(.*)h1\./m'
|
12
|
+
mappings:
|
13
|
+
123: features/products
|
14
|
+
"""
|
15
|
+
And a Confluence page on "example.com" with id 123:
|
16
|
+
"""
|
17
|
+
<input id="content-title" value="Product Management">
|
18
|
+
<div id="markupTextarea">
|
19
|
+
h1. Acceptance Criteria
|
20
|
+
|
21
|
+
Something
|
22
|
+
|
23
|
+
h2. Add Product
|
24
|
+
|
25
|
+
This feature describes adding a product
|
26
|
+
|
27
|
+
h6. Scenario: Scenario A
|
28
|
+
|
29
|
+
h2. Remove Product
|
30
|
+
|
31
|
+
This feature describes removing a product
|
32
|
+
|
33
|
+
h6. Scenario Outline: Scenario B
|
34
|
+
|
35
|
+
h1. Next Section
|
36
|
+
</div>
|
37
|
+
"""
|
38
|
+
When I run `cuki pull --skip-autoformat --skip-header`
|
39
|
+
Then the file "features/products/add_product.feature" should contain exactly:
|
40
|
+
"""
|
41
|
+
Feature: Add Product
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
http://example.com/pages/viewpage.action?pageId=123#ProductManagement-AddProduct
|
46
|
+
|
47
|
+
This feature describes adding a product
|
48
|
+
|
49
|
+
Scenario: Scenario A
|
50
|
+
|
51
|
+
|
52
|
+
"""
|
53
|
+
And the file "features/products/remove_product.feature" should contain exactly:
|
54
|
+
"""
|
55
|
+
Feature: Remove Product
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
http://example.com/pages/viewpage.action?pageId=123#ProductManagement-RemoveProduct
|
60
|
+
|
61
|
+
This feature describes removing a product
|
62
|
+
|
63
|
+
Scenario Outline: Scenario B
|
64
|
+
|
65
|
+
|
66
|
+
"""
|
67
|
+
|
@@ -21,12 +21,12 @@ Feature: Tables
|
|
21
21
|
| b | 2 |
|
22
22
|
</div>
|
23
23
|
"""
|
24
|
-
When I run `cuki pull`
|
24
|
+
When I run `cuki pull --skip-autoformat --skip-header`
|
25
25
|
Then the file "features/products/add_product.feature" should contain exactly:
|
26
26
|
"""
|
27
27
|
Feature: Add Product
|
28
28
|
|
29
|
-
http://example.com/pages/
|
29
|
+
http://example.com/pages/viewpage.action?pageId=123
|
30
30
|
|
31
31
|
|
32
32
|
Scenario: Foo
|
data/features/pull/tags.feature
CHANGED
@@ -18,13 +18,13 @@ Feature: Tags
|
|
18
18
|
h5. Scenario: Foo
|
19
19
|
</div>
|
20
20
|
"""
|
21
|
-
When I run `cuki pull`
|
21
|
+
When I run `cuki pull --skip-autoformat --skip-header`
|
22
22
|
Then the file "features/products/add_product.feature" should contain exactly:
|
23
23
|
"""
|
24
24
|
@draft
|
25
25
|
Feature: Add Product
|
26
26
|
|
27
|
-
http://example.com/pages/
|
27
|
+
http://example.com/pages/viewpage.action?pageId=123
|
28
28
|
|
29
29
|
|
30
30
|
Scenario: Foo
|
@@ -17,12 +17,12 @@ Feature: Textile
|
|
17
17
|
h6. Scenario Outline: Bar
|
18
18
|
</div>
|
19
19
|
"""
|
20
|
-
When I run `cuki pull`
|
20
|
+
When I run `cuki pull --skip-autoformat --skip-header`
|
21
21
|
Then the file "features/products/add_product.feature" should contain exactly:
|
22
22
|
"""
|
23
23
|
Feature: Add Product
|
24
24
|
|
25
|
-
http://example.com/pages/
|
25
|
+
http://example.com/pages/viewpage.action?pageId=123
|
26
26
|
|
27
27
|
|
28
28
|
Scenario: Foo
|
data/features/push/push.feature
CHANGED
@@ -4,7 +4,7 @@ Given /^a Confluence page on "([^"]*)" with id (\d+):$/ do |host, id, content|
|
|
4
4
|
# the URLs to be stubbed
|
5
5
|
|
6
6
|
@stubs ||= {}
|
7
|
-
@stubs["http://#{host}/pages/
|
7
|
+
@stubs["http://#{host}/pages/viewpage.action?pageId=#{id}"] = content
|
8
8
|
|
9
9
|
File.open('stubs.json', 'w') do |f|
|
10
10
|
f.write @stubs.to_json
|
data/lib/cuki.rb
CHANGED
@@ -4,6 +4,8 @@ require 'nokogiri'
|
|
4
4
|
require 'yaml'
|
5
5
|
require 'CGI'
|
6
6
|
require 'json'
|
7
|
+
require 'parallel'
|
8
|
+
require File.dirname(__FILE__) + '/string_utils.rb'
|
7
9
|
|
8
10
|
# terrible hack
|
9
11
|
if File.exist?('stubs.json') || File.exist?('stubs.json')
|
@@ -25,18 +27,28 @@ class Cuki
|
|
25
27
|
configure_http_client
|
26
28
|
|
27
29
|
action = args.first
|
30
|
+
if args.include?('--skip-autoformat')
|
31
|
+
args.delete_if { |arg| '--skip-autoformat' == arg }
|
32
|
+
@skip_autoformat = true
|
33
|
+
end
|
34
|
+
if args.include?('--skip-header')
|
35
|
+
args.delete_if { |arg| '--skip-header' == arg }
|
36
|
+
@skip_header = true
|
37
|
+
end
|
28
38
|
if 'pull' == action
|
29
39
|
configure_pull_stubs
|
30
40
|
verify_project
|
31
41
|
file = args[1]
|
32
42
|
if file
|
33
43
|
id = @config['mappings'].invert[file]
|
34
|
-
raise "could not get id for #{file}"
|
44
|
+
raise "could not get id for #{file}" unless id
|
35
45
|
pull_feature id, file
|
36
46
|
else
|
37
|
-
@config['mappings']
|
47
|
+
Parallel.map(@config['mappings'], :in_processes => 4) do |id, filepath|
|
48
|
+
pull_feature id, filepath
|
49
|
+
end
|
38
50
|
end
|
39
|
-
|
51
|
+
autoformat
|
40
52
|
elsif 'push' == action
|
41
53
|
configure_push_stubs
|
42
54
|
Pusher.push file, @config
|
@@ -51,7 +63,7 @@ class Cuki
|
|
51
63
|
def verify_project
|
52
64
|
# check features folder exists
|
53
65
|
raise "features folder not found" unless File.exists?('features')
|
54
|
-
|
66
|
+
autoformat
|
55
67
|
end
|
56
68
|
|
57
69
|
def read_config
|
@@ -72,35 +84,80 @@ class Cuki
|
|
72
84
|
|
73
85
|
def pull_feature(id, filepath)
|
74
86
|
@content = ''
|
75
|
-
|
76
|
-
|
77
|
-
|
87
|
+
wiki_edit_link = @config['host'] + '/pages/editpage.action?pageId=' + id.to_s
|
88
|
+
wiki_view_link = @config['host'] + '/pages/viewpage.action?pageId=' + id.to_s
|
89
|
+
puts "Downloading #{wiki_edit_link}"
|
90
|
+
response = @client.get wiki_edit_link
|
78
91
|
doc = Nokogiri(response.body)
|
79
|
-
|
92
|
+
|
80
93
|
unless doc.at('#content-title')
|
81
94
|
puts "Not a valid confluence page:"
|
82
95
|
puts doc.to_s
|
83
96
|
exit(1)
|
84
97
|
end
|
85
98
|
|
86
|
-
@
|
87
|
-
|
88
|
-
|
99
|
+
if @config['container']
|
100
|
+
handle_multi doc, id
|
101
|
+
else
|
102
|
+
|
103
|
+
@content += "Feature: " + doc.at('#content-title')[:value] + "\n\n"
|
104
|
+
@content += "#{wiki_view_link}\n\n"
|
105
|
+
@content += get_markup(doc)
|
89
106
|
|
90
|
-
|
107
|
+
clean
|
91
108
|
|
92
|
-
|
109
|
+
process_tags
|
93
110
|
|
94
|
-
|
111
|
+
@content = "# Generated by Cuki (#{Time.now})\n" + @content unless @skip_header
|
112
|
+
|
113
|
+
save_file filepath
|
114
|
+
end
|
95
115
|
end
|
96
116
|
|
97
117
|
def autoformat
|
98
|
-
`cucumber -a . --dry-run -P` unless
|
118
|
+
`cucumber -a . --dry-run -P` unless @skip_autoformat
|
119
|
+
end
|
120
|
+
|
121
|
+
def handle_multi doc, id
|
122
|
+
feature_title_compressed = doc.at('#content-title')[:value].anchorize
|
123
|
+
|
124
|
+
@content += get_markup(doc)
|
125
|
+
acceptance_criteria_matches = @content.match(@config['container'])
|
126
|
+
unless acceptance_criteria_matches
|
127
|
+
puts "Could not match #{config['container']}"
|
128
|
+
exit(1)
|
129
|
+
end
|
130
|
+
acceptance_criteria = acceptance_criteria_matches[1]
|
131
|
+
scenario_titles = acceptance_criteria.scan(/h2. (.*)/).flatten
|
132
|
+
scenario_blocks = acceptance_criteria.split(/h2. .*/)
|
133
|
+
scenario_blocks.shift
|
134
|
+
|
135
|
+
combined = {}
|
136
|
+
scenario_titles.each_with_index do |title, index|
|
137
|
+
combined[title] = scenario_blocks[index].gsub(/h6. (.*)/, '\1')
|
138
|
+
end
|
139
|
+
combined.each do |title, content|
|
140
|
+
scenario_title_compressed = title.anchorize
|
141
|
+
feature_filename = title.parameterize
|
142
|
+
|
143
|
+
dirpath = @config['mappings'][id]
|
144
|
+
|
145
|
+
FileUtils.mkdir_p(dirpath)
|
146
|
+
|
147
|
+
fname = "#{dirpath}/#{feature_filename.gsub("\r", '')}.feature"
|
148
|
+
File.open(fname, 'w') do |f|
|
149
|
+
puts "Writing #{fname}"
|
150
|
+
f.write "Feature: #{title}\n\n"
|
151
|
+
link = @config['host'] + "/pages/viewpage.action?pageId=#{id}##{feature_title_compressed}-#{scenario_title_compressed}"
|
152
|
+
f.write "\n\n" + link
|
153
|
+
f.write content
|
154
|
+
end
|
155
|
+
end
|
99
156
|
end
|
100
157
|
|
101
158
|
def clean
|
102
159
|
|
103
|
-
@content.gsub(' ', '')
|
160
|
+
@content.gsub!(' ', '')
|
104
161
|
|
105
162
|
# remove the double pipes used for table headers in Confluence
|
106
163
|
@content.gsub!('||', '|')
|
@@ -113,6 +170,13 @@ class Cuki
|
|
113
170
|
# remove any unwanted headers
|
114
171
|
@content.gsub!(/h\d\. (Scenario: .*)/, '\1')
|
115
172
|
@content.gsub!(/h\d\. (Scenario Outline: .*)/, '\1')
|
173
|
+
@content.gsub!(/h\d\. (Background: .*)/, '\1')
|
174
|
+
|
175
|
+
#Remove fancy quotes
|
176
|
+
@content.gsub!('’', "'")
|
177
|
+
@content.gsub!('‘', "'")
|
178
|
+
@content.gsub!('“', '"')
|
179
|
+
@content.gsub!('”', '"')
|
116
180
|
|
117
181
|
end
|
118
182
|
|
@@ -134,7 +198,7 @@ class Cuki
|
|
134
198
|
def save_file(filepath)
|
135
199
|
dir_path = File.dirname(filepath)
|
136
200
|
|
137
|
-
|
201
|
+
FileUtils.mkdir_p(dir_path) unless File.exists?(dir_path)
|
138
202
|
|
139
203
|
File.open(filepath, 'w') do |f|
|
140
204
|
puts "Writing #{filepath}"
|
@@ -172,4 +236,8 @@ class Cuki
|
|
172
236
|
end
|
173
237
|
end
|
174
238
|
|
239
|
+
def get_markup(doc)
|
240
|
+
CGI.unescapeHTML(doc.css('#markupTextarea').text)
|
241
|
+
end
|
242
|
+
|
175
243
|
end
|
data/lib/string_utils.rb
ADDED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 7
|
10
|
+
version: 0.0.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andy Waite
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-10-
|
18
|
+
date: 2011-10-17 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
requirement: &id001 !ruby/object:Gem::Requirement
|
@@ -56,11 +56,25 @@ dependencies:
|
|
56
56
|
- 0
|
57
57
|
version: "0"
|
58
58
|
version_requirements: *id003
|
59
|
+
name: parallel
|
60
|
+
prerelease: false
|
61
|
+
type: :runtime
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
hash: 3
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
version_requirements: *id004
|
59
73
|
name: shoulda
|
60
74
|
prerelease: false
|
61
75
|
type: :development
|
62
76
|
- !ruby/object:Gem::Dependency
|
63
|
-
requirement: &
|
77
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
64
78
|
none: false
|
65
79
|
requirements:
|
66
80
|
- - ~>
|
@@ -71,12 +85,12 @@ dependencies:
|
|
71
85
|
- 0
|
72
86
|
- 0
|
73
87
|
version: 1.0.0
|
74
|
-
version_requirements: *
|
88
|
+
version_requirements: *id005
|
75
89
|
name: bundler
|
76
90
|
prerelease: false
|
77
91
|
type: :development
|
78
92
|
- !ruby/object:Gem::Dependency
|
79
|
-
requirement: &
|
93
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
80
94
|
none: false
|
81
95
|
requirements:
|
82
96
|
- - ~>
|
@@ -87,12 +101,12 @@ dependencies:
|
|
87
101
|
- 6
|
88
102
|
- 4
|
89
103
|
version: 1.6.4
|
90
|
-
version_requirements: *
|
104
|
+
version_requirements: *id006
|
91
105
|
name: jeweler
|
92
106
|
prerelease: false
|
93
107
|
type: :development
|
94
108
|
- !ruby/object:Gem::Dependency
|
95
|
-
requirement: &
|
109
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
96
110
|
none: false
|
97
111
|
requirements:
|
98
112
|
- - ">="
|
@@ -101,12 +115,12 @@ dependencies:
|
|
101
115
|
segments:
|
102
116
|
- 0
|
103
117
|
version: "0"
|
104
|
-
version_requirements: *
|
118
|
+
version_requirements: *id007
|
105
119
|
name: rcov
|
106
120
|
prerelease: false
|
107
121
|
type: :development
|
108
122
|
- !ruby/object:Gem::Dependency
|
109
|
-
requirement: &
|
123
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
110
124
|
none: false
|
111
125
|
requirements:
|
112
126
|
- - ">="
|
@@ -115,7 +129,7 @@ dependencies:
|
|
115
129
|
segments:
|
116
130
|
- 0
|
117
131
|
version: "0"
|
118
|
-
version_requirements: *
|
132
|
+
version_requirements: *id008
|
119
133
|
name: rspec
|
120
134
|
prerelease: false
|
121
135
|
type: :development
|
@@ -139,10 +153,12 @@ files:
|
|
139
153
|
- Rakefile
|
140
154
|
- VERSION
|
141
155
|
- bin/cuki
|
156
|
+
- cucumber.yml
|
142
157
|
- cuki.gemspec
|
143
158
|
- cuki.yaml.sample
|
144
159
|
- features/pull/pull.feature
|
145
160
|
- features/pull/pull_single.feature
|
161
|
+
- features/pull/splitting.feature
|
146
162
|
- features/pull/tables.feature
|
147
163
|
- features/pull/tags.feature
|
148
164
|
- features/pull/textile.feature
|
@@ -154,6 +170,7 @@ files:
|
|
154
170
|
- features/support/env.rb
|
155
171
|
- lib/cuki.rb
|
156
172
|
- lib/pusher.rb
|
173
|
+
- lib/string_utils.rb
|
157
174
|
- spec/cuki_spec.rb
|
158
175
|
- spec/spec_helper.rb
|
159
176
|
homepage: http://github.com/andyw8/cuki
|