|
1 | 1 | # frozen_string_literal: true |
2 | 2 |
|
| 3 | +require 'puppetfile-resolver/puppetfile' |
3 | 4 | require 'puppetfile-resolver/puppetfile/parser/errors' |
4 | 5 | require 'puppetfile-resolver/puppetfile/document' |
5 | 6 | require 'puppetfile-resolver/puppetfile/parser/r10k_eval/dsl' |
@@ -51,8 +52,81 @@ def self.parse(puppetfile_contents) |
51 | 52 | raise err, e.backtrace |
52 | 53 | end |
53 | 54 |
|
| 55 | + # Post process magic comments |
| 56 | + post_process_flags!(document) |
| 57 | + |
| 58 | + # Freeze the flags so they can't be modified |
| 59 | + document.modules.each { |mod| mod.resolver_flags.freeze } |
| 60 | + |
54 | 61 | document |
55 | 62 | end |
| 63 | + |
| 64 | + # Parses a Puppetfile and applies the "magic comments" |
| 65 | + def self.post_process_flags!(document) |
| 66 | + flag_ranges = {} |
| 67 | + document.content.lines.each_with_index do |line, index| |
| 68 | + if (matches = line.match(%r{^\s*# resolver:disable ([A-Za-z\/,]+)(?:\s|$)})) |
| 69 | + flags_from_line(matches[1]).each do |flag| |
| 70 | + # Start a flag range if there isn't already one going |
| 71 | + next unless flag_ranges[flag].nil? |
| 72 | + flag_ranges[flag] = index |
| 73 | + end |
| 74 | + elsif (matches = line.match(%r{# resolver:disable ([A-Za-z\/,]+)(?:\s|$)})) |
| 75 | + flags_from_line(matches[1]).each do |flag| |
| 76 | + # Assert the flag if we're not already within a range |
| 77 | + next unless flag_ranges[flag].nil? |
| 78 | + assert_resolver_flag(document, flag, index, index) |
| 79 | + end |
| 80 | + elsif (matches = line.match(%r{^\s*# resolver:enable ([A-Za-z\/,]+)(?:\s|$)})) |
| 81 | + flags_from_line(matches[1]).each do |flag| |
| 82 | + # End a flag range if there isn't already one going |
| 83 | + next if flag_ranges[flag].nil? |
| 84 | + assert_resolver_flag(document, flag, flag_ranges[flag], index) |
| 85 | + flag_ranges.delete(flag) |
| 86 | + end |
| 87 | + end |
| 88 | + end |
| 89 | + |
| 90 | + return if flag_ranges.empty? |
| 91 | + # Any remaining flag ranges will be at the document end |
| 92 | + end_line = document.content.lines.count |
| 93 | + flag_ranges.each do |flag, start_line| |
| 94 | + assert_resolver_flag(document, flag, start_line, end_line) |
| 95 | + end |
| 96 | + end |
| 97 | + private_class_method :post_process_flags! |
| 98 | + |
| 99 | + # Extracts the flags from the text based definitions |
| 100 | + # @return [Array[Symbol]] |
| 101 | + def self.flags_from_line(line) |
| 102 | + line.split(',').map do |flag_name| |
| 103 | + case flag_name.downcase |
| 104 | + when 'dependency/puppet' |
| 105 | + PuppetfileResolver::Puppetfile::DISABLE_PUPPET_DEPENDENCY_FLAG |
| 106 | + when 'dependency/all' |
| 107 | + PuppetfileResolver::Puppetfile::DISABLE_ALL_DEPENDENCIES_FLAG |
| 108 | + else # rubocop:disable Style/EmptyElse We will be adding something here later |
| 109 | + # TODO: Should we log a warning/info here? |
| 110 | + nil |
| 111 | + end |
| 112 | + end.compact |
| 113 | + end |
| 114 | + private_class_method :flags_from_line |
| 115 | + |
| 116 | + # Sets the specified flag on modules which are between from_line to to_line |
| 117 | + def self.assert_resolver_flag(document, flag, from_line, to_line) |
| 118 | + document.modules.each do |mod| |
| 119 | + # If we don't know where the module is (?) then ignore it |
| 120 | + next if mod.location.start_line.nil? || mod.location.end_line.nil? |
| 121 | + |
| 122 | + # If the module doesn't span the range we're looking for (from_line --> to_line) ignore it |
| 123 | + next unless mod.location.start_line >= from_line && mod.location.start_line <= to_line || |
| 124 | + mod.location.end_line >= from_line && mod.location.end_line <= to_line |
| 125 | + mod.resolver_flags << flag unless mod.resolver_flags.include?(flag) |
| 126 | + end |
| 127 | + nil |
| 128 | + end |
| 129 | + private_class_method :assert_resolver_flag |
56 | 130 | end |
57 | 131 | end |
58 | 132 | end |
|
0 commit comments