sass 3.1.0.alpha.41 → 3.1.0.alpha.42
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.
- data/EDGE_GEM_VERSION +1 -1
- data/VERSION +1 -1
- data/lib/sass/cache_stores.rb +14 -0
- data/lib/sass/cache_stores/active_support.rb +28 -0
- data/lib/sass/cache_stores/base.rb +84 -0
- data/lib/sass/cache_stores/filesystem.rb +56 -0
- data/lib/sass/cache_stores/memory.rb +51 -0
- data/lib/sass/cache_stores/null.rb +25 -0
- data/lib/sass/engine.rb +2 -2
- data/lib/sass/plugin/configuration.rb +1 -1
- data/lib/sass/plugin/rails.rb +7 -5
- data/test/sass/cache_test.rb +7 -7
- data/test/sass/plugin_test.rb +1 -1
- metadata +7 -2
- data/lib/sass/cache_store.rb +0 -208
data/EDGE_GEM_VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.0.alpha.
|
1
|
+
3.1.0.alpha.42
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.0.alpha.
|
1
|
+
3.1.0.alpha.42
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
# Sass cache stores are in charge of storing cached information,
|
5
|
+
# especially parse trees for Sass documents.
|
6
|
+
#
|
7
|
+
# User-created importers must inherit from {CacheStores::Base}.
|
8
|
+
module CacheStores
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'sass/cache_stores/base'
|
13
|
+
require 'sass/cache_stores/filesystem'
|
14
|
+
require 'sass/cache_stores/memory'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Sass
|
2
|
+
module CacheStores
|
3
|
+
# A cache store that wraps an ActiveSupport cache store.
|
4
|
+
# This is useful for integrating with an app that uses ActiveSupport,
|
5
|
+
# or for taking advantage of the wide variety of ActiveSupport cache backends.
|
6
|
+
#
|
7
|
+
# This is automatically used within Rails.
|
8
|
+
class ActiveSupport < Base
|
9
|
+
# @param store [::ActiveSupport::Cache::Store] The cache store to wrap.
|
10
|
+
def initialize(store)
|
11
|
+
@store = store
|
12
|
+
end
|
13
|
+
|
14
|
+
# @see Base#_retrieve
|
15
|
+
def _retrieve(key, version, sha)
|
16
|
+
return unless val = @store.fetch('_sass/' + key)
|
17
|
+
return unless val[:version] == version
|
18
|
+
return unless val[:sha] == sha
|
19
|
+
return val[:contents]
|
20
|
+
end
|
21
|
+
|
22
|
+
# @see Base#_store
|
23
|
+
def _store(key, version, sha, contents)
|
24
|
+
@store.write('_sass/' + key, :version => version, :sha => sha, :contents => contents)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Sass
|
2
|
+
module CacheStores
|
3
|
+
# An abstract base class for backends for the Sass cache.
|
4
|
+
# Any key-value store can act as such a backend;
|
5
|
+
# it just needs to implement the
|
6
|
+
# \{#_store} and \{#_retrieve} methods.
|
7
|
+
#
|
8
|
+
# To use a cache store with Sass,
|
9
|
+
# use the {file:SASS_REFERENCE.md#cache_store-option `:cache_store` option}.
|
10
|
+
#
|
11
|
+
# @abstract
|
12
|
+
class Base
|
13
|
+
# Store cached contents for later retrieval
|
14
|
+
# Must be implemented by all CacheStore subclasses
|
15
|
+
#
|
16
|
+
# Note: cache contents contain binary data.
|
17
|
+
#
|
18
|
+
# @param key [String] The key to store the contents under
|
19
|
+
# @param version [String] The current sass version.
|
20
|
+
# Cached contents must not be retrieved across different versions of sass.
|
21
|
+
# @param sha [String] The sha of the sass source.
|
22
|
+
# Cached contents must not be retrieved if the sha has changed.
|
23
|
+
# @param contents [String] The contents to store.
|
24
|
+
def _store(key, version, sha, contents)
|
25
|
+
raise "#{self.class} must implement #_store."
|
26
|
+
end
|
27
|
+
|
28
|
+
# Retrieved cached contents.
|
29
|
+
# Must be implemented by all subclasses.
|
30
|
+
#
|
31
|
+
# Note: if the key exists but the sha or version have changed,
|
32
|
+
# then the key may be deleted by the cache store, if it wants to do so.
|
33
|
+
#
|
34
|
+
# @param key [String] The key to retrieve
|
35
|
+
# @param version [String] The current sass version.
|
36
|
+
# Cached contents must not be retrieved across different versions of sass.
|
37
|
+
# @param sha [String] The sha of the sass source.
|
38
|
+
# Cached contents must not be retrieved if the sha has changed.
|
39
|
+
# @return [String] The contents that were previously stored.
|
40
|
+
# @return [NilClass] when the cache key is not found or the version or sha have changed.
|
41
|
+
def _retrieve(key, version, sha)
|
42
|
+
raise "#{self.class} must implement #_retrieve."
|
43
|
+
end
|
44
|
+
|
45
|
+
# Store a {Sass::Tree::RootNode}.
|
46
|
+
#
|
47
|
+
# @param key [String] The key to store it under.
|
48
|
+
# @param sha [String] The checksum for the contents that are being stored.
|
49
|
+
# @param obj [Object] The object to cache.
|
50
|
+
def store(key, sha, root)
|
51
|
+
_store(key, Sass::VERSION, sha, Sass::Util.dump(root))
|
52
|
+
end
|
53
|
+
|
54
|
+
# Retrieve a {Sass::Tree::RootNode}.
|
55
|
+
#
|
56
|
+
# @param key [String] The key the root element was stored under.
|
57
|
+
# @param sha [String] The checksum of the root element's content.
|
58
|
+
# @return [Object] The cached object.
|
59
|
+
def retrieve(key, sha)
|
60
|
+
contents = _retrieve(key, Sass::VERSION, sha)
|
61
|
+
Sass::Util.load(contents) if contents
|
62
|
+
rescue EOFError, TypeError, ArgumentError => e
|
63
|
+
Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Return the key for the sass file.
|
67
|
+
#
|
68
|
+
# The `(sass_dirname, sass_basename)` pair
|
69
|
+
# should uniquely identify the Sass document,
|
70
|
+
# but otherwise there are no restrictions on their content.
|
71
|
+
#
|
72
|
+
# @param sass_dirname [String]
|
73
|
+
# The fully-expanded location of the Sass file.
|
74
|
+
# This corresponds to the directory name on a filesystem.
|
75
|
+
# @param sass_basename [String] The name of the Sass file that is being referenced.
|
76
|
+
# This corresponds to the basename on a filesystem.
|
77
|
+
def key(sass_dirname, sass_basename)
|
78
|
+
dir = Digest::SHA1.hexdigest(sass_dirname)
|
79
|
+
filename = "#{sass_basename}c"
|
80
|
+
"#{dir}/#{filename}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Sass
|
2
|
+
module CacheStores
|
3
|
+
# A backend for the Sass cache using the filesystem.
|
4
|
+
class Filesystem < Base
|
5
|
+
# The directory where the cached files will be stored.
|
6
|
+
#
|
7
|
+
# @return [String]
|
8
|
+
attr_accessor :cache_location
|
9
|
+
|
10
|
+
# @param cache_location [String] see \{#cache\_location}
|
11
|
+
def initialize(cache_location)
|
12
|
+
@cache_location = cache_location
|
13
|
+
end
|
14
|
+
|
15
|
+
# @see Base#\_retrieve
|
16
|
+
def _retrieve(key, version, sha)
|
17
|
+
return unless File.readable?(path_to(key))
|
18
|
+
contents = nil
|
19
|
+
File.open(path_to(key), "rb") do |f|
|
20
|
+
if f.readline("\n").strip == version && f.readline("\n").strip == sha
|
21
|
+
return f.read
|
22
|
+
end
|
23
|
+
end
|
24
|
+
File.unlink path_to(key)
|
25
|
+
nil
|
26
|
+
rescue EOFError, TypeError, ArgumentError => e
|
27
|
+
Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
|
28
|
+
end
|
29
|
+
|
30
|
+
# @see Base#\_store
|
31
|
+
def _store(key, version, sha, contents)
|
32
|
+
return unless File.writable?(File.dirname(@cache_location))
|
33
|
+
return if File.exists?(@cache_location) && !File.writable?(@cache_location)
|
34
|
+
compiled_filename = path_to(key)
|
35
|
+
return if File.exists?(File.dirname(compiled_filename)) && !File.writable?(File.dirname(compiled_filename))
|
36
|
+
return if File.exists?(compiled_filename) && !File.writable?(compiled_filename)
|
37
|
+
FileUtils.mkdir_p(File.dirname(compiled_filename))
|
38
|
+
File.open(compiled_filename, "wb") do |f|
|
39
|
+
f.puts(version)
|
40
|
+
f.puts(sha)
|
41
|
+
f.write(contents)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Returns the path to a file for the given key.
|
48
|
+
#
|
49
|
+
# @param key [String]
|
50
|
+
# @return [String] The path to the cache file.
|
51
|
+
def path_to(key)
|
52
|
+
File.join(cache_location, key)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Sass
|
2
|
+
module CacheStores
|
3
|
+
# A backend for the Sass cache using in-process memory.
|
4
|
+
class Memory < Base
|
5
|
+
# Since the {Memory} store is stored in the Sass tree's options hash,
|
6
|
+
# when the options get serialized as part of serializing the tree,
|
7
|
+
# you get crazy exponential growth in the size of the cached objects
|
8
|
+
# unless you don't dump the cache.
|
9
|
+
#
|
10
|
+
# @private
|
11
|
+
def _dump(depth)
|
12
|
+
""
|
13
|
+
end
|
14
|
+
|
15
|
+
# If we deserialize this class, just make a new empty one.
|
16
|
+
#
|
17
|
+
# @private
|
18
|
+
def self._load(repr)
|
19
|
+
Memory.new
|
20
|
+
end
|
21
|
+
|
22
|
+
# Create a new, empty cache store.
|
23
|
+
def initialize
|
24
|
+
@contents = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
# @see Base#_retrieve
|
28
|
+
def _retrieve(key, version, sha)
|
29
|
+
if @contents.has_key?(key)
|
30
|
+
return unless @contents[key][:version] == version
|
31
|
+
return unless @contents[key][:sha] == sha
|
32
|
+
return @contents[key][:contents]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @see Base#_store
|
37
|
+
def _store(key, version, sha, contents)
|
38
|
+
@contents[key] = {
|
39
|
+
:version => version,
|
40
|
+
:sha => sha,
|
41
|
+
:contents => contents
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
# Destructively clear the cache.
|
46
|
+
def reset!
|
47
|
+
@contents = {}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Sass
|
2
|
+
module CacheStores
|
3
|
+
# Doesn't store anything, but records what things it should have stored.
|
4
|
+
# This doesn't currently have any use except for testing and debugging.
|
5
|
+
#
|
6
|
+
# @private
|
7
|
+
class Null < Base
|
8
|
+
def initialize
|
9
|
+
@keys = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def _retrieve(key, version, sha)
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def _store(key, version, sha, contents)
|
17
|
+
@keys[key] = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def was_set?(key)
|
21
|
+
@keys[key]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/sass/engine.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'strscan'
|
2
2
|
require 'set'
|
3
3
|
require 'digest/sha1'
|
4
|
-
require 'sass/
|
4
|
+
require 'sass/cache_stores'
|
5
5
|
require 'sass/tree/node'
|
6
6
|
require 'sass/tree/root_node'
|
7
7
|
require 'sass/tree/rule_node'
|
@@ -156,7 +156,7 @@ module Sass
|
|
156
156
|
# Tracks the original filename of the top-level Sass file
|
157
157
|
options[:original_filename] = options[:original_filename] || options[:filename]
|
158
158
|
|
159
|
-
options[:cache_store] ||= Sass::
|
159
|
+
options[:cache_store] ||= Sass::CacheStores::Filesystem.new(options[:cache_location])
|
160
160
|
# Support both, because the docs said one and the other actually worked
|
161
161
|
# for quite a long time.
|
162
162
|
options[:line_comments] ||= options[:line_numbers]
|
@@ -31,7 +31,7 @@ module Sass
|
|
31
31
|
# @return [{Symbol => Object}]
|
32
32
|
def options
|
33
33
|
@options ||= default_options.dup
|
34
|
-
@options[:cache_store] ||= Sass::
|
34
|
+
@options[:cache_store] ||= Sass::CacheStores::Filesystem.new(@options[:cache_location])
|
35
35
|
@options
|
36
36
|
end
|
37
37
|
|
data/lib/sass/plugin/rails.rb
CHANGED
@@ -4,6 +4,7 @@ unless defined?(Sass::RAILS_LOADED)
|
|
4
4
|
module Sass::Plugin::Configuration
|
5
5
|
# Different default options in a rails envirionment.
|
6
6
|
def default_options
|
7
|
+
return @default_options if @default_options
|
7
8
|
opts = {
|
8
9
|
:quiet => Sass::Util.rails_env != "production",
|
9
10
|
:full_exception => Sass::Util.rails_env != "production",
|
@@ -11,7 +12,10 @@ unless defined?(Sass::RAILS_LOADED)
|
|
11
12
|
}
|
12
13
|
|
13
14
|
if Sass::Util.ap_geq?('3.1.0.beta')
|
14
|
-
|
15
|
+
require 'sass/importers/rails'
|
16
|
+
require 'sass/cache_stores/active_support'
|
17
|
+
opts.merge!(:load_paths => [Sass::Importers::Rails.new])
|
18
|
+
opts.merge!(:cache_store => Sass::CacheStores::ActiveSupport.new(Rails.cache)) if Rails.cache
|
15
19
|
else
|
16
20
|
opts.merge!(
|
17
21
|
:always_update => false,
|
@@ -20,7 +24,7 @@ unless defined?(Sass::RAILS_LOADED)
|
|
20
24
|
:always_check => Sass::Util.rails_env == "development")
|
21
25
|
end
|
22
26
|
|
23
|
-
@default_options
|
27
|
+
@default_options = opts.freeze
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
@@ -29,7 +33,6 @@ unless defined?(Sass::RAILS_LOADED)
|
|
29
33
|
# Disable this for now, until we figure out how to get Rails
|
30
34
|
# to pass in the view.
|
31
35
|
if Sass::Util.ap_geq?('3.1.0.beta')
|
32
|
-
require 'sass/importers/rails'
|
33
36
|
class Sass::Plugin::TemplateHandler
|
34
37
|
attr_reader :syntax
|
35
38
|
|
@@ -45,8 +48,7 @@ unless defined?(Sass::RAILS_LOADED)
|
|
45
48
|
:syntax => @syntax,
|
46
49
|
:filename => template.virtual_path,
|
47
50
|
:_rails_lookup_context => view.lookup_context,
|
48
|
-
:importer => Sass::Importers::Rails.new
|
49
|
-
:load_paths => [Sass::Importers::Rails.new] + Sass::Plugin.engine_options[:load_paths]))
|
51
|
+
:importer => Sass::Importers::Rails.new))
|
50
52
|
|
51
53
|
template.data[:sass_importers] = engine.dependencies.map do |e|
|
52
54
|
[e.options[:filename], e.options[:importer]]
|
data/test/sass/cache_test.rb
CHANGED
@@ -14,13 +14,13 @@ class CacheTest < Test::Unit::TestCase
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def test_file_cache_writes_a_file
|
17
|
-
file_store = Sass::
|
17
|
+
file_store = Sass::CacheStores::Filesystem.new(@@cache_dir)
|
18
18
|
file_store.store("asdf/foo.scssc", "fakesha1", root_node)
|
19
19
|
assert File.exists?("#{@@cache_dir}/asdf/foo.scssc")
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_file_cache_reads_a_file
|
23
|
-
file_store = Sass::
|
23
|
+
file_store = Sass::CacheStores::Filesystem.new(@@cache_dir)
|
24
24
|
assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc")
|
25
25
|
file_store.store("asdf/foo.scssc", "fakesha1", root_node)
|
26
26
|
assert File.exists?("#{@@cache_dir}/asdf/foo.scssc")
|
@@ -28,13 +28,13 @@ class CacheTest < Test::Unit::TestCase
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def test_file_cache_miss_returns_nil
|
31
|
-
file_store = Sass::
|
31
|
+
file_store = Sass::CacheStores::Filesystem.new(@@cache_dir)
|
32
32
|
assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc")
|
33
33
|
assert_nil file_store.retrieve("asdf/foo.scssc", "fakesha1")
|
34
34
|
end
|
35
35
|
|
36
36
|
def test_sha_change_invalidates_cache_and_cleans_up
|
37
|
-
file_store = Sass::
|
37
|
+
file_store = Sass::CacheStores::Filesystem.new(@@cache_dir)
|
38
38
|
assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc")
|
39
39
|
file_store.store("asdf/foo.scssc", "fakesha1", root_node)
|
40
40
|
assert File.exists?("#{@@cache_dir}/asdf/foo.scssc")
|
@@ -43,7 +43,7 @@ class CacheTest < Test::Unit::TestCase
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def test_version_change_invalidates_cache_and_cleans_up
|
46
|
-
file_store = Sass::
|
46
|
+
file_store = Sass::CacheStores::Filesystem.new(@@cache_dir)
|
47
47
|
assert !File.exists?("#{@@cache_dir}/asdf/foo.scssc")
|
48
48
|
file_store.store("asdf/foo.scssc", "fakesha1", root_node)
|
49
49
|
assert File.exists?("#{@@cache_dir}/asdf/foo.scssc")
|
@@ -58,7 +58,7 @@ class CacheTest < Test::Unit::TestCase
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def test_arbitrary_objects_can_go_into_cache
|
61
|
-
cache = Sass::
|
61
|
+
cache = Sass::CacheStores::Memory.new
|
62
62
|
an_object = {:foo => :bar}
|
63
63
|
cache.store("an_object", "", an_object)
|
64
64
|
assert_equal an_object, cache.retrieve("an_object", "")
|
@@ -71,4 +71,4 @@ class CacheTest < Test::Unit::TestCase
|
|
71
71
|
div { @include color(red); }
|
72
72
|
SCSS
|
73
73
|
end
|
74
|
-
end
|
74
|
+
end
|
data/test/sass/plugin_test.rb
CHANGED
@@ -13,7 +13,7 @@ class SassPluginTest < Test::Unit::TestCase
|
|
13
13
|
@@templates += %w[import_charset import_charset_ibm866] unless Sass::Util.ruby1_8?
|
14
14
|
@@templates << 'import_charset_1_8' if Sass::Util.ruby1_8?
|
15
15
|
|
16
|
-
@@cache_store = Sass::
|
16
|
+
@@cache_store = Sass::CacheStores::Memory.new
|
17
17
|
|
18
18
|
def setup
|
19
19
|
FileUtils.mkdir_p tempfile_loc
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.0.alpha.
|
4
|
+
version: 3.1.0.alpha.42
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Weizenbaum
|
@@ -57,7 +57,6 @@ files:
|
|
57
57
|
- lib/sass/plugin.rb
|
58
58
|
- lib/sass/script.rb
|
59
59
|
- lib/sass/selector.rb
|
60
|
-
- lib/sass/cache_store.rb
|
61
60
|
- lib/sass/plugin/configuration.rb
|
62
61
|
- lib/sass/plugin/merb.rb
|
63
62
|
- lib/sass/plugin/generic.rb
|
@@ -126,6 +125,12 @@ files:
|
|
126
125
|
- lib/sass/util.rb
|
127
126
|
- lib/sass/util/subset_map.rb
|
128
127
|
- lib/sass/version.rb
|
128
|
+
- lib/sass/cache_stores.rb
|
129
|
+
- lib/sass/cache_stores/active_support.rb
|
130
|
+
- lib/sass/cache_stores/base.rb
|
131
|
+
- lib/sass/cache_stores/filesystem.rb
|
132
|
+
- lib/sass/cache_stores/memory.rb
|
133
|
+
- lib/sass/cache_stores/null.rb
|
129
134
|
- vendor/fssm/LICENSE
|
130
135
|
- vendor/fssm/README.markdown
|
131
136
|
- vendor/fssm/Rakefile
|
data/lib/sass/cache_store.rb
DELETED
@@ -1,208 +0,0 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
|
3
|
-
module Sass
|
4
|
-
# An abstract base class for backends for the Sass cache.
|
5
|
-
# Any key-value store can act as such a backend;
|
6
|
-
# it just needs to implement the
|
7
|
-
# \{#_store} and \{#_retrieve} methods.
|
8
|
-
#
|
9
|
-
# To use a cache store with Sass,
|
10
|
-
# use the {file:SASS_REFERENCE.md#cache_store-option `:cache_store` option}.
|
11
|
-
class CacheStore
|
12
|
-
# Store cached contents for later retrieval
|
13
|
-
# Must be implemented by all CacheStore subclasses
|
14
|
-
#
|
15
|
-
# Note: cache contents contain binary data.
|
16
|
-
#
|
17
|
-
# @param key [String] The key to store the contents under
|
18
|
-
# @param version [String] The current sass version.
|
19
|
-
# Cached contents must not be retrieved across different versions of sass.
|
20
|
-
# @param sha [String] The sha of the sass source.
|
21
|
-
# Cached contents must not be retrieved if the sha has changed.
|
22
|
-
# @param contents [String] The contents to store.
|
23
|
-
def _store(key, version, sha, contents)
|
24
|
-
raise "#{self.class} must implement #_store."
|
25
|
-
end
|
26
|
-
|
27
|
-
# Retrieved cached contents.
|
28
|
-
# Must be implemented by all subclasses.
|
29
|
-
#
|
30
|
-
# Note: if the key exists but the sha or version have changed,
|
31
|
-
# then the key may be deleted by the cache store, if it wants to do so.
|
32
|
-
#
|
33
|
-
# @param key [String] The key to retrieve
|
34
|
-
# @param version [String] The current sass version.
|
35
|
-
# Cached contents must not be retrieved across different versions of sass.
|
36
|
-
# @param sha [String] The sha of the sass source.
|
37
|
-
# Cached contents must not be retrieved if the sha has changed.
|
38
|
-
# @return [String] The contents that were previously stored.
|
39
|
-
# @return [NilClass] when the cache key is not found or the version or sha have changed.
|
40
|
-
def _retrieve(key, version, sha)
|
41
|
-
raise "#{self.class} must implement #_retrieve."
|
42
|
-
end
|
43
|
-
|
44
|
-
# Store a {Sass::Tree::RootNode}.
|
45
|
-
#
|
46
|
-
# @param key [String] The key to store it under.
|
47
|
-
# @param sha [String] The checksum for the contents that are being stored.
|
48
|
-
# @param obj [Object] The object to cache.
|
49
|
-
def store(key, sha, root)
|
50
|
-
_store(key, Sass::VERSION, sha, Sass::Util.dump(root))
|
51
|
-
end
|
52
|
-
|
53
|
-
# Retrieve a {Sass::Tree::RootNode}.
|
54
|
-
#
|
55
|
-
# @param key [String] The key the root element was stored under.
|
56
|
-
# @param sha [String] The checksum of the root element's content.
|
57
|
-
# @return [Object] The cached object.
|
58
|
-
def retrieve(key, sha)
|
59
|
-
contents = _retrieve(key, Sass::VERSION, sha)
|
60
|
-
Sass::Util.load(contents) if contents
|
61
|
-
rescue EOFError, TypeError, ArgumentError => e
|
62
|
-
raise
|
63
|
-
Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
|
64
|
-
end
|
65
|
-
|
66
|
-
# Return the key for the sass file.
|
67
|
-
#
|
68
|
-
# The `(sass_dirname, sass_basename)` pair
|
69
|
-
# should uniquely identify the Sass document,
|
70
|
-
# but otherwise there are no restrictions on their content.
|
71
|
-
#
|
72
|
-
# @param sass_dirname [String]
|
73
|
-
# The fully-expanded location of the Sass file.
|
74
|
-
# This corresponds to the directory name on a filesystem.
|
75
|
-
# @param sass_basename [String] The name of the Sass file that is being referenced.
|
76
|
-
# This corresponds to the basename on a filesystem.
|
77
|
-
def key(sass_dirname, sass_basename)
|
78
|
-
dir = Digest::SHA1.hexdigest(sass_dirname)
|
79
|
-
filename = "#{sass_basename}c"
|
80
|
-
"#{dir}/#{filename}"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# A backend for the Sass cache using the filesystem.
|
85
|
-
class FileCacheStore < CacheStore
|
86
|
-
# The directory where the cached files will be stored.
|
87
|
-
#
|
88
|
-
# @return [String]
|
89
|
-
attr_accessor :cache_location
|
90
|
-
|
91
|
-
# Create a new FileCacheStore.
|
92
|
-
#
|
93
|
-
# @param cache_location [String] see \{#cache\_location}
|
94
|
-
def initialize(cache_location)
|
95
|
-
@cache_location = cache_location
|
96
|
-
end
|
97
|
-
|
98
|
-
# @see {CacheStore#\_retrieve\_}
|
99
|
-
def _retrieve(key, version, sha)
|
100
|
-
return unless File.readable?(path_to(key))
|
101
|
-
contents = nil
|
102
|
-
File.open(path_to(key), "rb") do |f|
|
103
|
-
if f.readline("\n").strip == version && f.readline("\n").strip == sha
|
104
|
-
return f.read
|
105
|
-
end
|
106
|
-
end
|
107
|
-
File.unlink path_to(key)
|
108
|
-
nil
|
109
|
-
rescue EOFError, TypeError, ArgumentError => e
|
110
|
-
Sass::Util.sass_warn "Warning. Error encountered while reading cache #{path_to(key)}: #{e}"
|
111
|
-
end
|
112
|
-
|
113
|
-
# @see {CacheStore#\_store\_}
|
114
|
-
def _store(key, version, sha, contents)
|
115
|
-
return unless File.writable?(File.dirname(@cache_location))
|
116
|
-
return if File.exists?(@cache_location) && !File.writable?(@cache_location)
|
117
|
-
compiled_filename = path_to(key)
|
118
|
-
return if File.exists?(File.dirname(compiled_filename)) && !File.writable?(File.dirname(compiled_filename))
|
119
|
-
return if File.exists?(compiled_filename) && !File.writable?(compiled_filename)
|
120
|
-
FileUtils.mkdir_p(File.dirname(compiled_filename))
|
121
|
-
File.open(compiled_filename, "wb") do |f|
|
122
|
-
f.puts(version)
|
123
|
-
f.puts(sha)
|
124
|
-
f.write(contents)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
private
|
129
|
-
|
130
|
-
# Returns the path to a file for the given key.
|
131
|
-
#
|
132
|
-
# @param key [String]
|
133
|
-
# @return [String] The path to the cache file.
|
134
|
-
def path_to(key)
|
135
|
-
File.join(cache_location, key)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
# A backend for the Sass cache using in-process memory.
|
140
|
-
class InMemoryCacheStore < CacheStore
|
141
|
-
# Since the {InMemoryCacheStore} is stored in the Sass tree's options hash,
|
142
|
-
# when the options get serialized as part of serializing the tree,
|
143
|
-
# you get crazy exponential growth in the size of the cached objects
|
144
|
-
# unless you don't dump the cache.
|
145
|
-
#
|
146
|
-
# @private
|
147
|
-
def _dump(depth)
|
148
|
-
""
|
149
|
-
end
|
150
|
-
|
151
|
-
# If we deserialize this class, just make a new empty one.
|
152
|
-
#
|
153
|
-
# @private
|
154
|
-
def self._load(repr)
|
155
|
-
InMemoryCacheStore.new
|
156
|
-
end
|
157
|
-
|
158
|
-
# Create a new, empty cache store.
|
159
|
-
def initialize
|
160
|
-
@contents = {}
|
161
|
-
end
|
162
|
-
|
163
|
-
# @see CacheStore#_retrieve
|
164
|
-
def _retrieve(key, version, sha)
|
165
|
-
if @contents.has_key?(key)
|
166
|
-
return unless @contents[key][:version] == version
|
167
|
-
return unless @contents[key][:sha] == sha
|
168
|
-
return @contents[key][:contents]
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
# @see CacheStore#_store
|
173
|
-
def _store(key, version, sha, contents)
|
174
|
-
@contents[key] = {
|
175
|
-
:version => version,
|
176
|
-
:sha => sha,
|
177
|
-
:contents => contents
|
178
|
-
}
|
179
|
-
end
|
180
|
-
|
181
|
-
# Destructively clear the cache.
|
182
|
-
def reset!
|
183
|
-
@contents = {}
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
# Doesn't store anything, but records what things it should have stored.
|
188
|
-
# This doesn't currently have any use except for testing and debugging.
|
189
|
-
#
|
190
|
-
# @private
|
191
|
-
class NullCacheStore < CacheStore
|
192
|
-
def initialize
|
193
|
-
@keys = {}
|
194
|
-
end
|
195
|
-
|
196
|
-
def _retrieve(key, version, sha)
|
197
|
-
nil
|
198
|
-
end
|
199
|
-
|
200
|
-
def _store(key, version, sha, contents)
|
201
|
-
@keys[key] = true
|
202
|
-
end
|
203
|
-
|
204
|
-
def was_set?(key)
|
205
|
-
@keys[key]
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|