s3cp 1.1.21 → 1.1.22

Sign up to get free protection for your applications and to get access to all the features.
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