sprockets-rails 2.3.2 → 3.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,128 +1,132 @@
1
1
  require 'action_view'
2
2
  require 'sprockets'
3
3
  require 'active_support/core_ext/class/attribute'
4
+ require 'sprockets/rails/utils'
4
5
 
5
6
  module Sprockets
6
7
  module Rails
7
8
  module Helper
8
- class << self
9
- attr_accessor :precompile, :assets, :raise_runtime_errors
10
- end
11
-
12
- def precompile
13
- Sprockets::Rails::Helper.precompile
14
- end
15
-
16
- def assets
17
- Sprockets::Rails::Helper.assets
18
- end
19
-
20
- def raise_runtime_errors
21
- Sprockets::Rails::Helper.raise_runtime_errors
22
- end
9
+ class AssetNotFound < StandardError; end
10
+ class AssetNotPrecompiled < StandardError; end
23
11
 
24
- class AssetFilteredError < StandardError
12
+ class AssetNotPrecompiledError < AssetNotPrecompiled
13
+ include Sprockets::Rails::Utils
25
14
  def initialize(source)
26
- msg = "Asset filtered out and will not be served: " <<
27
- "add `Rails.application.config.assets.precompile += %w( #{source} )` " <<
28
- "to `config/initializers/assets.rb` and restart your server"
29
- super(msg)
30
- end
31
- end
32
-
33
- class AbsoluteAssetPathError < ArgumentError
34
- def initialize(bad_path, good_path, prefix)
35
- msg = "Asset names passed to helpers should not include the #{prefix.inspect} prefix. " <<
36
- "Instead of #{bad_path.inspect}, use #{good_path.inspect}"
15
+ msg =
16
+ if using_sprockets4?
17
+ "Asset `#{ source }` was not declared to be precompiled in production.\n" +
18
+ "Declare links to your assets in `app/assets/config/manifest.js`.\n\n" +
19
+ " //= link #{ source }\n\n" +
20
+ "and restart your server"
21
+ else
22
+ "Asset was not declared to be precompiled in production.\n" +
23
+ "Add `Rails.application.config.assets.precompile += " +
24
+ "%w( #{source} )` to `config/initializers/assets.rb` and " +
25
+ "restart your server"
26
+ end
37
27
  super(msg)
38
28
  end
39
29
  end
40
30
 
41
- if defined? ActionView::Helpers::AssetUrlHelper
42
- include ActionView::Helpers::AssetUrlHelper
43
- include ActionView::Helpers::AssetTagHelper
44
- else
45
- require 'sprockets/rails/legacy_asset_tag_helper'
46
- require 'sprockets/rails/legacy_asset_url_helper'
47
- include LegacyAssetTagHelper
48
- include LegacyAssetUrlHelper
49
- end
31
+ include ActionView::Helpers::AssetUrlHelper
32
+ include ActionView::Helpers::AssetTagHelper
33
+ include Sprockets::Rails::Utils
50
34
 
51
- VIEW_ACCESSORS = [:assets_environment, :assets_manifest,
52
- :assets_prefix, :digest_assets, :debug_assets]
35
+ VIEW_ACCESSORS = [
36
+ :assets_environment, :assets_manifest,
37
+ :assets_precompile, :precompiled_asset_checker,
38
+ :assets_prefix, :digest_assets, :debug_assets,
39
+ :resolve_assets_with, :check_precompiled_asset,
40
+ :unknown_asset_fallback
41
+ ]
53
42
 
54
43
  def self.included(klass)
55
- if klass < Sprockets::Context
56
- klass.class_eval do
57
- alias_method :assets_environment, :environment
58
- def assets_manifest; end
59
- class_attribute :config, :assets_prefix, :digest_assets, :debug_assets
44
+ klass.class_attribute(*VIEW_ACCESSORS)
45
+
46
+ klass.class_eval do
47
+ remove_method :assets_environment
48
+ def assets_environment
49
+ if instance_variable_defined?(:@assets_environment)
50
+ @assets_environment = @assets_environment.cached
51
+ elsif env = self.class.assets_environment
52
+ @assets_environment = env.cached
53
+ else
54
+ nil
55
+ end
60
56
  end
61
- else
62
- klass.class_attribute(*VIEW_ACCESSORS)
63
57
  end
64
58
  end
65
59
 
66
60
  def self.extended(obj)
67
- obj.class_eval do
61
+ obj.singleton_class.class_eval do
68
62
  attr_accessor(*VIEW_ACCESSORS)
63
+
64
+ remove_method :assets_environment
65
+ def assets_environment
66
+ if env = @assets_environment
67
+ @assets_environment = env.cached
68
+ else
69
+ nil
70
+ end
71
+ end
69
72
  end
70
73
  end
71
74
 
75
+ # Writes over the built in ActionView::Helpers::AssetUrlHelper#compute_asset_path
76
+ # to use the asset pipeline.
72
77
  def compute_asset_path(path, options = {})
73
- # Check if we are inside Sprockets context before calling check_dependencies!.
74
- check_dependencies!(path) if defined?(depend_on)
78
+ debug = options[:debug]
75
79
 
76
- if digest_path = asset_digest_path(path)
77
- path = digest_path if digest_assets
78
- path += "?body=1" if options[:debug]
79
- File.join(assets_prefix || "/", path)
80
+ if asset_path = resolve_asset_path(path, debug)
81
+ File.join(assets_prefix || "/", legacy_debug_path(asset_path, debug))
80
82
  else
83
+ message = "The asset #{ path.inspect } is not present in the asset pipeline.\n"
84
+ raise AssetNotFound, message unless unknown_asset_fallback
85
+
86
+ if respond_to?(:public_compute_asset_path)
87
+ message << "Falling back to an asset that may be in the public folder.\n"
88
+ message << "This behavior is deprecated and will be removed.\n"
89
+ message << "To bypass the asset pipeline and preserve this behavior,\n"
90
+ message << "use the `skip_pipeline: true` option.\n"
91
+
92
+ call_stack = Kernel.respond_to?(:caller_locations) && ::Rails::VERSION::MAJOR >= 5 ? caller_locations : caller
93
+ ActiveSupport::Deprecation.warn(message, call_stack)
94
+ end
81
95
  super
82
96
  end
83
97
  end
84
98
 
85
- # Computes the full URL to a asset in the public directory. This
86
- # method checks for errors before returning path.
87
- def asset_path(source, options = {})
88
- unless options[:debug]
89
- check_errors_for(source, options)
99
+ # Resolve the asset path against the Sprockets manifest or environment.
100
+ # Returns nil if it's an asset we don't know about.
101
+ def resolve_asset_path(path, allow_non_precompiled = false) #:nodoc:
102
+ resolve_asset do |resolver|
103
+ resolver.asset_path path, digest_assets, allow_non_precompiled
90
104
  end
91
- super(source, options)
92
105
  end
93
- alias :path_to_asset :asset_path
94
106
 
95
- # Get digest for asset path.
107
+ # Expand asset path to digested form.
96
108
  #
97
109
  # path - String path
98
110
  # options - Hash options
99
111
  #
100
- # Returns String Hex digest or nil if digests are disabled.
101
- def asset_digest(path, options = {})
102
- return unless digest_assets
103
-
104
- if digest_path = asset_digest_path(path, options)
105
- digest_path[/-(.+)\./, 1]
112
+ # Returns String path or nil if no asset was found.
113
+ def asset_digest_path(path, options = {})
114
+ resolve_asset do |resolver|
115
+ resolver.digest_path path, options[:debug]
106
116
  end
107
117
  end
108
118
 
109
- # Expand asset path to digested form.
119
+ # Experimental: Get integrity for asset path.
110
120
  #
111
121
  # path - String path
112
122
  # options - Hash options
113
123
  #
114
- # Returns String path or nil if no asset was found.
115
- def asset_digest_path(path, options = {})
116
- if manifest = assets_manifest
117
- if digest_path = manifest.assets[path]
118
- return digest_path
119
- end
120
- end
124
+ # Returns String integrity attribute or nil if no asset was found.
125
+ def asset_integrity(path, options = {})
126
+ path = path_with_extname(path, options)
121
127
 
122
- if environment = assets_environment
123
- if asset = environment[path]
124
- return asset.digest_path
125
- end
128
+ resolve_asset do |resolver|
129
+ resolver.integrity path
126
130
  end
127
131
  end
128
132
 
@@ -131,21 +135,27 @@ module Sprockets
131
135
  # Eventually will be deprecated and replaced by source maps.
132
136
  def javascript_include_tag(*sources)
133
137
  options = sources.extract_options!.stringify_keys
138
+ integrity = compute_integrity?(options)
134
139
 
135
140
  if options["debug"] != false && request_debug_assets?
136
141
  sources.map { |source|
137
- check_errors_for(source, :type => :javascript)
138
- if asset = lookup_asset_for_path(source, :type => :javascript)
139
- asset.to_a.map do |a|
140
- super(path_to_javascript(a.logical_path, :debug => true), options)
142
+ if asset = lookup_debug_asset(source, type: :javascript)
143
+ if asset.respond_to?(:to_a)
144
+ asset.to_a.map do |a|
145
+ super(path_to_javascript(a.logical_path, debug: true), options)
146
+ end
147
+ else
148
+ super(path_to_javascript(asset.logical_path, debug: true), options)
141
149
  end
142
150
  else
143
151
  super(source, options)
144
152
  end
145
153
  }.flatten.uniq.join("\n").html_safe
146
154
  else
147
- sources.push(options)
148
- super(*sources)
155
+ sources.map { |source|
156
+ options = options.merge('integrity' => asset_integrity(source, type: :javascript)) if integrity
157
+ super source, options
158
+ }.join("\n").html_safe
149
159
  end
150
160
  end
151
161
 
@@ -154,81 +164,214 @@ module Sprockets
154
164
  # Eventually will be deprecated and replaced by source maps.
155
165
  def stylesheet_link_tag(*sources)
156
166
  options = sources.extract_options!.stringify_keys
167
+ integrity = compute_integrity?(options)
168
+
157
169
  if options["debug"] != false && request_debug_assets?
158
170
  sources.map { |source|
159
- check_errors_for(source, :type => :stylesheet)
160
- if asset = lookup_asset_for_path(source, :type => :stylesheet)
161
- asset.to_a.map do |a|
162
- super(path_to_stylesheet(a.logical_path, :debug => true), options)
171
+ if asset = lookup_debug_asset(source, type: :stylesheet)
172
+ if asset.respond_to?(:to_a)
173
+ asset.to_a.map do |a|
174
+ super(path_to_stylesheet(a.logical_path, debug: true), options)
175
+ end
176
+ else
177
+ super(path_to_stylesheet(asset.logical_path, debug: true), options)
163
178
  end
164
179
  else
165
180
  super(source, options)
166
181
  end
167
182
  }.flatten.uniq.join("\n").html_safe
168
183
  else
169
- sources.push(options)
170
- super(*sources)
184
+ sources.map { |source|
185
+ options = options.merge('integrity' => asset_integrity(source, type: :stylesheet)) if integrity
186
+ super source, options
187
+ }.join("\n").html_safe
171
188
  end
172
189
  end
173
190
 
174
191
  protected
175
- # Ensures the asset is included in the dependencies list.
176
- def check_dependencies!(dep)
177
- depend_on(dep)
178
- depend_on_asset(dep)
179
- rescue Sprockets::FileNotFound
192
+ # This is awkward: `integrity` is a boolean option indicating whether
193
+ # we want to include or omit the subresource integrity hash, but the
194
+ # options hash is also passed through as literal tag attributes.
195
+ # That means we have to delete the shortcut boolean option so it
196
+ # doesn't bleed into the tag attributes, but also check its value if
197
+ # it's boolean-ish.
198
+ def compute_integrity?(options)
199
+ if secure_subresource_integrity_context?
200
+ case options['integrity']
201
+ when nil, false, true
202
+ options.delete('integrity') == true
203
+ end
204
+ else
205
+ options.delete 'integrity'
206
+ false
207
+ end
180
208
  end
181
209
 
182
- # Raise errors when source is not in the precompiled list, or
183
- # incorrectly contains the assets_prefix.
184
- def check_errors_for(source, options)
185
- return unless self.raise_runtime_errors
210
+ # Only serve integrity metadata for HTTPS requests:
211
+ # http://www.w3.org/TR/SRI/#non-secure-contexts-remain-non-secure
212
+ def secure_subresource_integrity_context?
213
+ respond_to?(:request) && self.request && (self.request.local? || self.request.ssl?)
214
+ end
186
215
 
187
- source = source.to_s
188
- return if source.blank? || source =~ URI_REGEXP
216
+ # Enable split asset debugging. Eventually will be deprecated
217
+ # and replaced by source maps in Sprockets 3.x.
218
+ def request_debug_assets?
219
+ debug_assets || (defined?(controller) && controller && params[:debug_assets])
220
+ rescue # FIXME: what exactly are we rescuing?
221
+ false
222
+ end
189
223
 
190
- asset = lookup_asset_for_path(source, options)
224
+ # Internal method to support multifile debugging. Will
225
+ # eventually be removed w/ Sprockets 3.x.
226
+ def lookup_debug_asset(path, options = {})
227
+ path = path_with_extname(path, options)
191
228
 
192
- if asset && asset_needs_precompile?(asset.logical_path, asset.pathname.to_s)
193
- raise AssetFilteredError.new(asset.logical_path)
229
+ resolve_asset do |resolver|
230
+ resolver.find_debug_asset path
194
231
  end
232
+ end
195
233
 
196
- full_prefix = File.join(self.assets_prefix || "/", '')
197
- if !asset && source.start_with?(full_prefix)
198
- short_path = source[full_prefix.size, source.size]
199
- if lookup_asset_for_path(short_path, options)
200
- raise AbsoluteAssetPathError.new(source, short_path, full_prefix)
234
+ # compute_asset_extname is in AV::Helpers::AssetUrlHelper
235
+ def path_with_extname(path, options)
236
+ path = path.to_s
237
+ "#{path}#{compute_asset_extname(path, options)}"
238
+ end
239
+
240
+ # Try each asset resolver and return the first non-nil result.
241
+ def resolve_asset
242
+ asset_resolver_strategies.detect do |resolver|
243
+ if result = yield(resolver)
244
+ break result
201
245
  end
202
246
  end
203
247
  end
204
248
 
205
- # Returns true when an asset will not be available after precompile is run
206
- def asset_needs_precompile?(source, filename)
207
- if assets_environment && assets_environment.send(:matches_filter, precompile || [], source, filename)
208
- false
249
+ # List of resolvers in `config.assets.resolve_with` order.
250
+ def asset_resolver_strategies
251
+ @asset_resolver_strategies ||=
252
+ Array(resolve_assets_with).map do |name|
253
+ HelperAssetResolvers[name].new(self)
254
+ end
255
+ end
256
+
257
+ # Append ?body=1 if debug is on and we're on old Sprockets.
258
+ def legacy_debug_path(path, debug)
259
+ if debug && !using_sprockets4?
260
+ "#{path}?body=1"
209
261
  else
210
- true
262
+ path
211
263
  end
212
264
  end
265
+ end
213
266
 
214
- # Enable split asset debugging. Eventually will be deprecated
215
- # and replaced by source maps in Sprockets 3.x.
216
- def request_debug_assets?
217
- debug_assets || (defined?(controller) && controller && params[:debug_assets])
218
- rescue
219
- return false
267
+ # Use a separate module since Helper is mixed in and we needn't pollute
268
+ # the class namespace with our internals.
269
+ module HelperAssetResolvers #:nodoc:
270
+ def self.[](name)
271
+ case name
272
+ when :manifest
273
+ Manifest
274
+ when :environment
275
+ Environment
276
+ else
277
+ raise ArgumentError, "Unrecognized asset resolver: #{name.inspect}. Expected :manifest or :environment"
220
278
  end
279
+ end
221
280
 
222
- # Internal method to support multifile debugging. Will
223
- # eventually be removed w/ Sprockets 3.x.
224
- def lookup_asset_for_path(path, options = {})
225
- return unless env = assets_environment
226
- path = path.to_s
227
- if extname = compute_asset_extname(path, options)
228
- path = "#{path}#{extname}"
281
+ class Manifest #:nodoc:
282
+ def initialize(view)
283
+ @manifest = view.assets_manifest
284
+ raise ArgumentError, 'config.assets.resolve_with includes :manifest, but app.assets_manifest is nil' unless @manifest
285
+ end
286
+
287
+ def asset_path(path, digest, allow_non_precompiled = false)
288
+ if digest
289
+ digest_path path, allow_non_precompiled
290
+ end
291
+ end
292
+
293
+ def digest_path(path, allow_non_precompiled = false)
294
+ @manifest.assets[path]
295
+ end
296
+
297
+ def integrity(path)
298
+ if meta = metadata(path)
299
+ meta["integrity"]
300
+ end
301
+ end
302
+
303
+ def find_debug_asset(path)
304
+ nil
305
+ end
306
+
307
+ private
308
+ def metadata(path)
309
+ if digest_path = digest_path(path)
310
+ @manifest.files[digest_path]
311
+ end
312
+ end
313
+ end
314
+
315
+ class Environment #:nodoc:
316
+ def initialize(view)
317
+ raise ArgumentError, 'config.assets.resolve_with includes :environment, but app.assets is nil' unless view.assets_environment
318
+ @env = view.assets_environment
319
+ @precompiled_asset_checker = view.precompiled_asset_checker
320
+ @check_precompiled_asset = view.check_precompiled_asset
321
+ end
322
+
323
+ def asset_path(path, digest, allow_non_precompiled = false)
324
+ # Digests enabled? Do the work to calculate the full asset path.
325
+ if digest
326
+ digest_path path, allow_non_precompiled
327
+
328
+ # Otherwise, ask the Sprockets environment whether the asset exists
329
+ # and check whether it's also precompiled for production deploys.
330
+ elsif asset = find_asset(path)
331
+ raise_unless_precompiled_asset asset.logical_path unless allow_non_precompiled
332
+ path
333
+ end
334
+ end
335
+
336
+ def digest_path(path, allow_non_precompiled = false)
337
+ if asset = find_asset(path)
338
+ raise_unless_precompiled_asset asset.logical_path unless allow_non_precompiled
339
+ asset.digest_path
340
+ end
341
+ end
342
+
343
+ def integrity(path)
344
+ find_asset(path).try :integrity
345
+ end
346
+
347
+ def find_debug_asset(path)
348
+ if asset = find_asset(path, pipeline: :debug)
349
+ raise_unless_precompiled_asset asset.logical_path.sub('.debug', '')
350
+ asset
229
351
  end
230
- env[path]
231
352
  end
353
+
354
+ private
355
+ if RUBY_VERSION >= "2.7"
356
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
357
+ def find_asset(path, options = {})
358
+ @env[path, **options]
359
+ end
360
+ RUBY
361
+ else
362
+ def find_asset(path, options = {})
363
+ @env[path, options]
364
+ end
365
+ end
366
+
367
+ def precompiled?(path)
368
+ @precompiled_asset_checker.call path
369
+ end
370
+
371
+ def raise_unless_precompiled_asset(path)
372
+ raise Helper::AssetNotPrecompiledError.new(path) if @check_precompiled_asset && !precompiled?(path)
373
+ end
374
+ end
232
375
  end
233
376
  end
234
377
  end
@@ -0,0 +1,18 @@
1
+ module Sprockets
2
+ module Rails
3
+ class QuietAssets
4
+ def initialize(app)
5
+ @app = app
6
+ @assets_regex = %r(\A/{0,2}#{::Rails.application.config.assets.prefix})
7
+ end
8
+
9
+ def call(env)
10
+ if env['PATH_INFO'] =~ @assets_regex
11
+ ::Rails.logger.silence { @app.call(env) }
12
+ else
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ module Sprockets
2
+ module Rails
3
+ module RouteWrapper
4
+
5
+ def internal_assets_path?
6
+ path =~ %r{\A#{self.class.assets_prefix}\z}
7
+ end
8
+
9
+ def internal?
10
+ super || internal_assets_path?
11
+ end
12
+
13
+ def self.included(klass)
14
+ klass.class_eval do
15
+ def internal_with_sprockets?
16
+ internal_without_sprockets? || internal_assets_path?
17
+ end
18
+ alias_method_chain :internal?, :sprockets
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,54 @@
1
+ module Sprockets
2
+ module Rails
3
+ # Rewrites source mapping urls with the digested paths and protect against semicolon appending with a dummy comment line
4
+ class SourcemappingUrlProcessor
5
+ REGEX = /\/\/# sourceMappingURL=(.*\.map)/
6
+
7
+ class << self
8
+ def call(input)
9
+ env = input[:environment]
10
+ context = env.context_class.new(input)
11
+ data = input[:data].gsub(REGEX) do |_match|
12
+ sourcemap_logical_path = combine_sourcemap_logical_path(sourcefile: input[:name], sourcemap: $1)
13
+
14
+ begin
15
+ resolved_sourcemap_comment(sourcemap_logical_path, context: context)
16
+ rescue Sprockets::FileNotFound
17
+ removed_sourcemap_comment(sourcemap_logical_path, filename: input[:filename], env: env)
18
+ end
19
+ end
20
+
21
+ { data: data }
22
+ end
23
+
24
+ private
25
+ def combine_sourcemap_logical_path(sourcefile:, sourcemap:)
26
+ if (parts = sourcefile.split("/")).many?
27
+ parts[0..-2].append(sourcemap).join("/")
28
+ else
29
+ sourcemap
30
+ end
31
+ end
32
+
33
+ def resolved_sourcemap_comment(sourcemap_logical_path, context:)
34
+ "//# sourceMappingURL=#{sourcemap_asset_path(sourcemap_logical_path, context: context)}\n//!\n"
35
+ end
36
+
37
+ def sourcemap_asset_path(sourcemap_logical_path, context:)
38
+ # FIXME: Work-around for bug where if the sourcemap is nested two levels deep, it'll resolve as the source file
39
+ # that's being mapped, rather than the map itself. So context.resolve("a/b/c.js.map") will return "c.js?"
40
+ if context.resolve(sourcemap_logical_path) =~ /\.map/
41
+ context.asset_path(sourcemap_logical_path)
42
+ else
43
+ raise Sprockets::FileNotFound, "Failed to resolve source map asset due to nesting depth"
44
+ end
45
+ end
46
+
47
+ def removed_sourcemap_comment(sourcemap_logical_path, filename:, env:)
48
+ env.logger.warn "Removed sourceMappingURL comment for missing asset '#{sourcemap_logical_path}' from #{filename}"
49
+ nil
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -2,7 +2,6 @@ require 'rake'
2
2
  require 'rake/sprocketstask'
3
3
  require 'sprockets'
4
4
  require 'action_view'
5
- require 'action_view/base'
6
5
 
7
6
  module Sprockets
8
7
  module Rails
@@ -16,7 +15,9 @@ module Sprockets
16
15
 
17
16
  def environment
18
17
  if app
19
- app.assets
18
+ # Use initialized app.assets or force build an environment if
19
+ # config.assets.compile is disabled
20
+ app.assets || Sprockets::Railtie.build_environment(app)
20
21
  else
21
22
  super
22
23
  end
@@ -24,7 +25,8 @@ module Sprockets
24
25
 
25
26
  def output
26
27
  if app
27
- File.join(app.root, 'public', app.config.assets.prefix)
28
+ config = app.config
29
+ File.join(config.paths['public'].first, config.assets.prefix)
28
30
  else
29
31
  super
30
32
  end
@@ -46,17 +48,12 @@ module Sprockets
46
48
  end
47
49
  end
48
50
 
49
- def cache_path
50
- if app
51
- "#{app.config.root}/tmp/cache/assets"
52
- else
53
- @cache_path
54
- end
55
- end
56
- attr_writer :cache_path
57
-
58
51
  def define
59
52
  namespace :assets do
53
+ %w( environment precompile clean clobber ).each do |task|
54
+ Rake::Task[task].clear if Rake::Task.task_defined?(task)
55
+ end
56
+
60
57
  # Override this task change the loaded dependencies
61
58
  desc "Load asset compile environment"
62
59
  task :environment do
@@ -73,9 +70,8 @@ module Sprockets
73
70
 
74
71
  desc "Remove old compiled assets"
75
72
  task :clean, [:keep] => :environment do |t, args|
76
- keep = Integer(args.keep || 2)
77
73
  with_logger do
78
- manifest.clean(keep)
74
+ manifest.clean(Integer(args.keep || self.keep))
79
75
  end
80
76
  end
81
77
 
@@ -83,7 +79,6 @@ module Sprockets
83
79
  task :clobber => :environment do
84
80
  with_logger do
85
81
  manifest.clobber
86
- rm_rf cache_path if cache_path
87
82
  end
88
83
  end
89
84
  end