sprockets 3.0.0.beta.1 → 3.0.0.beta.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.
Potentially problematic release.
This version of sprockets might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/README.md +4 -0
 - data/lib/sprockets.rb +3 -2
 - data/lib/sprockets/asset.rb +20 -4
 - data/lib/sprockets/base.rb +16 -16
 - data/lib/sprockets/cache.rb +3 -3
 - data/lib/sprockets/cached_environment.rb +14 -14
 - data/lib/sprockets/configuration.rb +4 -4
 - data/lib/sprockets/digest_utils.rb +144 -0
 - data/lib/sprockets/manifest.rb +2 -1
 - data/lib/sprockets/path_utils.rb +35 -0
 - data/lib/sprockets/processing.rb +2 -2
 - data/lib/sprockets/server.rb +10 -10
 - data/lib/sprockets/utils.rb +0 -49
 - data/lib/sprockets/version.rb +1 -1
 - metadata +3 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 2dcb1bab6dcd806bd08e5f467aa057cd75004be8
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 86037ea057923f8b2afd7dbffdea6d72f3596d02
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: ce12f8ec442a3d4a3cef5352f12a6c83151ff4dd717ce0fb94d31811ca9f3c80953a3f52e3f582eb5ecb42d0af05d2e5320fe925c3c55e4b8b61fd6280ff4ef8
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: fbe0b9468d6e81a596517d4b4ecda0faf34ef84027ac7340ea2b603bc7635585ed2f93fa7e215e9c1062df1990c46222aefefd97caa4ba54a2dfcafa68c21811
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -394,6 +394,10 @@ submit a pull request. 
     | 
|
| 
       394 
394 
     | 
    
         
             
              idea](https://issues.apache.org/bugzilla/show_bug.cgi?id=39727)
         
     | 
| 
       395 
395 
     | 
    
         
             
            * Added linked or referenced assets. When an asset is compiled, any of its links
         
     | 
| 
       396 
396 
     | 
    
         
             
              will be compiled as well.
         
     | 
| 
      
 397 
     | 
    
         
            +
            * Add Asset integrity attribute for Subresource Integrity
         
     | 
| 
      
 398 
     | 
    
         
            +
            * Default digest changed to SHA256. Configuring digest_class is deprecated.
         
     | 
| 
      
 399 
     | 
    
         
            +
            * Rename Asset#digest to Asset#hexdigest. Asset#digest is deprecated and will
         
     | 
| 
      
 400 
     | 
    
         
            +
              return a raw byte String in 4.x.
         
     | 
| 
       397 
401 
     | 
    
         | 
| 
       398 
402 
     | 
    
         
             
            **2.12.2** (September 5, 2014)
         
     | 
| 
       399 
403 
     | 
    
         | 
    
        data/lib/sprockets.rb
    CHANGED
    
    | 
         @@ -29,6 +29,7 @@ module Sprockets 
     | 
|
| 
       29 
29 
     | 
    
         
             
              autoload :AssetURI,                'sprockets/asset_uri'
         
     | 
| 
       30 
30 
     | 
    
         
             
              autoload :Cache,                   'sprockets/cache'
         
     | 
| 
       31 
31 
     | 
    
         
             
              autoload :ContentTypeMismatch,     'sprockets/errors'
         
     | 
| 
      
 32 
     | 
    
         
            +
              autoload :DigestUtils,             'sprockets/digest_utils'
         
     | 
| 
       32 
33 
     | 
    
         
             
              autoload :EncodingUtils,           'sprockets/encoding_utils'
         
     | 
| 
       33 
34 
     | 
    
         
             
              autoload :Error,                   'sprockets/errors'
         
     | 
| 
       34 
35 
     | 
    
         
             
              autoload :FileNotFound,            'sprockets/errors'
         
     | 
| 
         @@ -58,8 +59,8 @@ module Sprockets 
     | 
|
| 
       58 
59 
     | 
    
         
             
              @version           = ''
         
     | 
| 
       59 
60 
     | 
    
         | 
| 
       60 
61 
     | 
    
         
             
              # Set the default digest
         
     | 
| 
       61 
     | 
    
         
            -
              require 'digest/ 
     | 
| 
       62 
     | 
    
         
            -
              @digest_class = Digest:: 
     | 
| 
      
 62 
     | 
    
         
            +
              require 'digest/sha2'
         
     | 
| 
      
 63 
     | 
    
         
            +
              @digest_class = Digest::SHA256
         
     | 
| 
       63 
64 
     | 
    
         | 
| 
       64 
65 
     | 
    
         
             
              require 'logger'
         
     | 
| 
       65 
66 
     | 
    
         
             
              @logger = Logger.new($stderr)
         
     | 
    
        data/lib/sprockets/asset.rb
    CHANGED
    
    | 
         @@ -1,3 +1,4 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'base64'
         
     | 
| 
       1 
2 
     | 
    
         
             
            require 'fileutils'
         
     | 
| 
       2 
3 
     | 
    
         
             
            require 'pathname'
         
     | 
| 
       3 
4 
     | 
    
         | 
| 
         @@ -49,7 +50,7 @@ module Sprockets 
     | 
|
| 
       49 
50 
     | 
    
         | 
| 
       50 
51 
     | 
    
         
             
                # Internal: Unique asset object ID.
         
     | 
| 
       51 
52 
     | 
    
         
             
                #
         
     | 
| 
       52 
     | 
    
         
            -
                # Returns  
     | 
| 
      
 53 
     | 
    
         
            +
                # Returns a String.
         
     | 
| 
       53 
54 
     | 
    
         
             
                attr_reader :id
         
     | 
| 
       54 
55 
     | 
    
         | 
| 
       55 
56 
     | 
    
         
             
                # Public: Internal URI to lookup asset by.
         
     | 
| 
         @@ -65,7 +66,7 @@ module Sprockets 
     | 
|
| 
       65 
66 
     | 
    
         
             
                #
         
     | 
| 
       66 
67 
     | 
    
         
             
                # Returns String.
         
     | 
| 
       67 
68 
     | 
    
         
             
                def digest_path
         
     | 
| 
       68 
     | 
    
         
            -
                  logical_path.sub(/\.(\w+)$/) { |ext| "-#{ 
     | 
| 
      
 69 
     | 
    
         
            +
                  logical_path.sub(/\.(\w+)$/) { |ext| "-#{etag}#{ext}" }
         
     | 
| 
       69 
70 
     | 
    
         
             
                end
         
     | 
| 
       70 
71 
     | 
    
         | 
| 
       71 
72 
     | 
    
         
             
                # Public: Returns String MIME type of asset. Returns nil if type is unknown.
         
     | 
| 
         @@ -165,10 +166,25 @@ module Sprockets 
     | 
|
| 
       165 
166 
     | 
    
         
             
                end
         
     | 
| 
       166 
167 
     | 
    
         | 
| 
       167 
168 
     | 
    
         
             
                # Public: Returns String hexdigest of source.
         
     | 
| 
       168 
     | 
    
         
            -
                 
     | 
| 
      
 169 
     | 
    
         
            +
                def hexdigest
         
     | 
| 
      
 170 
     | 
    
         
            +
                  DigestUtils.pack_hexdigest(@digest)
         
     | 
| 
      
 171 
     | 
    
         
            +
                end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                # Deprecated: Returns String hexdigest of source.
         
     | 
| 
      
 174 
     | 
    
         
            +
                #
         
     | 
| 
      
 175 
     | 
    
         
            +
                # In 4.x this will be changed to return a raw Digest byte String.
         
     | 
| 
      
 176 
     | 
    
         
            +
                alias_method :digest, :hexdigest
         
     | 
| 
       169 
177 
     | 
    
         | 
| 
       170 
178 
     | 
    
         
             
                # Pubic: ETag String of Asset.
         
     | 
| 
       171 
     | 
    
         
            -
                alias_method :etag, : 
     | 
| 
      
 179 
     | 
    
         
            +
                alias_method :etag, :hexdigest
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                # Public: Returns String base64 digest of source.
         
     | 
| 
      
 182 
     | 
    
         
            +
                def base64digest
         
     | 
| 
      
 183 
     | 
    
         
            +
                  DigestUtils.pack_base64digest(@digest)
         
     | 
| 
      
 184 
     | 
    
         
            +
                end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                # Public: A "named information" URL for subresource integrity.
         
     | 
| 
      
 187 
     | 
    
         
            +
                attr_reader :integrity
         
     | 
| 
       172 
188 
     | 
    
         | 
| 
       173 
189 
     | 
    
         
             
                # Public: Add enumerator to allow `Asset` instances to be used as Rack
         
     | 
| 
       174 
190 
     | 
    
         
             
                # compatible body objects.
         
     | 
    
        data/lib/sprockets/base.rb
    CHANGED
    
    | 
         @@ -8,7 +8,7 @@ require 'sprockets/server' 
     | 
|
| 
       8 
8 
     | 
    
         
             
            module Sprockets
         
     | 
| 
       9 
9 
     | 
    
         
             
              # `Base` class for `Environment` and `Cached`.
         
     | 
| 
       10 
10 
     | 
    
         
             
              class Base
         
     | 
| 
       11 
     | 
    
         
            -
                include PathUtils, HTTPUtils
         
     | 
| 
      
 11 
     | 
    
         
            +
                include PathUtils, HTTPUtils, DigestUtils
         
     | 
| 
       12 
12 
     | 
    
         
             
                include Configuration
         
     | 
| 
       13 
13 
     | 
    
         
             
                include Server
         
     | 
| 
       14 
14 
     | 
    
         
             
                include Resolve
         
     | 
| 
         @@ -33,39 +33,37 @@ module Sprockets 
     | 
|
| 
       33 
33 
     | 
    
         
             
                end
         
     | 
| 
       34 
34 
     | 
    
         
             
                alias_method :index, :cached
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                # Internal: Compute  
     | 
| 
      
 36 
     | 
    
         
            +
                # Internal: Compute digest for path.
         
     | 
| 
       37 
37 
     | 
    
         
             
                #
         
     | 
| 
       38 
38 
     | 
    
         
             
                # path - String filename or directory path.
         
     | 
| 
       39 
39 
     | 
    
         
             
                #
         
     | 
| 
       40 
     | 
    
         
            -
                # Returns a String  
     | 
| 
       41 
     | 
    
         
            -
                def  
     | 
| 
      
 40 
     | 
    
         
            +
                # Returns a String digest or nil.
         
     | 
| 
      
 41 
     | 
    
         
            +
                def file_digest(path)
         
     | 
| 
       42 
42 
     | 
    
         
             
                  if stat = self.stat(path)
         
     | 
| 
       43 
43 
     | 
    
         
             
                    # Caveat: Digests are cached by the path's current mtime. Its possible
         
     | 
| 
       44 
44 
     | 
    
         
             
                    # for a files contents to have changed and its mtime to have been
         
     | 
| 
       45 
45 
     | 
    
         
             
                    # negligently reset thus appearing as if the file hasn't changed on
         
     | 
| 
       46 
46 
     | 
    
         
             
                    # disk. Also, the mtime is only read to the nearest second. Its
         
     | 
| 
       47 
47 
     | 
    
         
             
                    # also possible the file was updated more than once in a given second.
         
     | 
| 
       48 
     | 
    
         
            -
                    cache.fetch([' 
     | 
| 
      
 48 
     | 
    
         
            +
                    cache.fetch(['file_digest', path, stat.mtime.to_i]) do
         
     | 
| 
       49 
49 
     | 
    
         
             
                      if stat.directory?
         
     | 
| 
       50 
50 
     | 
    
         
             
                        # If its a directive, digest the list of filenames
         
     | 
| 
       51 
     | 
    
         
            -
                         
     | 
| 
      
 51 
     | 
    
         
            +
                        digest_class.digest(self.entries(path).join(','))
         
     | 
| 
       52 
52 
     | 
    
         
             
                      elsif stat.file?
         
     | 
| 
       53 
53 
     | 
    
         
             
                        # If its a file, digest the contents
         
     | 
| 
       54 
     | 
    
         
            -
                         
     | 
| 
      
 54 
     | 
    
         
            +
                        digest_class.file(path.to_s).digest
         
     | 
| 
       55 
55 
     | 
    
         
             
                      end
         
     | 
| 
       56 
56 
     | 
    
         
             
                    end
         
     | 
| 
       57 
57 
     | 
    
         
             
                  end
         
     | 
| 
       58 
58 
     | 
    
         
             
                end
         
     | 
| 
       59 
59 
     | 
    
         | 
| 
       60 
     | 
    
         
            -
                # Internal: Compute  
     | 
| 
      
 60 
     | 
    
         
            +
                # Internal: Compute digest for a set of paths.
         
     | 
| 
       61 
61 
     | 
    
         
             
                #
         
     | 
| 
       62 
62 
     | 
    
         
             
                # paths - Array of filename or directory paths.
         
     | 
| 
       63 
63 
     | 
    
         
             
                #
         
     | 
| 
       64 
     | 
    
         
            -
                # Returns a String  
     | 
| 
       65 
     | 
    
         
            -
                def  
     | 
| 
       66 
     | 
    
         
            -
                  digest  
     | 
| 
       67 
     | 
    
         
            -
                  paths.each { |path| digest.update(file_hexdigest(path).to_s) }
         
     | 
| 
       68 
     | 
    
         
            -
                  digest.hexdigest
         
     | 
| 
      
 64 
     | 
    
         
            +
                # Returns a String digest.
         
     | 
| 
      
 65 
     | 
    
         
            +
                def files_digest(paths)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  digest(paths.map { |path| file_digest(path) })
         
     | 
| 
       69 
67 
     | 
    
         
             
                end
         
     | 
| 
       70 
68 
     | 
    
         | 
| 
       71 
69 
     | 
    
         
             
                # Find asset by logical path or expanded path.
         
     | 
| 
         @@ -191,16 +189,18 @@ module Sprockets 
     | 
|
| 
       191 
189 
     | 
    
         
             
                      asset.merge!({
         
     | 
| 
       192 
190 
     | 
    
         
             
                        encoding: Encoding::BINARY,
         
     | 
| 
       193 
191 
     | 
    
         
             
                        length: self.stat(asset[:filename]).size,
         
     | 
| 
       194 
     | 
    
         
            -
                        digest:  
     | 
| 
      
 192 
     | 
    
         
            +
                        digest: file_digest(asset[:filename]),
         
     | 
| 
       195 
193 
     | 
    
         
             
                        metadata: {}
         
     | 
| 
       196 
194 
     | 
    
         
             
                      })
         
     | 
| 
       197 
195 
     | 
    
         
             
                    end
         
     | 
| 
       198 
196 
     | 
    
         | 
| 
       199 
197 
     | 
    
         
             
                    metadata = asset[:metadata]
         
     | 
| 
       200 
198 
     | 
    
         
             
                    metadata[:dependency_paths] = Set.new(metadata[:dependency_paths]).merge([asset[:filename]])
         
     | 
| 
       201 
     | 
    
         
            -
                    metadata[: 
     | 
| 
      
 199 
     | 
    
         
            +
                    metadata[:dependency_sources_digest] = files_digest(metadata[:dependency_paths])
         
     | 
| 
       202 
200 
     | 
    
         | 
| 
       203 
     | 
    
         
            -
                    asset[: 
     | 
| 
      
 201 
     | 
    
         
            +
                    asset[:integrity] = integrity_uri(asset[:digest], asset[:content_type])
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                    asset[:id]  = pack_hexdigest(digest(asset))
         
     | 
| 
       204 
204 
     | 
    
         
             
                    asset[:uri] = AssetURI.build(filename, params.merge(id: asset[:id]))
         
     | 
| 
       205 
205 
     | 
    
         | 
| 
       206 
206 
     | 
    
         
             
                    # TODO: Avoid tracking Asset mtime
         
     | 
    
        data/lib/sprockets/cache.rb
    CHANGED
    
    | 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'sprockets/ 
     | 
| 
      
 1 
     | 
    
         
            +
            require 'sprockets/digest_utils'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'logger'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module Sprockets
         
     | 
| 
         @@ -142,7 +142,7 @@ module Sprockets 
     | 
|
| 
       142 
142 
     | 
    
         
             
                  #
         
     | 
| 
       143 
143 
     | 
    
         
             
                  # Returns a String with a length less than 250 characters.
         
     | 
| 
       144 
144 
     | 
    
         
             
                  def expand_key(key)
         
     | 
| 
       145 
     | 
    
         
            -
                    "sprockets/v#{VERSION}/#{ 
     | 
| 
      
 145 
     | 
    
         
            +
                    "sprockets/v#{VERSION}/#{DigestUtils.pack_urlsafe_base64digest(DigestUtils.digest(key))}"
         
     | 
| 
       146 
146 
     | 
    
         
             
                  end
         
     | 
| 
       147 
147 
     | 
    
         | 
| 
       148 
148 
     | 
    
         
             
                  PEEK_SIZE = 100
         
     | 
| 
         @@ -158,7 +158,7 @@ module Sprockets 
     | 
|
| 
       158 
158 
     | 
    
         
             
                      key.each { |k| str << peek_key(k) }
         
     | 
| 
       159 
159 
     | 
    
         
             
                      str.join(':')[0, PEEK_SIZE]
         
     | 
| 
       160 
160 
     | 
    
         
             
                    else
         
     | 
| 
       161 
     | 
    
         
            -
                      peek_key( 
     | 
| 
      
 161 
     | 
    
         
            +
                      peek_key(DigestUtils.pack_urlsafe_base64digest(DigestUtils.digest(key)))
         
     | 
| 
       162 
162 
     | 
    
         
             
                    end
         
     | 
| 
       163 
163 
     | 
    
         
             
                  end
         
     | 
| 
       164 
164 
     | 
    
         | 
| 
         @@ -14,10 +14,10 @@ module Sprockets 
     | 
|
| 
       14 
14 
     | 
    
         
             
                def initialize(environment)
         
     | 
| 
       15 
15 
     | 
    
         
             
                  initialize_configuration(environment)
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                  @cache 
     | 
| 
       18 
     | 
    
         
            -
                  @stats 
     | 
| 
       19 
     | 
    
         
            -
                  @entries 
     | 
| 
       20 
     | 
    
         
            -
                  @ 
     | 
| 
      
 17 
     | 
    
         
            +
                  @cache   = environment.cache
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @stats   = Hash.new { |h, k| h[k] = _stat(k) }
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @entries = Hash.new { |h, k| h[k] = _entries(k) }
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @digests = Hash.new { |h, k| h[k] = _file_digest(k) }
         
     | 
| 
       21 
21 
     | 
    
         
             
                end
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         
             
                # No-op return self as cached environment.
         
     | 
| 
         @@ -38,10 +38,10 @@ module Sprockets 
     | 
|
| 
       38 
38 
     | 
    
         
             
                  @stats[path]
         
     | 
| 
       39 
39 
     | 
    
         
             
                end
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                # Internal: Cache Environment# 
     | 
| 
       42 
     | 
    
         
            -
                alias_method : 
     | 
| 
       43 
     | 
    
         
            -
                def  
     | 
| 
       44 
     | 
    
         
            -
                  @ 
     | 
| 
      
 41 
     | 
    
         
            +
                # Internal: Cache Environment#file_digest
         
     | 
| 
      
 42 
     | 
    
         
            +
                alias_method :_file_digest, :file_digest
         
     | 
| 
      
 43 
     | 
    
         
            +
                def file_digest(path)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @digests[path]
         
     | 
| 
       45 
45 
     | 
    
         
             
                end
         
     | 
| 
       46 
46 
     | 
    
         | 
| 
       47 
47 
     | 
    
         
             
                protected
         
     | 
| 
         @@ -53,7 +53,7 @@ module Sprockets 
     | 
|
| 
       53 
53 
     | 
    
         
             
                      self.version,
         
     | 
| 
       54 
54 
     | 
    
         
             
                      self.paths,
         
     | 
| 
       55 
55 
     | 
    
         
             
                      uri,
         
     | 
| 
       56 
     | 
    
         
            -
                       
     | 
| 
      
 56 
     | 
    
         
            +
                      file_digest(filename)
         
     | 
| 
       57 
57 
     | 
    
         
             
                    ]
         
     | 
| 
       58 
58 
     | 
    
         
             
                  end
         
     | 
| 
       59 
59 
     | 
    
         | 
| 
         @@ -75,9 +75,9 @@ module Sprockets 
     | 
|
| 
       75 
75 
     | 
    
         
             
                  def build_asset_by_uri(uri)
         
     | 
| 
       76 
76 
     | 
    
         
             
                    dep_graph_key = asset_dependency_graph_cache_key(uri)
         
     | 
| 
       77 
77 
     | 
    
         | 
| 
       78 
     | 
    
         
            -
                    dependency_paths,  
     | 
| 
       79 
     | 
    
         
            -
                    if dependency_paths &&  
     | 
| 
       80 
     | 
    
         
            -
                      if  
     | 
| 
      
 78 
     | 
    
         
            +
                    dependency_paths, dependency_sources_digest, digest_uri = cache._get(dep_graph_key)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    if dependency_paths && dependency_sources_digest && digest_uri
         
     | 
| 
      
 80 
     | 
    
         
            +
                      if files_digest(dependency_paths) == dependency_sources_digest
         
     | 
| 
       81 
81 
     | 
    
         
             
                        if asset = cache._get(asset_digest_uri_cache_key(digest_uri))
         
     | 
| 
       82 
82 
     | 
    
         
             
                          return asset
         
     | 
| 
       83 
83 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -86,8 +86,8 @@ module Sprockets 
     | 
|
| 
       86 
86 
     | 
    
         | 
| 
       87 
87 
     | 
    
         
             
                    asset = super
         
     | 
| 
       88 
88 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
                     
     | 
| 
       90 
     | 
    
         
            -
                    cache._set(dep_graph_key, [dependency_paths,  
     | 
| 
      
 89 
     | 
    
         
            +
                    dependency_sources_digest, dependency_paths = asset[:metadata].values_at(:dependency_sources_digest, :dependency_paths)
         
     | 
| 
      
 90 
     | 
    
         
            +
                    cache._set(dep_graph_key, [dependency_paths, dependency_sources_digest, asset[:uri]])
         
     | 
| 
       91 
91 
     | 
    
         
             
                    cache.fetch(asset_digest_uri_cache_key(asset[:uri])) { asset }
         
     | 
| 
       92 
92 
     | 
    
         | 
| 
       93 
93 
     | 
    
         
             
                    asset
         
     | 
| 
         @@ -52,13 +52,13 @@ module Sprockets 
     | 
|
| 
       52 
52 
     | 
    
         
             
                  mutate_config(:version) { version.dup }
         
     | 
| 
       53 
53 
     | 
    
         
             
                end
         
     | 
| 
       54 
54 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
                # Returns a `Digest` implementation class.
         
     | 
| 
      
 55 
     | 
    
         
            +
                # Deprecated: Returns a `Digest` implementation class.
         
     | 
| 
       56 
56 
     | 
    
         
             
                #
         
     | 
| 
       57 
     | 
    
         
            -
                # Defaults to `Digest:: 
     | 
| 
      
 57 
     | 
    
         
            +
                # Defaults to `Digest::SHA256`.
         
     | 
| 
       58 
58 
     | 
    
         
             
                attr_reader :digest_class
         
     | 
| 
       59 
59 
     | 
    
         | 
| 
       60 
     | 
    
         
            -
                # Assign a `Digest` implementation class. This maybe any Ruby
         
     | 
| 
       61 
     | 
    
         
            -
                # `Digest::` implementation such as `Digest:: 
     | 
| 
      
 60 
     | 
    
         
            +
                # Deprecated: Assign a `Digest` implementation class. This maybe any Ruby
         
     | 
| 
      
 61 
     | 
    
         
            +
                # `Digest::` implementation such as `Digest::SHA256` or
         
     | 
| 
       62 
62 
     | 
    
         
             
                # `Digest::MD5`.
         
     | 
| 
       63 
63 
     | 
    
         
             
                #
         
     | 
| 
       64 
64 
     | 
    
         
             
                #     environment.digest_class = Digest::MD5
         
     | 
| 
         @@ -0,0 +1,144 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'digest/md5'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'digest/sha1'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'digest/sha2'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Sprockets
         
     | 
| 
      
 6 
     | 
    
         
            +
              module DigestUtils
         
     | 
| 
      
 7 
     | 
    
         
            +
                extend self
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # Internal: Default digest class.
         
     | 
| 
      
 10 
     | 
    
         
            +
                #
         
     | 
| 
      
 11 
     | 
    
         
            +
                # Returns a Digest::Base subclass.
         
     | 
| 
      
 12 
     | 
    
         
            +
                def digest_class
         
     | 
| 
      
 13 
     | 
    
         
            +
                  Digest::SHA256
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                # Internal: Maps digest bytesize to the digest class.
         
     | 
| 
      
 17 
     | 
    
         
            +
                DIGEST_SIZES = {
         
     | 
| 
      
 18 
     | 
    
         
            +
                  16 => Digest::MD5,
         
     | 
| 
      
 19 
     | 
    
         
            +
                  20 => Digest::SHA1,
         
     | 
| 
      
 20 
     | 
    
         
            +
                  32 => Digest::SHA256,
         
     | 
| 
      
 21 
     | 
    
         
            +
                  48 => Digest::SHA384,
         
     | 
| 
      
 22 
     | 
    
         
            +
                  64 => Digest::SHA512
         
     | 
| 
      
 23 
     | 
    
         
            +
                }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                # Internal: Detect digest class hash algorithm for digest bytes.
         
     | 
| 
      
 26 
     | 
    
         
            +
                #
         
     | 
| 
      
 27 
     | 
    
         
            +
                # While not elegant, all the supported digests have a unique bytesize.
         
     | 
| 
      
 28 
     | 
    
         
            +
                #
         
     | 
| 
      
 29 
     | 
    
         
            +
                # Returns Digest::Base or nil.
         
     | 
| 
      
 30 
     | 
    
         
            +
                def detect_digest_class(bytes)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  DIGEST_SIZES[bytes.bytesize]
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                # Internal: Generate a hexdigest for a nested JSON serializable object.
         
     | 
| 
      
 35 
     | 
    
         
            +
                #
         
     | 
| 
      
 36 
     | 
    
         
            +
                # obj - A JSON serializable object.
         
     | 
| 
      
 37 
     | 
    
         
            +
                #
         
     | 
| 
      
 38 
     | 
    
         
            +
                # Returns a String digest of the object.
         
     | 
| 
      
 39 
     | 
    
         
            +
                def digest(obj)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  digest = digest_class.new
         
     | 
| 
      
 41 
     | 
    
         
            +
                  queue  = [obj]
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  while queue.length > 0
         
     | 
| 
      
 44 
     | 
    
         
            +
                    obj = queue.shift
         
     | 
| 
      
 45 
     | 
    
         
            +
                    klass = obj.class
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    if klass == String
         
     | 
| 
      
 48 
     | 
    
         
            +
                      digest << obj
         
     | 
| 
      
 49 
     | 
    
         
            +
                    elsif klass == Symbol
         
     | 
| 
      
 50 
     | 
    
         
            +
                      digest << 'Symbol'
         
     | 
| 
      
 51 
     | 
    
         
            +
                      digest << obj.to_s
         
     | 
| 
      
 52 
     | 
    
         
            +
                    elsif klass == Fixnum
         
     | 
| 
      
 53 
     | 
    
         
            +
                      digest << 'Fixnum'
         
     | 
| 
      
 54 
     | 
    
         
            +
                      digest << obj.to_s
         
     | 
| 
      
 55 
     | 
    
         
            +
                    elsif klass == TrueClass
         
     | 
| 
      
 56 
     | 
    
         
            +
                      digest << 'TrueClass'
         
     | 
| 
      
 57 
     | 
    
         
            +
                    elsif klass == FalseClass
         
     | 
| 
      
 58 
     | 
    
         
            +
                      digest << 'FalseClass'
         
     | 
| 
      
 59 
     | 
    
         
            +
                    elsif klass == NilClass
         
     | 
| 
      
 60 
     | 
    
         
            +
                      digest << 'NilClass'
         
     | 
| 
      
 61 
     | 
    
         
            +
                    elsif klass == Array
         
     | 
| 
      
 62 
     | 
    
         
            +
                      digest << 'Array'
         
     | 
| 
      
 63 
     | 
    
         
            +
                      queue.concat(obj)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    elsif klass == Hash
         
     | 
| 
      
 65 
     | 
    
         
            +
                      digest << 'Hash'
         
     | 
| 
      
 66 
     | 
    
         
            +
                      queue.concat(obj.sort)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    elsif klass == Set
         
     | 
| 
      
 68 
     | 
    
         
            +
                      digest << 'Set'
         
     | 
| 
      
 69 
     | 
    
         
            +
                      queue.concat(obj.to_a)
         
     | 
| 
      
 70 
     | 
    
         
            +
                    elsif klass == Encoding
         
     | 
| 
      
 71 
     | 
    
         
            +
                      digest << 'Encoding'
         
     | 
| 
      
 72 
     | 
    
         
            +
                      digest << obj.name
         
     | 
| 
      
 73 
     | 
    
         
            +
                    else
         
     | 
| 
      
 74 
     | 
    
         
            +
                      raise TypeError, "couldn't digest #{klass}"
         
     | 
| 
      
 75 
     | 
    
         
            +
                    end
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  digest.digest
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                # Internal: Pack a binary digest to a hex encoded string.
         
     | 
| 
      
 82 
     | 
    
         
            +
                #
         
     | 
| 
      
 83 
     | 
    
         
            +
                # bin - String bytes
         
     | 
| 
      
 84 
     | 
    
         
            +
                #
         
     | 
| 
      
 85 
     | 
    
         
            +
                # Returns hex String.
         
     | 
| 
      
 86 
     | 
    
         
            +
                def pack_hexdigest(bin)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  bin.unpack('H*').first
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                # Internal: Pack a binary digest to a base64 encoded string.
         
     | 
| 
      
 91 
     | 
    
         
            +
                #
         
     | 
| 
      
 92 
     | 
    
         
            +
                # bin - String bytes
         
     | 
| 
      
 93 
     | 
    
         
            +
                #
         
     | 
| 
      
 94 
     | 
    
         
            +
                # Returns base64 String.
         
     | 
| 
      
 95 
     | 
    
         
            +
                def pack_base64digest(bin)
         
     | 
| 
      
 96 
     | 
    
         
            +
                  [bin].pack('m0')
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                # Internal: Pack a binary digest to a urlsafe base64 encoded string.
         
     | 
| 
      
 100 
     | 
    
         
            +
                #
         
     | 
| 
      
 101 
     | 
    
         
            +
                # bin - String bytes
         
     | 
| 
      
 102 
     | 
    
         
            +
                #
         
     | 
| 
      
 103 
     | 
    
         
            +
                # Returns urlsafe base64 String.
         
     | 
| 
      
 104 
     | 
    
         
            +
                def pack_urlsafe_base64digest(bin)
         
     | 
| 
      
 105 
     | 
    
         
            +
                  pack_base64digest(bin).tr('+/', '-_').tr('=', '')
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                # Internal: Maps digest class to the named information hash algorithm name.
         
     | 
| 
      
 109 
     | 
    
         
            +
                #
         
     | 
| 
      
 110 
     | 
    
         
            +
                # http://www.iana.org/assignments/named-information/named-information.xhtml
         
     | 
| 
      
 111 
     | 
    
         
            +
                NI_HASH_ALGORIHMS = {
         
     | 
| 
      
 112 
     | 
    
         
            +
                  Digest::SHA256 => 'sha-256'.freeze,
         
     | 
| 
      
 113 
     | 
    
         
            +
                  Digest::SHA384 => 'sha-384'.freeze,
         
     | 
| 
      
 114 
     | 
    
         
            +
                  Digest::SHA512 => 'sha-512'.freeze
         
     | 
| 
      
 115 
     | 
    
         
            +
                }
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                # Internal: Generate a "named information" URI for use in the `integrity`
         
     | 
| 
      
 118 
     | 
    
         
            +
                # attribute of an asset tag as per the subresource integrity specification.
         
     | 
| 
      
 119 
     | 
    
         
            +
                #
         
     | 
| 
      
 120 
     | 
    
         
            +
                # digest       - The String byte digest of the asset content.
         
     | 
| 
      
 121 
     | 
    
         
            +
                # content_type - The content-type the asset will be served with. This *must*
         
     | 
| 
      
 122 
     | 
    
         
            +
                #                be accurate if provided. Otherwise, subresource integrity
         
     | 
| 
      
 123 
     | 
    
         
            +
                #                will block the loading of the asset.
         
     | 
| 
      
 124 
     | 
    
         
            +
                #
         
     | 
| 
      
 125 
     | 
    
         
            +
                # Returns a String or nil if hash algorithm is incompatible.
         
     | 
| 
      
 126 
     | 
    
         
            +
                def integrity_uri(digest, content_type = nil)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  case digest
         
     | 
| 
      
 128 
     | 
    
         
            +
                  when Digest::Base
         
     | 
| 
      
 129 
     | 
    
         
            +
                    digest_class = digest.class
         
     | 
| 
      
 130 
     | 
    
         
            +
                    digest = digest.digest
         
     | 
| 
      
 131 
     | 
    
         
            +
                  when String
         
     | 
| 
      
 132 
     | 
    
         
            +
                    digest_class = DIGEST_SIZES[digest.bytesize]
         
     | 
| 
      
 133 
     | 
    
         
            +
                  else
         
     | 
| 
      
 134 
     | 
    
         
            +
                    raise TypeError, "unknown digest: #{digest.inspect}"
         
     | 
| 
      
 135 
     | 
    
         
            +
                  end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                  if hash_name = NI_HASH_ALGORIHMS[digest_class]
         
     | 
| 
      
 138 
     | 
    
         
            +
                    uri = "ni:///#{hash_name};#{pack_urlsafe_base64digest(digest)}"
         
     | 
| 
      
 139 
     | 
    
         
            +
                    uri << "?ct=#{content_type}" if content_type
         
     | 
| 
      
 140 
     | 
    
         
            +
                    uri
         
     | 
| 
      
 141 
     | 
    
         
            +
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
                end
         
     | 
| 
      
 143 
     | 
    
         
            +
              end
         
     | 
| 
      
 144 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/sprockets/manifest.rb
    CHANGED
    
    | 
         @@ -173,7 +173,8 @@ module Sprockets 
     | 
|
| 
       173 
173 
     | 
    
         
             
                        'logical_path' => asset.logical_path,
         
     | 
| 
       174 
174 
     | 
    
         
             
                        'mtime'        => asset.mtime.iso8601,
         
     | 
| 
       175 
175 
     | 
    
         
             
                        'size'         => asset.bytesize,
         
     | 
| 
       176 
     | 
    
         
            -
                        'digest'       => asset. 
     | 
| 
      
 176 
     | 
    
         
            +
                        'digest'       => asset.hexdigest,
         
     | 
| 
      
 177 
     | 
    
         
            +
                        'integrity'    => asset.integrity
         
     | 
| 
       177 
178 
     | 
    
         
             
                      }
         
     | 
| 
       178 
179 
     | 
    
         
             
                      assets[asset.logical_path] = asset.digest_path
         
     | 
| 
       179 
180 
     | 
    
         | 
    
        data/lib/sprockets/path_utils.rb
    CHANGED
    
    | 
         @@ -114,6 +114,41 @@ module Sprockets 
     | 
|
| 
       114 
114 
     | 
    
         
             
                  File.basename(path).scan(/\.[^.]+/)
         
     | 
| 
       115 
115 
     | 
    
         
             
                end
         
     | 
| 
       116 
116 
     | 
    
         | 
| 
      
 117 
     | 
    
         
            +
                # Internal: Returns all parents for path
         
     | 
| 
      
 118 
     | 
    
         
            +
                #
         
     | 
| 
      
 119 
     | 
    
         
            +
                # path - String absolute filename or directory
         
     | 
| 
      
 120 
     | 
    
         
            +
                # root - String path to stop at (default: system root)
         
     | 
| 
      
 121 
     | 
    
         
            +
                #
         
     | 
| 
      
 122 
     | 
    
         
            +
                # Returns an Array of String paths.
         
     | 
| 
      
 123 
     | 
    
         
            +
                def path_parents(path, root = nil)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  root = "#{root}#{File::SEPARATOR}" if root
         
     | 
| 
      
 125 
     | 
    
         
            +
                  parents = []
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 128 
     | 
    
         
            +
                    parent = File.dirname(path)
         
     | 
| 
      
 129 
     | 
    
         
            +
                    break if parent == path
         
     | 
| 
      
 130 
     | 
    
         
            +
                    break if root && !path.start_with?(root)
         
     | 
| 
      
 131 
     | 
    
         
            +
                    parents << path = parent
         
     | 
| 
      
 132 
     | 
    
         
            +
                  end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                  parents
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                # Internal: Find target basename checking upwards from path.
         
     | 
| 
      
 138 
     | 
    
         
            +
                #
         
     | 
| 
      
 139 
     | 
    
         
            +
                # basename - String filename: ".sprocketsrc"
         
     | 
| 
      
 140 
     | 
    
         
            +
                # path     - String path to start search: "app/assets/javascripts/app.js"
         
     | 
| 
      
 141 
     | 
    
         
            +
                # root     - String path to stop at (default: system root)
         
     | 
| 
      
 142 
     | 
    
         
            +
                #
         
     | 
| 
      
 143 
     | 
    
         
            +
                # Returns String filename or nil.
         
     | 
| 
      
 144 
     | 
    
         
            +
                def find_upwards(basename, path, root = nil)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  path_parents(path, root).each do |dir|
         
     | 
| 
      
 146 
     | 
    
         
            +
                    filename = File.join(dir, basename)
         
     | 
| 
      
 147 
     | 
    
         
            +
                    return filename if file?(filename)
         
     | 
| 
      
 148 
     | 
    
         
            +
                  end
         
     | 
| 
      
 149 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 150 
     | 
    
         
            +
                end
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
       117 
152 
     | 
    
         
             
                # Internal: Stat all the files under a directory.
         
     | 
| 
       118 
153 
     | 
    
         
             
                #
         
     | 
| 
       119 
154 
     | 
    
         
             
                # dir - A String directory
         
     | 
    
        data/lib/sprockets/processing.rb
    CHANGED
    
    | 
         @@ -180,7 +180,7 @@ module Sprockets 
     | 
|
| 
       180 
180 
     | 
    
         
             
                      when NilClass
         
     | 
| 
       181 
181 
     | 
    
         
             
                        # noop
         
     | 
| 
       182 
182 
     | 
    
         
             
                      when Hash
         
     | 
| 
       183 
     | 
    
         
            -
                        data = result[:data]
         
     | 
| 
      
 183 
     | 
    
         
            +
                        data = result[:data] if result.key?(:data)
         
     | 
| 
       184 
184 
     | 
    
         
             
                        metadata = metadata.merge(result)
         
     | 
| 
       185 
185 
     | 
    
         
             
                        metadata.delete(:data)
         
     | 
| 
       186 
186 
     | 
    
         
             
                      when String
         
     | 
| 
         @@ -195,7 +195,7 @@ module Sprockets 
     | 
|
| 
       195 
195 
     | 
    
         
             
                    source: data,
         
     | 
| 
       196 
196 
     | 
    
         
             
                    charset: data.encoding.name.downcase,
         
     | 
| 
       197 
197 
     | 
    
         
             
                    length: data.bytesize,
         
     | 
| 
       198 
     | 
    
         
            -
                    digest:  
     | 
| 
      
 198 
     | 
    
         
            +
                    digest: digest(data),
         
     | 
| 
       199 
199 
     | 
    
         
             
                    metadata: metadata
         
     | 
| 
       200 
200 
     | 
    
         
             
                  }
         
     | 
| 
       201 
201 
     | 
    
         
             
                end
         
     | 
    
        data/lib/sprockets/server.rb
    CHANGED
    
    | 
         @@ -67,11 +67,11 @@ module Sprockets 
     | 
|
| 
       67 
67 
     | 
    
         | 
| 
       68 
68 
     | 
    
         
             
                  if asset.nil?
         
     | 
| 
       69 
69 
     | 
    
         
             
                    status = :not_found
         
     | 
| 
       70 
     | 
    
         
            -
                  elsif fingerprint && asset. 
     | 
| 
      
 70 
     | 
    
         
            +
                  elsif fingerprint && asset.etag != fingerprint
         
     | 
| 
       71 
71 
     | 
    
         
             
                    status = :not_found
         
     | 
| 
       72 
     | 
    
         
            -
                  elsif if_match && asset. 
     | 
| 
      
 72 
     | 
    
         
            +
                  elsif if_match && asset.etag != if_match
         
     | 
| 
       73 
73 
     | 
    
         
             
                    status = :precondition_failed
         
     | 
| 
       74 
     | 
    
         
            -
                  elsif if_none_match && asset. 
     | 
| 
      
 74 
     | 
    
         
            +
                  elsif if_none_match && asset.etag == if_none_match
         
     | 
| 
       75 
75 
     | 
    
         
             
                    status = :not_modified
         
     | 
| 
       76 
76 
     | 
    
         
             
                  else
         
     | 
| 
       77 
77 
     | 
    
         
             
                    status = :ok
         
     | 
| 
         @@ -124,8 +124,8 @@ module Sprockets 
     | 
|
| 
       124 
124 
     | 
    
         
             
                  end
         
     | 
| 
       125 
125 
     | 
    
         | 
| 
       126 
126 
     | 
    
         
             
                  # Returns a 304 Not Modified response tuple
         
     | 
| 
       127 
     | 
    
         
            -
                  def not_modified_response(env,  
     | 
| 
       128 
     | 
    
         
            -
                    [ 304, cache_headers(env,  
     | 
| 
      
 127 
     | 
    
         
            +
                  def not_modified_response(env, etag)
         
     | 
| 
      
 128 
     | 
    
         
            +
                    [ 304, cache_headers(env, etag), [] ]
         
     | 
| 
       129 
129 
     | 
    
         
             
                  end
         
     | 
| 
       130 
130 
     | 
    
         | 
| 
       131 
131 
     | 
    
         
             
                  # Returns a 403 Forbidden response tuple
         
     | 
| 
         @@ -221,12 +221,12 @@ module Sprockets 
     | 
|
| 
       221 
221 
     | 
    
         
             
                    env["QUERY_STRING"].to_s =~ /body=(1|t)/
         
     | 
| 
       222 
222 
     | 
    
         
             
                  end
         
     | 
| 
       223 
223 
     | 
    
         | 
| 
       224 
     | 
    
         
            -
                  def cache_headers(env,  
     | 
| 
      
 224 
     | 
    
         
            +
                  def cache_headers(env, etag)
         
     | 
| 
       225 
225 
     | 
    
         
             
                    headers = {}
         
     | 
| 
       226 
226 
     | 
    
         | 
| 
       227 
227 
     | 
    
         
             
                    # Set caching headers
         
     | 
| 
       228 
228 
     | 
    
         
             
                    headers["Cache-Control"] = "public"
         
     | 
| 
       229 
     | 
    
         
            -
                    headers["ETag"]          = %("#{ 
     | 
| 
      
 229 
     | 
    
         
            +
                    headers["ETag"]          = %("#{etag}")
         
     | 
| 
       230 
230 
     | 
    
         | 
| 
       231 
231 
     | 
    
         
             
                    # If the request url contains a fingerprint, set a long
         
     | 
| 
       232 
232 
     | 
    
         
             
                    # expires on the response
         
     | 
| 
         @@ -262,16 +262,16 @@ module Sprockets 
     | 
|
| 
       262 
262 
     | 
    
         
             
                      headers["Content-Type"] = type
         
     | 
| 
       263 
263 
     | 
    
         
             
                    end
         
     | 
| 
       264 
264 
     | 
    
         | 
| 
       265 
     | 
    
         
            -
                    headers.merge(cache_headers(env, asset. 
     | 
| 
      
 265 
     | 
    
         
            +
                    headers.merge(cache_headers(env, asset.etag))
         
     | 
| 
       266 
266 
     | 
    
         
             
                  end
         
     | 
| 
       267 
267 
     | 
    
         | 
| 
       268 
     | 
    
         
            -
                  # Gets  
     | 
| 
      
 268 
     | 
    
         
            +
                  # Gets ETag fingerprint.
         
     | 
| 
       269 
269 
     | 
    
         
             
                  #
         
     | 
| 
       270 
270 
     | 
    
         
             
                  #     "foo-0aa2105d29558f3eb790d411d7d8fb66.js"
         
     | 
| 
       271 
271 
     | 
    
         
             
                  #     # => "0aa2105d29558f3eb790d411d7d8fb66"
         
     | 
| 
       272 
272 
     | 
    
         
             
                  #
         
     | 
| 
       273 
273 
     | 
    
         
             
                  def path_fingerprint(path)
         
     | 
| 
       274 
     | 
    
         
            -
                    path[/-([0-9a-f]{7, 
     | 
| 
      
 274 
     | 
    
         
            +
                    path[/-([0-9a-f]{7,128})\.[^.]+$/, 1]
         
     | 
| 
       275 
275 
     | 
    
         
             
                  end
         
     | 
| 
       276 
276 
     | 
    
         
             
              end
         
     | 
| 
       277 
277 
     | 
    
         
             
            end
         
     | 
    
        data/lib/sprockets/utils.rb
    CHANGED
    
    | 
         @@ -1,4 +1,3 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'digest/sha1'
         
     | 
| 
       2 
1 
     | 
    
         
             
            require 'set'
         
     | 
| 
       3 
2 
     | 
    
         | 
| 
       4 
3 
     | 
    
         
             
            module Sprockets
         
     | 
| 
         @@ -101,54 +100,6 @@ module Sprockets 
     | 
|
| 
       101 
100 
     | 
    
         
             
                  end
         
     | 
| 
       102 
101 
     | 
    
         
             
                end
         
     | 
| 
       103 
102 
     | 
    
         | 
| 
       104 
     | 
    
         
            -
                # Internal: Generate a hexdigest for a nested JSON serializable object.
         
     | 
| 
       105 
     | 
    
         
            -
                #
         
     | 
| 
       106 
     | 
    
         
            -
                # obj - A JSON serializable object.
         
     | 
| 
       107 
     | 
    
         
            -
                #
         
     | 
| 
       108 
     | 
    
         
            -
                # Returns a String SHA1 digest of the object.
         
     | 
| 
       109 
     | 
    
         
            -
                def hexdigest(obj)
         
     | 
| 
       110 
     | 
    
         
            -
                  digest = Digest::SHA1.new
         
     | 
| 
       111 
     | 
    
         
            -
                  queue  = [obj]
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
                  while queue.length > 0
         
     | 
| 
       114 
     | 
    
         
            -
                    obj = queue.shift
         
     | 
| 
       115 
     | 
    
         
            -
                    klass = obj.class
         
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
                    if klass == String
         
     | 
| 
       118 
     | 
    
         
            -
                      digest << 'String'
         
     | 
| 
       119 
     | 
    
         
            -
                      digest << obj
         
     | 
| 
       120 
     | 
    
         
            -
                    elsif klass == Symbol
         
     | 
| 
       121 
     | 
    
         
            -
                      digest << 'Symbol'
         
     | 
| 
       122 
     | 
    
         
            -
                      digest << obj.to_s
         
     | 
| 
       123 
     | 
    
         
            -
                    elsif klass == Fixnum
         
     | 
| 
       124 
     | 
    
         
            -
                      digest << 'Fixnum'
         
     | 
| 
       125 
     | 
    
         
            -
                      digest << obj.to_s
         
     | 
| 
       126 
     | 
    
         
            -
                    elsif klass == TrueClass
         
     | 
| 
       127 
     | 
    
         
            -
                      digest << 'TrueClass'
         
     | 
| 
       128 
     | 
    
         
            -
                    elsif klass == FalseClass
         
     | 
| 
       129 
     | 
    
         
            -
                      digest << 'FalseClass'
         
     | 
| 
       130 
     | 
    
         
            -
                    elsif klass == NilClass
         
     | 
| 
       131 
     | 
    
         
            -
                      digest << 'NilClass'
         
     | 
| 
       132 
     | 
    
         
            -
                    elsif klass == Array
         
     | 
| 
       133 
     | 
    
         
            -
                      digest << 'Array'
         
     | 
| 
       134 
     | 
    
         
            -
                      queue.concat(obj)
         
     | 
| 
       135 
     | 
    
         
            -
                    elsif klass == Hash
         
     | 
| 
       136 
     | 
    
         
            -
                      digest << 'Hash'
         
     | 
| 
       137 
     | 
    
         
            -
                      queue.concat(obj.sort)
         
     | 
| 
       138 
     | 
    
         
            -
                    elsif klass == Set
         
     | 
| 
       139 
     | 
    
         
            -
                      digest << 'Set'
         
     | 
| 
       140 
     | 
    
         
            -
                      queue.concat(obj.to_a)
         
     | 
| 
       141 
     | 
    
         
            -
                    elsif klass == Encoding
         
     | 
| 
       142 
     | 
    
         
            -
                      digest << 'Encoding'
         
     | 
| 
       143 
     | 
    
         
            -
                      digest << obj.name
         
     | 
| 
       144 
     | 
    
         
            -
                    else
         
     | 
| 
       145 
     | 
    
         
            -
                      raise TypeError, "couldn't digest #{klass}"
         
     | 
| 
       146 
     | 
    
         
            -
                    end
         
     | 
| 
       147 
     | 
    
         
            -
                  end
         
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
                  digest.hexdigest
         
     | 
| 
       150 
     | 
    
         
            -
                end
         
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
103 
     | 
    
         
             
                # Internal: Post-order Depth-First search algorithm.
         
     | 
| 
       153 
104 
     | 
    
         
             
                #
         
     | 
| 
       154 
105 
     | 
    
         
             
                # Used for resolving asset dependencies.
         
     | 
    
        data/lib/sprockets/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: sprockets
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 3.0.0.beta. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 3.0.0.beta.2
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Sam Stephenson
         
     | 
| 
         @@ -9,7 +9,7 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2014- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2014-10-10 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
15 
     | 
    
         
             
              name: rack
         
     | 
| 
         @@ -237,6 +237,7 @@ files: 
     | 
|
| 
       237 
237 
     | 
    
         
             
            - lib/sprockets/compressing.rb
         
     | 
| 
       238 
238 
     | 
    
         
             
            - lib/sprockets/configuration.rb
         
     | 
| 
       239 
239 
     | 
    
         
             
            - lib/sprockets/context.rb
         
     | 
| 
      
 240 
     | 
    
         
            +
            - lib/sprockets/digest_utils.rb
         
     | 
| 
       240 
241 
     | 
    
         
             
            - lib/sprockets/directive_processor.rb
         
     | 
| 
       241 
242 
     | 
    
         
             
            - lib/sprockets/eco_template.rb
         
     | 
| 
       242 
243 
     | 
    
         
             
            - lib/sprockets/ejs_template.rb
         
     |