Module: RightPublish::Storage

Defined in:
lib/right_publish/storage.rb

Class Method Summary collapse

Class Method Details

.get_etag_map(dir, options = {}) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# 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) ⇒ String

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.

Parameters:

  • filename (String)

    relative or absolute filename

Returns:

  • (String)

    the inferred MIME type for filename, based on its extension



94
95
96
97
98
99
100
101
102
103
104
105
106
107
# 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 = {}) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
# 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 = {}) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 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