travis-packagecloud-ruby 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 84a4d56bec4d70a54f2b482a5dd01f65f01c669c089ff30acc9812f171970222
4
+ data.tar.gz: c3797c10f55a0220e14cca64b01628841be63cd1557707ddd1bc8dd8e9bf603d
5
+ SHA512:
6
+ metadata.gz: 5a32ada5ae606b9a7d2579f5f15041c936473b7dd7769da01befdd996b646eff7fc8c8a9e8423988d1e2105fbdc72e85311ffde77f3d8e28465d0962fc9414a0
7
+ data.tar.gz: ca0e2a2698520dc5a54f1df7614ebaaf7906fa6a2a0061af7fbc0892f35c7d4f4692addbe7b7bd7af22539ccbe59a2b85f6c4caa855dd2b837adf7d82ca495b8
data/.document ADDED
@@ -0,0 +1,3 @@
1
+ -
2
+ ChangeLog.rdoc
3
+ LICENSE.txt
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ Gemfile.lock
2
+ doc/
3
+ pkg/
4
+ vendor/cache/*.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 1.8.7
5
+ - 1.9.3
6
+ - 2.1.0
7
+ - 2.4.3
8
+ - 2.5.0
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup rdoc --title "packagecloud-ruby Documentation" --protected
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Computology, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,135 @@
1
+ ## packagecloud-ruby
2
+
3
+ ![Build Status](https://travis-ci.org/computology/packagecloud-ruby.svg?branch=master "Build Status")
4
+
5
+
6
+ Ruby library for communicating with the [packagecloud.io](https://packagecloud.io) API.
7
+
8
+ * [Homepage](https://rubygems.org/gems/packagecloud-ruby)
9
+ * [Documentation](http://rubydoc.info/gems/packagecloud-ruby/frames)
10
+ * [Email](mailto:support@packagecloud.io)
11
+
12
+ ## Goals
13
+
14
+ This library aims to have widest amount of compatibility possible between Ruby versions and implementations. All dependencies are pure Ruby and kept to a minimum to ensure this.
15
+
16
+ #### Tested Rubies
17
+
18
+ * Ruby 1.8.x, 1.9x, and 2.x
19
+
20
+ ## Implemented API Endpoints
21
+
22
+ * [Get Package Contents](https://packagecloud.io/docs/api#resource_packages_method_contents)
23
+ * [Upload Package](https://packagecloud.io/docs/api#resource_packages_method_create)
24
+ * [List Distributions](https://packagecloud.io/docs/api#resource_distributions_method_index)
25
+ * [View Repository](https://packagecloud.io/docs/api#resource_repositories_method_show)
26
+ * [View Repositories](https://packagecloud.io/docs/api#resource_repositories_method_index)
27
+ * [Create Repository](https://packagecloud.io/docs/api#resource_repositories_method_create)
28
+
29
+ ## Installation
30
+
31
+ ```
32
+ gem install packagecloud-ruby
33
+ ```
34
+
35
+ ## Getting your API token
36
+
37
+ Login to [packagecloud.io](https://packagecloud.io) and
38
+ go to your [Account Settings](https://packagecloud.io/api_token) to see your API token.
39
+
40
+ ## Creating a Client
41
+
42
+ Note that you should not use the email address associated with your
43
+ [packagecloud.io](https://packagecloud.io) account when accessing the API.
44
+ Please use your username on the site.
45
+
46
+ ```ruby
47
+ require 'packagecloud'
48
+
49
+ # Create a client using your username and API token
50
+ credentials = Packagecloud::Credentials.new("joedamato", "my_api_token")
51
+ @client = Packagecloud::Client.new(credentials)
52
+
53
+ ```
54
+
55
+ ## Result objects
56
+
57
+ Every client API method call returns a ```Result``` object, which is simply:
58
+
59
+ ```ruby
60
+ module Packagecloud
61
+ class Result
62
+ attr_accessor :response
63
+ attr_accessor :succeeded
64
+ end
65
+ end
66
+ ```
67
+
68
+ If ```.succeeded``` is ```true``` then, ```.response``` is the parsed JSON response
69
+ of that endpoint, otherwise ```.response``` is the error text explaining what went wrong.
70
+
71
+
72
+ ## Usage
73
+
74
+ ### Distributions
75
+
76
+ This is the list of currently [supported distributions](https://packagecloud.io/docs#os_distro_version).
77
+
78
+ ```ruby
79
+ # Get all distributions
80
+ distros = @client.distributions
81
+
82
+ # Looking up a distribution id by name
83
+ id = @client.find_distribution_id("el/6") # returns 27
84
+ ```
85
+
86
+ ### Repositories
87
+
88
+ ```ruby
89
+ # Looking up all repositories available for a client
90
+ repos = @client.repositories
91
+
92
+ # Lookup info on a single repo
93
+ repo = @client.repository("my_repo")
94
+
95
+ # Creating a repository
96
+ @client.create_repository("my_repo")
97
+
98
+ ```
99
+
100
+ When specifying your repository name, you should use just the name and not
101
+ the fully qualified name (fqname).
102
+
103
+ For example:
104
+
105
+ ```ruby
106
+ # INCORRECT: this should just be "my_repo"
107
+ repo = @client.repository("user/my_repo")
108
+ ```
109
+
110
+ ### Packages
111
+
112
+ ```ruby
113
+ # Create RPM Packages (can take File, IO, or path argument)
114
+ rpm_package = Packagecloud::Package.new(:file => "libcurl-0.1.2.rpm")
115
+
116
+ # Creating gem Packages using IO (needs :filename passed in)
117
+ gem_package = Packagecloud::Package.new(:file => io_object, :filename => "rails-4.0.0.gem")
118
+
119
+ # Creating source Packages
120
+ source_files = { "jake_1.0.orig.tar.bz2" => open("/path/jake_1.0.orig.tar.bz2"),
121
+ "jake_1.0-7.debian.tar.gz" => open("/path/jake_1.0-7.debian.tar.gz") }
122
+ dsc_package = Packagecloud::Package.new(:file => "jake_1.0-7.dsc", :source_files => source_files)
123
+
124
+ # Upload Packages
125
+ @client.put_package("test_repo", gem_package)
126
+ @client.put_package("test_repo", rpm_package, "el/6")
127
+ @client.put_package("test_repo", dsc_package, "ubuntu/trusty")
128
+ @client.put_package("test_repo", node_package, "node")
129
+ ```
130
+
131
+ ## Copyright
132
+
133
+ Copyright (c) 2014-2018 Computology, LLC
134
+
135
+ See LICENSE.txt for details.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ begin
6
+ require 'bundler'
7
+ rescue LoadError => e
8
+ warn e.message
9
+ warn "Run `gem install bundler` to install Bundler."
10
+ exit -1
11
+ end
12
+
13
+ begin
14
+ Bundler.setup(:development)
15
+ rescue Bundler::BundlerError => e
16
+ warn e.message
17
+ warn "Run `bundle install` to install missing gems."
18
+ exit e.status_code
19
+ end
20
+
21
+ require 'rake'
22
+
23
+ require 'rubygems/tasks'
24
+ Gem::Tasks.new
25
+
26
+ require 'rspec/core/rake_task'
27
+ RSpec::Core::RakeTask.new
28
+
29
+ task :test => :spec
30
+ task :default => :spec
31
+
32
+ require 'yard'
33
+ YARD::Rake::YardocTask.new
34
+ task :doc => :yard
35
+
36
+ require 'rspec/core/rake_task'
37
+
38
+ desc "Run all specs with rcov"
39
+ RSpec::Core::RakeTask.new("spec:coverage") do |t|
40
+ t.rcov = true
41
+ t.rcov_opts = %w{-Ispec
42
+ --exclude gems\/,spec\/,features\/,seeds\/}
43
+ t.spec_opts = ["-c"]
44
+ end
45
+
@@ -0,0 +1,296 @@
1
+ require 'json'
2
+ require 'mime'
3
+ require 'excon'
4
+ require 'packagecloud/result'
5
+ require 'packagecloud/connection'
6
+ require 'packagecloud/version'
7
+
8
+ module Packagecloud
9
+ SUPPORTED_EXTENSIONS = ["deb", "dsc", "gem", "rpm", "whl", "zip", "egg", "egg-info", "tar", "bz2", "Z", "gz", "tgz"]
10
+
11
+ class UnauthenticatedException < StandardError
12
+ attr_reader :object
13
+
14
+ def initialize(object = nil)
15
+ @object = object
16
+ end
17
+ end
18
+
19
+ class GemOutOfDateException < StandardError
20
+ attr_reader :object
21
+
22
+ def initialize(object = nil)
23
+ @object = object
24
+ end
25
+ end
26
+
27
+ class InvalidRepoNameException < StandardError
28
+ attr_reader :object
29
+
30
+ def initialize(object = nil)
31
+ @object = object
32
+ end
33
+ end
34
+
35
+ class InvalidUsernameException < StandardError
36
+ attr_reader :object
37
+
38
+ def initialize(object = nil)
39
+ @object = object
40
+ end
41
+ end
42
+
43
+ class Client
44
+ attr_reader :connection
45
+ attr_reader :credentials
46
+
47
+ def initialize(credentials, user_agent="packagecloud-ruby #{Packagecloud::VERSION}", connection=Connection.new)
48
+ @credentials = credentials
49
+ @connection = connection
50
+ @user_agent = user_agent
51
+
52
+ scheme = self.connection.scheme
53
+ host = self.connection.host
54
+ port = self.connection.port
55
+ token = self.credentials.token
56
+
57
+ @excon = Excon.new("#{scheme}://#{token}@#{host}:#{port}", :connect_timeout => @connection.connect_timeout)
58
+ assert_valid_credentials
59
+ end
60
+
61
+ def distributions
62
+ response = get("/api/v1/distributions.json")
63
+ parsed_json_result(response)
64
+ end
65
+
66
+ def repositories
67
+ response = get("/api/v1/repos.json")
68
+ parsed_json_result(response)
69
+ end
70
+
71
+ def repository(repo)
72
+ assert_valid_repo_name(repo)
73
+ response = get("/api/v1/repos/#{username}/#{repo}.json")
74
+ parsed_json_result(response)
75
+ end
76
+
77
+ def gem_version
78
+ response = get("/api/v1/gem_version.json")
79
+ parsed_json_result(response)
80
+ end
81
+
82
+ def create_repository(repo, private=false)
83
+ assert_valid_repo_name(repo)
84
+ privacy = private ? 1 : 0
85
+ body = { "repository" => { "name" => repo, "private" => privacy.to_s } }
86
+ response = post("/api/v1/repos.json", body.to_json)
87
+ parsed_json_result(response)
88
+ end
89
+
90
+ def package_contents(repo, package, distro_version_id=nil)
91
+ assert_valid_repo_name(repo)
92
+ if distro_version_id.nil?
93
+ raise "No distribution supplied for package_contents!"
94
+ end
95
+
96
+ url = "/api/v1/repos/#{username}/#{repo}/packages/contents.json"
97
+
98
+ mixed_msg = MIME::Multipart::FormData.new
99
+
100
+ package.file.rewind
101
+ pkg_data = MIME::Application.new(package.file.read)
102
+ pkg_data.headers.set('Content-Transfer-Encoding', 'binary')
103
+ mixed_msg.add(pkg_data, "package[package_file]", package.filename)
104
+
105
+ if distro_version_id.is_a? String
106
+ distro_version = find_distribution_id(distro_version_id)
107
+ raise "Cannot find distribution: #{distro_version_id}" if distro_version.nil?
108
+ mixed_msg.add(MIME::Text.new(distro_version), "package[distro_version_id]")
109
+ else
110
+ mixed_msg.add(MIME::Text.new(distro_version_id), "package[distro_version_id]")
111
+ end
112
+
113
+ response = multipart_post(url, mixed_msg)
114
+
115
+ parsed_json_result(response)
116
+ end
117
+
118
+ def list_packages(repo)
119
+ assert_valid_repo_name(repo)
120
+ response = get("/api/v1/repos/#{username}/#{repo}/packages.json")
121
+ parsed_json_result(response)
122
+ end
123
+
124
+ def delete_package(repo, distro, distro_release, package_filename)
125
+ assert_valid_repo_name(repo)
126
+ url = "/api/v1/repos/#{username}/#{repo}/#{distro}/#{distro_release}/#{package_filename}"
127
+ response = delete(url)
128
+ parsed_json_result(response)
129
+ end
130
+
131
+ def put_package(repo, package, distro_version_id=nil)
132
+ assert_valid_repo_name(repo)
133
+
134
+ url = "/api/v1/repos/#{username}/#{repo}/packages.json"
135
+
136
+ mixed_msg = MIME::Multipart::FormData.new
137
+
138
+ if distro_version_id != nil
139
+ if distro_version_id.is_a? String
140
+ distro_version = find_distribution_id(distro_version_id)
141
+ raise "Cannot find distribution: #{distro_version_id}" if distro_version.nil?
142
+ mixed_msg.add(MIME::Text.new(distro_version), "package[distro_version_id]")
143
+ else
144
+ mixed_msg.add(MIME::Text.new(distro_version_id), "package[distro_version_id]")
145
+ end
146
+ end
147
+
148
+ package.file.rewind
149
+ pkg_data = MIME::Application.new(package.file.read)
150
+ pkg_data.headers.set('Content-Transfer-Encoding', 'binary')
151
+ mixed_msg.add(pkg_data, "package[package_file]", package.filename)
152
+
153
+ package.source_files.each do |filename, io|
154
+ io.rewind
155
+ src_pkg_data = MIME::Application.new(io.read)
156
+ src_pkg_data.headers.set('Content-Transfer-Encoding', 'binary')
157
+ mixed_msg.add(src_pkg_data, "package[source_files][]", filename)
158
+ end
159
+
160
+ response = multipart_post(url, mixed_msg)
161
+
162
+ prepare_result(response) { |result| result.response = "" }
163
+ end
164
+
165
+ def find_distribution_id(distro_query)
166
+ distros = distributions
167
+ if distros.succeeded
168
+ deb_distros = distro_map distros.response["deb"]
169
+ rpm_distros = distro_map distros.response["rpm"]
170
+ py_distros = distro_map distros.response["py"]
171
+ node_distros = distro_map distros.response["node"]
172
+ all_distros = deb_distros.merge(rpm_distros).merge(py_distros).merge(node_distros)
173
+ result = all_distros.select { |distro, id| distro.include?(distro_query) }
174
+ if result.size > 1
175
+ keys = result.map { |x| x.first }.join(' ')
176
+ raise ArgumentError, "'#{distro_query}' is ambiguous, did you mean: #{keys}?"
177
+ elsif result.size == 1
178
+ result.first[1] # [["ubuntu/breezy", 1]]
179
+ else
180
+ nil
181
+ end
182
+ end
183
+ end
184
+
185
+ def create_read_tokens(repo, master_token_id, read_token_name)
186
+ assert_valid_repo_name(repo)
187
+ url = "/api/v1/repos/#{username}/#{repo}/master_tokens/#{master_token_id}/read_tokens.json"
188
+ response = post(url, "read_token[name]=#{read_token_name}", "application/x-www-form-urlencoded")
189
+ parsed_json_result(response)
190
+ end
191
+
192
+ def delete_read_token(repo, master_token_id, read_token_id)
193
+ assert_valid_repo_name(repo)
194
+ url = "/api/v1/repos/#{username}/#{repo}/master_tokens/#{master_token_id}/read_tokens/#{read_token_id}"
195
+ response = delete(url)
196
+ Result.new.tap do |result|
197
+ result.succeeded = (response.status == 204)
198
+ end
199
+ end
200
+
201
+ def list_read_tokens(repo, master_token_id)
202
+ assert_valid_repo_name(repo)
203
+ response = get("/api/v1/repos/#{username}/#{repo}/master_tokens/#{master_token_id}/read_tokens.json")
204
+ parsed_json_result(response)
205
+ end
206
+
207
+ private
208
+ def assert_valid_repo_name(repo)
209
+ if repo.include?("/")
210
+ raise InvalidRepoNameException.new("The repo name: #{repo} is " \
211
+ "invalid. It looks like you are " \
212
+ "using the fully qualified name " \
213
+ "(fqname) instead of just the " \
214
+ "repo name. Please try again.")
215
+ end
216
+ end
217
+
218
+ def assert_valid_credentials
219
+ result = distributions
220
+ if result.succeeded == false && result.response.downcase.include?('unauthenticated')
221
+ raise UnauthenticatedException
222
+ end
223
+ end
224
+
225
+ def distro_map(distros)
226
+ result = {}
227
+ distros.each do |distro|
228
+ name = distro["index_name"]
229
+ distro["versions"].each do |version|
230
+ version_name = version["index_name"]
231
+ key = "#{name}/#{version_name}"
232
+ result[key] = version["id"]
233
+ end
234
+ end
235
+ result
236
+ end
237
+
238
+ def user_agent
239
+ "packagecloud-ruby #{VERSION}/#{@user_agent}"
240
+ end
241
+
242
+ def multipart_post(url, mixed_msg)
243
+ boundary = mixed_msg.boundary
244
+ content_type = "multipart/form-data; boundary=#{boundary}"
245
+ body = mixed_msg.to_s
246
+ post(url, body, content_type)
247
+ end
248
+
249
+ def post(url, body, content_type="application/json")
250
+ request(url, :post, body, content_type)
251
+ end
252
+
253
+ def get(url)
254
+ request(url, :get)
255
+ end
256
+
257
+ def delete(url)
258
+ request(url, 'DELETE')
259
+ end
260
+
261
+ def username
262
+ self.credentials.username
263
+ end
264
+
265
+ def request(url, method=:get, body=nil, content_type=nil)
266
+ headers = { "User-Agent" => user_agent }
267
+ if content_type != nil
268
+ headers.merge!({ "Content-Type" => content_type })
269
+ end
270
+ request_params = { :method => method, :path => url, :headers => headers }
271
+ if body != nil
272
+ request_params.merge!({ :body => body })
273
+ end
274
+
275
+ @excon.request(request_params.merge({:read_timeout => connection.read_timeout, :write_timeout => connection.write_timeout }))
276
+ end
277
+
278
+ # returns the parsed body of a successful result
279
+ def parsed_json_result(response)
280
+ prepare_result(response) { |result| result.response = JSON.parse(response.data[:body]) }
281
+ end
282
+
283
+ def prepare_result(response)
284
+ result = Result.new
285
+ if response.status == 201 || response.status == 200
286
+ result.succeeded = true
287
+ yield result
288
+ else
289
+ result.response = response.data[:body]
290
+ result.succeeded = false
291
+ end
292
+ result
293
+ end
294
+
295
+ end
296
+ end
@@ -0,0 +1,15 @@
1
+ module Packagecloud
2
+ class Connection
3
+ attr_reader :scheme, :host, :port, :connect_timeout, :read_timeout, :write_timeout
4
+
5
+ def initialize(scheme="https", host="packagecloud.io", port="443", options={})
6
+ @scheme = scheme
7
+ @host = host
8
+ @port = port
9
+
10
+ @connect_timeout = options[:connect_timeout] || 60
11
+ @read_timeout = options[:read_timeout] || 60
12
+ @write_timeout = options[:write_timeout] || 180
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ module Packagecloud
2
+ class Credentials
3
+ attr_reader :username
4
+ attr_reader :token
5
+
6
+ def initialize(username, token)
7
+ @username = username
8
+ @token = token
9
+ if @username.include?("@")
10
+ raise InvalidUsernameException.new("Sorry, looks like you may have " \
11
+ "tried to use an email address " \
12
+ "instead of your packagecloud.io " \
13
+ "username. Please use your " \
14
+ "username instead!")
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ module Packagecloud
2
+ class Package
3
+
4
+ attr_reader :file
5
+ attr_accessor :source_files
6
+ attr_reader :filename
7
+ attr_reader :client
8
+
9
+ def initialize(options = {})
10
+ if options[:file].nil?
11
+ raise ArgumentError, 'file cannot be nil' if file.nil?
12
+ end
13
+ if options[:file].is_a? String
14
+ options[:file] = File.open(options[:file])
15
+ end
16
+ if options[:file].is_a? File
17
+ options[:filename] = File.basename(options[:file].path)
18
+ end
19
+ if options[:filename].nil?
20
+ raise ArgumentError, 'filename cannot be nil' if file.nil?
21
+ end
22
+
23
+ @file = options[:file]
24
+ @filename = options[:filename]
25
+ @source_files = options[:source_files] || {}
26
+ @client = options[:client]
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,6 @@
1
+ module Packagecloud
2
+ class Result
3
+ attr_accessor :response
4
+ attr_accessor :succeeded
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ module Packagecloud
2
+ MAJOR_VERSION = "1"
3
+ MINOR_VERSION = "1"
4
+ PATCH_VERSION = "0"
5
+
6
+ VERSION = [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION].join(".")
7
+ end
@@ -0,0 +1,4 @@
1
+ require 'packagecloud/version'
2
+ require 'packagecloud/client'
3
+ require 'packagecloud/package'
4
+ require 'packagecloud/credentials'
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.expand_path('../lib/packagecloud/version', __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "travis-packagecloud-ruby"
7
+ gem.version = Packagecloud::VERSION
8
+ gem.summary = "library for interacting with packagecloud.io"
9
+ gem.description = gem.summary
10
+ gem.license = "MIT" # as stated in LICENSE.txt file
11
+ gem.authors = ["Joe Damato"]
12
+ gem.email = "joe@packagecloud.io"
13
+ gem.homepage = "https://rubygems.org/gems/packagecloud-ruby"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_runtime_dependency 'excon', '~> 0.40'
21
+ gem.add_runtime_dependency 'json_pure', '~> 2'
22
+ gem.add_runtime_dependency 'mime', '~> 0.4'
23
+
24
+ gem.add_development_dependency 'bundler', '~> 2.0'
25
+ gem.add_development_dependency 'rake', '~> 0.8'
26
+ gem.add_development_dependency 'rspec', '~> 2.4'
27
+ gem.add_development_dependency 'simplecov', '~> 0.9'
28
+ gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
29
+ gem.add_development_dependency 'yard', '~> 0.9.11'
30
+ end
Binary file