Add PathManager class to cache interim paths (#7732)

Merge pull request 7732
This commit is contained in:
Ashwin Maroli 2019-08-02 01:51:00 +05:30 committed by jekyllbot
parent 4eec5a55c3
commit b55927e8f7
6 changed files with 37 additions and 5 deletions

View File

@ -65,6 +65,7 @@ module Jekyll
autoload :LogAdapter, "jekyll/log_adapter" autoload :LogAdapter, "jekyll/log_adapter"
autoload :Page, "jekyll/page" autoload :Page, "jekyll/page"
autoload :PageWithoutAFile, "jekyll/page_without_a_file" autoload :PageWithoutAFile, "jekyll/page_without_a_file"
autoload :PathManager, "jekyll/path_manager"
autoload :PluginManager, "jekyll/plugin_manager" autoload :PluginManager, "jekyll/plugin_manager"
autoload :Publisher, "jekyll/publisher" autoload :Publisher, "jekyll/publisher"
autoload :Reader, "jekyll/reader" autoload :Reader, "jekyll/reader"

View File

@ -90,12 +90,12 @@ module Jekyll
# Check if an entry matches a specific pattern. # Check if an entry matches a specific pattern.
# Returns true if path matches against any glob pattern, else false. # Returns true if path matches against any glob pattern, else false.
def glob_include?(enumerator, entry) def glob_include?(enumerator, entry)
entry_with_source = File.join(site.source, entry) entry_with_source = PathManager.join(site.source, entry)
enumerator.any? do |pattern| enumerator.any? do |pattern|
case pattern case pattern
when String when String
pattern_with_source = File.join(site.source, pattern) pattern_with_source = PathManager.join(site.source, pattern)
File.fnmatch?(pattern_with_source, entry_with_source) || File.fnmatch?(pattern_with_source, entry_with_source) ||
entry_with_source.start_with?(pattern_with_source) entry_with_source.start_with?(pattern_with_source)

View File

@ -47,7 +47,7 @@ module Jekyll
end end
process(name) process(name)
read_yaml(File.join(base, dir), name) read_yaml(PathManager.join(base, dir), name)
data.default_proc = proc do |_, key| data.default_proc = proc do |_, key|
site.frontmatter_defaults.find(relative_path, type, key) site.frontmatter_defaults.find(relative_path, type, key)

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
module Jekyll
# A singleton class that caches frozen instances of path strings returned from its methods.
#
# NOTE:
# This class exists because `File.join` allocates an Array and returns a new String on every
# call using **the same arguments**. Caching the result means reduced memory usage.
# However, the caches are never flushed so that they can be used even when a site is
# regenerating. The results are frozen to deter mutation of the cached string.
#
# Therefore, employ this class only for situations where caching the result is necessary
# for performance reasons.
#
class PathManager
# This class cannot be initialized from outside
private_class_method :new
# Wraps `File.join` to cache the frozen result.
# Reassigns `nil`, empty strings and empty arrays to a frozen empty string beforehand.
#
# Returns a frozen string.
def self.join(base, item)
base = "" if base.nil? || base.empty?
item = "" if item.nil? || item.empty?
@join ||= {}
@join[base] ||= {}
@join[base][item] ||= File.join(base, item).freeze
end
end
end

View File

@ -85,7 +85,7 @@ module Jekyll
def retrieve_dirs(_base, dir, dot_dirs) def retrieve_dirs(_base, dir, dot_dirs)
dot_dirs.each do |file| dot_dirs.each do |file|
dir_path = site.in_source_dir(dir, file) dir_path = site.in_source_dir(dir, file)
rel_path = File.join(dir, file) rel_path = PathManager.join(dir, file)
@site.reader.read_directories(rel_path) unless @site.dest.chomp("/") == dir_path @site.reader.read_directories(rel_path) unless @site.dest.chomp("/") == dir_path
end end
end end

View File

@ -100,7 +100,7 @@ module Jekyll
def locate_include_file(context, file, safe) def locate_include_file(context, file, safe)
includes_dirs = tag_includes_dirs(context) includes_dirs = tag_includes_dirs(context)
includes_dirs.each do |dir| includes_dirs.each do |dir|
path = File.join(dir.to_s, file.to_s) path = PathManager.join(dir, file)
return path if valid_include_file?(path, dir.to_s, safe) return path if valid_include_file?(path, dir.to_s, safe)
end end
raise IOError, could_not_locate_message(file, includes_dirs, safe) raise IOError, could_not_locate_message(file, includes_dirs, safe)