altly-jammit-s3 0.6.0.2
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.
- data/LICENSE +22 -0
- data/bin/jammit-s3 +4 -0
- data/jammit-s3.gemspec +24 -0
- data/lib/jammit-s3.rb +44 -0
- data/lib/jammit/s3_command_line.rb +41 -0
- data/lib/jammit/s3_uploader.rb +167 -0
- metadata +104 -0
    
        data/LICENSE
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            Copyright (c) 2010 Jacques Crocker
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Permission is hereby granted, free of charge, to any person
         | 
| 4 | 
            +
            obtaining a copy of this software and associated documentation
         | 
| 5 | 
            +
            files (the "Software"), to deal in the Software without
         | 
| 6 | 
            +
            restriction, including without limitation the rights to use,
         | 
| 7 | 
            +
            copy, modify, merge, publish, distribute, sublicense, and/or sell
         | 
| 8 | 
            +
            copies of the Software, and to permit persons to whom the
         | 
| 9 | 
            +
            Software is furnished to do so, subject to the following
         | 
| 10 | 
            +
            conditions:
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            The above copyright notice and this permission notice shall be
         | 
| 13 | 
            +
            included in all copies or substantial portions of the Software.
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 16 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
         | 
| 17 | 
            +
            OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 18 | 
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
         | 
| 19 | 
            +
            HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
         | 
| 20 | 
            +
            WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
         | 
| 21 | 
            +
            FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
         | 
| 22 | 
            +
            OTHER DEALINGS IN THE SOFTWARE.
         | 
    
        data/bin/jammit-s3
    ADDED
    
    
    
        data/jammit-s3.gemspec
    ADDED
    
    | @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            Gem::Specification.new do |s|
         | 
| 2 | 
            +
              s.name      = 'altly-jammit-s3'
         | 
| 3 | 
            +
              s.version   = '0.6.0.2'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              s.homepage    = "http://documentcloud.github.com/jammit/"
         | 
| 6 | 
            +
              s.summary     = "Asset Packaging for Rails with Deployment to S3/Cloudfront"
         | 
| 7 | 
            +
              s.description = <<-EOS
         | 
| 8 | 
            +
                Jammit-S3 is an extension to the awesome Jammit library that handles deployment to s3 and cloudfront.
         | 
| 9 | 
            +
              EOS
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              s.authors           = ['Jacques Crocker']
         | 
| 12 | 
            +
              s.email             = 'railsjedi@gmail.com'
         | 
| 13 | 
            +
              s.rubyforge_project = 'jammit-s3'
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              s.require_paths     = ['lib']
         | 
| 16 | 
            +
              s.executables       = ['jammit-s3']
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              s.add_dependency 'altly-jammit',    '>= 0.5.4'
         | 
| 19 | 
            +
              s.add_dependency 'mimemagic',  '>= 0.1.7'
         | 
| 20 | 
            +
              s.add_dependency 's3', ">= 0.3.7"
         | 
| 21 | 
            +
              s.add_dependency 'ruby-hmac'
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              s.files = Dir['lib/**/*', 'bin/*', 'jammit-s3.gemspec', 'LICENSE', 'README']
         | 
| 24 | 
            +
            end
         | 
    
        data/lib/jammit-s3.rb
    ADDED
    
    | @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            require 'jammit/command_line'
         | 
| 2 | 
            +
            require 'jammit/s3_command_line'
         | 
| 3 | 
            +
            require 'jammit/s3_uploader'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Jammit
         | 
| 6 | 
            +
              def self.upload_to_s3!(options = {})
         | 
| 7 | 
            +
                S3Uploader.new(options).upload
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            if defined?(Rails)
         | 
| 12 | 
            +
              module Jammit
         | 
| 13 | 
            +
                class JammitRailtie < Rails::Railtie
         | 
| 14 | 
            +
                  initializer "set asset host and asset id" do
         | 
| 15 | 
            +
                    config.before_initialize do
         | 
| 16 | 
            +
                      if Jammit.configuration[:use_cloudfront] && Jammit.configuration[:cloudfront_cname].present? && Jammit.configuration[:cloudfront_domain].present?
         | 
| 17 | 
            +
                        asset_hostname = Jammit.configuration[:cloudfront_cname]
         | 
| 18 | 
            +
                        asset_hostname_ssl = Jammit.configuration[:cloudfront_domain]
         | 
| 19 | 
            +
                      elsif Jammit.configuration[:use_cloudfront] && Jammit.configuration[:cloudfront_domain].present?
         | 
| 20 | 
            +
                        asset_hostname = asset_hostname_ssl = Jammit.configuration[:cloudfront_domain]            
         | 
| 21 | 
            +
                      else
         | 
| 22 | 
            +
                        asset_hostname = asset_hostname_ssl = "#{Jammit.configuration[:s3_bucket]}.s3.amazonaws.com"
         | 
| 23 | 
            +
                      end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                      if Jammit.package_assets and asset_hostname.present?
         | 
| 26 | 
            +
                        puts "Initializing Cloudfront"                      
         | 
| 27 | 
            +
                        ActionController::Base.asset_host = Proc.new do |source, request|
         | 
| 28 | 
            +
                          if Jammit.configuration.has_key?(:ssl)
         | 
| 29 | 
            +
                            protocol = Jammit.configuration[:ssl] ? "https://" : "http://"
         | 
| 30 | 
            +
                          else
         | 
| 31 | 
            +
                            protocol = request.protocol
         | 
| 32 | 
            +
                          end
         | 
| 33 | 
            +
                          if request.protocol == "https://"
         | 
| 34 | 
            +
                            "#{protocol}#{asset_hostname_ssl}"
         | 
| 35 | 
            +
                          else 
         | 
| 36 | 
            +
                            "#{protocol}#{asset_hostname}"  
         | 
| 37 | 
            +
                          end              
         | 
| 38 | 
            +
                        end
         | 
| 39 | 
            +
                      end
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
            end
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            require 's3'
         | 
| 2 | 
            +
            module Jammit
         | 
| 3 | 
            +
              class S3CommandLine < CommandLine
         | 
| 4 | 
            +
                def initialize
         | 
| 5 | 
            +
                  super
         | 
| 6 | 
            +
                  ensure_s3_configuration
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  begin
         | 
| 9 | 
            +
                    Jammit.upload_to_s3!
         | 
| 10 | 
            +
                  rescue S3::Error::BucketAlreadyExists => e
         | 
| 11 | 
            +
                    # tell them to pick another name
         | 
| 12 | 
            +
                    puts e.message
         | 
| 13 | 
            +
                    exit(1)
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                protected
         | 
| 18 | 
            +
                  def ensure_s3_configuration
         | 
| 19 | 
            +
                    bucket_name = Jammit.configuration[:s3_bucket]
         | 
| 20 | 
            +
                    unless bucket_name.is_a?(String) && bucket_name.length > 0
         | 
| 21 | 
            +
                      puts "\nA valid s3_bucket name is required."
         | 
| 22 | 
            +
                      puts "Please add one to your Jammit config (config/assets.yml):\n\n"
         | 
| 23 | 
            +
                      puts "s3_bucket: my-bucket-name\n\n"
         | 
| 24 | 
            +
                      exit(1)
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    access_key_id = Jammit.configuration[:s3_access_key_id]
         | 
| 28 | 
            +
                    unless access_key_id.is_a?(String) && access_key_id.length > 0
         | 
| 29 | 
            +
                      puts "access_key_id: '#{access_key_id}' is not valid"
         | 
| 30 | 
            +
                      exit(1)
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    secret_access_key = Jammit.configuration[:s3_secret_access_key]
         | 
| 34 | 
            +
                    unless secret_access_key.is_a?(String) && secret_access_key.length > 0
         | 
| 35 | 
            +
                      puts "secret_access_key: '#{secret_access_key}' is not valid"
         | 
| 36 | 
            +
                      exit(1)
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| @@ -0,0 +1,167 @@ | |
| 1 | 
            +
            require 'rubygems'
         | 
| 2 | 
            +
            require 'hmac'
         | 
| 3 | 
            +
            require 'hmac-sha1'
         | 
| 4 | 
            +
            require 'net/https'
         | 
| 5 | 
            +
            require 'base64'
         | 
| 6 | 
            +
            require 'mimemagic'
         | 
| 7 | 
            +
            require 'digest/md5'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            module Jammit
         | 
| 10 | 
            +
              class S3Uploader
         | 
| 11 | 
            +
                def initialize(options = {})
         | 
| 12 | 
            +
                  @bucket = options[:bucket]
         | 
| 13 | 
            +
                  unless @bucket
         | 
| 14 | 
            +
                    @bucket_name = options[:bucket_name] || Jammit.configuration[:s3_bucket]
         | 
| 15 | 
            +
                    @access_key_id = options[:access_key_id] || Jammit.configuration[:s3_access_key_id]
         | 
| 16 | 
            +
                    @secret_access_key = options[:secret_access_key] || Jammit.configuration[:s3_secret_access_key]
         | 
| 17 | 
            +
                    @bucket_location = options[:bucket_location] || Jammit.configuration[:s3_bucket_location]
         | 
| 18 | 
            +
                    @cache_control = options[:cache_control] || Jammit.configuration[:s3_cache_control]
         | 
| 19 | 
            +
                    @acl = options[:acl] || Jammit.configuration[:s3_permission]
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    @bucket = find_or_create_bucket
         | 
| 22 | 
            +
                    if Jammit.configuration[:use_cloudfront]
         | 
| 23 | 
            +
                      @changed_files = []
         | 
| 24 | 
            +
                      @cloudfront_dist_id = options[:cloudfront_dist_id] || Jammit.configuration[:cloudfront_dist_id]
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def upload
         | 
| 30 | 
            +
                  log "Pushing assets to S3 bucket: #{@bucket.name}"
         | 
| 31 | 
            +
                  globs = []
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  # add default package path
         | 
| 34 | 
            +
                  if Jammit.gzip_assets
         | 
| 35 | 
            +
                    globs << "public/#{Jammit.package_path}/**/*.gz"
         | 
| 36 | 
            +
                  else
         | 
| 37 | 
            +
                    globs << "public/#{Jammit.package_path}/**/*.css"
         | 
| 38 | 
            +
                    globs << "public/#{Jammit.package_path}/**/*.js"
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  # add images
         | 
| 42 | 
            +
                  globs << "public/images/**/*" unless Jammit.configuration[:s3_upload_images] == false
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  # add custom configuration if defined
         | 
| 45 | 
            +
                  s3_upload_files = Jammit.configuration[:s3_upload_files]
         | 
| 46 | 
            +
                  globs << s3_upload_files if s3_upload_files.is_a?(String)
         | 
| 47 | 
            +
                  globs += s3_upload_files if s3_upload_files.is_a?(Array)
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  # upload all the globs
         | 
| 50 | 
            +
                  globs.each do |glob|
         | 
| 51 | 
            +
                    upload_from_glob(glob)
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  if Jammit.configuration[:use_cloudfront] && !@changed_files.empty?
         | 
| 55 | 
            +
                    log "invalidating cloudfront cache for changed files"
         | 
| 56 | 
            +
                    invalidate_cache(@changed_files)
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def upload_from_glob(glob)
         | 
| 61 | 
            +
                  log "Pushing files from #{glob}"
         | 
| 62 | 
            +
                  log "#{ASSET_ROOT}/#{glob}"
         | 
| 63 | 
            +
                  Dir["#{ASSET_ROOT}/#{glob}"].each do |local_path|
         | 
| 64 | 
            +
                    next if File.directory?(local_path)
         | 
| 65 | 
            +
                    remote_path = local_path.gsub(/^#{ASSET_ROOT}\/public\//, "")
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    use_gzip = false
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    # handle gzipped files
         | 
| 70 | 
            +
                    if File.extname(remote_path) == ".gz"
         | 
| 71 | 
            +
                      use_gzip = true
         | 
| 72 | 
            +
                      remote_path = remote_path.gsub(/\.gz$/, "")
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                    
         | 
| 75 | 
            +
                    # check if the file already exists on s3
         | 
| 76 | 
            +
                    begin
         | 
| 77 | 
            +
                      obj = @bucket.objects.find_first(remote_path)
         | 
| 78 | 
            +
                    rescue
         | 
| 79 | 
            +
                      obj = nil
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                    # if the object does not exist, or if the MD5 Hash / etag of the 
         | 
| 83 | 
            +
                    # file has changed, upload it
         | 
| 84 | 
            +
                    if !obj || (obj.etag != Digest::MD5.hexdigest(File.read(local_path)))
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                      # save to s3
         | 
| 87 | 
            +
                      new_object = @bucket.objects.build(remote_path)
         | 
| 88 | 
            +
                      new_object.cache_control = @cache_control if @cache_control
         | 
| 89 | 
            +
                      new_object.content_type = MimeMagic.by_path(remote_path)
         | 
| 90 | 
            +
                      new_object.content = open(local_path)
         | 
| 91 | 
            +
                      new_object.content_encoding = "gzip" if use_gzip
         | 
| 92 | 
            +
                      new_object.acl = @acl if @acl
         | 
| 93 | 
            +
                      log "pushing file to s3: #{remote_path}"
         | 
| 94 | 
            +
                      new_object.save
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                      if Jammit.configuration[:use_cloudfront] && obj
         | 
| 97 | 
            +
                        log "File changed and will be invalidated in cloudfront: #{remote_path}"
         | 
| 98 | 
            +
                        @changed_files << remote_path
         | 
| 99 | 
            +
                      end
         | 
| 100 | 
            +
                    else
         | 
| 101 | 
            +
                      log "file has not changed: #{remote_path}"
         | 
| 102 | 
            +
                    end
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                def find_or_create_bucket
         | 
| 107 | 
            +
                  s3_service = S3::Service.new(:access_key_id => @access_key_id, :secret_access_key => @secret_access_key)
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  # find or create the bucket
         | 
| 110 | 
            +
                  begin
         | 
| 111 | 
            +
                    s3_service.buckets.find(@bucket_name)
         | 
| 112 | 
            +
                  rescue S3::Error::NoSuchBucket
         | 
| 113 | 
            +
                    log "Bucket not found. Creating '#{@bucket_name}'..."
         | 
| 114 | 
            +
                    bucket = s3_service.buckets.build(@bucket_name)
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    location = (@bucket_location.to_s.strip.downcase == "eu") ? :eu : :us
         | 
| 117 | 
            +
                    bucket.save(location)
         | 
| 118 | 
            +
                    bucket
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
                
         | 
| 122 | 
            +
                def invalidate_cache(files)
         | 
| 123 | 
            +
                  paths = ""
         | 
| 124 | 
            +
                  files.each do |key|
         | 
| 125 | 
            +
                    log "adding /#{key} to list of invalidation requests"
         | 
| 126 | 
            +
                    paths += "<Path>/#{key}</Path>"
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
                  digest = HMAC::SHA1.new(@secret_access_key)
         | 
| 129 | 
            +
                  digest << date = Time.now.utc.strftime("%a, %d %b %Y %H:%M:%S %Z")
         | 
| 130 | 
            +
                  uri = URI.parse("https://cloudfront.amazonaws.com/2010-11-01/distribution/#{@cloudfront_dist_id}/invalidation")
         | 
| 131 | 
            +
                  req = Net::HTTP::Post.new(uri.path)
         | 
| 132 | 
            +
                  req.initialize_http_header({
         | 
| 133 | 
            +
                    'x-amz-date' => date,
         | 
| 134 | 
            +
                    'Content-Type' => 'text/xml',
         | 
| 135 | 
            +
                    'Authorization' => "AWS %s:%s" % [@access_key_id, Base64.encode64(digest.digest).gsub("\n", '')]
         | 
| 136 | 
            +
                  })
         | 
| 137 | 
            +
                  req.body = "<InvalidationBatch>#{paths}<CallerReference>#{@cloudfront_dist_id}_#{Time.now.utc.to_i}</CallerReference></InvalidationBatch>"
         | 
| 138 | 
            +
                  http = Net::HTTP.new(uri.host, uri.port)
         | 
| 139 | 
            +
                  http.use_ssl = true
         | 
| 140 | 
            +
                  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
         | 
| 141 | 
            +
                  res = http.request(req)
         | 
| 142 | 
            +
                  log result_message(req, res)
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                def result_message req, res
         | 
| 146 | 
            +
                  if res.code == "201"
         | 
| 147 | 
            +
                    'Invalidation request succeeded'
         | 
| 148 | 
            +
                  else
         | 
| 149 | 
            +
                    <<-EOM.gsub(/^\s*/, '')
         | 
| 150 | 
            +
                    =============================
         | 
| 151 | 
            +
                    Failed with #{res.code} error!
         | 
| 152 | 
            +
                    Request path:#{req.path}
         | 
| 153 | 
            +
                    Request header: #{req.to_hash}
         | 
| 154 | 
            +
                    Request body:#{req.body}
         | 
| 155 | 
            +
                    Response body: #{res.body}
         | 
| 156 | 
            +
                    =============================
         | 
| 157 | 
            +
                    EOM
         | 
| 158 | 
            +
                  end
         | 
| 159 | 
            +
                end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                def log(msg)
         | 
| 162 | 
            +
                  puts msg
         | 
| 163 | 
            +
                end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
              end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,104 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification 
         | 
| 2 | 
            +
            name: altly-jammit-s3
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            +
              prerelease: 
         | 
| 5 | 
            +
              version: 0.6.0.2
         | 
| 6 | 
            +
            platform: ruby
         | 
| 7 | 
            +
            authors: 
         | 
| 8 | 
            +
            - Jacques Crocker
         | 
| 9 | 
            +
            autorequire: 
         | 
| 10 | 
            +
            bindir: bin
         | 
| 11 | 
            +
            cert_chain: []
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            date: 2011-05-13 00:00:00 -07:00
         | 
| 14 | 
            +
            default_executable: 
         | 
| 15 | 
            +
            dependencies: 
         | 
| 16 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 17 | 
            +
              name: altly-jammit
         | 
| 18 | 
            +
              prerelease: false
         | 
| 19 | 
            +
              requirement: &id001 !ruby/object:Gem::Requirement 
         | 
| 20 | 
            +
                none: false
         | 
| 21 | 
            +
                requirements: 
         | 
| 22 | 
            +
                - - ">="
         | 
| 23 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 24 | 
            +
                    version: 0.5.4
         | 
| 25 | 
            +
              type: :runtime
         | 
| 26 | 
            +
              version_requirements: *id001
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 28 | 
            +
              name: mimemagic
         | 
| 29 | 
            +
              prerelease: false
         | 
| 30 | 
            +
              requirement: &id002 !ruby/object:Gem::Requirement 
         | 
| 31 | 
            +
                none: false
         | 
| 32 | 
            +
                requirements: 
         | 
| 33 | 
            +
                - - ">="
         | 
| 34 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 35 | 
            +
                    version: 0.1.7
         | 
| 36 | 
            +
              type: :runtime
         | 
| 37 | 
            +
              version_requirements: *id002
         | 
| 38 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 39 | 
            +
              name: s3
         | 
| 40 | 
            +
              prerelease: false
         | 
| 41 | 
            +
              requirement: &id003 !ruby/object:Gem::Requirement 
         | 
| 42 | 
            +
                none: false
         | 
| 43 | 
            +
                requirements: 
         | 
| 44 | 
            +
                - - ">="
         | 
| 45 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 46 | 
            +
                    version: 0.3.7
         | 
| 47 | 
            +
              type: :runtime
         | 
| 48 | 
            +
              version_requirements: *id003
         | 
| 49 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 50 | 
            +
              name: ruby-hmac
         | 
| 51 | 
            +
              prerelease: false
         | 
| 52 | 
            +
              requirement: &id004 !ruby/object:Gem::Requirement 
         | 
| 53 | 
            +
                none: false
         | 
| 54 | 
            +
                requirements: 
         | 
| 55 | 
            +
                - - ">="
         | 
| 56 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 57 | 
            +
                    version: "0"
         | 
| 58 | 
            +
              type: :runtime
         | 
| 59 | 
            +
              version_requirements: *id004
         | 
| 60 | 
            +
            description: "    Jammit-S3 is an extension to the awesome Jammit library that handles deployment to s3 and cloudfront.\n"
         | 
| 61 | 
            +
            email: railsjedi@gmail.com
         | 
| 62 | 
            +
            executables: 
         | 
| 63 | 
            +
            - jammit-s3
         | 
| 64 | 
            +
            extensions: []
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            extra_rdoc_files: []
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            files: 
         | 
| 69 | 
            +
            - lib/jammit/s3_command_line.rb
         | 
| 70 | 
            +
            - lib/jammit/s3_uploader.rb
         | 
| 71 | 
            +
            - lib/jammit-s3.rb
         | 
| 72 | 
            +
            - bin/jammit-s3
         | 
| 73 | 
            +
            - jammit-s3.gemspec
         | 
| 74 | 
            +
            - LICENSE
         | 
| 75 | 
            +
            has_rdoc: true
         | 
| 76 | 
            +
            homepage: http://documentcloud.github.com/jammit/
         | 
| 77 | 
            +
            licenses: []
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            post_install_message: 
         | 
| 80 | 
            +
            rdoc_options: []
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            require_paths: 
         | 
| 83 | 
            +
            - lib
         | 
| 84 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         | 
| 85 | 
            +
              none: false
         | 
| 86 | 
            +
              requirements: 
         | 
| 87 | 
            +
              - - ">="
         | 
| 88 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 89 | 
            +
                  version: "0"
         | 
| 90 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 91 | 
            +
              none: false
         | 
| 92 | 
            +
              requirements: 
         | 
| 93 | 
            +
              - - ">="
         | 
| 94 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 95 | 
            +
                  version: "0"
         | 
| 96 | 
            +
            requirements: []
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            rubyforge_project: jammit-s3
         | 
| 99 | 
            +
            rubygems_version: 1.6.2
         | 
| 100 | 
            +
            signing_key: 
         | 
| 101 | 
            +
            specification_version: 3
         | 
| 102 | 
            +
            summary: Asset Packaging for Rails with Deployment to S3/Cloudfront
         | 
| 103 | 
            +
            test_files: []
         | 
| 104 | 
            +
             |