Skip to content

Instantly share code, notes, and snippets.

@swdyh
Created June 25, 2012 07:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save swdyh/2987222 to your computer and use it in GitHub Desktop.
Save swdyh/2987222 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'digest/md5'
require 'optparse'
require 'stringio'
module S3Etag
def calc opt = {}
threshold = opt[:threshold] || 16 * 1024 * 1024
max_parts = opt[:max_parts] || 10000
min_part_size = opt[:min_part_size] || 5 * 1024 * 1024
if opt[:file]
total_size = File.stat(opt[:file]).size
io = open(opt[:file])
elsif opt[:data]
total_size = opt[:data].size
io = StringIO.new opt[:data]
else
raise ':file or :data is required'
end
r = nil
begin
if total_size <= threshold
r = Digest::MD5.hexdigest(io.read)
else
part_size = [(total_size.to_f / max_parts).ceil, min_part_size].max.to_i
md5s = []
while !io.eof?
md5s << Digest::MD5.digest(io.read(part_size))
end
r = Digest::MD5.hexdigest(md5s.join('')) + '-' + md5s.size.to_s
end
rescue Exception => e
raise e
ensure
io.close
end
end
module_function :calc
end
if __FILE__ == $0
opt = {}
op = OptionParser.new
op.on('-t', '--threshold threshold'){ |v| opt[:threshold] = v.to_i }
op.on('-p', '--max-parts max-parts'){ |v| opt[:max_parts] = v.to_i }
op.on('-s', '--min_part_size min_part_size'){ |v| opt[:min_part_size] = v.to_i }
path = ARGV.last
if path && File.file?(path)
begin
op.parse ARGV
rescue OptionParser::InvalidOption => e
puts op.summarize(['invalid option.', 's3etag file'], 100)
else
puts S3Etag.calc(opt.merge(:file => path))
end
else
puts op.summarize(['s3etag file'], 100)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment