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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b13b897dc28165d84d3736775184a54e5fabc23d80109a575e87f2945512598
4
- data.tar.gz: 6882635f60763cf6c6348051946fc2e9afb3c1d1d0021455d82d987e43dceaf3
3
+ metadata.gz: 86cf131c69ae6f5ed14759519a6eda0fc7418da517049dd58742d0d6e88e6f03
4
+ data.tar.gz: 1f12f821cf54a85007457ffbe4ece5d8188746fa91c649f136519b25da09e891
5
5
  SHA512:
6
- metadata.gz: e9bd784476603c454fe028c45e09a2ed5f25380e60cace4b9cae1c5fe33fb6faf7091881ca609d171416fe73d48f29ff1aae339975b289b321800f4c0bcbeaf5
7
- data.tar.gz: 4af70dc19ba7ccf9d8035e4633d78ba2c10e52e4ba677e5b41b440bf1c20b502722483e42966d4d01b94b093c494453575158cc6b5c105bf4b1ea2a77025abbd
6
+ metadata.gz: 1d9027441e8bec7da48773e17a0d588dbce31b6748569539fa1836db5330256cae1812ce8cfa54d48cea818c8261ce319b36fca8db570baf9314898bc6054fa0
7
+ data.tar.gz: 3f55c0d42f68137795ac00df50a0a5d5988c9d717f544b1124a5095af4a4c04dc0bf31808154ce7c70d9ef9c4726dc963a1853813a8689b8b3c9365f5804e087
data/Gemfile.lock CHANGED
@@ -103,4 +103,4 @@ DEPENDENCIES
103
103
  rubocop
104
104
 
105
105
  BUNDLED WITH
106
- 4.0.21
106
+ 4.0.23
data/_VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.794
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
- def self.upload_chunks(io, path, options, upload = nil, etags = [], params: {})
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.read(upload.partsize) || ""
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
- def self.upload_file(path, destination = nil, options = {}, params: {})
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
- upload, etags = upload_chunks(local_file, destination, options, params: params)
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",