wetransfer 0.1.0 → 0.2.0
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 +4 -4
- data/.travis.yml +2 -3
- data/README.md +11 -35
- data/examples/create_transfer.rb +13 -0
- data/lib/we_transfer_client.rb +194 -0
- data/lib/we_transfer_client/version.rb +3 -0
- data/spec/integration_spec.rb +98 -0
- data/wetransfer.gemspec +5 -8
- metadata +15 -25
- data/lib/wetransfer.rb +0 -16
- data/lib/wetransfer/client.rb +0 -126
- data/lib/wetransfer/connection.rb +0 -77
- data/lib/wetransfer/item.rb +0 -14
- data/lib/wetransfer/item_builder.rb +0 -59
- data/lib/wetransfer/transfer.rb +0 -30
- data/lib/wetransfer/transfer_builder.rb +0 -28
- data/lib/wetransfer/version.rb +0 -3
- data/spec/client_spec.rb +0 -82
- data/spec/connection_spec.rb +0 -74
- data/spec/item_builder_spec.rb +0 -104
- data/spec/spec_helper.rb +0 -24
- data/spec/test_server.rb +0 -208
- data/spec/wetransfer_spec.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e0f327dda7a10e3f6b84555d9a3345b1542061c
|
4
|
+
data.tar.gz: 3800f908a5b774c44e297cdc1d5047fcdbb95ef7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32550fa1fccece36ff52b75a95f7fc51e6d3d67bf90b6c63962b99671be5b6fa81b6576bbee71a786ee49dea7701450fc3a28007743edd30379bbea0917d3eb5
|
7
|
+
data.tar.gz: 4625e08a9cce1b5bf3f8df1ac209499cc488791b96bb2c18f9086f76ecb999261d3a8482ed2ac878af017f50813b4e6a14a20664f3521dfdaa1c37196634082e
|
data/.travis.yml
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
- 2.
|
5
|
-
- 2.4.4
|
4
|
+
- 2.1.0
|
6
5
|
- 2.5.1
|
7
6
|
- jruby-9.0
|
8
7
|
before_install: gem install bundler -v 1.16.1
|
@@ -11,5 +10,5 @@ matrix:
|
|
11
10
|
allow_failures:
|
12
11
|
- rvm: jruby-9.0
|
13
12
|
script:
|
14
|
-
- bundle exec rubocop -c .rubocop.yml --force-exclusion
|
15
13
|
- bundle exec rspec
|
14
|
+
- bundle exec rubocop -c .rubocop.yml --force-exclusion
|
data/README.md
CHANGED
@@ -19,7 +19,7 @@ For your API key please visit our [developer portal](https://developers.wetransf
|
|
19
19
|
Add this line to your application's Gemfile:
|
20
20
|
|
21
21
|
```ruby
|
22
|
-
gem '
|
22
|
+
gem 'we_transfer_client'
|
23
23
|
```
|
24
24
|
|
25
25
|
And then execute:
|
@@ -32,56 +32,32 @@ Or install it yourself as:
|
|
32
32
|
|
33
33
|
## Usage
|
34
34
|
|
35
|
-
### Configuration
|
36
|
-
|
37
|
-
The gem allows you to configure several settings using environment variables.
|
38
|
-
|
39
|
-
- `WT_API_LOGGING_ON` can be set to (a string) "true" if you want to switch Faraday's default logging on.
|
40
|
-
|
41
|
-
- `WT_API_URL` can be set to a staging or test URL (something we do not offer yet, but plan to in the future)
|
42
|
-
|
43
|
-
- `WT_API_CONNECTION_PATH` can be set to prefix the paths passed to faraday - for example if you're testing against a test API or a different version.
|
44
|
-
|
45
35
|
### Super simple transfers
|
46
36
|
|
47
37
|
You'll need to retrieve an API key from [our developer portal](https://developers.wetransfer.com).
|
48
38
|
|
49
|
-
Be sure to not commit this key to
|
39
|
+
Be sure to not commit this key to Github! If you do though, no worries, you can always revoke & create a new key from within the portal. You will most likely want to pass this to the client setter using an environment variable.
|
50
40
|
|
51
41
|
Now that you've got a wonderful WeTransfer API key, you can create a Client object like so:
|
52
42
|
|
53
43
|
```ruby
|
54
|
-
# In a .env or other secret handling file, not checked in to version control:
|
55
|
-
WT_API_KEY=<your API key>
|
56
|
-
|
57
44
|
# In your project file:
|
58
|
-
@client =
|
45
|
+
@client = WeTransferClient.new(api_key: ENV.fetch('WT_API_KEY'))
|
59
46
|
```
|
60
47
|
|
61
48
|
Now that you've got the client set up you can use the `create_transfer` to, well, create a transfer!
|
62
49
|
|
63
|
-
If you pass item paths to the method it will handle the upload process itself, otherwise you can omit them and
|
64
|
-
use the `add_items` method once the transfer has been created.
|
65
|
-
|
66
50
|
```ruby
|
67
|
-
transfer = @client.create_transfer(name: "My wonderful transfer", description: "I'm so excited to share this"
|
51
|
+
transfer = @client.create_transfer(name: "My wonderful transfer", description: "I'm so excited to share this") do |upload|
|
52
|
+
upload.add_file_at(path: '/path/to/local/file.jpg')
|
53
|
+
upload.add_file_at(path: '/path/to/another/local/file.jpg')
|
54
|
+
upload.add_file(name: 'README.txt', io: StringIO.new("This is the contents of the file"))
|
55
|
+
end
|
68
56
|
|
69
|
-
transfer.shortened_url
|
57
|
+
transfer.shortened_url => "https://we.tl/SSBsb3ZlIHJ1Ynk="
|
70
58
|
```
|
71
59
|
|
72
|
-
|
73
|
-
|
74
|
-
### `add_items`
|
75
|
-
|
76
|
-
If you want slightly more granular control over your transfer, create it without an `items` array, and then use `add_items` with the resulting transfer object.
|
77
|
-
|
78
|
-
```ruby
|
79
|
-
transfer = @client.create_transfer(name: "My wonderful transfer", description: "I'm so excited to share this")
|
80
|
-
|
81
|
-
@client.add_items(transfer: @transfer, items: ["/path/to/local/file_1.jpg", "/path/to/local/file_2.png", "/path/to/local/file_3.key"])
|
82
|
-
|
83
|
-
transfer.shortened_url = "https://we.tl/d2V0cmFuc2Zlci5ob21lcnVuLmNv"
|
84
|
-
```
|
60
|
+
The upload will be performed at the end of the block.
|
85
61
|
|
86
62
|
## Development
|
87
63
|
|
@@ -99,4 +75,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
99
75
|
|
100
76
|
## Code of Conduct
|
101
77
|
|
102
|
-
Everyone interacting in the WetransferRubySdk project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/wetransfer/wetransfer/blob/master/CODE_OF_CONDUCT.md).
|
78
|
+
Everyone interacting in the WetransferRubySdk project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/wetransfer/wetransfer/blob/master/CODE_OF_CONDUCT.md).
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'we_transfer_client'
|
2
|
+
require 'dotenv'
|
3
|
+
Dotenv.load
|
4
|
+
|
5
|
+
client = WeTransferClient.new(api_key: ENV.fetch('WT_API_KEY')) # , logger: Logger.new($stderr))
|
6
|
+
transfer = client.create_transfer(title: 'My amazing board', message: 'Hi there!') do |builder|
|
7
|
+
builder.add_file(name: File.basename(__FILE__), io: File.open(__FILE__, 'rb'))
|
8
|
+
builder.add_file(name: 'amazing.txt', io: StringIO.new('This is unbelievable'))
|
9
|
+
builder.add_file(name: 'huge.bin', io: File.open('/path/to/local/file.jpg', 'rb'))
|
10
|
+
builder.add_file_at(path: __FILE__)
|
11
|
+
end
|
12
|
+
|
13
|
+
puts transfer.shortened_url
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'logger'
|
3
|
+
require 'ks'
|
4
|
+
require 'securerandom'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
class WeTransferClient
|
8
|
+
require_relative 'we_transfer_client/version'
|
9
|
+
|
10
|
+
class Error < StandardError
|
11
|
+
end
|
12
|
+
|
13
|
+
NULL_LOGGER = Logger.new(nil)
|
14
|
+
MAGIC_PART_SIZE = 6 * 1024 * 1024
|
15
|
+
EXPOSED_COLLECTION_ATTRIBUTES = [:id, :version_identifier, :state, :shortened_url, :name, :description, :size, :items]
|
16
|
+
EXPOSED_ITEM_ATTRIBUTES = [:id, :local_identifier, :content_identifier, :name, :size, :mime_type]
|
17
|
+
|
18
|
+
class FutureFileItem < Ks.strict(:name, :io, :local_identifier)
|
19
|
+
def initialize(**kwargs)
|
20
|
+
super(local_identifier: SecureRandom.uuid, **kwargs)
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_item_request_params
|
24
|
+
# Ideally the content identifier should stay the same throughout multiple
|
25
|
+
# calls if the file contents doesn't change.
|
26
|
+
{
|
27
|
+
content_identifier: 'file',
|
28
|
+
local_identifier: local_identifier,
|
29
|
+
filename: name,
|
30
|
+
filesize: io.size,
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class TransferBuilder
|
36
|
+
attr_reader :items
|
37
|
+
|
38
|
+
def initialize
|
39
|
+
@items = []
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_file(name:, io:)
|
43
|
+
ensure_io_compliant!(io)
|
44
|
+
@items << FutureFileItem.new(name: name, io: io)
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_file_at(path:)
|
49
|
+
add_file(name: File.basename(path), io: File.open(path, 'rb'))
|
50
|
+
end
|
51
|
+
|
52
|
+
def ensure_io_compliant!(io)
|
53
|
+
io.seek(0)
|
54
|
+
io.read(1) # Will cause things like Errno::EACCESS to happen early, before the upload begins
|
55
|
+
io.seek(0) # Also rewinds the IO for later uploading action
|
56
|
+
size = io.size # Will cause a NoMethodError
|
57
|
+
raise Error, 'The IO object given to add_file has a size of 0' if size <= 0
|
58
|
+
rescue NoMethodError
|
59
|
+
raise Error, "The IO object given to add_file must respond to seek(), read() and size(), but #{io.inspect} did not"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class FutureTransfer < Ks.strict(:name, :description, :items)
|
64
|
+
def to_create_transfer_params
|
65
|
+
{
|
66
|
+
name: name,
|
67
|
+
description: description,
|
68
|
+
items: items.map(&:to_item_request_params),
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class RemoteTransfer < Ks.strict(*EXPOSED_COLLECTION_ATTRIBUTES)
|
74
|
+
end
|
75
|
+
|
76
|
+
class RemoteItem < Ks.strict(*EXPOSED_ITEM_ATTRIBUTES)
|
77
|
+
end
|
78
|
+
|
79
|
+
def initialize(api_key:, logger: NULL_LOGGER)
|
80
|
+
@api_url_base = 'https://dev.wetransfer.com'
|
81
|
+
@api_key = api_key.to_str
|
82
|
+
@bearer_token = nil
|
83
|
+
@logger = logger
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_transfer(title:, message:)
|
87
|
+
builder = TransferBuilder.new
|
88
|
+
yield(builder)
|
89
|
+
raise 'The transfer you have tried to create contains no items' if builder.items.empty?
|
90
|
+
future_transfer = FutureTransfer.new(name: title, description: message, items: builder.items)
|
91
|
+
create_and_upload(future_transfer)
|
92
|
+
end
|
93
|
+
|
94
|
+
def create_and_upload(xfer)
|
95
|
+
authorize_if_no_bearer_token!
|
96
|
+
response = faraday.post(
|
97
|
+
'/v1/transfers',
|
98
|
+
JSON.pretty_generate(xfer.to_create_transfer_params),
|
99
|
+
auth_headers.merge('Content-Type' => 'application/json')
|
100
|
+
)
|
101
|
+
ensure_ok_status!(response)
|
102
|
+
create_transfer_response = JSON.parse(response.body, symbolize_names: true)
|
103
|
+
|
104
|
+
remote_transfer = hash_to_struct(create_transfer_response, RemoteTransfer)
|
105
|
+
remote_transfer.items = remote_transfer.items.map do |remote_item_hash|
|
106
|
+
hash_to_struct(remote_item_hash, RemoteItem)
|
107
|
+
end
|
108
|
+
|
109
|
+
item_id_map = Hash[xfer.items.map(&:local_identifier).zip(xfer.items)]
|
110
|
+
|
111
|
+
create_transfer_response.fetch(:items).each do |remote_item|
|
112
|
+
local_item = item_id_map.fetch(remote_item.fetch(:local_identifier))
|
113
|
+
remote_item_id = remote_item.fetch(:id)
|
114
|
+
put_io_in_parts(
|
115
|
+
remote_item_id,
|
116
|
+
remote_item.fetch(:meta).fetch(:multipart_parts),
|
117
|
+
remote_item.fetch(:meta).fetch(:multipart_upload_id),
|
118
|
+
local_item.io
|
119
|
+
)
|
120
|
+
|
121
|
+
complete_response = faraday.post(
|
122
|
+
"/v1/files/#{remote_item_id}/uploads/complete",
|
123
|
+
'{}',
|
124
|
+
auth_headers.merge('Content-Type' => 'application/json')
|
125
|
+
)
|
126
|
+
ensure_ok_status!(complete_response)
|
127
|
+
end
|
128
|
+
|
129
|
+
remote_transfer
|
130
|
+
end
|
131
|
+
|
132
|
+
def hash_to_struct(hash, struct_class)
|
133
|
+
members = struct_class.members
|
134
|
+
struct_attrs = Hash[members.zip(hash.values_at(*members))]
|
135
|
+
struct_class.new(**struct_attrs)
|
136
|
+
end
|
137
|
+
|
138
|
+
def put_io_in_parts(item_id, n_parts, multipart_id, io)
|
139
|
+
chunk_size = MAGIC_PART_SIZE
|
140
|
+
(1..n_parts).each do |part_n_one_based|
|
141
|
+
response = faraday.get("/v1/files/#{item_id}/uploads/#{part_n_one_based}/#{multipart_id}", {}, auth_headers)
|
142
|
+
ensure_ok_status!(response)
|
143
|
+
response = JSON.parse(response.body, symbolize_names: true)
|
144
|
+
|
145
|
+
upload_url = response.fetch(:upload_url)
|
146
|
+
part_io = StringIO.new(io.read(chunk_size)) # needs a lens
|
147
|
+
part_io.rewind
|
148
|
+
response = faraday.put(upload_url, part_io, 'Content-Type' => 'binary/octet-stream', 'Content-Length' => part_io.size.to_s)
|
149
|
+
ensure_ok_status!(response)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def faraday
|
154
|
+
Faraday.new(@api_url_base) do |c|
|
155
|
+
c.response :logger, @logger
|
156
|
+
c.adapter Faraday.default_adapter
|
157
|
+
c.headers = { 'User-Agent' => "WetransferRubySdk/#{WeTransferClient::VERSION} Ruby #{RUBY_VERSION}"}
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def authorize_if_no_bearer_token!
|
162
|
+
return if @bearer_token
|
163
|
+
response = faraday.post('/v1/authorize', '{}', 'Content-Type' => 'application/json', 'X-API-Key' => @api_key)
|
164
|
+
ensure_ok_status!(response)
|
165
|
+
@bearer_token = JSON.parse(response.body, symbolize_names: true)[:token]
|
166
|
+
if @bearer_token.nil? || @bearer_token.empty?
|
167
|
+
raise Error, "The authorization call returned #{response.body} and no usable :token key could be found there"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def auth_headers
|
172
|
+
raise 'No bearer token retrieved yet' unless @bearer_token
|
173
|
+
{
|
174
|
+
'X-API-Key' => @api_key,
|
175
|
+
'Authorization' => ('Bearer %s' % @bearer_token),
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
def ensure_ok_status!(response)
|
180
|
+
case response.status
|
181
|
+
when 200..299
|
182
|
+
nil
|
183
|
+
when 400..499
|
184
|
+
@logger.error { response.body }
|
185
|
+
raise Error, "Response had a #{response.status} code, the server will not accept this request even if retried"
|
186
|
+
when 500..504
|
187
|
+
@logger.error { response.body }
|
188
|
+
raise Error, "Response had a #{response.status} code, we could retry"
|
189
|
+
else
|
190
|
+
@logger.error { response.body }
|
191
|
+
raise Error, "Response had a #{response.status} code, no idea what to do with that"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
4
|
+
|
5
|
+
require 'dotenv'
|
6
|
+
Dotenv.load
|
7
|
+
|
8
|
+
require_relative '../lib/we_transfer_client.rb'
|
9
|
+
|
10
|
+
describe WeTransferClient do
|
11
|
+
let :test_logger do
|
12
|
+
Logger.new($stderr).tap { |log| log.level = Logger::WARN }
|
13
|
+
end
|
14
|
+
|
15
|
+
let :very_large_file do
|
16
|
+
tf = Tempfile.new('test-upload')
|
17
|
+
20.times { tf << Random.new.bytes(1024 * 1024) }
|
18
|
+
tf << Random.new.bytes(rand(1..512))
|
19
|
+
tf.rewind
|
20
|
+
tf
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'exposes VERSION' do
|
24
|
+
expect(WeTransferClient::VERSION).to be_kind_of(String)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'is able to create a transfer start to finish, both with small and large files' do
|
28
|
+
client = WeTransferClient.new(api_key: ENV.fetch('WT_API_KEY'), logger: test_logger)
|
29
|
+
transfer = client.create_transfer(title: 'My amazing board', message: 'Hi there!') do |builder|
|
30
|
+
# Upload ourselves
|
31
|
+
add_result = builder.add_file(name: File.basename(__FILE__), io: File.open(__FILE__, 'rb'))
|
32
|
+
expect(add_result).to eq(true)
|
33
|
+
|
34
|
+
# Upload ourselves again, but using add_file_at
|
35
|
+
add_result = builder.add_file_at(path: __FILE__) # Upload ourselves again, but this time via path
|
36
|
+
expect(add_result).to eq(true)
|
37
|
+
|
38
|
+
# Upload the large file
|
39
|
+
add_result = builder.add_file(name: 'large.bin', io: very_large_file)
|
40
|
+
expect(add_result).to eq(true)
|
41
|
+
|
42
|
+
expect(add_result).to eq(true)
|
43
|
+
end
|
44
|
+
|
45
|
+
expect(transfer).to be_kind_of(WeTransferClient::RemoteTransfer)
|
46
|
+
expect(transfer.id).to be_kind_of(String)
|
47
|
+
|
48
|
+
# expect(transfer.version_identifier).to be_kind_of(String)
|
49
|
+
expect(transfer.state).to be_kind_of(String)
|
50
|
+
expect(transfer.name).to eq('My amazing board')
|
51
|
+
expect(transfer.description).to eq('Hi there!')
|
52
|
+
expect(transfer.items).to be_kind_of(Array)
|
53
|
+
expect(transfer.items.length).to eq(3)
|
54
|
+
|
55
|
+
item = transfer.items.first
|
56
|
+
expect(item).to be_kind_of(WeTransferClient::RemoteItem)
|
57
|
+
|
58
|
+
expect(transfer.shortened_url).to be_kind_of(String)
|
59
|
+
response = Faraday.get(transfer.shortened_url)
|
60
|
+
expect(response.status).to eq(302)
|
61
|
+
expect(response['location']).to start_with('https://wetransfer')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'refuses to create a transfer with no items' do
|
65
|
+
client = WeTransferClient.new(api_key: ENV.fetch('WT_API_KEY'), logger: test_logger)
|
66
|
+
expect {
|
67
|
+
client.create_transfer(title: 'My amazing board', message: 'Hi there!') do |builder|
|
68
|
+
# ...do nothing
|
69
|
+
end
|
70
|
+
}.to raise_error(/no items/)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'refuses to create a transfer when reading an IO raises an error' do
|
74
|
+
broken = StringIO.new('hello')
|
75
|
+
def broken.read(*)
|
76
|
+
raise 'This failed somehow'
|
77
|
+
end
|
78
|
+
|
79
|
+
client = WeTransferClient.new(api_key: ENV.fetch('WT_API_KEY'), logger: test_logger)
|
80
|
+
expect(client).not_to receive(:faraday) # Since we will not be doing any requests - we fail earlier
|
81
|
+
expect {
|
82
|
+
client.create_transfer(title: 'My amazing board', message: 'Hi there!') do |builder|
|
83
|
+
builder.add_file(name: 'broken', io: broken)
|
84
|
+
end
|
85
|
+
}.to raise_error(/failed somehow/)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'refuses to create a transfer when given an IO of 0 size' do
|
89
|
+
broken = StringIO.new('')
|
90
|
+
|
91
|
+
client = WeTransferClient.new(api_key: ENV.fetch('WT_API_KEY'), logger: test_logger)
|
92
|
+
expect {
|
93
|
+
client.create_transfer(title: 'My amazing board', message: 'Hi there!') do |builder|
|
94
|
+
builder.add_file(name: 'broken', io: broken)
|
95
|
+
end
|
96
|
+
}.to raise_error(/has a size of 0/)
|
97
|
+
end
|
98
|
+
end
|
data/wetransfer.gemspec
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require '
|
4
|
+
require 'we_transfer_client/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'wetransfer'
|
8
|
-
spec.version =
|
8
|
+
spec.version = WeTransferClient::VERSION
|
9
9
|
spec.authors = ['Noah Berman', 'David Bosveld']
|
10
10
|
spec.email = ['noah@wetransfer.com', 'david@wetransfer.com', 'developers@wetransfer.com']
|
11
11
|
|
@@ -23,18 +23,15 @@ Gem::Specification.new do |spec|
|
|
23
23
|
'public gem pushes.'
|
24
24
|
end
|
25
25
|
|
26
|
-
spec.files = `git ls-files -z`.split("\x0")
|
27
|
-
# Make sure large fixture files are not packaged with the gem every time
|
28
|
-
f.match(%r{^spec/fixtures/})
|
29
|
-
end
|
26
|
+
spec.files = `git ls-files -z`.split("\x0")
|
30
27
|
spec.bindir = 'exe'
|
31
28
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
29
|
spec.require_paths = ['lib']
|
33
30
|
|
34
|
-
spec.add_dependency 'faraday', '~> 0.
|
35
|
-
spec.add_dependency 'dotenv', '~> 2.2'
|
31
|
+
spec.add_dependency 'faraday', '~> 0.15'
|
36
32
|
spec.add_dependency 'ks', '~> 0.0.1'
|
37
33
|
|
34
|
+
spec.add_development_dependency 'dotenv', '~> 2.2'
|
38
35
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
39
36
|
spec.add_development_dependency 'pry', '~> 0.11'
|
40
37
|
spec.add_development_dependency 'rake', '~> 10.0'
|