Permalink
Browse files

Added overrides for sprockets gem

  • Loading branch information...
0 parents commit 824d198560fd5fceb8e28a42df686e43ebf94f1e @ndbroadbent committed Sep 28, 2012
@@ -0,0 +1,6 @@
+.bundle/
+pkg/
+Gemfile.lock
+tmp
+.rbenv-version
+.rvmrc
@@ -0,0 +1,6 @@
+source "http://rubygems.org"
+
+# Specify your gem's dependencies in sprockets-rails.gemspec
+gemspec
+
+gem "debugger"
@@ -0,0 +1,20 @@
+Copyright (c) 2012 David Heinemeier Hansson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,6 @@
+## turbo-sprockets-rails3
+
+* Speeds up the Rails 3 asset pipeline by only recompiling changed assets
+* Generates non-digest assets from precompiled assets - Only compile once!
+
+MIT-LICENSE.
@@ -0,0 +1,25 @@
+#!/usr/bin/env rake
+require 'rake/testtask'
+ENV["TEST_CORES"] = "1"
+
+namespace :test do
+ task :isolated do
+ Dir["test/assets*_test.rb"].each do |file|
+ dash_i = [
+ 'test',
+ 'lib',
+ ]
+ ruby "-I#{dash_i.join ':'}", file
+ end
+ end
+end
+
+Rake::TestTask.new("test:regular") do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/sprockets*_test.rb'
+ t.verbose = true
+end
+
+task :test => ['test:isolated', 'test:regular']
+task :default => :test
@@ -0,0 +1,134 @@
+require 'sprockets/asset'
+require 'sprockets/utils'
+
+module Sprockets
+ # `AssetWithDependencies` is the base class for `ProcessedAsset` and `UnprocessedAsset`.
+ class AssetWithDependencies < Asset
+
+ # :dependency_digest is used internally to check equality
+ attr_reader :dependency_digest, :source
+
+
+ # Initialize asset from serialized hash
+ def init_with(environment, coder, asset_options = {})
+ asset_options[:bundle] = false
+
+ super(environment, coder)
+
+ @source = coder['source']
+ @dependency_digest = coder['dependency_digest']
+
+ @required_assets = coder['required_paths'].map { |p|
+ p = expand_root_path(p)
+
+ unless environment.paths.detect { |path| p[path] }
+ raise UnserializeError, "#{p} isn't in paths"
+ end
+
+ p == pathname.to_s ? self : environment.find_asset(p, asset_options)
+ }
+ @dependency_paths = coder['dependency_paths'].map { |h|
+ DependencyFile.new(expand_root_path(h['path']), h['mtime'], h['digest'])
+ }
+ end
+
+ # Serialize custom attributes.
+ def encode_with(coder)
+ super
+
+ coder['source'] = source
+ coder['dependency_digest'] = dependency_digest
+
+ coder['required_paths'] = required_assets.map { |a|
+ relativize_root_path(a.pathname).to_s
+ }
+ coder['dependency_paths'] = dependency_paths.map { |d|
+ { 'path' => relativize_root_path(d.pathname).to_s,
+ 'mtime' => d.mtime.iso8601,
+ 'digest' => d.digest }
+ }
+ end
+
+ # Checks if Asset is stale by comparing the actual mtime and
+ # digest to the inmemory model.
+ def fresh?(environment)
+ # Check freshness of all declared dependencies
+ @dependency_paths.all? { |dep| dependency_fresh?(environment, dep) }
+ end
+
+ protected
+ class DependencyFile < Struct.new(:pathname, :mtime, :digest)
+ def initialize(pathname, mtime, digest)
+ pathname = Pathname.new(pathname) unless pathname.is_a?(Pathname)
+ mtime = Time.parse(mtime) if mtime.is_a?(String)
+ super
+ end
+
+ def eql?(other)
+ other.is_a?(DependencyFile) &&
+ pathname.eql?(other.pathname) &&
+ mtime.eql?(other.mtime) &&
+ digest.eql?(other.digest)
+ end
+
+ def hash
+ pathname.to_s.hash
+ end
+ end
+
+ private
+ def build_required_assets(environment, context, asset_options = {})
+ asset_options[:bundle] = false
+ @required_assets = []
+ required_assets_cache = {}
+
+ (context._required_paths + [pathname.to_s]).each do |path|
+ if path == self.pathname.to_s
+ unless required_assets_cache[self]
+ required_assets_cache[self] = true
+ @required_assets << self
+ end
+ elsif asset = environment.find_asset(path, asset_options)
+ asset.required_assets.each do |asset_dependency|
+ unless required_assets_cache[asset_dependency]
+ required_assets_cache[asset_dependency] = true
+ @required_assets << asset_dependency
+ end
+ end
+ end
+ end
+
+ required_assets_cache.clear
+ required_assets_cache = nil
+ end
+
+ def build_dependency_paths(environment, context, asset_options = {})
+ asset_options[:bundle] = false
+ dependency_paths = {}
+
+ context._dependency_paths.each do |path|
+ dep = DependencyFile.new(path, environment.stat(path).mtime, environment.file_digest(path).hexdigest)
+ dependency_paths[dep] = true
+ end
+
+ context._dependency_assets.each do |path|
+ if path == self.pathname.to_s
+ dep = DependencyFile.new(pathname, environment.stat(path).mtime, environment.file_digest(path).hexdigest)
+ dependency_paths[dep] = true
+ elsif asset = environment.find_asset(path, asset_options)
+ asset.dependency_paths.each do |d|
+ dependency_paths[d] = true
+ end
+ end
+ end
+
+ @dependency_paths = dependency_paths.keys
+ end
+
+ def compute_dependency_digest(environment)
+ required_assets.inject(environment.digest) { |digest, asset|
+ digest.update asset.digest
+ }.hexdigest
+ end
+ end
+end
@@ -0,0 +1,28 @@
+require 'sprockets/asset_with_dependencies'
+
+module Sprockets
+ class UnprocessedAsset < AssetWithDependencies
+ def initialize(environment, logical_path, pathname)
+ super
+
+ context = environment.context_class.new(environment, logical_path, pathname)
+ attributes = environment.attributes_for(pathname)
+ processors = attributes.processors
+
+ # Remove all engine processors except ERB to return unprocessed source file
+ processors -= (attributes.engines - [Tilt::ERBTemplate])
+
+ @source = context.evaluate(pathname, :processors => processors)
+
+ build_required_assets(environment, context, :process => false)
+ build_dependency_paths(environment, context, :process => false)
+
+ @dependency_digest = compute_dependency_digest(environment)
+ end
+ end
+
+ # Return unprocessed dependencies when initializing asset from serialized hash
+ def init_with(environment, coder)
+ super(environment, coder, :process => false)
+ end
+end
@@ -0,0 +1,5 @@
+Dir[File.expand_path('../turbo-sprockets/sprockets_overrides/*.rb', __FILE__)].each do |f|
+ require f
+end
+
+#require 'turbo-sprockets/railtie'
@@ -0,0 +1,29 @@
+require 'sprockets/asset'
+
+Sprockets::Asset.class_eval do
+ # Internal initializer to load `Asset` from serialized `Hash`.
+ def self.from_hash(environment, hash)
+ return unless hash.is_a?(Hash)
+
+ klass = case hash['class']
+ when 'BundledAsset'
+ BundledAsset
+ when 'ProcessedAsset'
+ ProcessedAsset
+ when 'UnprocessedAsset'
+ UnprocessedAsset
+ when 'StaticAsset'
+ StaticAsset
+ else
+ nil
+ end
+
+ if klass
+ asset = klass.allocate
+ asset.init_with(environment, hash)
+ asset
+ end
+ rescue UnserializeError
+ nil
+ end
+end
@@ -0,0 +1,37 @@
+require 'sprockets/base'
+require 'sprockets/unprocessed_asset'
+
+module Sprockets
+ Base.class_eval do
+ protected
+
+ def build_asset(logical_path, pathname, options)
+ pathname = Pathname.new(pathname)
+
+ # If there are any processors to run on the pathname, use
+ # `BundledAsset`. Otherwise use `StaticAsset` and treat is as binary.
+ if attributes_for(pathname).processors.any?
+ if options[:bundle] == false
+ circular_call_protection(pathname.to_s) do
+ if options[:process] == false
+ UnprocessedAsset.new(index, logical_path, pathname)
+ else
+ ProcessedAsset.new(index, logical_path, pathname)
+ end
+ end
+ else
+ BundledAsset.new(index, logical_path, pathname, options)
+ end
+ else
+ StaticAsset.new(index, logical_path, pathname)
+ end
+ end
+
+ private
+
+ def cache_key_for(path, options)
+ options[:process] = true unless options.key?(:process)
+ "#{path}:#{options[:bundle] ? '1' : '0'}:#{options[:process] ? '1' : '0'}"
+ end
+ end
+end
@@ -0,0 +1,31 @@
+require 'sprockets/bundled_asset'
+
+Sprockets::BundledAsset.class_eval do
+
+ # Adds :process options
+
+ def initialize(environment, logical_path, pathname, options = {})
+ super(environment, logical_path, pathname)
+ @process = options.fetch(:process, true)
+
+ @processed_asset = environment.find_asset(pathname, :bundle => false, :process => @process)
+ @required_assets = @processed_asset.required_assets
+ @dependency_paths = @processed_asset.dependency_paths
+
+ @source = ""
+
+ # Explode Asset into parts and gather the dependency bodies
+ to_a.each { |dependency| @source << dependency.to_s }
+
+ if @process
+ # Run bundle processors on concatenated source
+ context = environment.context_class.new(environment, logical_path, pathname)
+ @source = context.evaluate(pathname, :data => @source,
+ :processors => environment.bundle_processors(content_type))
+ end
+
+ @mtime = to_a.map(&:mtime).max
+ @length = Rack::Utils.bytesize(source)
+ @digest = environment.digest.update(source).hexdigest
+ end
+end
@@ -0,0 +1,19 @@
+require 'sprockets/environment'
+
+Sprockets::Environment.class_eval do
+
+ # Adds :process options
+
+ def find_asset(path, options = {})
+ options[:bundle] = true unless options.key?(:bundle)
+ options[:process] = true unless options.key?(:process)
+
+ # Ensure in-memory cached assets are still fresh on every lookup
+ if (asset = @assets[cache_key_for(path, options)]) && asset.fresh?(self)
+ asset
+ elsif asset = index.find_asset(path, options)
+ # Cache is pushed upstream by Index#find_asset
+ asset
+ end
+ end
+end
@@ -0,0 +1,28 @@
+require 'sprockets/index'
+
+Sprockets::Index.class_eval do
+
+ # Adds :process options
+
+ def find_asset(path, options = {})
+ options[:bundle] = true unless options.key?(:bundle)
+ options[:process] = true unless options.key?(:process)
+
+ if asset = @assets[cache_key_for(path, options)]
+ asset
+ elsif asset = super
+ logical_path_cache_key = cache_key_for(path, options)
+ full_path_cache_key = cache_key_for(asset.pathname, options)
+
+ # Cache on Index
+ @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
+
+ # Push cache upstream to Environment
+ @environment.instance_eval do
+ @assets[logical_path_cache_key] = @assets[full_path_cache_key] = asset
+ end
+
+ asset
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit 824d198

Please sign in to comment.