module RightPublish::Storage

Public Class Methods

get_etag_map(dir, options={}) click to toggle source
# File lib/right_publish/storage.rb, line 109
def self.get_etag_map(dir, options={})
  hash_map = {}
  dir.files.each do |file|
    # skip directories
    next if file.key[-1,1] == '/'
    # skip files not located in specified subdir
    next if file.key[0,options[:subdir].size] != options[:subdir] if options.has_key? :subdir

    md5 = dir.compute_md5(file)

    if hash_map.has_key? md5
      hash_map[md5][file.key] = file
    else
      hash_map[md5] = {file.key=>file}
    end
  end
  hash_map
end
guess_mime_type(filename) click to toggle source

Given a filename, make an educated guess as to its MIME type. We rely on the mime-types gem and its built-in database of extensions and types, but many extensions are in use by multiple MIME types.

If the extension maps to more than one MIME type, we will pick the first type that is a member of RightPublish::MIME_TYPES. This gives us 100% reliable behavior for MIME types that RightPublish “knows,” and passable behavior for other types.

@param [String] filename relative or absolute filename @return [String] the inferred MIME type for filename, based on its extension

# File lib/right_publish/storage.rb, line 94
def self.guess_mime_type(filename)
  filename = File.basename(filename)
  candidates = MIME::Types.type_for(filename)

  if candidates.size == 1
    winner = candidates.first
  elsif preferred = candidates.detect { |c| RightPublish::MIME_TYPES.keys.include? c.to_s }
    winner = preferred
  else
    winner = 'application/octet-stream'
  end

  winner.to_s
end
ls(bucket, options={}) { |file| ... } click to toggle source
# File lib/right_publish/storage.rb, line 33
def self.ls(bucket, options={})
  storage = bucket.get_directories()
  storage.files.each do |file|
    # skip directories
    next if file.key[-1,1] == '/'
    # skip files not located in specified subdir
    next if file.key[0,options[:subdir].size] != options[:subdir] if options.has_key? :subdir

    yield(file)
  end
end
sync_dirs(src, dest, options={}) click to toggle source
# File lib/right_publish/storage.rb, line 45
def self.sync_dirs(src, dest, options={})
  src_dir = src.get_directories()
  dest_dir = dest.get_directories()

  src_map = get_etag_map(src_dir, options)
  dest_map = get_etag_map(dest_dir, options)

  dest_map.each_pair do |hash, files|
    files.each do |path, file|
      unless src_map.include? hash and src_map[hash].include? path
        Profile.log("Removing: #{path}", :debug)
        file.destroy
      end
    end
  end if options[:sweep]

  src_map.each_pair do |hash, files|
    # If we already have this data, just copy it, otherwise
    # sync down a copy and make copies of that.
    if dest_map.include? hash
      local_copy = dest_map[hash].first.last
    else
      remote_file = files.shift
      Profile.log("Synchronizing: #{remote_file.first}", :debug)
      # Need to wrap the raw data in a stringio object or the call will fail on windows
      local_copy = dest_dir.files.create(:key=>remote_file.first, :body=>StringIO.new(remote_file.last.body),
                                         :acl=>'public-read',
                                         :content_type => guess_mime_type(remote_file.first))
    end

    files.each_key do |file|
      unless dest_map.include? hash and dest_map[hash].include? file
        Profile.log("Duplicating: #{file}", :debug)
        local_copy.copy(dest_dir.key, file, 'x-amz-acl'=>'public-read')
      end
    end
  end
end