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
|
# frozen_string_literal: true
module ExpandVariables
VARIABLES_REGEXP = /\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/.freeze
class << self
def expand(value, variables, expand_file_refs: true)
replace_with(value, variables) do |collection, last_match|
match_or_blank_value(collection, last_match, expand_file_refs: expand_file_refs)
end
end
def expand_existing(value, variables, expand_file_refs: true)
replace_with(value, variables) do |collection, last_match|
match_or_original_value(collection, last_match, expand_file_refs: expand_file_refs)
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:)
match = last_match[1] || last_match[2]
replacement = collection[match]
if replacement.nil?
nil
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:)
match_or_blank_value(collection, last_match, expand_file_refs: expand_file_refs) || last_match[0]
end
end
end
|