debian-mirror-gitlab/app/services/packages/debian/parse_debian822_service.rb

67 lines
1.8 KiB
Ruby
Raw Normal View History

2021-01-29 00:20:46 +05:30
# 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