Some immutability tweaks
This commit is contained in:
parent
e64954fbff
commit
69e66b04df
|
@ -1,5 +1,6 @@
|
||||||
if ENV['TEST'] || ENV['CONTRACTS'] == 'true'
|
if ENV['TEST'] || ENV['CONTRACTS'] == 'true'
|
||||||
require 'contracts'
|
require 'contracts'
|
||||||
|
require 'hamster'
|
||||||
|
|
||||||
module Contracts
|
module Contracts
|
||||||
class IsA
|
class IsA
|
||||||
|
@ -27,21 +28,7 @@ if ENV['TEST'] || ENV['CONTRACTS'] == 'true'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# class MethodDefined
|
VectorOf = Contracts::CollectionOf::Factory.new(::Hamster::Vector)
|
||||||
# def self.[](val)
|
|
||||||
# @lookup ||= {}
|
|
||||||
# @lookup[val] ||= new(val)
|
|
||||||
# end
|
|
||||||
|
|
||||||
# def initialize(val)
|
|
||||||
# @val = val
|
|
||||||
# end
|
|
||||||
|
|
||||||
# def valid?(val)
|
|
||||||
# val.method_defined? @val
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
|
|
||||||
ResourceList = Contracts::ArrayOf[IsA['Middleman::Sitemap::Resource']]
|
ResourceList = Contracts::ArrayOf[IsA['Middleman::Sitemap::Resource']]
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -125,8 +112,8 @@ else
|
||||||
class Frozen < Callable
|
class Frozen < Callable
|
||||||
end
|
end
|
||||||
|
|
||||||
# class MethodDefined < Callable
|
class VectorOf < Callable
|
||||||
# end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
require 'hamster'
|
||||||
|
|
||||||
module Middleman
|
module Middleman
|
||||||
module CoreExtensions
|
module CoreExtensions
|
||||||
module Collections
|
module Collections
|
||||||
|
@ -9,13 +11,13 @@ module Middleman
|
||||||
attr_reader :descriptors
|
attr_reader :descriptors
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@descriptors = []
|
@descriptors = ::Hamster.set
|
||||||
end
|
end
|
||||||
|
|
||||||
def method_missing(name, *args, &block)
|
def method_missing(name, *args, &block)
|
||||||
internal = :"_internal_#{name}"
|
internal = :"_internal_#{name}"
|
||||||
if respond_to?(internal)
|
if respond_to?(internal)
|
||||||
@descriptors << send(internal, *args, &block)
|
@descriptors = @descriptors.add(send(internal, *args, &block))
|
||||||
else
|
else
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
|
||||||
|
|
||||||
def initialize(*)
|
def initialize(*)
|
||||||
super
|
super
|
||||||
|
|
||||||
require 'i18n'
|
require 'i18n'
|
||||||
|
|
||||||
# Don't fail on invalid locale, that's not what our current
|
# Don't fail on invalid locale, that's not what our current
|
||||||
|
|
|
@ -179,15 +179,15 @@ module Middleman
|
||||||
http_opts[:SSLEnable] = true
|
http_opts[:SSLEnable] = true
|
||||||
|
|
||||||
if ssl_certificate || ssl_private_key
|
if ssl_certificate || ssl_private_key
|
||||||
raise "You must provide both :ssl_certificate and :ssl_private_key" unless ssl_private_key && ssl_certificate
|
raise 'You must provide both :ssl_certificate and :ssl_private_key' unless ssl_private_key && ssl_certificate
|
||||||
http_opts[:SSLCertificate] = OpenSSL::X509::Certificate.new File.read ssl_certificate
|
http_opts[:SSLCertificate] = OpenSSL::X509::Certificate.new File.read ssl_certificate
|
||||||
http_opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new File.read ssl_private_key
|
http_opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new File.read ssl_private_key
|
||||||
else
|
else
|
||||||
# use a generated self-signed cert
|
# use a generated self-signed cert
|
||||||
http_opts[:SSLCertName] = [
|
http_opts[:SSLCertName] = [
|
||||||
%w(CN localhost),
|
%w(CN localhost),
|
||||||
%w(CN #{host})
|
%w(CN #{host})
|
||||||
].uniq
|
].uniq
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Used for merging results of metadata callbacks
|
# Used for merging results of metadata callbacks
|
||||||
require 'active_support/core_ext/hash/deep_merge'
|
require 'active_support/core_ext/hash/deep_merge'
|
||||||
require 'monitor'
|
require 'monitor'
|
||||||
|
require 'hamster'
|
||||||
|
|
||||||
# Ignores
|
# Ignores
|
||||||
Middleman::Extensions.register :sitemap_ignore, auto_activate: :before_configuration do
|
Middleman::Extensions.register :sitemap_ignore, auto_activate: :before_configuration do
|
||||||
|
@ -37,6 +38,8 @@ require 'middleman-core/contracts'
|
||||||
module Middleman
|
module Middleman
|
||||||
# Sitemap namespace
|
# Sitemap namespace
|
||||||
module Sitemap
|
module Sitemap
|
||||||
|
ManipulatorDescriptor = Struct.new :name, :manipulator, :priority, :custom_name
|
||||||
|
|
||||||
# The Store class
|
# The Store class
|
||||||
#
|
#
|
||||||
# The Store manages a collection of Resource objects, which represent
|
# The Store manages a collection of Resource objects, which represent
|
||||||
|
@ -46,20 +49,21 @@ module Middleman
|
||||||
class Store
|
class Store
|
||||||
include Contracts
|
include Contracts
|
||||||
|
|
||||||
# @return [Middleman::Application]
|
Contract IsA['Middleman::Application']
|
||||||
attr_reader :app
|
attr_reader :app
|
||||||
|
|
||||||
|
Contract Num
|
||||||
attr_reader :update_count
|
attr_reader :update_count
|
||||||
|
|
||||||
# Initialize with parent app
|
# Initialize with parent app
|
||||||
# @param [Middleman::Application] app
|
# @param [Middleman::Application] app
|
||||||
|
Contract IsA['Middleman::Application'] => Any
|
||||||
def initialize(app)
|
def initialize(app)
|
||||||
@app = app
|
@app = app
|
||||||
@resources = []
|
@resources = []
|
||||||
@update_count = 0
|
@update_count = 0
|
||||||
|
|
||||||
# TODO: Should this be a set or hash?
|
@resource_list_manipulators = ::Hamster.vector
|
||||||
@resource_list_manipulators = []
|
|
||||||
@needs_sitemap_rebuild = true
|
@needs_sitemap_rebuild = true
|
||||||
|
|
||||||
@lock = Monitor.new
|
@lock = Monitor.new
|
||||||
|
@ -76,24 +80,29 @@ module Middleman
|
||||||
# @param [Numeric] priority Sets the order of this resource list manipulator relative to the rest. By default this is 50, and manipulators run in the order they are registered, but if a priority is provided then this will run ahead of or behind other manipulators.
|
# @param [Numeric] priority Sets the order of this resource list manipulator relative to the rest. By default this is 50, and manipulators run in the order they are registered, but if a priority is provided then this will run ahead of or behind other manipulators.
|
||||||
# @param [Symbol] custom_name The method name to execute.
|
# @param [Symbol] custom_name The method name to execute.
|
||||||
# @return [void]
|
# @return [void]
|
||||||
Contract Symbol, RespondTo['manipulate_resource_list'], Maybe[Num], Maybe[Symbol] => Any
|
Contract Symbol, RespondTo[:manipulate_resource_list], Maybe[Num], Maybe[Symbol] => Any
|
||||||
def register_resource_list_manipulator(name, manipulator, priority=50, custom_name=nil)
|
def register_resource_list_manipulator(name, manipulator, priority=50, custom_name=nil)
|
||||||
# The third argument used to be a boolean - handle those who still pass one
|
# The third argument used to be a boolean - handle those who still pass one
|
||||||
priority = 50 unless priority.is_a? Numeric
|
priority = 50 unless priority.is_a? Numeric
|
||||||
@resource_list_manipulators << [name, manipulator, priority, custom_name]
|
@resource_list_manipulators = @resource_list_manipulators.push(
|
||||||
|
ManipulatorDescriptor.new(name, manipulator, priority, custom_name)
|
||||||
|
)
|
||||||
|
|
||||||
# The index trick is used so that the sort is stable - manipulators with the same priority
|
# The index trick is used so that the sort is stable - manipulators with the same priority
|
||||||
# will always be ordered in the same order as they were registered.
|
# will always be ordered in the same order as they were registered.
|
||||||
n = 0
|
n = 0
|
||||||
@resource_list_manipulators = @resource_list_manipulators.sort_by do |m|
|
@resource_list_manipulators = @resource_list_manipulators.sort_by do |m|
|
||||||
n += 1
|
n += 1
|
||||||
[m[2], n]
|
[m[:priority], n]
|
||||||
end
|
end
|
||||||
|
|
||||||
rebuild_resource_list!(:registered_new)
|
rebuild_resource_list!(:registered_new)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Rebuild the list of resources from scratch, using registed manipulators
|
# Rebuild the list of resources from scratch, using registed manipulators
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def rebuild_resource_list!(_=nil)
|
Contract Maybe[Symbol] => Any
|
||||||
|
def rebuild_resource_list!(_name=nil)
|
||||||
@lock.synchronize do
|
@lock.synchronize do
|
||||||
@needs_sitemap_rebuild = true
|
@needs_sitemap_rebuild = true
|
||||||
end
|
end
|
||||||
|
@ -178,11 +187,13 @@ module Middleman
|
||||||
|
|
||||||
@app.logger.debug '== Rebuilding resource list'
|
@app.logger.debug '== Rebuilding resource list'
|
||||||
|
|
||||||
@resources = @resource_list_manipulators.reduce([]) do |result, (_, manipulator, _, custom_name)|
|
@resources = @resource_list_manipulators.reduce([]) do |result, m|
|
||||||
newres = manipulator.send(custom_name || :manipulate_resource_list, result)
|
newres = m[:manipulator].send(m[:custom_name] || :manipulate_resource_list, result)
|
||||||
|
|
||||||
# Reset lookup cache
|
# Reset lookup cache
|
||||||
reset_lookup_cache!
|
reset_lookup_cache!
|
||||||
|
|
||||||
|
# Rebuild cache
|
||||||
newres.each do |resource|
|
newres.each do |resource|
|
||||||
@_lookup_by_path[resource.path] = resource
|
@_lookup_by_path[resource.path] = resource
|
||||||
@_lookup_by_destination_path[resource.destination_path] = resource
|
@_lookup_by_destination_path[resource.destination_path] = resource
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
require 'hamster'
|
||||||
require 'middleman-core/contracts'
|
require 'middleman-core/contracts'
|
||||||
require 'backports/2.0.0/enumerable/lazy'
|
require 'backports/2.0.0/enumerable/lazy'
|
||||||
|
|
||||||
|
@ -47,10 +48,10 @@ module Middleman
|
||||||
@options = options
|
@options = options
|
||||||
|
|
||||||
# Set of procs wanting to be notified of changes
|
# Set of procs wanting to be notified of changes
|
||||||
@on_change_callbacks = []
|
@on_change_callbacks = ::Hamster.vector
|
||||||
|
|
||||||
# Global ignores
|
# Global ignores
|
||||||
@ignores = {}
|
@ignores = ::Hamster.hash
|
||||||
|
|
||||||
# Whether we're "running", which means we're in a stable
|
# Whether we're "running", which means we're in a stable
|
||||||
# watch state after all initialization and config.
|
# watch state after all initialization and config.
|
||||||
|
@ -72,7 +73,8 @@ module Middleman
|
||||||
# @return [void]
|
# @return [void]
|
||||||
Contract Symbol, Symbol, Or[Regexp, Proc] => Any
|
Contract Symbol, Symbol, Or[Regexp, Proc] => Any
|
||||||
def ignore(name, type, regex=nil, &block)
|
def ignore(name, type, regex=nil, &block)
|
||||||
@ignores[name] = { type: type, validator: (block_given? ? block : regex) }
|
@ignores = @ignores.put(name, type: type,
|
||||||
|
validator: (block_given? ? block : regex))
|
||||||
|
|
||||||
bump_count
|
bump_count
|
||||||
find_new_files! if @running
|
find_new_files! if @running
|
||||||
|
@ -238,11 +240,10 @@ module Middleman
|
||||||
# Add callback to be run on file change or deletion
|
# Add callback to be run on file change or deletion
|
||||||
#
|
#
|
||||||
# @param [Symbol] type The change type.
|
# @param [Symbol] type The change type.
|
||||||
# @return [Set<CallbackDescriptor>]
|
# @return [void]
|
||||||
Contract Symbol, Proc => ArrayOf[CallbackDescriptor]
|
Contract Symbol, Proc => Any
|
||||||
def on_change(type, &block)
|
def on_change(type, &block)
|
||||||
@on_change_callbacks << CallbackDescriptor.new(type, block)
|
@on_change_callbacks = @on_change_callbacks.push(CallbackDescriptor.new(type, block))
|
||||||
@on_change_callbacks
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Backwards compatible change handler.
|
# Backwards compatible change handler.
|
||||||
|
@ -328,7 +329,7 @@ module Middleman
|
||||||
# @param [Set] callback_descriptors The registered callbacks.
|
# @param [Set] callback_descriptors The registered callbacks.
|
||||||
# @param [Array<Middleman::SourceFile>] files The files that were changed.
|
# @param [Array<Middleman::SourceFile>] files The files that were changed.
|
||||||
# @return [void]
|
# @return [void]
|
||||||
Contract ArrayOf[CallbackDescriptor], ArrayOf[SourceFile], ArrayOf[SourceFile] => Any
|
Contract VectorOf[CallbackDescriptor], ArrayOf[SourceFile], ArrayOf[SourceFile] => Any
|
||||||
def run_callbacks(callback_descriptors, updated_files, removed_files)
|
def run_callbacks(callback_descriptors, updated_files, removed_files)
|
||||||
callback_descriptors.each do |callback|
|
callback_descriptors.each do |callback|
|
||||||
if callback[:type] == :all
|
if callback[:type] == :all
|
||||||
|
|
Loading…
Reference in a new issue