class Sass::Plugin::StalenessChecker
as its instance-level caches are never explicitly expired.
WARNING: It is important not to retain the instance for too long,
the caches should make the whole process significantly faster.
and the instance-level {#stylesheet_needs_update?} method should be used.
a StalenessChecker instance should be created,
* For a series of staleness checks (e.g. checking all files for staleness)
should be used.
the class-level {stylesheet_needs_update?} method
* For a one-off staleness check of a single ‘.sss` file,
Usage:
These are only used by a single StalenessChecker instance.
and one for whether a file is stale during this particular run.
* Two short-lived instance-level caches, one for file mtimes
This is a long-lived cache that is reused by every StalenessChecker instance.
* A class-level dependency cache which stores @import paths for each file.
To speed things up two level of caches are employed:
The class handles `.sss` file staleness checks via their mtime timestamps.
def self.stylesheet_needs_update?(css_file, template_file)
-
template_file
(String
) -- The location of the Sass or SCSS template -
css_file
(String
) -- The location of the CSS file to check.
def self.stylesheet_needs_update?(css_file, template_file) new.stylesheet_needs_update?(css_file, template_file) end
def compute_dependencies(filename)
def compute_dependencies(filename) Files.tree_for(filename, Plugin.engine_options).grep(Tree::ImportNode) do |n| File.expand_path(n.full_filename) unless n.full_filename =~ /\.css$/ end.compact rescue Sass::SyntaxError => e [] # If the file has an error, we assume it has no dependencies end
def dependencies(filename)
def dependencies(filename) stored_mtime, dependencies = @dependencies[filename] if !stored_mtime || stored_mtime < mtime(filename) @dependencies[filename] = [mtime(filename), dependencies = compute_dependencies(filename)] end dependencies end
def dependencies_stale?(template_file, css_mtime)
def dependencies_stale?(template_file, css_mtime) timestamps = @dependencies_stale[template_file] ||= {} timestamps.each_pair do |checked_css_mtime, is_stale| if checked_css_mtime <= css_mtime && !is_stale return false elsif checked_css_mtime > css_mtime && is_stale return true end end timestamps[css_mtime] = dependencies(template_file).any?(&dependency_updated?(css_mtime)) end
def dependency_updated?(css_mtime)
def dependency_updated?(css_mtime) lambda do |dep| begin mtime(dep) > css_mtime || dependencies_stale?(dep, css_mtime) rescue Sass::SyntaxError # If there's an error finding depenencies, default to recompiling. true end end end
def initialize
Creates a new StalenessChecker
def initialize @dependencies = self.class.dependencies_cache # Entries in the following instance-level caches are never explicitly expired. # Instead they are supposed to automaticaly go out of scope when a series of staleness checks # (this instance of StalenessChecker was created for) is finished. @mtimes, @dependencies_stale = {}, {} end
def mtime(filename)
def mtime(filename) @mtimes[filename] ||= begin File.mtime(filename).to_i rescue Errno::ENOENT @dependencies.delete(filename) DELETED end end
def stylesheet_needs_update?(css_file, template_file)
-
template_file
(String
) -- The location of the Sass or SCSS template -
css_file
(String
) -- The location of the CSS file to check.
def stylesheet_needs_update?(css_file, template_file) template_file, css_mtime = File.expand_path(template_file), mtime(css_file) css_mtime == DELETED || dependency_updated?(css_mtime).call(template_file) end