arr-pm 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of arr-pm might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/Guardfile +77 -0
- data/arr-pm.gemspec +1 -1
- data/lib/arr-pm/file.rb +6 -4
- data/lib/arr-pm/file/header.rb +2 -10
- data/lib/arr-pm/namespace.rb +6 -0
- data/lib/arr-pm/v2/architecture.rb +32 -0
- data/lib/arr-pm/v2/error.rb +32 -0
- data/lib/arr-pm/v2/format.rb +16 -0
- data/lib/arr-pm/v2/header.rb +35 -0
- data/lib/arr-pm/v2/header_header.rb +36 -0
- data/lib/arr-pm/v2/lead.rb +121 -0
- data/lib/arr-pm/v2/package.rb +18 -0
- data/lib/arr-pm/v2/tag.rb +295 -0
- data/lib/arr-pm/v2/type.rb +15 -0
- data/spec/arr-pm/v2/header_spec.rb +34 -0
- data/spec/arr-pm/v2/lead_spec.rb +125 -0
- data/spec/fixtures/example-1.0-1.x86_64.rpm +0 -0
- data/spec/fixtures/example.json +55 -0
- metadata +21 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ceb08ab00b24c659ee4f0fd42d8f5c8ad77416ffff3f89e8ee18ec46ddc58383
|
4
|
+
data.tar.gz: b53d4d64c24362fb2cf27606842d8352e9f7d184f9ba3b76eb1e33b3e13b2775
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 441b7c7a0d0851c3c4cadaf7e2e0f20d32388ba4df722ee3f76bfb3a34bb072739daf63739cf19e9d8f221a40a80f999ca47b2825043ded493d1f3363dec3e54
|
7
|
+
data.tar.gz: 815d8fff66bc8672b7e212f6c138795a9029b5e78032d26051ac114e306084f97d01519060427aeb50e9bca29dd49af5d5567370904d8881fc99179184811cd3
|
data/Guardfile
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features)
|
6
|
+
|
7
|
+
## Uncomment to clear the screen before every task
|
8
|
+
# clearing :on
|
9
|
+
|
10
|
+
## Guard internally checks for changes in the Guardfile and exits.
|
11
|
+
## If you want Guard to automatically start up again, run guard in a
|
12
|
+
## shell loop, e.g.:
|
13
|
+
##
|
14
|
+
## $ while bundle exec guard; do echo "Restarting Guard..."; done
|
15
|
+
##
|
16
|
+
## Note: if you are using the `directories` clause above and you are not
|
17
|
+
## watching the project directory ('.'), then you will want to move
|
18
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
19
|
+
#
|
20
|
+
# $ mkdir config
|
21
|
+
# $ mv Guardfile config/
|
22
|
+
# $ ln -s config/Guardfile .
|
23
|
+
#
|
24
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
25
|
+
|
26
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
27
|
+
# rspec may be run, below are examples of the most common uses.
|
28
|
+
# * bundler: 'bundle exec rspec'
|
29
|
+
# * bundler binstubs: 'bin/rspec'
|
30
|
+
# * spring: 'bin/rspec' (This will use spring if running and you have
|
31
|
+
# installed the spring binstubs per the docs)
|
32
|
+
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
33
|
+
# * 'just' rspec: 'rspec'
|
34
|
+
|
35
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
36
|
+
require "guard/rspec/dsl"
|
37
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
38
|
+
|
39
|
+
# Feel free to open issues for suggestions and improvements
|
40
|
+
|
41
|
+
# RSpec files
|
42
|
+
rspec = dsl.rspec
|
43
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
44
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
45
|
+
watch(rspec.spec_files)
|
46
|
+
|
47
|
+
# Ruby files
|
48
|
+
ruby = dsl.ruby
|
49
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
50
|
+
|
51
|
+
# Rails files
|
52
|
+
rails = dsl.rails(view_extensions: %w(erb haml slim))
|
53
|
+
dsl.watch_spec_files_for(rails.app_files)
|
54
|
+
dsl.watch_spec_files_for(rails.views)
|
55
|
+
|
56
|
+
watch(rails.controllers) do |m|
|
57
|
+
[
|
58
|
+
rspec.spec.("routing/#{m[1]}_routing"),
|
59
|
+
rspec.spec.("controllers/#{m[1]}_controller"),
|
60
|
+
rspec.spec.("acceptance/#{m[1]}")
|
61
|
+
]
|
62
|
+
end
|
63
|
+
|
64
|
+
# Rails config changes
|
65
|
+
watch(rails.spec_helper) { rspec.spec_dir }
|
66
|
+
watch(rails.routes) { "#{rspec.spec_dir}/routing" }
|
67
|
+
watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
|
68
|
+
|
69
|
+
# Capybara features specs
|
70
|
+
watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
|
71
|
+
|
72
|
+
# Turnip features and steps
|
73
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
74
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
|
75
|
+
Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
|
76
|
+
end
|
77
|
+
end
|
data/arr-pm.gemspec
CHANGED
@@ -2,7 +2,7 @@ Gem::Specification.new do |spec|
|
|
2
2
|
files = %x{git ls-files}.split("\n")
|
3
3
|
|
4
4
|
spec.name = "arr-pm"
|
5
|
-
spec.version = "0.0.
|
5
|
+
spec.version = "0.0.11"
|
6
6
|
spec.summary = "RPM reader and writer library"
|
7
7
|
spec.description = "This library allows to you to read and write rpm " \
|
8
8
|
"packages. Written in pure ruby because librpm is not available " \
|
data/lib/arr-pm/file.rb
CHANGED
@@ -179,10 +179,12 @@ class RPM::File
|
|
179
179
|
results = []
|
180
180
|
# short-circuit if there's no :fileflags tag
|
181
181
|
return results unless tags.include?(:fileflags)
|
182
|
-
tags[:fileflags].
|
183
|
-
|
184
|
-
|
185
|
-
|
182
|
+
if !tags[:fileflags].nil?
|
183
|
+
tags[:fileflags].each_with_index do |flag, i|
|
184
|
+
# The :fileflags (and other :file... tags) are an array, in order of
|
185
|
+
# files in the rpm payload, we want a list of paths of config files.
|
186
|
+
results << files[i] if mask?(flag, FLAG_CONFIG_FILE)
|
187
|
+
end
|
186
188
|
end
|
187
189
|
return results
|
188
190
|
end # def config_files
|
data/lib/arr-pm/file/header.rb
CHANGED
@@ -12,16 +12,8 @@ class RPM::File::Header
|
|
12
12
|
attr_accessor :data_length # rpmlib calls this field 'dl' unhelpfully
|
13
13
|
|
14
14
|
HEADER_SIGNED_TYPE = 5
|
15
|
-
|
16
|
-
|
17
|
-
# Ruby 2 forces all strings to be UTF-8, so "\x01" becomes "\u0001"
|
18
|
-
# which is two bytes 00 01 which is not what we want. I can't find
|
19
|
-
# a sane way to create a string without this madness in Ruby 2,
|
20
|
-
# so let's just pack two 4-byte integers and go about our day.
|
21
|
-
HEADER_MAGIC = [0x8eade801, 0x00000000].pack("NN")
|
22
|
-
else
|
23
|
-
HEADER_MAGIC = "\x8e\xad\xe8\x01\x00\x00\x00\x00"
|
24
|
-
end
|
15
|
+
HEADER_MAGIC = "\x8e\xad\xe8\x01\x00\x00\x00\x00".force_encoding("BINARY")
|
16
|
+
|
25
17
|
# magic + index_count + data_length
|
26
18
|
HEADER_HEADER_LENGTH = HEADER_MAGIC.length + 4 + 4
|
27
19
|
TAG_ENTRY_SIZE = 16 # tag id, type, offset, count == 16 bytes
|
data/lib/arr-pm/namespace.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "arr-pm/namespace"
|
2
|
+
|
3
|
+
module ArrPM::V2::Architecture
|
4
|
+
|
5
|
+
NOARCH = 0
|
6
|
+
I386 = 1
|
7
|
+
ALPHA = 2
|
8
|
+
SPARC = 3
|
9
|
+
MIPS = 4
|
10
|
+
PPC = 5
|
11
|
+
M68K = 6
|
12
|
+
IP = 7
|
13
|
+
RS6000 = 8
|
14
|
+
IA64 = 9
|
15
|
+
SPARC64 = 10
|
16
|
+
MIPSEL = 11
|
17
|
+
ARM = 12
|
18
|
+
MK68KMINT = 13
|
19
|
+
S390 = 14
|
20
|
+
S390X = 15
|
21
|
+
PPC64 = 16
|
22
|
+
SH = 17
|
23
|
+
XTENSA = 18
|
24
|
+
X86_64 = 19
|
25
|
+
|
26
|
+
module_function
|
27
|
+
|
28
|
+
# Is a given rpm architecture value valid?
|
29
|
+
def valid?(value)
|
30
|
+
return value >= 0 && value <= 19
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "arr-pm/namespace"
|
4
|
+
require "arr-pm/v2/format"
|
5
|
+
|
6
|
+
module ArrPM::V2::Error
|
7
|
+
class Base < StandardError; end
|
8
|
+
|
9
|
+
class InvalidMagicValue < Base
|
10
|
+
def initialize(value)
|
11
|
+
super("Got invalid magic value '#{value}'. Expected #{ArrPM::V2::Format::MAGIC}.")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class InvalidHeaderMagicValue < Base
|
16
|
+
def initialize(value)
|
17
|
+
super("Got invalid magic value '#{value}'. Expected #{ArrPM::V2::HeaderHeader::MAGIC}.")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class EmptyFile < Base; end
|
22
|
+
class ShortFile < Base; end
|
23
|
+
class InvalidVersion < Base; end
|
24
|
+
class InvalidType < Base
|
25
|
+
def initialize(value)
|
26
|
+
super("Invalid type: #{value.inspect}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
class InvalidName < Base; end
|
30
|
+
class InvalidArchitecture < Base; end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "arr-pm/namespace"
|
4
|
+
|
5
|
+
module ArrPM::V2::Format
|
6
|
+
MAGIC = [0x8e, 0xad, 0xe8]
|
7
|
+
MAGIC_LENGTH = MAGIC.count
|
8
|
+
MAGIC_STRING = MAGIC.pack("C#{MAGIC_LENGTH}")
|
9
|
+
|
10
|
+
module_function
|
11
|
+
def valid_magic?(magic)
|
12
|
+
magic = magic.bytes if magic.is_a?(String)
|
13
|
+
|
14
|
+
magic == MAGIC
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "arr-pm/namespace"
|
4
|
+
require "arr-pm/v2/format"
|
5
|
+
require "arr-pm/v2/header_header"
|
6
|
+
require "arr-pm/v2/tag"
|
7
|
+
require "arr-pm/v2/error"
|
8
|
+
|
9
|
+
class ArrPM::V2::Header
|
10
|
+
attr_reader :tags
|
11
|
+
|
12
|
+
def load(io)
|
13
|
+
headerheader = ArrPM::V2::HeaderHeader.new
|
14
|
+
headerheader.load(io)
|
15
|
+
headerdata = io.read(headerheader.entries * 16)
|
16
|
+
tagdata = io.read(headerheader.bytesize)
|
17
|
+
parse(headerdata, headerheader.entries, tagdata)
|
18
|
+
|
19
|
+
# signature headers are padded up to an 8-byte boundar, details here:
|
20
|
+
# http://rpm.org/gitweb?p=rpm.git;a=blob;f=lib/signature.c;h=63e59c00f255a538e48cbc8b0cf3b9bd4a4dbd56;hb=HEAD#l204
|
21
|
+
# Throw away the pad.
|
22
|
+
io.read(tagdata.length % 8)
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse(data, entry_count, tagdata)
|
26
|
+
@tags = entry_count.times.collect do |i|
|
27
|
+
tag_number, type_number, offset, count = data[i * 16, 16].unpack("NNNN")
|
28
|
+
|
29
|
+
tag = ArrPM::V2::Tag.new(tag_number, type_number)
|
30
|
+
tag.parse(tagdata, offset, count)
|
31
|
+
tag
|
32
|
+
end
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "arr-pm/namespace"
|
4
|
+
require "arr-pm/v2/format"
|
5
|
+
require "arr-pm/v2/error"
|
6
|
+
|
7
|
+
# The header of an rpm has ... a header. Funky naming :)
|
8
|
+
class ArrPM::V2::HeaderHeader
|
9
|
+
MAGIC = [ 0x8e, 0xad, 0xe8 ]
|
10
|
+
MAGIC_LENGTH = MAGIC.count
|
11
|
+
|
12
|
+
attr_accessor :version, :entries, :bytesize
|
13
|
+
|
14
|
+
def load(io)
|
15
|
+
data = io.read(16)
|
16
|
+
parse(data)
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse(data)
|
20
|
+
magic, version, reserved, entries, bytesize = data.unpack("a3Ca4NN")
|
21
|
+
self.class.validate_magic(magic.bytes)
|
22
|
+
|
23
|
+
@version = version
|
24
|
+
@entries = entries
|
25
|
+
@bytesize = bytesize
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def dump
|
30
|
+
[magic, 1, 0, @entries, @bytesize].pack("a3Ca4NN")
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.validate_magic(value)
|
34
|
+
raise ArrPM::V2::Error::InvalidHeaderMagicValue, value if value != MAGIC
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "arr-pm/namespace"
|
4
|
+
require "arr-pm/v2/format"
|
5
|
+
require "arr-pm/v2/error"
|
6
|
+
|
7
|
+
class ArrPM::V2::Lead
|
8
|
+
LENGTH = 96
|
9
|
+
MAGIC = [ 0xed, 0xab, 0xee, 0xdb ]
|
10
|
+
MAGIC_LENGTH = MAGIC.count
|
11
|
+
|
12
|
+
SIGNED_TYPE = 5
|
13
|
+
|
14
|
+
attr_accessor :major, :minor, :type, :architecture, :name, :os, :signature_type, :reserved
|
15
|
+
|
16
|
+
def validate
|
17
|
+
self.class.validate_type(type)
|
18
|
+
self.class.validate_architecture(architecture)
|
19
|
+
if name.length > 65
|
20
|
+
raise ArrPM::V2::Error::InvalidName, "Name is longer than 65 chracters. This is invalid."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def dump(io)
|
25
|
+
io.write(serialize)
|
26
|
+
end
|
27
|
+
|
28
|
+
def serialize
|
29
|
+
validate
|
30
|
+
[ *MAGIC, major, minor, type, architecture, name, os, signature_type, *reserved ].pack("C4CCnnZ66nnC16")
|
31
|
+
end
|
32
|
+
|
33
|
+
def load(io)
|
34
|
+
data = io.read(LENGTH)
|
35
|
+
parse(data)
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse(bytestring)
|
39
|
+
raise ArrPM::V2::Error::EmptyFile if bytestring.nil?
|
40
|
+
data = bytestring.bytes
|
41
|
+
|
42
|
+
@magic = self.class.parse_magic(data)
|
43
|
+
@major, @minor = self.class.parse_version(data)
|
44
|
+
@type = self.class.parse_type(data)
|
45
|
+
@architecture = self.class.parse_architecture(data)
|
46
|
+
@name = self.class.parse_name(data)
|
47
|
+
@os = self.class.parse_os(data)
|
48
|
+
@signature_type = self.class.parse_signature_type(data)
|
49
|
+
@reserved = self.class.parse_reserved(data)
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def signature?
|
54
|
+
@signature_type == SIGNED_TYPE
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.valid_version?(version)
|
58
|
+
version == 1
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.parse_magic(data)
|
62
|
+
magic = data[0, MAGIC_LENGTH]
|
63
|
+
validate_magic(magic)
|
64
|
+
magic
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.validate_magic(magic)
|
68
|
+
raise ArrPM::V2::Error::InvalidMagicValue, magic unless magic == MAGIC
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.parse_version(data)
|
72
|
+
offset = MAGIC_LENGTH
|
73
|
+
major, minor = data[offset, 2]
|
74
|
+
return major, minor
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.parse_type(data)
|
78
|
+
offset = MAGIC_LENGTH + 2
|
79
|
+
type = data[offset, 2].pack("CC").unpack("n").first
|
80
|
+
validate_type(type)
|
81
|
+
type
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.validate_type(type)
|
85
|
+
raise ArrPM::V2::Error::InvalidType, type unless ArrPM::V2::Type.valid?(type)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.parse_architecture(data)
|
89
|
+
offset = MAGIC_LENGTH + 4
|
90
|
+
architecture = data[offset, 2].pack("C*").unpack("n").first
|
91
|
+
validate_architecture(architecture)
|
92
|
+
architecture
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.validate_architecture(architecture)
|
96
|
+
raise ArrPM::V2::Error::InvalidArchitecture unless ArrPM::V2::Architecture.valid?(architecture)
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.parse_name(data)
|
100
|
+
offset = MAGIC_LENGTH + 6
|
101
|
+
name = data[offset, 66]
|
102
|
+
length = name.find_index(0) # find the first null byte
|
103
|
+
raise ArrPM::V2::Error::InvalidName unless length
|
104
|
+
return name[0, length].pack("C*")
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.parse_os(data)
|
108
|
+
offset = MAGIC_LENGTH + 72
|
109
|
+
data[offset, 2].pack("C*").unpack("n").first
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.parse_signature_type(data)
|
113
|
+
offset = MAGIC_LENGTH + 74
|
114
|
+
data[offset, 2].pack("C*").unpack("n").first
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.parse_reserved(data)
|
118
|
+
offset = MAGIC_LENGTH + 76
|
119
|
+
data[offset, 16]
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "arr-pm/namespace"
|
4
|
+
|
5
|
+
class ArrPM::V2::RPM
|
6
|
+
attr_accessor :name
|
7
|
+
attr_accessor :epoch
|
8
|
+
attr_accessor :version
|
9
|
+
attr_accessor :release
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
defaults
|
13
|
+
end
|
14
|
+
|
15
|
+
def defaults
|
16
|
+
@type = Type::BINARY
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,295 @@
|
|
1
|
+
require "arr-pm/namespace"
|
2
|
+
|
3
|
+
class ArrPM::V2::Tag
|
4
|
+
module Type
|
5
|
+
NULL = 0
|
6
|
+
CHAR = 1
|
7
|
+
INT8 = 2
|
8
|
+
INT16 = 3
|
9
|
+
INT32 = 4
|
10
|
+
INT64 = 5
|
11
|
+
STRING = 6
|
12
|
+
BINARY = 7
|
13
|
+
STRING_ARRAY = 8
|
14
|
+
I18NSTRING = 9
|
15
|
+
|
16
|
+
TYPE_MAP = Hash[constants.collect { |c| [const_get(c), c] }]
|
17
|
+
|
18
|
+
def self.parse(data, type, offset, count)
|
19
|
+
case type
|
20
|
+
when NULL
|
21
|
+
nil
|
22
|
+
when CHAR
|
23
|
+
data[offset, count].unpack("A#{count}")
|
24
|
+
when INT8
|
25
|
+
data[offset, count].unpack("C" * count)
|
26
|
+
when INT16
|
27
|
+
data[offset, 2 * count].unpack("n" * count)
|
28
|
+
when INT32
|
29
|
+
data[offset, 4 * count].unpack("N" * count)
|
30
|
+
when INT64
|
31
|
+
a, b = data[offset, 8].unpack("NN")
|
32
|
+
a << 32 + b
|
33
|
+
when STRING, I18NSTRING
|
34
|
+
data[offset..-1][/^[^\0]*/]
|
35
|
+
when BINARY
|
36
|
+
data[offset, count]
|
37
|
+
when STRING_ARRAY
|
38
|
+
data[offset..-1].split("\0")[0...count]
|
39
|
+
else
|
40
|
+
raise ArrPM::V2::Error::InvalidType, type
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end # module Type
|
44
|
+
|
45
|
+
HEADERIMAGE = 61
|
46
|
+
HEADERSIGNATURES = 62
|
47
|
+
HEADERIMMUTABLE = 63
|
48
|
+
HEADERREGIONS = 64
|
49
|
+
HEADERI18NTABLE = 100
|
50
|
+
SIG_BASE = 256
|
51
|
+
|
52
|
+
SIGSIZE = 257
|
53
|
+
SIGLEMD5_1 = 258
|
54
|
+
SIGPGP = 259
|
55
|
+
SIGLEMD5_2 = 260
|
56
|
+
SIGMD5 = 261
|
57
|
+
SIGGPG = 262
|
58
|
+
SIGPGP5 = 263
|
59
|
+
BADSHA1_1 = 264
|
60
|
+
BADSHA1_2 = 265
|
61
|
+
PUBKEYS = 266
|
62
|
+
DSAHEADER = 267
|
63
|
+
RSAHEADER = 268
|
64
|
+
SHA1HEADER = 269
|
65
|
+
LONGSIGSIZE = 270
|
66
|
+
LONGARCHIVESIZE = 271
|
67
|
+
|
68
|
+
NAME = 1000
|
69
|
+
VERSION = 1001
|
70
|
+
RELEASE = 1002
|
71
|
+
EPOCH = 1003
|
72
|
+
SUMMARY = 1004
|
73
|
+
DESCRIPTION = 1005
|
74
|
+
BUILDTIME = 1006
|
75
|
+
BUILDHOST = 1007
|
76
|
+
INSTALLTIME = 1008
|
77
|
+
SIZE = 1009
|
78
|
+
DISTRIBUTION = 1010
|
79
|
+
VENDOR = 1011
|
80
|
+
GIF = 1012
|
81
|
+
XPM = 1013
|
82
|
+
LICENSE = 1014
|
83
|
+
PACKAGER = 1015
|
84
|
+
GROUP = 1016
|
85
|
+
CHANGELOG = 1017
|
86
|
+
SOURCE = 1018
|
87
|
+
PATCH = 1019
|
88
|
+
URL = 1020
|
89
|
+
OS = 1021
|
90
|
+
ARCH = 1022
|
91
|
+
PREIN = 1023
|
92
|
+
POSTIN = 1024
|
93
|
+
PREUN = 1025
|
94
|
+
POSTUN = 1026
|
95
|
+
OLDFILENAMES = 1027
|
96
|
+
FILESIZES = 1028
|
97
|
+
FILESTATES = 1029
|
98
|
+
FILEMODES = 1030
|
99
|
+
FILEUIDS = 1031
|
100
|
+
FILEGIDS = 1032
|
101
|
+
FILERDEVS = 1033
|
102
|
+
FILEMTIMES = 1034
|
103
|
+
FILEDIGESTS = 1035
|
104
|
+
FILELINKTOS = 1036
|
105
|
+
FILEFLAGS = 1037
|
106
|
+
ROOT = 1038
|
107
|
+
FILEUSERNAME = 1039
|
108
|
+
FILEGROUPNAME = 1040
|
109
|
+
EXCLUDE = 1041
|
110
|
+
EXCLUSIVE = 1042
|
111
|
+
ICON = 1043
|
112
|
+
SOURCERPM = 1044
|
113
|
+
FILEVERIFYFLAGS = 1045
|
114
|
+
ARCHIVESIZE = 1046
|
115
|
+
PROVIDENAME = 1047
|
116
|
+
REQUIREFLAGS = 1048
|
117
|
+
REQUIRENAME = 1049
|
118
|
+
REQUIREVERSION = 1050
|
119
|
+
NOSOURCE = 1051
|
120
|
+
NOPATCH = 1052
|
121
|
+
CONFLICTFLAGS = 1053
|
122
|
+
CONFLICTNAME = 1054
|
123
|
+
CONFLICTVERSION = 1055
|
124
|
+
DEFAULTPREFIX = 1056
|
125
|
+
BUILDROOT = 1057
|
126
|
+
INSTALLPREFIX = 1058
|
127
|
+
EXCLUDEARCH = 1059
|
128
|
+
EXCLUDEOS = 1060
|
129
|
+
EXCLUSIVEARCH = 1061
|
130
|
+
EXCLUSIVEOS = 1062
|
131
|
+
AUTOREQPROV = 1063
|
132
|
+
RPMVERSION = 1064
|
133
|
+
TRIGGERSCRIPTS = 1065
|
134
|
+
TRIGGERNAME = 1066
|
135
|
+
TRIGGERVERSION = 1067
|
136
|
+
TRIGGERFLAGS = 1068
|
137
|
+
TRIGGERINDEX = 1069
|
138
|
+
VERIFYSCRIPT = 1079
|
139
|
+
CHANGELOGTIME = 1080
|
140
|
+
CHANGELOGNAME = 1081
|
141
|
+
CHANGELOGTEXT = 1082
|
142
|
+
BROKENMD5 = 1083
|
143
|
+
PREREQ = 1084
|
144
|
+
PREINPROG = 1085
|
145
|
+
POSTINPROG = 1086
|
146
|
+
PREUNPROG = 1087
|
147
|
+
POSTUNPROG = 1088
|
148
|
+
BUILDARCHS = 1089
|
149
|
+
OBSOLETENAME = 1090
|
150
|
+
VERIFYSCRIPTPROG = 1091
|
151
|
+
TRIGGERSCRIPTPROG = 1092
|
152
|
+
DOCDIR = 1093
|
153
|
+
COOKIE = 1094
|
154
|
+
FILEDEVICES = 1095
|
155
|
+
FILEINODES = 1096
|
156
|
+
FILELANGS = 1097
|
157
|
+
PREFIXES = 1098
|
158
|
+
INSTPREFIXES = 1099
|
159
|
+
TRIGGERIN = 1100
|
160
|
+
TRIGGERUN = 1101
|
161
|
+
TRIGGERPOSTUN = 1102
|
162
|
+
AUTOREQ = 1103
|
163
|
+
AUTOPROV = 1104
|
164
|
+
CAPABILITY = 1105
|
165
|
+
SOURCEPACKAGE = 1106
|
166
|
+
OLDORIGFILENAMES = 1107
|
167
|
+
BUILDPREREQ = 1108
|
168
|
+
BUILDREQUIRES = 1109
|
169
|
+
BUILDCONFLICTS = 1110
|
170
|
+
BUILDMACROS = 1111
|
171
|
+
PROVIDEFLAGS = 1112
|
172
|
+
PROVIDEVERSION = 1113
|
173
|
+
OBSOLETEFLAGS = 1114
|
174
|
+
OBSOLETEVERSION = 1115
|
175
|
+
DIRINDEXES = 1116
|
176
|
+
BASENAMES = 1117
|
177
|
+
DIRNAMES = 1118
|
178
|
+
ORIGDIRINDEXES = 1119
|
179
|
+
ORIGBASENAMES = 1120
|
180
|
+
ORIGDIRNAMES = 1121
|
181
|
+
OPTFLAGS = 1122
|
182
|
+
DISTURL = 1123
|
183
|
+
PAYLOADFORMAT = 1124
|
184
|
+
PAYLOADCOMPRESSOR = 1125
|
185
|
+
PAYLOADFLAGS = 1126
|
186
|
+
INSTALLCOLOR = 1127
|
187
|
+
INSTALLTID = 1128
|
188
|
+
REMOVETID = 1129
|
189
|
+
SHA1RHN = 1130
|
190
|
+
RHNPLATFORM = 1131
|
191
|
+
PLATFORM = 1132
|
192
|
+
PATCHESNAME = 1133
|
193
|
+
PATCHESFLAGS = 1134
|
194
|
+
PATCHESVERSION = 1135
|
195
|
+
CACHECTIME = 1136
|
196
|
+
CACHEPKGPATH = 1137
|
197
|
+
CACHEPKGSIZE = 1138
|
198
|
+
CACHEPKGMTIME = 1139
|
199
|
+
FILECOLORS = 1140
|
200
|
+
FILECLASS = 1141
|
201
|
+
CLASSDICT = 1142
|
202
|
+
FILEDEPENDSX = 1143
|
203
|
+
FILEDEPENDSN = 1144
|
204
|
+
DEPENDSDICT = 1145
|
205
|
+
SOURCEPKGID = 1146
|
206
|
+
FILECONTEXTS = 1147
|
207
|
+
FSCONTEXTS = 1148
|
208
|
+
RECONTEXTS = 1149
|
209
|
+
POLICIES = 1150
|
210
|
+
PRETRANS = 1151
|
211
|
+
POSTTRANS = 1152
|
212
|
+
PRETRANSPROG = 1153
|
213
|
+
POSTTRANSPROG = 1154
|
214
|
+
DISTTAG = 1155
|
215
|
+
SUGGESTSNAME = 1156
|
216
|
+
SUGGESTSVERSION = 1157
|
217
|
+
SUGGESTSFLAGS = 1158
|
218
|
+
ENHANCESNAME = 1159
|
219
|
+
ENHANCESVERSION = 1160
|
220
|
+
ENHANCESFLAGS = 1161
|
221
|
+
PRIORITY = 1162
|
222
|
+
CVSID = 1163
|
223
|
+
BLINKPKGID = 1164
|
224
|
+
BLINKHDRID = 1165
|
225
|
+
BLINKNEVRA = 1166
|
226
|
+
FLINKPKGID = 1167
|
227
|
+
FLINKHDRID = 1168
|
228
|
+
FLINKNEVRA = 1169
|
229
|
+
PACKAGEORIGIN = 1170
|
230
|
+
TRIGGERPREIN = 1171
|
231
|
+
BUILDSUGGESTS = 1172
|
232
|
+
BUILDENHANCES = 1173
|
233
|
+
SCRIPTSTATES = 1174
|
234
|
+
SCRIPTMETRICS = 1175
|
235
|
+
BUILDCPUCLOCK = 1176
|
236
|
+
FILEDIGESTALGOS = 1177
|
237
|
+
VARIANTS = 1178
|
238
|
+
XMAJOR = 1179
|
239
|
+
XMINOR = 1180
|
240
|
+
REPOTAG = 1181
|
241
|
+
KEYWORDS = 1182
|
242
|
+
BUILDPLATFORMS = 1183
|
243
|
+
PACKAGECOLOR = 1184
|
244
|
+
PACKAGEPREFCOLOR = 1185
|
245
|
+
XATTRSDICT = 1186
|
246
|
+
FILEXATTRSX = 1187
|
247
|
+
DEPATTRSDICT = 1188
|
248
|
+
CONFLICTATTRSX = 1189
|
249
|
+
OBSOLETEATTRSX = 1190
|
250
|
+
PROVIDEATTRSX = 1191
|
251
|
+
REQUIREATTRSX = 1192
|
252
|
+
BUILDPROVIDES = 1193
|
253
|
+
BUILDOBSOLETES = 1194
|
254
|
+
DBINSTANCE = 1195
|
255
|
+
NVRA = 1196
|
256
|
+
FILENAMES = 5000
|
257
|
+
FILEPROVIDE = 5001
|
258
|
+
FILEREQUIRE = 5002
|
259
|
+
FSNAMES = 5003
|
260
|
+
FSSIZES = 5004
|
261
|
+
TRIGGERCONDS = 5005
|
262
|
+
TRIGGERTYPE = 5006
|
263
|
+
ORIGFILENAMES = 5007
|
264
|
+
LONGFILESIZES = 5008
|
265
|
+
LONGSIZE = 5009
|
266
|
+
FILECAPS = 5010
|
267
|
+
FILEDIGESTALGO = 5011
|
268
|
+
BUGURL = 5012
|
269
|
+
EVR = 5013
|
270
|
+
NVR = 5014
|
271
|
+
NEVR = 5015
|
272
|
+
NEVRA = 5016
|
273
|
+
HEADERCOLOR = 5017
|
274
|
+
VERBOSE = 5018
|
275
|
+
EPOCHNUM = 5019
|
276
|
+
ENCODING = 5062
|
277
|
+
|
278
|
+
TAG_MAP = Hash[constants.collect { |c| [const_get(c), c] }]
|
279
|
+
|
280
|
+
attr_accessor :tag, :type, :value
|
281
|
+
|
282
|
+
def initialize(tag_number, type_number)
|
283
|
+
@tag = self.class::TAG_MAP[tag_number] || tag_number
|
284
|
+
@type = type_number
|
285
|
+
end
|
286
|
+
|
287
|
+
def parse(data, offset, count)
|
288
|
+
@value = Type.parse(data, @type, offset, count)
|
289
|
+
nil
|
290
|
+
end
|
291
|
+
|
292
|
+
def inspect
|
293
|
+
format("<%s#%s> %s/%d value=%s>", self.class.name, self.object_id, @tag, @type, @value.inspect)
|
294
|
+
end
|
295
|
+
end # module ArrPM::V2::Tag
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "arr-pm/namespace"
|
2
|
+
|
3
|
+
module ArrPM::V2::Type
|
4
|
+
BINARY = 0
|
5
|
+
SOURCE = 1
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
# Is a given rpm type value valid?
|
10
|
+
#
|
11
|
+
# The only valid types are BINARY (0) or SOURCE (1)
|
12
|
+
def valid?(value)
|
13
|
+
return (value == BINARY || value == SOURCE)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "flores/random"
|
4
|
+
|
5
|
+
require "arr-pm/v2/header"
|
6
|
+
require "arr-pm/v2/type"
|
7
|
+
require "arr-pm/v2/architecture"
|
8
|
+
require "json"
|
9
|
+
|
10
|
+
describe ArrPM::V2::Header do
|
11
|
+
context "with a known good rpm" do
|
12
|
+
let(:path) { File.join(File.dirname(__FILE__), "../../fixtures/example-1.0-1.x86_64.rpm") }
|
13
|
+
let(:file) { File.new(path) }
|
14
|
+
|
15
|
+
before do
|
16
|
+
lead = ArrPM::V2::Lead.new
|
17
|
+
lead.load(file)
|
18
|
+
|
19
|
+
# Throw away the signature if we have one
|
20
|
+
described_class.new.load(file) if lead.signature?
|
21
|
+
|
22
|
+
subject.load(file)
|
23
|
+
end
|
24
|
+
|
25
|
+
expectations = JSON.parse(File.read(File.join(File.dirname(__FILE__), "../../fixtures/example.json")))
|
26
|
+
|
27
|
+
expectations.each do |name, expected_value|
|
28
|
+
it "should have expected value for the #{name} tag" do
|
29
|
+
tag = subject.tags.find { |t| t.tag.to_s == name }
|
30
|
+
expect(tag.value).to be == expected_value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "flores/random"
|
4
|
+
|
5
|
+
require "arr-pm/v2/lead"
|
6
|
+
require "arr-pm/v2/type"
|
7
|
+
require "arr-pm/v2/architecture"
|
8
|
+
|
9
|
+
describe ArrPM::V2::Lead do
|
10
|
+
let(:major) { Flores::Random.integer(0..255) }
|
11
|
+
let(:minor) { Flores::Random.integer(0..255) }
|
12
|
+
let(:magic) { described_class::MAGIC }
|
13
|
+
let(:type) { ArrPM::V2::Type::BINARY }
|
14
|
+
let(:architecture) { ArrPM::V2::Architecture::I386 }
|
15
|
+
let(:os) { 0 }
|
16
|
+
let(:os_bytes) { [os].pack("n").unpack("C2") }
|
17
|
+
let(:signature_type) { 0 }
|
18
|
+
let(:signature_type_bytes) { [signature_type].pack("n").unpack("C2") }
|
19
|
+
let(:longname) { "test-1.0-1" }
|
20
|
+
let(:longnamebytes) { longname.bytes + (66-longname.bytesize).times.collect { 0 } }
|
21
|
+
let(:leadbytes) { magic + [major, minor] + [0, type, 0, architecture] + longnamebytes + os_bytes + signature_type_bytes + 16.times.collect { 0 } }
|
22
|
+
let(:lead) { leadbytes.pack("C*") }
|
23
|
+
|
24
|
+
describe ".parse_magic" do
|
25
|
+
context "when given an invalid magic value" do
|
26
|
+
# Generate random bytes for the magic value, should be bad.
|
27
|
+
let(:magic) { Flores::Random.iterations(0..10).collect { Flores::Random.integer(0..255) } }
|
28
|
+
|
29
|
+
it "should fail" do
|
30
|
+
expect { described_class.parse_magic(leadbytes) }.to raise_error(ArrPM::V2::Error::InvalidMagicValue)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when given a valid magic value" do
|
35
|
+
it "should succeed" do
|
36
|
+
expect { described_class.parse_magic(leadbytes) }.not_to raise_error
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".parse_version" do
|
42
|
+
context "when given an invalid version value" do
|
43
|
+
let(:data) { magic + [major, minor] }
|
44
|
+
|
45
|
+
it "should return an array of two values " do
|
46
|
+
expect(described_class.parse_version(leadbytes)).to be == [major, minor]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe ".parse_type" do
|
52
|
+
context "when given an invalid type" do
|
53
|
+
let(:type) { Flores::Random.integer(2..1000) }
|
54
|
+
it "should fail" do
|
55
|
+
expect { described_class.parse_type(leadbytes) }.to raise_error(ArrPM::V2::Error::InvalidType)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
context "with a valid type" do
|
59
|
+
it "should return the type" do
|
60
|
+
expect(described_class.parse_type(leadbytes)).to be == type
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe ".parse_name" do
|
66
|
+
context "with a valid name" do
|
67
|
+
it "should return the name" do
|
68
|
+
expect(described_class.parse_name(leadbytes)).to be == longname
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe ".parse_signature_type" do
|
74
|
+
it "should return the signature type" do
|
75
|
+
expect(described_class.parse_signature_type(leadbytes)).to be == signature_type
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe ".parse_reserved" do
|
80
|
+
it "should return exactly 16 bytes" do
|
81
|
+
expect(described_class.parse_reserved(leadbytes).count).to be == 16
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#parse" do
|
86
|
+
before do
|
87
|
+
subject.parse(lead)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should have a correct parsed values" do
|
91
|
+
expect(subject.name).to be == longname
|
92
|
+
expect(subject.major).to be == major
|
93
|
+
expect(subject.minor).to be == minor
|
94
|
+
expect(subject.type).to be == type
|
95
|
+
expect(subject.architecture).to be == architecture
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#dump" do
|
100
|
+
before do
|
101
|
+
subject.parse(lead)
|
102
|
+
end
|
103
|
+
|
104
|
+
let(:blob) { subject.serialize }
|
105
|
+
|
106
|
+
it "should parse successfully" do
|
107
|
+
subject.parse(blob)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context "with a known good rpm" do
|
112
|
+
let(:path) { File.join(File.dirname(__FILE__), "../../fixtures/example-1.0-1.x86_64.rpm") }
|
113
|
+
|
114
|
+
before do
|
115
|
+
subject.load(File.new(path))
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should have expected values" do
|
119
|
+
expect(subject.name).to be == "example-1.0-1"
|
120
|
+
expect(subject.major).to be == 3
|
121
|
+
expect(subject.minor).to be == 0
|
122
|
+
expect(subject.architecture).to be == architecture
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
Binary file
|
@@ -0,0 +1,55 @@
|
|
1
|
+
{
|
2
|
+
"NAME": "example",
|
3
|
+
"VERSION": "1.0",
|
4
|
+
"RELEASE": "1",
|
5
|
+
"SUMMARY": "no description given",
|
6
|
+
"DESCRIPTION": "no description given",
|
7
|
+
"BUILDTIME": [
|
8
|
+
1466326707
|
9
|
+
],
|
10
|
+
"BUILDHOST": "localhost",
|
11
|
+
"SIZE": [
|
12
|
+
0
|
13
|
+
],
|
14
|
+
"VENDOR": "none",
|
15
|
+
"LICENSE": "unknown",
|
16
|
+
"PACKAGER": "<jls@localhost.localdomain>",
|
17
|
+
"GROUP": "default",
|
18
|
+
"URL": "http://example.com/no-uri-given",
|
19
|
+
"OS": "linux",
|
20
|
+
"ARCH": "x86_64",
|
21
|
+
"SOURCERPM": "example-1.0-1.src.rpm",
|
22
|
+
"PROVIDENAME": [
|
23
|
+
"example",
|
24
|
+
"example(x86-64)"
|
25
|
+
],
|
26
|
+
"REQUIREFLAGS": [
|
27
|
+
16777226,
|
28
|
+
16777226
|
29
|
+
],
|
30
|
+
"REQUIRENAME": [
|
31
|
+
"rpmlib(CompressedFileNames)",
|
32
|
+
"rpmlib(PayloadFilesHavePrefix)"
|
33
|
+
],
|
34
|
+
"REQUIREVERSION": [
|
35
|
+
"3.0.4-1",
|
36
|
+
"4.0-1"
|
37
|
+
],
|
38
|
+
"RPMVERSION": "4.13.0-rc1",
|
39
|
+
"PREFIXES": [
|
40
|
+
"/"
|
41
|
+
],
|
42
|
+
"PROVIDEFLAGS": [
|
43
|
+
8,
|
44
|
+
8
|
45
|
+
],
|
46
|
+
"PROVIDEVERSION": [
|
47
|
+
"1.0-1",
|
48
|
+
"1.0-1"
|
49
|
+
],
|
50
|
+
"PAYLOADFORMAT": "cpio",
|
51
|
+
"PAYLOADCOMPRESSOR": "gzip",
|
52
|
+
"PAYLOADFLAGS": "9",
|
53
|
+
"PLATFORM": "x86_64-redhat-linux-gnu",
|
54
|
+
"ENCODING": "utf-8"
|
55
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arr-pm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordan Sissel
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cabin
|
@@ -50,6 +50,7 @@ files:
|
|
50
50
|
- ".gitignore"
|
51
51
|
- ".rubocop.yml"
|
52
52
|
- Gemfile
|
53
|
+
- Guardfile
|
53
54
|
- LICENSE
|
54
55
|
- Makefile
|
55
56
|
- README.md
|
@@ -63,11 +64,24 @@ files:
|
|
63
64
|
- lib/arr-pm/file/tag.rb
|
64
65
|
- lib/arr-pm/namespace.rb
|
65
66
|
- lib/arr-pm/requires.rb
|
66
|
-
|
67
|
+
- lib/arr-pm/v2/architecture.rb
|
68
|
+
- lib/arr-pm/v2/error.rb
|
69
|
+
- lib/arr-pm/v2/format.rb
|
70
|
+
- lib/arr-pm/v2/header.rb
|
71
|
+
- lib/arr-pm/v2/header_header.rb
|
72
|
+
- lib/arr-pm/v2/lead.rb
|
73
|
+
- lib/arr-pm/v2/package.rb
|
74
|
+
- lib/arr-pm/v2/tag.rb
|
75
|
+
- lib/arr-pm/v2/type.rb
|
76
|
+
- spec/arr-pm/v2/header_spec.rb
|
77
|
+
- spec/arr-pm/v2/lead_spec.rb
|
78
|
+
- spec/fixtures/example-1.0-1.x86_64.rpm
|
79
|
+
- spec/fixtures/example.json
|
80
|
+
homepage:
|
67
81
|
licenses:
|
68
82
|
- Apache 2
|
69
83
|
metadata: {}
|
70
|
-
post_install_message:
|
84
|
+
post_install_message:
|
71
85
|
rdoc_options: []
|
72
86
|
require_paths:
|
73
87
|
- lib
|
@@ -83,9 +97,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
97
|
- !ruby/object:Gem::Version
|
84
98
|
version: '0'
|
85
99
|
requirements: []
|
86
|
-
|
87
|
-
|
88
|
-
signing_key:
|
100
|
+
rubygems_version: 3.2.15
|
101
|
+
signing_key:
|
89
102
|
specification_version: 4
|
90
103
|
summary: RPM reader and writer library
|
91
104
|
test_files: []
|