Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/ci/interpolation/template.rb')
-rw-r--r--lib/gitlab/ci/interpolation/template.rb67
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/gitlab/ci/interpolation/template.rb b/lib/gitlab/ci/interpolation/template.rb
new file mode 100644
index 00000000000..0211279f266
--- /dev/null
+++ b/lib/gitlab/ci/interpolation/template.rb
@@ -0,0 +1,67 @@
+# 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