files.com 1.1.794 → 1.1.796
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/Gemfile.lock +1 -1
- data/_VERSION +1 -1
- data/lib/files.com/models/file.rb +42 -10
- data/spec/api_scenarios_spec.rb +1298 -0
- data/spec/models/file_transfer_spec.rb +191 -0
- data/spec/models/file_underscore_destinations_spec.rb +1 -1
- data/spec/spec_helper.rb +118 -8
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 86cf131c69ae6f5ed14759519a6eda0fc7418da517049dd58742d0d6e88e6f03
|
|
4
|
+
data.tar.gz: 1f12f821cf54a85007457ffbe4ece5d8188746fa91c649f136519b25da09e891
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d9027441e8bec7da48773e17a0d588dbce31b6748569539fa1836db5330256cae1812ce8cfa54d48cea818c8261ce319b36fca8db570baf9314898bc6054fa0
|
|
7
|
+
data.tar.gz: 3f55c0d42f68137795ac00df50a0a5d5988c9d717f544b1124a5095af4a4c04dc0bf31808154ce7c70d9ef9c4726dc963a1853813a8689b8b3c9365f5804e087
|
data/Gemfile.lock
CHANGED
data/_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.1.
|
|
1
|
+
1.1.796
|
|
@@ -72,9 +72,9 @@ module Files
|
|
|
72
72
|
PathUtil.normalize("_", root, id.to_s, relative_path)
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
def self.upload_to_remote_server(path, remote_server_id, destination = nil, options = {}, params: {})
|
|
75
|
+
def self.upload_to_remote_server(path, remote_server_id, destination = nil, options = {}, params: {}, progress: nil)
|
|
76
76
|
destination ||= ::File.basename(path)
|
|
77
|
-
upload_file(path, underscore_destination_path("RemoteServers", remote_server_id, destination), options, params: params)
|
|
77
|
+
upload_file(path, underscore_destination_path("RemoteServers", remote_server_id, destination), options, params: params, progress: progress)
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def self.copy_to_remote_server(path, remote_server_id, destination, params = {}, options = {})
|
|
@@ -85,9 +85,9 @@ module Files
|
|
|
85
85
|
move(path, params.merge(destination: underscore_destination_path("RemoteServers", remote_server_id, destination)), options)
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
def self.upload_to_snapshot(path, snapshot_id, destination = nil, options = {}, params: {})
|
|
88
|
+
def self.upload_to_snapshot(path, snapshot_id, destination = nil, options = {}, params: {}, progress: nil)
|
|
89
89
|
destination ||= ::File.basename(path)
|
|
90
|
-
upload_file(path, underscore_destination_path("Snapshots", snapshot_id, destination), options, params: params)
|
|
90
|
+
upload_file(path, underscore_destination_path("Snapshots", snapshot_id, destination), options, params: params, progress: progress)
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
def self.copy_to_snapshot(path, snapshot_id, destination, params = {}, options = {})
|
|
@@ -98,9 +98,9 @@ module Files
|
|
|
98
98
|
move(path, params.merge(destination: underscore_destination_path("Snapshots", snapshot_id, destination)), options)
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
-
def self.upload_to_child_site(path, site_id, destination = nil, options = {}, params: {})
|
|
101
|
+
def self.upload_to_child_site(path, site_id, destination = nil, options = {}, params: {}, progress: nil)
|
|
102
102
|
destination ||= ::File.basename(path)
|
|
103
|
-
upload_file(path, underscore_destination_path("Sites", site_id, destination), options, params: params)
|
|
103
|
+
upload_file(path, underscore_destination_path("Sites", site_id, destination), options, params: params, progress: progress)
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def self.copy_to_child_site(path, site_id, destination, params = {}, options = {})
|
|
@@ -207,27 +207,59 @@ module Files
|
|
|
207
207
|
paths.map { |p| delete(p) }
|
|
208
208
|
end
|
|
209
209
|
|
|
210
|
-
|
|
210
|
+
# Uploads what io holds to path, a part at a time as the API grants each, and returns the last part, the parts'
|
|
211
|
+
# ETags and the bytes sent. Each part is filled from as many reads as it takes (read_part). With progress, a
|
|
212
|
+
# callable, each part's response must be a success (2xx) before the part counts as acknowledged; progress is then
|
|
213
|
+
# called with total_bytes (nil: unknown here), acknowledged_bytes (this call's bytes so far), part_number and
|
|
214
|
+
# part_bytes. Anything it raises ends the upload there, with no later part planned or sent.
|
|
215
|
+
def self.upload_chunks(io, path, options, upload = nil, etags = [], params: {}, progress: nil)
|
|
211
216
|
etags ||= []
|
|
212
217
|
bytes_written = 0
|
|
213
218
|
request_parts = options[:size] && options[:size] < 5.megabytes ? 1 : 5
|
|
214
219
|
loop do
|
|
215
220
|
begin_upload = File.begin_upload(path, params.merge(ref: upload&.ref, parts: request_parts, part: (upload&.part_number || 0) + 1), options) if begin_upload.nil? || begin_upload.empty?
|
|
216
221
|
upload = begin_upload.is_a?(Enumerable) ? begin_upload.shift : begin_upload
|
|
217
|
-
buf = io
|
|
222
|
+
buf = read_part(io, upload.partsize)
|
|
218
223
|
bytes_written += buf.length
|
|
219
224
|
method = upload.http_method.downcase.to_sym
|
|
220
225
|
response = client(options).remote_request(method, upload.upload_uri, { 'Content-Length': buf.length.to_s, 'Content-Type': 'application/octet-stream' }, buf)
|
|
226
|
+
raise APIError.new("Transfer request failed", http_status: response.status), cause: nil if progress && !response.status.between?(200, 299)
|
|
227
|
+
|
|
221
228
|
etags << { etag: response.headers["ETag"], part: upload.part_number }
|
|
229
|
+
progress&.call({ total_bytes: nil, acknowledged_bytes: bytes_written, part_number: upload.part_number, part_bytes: buf.length })
|
|
222
230
|
return upload, etags, bytes_written if io.eof?
|
|
223
231
|
end
|
|
224
232
|
end
|
|
225
233
|
|
|
226
|
-
|
|
234
|
+
# The next part's bytes from io: as many reads as it takes to fill length bytes. A read that gives nothing (nil or
|
|
235
|
+
# "") ends the part when io.eof? says the source has ended; before its end, the source made no progress, and the
|
|
236
|
+
# part is not sent.
|
|
237
|
+
private_class_method def self.read_part(io, length)
|
|
238
|
+
buf = String.new(encoding: Encoding::BINARY)
|
|
239
|
+
while buf.bytesize < length
|
|
240
|
+
chunk = io.read(length - buf.bytesize)
|
|
241
|
+
if chunk.nil? || chunk.empty?
|
|
242
|
+
break if io.eof?
|
|
243
|
+
|
|
244
|
+
raise InvalidParameterError, "The upload source returned no bytes before its end"
|
|
245
|
+
end
|
|
246
|
+
# A read that fills the part at once, as an IO's or a StringIO's does, is sent as it came.
|
|
247
|
+
return chunk if buf.empty? && chunk.bytesize == length
|
|
248
|
+
|
|
249
|
+
buf << chunk.b
|
|
250
|
+
end
|
|
251
|
+
buf
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# With progress, a callable, it is called after each part is acknowledged, as upload_chunks reports it, with
|
|
255
|
+
# total_bytes the local file's size.
|
|
256
|
+
def self.upload_file(path, destination = nil, options = {}, params: {}, progress: nil)
|
|
227
257
|
local_file = ::File.open(path, 'r')
|
|
228
258
|
destination ||= File.basename(path)
|
|
229
259
|
params[:size] ||= local_file.size
|
|
230
|
-
|
|
260
|
+
total_bytes = local_file.size
|
|
261
|
+
report = progress && ->(part) { progress.call(part.merge(total_bytes: total_bytes)) }
|
|
262
|
+
upload, etags = upload_chunks(local_file, destination, options, params: params, progress: report)
|
|
231
263
|
|
|
232
264
|
params = {
|
|
233
265
|
action: "end",
|