1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
# 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
}.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.each_with_object({}) do |attribute, hash|
hash[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
|