diff options
Diffstat (limited to 'app/services/packages/debian/parse_debian822_service.rb')
-rw-r--r-- | app/services/packages/debian/parse_debian822_service.rb | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/app/services/packages/debian/parse_debian822_service.rb b/app/services/packages/debian/parse_debian822_service.rb new file mode 100644 index 00000000000..665929d2324 --- /dev/null +++ b/app/services/packages/debian/parse_debian822_service.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +module Packages + module Debian + # Parse String as Debian RFC822 control data format + # https://manpages.debian.org/unstable/dpkg-dev/deb822.5 + class ParseDebian822Service + InvalidDebian822Error = Class.new(StandardError) + + def initialize(input) + @input = input + end + + def execute + output = {} + @input.each_line('', chomp: true) do |block| + section = {} + section_name, field = nil + block.each_line(chomp: true) do |line| + next if comment_line?(line) + + if continuation_line?(line) + raise InvalidDebian822Error, "Parse error. Unexpected continuation line" if field.nil? + + section[field] += "\n" + section[field] += line[1..] unless paragraph_separator?(line) + elsif match = match_section_line(line) + section_name = match[:name] if section_name.nil? + field = match[:field].to_sym + + raise InvalidDebian822Error, "Duplicate field '#{field}' in section '#{section_name}'" if section.include?(field) + + section[field] = match[:value] + else + raise InvalidDebian822Error, "Parse error on line #{line}" + end + end + + raise InvalidDebian822Error, "Duplicate section '#{section_name}'" if output[section_name] + + output[section_name] = section + end + + output + end + + private + + def comment_line?(line) + line.match?(/^#/) + end + + def continuation_line?(line) + line.match?(/^ /) + end + + def paragraph_separator?(line) + line == ' .' + end + + def match_section_line(line) + line.match(/(?<name>(?<field>^\S+):\s*(?<value>.*))/) + end + end + end +end |