feat: 🔥 oh god
This commit is contained in:
parent
cdb5492bfe
commit
3c7f48016d
30 changed files with 708 additions and 280 deletions
|
@ -6,4 +6,6 @@ require_relative 'comfpile/core.rb'
|
|||
|
||||
require_relative 'comfpile/engines/filesource_engine.rb'
|
||||
require_relative 'comfpile/engines/parser_engine.rb'
|
||||
require_relative 'comfpile/engines/config_engine.rb'
|
||||
require_relative 'comfpile/engines/config_engine.rb'
|
||||
|
||||
require_relative 'comfpile/context.rb'
|
|
@ -8,6 +8,9 @@ module Comfpile
|
|||
class Artefact
|
||||
attr_reader :core, :engine
|
||||
|
||||
# @return [Comfpile::ContextKey] The context key of this artefact
|
||||
attr_reader :context
|
||||
|
||||
attr_reader :exit_state
|
||||
attr_reader :stage, :target
|
||||
|
||||
|
@ -32,6 +35,8 @@ module Comfpile
|
|||
# linking steps, but the objects can be built separately.
|
||||
attr_reader :referenced_artefacts
|
||||
|
||||
attr_reader :build_dir
|
||||
|
||||
# ARTEFACT STATES
|
||||
#
|
||||
# The following states are known to the system:
|
||||
|
@ -55,7 +60,7 @@ module Comfpile
|
|||
|
||||
@stage = stage
|
||||
@target = target
|
||||
@context = @core.sanitize_context context
|
||||
@context = @core.get_context_key context
|
||||
|
||||
@parent_artefact = nil
|
||||
|
||||
|
@ -76,6 +81,8 @@ module Comfpile
|
|||
|
||||
@exit_state = nil
|
||||
@running = false
|
||||
|
||||
@build_dir = opts[:build_dir] || @core.get_context_build_dir_path(self)
|
||||
end
|
||||
|
||||
def [](key)
|
||||
|
@ -109,7 +116,7 @@ module Comfpile
|
|||
@log_current_line = text
|
||||
@log_current_level = level
|
||||
|
||||
puts "> %-30s %s:\n %s" % [@stage, @target, text]
|
||||
print "\033[2K> %-30s %s: %s\r" % [@stage, @target, text]
|
||||
|
||||
nil
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ module Comfpile
|
|||
end
|
||||
|
||||
def craft(stage, target, context)
|
||||
context = @core.sanitize_context context
|
||||
context = @core.get_context_key context
|
||||
|
||||
@recipes.each do |recipe|
|
||||
match = target
|
||||
|
@ -25,10 +25,10 @@ module Comfpile
|
|||
next unless stage == recipe[:stage]
|
||||
end
|
||||
|
||||
if r = recipe[:regex]
|
||||
if not (r = recipe[:regex]).nil?
|
||||
if r.is_a? String
|
||||
next unless target == r
|
||||
else
|
||||
elsif r.is_a? Regexp
|
||||
match = r.match target
|
||||
next if match.nil?
|
||||
end
|
||||
|
@ -51,7 +51,7 @@ module Comfpile
|
|||
other.subpriority <=> self.subpriority
|
||||
end
|
||||
|
||||
def add_recipe(stage = nil, target_regex, &block)
|
||||
def add_recipe(stage, target_regex = nil, &block)
|
||||
@recipes << {
|
||||
regex: target_regex,
|
||||
stage: stage,
|
||||
|
|
|
@ -53,17 +53,7 @@ module Comfpile
|
|||
tags.empty?
|
||||
end
|
||||
|
||||
def hash
|
||||
@tag.hash
|
||||
end
|
||||
|
||||
def eql?(other)
|
||||
if(other.is_a? Symbol)
|
||||
@tag.eql? other
|
||||
elsif(other.is_a? ContextTag)
|
||||
@tag.eql? other.tag
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -119,78 +109,88 @@ module Comfpile
|
|||
raise ArgumentError, "Attempted to set child-parameter of another parameter!"
|
||||
end
|
||||
|
||||
current_hash[key[-1]] = value
|
||||
|
||||
value
|
||||
end
|
||||
alias set []=
|
||||
|
||||
def set_flag(key, value)
|
||||
set resolve_key(key).append(value), true
|
||||
end
|
||||
def get_flags(key)
|
||||
(@config_options&.dig(*resolve_key(key)) || {}).keys
|
||||
return @provider.provide_context(new_keys)
|
||||
end
|
||||
|
||||
def dig(arg0, *args)
|
||||
@config_options&.dig(arg0, *args)
|
||||
end
|
||||
|
||||
def append(key, value)
|
||||
key = resolve_key key
|
||||
array = @config_options&.dig(*key)
|
||||
|
||||
if array.nil?
|
||||
array = set key, []
|
||||
end
|
||||
|
||||
raise ArgumentError, "Attempted to append to a non-list parameter!" unless array.is_a? Array
|
||||
|
||||
array << value
|
||||
end
|
||||
alias append_to append
|
||||
|
||||
def assert(orig_key, value)
|
||||
key = resolve_key orig_key
|
||||
current_value = @config_options&.dig(*key)
|
||||
|
||||
if current_value.nil?
|
||||
set key, value
|
||||
elsif current_value != value
|
||||
raise ArgumentError, "Config key assertion failed! #{orig_key} should be #{value}, is #{current_value}!"
|
||||
end
|
||||
end
|
||||
|
||||
def build_config
|
||||
@config_options = nil
|
||||
|
||||
@seeder_blocks.sort { |block| block[:priority] }.each do |block|
|
||||
self.instance_exec(block, &block[:block])
|
||||
end
|
||||
|
||||
self.freeze
|
||||
def to_s
|
||||
"CTX[" + @context_symbol.to_s + "]"
|
||||
end
|
||||
alias inspect to_s
|
||||
end
|
||||
|
||||
class ContextConfigContainer
|
||||
|
||||
class ContextKeyProvider
|
||||
def initialize
|
||||
@context_configs_seeds = []
|
||||
@known_context_keys = Hash.new
|
||||
end
|
||||
|
||||
def find_seeds_for(context_tag)
|
||||
out = []
|
||||
def symbol_to_keys(symbol)
|
||||
raise ArgumentError, 'Input symbol needs to be a Symbol!' unless symbol.is_a? Symbol
|
||||
|
||||
@context_configs_seeds.each do |seed|
|
||||
seed_tags = seed[:context_tags]
|
||||
|
||||
seed_tags.each do |tag|
|
||||
out_keys = Hash.new
|
||||
|
||||
symbol.to_s.split(';').each do |key|
|
||||
if key =~ /(?<key>[^=]+)=(?<value>[^=]+)/
|
||||
out_keys[$~['key'].to_sym] = $~['value'].to_s
|
||||
else
|
||||
out_keys[key.to_sym] = true
|
||||
end
|
||||
end
|
||||
|
||||
out_keys
|
||||
end
|
||||
|
||||
def add_to_config(context_config)
|
||||
raise ArgumentError, "No context supplied!" unless context_config.is_a? ContextConfig
|
||||
def sanitize_keys(keys)
|
||||
out_keys = Hash.new
|
||||
|
||||
keys.each do |key, value|
|
||||
if value.is_a? TrueClass
|
||||
out_keys[key.to_sym] = true
|
||||
elsif (not value.nil?) and (not value.is_a? FalseClass)
|
||||
out_keys[key.to_sym] = value.to_s
|
||||
end
|
||||
end
|
||||
|
||||
out_keys
|
||||
end
|
||||
|
||||
def keys_to_symbol(keys)
|
||||
raise ArgumentError, 'Keys needs to be a Hash!' unless keys.is_a? Hash
|
||||
|
||||
keys.keys.sort.map do |key|
|
||||
value = keys[key]
|
||||
|
||||
if value.is_a? TrueClass
|
||||
key.to_s
|
||||
elsif value.is_a? FalseClass
|
||||
nil
|
||||
else
|
||||
"#{key}=#{value}"
|
||||
end
|
||||
end.compact.join(';').to_sym
|
||||
end
|
||||
|
||||
def provide_context(ctx)
|
||||
return ctx if ctx.is_a? ContextKey
|
||||
|
||||
orig_ctx = ctx
|
||||
|
||||
return @known_context_keys[ctx] if @known_context_keys.include? ctx
|
||||
|
||||
ctx = symbol_to_keys(ctx) if ctx.is_a? Symbol
|
||||
ctx = sanitize_keys(ctx)
|
||||
|
||||
ctx_symbol = keys_to_symbol(ctx)
|
||||
|
||||
if @known_context_keys.include? ctx
|
||||
existing_ctx = @known_context_keys[ctx]
|
||||
@known_context_keys[orig_ctx] = existing_ctx
|
||||
return existing_ctx
|
||||
end
|
||||
|
||||
new_ctx = ContextKey.new(self, ctx, ctx_symbol)
|
||||
|
||||
@known_context_keys[ctx] = new_ctx
|
||||
@known_context_keys[ctx_symbol] = new_ctx
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
require 'digest'
|
||||
|
||||
require_relative 'artefact_engine.rb'
|
||||
|
||||
require_relative 'context.rb'
|
||||
|
@ -7,7 +9,9 @@ module Comfpile
|
|||
class Core
|
||||
attr_reader :processing_stack
|
||||
|
||||
def initialize()
|
||||
def initialize(build_dir_path: File.join('/tmp/comfpile/', Digest::MD5.hexdigest(Dir.pwd)))
|
||||
@build_dir_path = File.expand_path(build_dir_path)
|
||||
|
||||
@artefact_engines = []
|
||||
@artefact_prio_counter = 0
|
||||
|
||||
|
@ -15,44 +19,18 @@ module Comfpile
|
|||
# First query is stage, second filename.
|
||||
@artefacts = {}
|
||||
|
||||
@valid_contexts = {}
|
||||
|
||||
# Stack-style processing queue for item processing
|
||||
@processing_stack = []
|
||||
|
||||
@context_key_provider = ContextKeyProvider.new()
|
||||
end
|
||||
|
||||
# Sanitize and unify context tags.
|
||||
# This function will take either an array of tags, or a symbol,
|
||||
# and sanitize and unify it to match a predictable context tag
|
||||
# format.
|
||||
#
|
||||
# Context tags are symbols containing a list of unique configs
|
||||
# types to use, separated by underscore ('_')
|
||||
#
|
||||
# @param [Array<Symbol,String>, Symbol] context The context to
|
||||
# sanitize
|
||||
#
|
||||
# @return [Symbol] Sanitized context. Unique, sorted list
|
||||
# of tags, joined into a Symbol.
|
||||
#
|
||||
def sanitize_context(context)
|
||||
if context.nil?
|
||||
return :default
|
||||
elsif context.is_a? Array
|
||||
new_context = context.uniq.sort.join('_').to_sym
|
||||
@valid_contexts[new_context] = true
|
||||
|
||||
return new_context
|
||||
elsif context.is_a? Symbol
|
||||
return context if @valid_contexts[context]
|
||||
return sanitize_context(context.to_s.split('_'))
|
||||
else
|
||||
raise ArgumentError, "Unknown context key type supplied!"
|
||||
end
|
||||
def get_context_key(key)
|
||||
return @context_key_provider.provide_context(key)
|
||||
end
|
||||
|
||||
def find_artefact(stage, file = :none, context = :default)
|
||||
context = sanitize_context(context)
|
||||
context = get_context_key(context)
|
||||
|
||||
@artefacts.dig(context, stage, file)
|
||||
end
|
||||
|
@ -73,7 +51,7 @@ module Comfpile
|
|||
# @return [Comfpile::Artefact, nil] Found or created artefact, or nil if nothing could be done
|
||||
#
|
||||
def craft_artefact(stage, file = :none, context = :default)
|
||||
context = sanitize_context(context)
|
||||
context = get_context_key(context)
|
||||
|
||||
artefact = find_artefact(stage, file, context)
|
||||
|
||||
|
@ -97,7 +75,7 @@ module Comfpile
|
|||
end
|
||||
|
||||
def add_artefact(stage, file = :none, context = :default, engine: nil, artefact_class: Comfpile::Artefact)
|
||||
context = sanitize_context context
|
||||
context = get_context_key context
|
||||
|
||||
return unless find_artefact(stage, file, context).nil?
|
||||
|
||||
|
@ -165,6 +143,12 @@ module Comfpile
|
|||
nil
|
||||
end
|
||||
|
||||
def get_context_build_dir_path(context)
|
||||
context = context.context if context.is_a? Artefact
|
||||
|
||||
File.expand_path(File.join(@build_dir_path, context.to_s))
|
||||
end
|
||||
|
||||
def execute_step
|
||||
return if @processing_stack.empty?
|
||||
# puts "Got #{@processing_stack.length} items..."
|
||||
|
@ -177,9 +161,14 @@ module Comfpile
|
|||
|
||||
# puts "Processing artefact #{artefact.stage} #{artefact.target}"
|
||||
|
||||
begin
|
||||
artefact.execute_step
|
||||
rescue ArtefactExecSkipError
|
||||
build_path = get_context_build_dir_path(artefact)
|
||||
FileUtils.mkpath build_path
|
||||
|
||||
Dir.chdir build_path do
|
||||
begin
|
||||
artefact.execute_step
|
||||
rescue ArtefactExecSkipError
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
|
|
|
@ -25,7 +25,9 @@ module Comfpile
|
|||
end
|
||||
|
||||
@config_file_artefact = craft_artefact(:sourcefile, File.join(@target, "comf.yml"))
|
||||
wait_on @config_file_artefact
|
||||
return if @config_file_artefact.nil?
|
||||
|
||||
wait_on @config_file_artefact
|
||||
|
||||
add_step do
|
||||
unless @config_file_artefact.nil?
|
||||
|
|
|
@ -6,18 +6,23 @@ module Comfpile
|
|||
alias path filename
|
||||
alias file filename
|
||||
|
||||
def initialize(*args, file: filename, **opts)
|
||||
def initialize(*args, file: nil, **opts)
|
||||
super(*args, **opts)
|
||||
|
||||
@filename = file
|
||||
@original_filename = file
|
||||
|
||||
unless File.exist? @filename
|
||||
unless File.exist? @original_filename
|
||||
fail! "File could not be loaded!"
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
# TODO add actual file reading/copying to build dir
|
||||
@filename = @target
|
||||
|
||||
add_step do
|
||||
FileUtils.mkpath File.dirname(@filename)
|
||||
FileUtils.cp @original_filename, @filename
|
||||
end
|
||||
end
|
||||
|
||||
def mtime
|
||||
|
@ -35,7 +40,7 @@ module Comfpile
|
|||
def craft(stage, target, context)
|
||||
return nil unless stage == :sourcefile
|
||||
|
||||
full_path = File.join(@root_path, target)
|
||||
full_path = File.expand_path(File.join(@root_path, target))
|
||||
|
||||
return nil unless File.exists? full_path
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ module Comfpile
|
|||
end
|
||||
|
||||
def sourcefile_dependency_step
|
||||
['include', 'require', 'reference'].map do |key|
|
||||
['include', 'require', 'reference'].each do |key|
|
||||
key_artefacts = resolve_sourcefile(find_parsed_parameters(key), optional: key == 'include')
|
||||
|
||||
@parsed_dependencies[key] = key_artefacts.map { |key| craft_artefact(:parsed, key) }
|
||||
|
|
171
lib/comfpile/old_context.rb
Normal file
171
lib/comfpile/old_context.rb
Normal file
|
@ -0,0 +1,171 @@
|
|||
|
||||
|
||||
module Comfpile
|
||||
class ContextTag
|
||||
def initialize(tag)
|
||||
@@known_tags ||= {}
|
||||
|
||||
case tag
|
||||
when Symbol, String
|
||||
precompiled = @@known_tags[tag.to_sym]
|
||||
|
||||
if not precompiled.nil?
|
||||
@tag = precompiled[:tag]
|
||||
@tag_array = precompiled[:array]
|
||||
else
|
||||
@tag_array = tag.to_s.split('_').uniq.sort
|
||||
|
||||
end
|
||||
when Array
|
||||
@tag_array = tag.map(&:to_s).uniq.sort
|
||||
@tag = @tag_array
|
||||
end
|
||||
|
||||
@tag ||= @tag_array.join('_').to_sym
|
||||
|
||||
tag_data = {
|
||||
tag: @tag,
|
||||
array: @ŧag_array
|
||||
}
|
||||
|
||||
@@known_tags[@tag] ||= tag_data
|
||||
@@known_tags[tag] ||= tag_data
|
||||
end
|
||||
|
||||
|
||||
def self.tagify(tag)
|
||||
@known_tags ||= {}
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
# This class represents the configuration of a specific context.
|
||||
# It has two main jobs:
|
||||
# To provide functions to set up and merge configuration options
|
||||
# from the various tags given to it, and
|
||||
# to give reader options for the various config options.
|
||||
#
|
||||
# Most importantly, it contains mechanisms for safely setting up
|
||||
# configurations and flagging issues.
|
||||
#
|
||||
class ContextConfig
|
||||
attr_reader :context_tag
|
||||
|
||||
attr_reader :config_options
|
||||
|
||||
def initialize(context_tag, parent)
|
||||
@context_tag = context_tag
|
||||
|
||||
@seeder_blocks = []
|
||||
|
||||
@config_options = nil
|
||||
end
|
||||
|
||||
def add_seeder_block(priority, &block)
|
||||
@seeder_blocks << {
|
||||
priority: priority,
|
||||
block: block
|
||||
}
|
||||
end
|
||||
|
||||
def resolve_key(key)
|
||||
if key.is_a? Array
|
||||
return key.map {|k| k.to_sym }
|
||||
elsif key.is_a? String
|
||||
return key.split('.').map {|k| k.to_sym }
|
||||
elsif key.is_a? Symbol
|
||||
return resolve_key(key.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
def [](key)
|
||||
@config_options&.dig(*resolve_key(key))
|
||||
end
|
||||
def []=(key, value)
|
||||
key = resolve_key(key)
|
||||
|
||||
current_hash = (@config_options ||= {})
|
||||
key[0..-2].each do |key|
|
||||
current_hash = (current_hash[key] ||= {})
|
||||
next if current_hash.is_a? Hash
|
||||
raise ArgumentError, "Attempted to set child-parameter of another parameter!"
|
||||
end
|
||||
|
||||
current_hash[key[-1]] = value
|
||||
|
||||
value
|
||||
end
|
||||
alias set []=
|
||||
|
||||
def set_flag(key, value)
|
||||
set resolve_key(key).append(value), true
|
||||
end
|
||||
def get_flags(key)
|
||||
(@config_options&.dig(*resolve_key(key)) || {}).keys
|
||||
end
|
||||
|
||||
def dig(arg0, *args)
|
||||
@config_options&.dig(arg0, *args)
|
||||
end
|
||||
|
||||
def append(key, value)
|
||||
key = resolve_key key
|
||||
array = @config_options&.dig(*key)
|
||||
|
||||
if array.nil?
|
||||
array = set key, []
|
||||
end
|
||||
|
||||
raise ArgumentError, "Attempted to append to a non-list parameter!" unless array.is_a? Array
|
||||
|
||||
array << value
|
||||
end
|
||||
alias append_to append
|
||||
|
||||
def assert(orig_key, value)
|
||||
key = resolve_key orig_key
|
||||
current_value = @config_options&.dig(*key)
|
||||
|
||||
if current_value.nil?
|
||||
set key, value
|
||||
elsif current_value != value
|
||||
raise ArgumentError, "Config key assertion failed! #{orig_key} should be #{value}, is #{current_value}!"
|
||||
end
|
||||
end
|
||||
|
||||
def build_config
|
||||
@config_options = nil
|
||||
|
||||
@seeder_blocks.sort { |block| block[:priority] }.each do |block|
|
||||
self.instance_exec(block, &block[:block])
|
||||
end
|
||||
|
||||
self.freeze
|
||||
end
|
||||
end
|
||||
|
||||
class ContextConfigContainer
|
||||
def initialize
|
||||
@context_configs_seeds = []
|
||||
end
|
||||
|
||||
def find_seeds_for(context_tag)
|
||||
out = []
|
||||
|
||||
@context_configs_seeds.each do |seed|
|
||||
seed_tags = seed[:context_tags]
|
||||
|
||||
seed_tags.each do |tag|
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def add_to_config(context_config)
|
||||
raise ArgumentError, "No context supplied!" unless context_config.is_a? ContextConfig
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue