Simplify FixtureResolver to reuse filtering logic

Previously FixtureResolver had a copy-pasted version of the filtering
already done by OptimizedFileSystemResolver. This PR replaces this by
extracting the two places actual filesystem operations into separate
methods and overriding those.

It would be nice to not rely on overriding methods at all, and to
extract the actual filtering into a separate, reusable class, but I
don't want to do that until some other changes are made to the
filtering.

This should also make FixtureResolver much more accurate to
OptimizedFileSystemResolver, by also creating and caching the
UnboundTemplate classes, which de-duplicate templates.
This commit is contained in:
John Hawthorn 2020-02-24 11:47:29 -08:00
parent a9e455f484
commit c3c1c32f4b
2 changed files with 24 additions and 29 deletions

@ -204,9 +204,13 @@ def query(path, details, formats, locals, cache:)
end
end
def source_for_template(template)
Template::Sources::File.new(template)
end
def build_unbound_template(template, virtual_path)
handler, format, variant = extract_handler_and_format_and_variant(template)
source = Template::Sources::File.new(template)
source = source_for_template(template)
UnboundTemplate.new(
source,
@ -316,14 +320,22 @@ def initialize(path)
end
private
def find_template_paths_from_details(path, details)
def find_candidate_template_paths(path)
# Instead of checking for every possible path, as our other globs would
# do, scan the directory for files with the right prefix.
query = "#{escape_entry(File.join(@path, path))}*"
Dir[query].reject do |filename|
File.directory?(filename)
end
end
def find_template_paths_from_details(path, details)
candidates = find_candidate_template_paths(path)
regex = build_regex(path, details)
Dir[query].uniq.reject do |filename|
candidates.uniq.reject do |filename|
# This regex match does double duty of finding only files which match
# details (instead of just matching the prefix) and also filtering for
# case-insensitive file systems.

@ -27,34 +27,17 @@ def to_s
end
private
def query(path, exts, _, locals, cache:)
regex = build_regex(path, exts)
@hash.select do |_path, _|
("/" + _path).match?(regex)
end.map do |_path, source|
handler, format, variant = extract_handler_and_format_and_variant(_path)
Template.new(source, _path, handler,
virtual_path: path.virtual,
format: format,
variant: variant,
locals: locals
)
end.sort_by do |t|
match = ("/" + t.identifier).match(regex)
EXTENSIONS.keys.reverse.map do |ext|
if ext == :variants && exts[ext] == :any
match[ext].nil? ? 0 : 1
elsif match[ext].nil?
exts[ext].length
else
found = match[ext].to_sym
exts[ext].index(found)
end
end
def find_candidate_template_paths(path)
@hash.keys.select do |fixture|
fixture.start_with?(path.virtual)
end.map do |fixture|
"/#{fixture}"
end
end
def source_for_template(template)
@hash[template[1..template.size]]
end
end
class NullResolver < PathResolver