mirror of
https://github.com/jekyll/jekyll.git
synced 2026-04-28 03:01:03 -04:00
Use disk for persistent cache
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "digest"
|
||||
require "fileutils"
|
||||
require "pstore"
|
||||
|
||||
module Jekyll
|
||||
class Cache
|
||||
extend Forwardable
|
||||
|
||||
def_delegators :@cache, :[], :[]=, :clear, :delete, :key?
|
||||
|
||||
# Get an existing named cache, or create a new one if none exists
|
||||
#
|
||||
# name - name of the cache
|
||||
@@ -13,31 +15,113 @@ module Jekyll
|
||||
# Returns nothing.
|
||||
# rubocop:disable Style/ClassVars
|
||||
def initialize(name)
|
||||
@@base_dir ||= File.expand_path(".jekyll-cache/Jekyll/Cache")
|
||||
@@caches ||= {}
|
||||
@@caches[name] ||= {}
|
||||
@cache = @@caches[name]
|
||||
@cache = @@caches[name] ||= {}
|
||||
@name = name
|
||||
FileUtils.mkdir_p(path_to)
|
||||
end
|
||||
|
||||
def self.clear
|
||||
@@caches ||= {}
|
||||
@@caches.clear
|
||||
delete_cache_files
|
||||
@@caches.each_value(&:clear)
|
||||
end
|
||||
# rubocop:enable Style/ClassVars
|
||||
|
||||
# rubocop:disable Lint/UselessSetterCall
|
||||
def self.clear_if_config_changed(config)
|
||||
cache = Jekyll::Cache.new "Jekyll::Cache"
|
||||
clear unless cache["config"] == config
|
||||
cache["config"] = config
|
||||
def clear
|
||||
delete_cache_files
|
||||
@cache.clear
|
||||
end
|
||||
# rubocop:enable Lint/UselessSetterCall
|
||||
|
||||
def getset(key)
|
||||
if key?(key)
|
||||
@cache[key]
|
||||
def [](key)
|
||||
return @cache[key] if @cache.key?(key)
|
||||
path = path_to(hash(key))
|
||||
if File.file?(path) && File.readable?(path)
|
||||
@cache[key] = load(path)
|
||||
else
|
||||
@cache[key] = yield
|
||||
raise
|
||||
end
|
||||
end
|
||||
|
||||
def getset(key)
|
||||
return @cache[key] if @cache.key?(key)
|
||||
path = path_to(hash(key))
|
||||
if File.file?(path) && File.readable?(path)
|
||||
value = load(path)
|
||||
else
|
||||
value = yield
|
||||
dump(path, value)
|
||||
end
|
||||
@cache[key] = value
|
||||
end
|
||||
|
||||
def []=(key, value)
|
||||
@cache[key] = value
|
||||
path = path_to(hash(key))
|
||||
dump(path, value)
|
||||
end
|
||||
|
||||
def delete(key)
|
||||
@cache.delete(key)
|
||||
path = path_to(hash(key))
|
||||
File.delete(path)
|
||||
end
|
||||
|
||||
def key?(key)
|
||||
return true if @cache.key?(key)
|
||||
path = path_to(hash(key))
|
||||
File.file?(path) && File.readable?(path)
|
||||
end
|
||||
|
||||
# rubocop:disable Style/ClassVars
|
||||
def self.clear_if_config_changed(config)
|
||||
config = config.inspect
|
||||
cache = Jekyll::Cache.new "Jekyll::Cache"
|
||||
unless cache.key?("config") && cache["config"] == config
|
||||
delete_cache_files
|
||||
@@caches = {}
|
||||
cache = Jekyll::Cache.new "Jekyll::Cache"
|
||||
cache["config"] = config
|
||||
end
|
||||
end
|
||||
# rubocop:enable Style/ClassVars
|
||||
|
||||
private
|
||||
|
||||
def path_to(hash = nil)
|
||||
@base_dir ||= File.join(@@base_dir, @name)
|
||||
return @base_dir if hash.nil?
|
||||
File.join(@base_dir, hash[0..1], hash[2..-1]).freeze
|
||||
end
|
||||
|
||||
def hash(key)
|
||||
Digest::SHA2.hexdigest(key).freeze
|
||||
end
|
||||
|
||||
def delete_cache_files
|
||||
FileUtils.rm_rf(path_to)
|
||||
end
|
||||
|
||||
# rubocop:disable Security/MarshalLoad
|
||||
def load(path)
|
||||
cached_file = File.open(path, "rb")
|
||||
value = Marshal.load(cached_file)
|
||||
cached_file.close
|
||||
value
|
||||
end
|
||||
# rubocop:enable Security/MarshalLoad
|
||||
|
||||
def dump(path, value)
|
||||
dir, _file = File.split(path)
|
||||
FileUtils.mkdir_p(dir)
|
||||
cached_file = File.open(path, "wb")
|
||||
Marshal.dump(value, cached_file)
|
||||
cached_file.close
|
||||
end
|
||||
|
||||
def self.delete_cache_files
|
||||
FileUtils.rm_rf(@@base_dir)
|
||||
end
|
||||
private_class_method :delete_cache_files
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user