sprockets-rails 2.3.3 → 3.4.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.
@@ -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