summaryrefslogtreecommitdiff
path: root/app/services/packages/debian/parse_debian822_service.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/packages/debian/parse_debian822_service.rb')
-rw-r--r--app/services/packages/debian/parse_debian822_service.rb66
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