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

expand_variables.rb « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ad5aabfa1f3b181f5845ddfe1600a04f1b8ed147 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# frozen_string_literal: true

module ExpandVariables
  VariableExpansionError = Class.new(StandardError)

  VARIABLES_REGEXP = /\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/

  class << self
    def expand(value, variables, expand_file_refs: true, fail_on_masked: false)
      replace_with(value, variables) do |collection, last_match|
        match_or_blank_value(
          collection, last_match, expand_file_refs: expand_file_refs, fail_on_masked: fail_on_masked
        )
      end
    end

    def expand_existing(value, variables, expand_file_refs: true, fail_on_masked: false)
      replace_with(value, variables) do |collection, last_match|
        match_or_original_value(
          collection, last_match, expand_file_refs: expand_file_refs, fail_on_masked: fail_on_masked
        )
      end
    end

    def possible_var_reference?(value)
      return unless value

      %w[$ %].any? { |symbol| value.include?(symbol) }
    end

    private

    def replace_with(value, variables)
      # We lazily fabricate the variables collection in case there is no variable in the value string.
      # `collection` needs to be initialized to nil here
      # so that it is memoized in the closure block for `gsub`.
      collection = nil

      value.gsub(VARIABLES_REGEXP) do
        collection ||= Gitlab::Ci::Variables::Collection.fabricate(variables)
        yield(collection, Regexp.last_match)
      end
    end

    def match_or_blank_value(collection, last_match, expand_file_refs:, fail_on_masked:)
      match = last_match[1] || last_match[2]
      replacement = collection[match]

      if replacement.nil?
        nil
      elsif fail_on_masked && replacement.masked?
        raise VariableExpansionError, 'masked variables cannot be expanded'
      elsif replacement.file?
        expand_file_refs ? replacement.value : last_match
      else
        replacement.value
      end
    end

    def match_or_original_value(collection, last_match, expand_file_refs:, fail_on_masked:)
      match_or_blank_value(
        collection, last_match, expand_file_refs: expand_file_refs, fail_on_masked: fail_on_masked
      ) || last_match[0]
    end
  end
end