File indexing completed on 2024-04-21 05:08:03

0001 # frozen_string_literal: true
0002 #
0003 # Copyright (C) 2016 Harald Sitter <sitter@kde.org>
0004 #
0005 # This library is free software; you can redistribute it and/or
0006 # modify it under the terms of the GNU Lesser General Public
0007 # License as published by the Free Software Foundation; either
0008 # version 2.1 of the License, or (at your option) version 3, or any
0009 # later version accepted by the membership of KDE e.V. (or its
0010 # successor approved by the membership of KDE e.V.), which shall
0011 # act as a proxy defined in Section 6 of version 3 of the license.
0012 #
0013 # This library is distributed in the hope that it will be useful,
0014 # but WITHOUT ANY WARRANTY; without even the implied warranty of
0015 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016 # Lesser General Public License for more details.
0017 #
0018 # You should have received a copy of the GNU Lesser General Public
0019 # License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0020 
0021 require 'nokogiri'
0022 
0023 module Debian
0024   class UScan
0025     # State identifier strings.
0026     module States
0027       NEWER_AVAILABLE = 'Newer version available'.freeze
0028       UP_TO_DATE = 'up to date'.freeze
0029       DEBIAN_NEWER = 'Debian version newer than remote site'.freeze
0030       OLDER_ONLY = 'only older package available'.freeze
0031 
0032       # Compatiblity map because uscan randomly changes the bloody strings.
0033       # @param [String] string actual uscan string we want to map
0034       # @return [String] const representation of that string
0035       def self.map(string)
0036         case string
0037         when 'newer package available'
0038           NEWER_AVAILABLE
0039         else
0040           string
0041         end
0042       end
0043     end
0044 
0045     # UScan's debian external health status format parser.
0046     class DEHS
0047       class ParseError < StandardError; end
0048 
0049       # A Package status report.
0050       class Package
0051         attr_reader :name
0052         attr_reader :status
0053         attr_reader :upstream_version
0054         attr_reader :upstream_url
0055 
0056         def initialize(name)
0057           @name = name
0058         end
0059 
0060         # Sets instance variable according to XML element.
0061         def _apply_element(element)
0062           instance_variable_set(to_instance(element.name), element.content)
0063         end
0064 
0065         private
0066 
0067         def to_instance(str)
0068           "@#{str.tr('-', '_')}".to_sym
0069         end
0070       end
0071 
0072       class << self
0073         def parse_packages(xml)
0074           packages = []
0075           Nokogiri::XML(xml).root.elements.each do |element|
0076             if element.name == 'package'
0077               next packages << Package.new(element.content)
0078             end
0079             verify_status(element)
0080             packages[-1]._apply_element(element)
0081           end
0082           packages
0083         end
0084 
0085         private
0086 
0087         def verify_status(element)
0088           return unless element.name == 'status'
0089           # Edit the content to the mapped value, so we always get consistent
0090           # strings.
0091           element.content = States.map(element.content)
0092           return if States.constants.any? do |const|
0093             States.const_get(const) == element.content
0094           end
0095           raise ParseError, "Unmapped status: '#{element.content}'"
0096         end
0097       end
0098     end
0099   end
0100 end