68 lines
1.6 KiB
Ruby
68 lines
1.6 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
module Gitlab
|
||
|
module Ci
|
||
|
module Interpolation
|
||
|
class Template
|
||
|
include Gitlab::Utils::StrongMemoize
|
||
|
|
||
|
attr_reader :blocks, :ctx
|
||
|
|
||
|
TooManyBlocksError = Class.new(StandardError)
|
||
|
InvalidBlockError = Class.new(StandardError)
|
||
|
|
||
|
MAX_BLOCKS = 10_000
|
||
|
|
||
|
def initialize(config, ctx)
|
||
|
@config = Interpolation::Config.fabricate(config)
|
||
|
@ctx = Interpolation::Context.fabricate(ctx)
|
||
|
@errors = []
|
||
|
@blocks = {}
|
||
|
|
||
|
interpolate! if valid?
|
||
|
end
|
||
|
|
||
|
def valid?
|
||
|
errors.none?
|
||
|
end
|
||
|
|
||
|
def errors
|
||
|
@errors + @config.errors + @ctx.errors + @blocks.values.flat_map(&:errors)
|
||
|
end
|
||
|
|
||
|
def size
|
||
|
@blocks.size
|
||
|
end
|
||
|
|
||
|
def interpolated
|
||
|
@result if valid?
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def interpolate!
|
||
|
@result = @config.replace! do |data|
|
||
|
Interpolation::Block.match(data) do |block, data|
|
||
|
evaluate_block(block, data)
|
||
|
end
|
||
|
end
|
||
|
rescue TooManyBlocksError
|
||
|
@errors.push('too many interpolation blocks')
|
||
|
rescue InvalidBlockError
|
||
|
@errors.push('interpolation interrupted by errors')
|
||
|
end
|
||
|
strong_memoize_attr :interpolate!
|
||
|
|
||
|
def evaluate_block(block, data)
|
||
|
block = (@blocks[block] ||= Interpolation::Block.new(block, data, ctx))
|
||
|
|
||
|
raise TooManyBlocksError if @blocks.count > MAX_BLOCKS
|
||
|
raise InvalidBlockError unless block.valid?
|
||
|
|
||
|
block.value
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|