s3cp 1.1.21 → 1.1.22

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 (4) hide show
  1. data/History.txt +30 -0
  2. data/lib/s3cp/s3cp.rb +32 -10
  3. data/lib/s3cp/version.rb +1 -1
  4. metadata +4 -4
data/History.txt CHANGED
@@ -1,3 +1,33 @@
1
+ === 1.1.22 (2013-03-07)
2
+
3
+ * Changed: s3cp now adds a new "md5" custom metadata to any uploaded file
4
+ using multi-part protocol with --checksum option to allow for
5
+ proper content integrity checking and synchronization (--sync)
6
+ on (large / multi-part) files since the etag metadata is only a
7
+ valid MD5 value for files uploaded as a single part.
8
+
9
+ As a reminder, --checksum is on by default and multi-part upload
10
+ kicks in by default for files > 16MB. These defaults are
11
+ configurable through the command-line, environment variables or
12
+ $HOME/.s3cp.
13
+
14
+ On the command line,
15
+
16
+ # Turn things off
17
+ % export S3CP_CHECKSUM=false
18
+ % export S3CP_MULTIPART=false
19
+
20
+ # Configure multipart threshold for files > 64MB
21
+ % export S3CP_MULTIPART=67108864
22
+
23
+ In your in $HOME/.s3cp,
24
+
25
+ ENV["S3CP_MULTIPART"] = "false"
26
+
27
+ # Use multi-part upload only for files > 128MB
28
+ AWS.config.s3_multipart_threshold = (128 * 1024 * 1024)
29
+
30
+
1
31
  === 1.1.21 (2013-03-05)
2
32
 
3
33
  * Fixed: s3cp --sync would not correctly copy a file from S3 to local file
data/lib/s3cp/s3cp.rb CHANGED
@@ -27,7 +27,14 @@ options[:checksum] = ENV["S3CP_CHECKSUM"] ? (ENV["S3CP_CHECKSUM"] =~ /y|y
27
27
  options[:retries] = ENV["S3CP_RETRIES"] ? ENV["S3CP_RETRIES"].to_i : 18
28
28
  options[:retry_delay] = ENV["S3CP_RETRY_DELAY"] ? ENV["S3CP_RETRY_DELAY"].to_i : 1
29
29
  options[:retry_backoff] = ENV["S3CP_BACKOFF"] ? ENV["S3CP_BACKOFF"].to_f : 1.4142 # double every 2 tries
30
-
30
+ options[:multipart] = case ENV["S3CP_MULTIPART"]
31
+ when /n|no|false/i
32
+ false
33
+ when /\d+/
34
+ ENV["S3CP_MULTIPART"].to_i
35
+ else
36
+ true
37
+ end
31
38
  options[:include_regex] = []
32
39
  options[:exclude_regex] = []
33
40
  options[:sync] = false
@@ -275,7 +282,7 @@ def local_to_s3(bucket_to, key, file, options = {})
275
282
  when :not_found
276
283
  nil
277
284
  when :invalid
278
- STDERR.puts "Warning: invalid MD5 checksum in metadata; file will be force-copied."
285
+ STDERR.puts "Warning: No MD5 checksum available and ETag not suitable due to multi-part upload; file will be force-copied."
279
286
  nil
280
287
  else
281
288
  md5
@@ -295,17 +302,31 @@ def local_to_s3(bucket_to, key, file, options = {})
295
302
  end
296
303
 
297
304
  begin
305
+ obj = @s3.buckets[bucket_to].objects[key]
306
+
298
307
  s3_options = {}
299
308
  S3CP.set_header_options(s3_options, @headers)
300
309
  s3_options[:acl] = options[:acl]
301
310
  s3_options[:content_length] = File.size(file)
302
311
 
312
+ multipart_threshold = options[:multipart].is_a?(Fixnum) ? options[:multipart] : AWS.config.s3_multipart_threshold
313
+ if (expected_md5 != nil) && (File.size(file) >= multipart_threshold) && options[:multipart]
314
+ meta = s3_options[:metadata] || {}
315
+ meta[:md5] = expected_md5
316
+ s3_options[:metadata] = meta
317
+ end
318
+
319
+ if options[:multipart]
320
+ s3_options[:multipart_threshold] = multipart_threshold
321
+ else
322
+ s3_options[:single_request] = true
323
+ end
324
+
303
325
  progress_bar = ProgressBar.new(File.basename(file), File.size(file)).tap do |p|
304
326
  p.file_transfer_mode
305
327
  end
306
328
 
307
329
  File.open(file) do |io|
308
- obj = @s3.buckets[bucket_to].objects[key]
309
330
  obj.write(ProxyIO.new(io, progress_bar), s3_options)
310
331
  end
311
332
 
@@ -427,13 +448,14 @@ def s3_checksum(bucket, key)
427
448
  raise e
428
449
  end
429
450
 
430
- md5 = metadata[:etag] or fail "Unable to get etag/md5 for #{bucket_to}:#{key}"
431
- return :invalid unless md5
432
-
433
- md5 = md5.sub(/^"/, "").sub(/"$/, "") # strip beginning and trailing quotes
434
- return :invalid if md5 =~ /-/
435
-
436
- md5
451
+ case
452
+ when metadata[:meta] && metadata[:meta]["md5"]
453
+ metadata[:meta]["md5"]
454
+ when metadata[:etag] && metadata[:etag] !~ /-/
455
+ metadata[:etag].sub(/^"/, "").sub(/"$/, "") # strip beginning and trailing quotes
456
+ else
457
+ :invalid
458
+ end
437
459
  end
438
460
 
439
461
  def key_path(prefix, key)
data/lib/s3cp/version.rb CHANGED
@@ -16,5 +16,5 @@
16
16
  # the License.
17
17
 
18
18
  module S3CP
19
- VERSION = "1.1.21"
19
+ VERSION = "1.1.22"
20
20
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3cp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 57
4
+ hash: 63
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
- - 21
10
- version: 1.1.21
9
+ - 22
10
+ version: 1.1.22
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alex Boisvert
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2013-03-06 00:00:00 Z
18
+ date: 2013-03-08 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  version_requirements: &id001 !ruby/object:Gem::Requirement