sprockets 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sprockets might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ec93323cfb4ee9daedbf87dd84da7e788eb5fed5
4
- data.tar.gz: 5e43ec7e11e4d9fd167ed70f00633ae0995a72aa
3
+ metadata.gz: 12abb21d7b7beb859bc402887f2b6a1081408103
4
+ data.tar.gz: f90c9972dc5ee2d6db3ca2d052bd20440eadce4f
5
5
  SHA512:
6
- metadata.gz: b891fd59f01709b0ded0462aec839bfb346c36e379a48e3eaf770e60d369e87040e6ec0941b35fe2a79411a2e39cbf48b2131d2ef241d62dadd84640d8df3276
7
- data.tar.gz: dc144eaac6981bdbea7838822e049fb026304d615b94286ec989f3d3ada6731f978e5151eb67caa91f81a03fbf66037027f3c90ceaa68d9aa57897ae35390977
6
+ metadata.gz: 7d47b7a7900ace1158e5d37f4414359c83266e7e37f4fbad746f657139719b57b36dfd260c66ed03768623d52cb0bcc859a39fde55f38d9c80e685d1e50ae437
7
+ data.tar.gz: 4ea4085268e814ad668d8d6038f9f0253c7afbbdd97c79c596eb7e82939ae7720d8f1c9674432d301759e225a8d5c1677c82c45d028ae86ddc639ebd6cbdffca
@@ -0,0 +1,222 @@
1
+ **3.3.0** (August 12, 2015)
2
+
3
+ * Change internal cache lookup to use relative asset paths instead of absolute paths.
4
+
5
+ **3.2.0** (June 2, 2015)
6
+
7
+ * Updated SRI integrity to align with spec changes
8
+ * Deprecated Manifest integrity attribute
9
+ * Cleanup concatenating JS sources with newlines
10
+
11
+ **3.1.0** (May 10, 2015)
12
+
13
+ * Removed "index" logical path normalization. Asset#logical_path is always the
14
+ full logical path to the index file.
15
+ * Fixed static asset mtimes
16
+ * Fix manifest cleanup by age
17
+ * Removed redundant minifier level cache
18
+ * Updated SRI format according to spec changes
19
+
20
+ **3.0.3** (April 27, 2015)
21
+
22
+ * Fix static asset mtime fallback
23
+ * Only warn when specified asset version can not be loaded.
24
+
25
+ **3.0.2** (April 22, 2015)
26
+
27
+ * Ensure legacy Tilt handlers return String class data. Fixes issues with Haml
28
+ Tilt handler.
29
+ * Type check and improve error messages raised on bad processor returned results.
30
+ * Improve error message for relative paths not under load path.
31
+ * Changed HTML encoding fallback from ISO-8859-1 to default external.
32
+ * Avoid falling back to 0 mtimes which may cause warnings with tar
33
+
34
+ **3.0.1** (April 14, 2015)
35
+
36
+ * Fixed `Context#depend_on` with paths outside the load path
37
+
38
+ **3.0.0** (April 12, 2015)
39
+
40
+ [Guide to upgrading from Sprockets 2.x to 3.x](https://github.com/rails/sprockets/blob/master/UPGRADING.md)
41
+
42
+ * New processor API. Tilt interface is deprecated.
43
+ * Improved file store caching backend.
44
+ * MIME Types now accept charset custom charset detecters. Improves support for UTF-16/32 files.
45
+ * Environment#version no longer affects asset digests. Only used for busting the asset cache.
46
+ * Removed builtin support for LESS.
47
+ * Removed `//= include` directive support.
48
+ * Deprecated `BundledAsset#to_a`. Use `BundledAsset#included` to access debugging subcomponents.
49
+ * Support circular dependencies. For parity with ES6 modules.
50
+ * Manifest compilation will no longer generate .gz files by default. [Mixing
51
+ Content-Encoding and ETags is just a bad
52
+ idea](https://issues.apache.org/bugzilla/show_bug.cgi?id=39727)
53
+ * Added linked or referenced assets. When an asset is compiled, any of its links will be compiled as well.
54
+ * Introduce some limitations around enumerating all logical paths. 4.x will deprecate it and favor linked manifests for compliation.
55
+ * Add Asset integrity attribute for Subresource Integrity
56
+ * Default digest changed to SHA256. Configuring `digest_class` is deprecated.
57
+ * Rename `Asset#digest` to `Asset#hexdigest`. `Asset#digest` is deprecated and will
58
+ return a raw byte String in 4.x.
59
+ * Added transitional compatibility flag to `Environment#resolve(path, compat: true)`. 2.x mode operates with `compat: true` and 4.x with `compat: false`
60
+ * `manifest-abc123.json` renamed to `.sprockets-abc123.json`
61
+
62
+ **2.12.3** (October 28, 2014)
63
+
64
+ * Security: Fix directory traversal bug in development mode server.
65
+
66
+ **2.12.2** (September 5, 2014)
67
+
68
+ * Ensure internal asset lookups calls are still restricted to load paths within
69
+ asset compiles. Though, you should not depend on internal asset resolves to be
70
+ completely restricted for security reasons. Assets themselves should be
71
+ considered full scripting environments with filesystem access.
72
+
73
+ **2.12.1** (April 17, 2014)
74
+
75
+ * Fix making manifest target directory when its different than the output directory.
76
+
77
+ **2.12.0** (March 13, 2014)
78
+
79
+ * Avoid context reference in SassImporter hack so its Marshallable. Fixes
80
+ issues with Sass 3.3.x.
81
+
82
+ **2.11.0** (February 19, 2014)
83
+
84
+ * Cache store must now be an LRU implementation.
85
+ * Default digest changed to SHA1. To continue using MD5.
86
+ `env.digest_class = Digest::MD5`.
87
+
88
+ **2.10.0** (May 24, 2013)
89
+
90
+ * Support for `bower.json`
91
+
92
+ **2.9.3** (April 20, 2013)
93
+
94
+ * Fixed sass caching bug
95
+
96
+ **2.9.2** (April 8, 2013)
97
+
98
+ * Improve file freshness check performance
99
+ * Directive processor encoding fixes
100
+
101
+ **2.9.1** (April 6, 2013)
102
+
103
+ * Support for Uglifier 2.x
104
+
105
+ **2.9.0** (February 25, 2013)
106
+
107
+ * Write out gzipped variants of bundled assets.
108
+
109
+ **2.8.2** (December 10, 2012)
110
+
111
+ * Fixed top level Sass constant references
112
+ * Fixed manifest logger when environment is disabled
113
+
114
+ **2.8.1** (October 31, 2012)
115
+
116
+ * Fixed Sass importer bug
117
+
118
+ **2.8.0** (October 16, 2012)
119
+
120
+ * Allow manifest location to be separated from output directory
121
+ * Pass logical path and absolute path to each_logical_path iterator
122
+
123
+ **2.7.0** (October 10, 2012)
124
+
125
+ * Added --css-compressor and --js-compressor command line flags
126
+ * Added css/js compressor shorthand
127
+ * Change default manifest.json filename to be a randomized manifest-16HEXBYTES.json
128
+ * Allow nil environment to be passed to manifest
129
+ * Allow manifest instance to be set on rake task
130
+
131
+ **2.6.0** (September 19, 2012)
132
+
133
+ * Added bower component.json require support
134
+
135
+ **2.5.0** (September 4, 2012)
136
+
137
+ * Fixed Ruby 2.0 RegExp warning
138
+ * Provide stubbed implementation of context *_path helpers
139
+ * Add SassCompressor
140
+
141
+ **2.4.5** (July 10, 2012)
142
+
143
+ * Tweaked some logger levels
144
+
145
+ **2.4.4** (July 2, 2012)
146
+
147
+ * Canonicalize logical path extensions
148
+ * Check absolute paths passed to depend_on
149
+
150
+ **2.4.3** (May 16, 2012)
151
+
152
+ * Exposed :sprockets in sass options
153
+ * Include dependency paths in asset mtime
154
+
155
+ **2.4.2** (May 7, 2012)
156
+
157
+ * Fixed MultiJson feature detect
158
+
159
+ **2.4.1** (April 26, 2012)
160
+
161
+ * Fixed MultiJson API change
162
+ * Fixed gzip mtime
163
+
164
+ **2.4.0** (March 27, 2012)
165
+
166
+ * Added global path registry
167
+ * Added global processor registry
168
+
169
+ **2.3.2** (March 26, 2012)
170
+
171
+ * Fix Context#logical_path with dots
172
+
173
+ **2.3.1** (February 11, 2012)
174
+
175
+ * Added bytesize to manifest
176
+ * Added Asset#bytesize alias
177
+ * Security: Check path for forbidden access after unescaping
178
+
179
+ **2.3.0** (January 16, 2012)
180
+
181
+ * Added special Sass importer that automatically tracks any `@import`ed files.
182
+
183
+ **2.2.0** (January 10, 2012)
184
+
185
+ * Added `sprockets` command line utility.
186
+ * Added rake/sprocketstask.
187
+ * Added json manifest log of compiled assets.
188
+ * Added `stub` directive that allows you to exclude files from the bundle.
189
+ * Added per environment external encoding (Environment#default_external_encoding). Defaults to UTF-8. Fixes issues where LANG is not set correctly and Rubys default external is set to ASCII.
190
+
191
+ **2.1.2** (November 20, 2011)
192
+
193
+ * Disabled If-Modified-Since server checks. Fixes some browser caching issues when serving the asset body only. If-None-Match caching is sufficient.
194
+
195
+ **2.1.1** (November 18, 2011)
196
+
197
+ * Fix windows absolute path check bug.
198
+
199
+ **2.1.0** (November 11, 2011)
200
+
201
+ * Directive comment lines are now turned into empty lines instead of removed. This way line numbers in
202
+ CoffeeScript syntax errors are correct.
203
+ * Performance and caching bug fixes.
204
+
205
+ **2.0.3** (October 17, 2011)
206
+
207
+ * Detect format extensions from right to left.
208
+ * Make JST namespace configurable.
209
+
210
+ **2.0.2** (October 4, 2011)
211
+
212
+ * Fixed loading stale cache from bundler gems.
213
+
214
+ **2.0.1** (September 30, 2011)
215
+
216
+ * Fixed bug with fingerprinting file names with multiple dots.
217
+ * Decode URIs as default internal.
218
+ * Fix symlinked asset directories.
219
+
220
+ **2.0.0** (August 29, 2011)
221
+
222
+ * Initial public release.
@@ -10,6 +10,7 @@ require 'sprockets/path_dependency_utils'
10
10
  require 'sprockets/path_utils'
11
11
  require 'sprockets/resolve'
12
12
  require 'sprockets/server'
13
+ require 'sprockets/loader'
13
14
 
14
15
  module Sprockets
15
16
  # `Base` class for `Environment` and `Cached`.
@@ -48,9 +49,10 @@ module Sprockets
48
49
  # Caveat: Digests are cached by the path's current mtime. Its possible
49
50
  # for a files contents to have changed and its mtime to have been
50
51
  # negligently reset thus appearing as if the file hasn't changed on
51
- # disk. Also, the mtime is only read to the nearest second. Its
52
+ # disk. Also, the mtime is only read to the nearest second. It's
52
53
  # also possible the file was updated more than once in a given second.
53
- cache.fetch("file_digest:#{path}:#{stat.mtime.to_i}") do
54
+ key = UnloadedAsset.new(path, self).file_digest_key(stat.mtime.to_i)
55
+ cache.fetch(key) do
54
56
  self.stat_digest(path, stat)
55
57
  end
56
58
  end
@@ -51,18 +51,18 @@ module Sprockets
51
51
  end
52
52
  alias_method :depend_on, :add_dependency
53
53
 
54
- # Internal: Resolve set of dependency URIs.
55
- #
56
- # Returns Array of resolved Objects.
57
- def resolve_dependencies(uris)
58
- uris.map { |uri| resolve_dependency(uri) }
59
- end
60
-
61
54
  # Internal: Resolve dependency URIs.
62
55
  #
63
56
  # Returns resolved Object.
64
57
  def resolve_dependency(str)
65
- scheme = str[/([^:]+)/, 1]
58
+ # Optimize for the most common scheme to
59
+ # save 22k allocations on an average Spree app.
60
+ scheme = if str.start_with?('file-digest:'.freeze)
61
+ 'file-digest'.freeze
62
+ else
63
+ str[/([^:]+)/, 1]
64
+ end
65
+
66
66
  if resolver = config[:dependency_resolvers][scheme]
67
67
  resolver.call(self, str)
68
68
  else
@@ -66,7 +66,7 @@ module Sprockets
66
66
  elsif klass == FalseClass
67
67
  digest << 'FalseClass'
68
68
  elsif klass == NilClass
69
- digest << 'NilClass'
69
+ digest << 'NilClass'.freeze
70
70
  elsif klass == Array
71
71
  digest << 'Array'
72
72
  queue.concat(obj)
@@ -12,37 +12,198 @@ require 'sprockets/transformers'
12
12
  require 'sprockets/uri_utils'
13
13
 
14
14
  module Sprockets
15
+
16
+ # Internal: Used to parse and store the URI to an unloaded asset
17
+ # Generates keys used to store and retrieve items from cache
18
+ class UnloadedAsset
19
+
20
+ # Internal: Initialize object for generating cache keys
21
+ #
22
+ # uri - A String containing complete URI to a file including schema
23
+ # and full path such as
24
+ # "file:///Path/app/assets/js/app.js?type=application/javascript"
25
+ # env - The current "environment" that assets are being loaded into.
26
+ # We need it so we know where the +root+ (directory where sprockets
27
+ # is being invoked). We also need for the `file_digest` method,
28
+ # since, for some strange reason, memoization is provided by
29
+ # overriding methods such as `stat` in the `PathUtils` module.
30
+ #
31
+ # Returns UnloadedAsset.
32
+ def initialize(uri, env)
33
+ @uri = uri
34
+ @env = env
35
+ @root = env.root
36
+ @relative_path = get_relative_path_from_uri
37
+ @params = nil # lazy loaded
38
+ @filename = nil # lazy loaded
39
+ end
40
+ attr_reader :relative_path, :root, :uri
41
+
42
+
43
+ # Internal: Full file path without schema
44
+ #
45
+ # This returns a string containing the full path to the asset without the schema.
46
+ # Information is loaded lazilly since we want `UnloadedAsset.new(dep, self).relative_path`
47
+ # to be fast. Calling this method the first time allocates an array and a hash.
48
+ #
49
+ # Example
50
+ #
51
+ # If the URI is `file:///Full/path/app/assets/javascripts/application.js"` then the
52
+ # filename would be `"/Full/path/app/assets/javascripts/application.js"`
53
+ #
54
+ # Returns a String.
55
+ def filename
56
+ unless @filename
57
+ load_file_params
58
+ end
59
+ @filename
60
+ end
61
+
62
+ # Internal: Hash of param values
63
+ #
64
+ # This information is generated and used internally by sprockets.
65
+ # Known keys include `:type` which store the asset's mime-type, `:id` which is a fully resolved
66
+ # digest for the asset (includes dependency digest as opposed to a digest of only file contents)
67
+ # and `:pipeline`. Hash may be empty.
68
+ #
69
+ # Example
70
+ #
71
+ # If the URI is `file:///Full/path/app/assets/javascripts/application.js"type=application/javascript`
72
+ # Then the params would be `{type: "application/javascript"}`
73
+ #
74
+ # Returns a Hash.
75
+ def params
76
+ unless @params
77
+ load_file_params
78
+ end
79
+ @params
80
+ end
81
+
82
+ # Internal: Key of asset
83
+ #
84
+ # Used to retrieve an asset from the cache based on relative path to asset
85
+ #
86
+ # Returns a String.
87
+ def asset_key
88
+ "asset-uri:#{relative_path}"
89
+ end
90
+
91
+ # Public: Dependency History key
92
+ #
93
+ # Used to retrieve an array of "histories" each of which contain a set of stored dependencies
94
+ # for a given asset path and filename digest.
95
+ #
96
+ # A dependency can refer to either an asset i.e. index.js
97
+ # may rely on jquery.js (so jquery.js is a dependency), or other factors that may affect
98
+ # compilation, such as the VERSION of sprockets (i.e. the environment) and what "processors"
99
+ # are used.
100
+ #
101
+ # For example a history array with one Set of dependencies may look like:
102
+ #
103
+ # [["environment-version", "environment-paths", "processors:type=text/css&file_type=text/css",
104
+ # "file-digest:///Full/path/app/assets/stylesheets/application.css",
105
+ # "processors:type=text/css&file_type=text/css&pipeline=self",
106
+ # "file-digest:///Full/path/app/assets/stylesheets"]]
107
+ #
108
+ # This method of asset lookup is used to ensure that none of the dependencies have been modified
109
+ # since last lookup. If one of them has, the key will be different and a new entry must be stored.
110
+ #
111
+ # URI depndencies are later converted to relative paths
112
+ #
113
+ # Returns a String.
114
+ def dependency_history_key
115
+ "asset-uri-cache-dependencies:#{relative_path}:#{ @env.file_digest(filename) }"
116
+ end
117
+
118
+ # Internal: Digest key
119
+ #
120
+ # Used to retrieve a string containing the relative path to an asset based on
121
+ # a digest. The digest is generated from dependencies stored via information stored in
122
+ # the `dependency_history_key` after each of the "dependencies" is "resolved" for example
123
+ # "environment-version" may be resolved to "environment-1.0-3.2.0" for version "3.2.0" of sprockets
124
+ #
125
+ # Returns a String.
126
+ def digest_key(digest)
127
+ "asset-uri-digest:#{relative_path}:#{digest}"
128
+ end
129
+
130
+ # Internal: File digest key
131
+ #
132
+ # The digest for a given file won't change if the path and the stat time hasn't changed
133
+ # We can save time by not re-computing this information and storing it in the cache
134
+ #
135
+ # Returns a String.
136
+ def file_digest_key(stat)
137
+ "file_digest:#{relative_path}:#{stat}"
138
+ end
139
+
140
+ private
141
+ # Internal: Parses uri into filename and params hash
142
+ #
143
+ # Returns Array with filename and params hash
144
+ def load_file_params
145
+ @filename, @params = URIUtils.parse_asset_uri(uri)
146
+ end
147
+
148
+ # Internal: Converts uri to a relative path
149
+ #
150
+ # Returns a relative path if given URI is in the `@env.root` of where sprockets
151
+ # is running. Otherwise it returns a string of the absolute path
152
+ #
153
+ # Returns a String.
154
+ def get_relative_path_from_uri
155
+ path = uri.sub(/\Afile:\/\//, "".freeze)
156
+ if relative_path = PathUtils.split_subpath(root, path)
157
+ relative_path
158
+ else
159
+ path
160
+ end
161
+ end
162
+ end
15
163
  # The loader phase takes a asset URI location and returns a constructed Asset
16
164
  # object.
17
165
  module Loader
18
166
  include DigestUtils, PathUtils, ProcessorUtils, URIUtils
19
167
  include Engines, Mime, Processing, Resolve, Transformers
20
168
 
21
- # Public: Load Asset by AssetURI.
169
+
170
+ # Public: Load Asset by Asset URI.
171
+ #
172
+ # uri - A String containing complete URI to a file including schema
173
+ # and full path such as:
174
+ # "file:///Path/app/assets/js/app.js?type=application/javascript"
22
175
  #
23
- # uri - AssetURI
24
176
  #
25
177
  # Returns Asset.
26
178
  def load(uri)
27
- filename, params = parse_asset_uri(uri)
28
- if params.key?(:id)
29
- unless asset = cache.get("asset-uri:#{VERSION}:#{uri}", true)
30
- id = params.delete(:id)
31
- uri_without_id = build_asset_uri(filename, params)
32
- asset = load_asset_by_uri(uri_without_id, filename, params)
179
+ unloaded = UnloadedAsset.new(uri, self)
180
+ if unloaded.params.key?(:id)
181
+ unless asset = cache.get(unloaded.asset_key, true)
182
+ id = unloaded.params.delete(:id)
183
+ uri_without_id = build_asset_uri(unloaded.filename, unloaded.params)
184
+ asset = load_from_unloaded(UnloadedAsset.new(uri_without_id, self))
33
185
  if asset[:id] != id
34
186
  @logger.warn "Sprockets load error: Tried to find #{uri}, but latest was id #{asset[:id]}"
35
187
  end
36
188
  end
37
189
  else
38
- asset = fetch_asset_from_dependency_cache(uri, filename) do |paths|
190
+ asset = fetch_asset_from_dependency_cache(unloaded) do |paths|
191
+ # When asset is previously generated, its "dependencies" are stored in the cache.
192
+ # The presence of `paths` indicates dependencies were stored.
193
+ # We can check to see if the dependencies have not changed by "resolving" them and
194
+ # generating a digest key from the resolved entries. If this digest key has not
195
+ # changed the asset will be pulled from cache.
196
+ #
197
+ # If this `paths` is present but the cache returns nothing then `fetch_asset_from_dependency_cache`
198
+ # will confusingly be called again with `paths` set to nil where the asset will be
199
+ # loaded from disk.
39
200
  if paths
40
- digest = digest(resolve_dependencies(paths))
41
- if id_uri = cache.get("asset-uri-digest:#{VERSION}:#{uri}:#{digest}", true)
42
- cache.get("asset-uri:#{VERSION}:#{id_uri}", true)
201
+ digest = DigestUtils.digest(resolve_dependencies(paths))
202
+ if uri_from_cache = cache.get(unloaded.digest_key(digest), true)
203
+ cache.get(UnloadedAsset.new(uri_from_cache, self).asset_key, true)
43
204
  end
44
205
  else
45
- load_asset_by_uri(uri, filename, params)
206
+ load_from_unloaded(unloaded)
46
207
  end
47
208
  end
48
209
  end
@@ -50,25 +211,32 @@ module Sprockets
50
211
  end
51
212
 
52
213
  private
53
- def load_asset_by_uri(uri, filename, params)
54
- unless file?(filename)
55
- raise FileNotFound, "could not find file: #{filename}"
214
+
215
+ # Internal: Loads an asset and saves it to cache
216
+ #
217
+ # unloaded - An UnloadedAsset
218
+ #
219
+ # This method is only called when the given unloaded asset could not be
220
+ # successfully pulled from cache.
221
+ def load_from_unloaded(unloaded)
222
+ unless file?(unloaded.filename)
223
+ raise FileNotFound, "could not find file: #{unloaded.filename}"
56
224
  end
57
225
 
58
- load_path, logical_path = paths_split(config[:paths], filename)
226
+ load_path, logical_path = paths_split(config[:paths], unloaded.filename)
59
227
 
60
228
  unless load_path
61
- raise FileOutsidePaths, "#{filename} is no longer under a load path: #{self.paths.join(', ')}"
229
+ raise FileOutsidePaths, "#{unloaded.filename} is no longer under a load path: #{self.paths.join(', ')}"
62
230
  end
63
231
 
64
232
  logical_path, file_type, engine_extnames, _ = parse_path_extnames(logical_path)
65
233
  name = logical_path
66
234
 
67
- if pipeline = params[:pipeline]
235
+ if pipeline = unloaded.params[:pipeline]
68
236
  logical_path += ".#{pipeline}"
69
237
  end
70
238
 
71
- if type = params[:type]
239
+ if type = unloaded.params[:type]
72
240
  logical_path += config[:mime_types][type][:extensions].first
73
241
  end
74
242
 
@@ -86,8 +254,8 @@ module Sprockets
86
254
  result = call_processors(processors, {
87
255
  environment: self,
88
256
  cache: self.cache,
89
- uri: uri,
90
- filename: filename,
257
+ uri: unloaded.uri,
258
+ filename: unloaded.filename,
91
259
  load_path: load_path,
92
260
  name: name,
93
261
  content_type: type,
@@ -101,28 +269,28 @@ module Sprockets
101
269
  length: source.bytesize
102
270
  )
103
271
  else
104
- dependencies << build_file_digest_uri(filename)
272
+ dependencies << build_file_digest_uri(unloaded.filename)
105
273
  metadata = {
106
- digest: file_digest(filename),
107
- length: self.stat(filename).size,
274
+ digest: file_digest(unloaded.filename),
275
+ length: self.stat(unloaded.filename).size,
108
276
  dependencies: dependencies
109
277
  }
110
278
  end
111
279
 
112
280
  asset = {
113
- uri: uri,
281
+ uri: unloaded.uri,
114
282
  load_path: load_path,
115
- filename: filename,
283
+ filename: unloaded.filename,
116
284
  name: name,
117
285
  logical_path: logical_path,
118
286
  content_type: type,
119
287
  source: source,
120
288
  metadata: metadata,
121
- dependencies_digest: digest(resolve_dependencies(metadata[:dependencies]))
289
+ dependencies_digest: DigestUtils.digest(resolve_dependencies(metadata[:dependencies]))
122
290
  }
123
291
 
124
292
  asset[:id] = pack_hexdigest(digest(asset))
125
- asset[:uri] = build_asset_uri(filename, params.merge(id: asset[:id]))
293
+ asset[:uri] = build_asset_uri(unloaded.filename, unloaded.params.merge(id: asset[:id]))
126
294
 
127
295
  # Deprecated: Avoid tracking Asset mtime
128
296
  asset[:mtime] = metadata[:dependencies].map { |u|
@@ -133,18 +301,92 @@ module Sprockets
133
301
  nil
134
302
  end
135
303
  }.compact.max
136
- asset[:mtime] ||= self.stat(filename).mtime.to_i
304
+ asset[:mtime] ||= self.stat(unloaded.filename).mtime.to_i
137
305
 
138
- cache.set("asset-uri:#{VERSION}:#{asset[:uri]}", asset, true)
139
- cache.set("asset-uri-digest:#{VERSION}:#{uri}:#{asset[:dependencies_digest]}", asset[:uri], true)
306
+ # Unloaded asset and stored_asset now have a different URI
307
+ stored_asset = UnloadedAsset.new(asset[:uri], self)
308
+
309
+ # Save the asset in the cache under the new URI
310
+ cache.set(stored_asset.asset_key, asset, true)
311
+
312
+ # Save the new relative path for the digest key of the unloaded asset
313
+ cache.set(unloaded.digest_key(asset[:dependencies_digest]), stored_asset.relative_path, true) # wat
140
314
 
141
315
  asset
142
316
  end
143
317
 
144
- def fetch_asset_from_dependency_cache(uri, filename, limit = 3)
145
- key = "asset-uri-cache-dependencies:#{VERSION}:#{uri}:#{file_digest(filename)}"
146
- history = cache.get(key) || []
147
318
 
319
+ # Internal: Resolve set of dependency URIs.
320
+ #
321
+ # uris - An Array of "dependencies" for example:
322
+ # ["environment-version", "environment-paths", "processors:type=text/css&file_type=text/css",
323
+ # "file-digest:///Full/path/app/assets/stylesheets/application.css",
324
+ # "processors:type=text/css&file_type=text/css&pipeline=self",
325
+ # "file-digest:///Full/path/app/assets/stylesheets"]
326
+ #
327
+ # Returns back array of things that the given uri dpends on
328
+ # For example the environment version, if you're using a different version of sprockets
329
+ # then the dependencies should be different, this is used only for generating cache key
330
+ # for example the "environment-version" may be resolved to "environment-1.0-3.2.0" for
331
+ # version "3.2.0" of sprockets.
332
+ #
333
+ # Any paths that are returned are converted to relative paths
334
+ #
335
+ # Returns array of resolved dependencies
336
+ def resolve_dependencies(uris)
337
+ uris.map do |uri|
338
+ dependency = resolve_dependency(uri)
339
+ case dependency
340
+ when Array
341
+ dependency.map do |dep|
342
+ if dep && dep.is_a?(String)
343
+ UnloadedAsset.new(dep, self).relative_path
344
+ else
345
+ dep
346
+ end
347
+ end
348
+ else
349
+ dependency
350
+ end
351
+ end
352
+ end
353
+
354
+ # Internal: Retrieves an asset based on its digest
355
+ #
356
+ # unloaded - An UnloadedAsset
357
+ # limit - A Fixnum which sets the maximum number of versions of "histories"
358
+ # stored in the cache
359
+ #
360
+ # This method attempts to retrieve the last `limit` number of histories of an asset
361
+ # from the cache a "history" which is an array of unresolved "dependencies" that the asset needs
362
+ # to compile. In this case A dependency can refer to either an asset i.e. index.js
363
+ # may rely on jquery.js (so jquery.js is a depndency), or other factors that may affect
364
+ # compilation, such as the VERSION of sprockets (i.e. the environment) and what "processors"
365
+ # are used.
366
+ #
367
+ # For example a history array may look something like this
368
+ #
369
+ # [["environment-version", "environment-paths", "processors:type=text/css&file_type=text/css",
370
+ # "file-digest:///Full/path/app/assets/stylesheets/application.css",
371
+ # "processors:type=text/css&file_type=text/css&pipeline=self",
372
+ # "file-digest:///Full/path/app/assets/stylesheets"]]
373
+ #
374
+ # Where the first entry is a Set of dependencies for last generated version of that asset.
375
+ # Multiple versions are stored since sprockets keeps the last `limit` number of assets
376
+ # generated present in the system.
377
+ #
378
+ # If a "history" of dependencies is present in the cache, each version of "history" will be
379
+ # yielded to the passed block which is responsible for loading the asset. If found, the existing
380
+ # history will be saved with the dependency that found a valid asset moved to the front.
381
+ #
382
+ # If no history is present, or if none of the histories could be resolved to a valid asset then,
383
+ # the block is yielded to and expected to return a valid asset.
384
+ # When this happens the dependencies for the returned asset are added to the "history", and older
385
+ # entries are removed if the "history" is above `limit`.
386
+ def fetch_asset_from_dependency_cache(unloaded, limit = 3)
387
+ key = unloaded.dependency_history_key
388
+
389
+ history = cache.get(key) || []
148
390
  history.each_with_index do |deps, index|
149
391
  if asset = yield(deps)
150
392
  cache.set(key, history.rotate!(index)) if index > 0
@@ -48,7 +48,7 @@ module Sprockets
48
48
  path.force_encoding(Encoding::UTF_8)
49
49
 
50
50
  # Hack for parsing Windows "file:///C:/Users/IEUser" paths
51
- path.gsub!(/^\/([a-zA-Z]:)/, '\1')
51
+ path.gsub!(/^\/([a-zA-Z]:)/, '\1'.freeze)
52
52
 
53
53
  [scheme, host, path, query]
54
54
  end
@@ -125,7 +125,7 @@ module Sprockets
125
125
  def parse_file_digest_uri(uri)
126
126
  scheme, _, path, _ = split_file_uri(uri)
127
127
 
128
- unless scheme == 'file-digest'
128
+ unless scheme == 'file-digest'.freeze
129
129
  raise URI::InvalidURIError, "expected file-digest scheme: #{uri}"
130
130
  end
131
131
 
@@ -143,7 +143,7 @@ module Sprockets
143
143
  #
144
144
  # Returns String URI.
145
145
  def build_file_digest_uri(path)
146
- join_file_uri("file-digest", nil, path, nil)
146
+ join_file_uri('file-digest'.freeze, nil, path, nil)
147
147
  end
148
148
 
149
149
  # Internal: Serialize hash of params into query string.
@@ -1,3 +1,3 @@
1
1
  module Sprockets
2
- VERSION = "3.2.0"
2
+ VERSION = "3.3.0"
3
3
  end
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.2.0
4
+ version: 3.3.0
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: 2015-06-02 00:00:00.000000000 Z
12
+ date: 2015-08-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -217,6 +217,7 @@ executables:
217
217
  extensions: []
218
218
  extra_rdoc_files: []
219
219
  files:
220
+ - CHANGELOG.md
220
221
  - LICENSE
221
222
  - README.md
222
223
  - bin/sprockets
@@ -313,3 +314,4 @@ signing_key:
313
314
  specification_version: 4
314
315
  summary: Rack-based asset packaging system
315
316
  test_files: []
317
+ has_rdoc: