debian-mirror-gitlab/app/services/packages/rpm/parse_package_service.rb
2023-03-05 14:24:40 +05:30

85 lines
2.7 KiB
Ruby

# frozen_string_literal: true
module Packages
module Rpm
class ParsePackageService
include ::Gitlab::Utils::StrongMemoize
BUILD_ATTRIBUTES_METHOD_NAMES = %i[changelogs requirements provides].freeze
STATIC_ATTRIBUTES = %i[name version release summary description arch
license sourcerpm group buildhost packager vendor].freeze
CHANGELOGS_RPM_KEYS = %i[changelogtext changelogtime].freeze
REQUIREMENTS_RPM_KEYS = %i[requirename requireversion requireflags].freeze
PROVIDES_RPM_KEYS = %i[providename provideflags provideversion].freeze
def initialize(package_file)
@rpm = RPM::File.new(package_file)
end
def execute
raise ArgumentError, 'Unable to parse package' unless valid_package?
{
files: rpm.files || [],
epoch: package_tags[:epoch] || '0',
changelogs: build_changelogs,
requirements: build_requirements,
provides: build_provides,
directories: package_tags[:dirnames]
}.merge(extract_static_attributes)
end
private
attr_reader :rpm
def valid_package?
rpm.files && package_tags && true
rescue RuntimeError
# if arr-pm throws an error due to an incorrect file format,
# we just want this validation to fail rather than throw an exception
false
end
def package_tags
strong_memoize(:package_tags) do
rpm.tags
end
end
def extract_static_attributes
STATIC_ATTRIBUTES.index_with do |attribute|
package_tags[attribute]
end
end
# Define methods for building RPM attribute data from parsed package
# Transform
# changelogtime: [123, 234],
# changelogname: ["First", "Second"]
# changelogtext: ["Work1", "Work2"]
# Into
# changelog: [
# {changelogname: "First", changelogtext: "Work1", changelogtime: 123},
# {changelogname: "Second", changelogtext: "Work2", changelogtime: 234}
# ]
BUILD_ATTRIBUTES_METHOD_NAMES.each do |resource|
define_method("build_#{resource}") do
resource_keys = self.class.const_get("#{resource.upcase}_RPM_KEYS", false).dup
return [] if resource_keys.any? { package_tags[_1].blank? }
first_attributes = package_tags[resource_keys.first]
zipped_data = first_attributes.zip(*resource_keys[1..].map { package_tags[_1] })
build_hashes(resource_keys, zipped_data)
end
end
def build_hashes(resource_keys, zipped_data)
zipped_data.map do |data|
resource_keys.zip(data).to_h
end
end
end
end
end