Generic related files check
This commit is contained in:
parent
a546e0f523
commit
16b997498b
|
@ -61,3 +61,5 @@ Style/ParallelAssignment:
|
|||
Enabled: false
|
||||
Style/BlockDelimiters:
|
||||
Enabled: false
|
||||
Style/MultilineBlockChain:
|
||||
Enabled: false
|
||||
|
|
1
Gemfile
1
Gemfile
|
@ -7,6 +7,7 @@ gem 'yard', '~> 0.8', require: false
|
|||
# Test tools
|
||||
gem 'pry', '~> 0.10', group: :development, require: false
|
||||
gem 'pry-byebug'
|
||||
gem 'pry-stack_explorer'
|
||||
gem 'aruba', '~> 0.7.4', require: false
|
||||
gem 'rspec', '~> 3.0', require: false
|
||||
gem 'cucumber', '~> 2.0', require: false
|
||||
|
|
0
middleman-core/fixtures/related-files-app/config.rb
Normal file
0
middleman-core/fixtures/related-files-app/config.rb
Normal file
|
@ -180,7 +180,7 @@ module Middleman
|
|||
Contract String => String
|
||||
def extensionless_path(file)
|
||||
path = file.dup
|
||||
remove_templating_extensions(path)
|
||||
::Middleman::Util.remove_templating_extensions(path)
|
||||
end
|
||||
|
||||
# Actually update the resource list, assuming anything has called
|
||||
|
@ -224,16 +224,6 @@ module Middleman
|
|||
end
|
||||
end
|
||||
|
||||
# Removes the templating extensions, while keeping the others
|
||||
# @param [String] path
|
||||
# @return [String]
|
||||
Contract String => String
|
||||
def remove_templating_extensions(path)
|
||||
# Strip templating extensions as long as Tilt knows them
|
||||
path = path.sub(/#{::Regexp.escape(File.extname(path))}$/, '') while ::Tilt[path]
|
||||
path
|
||||
end
|
||||
|
||||
# Remove the locale token from the end of the path
|
||||
# @param [String] path
|
||||
# @return [String]
|
||||
|
|
|
@ -225,15 +225,23 @@ module Middleman
|
|||
# @return [void]
|
||||
Contract ArrayOf[Pathname], ArrayOf[Pathname] => Any
|
||||
def update(updated_paths, removed_paths)
|
||||
valid_updates = (updated_paths | find_related_files(updated_paths + removed_paths))
|
||||
.lazy
|
||||
.map(&method(:path_to_source_file))
|
||||
valid_updates = updated_paths
|
||||
.map { |p| ::Middleman::Util.path_to_source_file(p, @directory, @type) }
|
||||
.select(&method(:valid?))
|
||||
.to_a
|
||||
.each do |f|
|
||||
add_file_to_cache(f)
|
||||
logger.debug "== Change (#{f[:types].inspect}): #{f[:relative_path]}"
|
||||
end
|
||||
|
||||
valid_updates.each do |f|
|
||||
add_file_to_cache(f)
|
||||
logger.debug "== Change (#{f[:types].inspect}): #{f[:relative_path]}"
|
||||
end
|
||||
|
||||
related_updates = ::Middleman::Util.find_related_files(app, (updated_paths + removed_paths)).select(&method(:valid?))
|
||||
|
||||
related_updates.each do |f|
|
||||
add_file_to_cache(f)
|
||||
logger.debug "== Possible Change (#{f[:types].inspect}): #{f[:relative_path]}"
|
||||
end
|
||||
|
||||
valid_updates |= related_updates
|
||||
|
||||
valid_removes = removed_paths
|
||||
.lazy
|
||||
|
@ -283,35 +291,5 @@ module Middleman
|
|||
@only.any? { |reg| reg.match(file[:relative_path].to_s) }
|
||||
end
|
||||
end
|
||||
|
||||
# Convert a path to a file resprentation.
|
||||
#
|
||||
# @param [Pathname] path The path.
|
||||
# @return [Middleman::SourceFile]
|
||||
Contract Pathname => IsA['Middleman::SourceFile']
|
||||
def path_to_source_file(path)
|
||||
types = Set.new([@type])
|
||||
|
||||
relative_path = path.relative_path_from(@directory)
|
||||
destination_dir = @options.fetch(:destination_dir, false)
|
||||
relative_path = File.join(destination_dir, relative_path) if destination_dir
|
||||
|
||||
::Middleman::SourceFile.new(Pathname(relative_path), path, @directory, types)
|
||||
end
|
||||
|
||||
# Finds files which should also be considered to be dirty when
|
||||
# the given file(s) are touched.
|
||||
#
|
||||
# @param [Pathname] files The original touched file paths.
|
||||
# @return [Pathname] All related file paths, not including the source file paths.
|
||||
Contract ArrayOf[Pathname] => ArrayOf[Pathname]
|
||||
def find_related_files(files)
|
||||
files.flat_map do |file|
|
||||
# If any partial file changes, reload all non-partials
|
||||
if File.basename(file).start_with?('_')
|
||||
Dir[File.join(@directory, app.config[:source], "**/[^_]*.#{File.extname(file)}")].map { |p| Pathname(p) }
|
||||
end
|
||||
end.compact.uniq - files
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -430,6 +430,95 @@ module Middleman
|
|||
end
|
||||
end
|
||||
|
||||
Contract String => String
|
||||
def step_through_extensions(path)
|
||||
while ::Tilt[path]
|
||||
yield File.extname(path) if block_given?
|
||||
|
||||
# Strip templating extensions as long as Tilt knows them
|
||||
path = path.sub(/#{::Regexp.escape(File.extname(path))}$/, '')
|
||||
end
|
||||
|
||||
yield File.extname(path) if block_given?
|
||||
|
||||
path
|
||||
end
|
||||
|
||||
# Removes the templating extensions, while keeping the others
|
||||
# @param [String] path
|
||||
# @return [String]
|
||||
Contract String => String
|
||||
def remove_templating_extensions(path)
|
||||
step_through_extensions(path)
|
||||
end
|
||||
|
||||
# Removes the templating extensions, while keeping the others
|
||||
# @param [String] path
|
||||
# @return [String]
|
||||
Contract String => ArrayOf[String]
|
||||
def collect_extensions(path)
|
||||
result = []
|
||||
|
||||
step_through_extensions(path) { |e| result << e }
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
# Convert a path to a file resprentation.
|
||||
#
|
||||
# @param [Pathname] path The path.
|
||||
# @return [Middleman::SourceFile]
|
||||
Contract Pathname, Pathname, Symbol => IsA['Middleman::SourceFile']
|
||||
def path_to_source_file(path, directory, type)
|
||||
types = Set.new([type])
|
||||
|
||||
relative_path = path.relative_path_from(directory)
|
||||
# destination_dir = @options.fetch(:destination_dir, false)
|
||||
# relative_path = File.join(destination_dir, relative_path) if destination_dir
|
||||
|
||||
::Middleman::SourceFile.new(Pathname(relative_path), path, directory, types)
|
||||
end
|
||||
|
||||
# Finds files which should also be considered to be dirty when
|
||||
# the given file(s) are touched.
|
||||
#
|
||||
# @param [Middleman::Application] app The app.
|
||||
# @param [Pathname] files The original touched file paths.
|
||||
# @return [Middleman::SourceFile] All related file paths, not including the source file paths.
|
||||
Contract IsA['Middleman::Application'], ArrayOf[Pathname] => ArrayOf[IsA['Middleman::SourceFile']]
|
||||
def find_related_files(app, files)
|
||||
all_extensions = files.flat_map { |f| collect_extensions(f.to_s) }
|
||||
|
||||
sass_type_aliasing = ['.scss', '.sass']
|
||||
erb_type_aliasing = ['.erb', '.haml', '.slim']
|
||||
|
||||
if (all_extensions & sass_type_aliasing).length > 0
|
||||
all_extensions |= sass_type_aliasing
|
||||
end
|
||||
|
||||
if (all_extensions & erb_type_aliasing).length > 0
|
||||
all_extensions |= erb_type_aliasing
|
||||
end
|
||||
|
||||
all_extensions.uniq!
|
||||
|
||||
app.sitemap.resources.select { |r|
|
||||
local_extensions = collect_extensions(r.file_descriptor[:relative_path].to_s)
|
||||
|
||||
if (local_extensions & sass_type_aliasing).length > 0
|
||||
local_extensions |= sass_type_aliasing
|
||||
end
|
||||
|
||||
if (local_extensions & erb_type_aliasing).length > 0
|
||||
local_extensions |= erb_type_aliasing
|
||||
end
|
||||
|
||||
local_extensions.uniq!
|
||||
|
||||
((all_extensions & local_extensions).length > 0) && files.none? { |f| f == r.file_descriptor[:full_path] }
|
||||
}.map(&:file_descriptor)
|
||||
end
|
||||
|
||||
# Handy methods for dealing with URI templates. Mix into whatever class.
|
||||
module UriTemplates
|
||||
module_function
|
||||
|
|
|
@ -141,4 +141,44 @@ describe Middleman::Util do
|
|||
|
||||
end
|
||||
|
||||
describe "::find_related_files" do
|
||||
after(:each) do
|
||||
Given.cleanup!
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
Given.fixture 'related-files-app'
|
||||
@mm = Middleman::Application.new
|
||||
end
|
||||
|
||||
def source_file(path)
|
||||
Pathname(File.expand_path("source/#{path}"))
|
||||
end
|
||||
|
||||
it "Finds partials possibly related to ERb files" do
|
||||
related = Middleman::Util.find_related_files(@mm, [source_file('partials/_test.erb')]).map { |f| f[:full_path].to_s }
|
||||
expect(related).to include File.expand_path("source/index.html.erb")
|
||||
|
||||
related = Middleman::Util.find_related_files(@mm, [source_file('partials/_test2.haml')]).map { |f| f[:full_path].to_s }
|
||||
expect(related).to include File.expand_path("source/index.html.erb")
|
||||
end
|
||||
|
||||
it "Finds partials possible related to Scss files" do
|
||||
related = Middleman::Util.find_related_files(@mm, [source_file('stylesheets/_include4.scss')]).map { |f| f[:full_path].to_s }
|
||||
expect(related).to include File.expand_path("source/stylesheets/site.css.scss")
|
||||
expect(related).to include File.expand_path("source/stylesheets/include2.css.scss")
|
||||
|
||||
related = Middleman::Util.find_related_files(@mm, [source_file('stylesheets/include2.css.scss')]).map { |f| f[:full_path].to_s }
|
||||
expect(related).to include File.expand_path("source/stylesheets/site.css.scss")
|
||||
expect(related).not_to include File.expand_path("source/stylesheets/include2.css.scss")
|
||||
|
||||
related = Middleman::Util.find_related_files(@mm, [source_file('stylesheets/include1.css')]).map { |f| f[:full_path].to_s }
|
||||
expect(related).to include File.expand_path("source/stylesheets/site.css.scss")
|
||||
expect(related).to include File.expand_path("source/stylesheets/include2.css.scss")
|
||||
|
||||
related = Middleman::Util.find_related_files(@mm, [source_file('stylesheets/_include3.sass')]).map { |f| f[:full_path].to_s }
|
||||
expect(related).to include File.expand_path("source/stylesheets/site.css.scss")
|
||||
expect(related).to include File.expand_path("source/stylesheets/include2.css.scss")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue