social_snippet 0.0.5 → 0.0.6
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 +8 -8
- data/.gitignore +1 -0
- data/README.md +5 -5
- data/lib/social_snippet/api/completion_api.rb +13 -0
- data/lib/social_snippet/api/config_api.rb +14 -0
- data/lib/social_snippet/api/insert_snippet_api.rb +15 -0
- data/lib/social_snippet/api/install_repository_api.rb +109 -0
- data/lib/social_snippet/api/manifest_api.rb +83 -0
- data/lib/social_snippet/api/registry_api.rb +8 -0
- data/lib/social_snippet/api/search_api.rb +44 -0
- data/lib/social_snippet/api/show_api.rb +10 -0
- data/lib/social_snippet/api/update_repository_api.rb +54 -0
- data/lib/social_snippet/api.rb +20 -309
- data/lib/social_snippet/repository/repository_manager.rb +3 -1
- data/lib/social_snippet/resolvers/base_resolver.rb +21 -0
- data/lib/social_snippet/resolvers/dep_resolver.rb +7 -2
- data/lib/social_snippet/resolvers/insert_resolver.rb +8 -4
- data/lib/social_snippet/tag.rb +8 -0
- data/lib/social_snippet/tag_parser.rb +12 -22
- data/lib/social_snippet/version.rb +1 -1
- data/social_snippet.gemspec +2 -0
- data/spec/lib/command_line/sspm_init_spec.rb +1 -1
- data/spec/lib/insert_resolver_spec.rb +164 -109
- data/spec/lib/repository/repository_manager_spec.rb +8 -1
- data/test/base_resolver_test.rb +43 -0
- metadata +14 -3
data/lib/social_snippet/api.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
|
1
|
+
class SocialSnippet::Api; end
|
2
|
+
|
3
|
+
require_relative "api/config_api"
|
4
|
+
require_relative "api/manifest_api"
|
5
|
+
require_relative "api/insert_snippet_api"
|
6
|
+
require_relative "api/install_repository_api"
|
7
|
+
require_relative "api/update_repository_api"
|
8
|
+
require_relative "api/completion_api"
|
9
|
+
require_relative "api/show_api"
|
10
|
+
require_relative "api/search_api"
|
11
|
+
require_relative "api/registry_api"
|
2
12
|
|
3
13
|
class SocialSnippet::Api
|
4
14
|
|
@@ -9,183 +19,15 @@ class SocialSnippet::Api
|
|
9
19
|
@social_snippet = new_social_snippet
|
10
20
|
end
|
11
21
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
# Initialize the snippet.json interactively.
|
24
|
-
# $ sspm init
|
25
|
-
def init_manifest(options = {})
|
26
|
-
answer = {}
|
27
|
-
json_str = "{}"
|
28
|
-
|
29
|
-
# load current configuration
|
30
|
-
if ::File.exists?("snippet.json")
|
31
|
-
answer = ::JSON.parse(::File.read "snippet.json")
|
32
|
-
end
|
33
|
-
|
34
|
-
loop do
|
35
|
-
answer = ask_manifest_questions(manifest_questions(answer), answer)
|
36
|
-
json_str = ::JSON.pretty_generate(answer)
|
37
|
-
social_snippet.logger.say ""
|
38
|
-
social_snippet.logger.say json_str
|
39
|
-
social_snippet.logger.say ""
|
40
|
-
break if ask_confirm("Is this okay? [Y/N]: ")
|
41
|
-
end
|
42
|
-
|
43
|
-
::File.write "snippet.json", json_str
|
44
|
-
|
45
|
-
answer
|
46
|
-
end
|
47
|
-
|
48
|
-
# Insert snippets to given text.
|
49
|
-
# $ ssnip
|
50
|
-
#
|
51
|
-
# @param src [String] The text of source code
|
52
|
-
#
|
53
|
-
def insert_snippet(src, options = {})
|
54
|
-
resolver = ::SocialSnippet::Resolvers::InsertResolver.new(social_snippet, options)
|
55
|
-
res = resolver.insert(src)
|
56
|
-
output res
|
57
|
-
res
|
58
|
-
end
|
59
|
-
|
60
|
-
# $ sspm install name
|
61
|
-
def install_repository_by_name(repo_name, repo_ref, options = {})
|
62
|
-
installed_as = repo_name
|
63
|
-
installed_as = options[:name] unless options[:name].nil?
|
64
|
-
|
65
|
-
unless installed_as === repo_name
|
66
|
-
output "Installing as #{installed_as}"
|
67
|
-
end
|
68
|
-
|
69
|
-
if social_snippet.repo_manager.exists?(installed_as, repo_ref)
|
70
|
-
output "#{installed_as} is already installed"
|
71
|
-
return
|
72
|
-
end
|
73
|
-
|
74
|
-
output "Finding: #{repo_name}"
|
75
|
-
info = social_snippet.registry_client.repositories.find(repo_name)
|
76
|
-
output "Found at: #{info["url"]}"
|
77
|
-
|
78
|
-
output "Cloning repository..."
|
79
|
-
repo = ::SocialSnippet::Repository::RepositoryFactory.clone(info["url"])
|
80
|
-
|
81
|
-
install_repository installed_as, repo_ref, repo
|
82
|
-
end
|
83
|
-
|
84
|
-
# $ sspm install URL
|
85
|
-
def install_repository_by_url(repo_url, repo_ref, options = {})
|
86
|
-
output "Cloning repository..."
|
87
|
-
repo = ::SocialSnippet::Repository::RepositoryFactory.clone(repo_url)
|
88
|
-
install_repository_by_repo repo, repo_ref, options
|
89
|
-
end
|
90
|
-
|
91
|
-
# $ sspm install ./path/to/repo
|
92
|
-
def install_repository_by_path(repo_path, repo_ref, options = {})
|
93
|
-
output "Cloning repository..."
|
94
|
-
repo = ::SocialSnippet::Repository::RepositoryFactory.clone_local(repo_path)
|
95
|
-
install_repository_by_repo repo, repo_ref, options
|
96
|
-
end
|
97
|
-
|
98
|
-
def install_repository_by_repo(repo, repo_ref, options)
|
99
|
-
installed_as = repo.name
|
100
|
-
installed_as = options[:name] unless options[:name].nil?
|
101
|
-
output "Installing as #{installed_as}"
|
102
|
-
|
103
|
-
if social_snippet.repo_manager.exists?(installed_as)
|
104
|
-
output "#{installed_as} is already installed"
|
105
|
-
return
|
106
|
-
end
|
107
|
-
|
108
|
-
install_repository installed_as, repo_ref, repo
|
109
|
-
end
|
110
|
-
|
111
|
-
# Update a repository
|
112
|
-
# $ sspm update repo-name
|
113
|
-
def update_repository(repo_name, options = {})
|
114
|
-
unless social_snippet.repo_manager.exists?(repo_name)
|
115
|
-
output "ERROR: #{repo_name} is not installed"
|
116
|
-
return
|
117
|
-
end
|
118
|
-
|
119
|
-
output "Fetching update for #{repo_name}"
|
120
|
-
ret = social_snippet.repo_manager.fetch(repo_name, options)
|
121
|
-
|
122
|
-
repo = social_snippet.repo_manager.find_repository(repo_name)
|
123
|
-
display_name = repo_name
|
124
|
-
|
125
|
-
# nothing to update
|
126
|
-
if ret == 0 && social_snippet.repo_manager.exists?(repo_name, repo.latest_version)
|
127
|
-
output "Everything up-to-date"
|
128
|
-
return
|
129
|
-
end
|
130
|
-
|
131
|
-
output "Updating #{repo_name}"
|
132
|
-
unless options[:dry_run]
|
133
|
-
version = repo.latest_version
|
134
|
-
if repo.has_versions? && repo.current_ref != version
|
135
|
-
output "Bumping version into #{version}"
|
136
|
-
display_name = "#{repo_name}\##{version}"
|
137
|
-
repo.checkout version
|
138
|
-
social_snippet.repo_manager.update repo_name, version, repo, options
|
139
|
-
end
|
140
|
-
social_snippet.repo_manager.cache_installing_repo repo
|
141
|
-
end
|
142
|
-
|
143
|
-
output "Success #{display_name}"
|
144
|
-
|
145
|
-
# update deps
|
146
|
-
if social_snippet.repo_manager.has_deps?(repo_name)
|
147
|
-
output "Updating #{display_name}'s dependencies"
|
148
|
-
deps = social_snippet.repo_manager.deps(repo_name)
|
149
|
-
install_missing_dependencies deps, options
|
150
|
-
output "Finish updating #{display_name}'s dependencies"
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
# Update all installed repositories
|
155
|
-
# $ sspm update
|
156
|
-
def update_all_repositories(options = {})
|
157
|
-
social_snippet.repo_manager.each_installed_repo do |repo_name|
|
158
|
-
update_repository repo_name, options
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def complete_snippet_path(keyword)
|
163
|
-
social_snippet.repo_manager.complete(keyword)
|
164
|
-
end
|
165
|
-
|
166
|
-
def cli_complete_snippet_path(keyword)
|
167
|
-
complete_snippet_path(keyword).each do |cand_repo|
|
168
|
-
output cand_repo
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
def show_info(repo_name)
|
173
|
-
repo_info = social_snippet.registry_client.repositories.find(repo_name)
|
174
|
-
output ::JSON.pretty_generate(repo_info)
|
175
|
-
end
|
176
|
-
|
177
|
-
# $ sspm search query
|
178
|
-
def search_repositories(query, options = {})
|
179
|
-
format_text = search_result_format(options)
|
180
|
-
social_snippet.registry_client.repositories.search(query).each do |repo|
|
181
|
-
output format_text % search_result_list(repo, options)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
def add_url(url, options = {})
|
186
|
-
ret = social_snippet.registry_client.repositories.add_url(url)
|
187
|
-
output ret
|
188
|
-
end
|
22
|
+
include ::SocialSnippet::Api::ConfigApi
|
23
|
+
include ::SocialSnippet::Api::ManifestApi
|
24
|
+
include ::SocialSnippet::Api::InsertSnippetApi
|
25
|
+
include ::SocialSnippet::Api::InstallRepositoryApi
|
26
|
+
include ::SocialSnippet::Api::UpdateRepositoryApi
|
27
|
+
include ::SocialSnippet::Api::CompletionApi
|
28
|
+
include ::SocialSnippet::Api::ShowApi
|
29
|
+
include ::SocialSnippet::Api::SearchApi
|
30
|
+
include ::SocialSnippet::Api::RegistryApi
|
189
31
|
|
190
32
|
#
|
191
33
|
# Helpers
|
@@ -193,137 +35,6 @@ class SocialSnippet::Api
|
|
193
35
|
|
194
36
|
private
|
195
37
|
|
196
|
-
# Install repository
|
197
|
-
#
|
198
|
-
# @param repo [::SocialSnippet::Repository::Drivers::BaseRepository]
|
199
|
-
def install_repository(repo_name, repo_ref, repo, options = {})
|
200
|
-
display_name = repo_name
|
201
|
-
|
202
|
-
if repo_ref.nil?
|
203
|
-
repo_ref = resolve_reference(repo)
|
204
|
-
|
205
|
-
if repo.has_versions?
|
206
|
-
output "Resolving #{display_name}'s version"
|
207
|
-
else
|
208
|
-
output "No versions, use current reference"
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
display_name = "#{repo_name}\##{repo_ref}"
|
213
|
-
|
214
|
-
output "Installing: #{display_name}"
|
215
|
-
unless options[:dry_run]
|
216
|
-
social_snippet.repo_manager.install repo_name, repo_ref, repo, options
|
217
|
-
end
|
218
|
-
|
219
|
-
output "Success: #{display_name}"
|
220
|
-
|
221
|
-
# install dependencies
|
222
|
-
if has_dependencies?(repo)
|
223
|
-
output "Finding #{display_name}'s dependencies"
|
224
|
-
install_missing_dependencies repo.dependencies, options
|
225
|
-
output "Finish finding #{display_name}'s dependencies"
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
def ask_confirm(message)
|
230
|
-
ret = social_snippet.prompt.ask(message) do |q|
|
231
|
-
q.limit = 1
|
232
|
-
q.validate = /^[yn]$/i
|
233
|
-
end
|
234
|
-
/y/i === ret
|
235
|
-
end
|
236
|
-
|
237
|
-
def ask_manifest_questions(questions, obj)
|
238
|
-
questions.inject(obj) do |obj, q|
|
239
|
-
obj[q[:key]] = ask_manifest_question(q)
|
240
|
-
obj
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
def ask_manifest_question(question)
|
245
|
-
if question[:type] === :string
|
246
|
-
social_snippet.prompt.ask("#{question[:key]}: ") do |q|
|
247
|
-
q.default = question[:default]
|
248
|
-
if question[:validate].is_a?(Regexp)
|
249
|
-
q.validate = question[:validate]
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
def manifest_questions(answer)
|
256
|
-
[
|
257
|
-
{
|
258
|
-
:key => "name",
|
259
|
-
:type => :string,
|
260
|
-
:validate => /[a-zA-Z0-9\.\-_]+/,
|
261
|
-
:default => answer["name"],
|
262
|
-
},
|
263
|
-
{
|
264
|
-
:key => "description",
|
265
|
-
:type => :string,
|
266
|
-
:default => answer["description"],
|
267
|
-
},
|
268
|
-
{
|
269
|
-
:key => "license",
|
270
|
-
:default => answer["license"] || "MIT",
|
271
|
-
:type => :string,
|
272
|
-
},
|
273
|
-
]
|
274
|
-
end
|
275
|
-
|
276
|
-
def resolve_reference(repo)
|
277
|
-
if repo.has_versions?
|
278
|
-
repo.latest_version
|
279
|
-
else
|
280
|
-
repo.current_ref
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
def has_dependencies?(repo)
|
285
|
-
repo.dependencies && ( not repo.dependencies.empty? )
|
286
|
-
end
|
287
|
-
|
288
|
-
def install_missing_dependencies(repo_deps, options = {})
|
289
|
-
repo_deps.each do |dep_repo_name, dep_repo_ref|
|
290
|
-
unless social_snippet.repo_manager.exists?(dep_repo_name, dep_repo_ref)
|
291
|
-
install_repository_by_name dep_repo_name, dep_repo_ref, options
|
292
|
-
end
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
def search_result_format(options)
|
297
|
-
keys = [ # TODO: improve (change order by option, etc...)
|
298
|
-
:name,
|
299
|
-
:desc,
|
300
|
-
:url,
|
301
|
-
:installed,
|
302
|
-
]
|
303
|
-
|
304
|
-
list = []
|
305
|
-
keys.each {|key| list.push "%s" if options[key] }
|
306
|
-
|
307
|
-
return list.join(" ")
|
308
|
-
end
|
309
|
-
|
310
|
-
def search_result_list(repo, options)
|
311
|
-
list = []
|
312
|
-
list.push repo["name"] if options[:name]
|
313
|
-
list.push "\"#{repo["desc"]}\"" if options[:desc]
|
314
|
-
list.push repo["url"] if options[:url]
|
315
|
-
list.push search_result_installed(repo) if options[:installed]
|
316
|
-
return list
|
317
|
-
end
|
318
|
-
|
319
|
-
def search_result_installed(repo)
|
320
|
-
if social_snippet.repo_manager.exists?(repo["name"])
|
321
|
-
"#installed"
|
322
|
-
else
|
323
|
-
""
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
38
|
def output(message)
|
328
39
|
social_snippet.logger.say message
|
329
40
|
end
|
@@ -77,6 +77,8 @@ module SocialSnippet::Repository
|
|
77
77
|
#
|
78
78
|
# @param name [String] The name of repository
|
79
79
|
def find_repository(name, ref = nil)
|
80
|
+
return nil if name.nil? || name.empty?
|
81
|
+
|
80
82
|
repo_paths.each do |repo_path|
|
81
83
|
path = "#{repo_path}/#{name}"
|
82
84
|
if ::Dir.exists?(path)
|
@@ -86,7 +88,7 @@ module SocialSnippet::Repository
|
|
86
88
|
end
|
87
89
|
end
|
88
90
|
|
89
|
-
|
91
|
+
nil
|
90
92
|
end
|
91
93
|
|
92
94
|
def find_repositories_start_with(prefix)
|
@@ -41,8 +41,29 @@ module SocialSnippet
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
# @param lines [Array<String>]
|
45
|
+
def filter(lines)
|
46
|
+
lines = cut_filter(lines)
|
47
|
+
lines
|
48
|
+
end
|
49
|
+
|
44
50
|
private
|
45
51
|
|
52
|
+
def cut_filter(lines)
|
53
|
+
cut_level = 0
|
54
|
+
lines.select do |line|
|
55
|
+
if Tag.is_begin_cut?(line)
|
56
|
+
cut_level += 1
|
57
|
+
false
|
58
|
+
elsif Tag.is_end_cut?(line)
|
59
|
+
cut_level -= 1
|
60
|
+
false
|
61
|
+
else
|
62
|
+
cut_level === 0
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
46
67
|
def move_context_by_tag!(context, tag)
|
47
68
|
if tag.has_repo?
|
48
69
|
if tag.has_ref?
|
@@ -48,8 +48,13 @@ module SocialSnippet
|
|
48
48
|
:tag => tag,
|
49
49
|
:context => new_context,
|
50
50
|
})
|
51
|
-
# find more deps
|
52
|
-
|
51
|
+
# find more deps
|
52
|
+
if snippet.is_a?(Snippet)
|
53
|
+
snippet_lines = snippet.lines
|
54
|
+
else
|
55
|
+
snippet_lines = snippet.split($/)
|
56
|
+
end
|
57
|
+
found_tags.push *find_func(snippet_lines, new_context, tag)
|
53
58
|
end
|
54
59
|
|
55
60
|
return found_tags
|
@@ -25,7 +25,7 @@ module SocialSnippet
|
|
25
25
|
# @param src [Array<String>] The text of source code
|
26
26
|
def insert(src)
|
27
27
|
context = Context.new("")
|
28
|
-
lines = src.split
|
28
|
+
lines = filter(src.split $/)
|
29
29
|
|
30
30
|
TagParser.find_snippet_tags(lines).each do |tag_info|
|
31
31
|
visit tag_info[:tag]
|
@@ -58,8 +58,12 @@ module SocialSnippet
|
|
58
58
|
end
|
59
59
|
|
60
60
|
# Insert snippet by tag and context
|
61
|
-
def insert_by_tag_and_context!(inserter,
|
62
|
-
|
61
|
+
def insert_by_tag_and_context!(inserter, snippet_str, context, tag)
|
62
|
+
if snippet_str.is_a?(Snippet)
|
63
|
+
src = insert_func(snippet_str.lines, context, tag)
|
64
|
+
else
|
65
|
+
src = insert_func(snippet_str.split($/), context, tag)
|
66
|
+
end
|
63
67
|
|
64
68
|
options[:margin_top].times { inserter.insert "" }
|
65
69
|
inserter.insert tag.to_snippet_tag # @snip -> @snippet
|
@@ -71,7 +75,7 @@ module SocialSnippet
|
|
71
75
|
|
72
76
|
# Insert depended snippet
|
73
77
|
def insert_depended_snippets!(inserter, snippet, context, tag)
|
74
|
-
dep_tags = deps_resolver.find(snippet.lines
|
78
|
+
dep_tags = deps_resolver.find(snippet.lines, context, tag)
|
75
79
|
dep_tags = sort_dep_tags_by_dep(dep_tags)
|
76
80
|
|
77
81
|
dep_tags.each do |tag_info|
|
data/lib/social_snippet/tag.rb
CHANGED
@@ -93,6 +93,14 @@ class SocialSnippet::Tag
|
|
93
93
|
|
94
94
|
class << self
|
95
95
|
|
96
|
+
def is_begin_cut?(s)
|
97
|
+
/@begin_cut/ === s
|
98
|
+
end
|
99
|
+
|
100
|
+
def is_end_cut?(s)
|
101
|
+
/@end_cut/ === s
|
102
|
+
end
|
103
|
+
|
96
104
|
# Check given line to match @snip tag
|
97
105
|
def is_snip_tag_line(s)
|
98
106
|
return /@snip\s*<.*?>/ === s
|
@@ -7,22 +7,7 @@ class SocialSnippet::TagParser
|
|
7
7
|
# @param s [String or Array] parsed text
|
8
8
|
# @return [Array] found `@snip` tags with line_no
|
9
9
|
def find_snip_tags(s)
|
10
|
-
|
11
|
-
|
12
|
-
lines = get_lines(s)
|
13
|
-
|
14
|
-
lines.each.with_index do |line, i|
|
15
|
-
if ::SocialSnippet::Tag.is_snip_tag_line(line)
|
16
|
-
found_lines.push(
|
17
|
-
{
|
18
|
-
:line_no => i,
|
19
|
-
:tag => ::SocialSnippet::Tag.new(line),
|
20
|
-
}
|
21
|
-
)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
return found_lines
|
10
|
+
find_lines(s) {|line| ::SocialSnippet::Tag.is_snip_tag_line(line) }
|
26
11
|
end
|
27
12
|
|
28
13
|
# Find `@snippet` tags from text
|
@@ -30,12 +15,14 @@ class SocialSnippet::TagParser
|
|
30
15
|
# @param s [String or Array] parsed text
|
31
16
|
# @return [Array] found `@snippet` tags with line_no
|
32
17
|
def find_snippet_tags(s)
|
33
|
-
|
18
|
+
find_lines(s) {|line| ::SocialSnippet::Tag.is_snippet_tag_line(line) }
|
19
|
+
end
|
34
20
|
|
35
|
-
|
21
|
+
private
|
36
22
|
|
37
|
-
|
38
|
-
|
23
|
+
def find_lines(s, &comparator)
|
24
|
+
get_lines(s).each.with_index.inject([]) do |found_lines, (line, i)|
|
25
|
+
if comparator.call(line)
|
39
26
|
found_lines.push(
|
40
27
|
{
|
41
28
|
:line_no => i,
|
@@ -43,9 +30,8 @@ class SocialSnippet::TagParser
|
|
43
30
|
}
|
44
31
|
)
|
45
32
|
end
|
33
|
+
found_lines
|
46
34
|
end
|
47
|
-
|
48
|
-
return found_lines
|
49
35
|
end
|
50
36
|
|
51
37
|
def get_lines(s)
|
@@ -53,6 +39,10 @@ class SocialSnippet::TagParser
|
|
53
39
|
s.split($/)
|
54
40
|
elsif s.is_a?(Array)
|
55
41
|
s
|
42
|
+
elsif s.is_a?(Enumerator)
|
43
|
+
s
|
44
|
+
else
|
45
|
+
raise "error unknown data"
|
56
46
|
end
|
57
47
|
end
|
58
48
|
|
data/social_snippet.gemspec
CHANGED
@@ -17,6 +17,8 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
+
spec.required_ruby_version = ">= 1.9.3"
|
21
|
+
|
20
22
|
spec.add_runtime_dependency "version_sorter", "~> 1.1.0"
|
21
23
|
spec.add_runtime_dependency "rugged", ["~> 0.21.4", ">= 0.21.4"]
|
22
24
|
spec.add_runtime_dependency "rest-client", "~> 1.7.0"
|