mss-sdk 1.0.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.
Files changed (131) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +9 -0
  3. data/LICENSE.txt +0 -0
  4. data/README.md +192 -0
  5. data/bin/mss-rb +178 -0
  6. data/ca-bundle.crt +3554 -0
  7. data/lib/mss/core/async_handle.rb +89 -0
  8. data/lib/mss/core/cacheable.rb +76 -0
  9. data/lib/mss/core/client.rb +786 -0
  10. data/lib/mss/core/collection/simple.rb +81 -0
  11. data/lib/mss/core/collection/with_limit_and_next_token.rb +70 -0
  12. data/lib/mss/core/collection/with_next_token.rb +96 -0
  13. data/lib/mss/core/collection.rb +262 -0
  14. data/lib/mss/core/configuration.rb +527 -0
  15. data/lib/mss/core/credential_providers.rb +653 -0
  16. data/lib/mss/core/data.rb +251 -0
  17. data/lib/mss/core/deprecations.rb +83 -0
  18. data/lib/mss/core/endpoints.rb +36 -0
  19. data/lib/mss/core/http/connection_pool.rb +374 -0
  20. data/lib/mss/core/http/curb_handler.rb +150 -0
  21. data/lib/mss/core/http/handler.rb +88 -0
  22. data/lib/mss/core/http/net_http_handler.rb +144 -0
  23. data/lib/mss/core/http/patch.rb +98 -0
  24. data/lib/mss/core/http/request.rb +258 -0
  25. data/lib/mss/core/http/response.rb +80 -0
  26. data/lib/mss/core/indifferent_hash.rb +87 -0
  27. data/lib/mss/core/inflection.rb +55 -0
  28. data/lib/mss/core/ini_parser.rb +41 -0
  29. data/lib/mss/core/json_client.rb +46 -0
  30. data/lib/mss/core/json_parser.rb +75 -0
  31. data/lib/mss/core/json_request_builder.rb +34 -0
  32. data/lib/mss/core/json_response_parser.rb +78 -0
  33. data/lib/mss/core/lazy_error_classes.rb +107 -0
  34. data/lib/mss/core/log_formatter.rb +426 -0
  35. data/lib/mss/core/managed_file.rb +31 -0
  36. data/lib/mss/core/meta_utils.rb +44 -0
  37. data/lib/mss/core/model.rb +61 -0
  38. data/lib/mss/core/naming.rb +29 -0
  39. data/lib/mss/core/option_grammar.rb +737 -0
  40. data/lib/mss/core/options/json_serializer.rb +81 -0
  41. data/lib/mss/core/options/validator.rb +154 -0
  42. data/lib/mss/core/options/xml_serializer.rb +117 -0
  43. data/lib/mss/core/page_result.rb +74 -0
  44. data/lib/mss/core/policy.rb +938 -0
  45. data/lib/mss/core/query_client.rb +40 -0
  46. data/lib/mss/core/query_error_parser.rb +23 -0
  47. data/lib/mss/core/query_request_builder.rb +46 -0
  48. data/lib/mss/core/query_response_parser.rb +34 -0
  49. data/lib/mss/core/region.rb +84 -0
  50. data/lib/mss/core/region_collection.rb +79 -0
  51. data/lib/mss/core/resource.rb +412 -0
  52. data/lib/mss/core/resource_cache.rb +39 -0
  53. data/lib/mss/core/response.rb +214 -0
  54. data/lib/mss/core/response_cache.rb +49 -0
  55. data/lib/mss/core/rest_error_parser.rb +23 -0
  56. data/lib/mss/core/rest_json_client.rb +39 -0
  57. data/lib/mss/core/rest_request_builder.rb +153 -0
  58. data/lib/mss/core/rest_response_parser.rb +65 -0
  59. data/lib/mss/core/rest_xml_client.rb +46 -0
  60. data/lib/mss/core/service_interface.rb +82 -0
  61. data/lib/mss/core/signers/base.rb +45 -0
  62. data/lib/mss/core/signers/cloud_front.rb +55 -0
  63. data/lib/mss/core/signers/s3.rb +158 -0
  64. data/lib/mss/core/signers/version_2.rb +71 -0
  65. data/lib/mss/core/signers/version_3.rb +85 -0
  66. data/lib/mss/core/signers/version_3_https.rb +60 -0
  67. data/lib/mss/core/signers/version_4/chunk_signed_stream.rb +190 -0
  68. data/lib/mss/core/signers/version_4.rb +227 -0
  69. data/lib/mss/core/uri_escape.rb +43 -0
  70. data/lib/mss/core/xml/frame.rb +245 -0
  71. data/lib/mss/core/xml/frame_stack.rb +84 -0
  72. data/lib/mss/core/xml/grammar.rb +306 -0
  73. data/lib/mss/core/xml/parser.rb +69 -0
  74. data/lib/mss/core/xml/root_frame.rb +64 -0
  75. data/lib/mss/core/xml/sax_handlers/libxml.rb +46 -0
  76. data/lib/mss/core/xml/sax_handlers/nokogiri.rb +55 -0
  77. data/lib/mss/core/xml/sax_handlers/ox.rb +40 -0
  78. data/lib/mss/core/xml/sax_handlers/rexml.rb +46 -0
  79. data/lib/mss/core/xml/stub.rb +122 -0
  80. data/lib/mss/core.rb +602 -0
  81. data/lib/mss/errors.rb +161 -0
  82. data/lib/mss/rails.rb +194 -0
  83. data/lib/mss/s3/access_control_list.rb +262 -0
  84. data/lib/mss/s3/acl_object.rb +263 -0
  85. data/lib/mss/s3/acl_options.rb +200 -0
  86. data/lib/mss/s3/bucket.rb +757 -0
  87. data/lib/mss/s3/bucket_collection.rb +161 -0
  88. data/lib/mss/s3/bucket_lifecycle_configuration.rb +472 -0
  89. data/lib/mss/s3/bucket_region_cache.rb +51 -0
  90. data/lib/mss/s3/bucket_tag_collection.rb +110 -0
  91. data/lib/mss/s3/bucket_version_collection.rb +78 -0
  92. data/lib/mss/s3/cipher_io.rb +119 -0
  93. data/lib/mss/s3/client/xml.rb +265 -0
  94. data/lib/mss/s3/client.rb +2076 -0
  95. data/lib/mss/s3/config.rb +60 -0
  96. data/lib/mss/s3/cors_rule.rb +107 -0
  97. data/lib/mss/s3/cors_rule_collection.rb +193 -0
  98. data/lib/mss/s3/data_options.rb +190 -0
  99. data/lib/mss/s3/encryption_utils.rb +145 -0
  100. data/lib/mss/s3/errors.rb +93 -0
  101. data/lib/mss/s3/multipart_upload.rb +353 -0
  102. data/lib/mss/s3/multipart_upload_collection.rb +75 -0
  103. data/lib/mss/s3/object_collection.rb +355 -0
  104. data/lib/mss/s3/object_metadata.rb +102 -0
  105. data/lib/mss/s3/object_upload_collection.rb +76 -0
  106. data/lib/mss/s3/object_version.rb +153 -0
  107. data/lib/mss/s3/object_version_collection.rb +88 -0
  108. data/lib/mss/s3/paginated_collection.rb +74 -0
  109. data/lib/mss/s3/policy.rb +73 -0
  110. data/lib/mss/s3/prefix_and_delimiter_collection.rb +46 -0
  111. data/lib/mss/s3/prefixed_collection.rb +84 -0
  112. data/lib/mss/s3/presign_v4.rb +135 -0
  113. data/lib/mss/s3/presigned_post.rb +574 -0
  114. data/lib/mss/s3/region_detection.rb +75 -0
  115. data/lib/mss/s3/request.rb +61 -0
  116. data/lib/mss/s3/s3_object.rb +1795 -0
  117. data/lib/mss/s3/tree/branch_node.rb +67 -0
  118. data/lib/mss/s3/tree/child_collection.rb +103 -0
  119. data/lib/mss/s3/tree/leaf_node.rb +93 -0
  120. data/lib/mss/s3/tree/node.rb +21 -0
  121. data/lib/mss/s3/tree/parent.rb +86 -0
  122. data/lib/mss/s3/tree.rb +115 -0
  123. data/lib/mss/s3/uploaded_part.rb +81 -0
  124. data/lib/mss/s3/uploaded_part_collection.rb +83 -0
  125. data/lib/mss/s3/website_configuration.rb +101 -0
  126. data/lib/mss/s3.rb +161 -0
  127. data/lib/mss/version.rb +16 -0
  128. data/lib/mss-sdk.rb +2 -0
  129. data/lib/mss.rb +14 -0
  130. data/rails/init.rb +14 -0
  131. metadata +201 -0
@@ -0,0 +1,93 @@
1
+ # Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ #
8
+ # or in the "license" file accompanying this file. This file is
9
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
10
+ # ANY KIND, either express or implied. See the License for the specific
11
+ # language governing permissions and limitations under the License.
12
+
13
+ module MSS
14
+ class S3
15
+
16
+ # This module contains exception classes for each of the error
17
+ # types that S3 can return. You can use these classes to rescue
18
+ # specific errors, for example:
19
+ #
20
+ # begin
21
+ # S3.new.buckets.mybucket.
22
+ # objects.myobj.write("HELLO")
23
+ # rescue S3::Errors::NoSuchBucket => e
24
+ # S3.new.buckets.create("mybucket")
25
+ # retry
26
+ # end
27
+ #
28
+ # All errors raised as a result of error responses from the
29
+ # service are instances of either {ClientError} or {ServerError}.
30
+ module Errors
31
+
32
+ # @api private
33
+ GRAMMAR = Core::XML::Grammar.customize
34
+
35
+ extend Core::LazyErrorClasses
36
+
37
+ class BatchDeleteError < StandardError
38
+
39
+ def initialize error_counts
40
+ @error_counts = error_counts
41
+ total = error_counts.values.inject(0) {|sum,count| sum + count }
42
+ super("Failed to delete #{total} objects")
43
+ end
44
+
45
+ # @return [Hash] Returns a hash of error codes and how many
46
+ # objects failed with that code.
47
+ attr_reader :error_counts
48
+
49
+ end
50
+
51
+ # This error is special, because S3 does not (and must not
52
+ # according to RFC 2616) return a body with the HTTP response.
53
+ # The interface is the same as for any other client error.
54
+ class NotModified < MSS::Errors::Base
55
+
56
+ include MSS::Errors::ClientError
57
+
58
+ def initialize(req, resp)
59
+ super(req, resp, "NotModified", "Not Modified")
60
+ end
61
+
62
+ end
63
+
64
+ # This error is special, because S3 does not return a body with
65
+ # the HTTP response. The interface is the same as for any other
66
+ # client error.
67
+ class NoSuchKey < MSS::Errors::Base
68
+
69
+ include MSS::Errors::ClientError
70
+
71
+ def initialize(req, resp, code = nil, message = nil)
72
+ super(req, resp, "NoSuchKey", "No Such Key")
73
+ end
74
+
75
+ end
76
+
77
+ # This error is special, because S3 must first retrieve the client
78
+ # side encryption key in it's encrypted form before finding if the
79
+ # key is incorrect.
80
+ class IncorrectClientSideEncryptionKey < MSS::Errors::Base
81
+
82
+ include MSS::Errors::ClientError
83
+
84
+ def initialize(msg)
85
+ super("",
86
+ "",
87
+ "IncorrectClientSideEncryptionKey",
88
+ msg)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,353 @@
1
+ # Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ #
8
+ # or in the "license" file accompanying this file. This file is
9
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
10
+ # ANY KIND, either express or implied. See the License for the specific
11
+ # language governing permissions and limitations under the License.
12
+
13
+ require 'thread'
14
+
15
+ module MSS
16
+ class S3
17
+
18
+ # Represents a multipart upload to an S3 object. See
19
+ # {S3Object#multipart_upload} for a convenient way to initiate a
20
+ # multipart upload.
21
+ #
22
+ # Note: After you initiate multipart upload and upload one or more
23
+ # parts, you must either complete or abort multipart upload in order
24
+ # to stop getting charged for storage of the uploaded parts. Only
25
+ # after you either complete or abort multipart upload, Amazon S3
26
+ # frees up the parts storage and stops charging you for the parts
27
+ # storage.
28
+ class MultipartUpload
29
+
30
+ include Core::Model
31
+
32
+ class EmptyUploadError < StandardError; end
33
+
34
+ # @api private
35
+ def initialize(object, id, options = {})
36
+ @id = id
37
+ @object = object
38
+
39
+ super
40
+
41
+ @completed_parts = {}
42
+ @increment_mutex = Mutex.new
43
+ @completed_mutex = Mutex.new
44
+ @last_part = 0
45
+ end
46
+
47
+ def bucket
48
+ object.bucket
49
+ end
50
+
51
+ def inspect
52
+ "<#{self.class}:#{object.bucket.name}/#{object.key}:#{id}>"
53
+ end
54
+ # @return [String] Returns the upload id.
55
+ attr_reader :id
56
+
57
+ alias_method :upload_id, :id
58
+
59
+ # @return [S3Object] Returns the object this upload is intended for.
60
+ attr_reader :object
61
+
62
+ # @return [Boolean] Returns true if both multipart uploads
63
+ # represent the same object and upload.
64
+ def ==(other)
65
+ other.kind_of?(MultipartUpload) and
66
+ other.object == object and
67
+ other.id == id
68
+ end
69
+
70
+ alias_method :eql?, :==
71
+
72
+ # @return [Boolean] True if the upload exists.
73
+ #def exists?
74
+ # client.list_parts(base_opts)
75
+ #rescue Errors::NoSuchUpload => e
76
+ # false
77
+ #else
78
+ # true
79
+ #end
80
+
81
+ # @return The upload initiator. This object will have `:id`
82
+ # and `:display_name` methods; if the initiator is an IAM
83
+ # user, the `:id` method will return the ARN of the user, and
84
+ # if the initiator is an MSS account, this method will return
85
+ # the same data as {#owner}.
86
+ #def initiator
87
+ # client.list_parts(base_opts).initiator
88
+ #end
89
+
90
+ # @return The upload owner. This object will have `:id`
91
+ # and `:display_name` methods.
92
+ #def owner
93
+ # client.list_parts(base_opts).owner
94
+ #end
95
+
96
+ # @return [Symbol] The class of storage used to store the
97
+ # uploaded object. Possible values:
98
+ #
99
+ # * `:standard`
100
+ # * `:reduced_redundancy?`
101
+ #def storage_class
102
+ # client.list_parts(base_opts).storage_class.downcase.to_sym
103
+ #end
104
+
105
+ # @return [Boolean] True if the uploaded object will be stored
106
+ # with reduced redundancy.
107
+ #def reduced_redundancy?
108
+ # storage_class == :reduced_redundancy
109
+ #end
110
+
111
+ # Aborts the upload. After a multipart upload is aborted, no
112
+ # additional parts can be uploaded using that upload ID. The
113
+ # storage consumed by any previously uploaded parts will be
114
+ # freed. However, if any part uploads are currently in
115
+ # progress, those part uploads might or might not succeed. As
116
+ # a result, it might be necessary to abort a given multipart
117
+ # upload multiple times in order to completely free all
118
+ # storage consumed by all parts.
119
+ # @return [nil]
120
+ def abort
121
+ unless aborted?
122
+ client.abort_multipart_upload(base_opts)
123
+ @aborted = true
124
+ end
125
+ nil
126
+ end
127
+ alias_method :delete, :abort
128
+ alias_method :cancel, :abort
129
+
130
+ # @return [Boolean] True if the upload has been aborted.
131
+ # @see #abort
132
+ def aborted?
133
+ @aborted
134
+ end
135
+
136
+ # Uploads a part.
137
+ #
138
+ # @overload add_part(data, options = {})
139
+ #
140
+ # @param data The data to upload.
141
+ # Valid values include:
142
+ #
143
+ # * A string
144
+ # * A Pathname object
145
+ # * Any object responding to `read` and `eof?`; the object
146
+ # must support the following access methods:
147
+ #
148
+ # read # all at once
149
+ # read(length) until eof? # in chunks
150
+ #
151
+ # If you specify data this way, you must also include
152
+ # the `:content_length` option.
153
+ #
154
+ # @param [Hash] options Additional options for the upload.
155
+ #
156
+ # @option options [Integer] :content_length If provided,
157
+ # this option must match the total number of bytes written
158
+ # to S3 during the operation. This option is required if
159
+ # `:data` is an IO-like object without a `size` method.
160
+ #
161
+ # @overload add_part(options)
162
+ #
163
+ # @param [Hash] options Options for the upload. Either
164
+ # `:data` or `:file` is required.
165
+ #
166
+ # @option options :data The data to upload. Valid values
167
+ # include:
168
+ #
169
+ # * A string
170
+ # * A Pathname object
171
+ # * Any object responding to `read` and `eof?`; the object
172
+ # must support the following access methods:
173
+ #
174
+ # read # all at once
175
+ # read(length) until eof? # in chunks
176
+ #
177
+ # If you specify data this way, you must also include
178
+ # the `:content_length` option.
179
+ #
180
+ # @option options [String] :file Can be specified instead of
181
+ # `:data`; its value specifies the path of a file to
182
+ # upload.
183
+ #
184
+ # @option options [Integer] :content_length If provided,
185
+ # this option must match the total number of bytes written
186
+ # to S3 during the operation. This option is required if
187
+ # `:data` is an IO-like object without a `size` method.
188
+ #
189
+ # @option options [Integer] :part_number The part number.
190
+ def add_part(data_or_options, options = {})
191
+ if data_or_options.kind_of?(Hash)
192
+ part_options = base_opts.merge(data_or_options)
193
+ else
194
+ part_options = base_opts.merge(:data => data_or_options)
195
+ end
196
+ part_options.merge!(options)
197
+
198
+ unless part_options[:part_number]
199
+ @increment_mutex.synchronize do
200
+ part_options[:part_number] = (@last_part += 1)
201
+ end
202
+ end
203
+ part_number = part_options[:part_number]
204
+
205
+ resp = client.upload_part(part_options)
206
+ @completed_mutex.synchronize do
207
+ @completed_parts[part_number] = {
208
+ :part_number => part_number,
209
+ :etag => resp.etag
210
+ }
211
+ end
212
+ UploadedPart.new(self, part_number)
213
+ end
214
+
215
+ # Copies a part.
216
+ #
217
+ # @param [string] copy_source Full S3 name of source, ie bucket/key
218
+ #
219
+ # @param [Hash] options Additional options for the copy.
220
+ #
221
+ # @option options [Integer] :part_number The part number.
222
+ #
223
+ # @option options [Integer] :copy_source_range Range of bytes to copy, ie bytes=0-45687
224
+ #def copy_part(copy_source, options = {})
225
+ # part_options = base_opts.merge(options)
226
+ # part_options.merge!(:copy_source => copy_source)
227
+
228
+ # unless part_options[:part_number]
229
+ # @increment_mutex.synchronize do
230
+ # part_options[:part_number] = (@last_part += 1)
231
+ # end
232
+ # end
233
+ # part_number = part_options[:part_number]
234
+
235
+ # resp = client.copy_part(part_options)
236
+ # @completed_mutex.synchronize do
237
+ # @completed_parts[part_number] = {
238
+ # :part_number => part_number,
239
+ # :etag => resp[:etag]
240
+ # }
241
+ # end
242
+ # UploadedPart.new(self, part_number)
243
+ #end
244
+
245
+ # Completes the upload by assembling previously uploaded
246
+ # parts.
247
+ #
248
+ # @return [S3Object, ObjectVersion] If the bucket has versioning
249
+ # enabled, returns the {ObjectVersion} representing the
250
+ # version that was uploaded. If versioning is disabled,
251
+ # returns the object.
252
+ #def complete(*parts)
253
+ def complete()
254
+ #parts = parts.flatten
255
+ #case parts.first
256
+ #when :remote_parts
257
+ # complete_opts = get_complete_opts
258
+ #when :local_parts, nil
259
+ complete_opts = base_opts.merge(:parts => completed_parts)
260
+ #else
261
+ # part_numbers = parts.map do |part|
262
+ # case part
263
+ # when Integer
264
+ # part
265
+ # when UploadedPart
266
+ # raise ArgumentError.new("cannot complete an upload with parts "+
267
+ # "from a different upload") unless
268
+ # part.upload == self
269
+
270
+ # part.part_number
271
+ # else
272
+ # raise ArgumentError.new("expected number or UploadedPart")
273
+ # end
274
+ # end
275
+ # complete_opts = get_complete_opts(part_numbers)
276
+ #end
277
+
278
+ raise EmptyUploadError.new("Unable to complete an empty upload.") if complete_opts[:parts].empty?
279
+
280
+ resp = client.complete_multipart_upload(complete_opts)
281
+ if resp.data[:version_id]
282
+ ObjectVersion.new(object, resp.data[:version_id])
283
+ else
284
+ object
285
+ end
286
+ end
287
+
288
+ # Completes the upload or aborts it if no parts have been
289
+ # uploaded yet. Does nothing if the upload has already been
290
+ # aborted.
291
+ #
292
+ # @return [S3Object, ObjectVersion] If the bucket has versioning
293
+ # enabled, returns the {ObjectVersion} representing the
294
+ # version that was uploaded. If versioning is disabled,
295
+ # returns the object. If no upload was attempted (e.g. if it
296
+ # was aborted or if no parts were uploaded), returns `nil`.
297
+ def close
298
+ if aborted?
299
+ nil
300
+ elsif completed_parts.empty?
301
+ abort
302
+ else
303
+ complete
304
+ end
305
+ end
306
+
307
+ # @return [UploadedPartCollection] A collection representing
308
+ # the parts that have been uploaded to S3 for this upload.
309
+ #def parts
310
+ # UploadedPartCollection.new(self)
311
+ #end
312
+
313
+ # @api private
314
+ def completed_parts
315
+ @completed_parts.values.
316
+ sort { |a, b| a[:part_number] <=> b[:part_number] }
317
+ end
318
+
319
+ # @api private
320
+ def inspect
321
+ "<#{self.class}:#{object.bucket.name}/#{object.key}:#{id}>"
322
+ end
323
+
324
+ private
325
+
326
+ #def get_complete_opts(part_numbers = nil)
327
+ # parts = []
328
+ # self.parts.each do |part|
329
+ # parts << { :part_number => part.part_number, :etag => part.etag }
330
+ # end
331
+
332
+ # if part_numbers
333
+ # parts.reject! do |part|
334
+ # !part_numbers.include?(part[:part_number])
335
+ # end
336
+ # end
337
+
338
+ # base_opts.merge(:parts => parts)
339
+ #end
340
+
341
+ def base_opts
342
+ opts = {
343
+ :bucket_name => object.bucket.name,
344
+ :key => object.key
345
+ }
346
+ opts[:upload_id] = upload_id if upload_id
347
+ opts
348
+ end
349
+
350
+ end
351
+
352
+ end
353
+ end
@@ -0,0 +1,75 @@
1
+ # Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ #
8
+ # or in the "license" file accompanying this file. This file is
9
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
10
+ # ANY KIND, either express or implied. See the License for the specific
11
+ # language governing permissions and limitations under the License.
12
+
13
+ module MSS
14
+ class S3
15
+
16
+ # Represents the uploads in progress for a bucket.
17
+ #
18
+ # Note: After you initiate multipart upload and upload one or more
19
+ # parts, you must either complete or abort multipart upload in order
20
+ # to stop getting charged for storage of the uploaded parts. Only
21
+ # after you either complete or abort multipart upload, Amazon S3 frees
22
+ # up the parts storage and stops charging you for the parts storage.
23
+ #
24
+ # @example Finding uploads by prefix
25
+ #
26
+ # bucket.multipart_uploads.with_prefix("photos/").
27
+ # map { |upload| upload.object.key }
28
+ # # => ["photos/1.jpg", "photos/2.jpg", ...]
29
+ #
30
+ # @example Browsing with a tree interface
31
+ #
32
+ # bucket.multipart_uploads.with_prefix("photos").as_tree.
33
+ # children.select(&:branch?).map(&:prefix)
34
+ # # => ["photos/2010", "photos/2011", ...]
35
+ #
36
+ # @see Tree
37
+ class MultipartUploadCollection
38
+
39
+ include Enumerable
40
+ include Core::Model
41
+ include PrefixAndDelimiterCollection
42
+
43
+ # @return [Bucket] The bucket in which the uploads are taking
44
+ # place.
45
+ attr_reader :bucket
46
+
47
+ # @api private
48
+ def initialize(bucket, opts = {})
49
+ @bucket = bucket
50
+ super
51
+ end
52
+
53
+ protected
54
+
55
+ def each_member_in_page(page, &block)
56
+ super
57
+ page.uploads.each do |u|
58
+ object = S3Object.new(bucket, u.key)
59
+ upload = MultipartUpload.new(object, u.upload_id)
60
+ yield(upload)
61
+ end
62
+ end
63
+
64
+ def list_request(options)
65
+ client.list_multipart_uploads(options)
66
+ end
67
+
68
+ def limit_param; :max_uploads; end
69
+
70
+ def pagination_markers; super + [:upload_id_marker]; end
71
+
72
+ end
73
+
74
+ end
75
+ end