rpm 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +10 -0
- data/ChangeLog +5 -0
- data/README.rdoc +11 -1
- data/lib/rpm/{ffi → c}/header.rb +1 -1
- data/lib/rpm/c/rpmcallback.rb +28 -0
- data/lib/rpm/c/rpmcli.rb +7 -0
- data/lib/rpm/{ffi → c}/rpmdb.rb +1 -1
- data/lib/rpm/{ffi → c}/rpmds.rb +1 -6
- data/lib/rpm/{ffi → c}/rpmfi.rb +1 -1
- data/lib/rpm/c/rpmio.rb +21 -0
- data/lib/rpm/{ffi → c}/rpmlib.rb +1 -1
- data/lib/rpm/{ffi → c}/rpmlog.rb +3 -1
- data/lib/rpm/{ffi → c}/rpmmacro.rb +1 -10
- data/lib/rpm/{ffi → c}/rpmprob.rb +17 -3
- data/lib/rpm/{ffi → c}/rpmps.rb +1 -1
- data/lib/rpm/{ffi → c}/rpmtag.rb +12 -4
- data/lib/rpm/{ffi → c}/rpmtd.rb +1 -1
- data/lib/rpm/{ffi → c}/rpmts.rb +6 -2
- data/lib/rpm/{ffi → c}/rpmtypes.rb +3 -1
- data/lib/rpm/c.rb +47 -0
- data/lib/rpm/db.rb +5 -5
- data/lib/rpm/dependency.rb +10 -10
- data/lib/rpm/gem_version.rb +1 -1
- data/lib/rpm/match_iterator.rb +5 -5
- data/lib/rpm/package.rb +55 -55
- data/lib/rpm/problem.rb +71 -0
- data/lib/rpm/transaction.rb +186 -35
- data/lib/rpm/version.rb +3 -4
- data/lib/rpm.rb +16 -24
- data/rpm.gemspec +1 -1
- data/test/data/simple-1.0-0.i586.rpm +0 -0
- data/test/data/simple.spec +0 -4
- data/test/data/simple_with_deps-1.0-0.i586.rpm +0 -0
- data/test/data/simple_with_deps.spec +41 -0
- data/test/helper.rb +1 -1
- data/test/test_dependency.rb +1 -1
- data/test/test_lib.rb +13 -13
- data/test/test_package.rb +24 -3
- data/test/test_problem.rb +20 -0
- data/test/test_transaction.rb +115 -14
- data/test/test_version.rb +2 -0
- metadata +80 -69
- data/lib/rpm/ffi/rpmcallback.rb +0 -26
- data/lib/rpm/ffi.rb +0 -44
data/lib/rpm/gem_version.rb
CHANGED
data/lib/rpm/match_iterator.rb
CHANGED
@@ -7,7 +7,7 @@ module RPM
|
|
7
7
|
|
8
8
|
# @visibility private
|
9
9
|
def self.release(ptr)
|
10
|
-
RPM::
|
10
|
+
RPM::C.rpmdbFreeIterator(ptr)
|
11
11
|
end
|
12
12
|
|
13
13
|
# Creates a managed MatchIterator from a raw pointer
|
@@ -27,7 +27,7 @@ module RPM
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def next_iterator
|
30
|
-
pkg_ptr = RPM::
|
30
|
+
pkg_ptr = RPM::C.rpmdbNextIterator(@ptr)
|
31
31
|
if !pkg_ptr.null?
|
32
32
|
return RPM::Package.new(pkg_ptr)
|
33
33
|
end
|
@@ -37,11 +37,11 @@ module RPM
|
|
37
37
|
# @ return header join key for current position of rpm
|
38
38
|
# database iterator
|
39
39
|
def offset
|
40
|
-
RPM::
|
40
|
+
RPM::C.rpmdbGetIteratorOffset(@ptr)
|
41
41
|
end
|
42
42
|
|
43
43
|
def set_iterator_re(tag, mode, string)
|
44
|
-
ret = RPM::
|
44
|
+
ret = RPM::C.rpmdbSetIteratorRE(@ptr, tag, mode, string)
|
45
45
|
raise "Error when setting regular expression '#{string}'" if ret != 0
|
46
46
|
self
|
47
47
|
end
|
@@ -63,7 +63,7 @@ module RPM
|
|
63
63
|
alias :version :set_iterator_version
|
64
64
|
|
65
65
|
def get_iterator_count
|
66
|
-
RPM::
|
66
|
+
RPM::C.rpmdbGetIteratorCount(@ptr)
|
67
67
|
end
|
68
68
|
|
69
69
|
alias :count :get_iterator_count
|
data/lib/rpm/package.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'rpm/
|
1
|
+
require 'rpm/c'
|
2
2
|
require 'rpm/file'
|
3
3
|
|
4
4
|
module RPM
|
@@ -23,15 +23,15 @@ module RPM
|
|
23
23
|
if not version.is_a?(RPM::Version)
|
24
24
|
raise TypeError, "illegal argument type: version should be RPM::Version"
|
25
25
|
end
|
26
|
-
hdr = RPM::
|
27
|
-
if RPM::
|
26
|
+
hdr = RPM::C.headerNew
|
27
|
+
if RPM::C.headerPutString(hdr, :name, name) != 1
|
28
28
|
raise "Can't set package name: #{name}"
|
29
29
|
end
|
30
|
-
if RPM::
|
30
|
+
if RPM::C.headerPutString(hdr, :version, version.v) != 1
|
31
31
|
raise "Can't set package version: #{version.v}"
|
32
32
|
end
|
33
33
|
if version.e
|
34
|
-
if RPM::
|
34
|
+
if RPM::C.headerPutUint32(hdr, :epoch, version.e) != 1
|
35
35
|
raise "Can't set package epoch: #{version.e}"
|
36
36
|
end
|
37
37
|
end
|
@@ -87,7 +87,7 @@ module RPM
|
|
87
87
|
# pkg.sprintf("%{name}") => "apache2"
|
88
88
|
def sprintf(fmt)
|
89
89
|
error = ::FFI::MemoryPointer.new(:pointer, 1)
|
90
|
-
val = RPM::
|
90
|
+
val = RPM::C.headerFormat(@hdr, fmt, error)
|
91
91
|
raise error.get_pointer(0).read_string if val.null?
|
92
92
|
val.read_string
|
93
93
|
end
|
@@ -129,8 +129,8 @@ module RPM
|
|
129
129
|
grouplist[i],
|
130
130
|
rdevlist[i],
|
131
131
|
modelist[i],
|
132
|
-
flaglist.nil? ? RPM::
|
133
|
-
statelist.nil? ? RPM::
|
132
|
+
flaglist.nil? ? RPM::C::FileAttrs[:none] : flaglist[i],
|
133
|
+
statelist.nil? ? RPM::C::FileState[:normal] : statelist[i]
|
134
134
|
)
|
135
135
|
ret << file
|
136
136
|
end
|
@@ -145,20 +145,20 @@ module RPM
|
|
145
145
|
def dependencies(klass, nametag, versiontag, flagtag)
|
146
146
|
deps = []
|
147
147
|
|
148
|
-
nametd = ::FFI::AutoPointer.new(RPM::
|
149
|
-
versiontd = ::FFI::AutoPointer.new(RPM::
|
150
|
-
flagtd = ::FFI::AutoPointer.new(RPM::
|
148
|
+
nametd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
149
|
+
versiontd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
150
|
+
flagtd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
151
151
|
|
152
|
-
min = RPM::
|
153
|
-
return deps if (RPM::
|
154
|
-
return deps if (RPM::
|
155
|
-
return deps if (RPM::
|
152
|
+
min = RPM::C::HEADERGET_MINMEM
|
153
|
+
return deps if (RPM::C.headerGet(@hdr, nametag, nametd, min) != 1)
|
154
|
+
return deps if (RPM::C.headerGet(@hdr, versiontag, versiontd, min) != 1)
|
155
|
+
return deps if (RPM::C.headerGet(@hdr, flagtag, flagtd, min) != 1)
|
156
156
|
|
157
|
-
RPM::
|
158
|
-
while RPM::
|
159
|
-
deps << klass.new(RPM::
|
160
|
-
RPM::Version.new(RPM::
|
161
|
-
RPM::
|
157
|
+
RPM::C.rpmtdInit(nametd)
|
158
|
+
while RPM::C.rpmtdNext(nametd) != -1
|
159
|
+
deps << klass.new(RPM::C.rpmtdGetString(nametd),
|
160
|
+
RPM::Version.new(RPM::C.rpmtdNextString(versiontd)),
|
161
|
+
RPM::C.rpmtdNextUint32(flagtd).read_uint, self)
|
162
162
|
end
|
163
163
|
deps
|
164
164
|
end
|
@@ -175,32 +175,32 @@ module RPM
|
|
175
175
|
|
176
176
|
# @return [Array<RPM::Conflicts>] Conflicts list for this package
|
177
177
|
def conflicts
|
178
|
-
dependencies(RPM::
|
178
|
+
dependencies(RPM::Conflict, :conflictname, :conflictversion, :conflictflags)
|
179
179
|
end
|
180
180
|
|
181
181
|
# @return [Array<RPM::Obsolete>] Obsoletes list for this package
|
182
182
|
def obsoletes
|
183
|
-
dependencies(RPM::
|
183
|
+
dependencies(RPM::Obsolete, :obsoletename, :obsoleteversion, :obsoleteflags)
|
184
184
|
end
|
185
185
|
|
186
186
|
# @return [Array<RPM::Changelog>] changelog of the package as an array
|
187
187
|
def changelog
|
188
188
|
entries = []
|
189
|
-
nametd = ::FFI::AutoPointer.new(RPM::
|
190
|
-
timetd = ::FFI::AutoPointer.new(RPM::
|
191
|
-
texttd = ::FFI::AutoPointer.new(RPM::
|
189
|
+
nametd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
190
|
+
timetd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
191
|
+
texttd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
192
192
|
|
193
|
-
min = RPM::
|
194
|
-
return deps if (RPM::
|
195
|
-
return deps if (RPM::
|
196
|
-
return deps if (RPM::
|
193
|
+
min = RPM::C::HEADERGET_MINMEM
|
194
|
+
return deps if (RPM::C.headerGet(@hdr, :changelogtime, timetd, min) != 1)
|
195
|
+
return deps if (RPM::C.headerGet(@hdr, :changelogname, nametd, min) != 1)
|
196
|
+
return deps if (RPM::C.headerGet(@hdr, :changelogtext, texttd, min) != 1)
|
197
197
|
|
198
|
-
RPM::
|
199
|
-
while RPM::
|
198
|
+
RPM::C.rpmtdInit(timetd)
|
199
|
+
while RPM::C.rpmtdNext(timetd) != -1
|
200
200
|
entry = RPM::ChangeLog.new
|
201
|
-
entry.time = RPM::
|
202
|
-
entry.name = RPM::
|
203
|
-
entry.text = RPM::
|
201
|
+
entry.time = RPM::C.rpmtdGetUint32(timetd)
|
202
|
+
entry.name = RPM::C.rpmtdNextString(nametd)
|
203
|
+
entry.text = RPM::C.rpmtdNextString(texttd)
|
204
204
|
entries << entry
|
205
205
|
end
|
206
206
|
entries
|
@@ -222,14 +222,14 @@ module RPM
|
|
222
222
|
# The value of the entry
|
223
223
|
def [](tag)
|
224
224
|
val = nil
|
225
|
-
tagc = ::FFI::AutoPointer.new(RPM::
|
225
|
+
tagc = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
226
226
|
|
227
|
-
return nil if (RPM::
|
228
|
-
RPM::
|
227
|
+
return nil if (RPM::C.headerGet(ptr, tag, tagc,
|
228
|
+
RPM::C::HEADERGET_MINMEM) == 0)
|
229
229
|
|
230
|
-
type = RPM::
|
231
|
-
count = RPM::
|
232
|
-
ret_type = RPM::
|
230
|
+
type = RPM::C.rpmtdType(tagc)
|
231
|
+
count = RPM::C.rpmtdCount(tagc)
|
232
|
+
ret_type = RPM::C.rpmTagGetReturnType(tag)
|
233
233
|
|
234
234
|
method_name = case type
|
235
235
|
when :int8_type, :char_type, :int16_type, :int32_type, :int64_type then :rpmtdGetNumber
|
@@ -246,14 +246,14 @@ module RPM
|
|
246
246
|
|
247
247
|
if is_array
|
248
248
|
ret = []
|
249
|
-
RPM::
|
250
|
-
while RPM::
|
251
|
-
ret << RPM::
|
249
|
+
RPM::C.rpmtdInit(tagc)
|
250
|
+
while RPM::C.rpmtdNext(tagc) != -1
|
251
|
+
ret << RPM::C.send(method_name, tagc)
|
252
252
|
end
|
253
253
|
return ret
|
254
254
|
end
|
255
255
|
|
256
|
-
return RPM::
|
256
|
+
return RPM::C.send(method_name, tagc)
|
257
257
|
end
|
258
258
|
|
259
259
|
# @return [String] This package name
|
@@ -273,7 +273,7 @@ module RPM
|
|
273
273
|
v_ptr = ::FFI::MemoryPointer.new(:pointer, 1)
|
274
274
|
r_ptr = ::FFI::MemoryPointer.new(:pointer, 1)
|
275
275
|
|
276
|
-
RPM::
|
276
|
+
RPM::C.headerNVR(ptr, nil, v_ptr, r_ptr)
|
277
277
|
v = v_ptr.read_pointer.read_string
|
278
278
|
r = r_ptr.read_pointer.read_string
|
279
279
|
v_ptr.free
|
@@ -295,43 +295,43 @@ module RPM
|
|
295
295
|
hdr = ::FFI::MemoryPointer.new(:pointer)
|
296
296
|
fd = nil
|
297
297
|
begin
|
298
|
-
fd = RPM::
|
299
|
-
if RPM::
|
300
|
-
raise "#{filename} : #{RPM::
|
298
|
+
fd = RPM::C.Fopen(filename, 'r')
|
299
|
+
if RPM::C.Ferror(fd) != 0
|
300
|
+
raise "#{filename} : #{RPM::C.Fstrerror(fd)}"
|
301
301
|
end
|
302
302
|
RPM.transaction do |ts|
|
303
|
-
rc = RPM::
|
303
|
+
rc = RPM::C.rpmReadPackageFile(ts.ptr, fd, filename, hdr)
|
304
304
|
end
|
305
305
|
ensure
|
306
|
-
RPM::
|
306
|
+
RPM::C.Fclose(fd) unless fd.nil?
|
307
307
|
end
|
308
308
|
Package.new(hdr.get_pointer(0))
|
309
309
|
end
|
310
310
|
|
311
311
|
# @visibility private
|
312
312
|
def self.release(ptr)
|
313
|
-
RPM::
|
313
|
+
RPM::C.headerFree(ptr)
|
314
314
|
end
|
315
315
|
|
316
316
|
# @visibility private
|
317
317
|
def self.release_td(ptr)
|
318
|
-
RPM::
|
318
|
+
RPM::C.rpmtdFree(ptr)
|
319
319
|
end
|
320
320
|
|
321
321
|
# @visibility private
|
322
322
|
def initialize(hdr=nil)
|
323
323
|
if hdr.nil?
|
324
|
-
@hdr = ::FFI::AutoPointer.new(RPM::
|
324
|
+
@hdr = ::FFI::AutoPointer.new(RPM::C.headerNew, Header.method(:release))
|
325
325
|
elsif hdr.is_a?(::FFI::Pointer)
|
326
326
|
# ref
|
327
|
-
hdr = RPM::
|
327
|
+
hdr = RPM::C.headerLink(hdr)
|
328
328
|
@hdr = ::FFI::AutoPointer.new(hdr, Package.method(:release))
|
329
329
|
else
|
330
330
|
raise "Can't initialize header with '#{hdr}'"
|
331
331
|
end
|
332
332
|
end
|
333
333
|
|
334
|
-
# @return [RPM::
|
334
|
+
# @return [RPM::C::Header] header pointer
|
335
335
|
# @visibility private
|
336
336
|
def ptr
|
337
337
|
@hdr
|
data/lib/rpm/problem.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
module RPM
|
3
|
+
|
4
|
+
class Problem
|
5
|
+
|
6
|
+
def self.release(ptr)
|
7
|
+
RPM::C.rpmProblemFree(ptr)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Creates a problem from an existing C pointer, refcounting it
|
11
|
+
# first.
|
12
|
+
# @param [FFI::Pointer] ptr existing C pointer
|
13
|
+
# @return [RPM::Problem] wrapped object
|
14
|
+
def self.from_ptr(ptr)
|
15
|
+
case ptr
|
16
|
+
when FFI::Pointer
|
17
|
+
new(FFI::AutoPointer.new(RPM::C.rpmProblemLink(ptr), Problem.method(:release)))
|
18
|
+
else
|
19
|
+
raise "Can't initialize header with '#{ptr}'"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Create a problem item.
|
24
|
+
# @param [RPM::ProblemType] type problem type
|
25
|
+
# @param [String] pkg_nver name-version-edition-release of the related package
|
26
|
+
# @param [String] key key of the related package
|
27
|
+
# @param [String] alt_nver name-version-edition-release of the other related package
|
28
|
+
# @param [String] str generic data string from a problem
|
29
|
+
def self.create(type, pkg_nevr, key, alt_nevr, str, number)
|
30
|
+
ptr = ::FFI::AutoPointer.new(RPM::C.rpmProblemCreate(type, pkg_nevr, key, alt_nevr, str, number), Problem.method(:release))
|
31
|
+
new(ptr)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @visibility private
|
35
|
+
def initialize(ptr)
|
36
|
+
@ptr = ptr
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [RPM::ProblemType] type of problem (dependency, diskpace etc).
|
40
|
+
def type
|
41
|
+
RPM::C.rpmProblemGetType(@ptr)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [String] filename or python object address of a problem.
|
45
|
+
def key
|
46
|
+
RPM::C.rpmProblemGetKey(@ptr).read_string
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [String] a generic data string from a problem.
|
50
|
+
def str
|
51
|
+
RPM::C.rpmProblemGetStr(@ptr)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [String] formatted string representation of a problem
|
55
|
+
def to_s
|
56
|
+
RPM::C.rpmProblemString(@ptr)
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Fixnum] compare two problems for equality.
|
60
|
+
def <=>(other)
|
61
|
+
RPM::C.rpmProblemCompare(@ptr, other.ptr)
|
62
|
+
end
|
63
|
+
|
64
|
+
# @visibility private
|
65
|
+
def ptr
|
66
|
+
@ptr
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
data/lib/rpm/transaction.rb
CHANGED
@@ -2,26 +2,38 @@ require 'rpm'
|
|
2
2
|
|
3
3
|
module RPM
|
4
4
|
|
5
|
+
CallbackData = Struct.new(:type, :key, :package, :amount, :total) do
|
6
|
+
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
"#{type} #{key} #{package} #{amount} #{total}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
5
13
|
class Transaction
|
6
14
|
|
7
15
|
def self.release(ptr)
|
8
|
-
RPM::
|
16
|
+
RPM::C.rpmtsFree(ptr)
|
9
17
|
end
|
10
18
|
|
11
19
|
def initialize(opts={})
|
12
|
-
|
20
|
+
# http://markmail.org/message/ypsiqxop442p7rzz
|
21
|
+
# The key pointer needs to stay valid during commit
|
22
|
+
# so we keep a reference to them mapping from
|
23
|
+
# object_id to ruby object.
|
24
|
+
@keys = {}
|
13
25
|
opts[:root] ||= '/'
|
14
26
|
|
15
|
-
@ptr = ::FFI::AutoPointer.new(RPM::
|
16
|
-
RPM::
|
27
|
+
@ptr = ::FFI::AutoPointer.new(RPM::C.rpmtsCreate, Transaction.method(:release))
|
28
|
+
RPM::C.rpmtsSetRootDir(@ptr, opts[:root])
|
17
29
|
end
|
18
30
|
|
19
31
|
# @return [RPM::MatchIterator] Creates an iterator for +tag+ and +val+
|
20
32
|
def init_iterator(tag, val)
|
21
33
|
raise TypeError if (val && !val.is_a?(String))
|
22
|
-
|
23
|
-
it_ptr = RPM::
|
24
|
-
|
34
|
+
|
35
|
+
it_ptr = RPM::C.rpmtsInitIterator(@ptr, tag.nil? ? 0 : tag, val, 0)
|
36
|
+
|
25
37
|
raise "Can't init iterator for [#{tag}] -> '#{val}'" if it_ptr.null?
|
26
38
|
return MatchIterator.from_ptr(it_ptr)
|
27
39
|
end
|
@@ -30,7 +42,7 @@ module RPM
|
|
30
42
|
def ptr
|
31
43
|
@ptr
|
32
44
|
end
|
33
|
-
|
45
|
+
|
34
46
|
#
|
35
47
|
# @yield [Package] Called for each match
|
36
48
|
# @param [Number] key RPM tag key
|
@@ -63,68 +75,207 @@ module RPM
|
|
63
75
|
|
64
76
|
# Add a install operation to the transaction
|
65
77
|
# @param [Package] pkg Package to install
|
78
|
+
# @param [String] key e.g. filename where to install from
|
66
79
|
def install(pkg, key)
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
80
|
+
install_element(pkg, key, :upgrade => false)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Add an upgrade operation to the transaction
|
84
|
+
# @param [Package] pkg Package to upgrade
|
85
|
+
# @param [String] key e.g. filename where to install from
|
86
|
+
def upgrade(pkg, key)
|
87
|
+
install_element(pkg, key, :upgrade => true)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Add a delete operation to the transaction
|
91
|
+
# @param [String, Package, Dependency] pkg Package to delete
|
92
|
+
def delete(pkg)
|
93
|
+
iterator = case pkg
|
94
|
+
when Package
|
95
|
+
pkg[:sigmd5] ? each_match(:sigmd5, pkg[:sigmd5]) : each_match(:label, pkg[:label])
|
96
|
+
when String
|
97
|
+
each_match(:label, pkg)
|
98
|
+
when Dependency
|
99
|
+
each_match(:label, pkg.name).set_iterator_version(pkg.version)
|
100
|
+
else
|
101
|
+
raise TypeError, "illegal argument type"
|
102
|
+
end
|
103
|
+
|
104
|
+
iterator.each do |header|
|
105
|
+
ret = RPM::C.rpmtsAddEraseElement(@ptr, header.ptr, iterator.offset)
|
106
|
+
raise RuntimeError, "Error while adding erase/#{pkg} to transaction" if ret != 0
|
107
|
+
end
|
75
108
|
end
|
76
109
|
|
77
110
|
# Sets the root directory for this transaction
|
78
111
|
# @param [String] root directory
|
79
112
|
def root_dir=(dir)
|
80
|
-
rc = RPM::
|
113
|
+
rc = RPM::C.rpmtsSetRootDir(@ptr, dir)
|
81
114
|
raise "Can't set #{dir} as root directory" if rc < 0
|
82
115
|
end
|
83
116
|
|
84
117
|
# @return [String ] the root directory for this transaction
|
85
118
|
def root_dir
|
86
|
-
RPM::
|
119
|
+
RPM::C.rpmtsRootDir(@ptr)
|
87
120
|
end
|
88
121
|
|
89
122
|
def flags=(fl)
|
90
|
-
RPM::
|
123
|
+
RPM::C.rpmtsSetFlags(@ptr, fl)
|
91
124
|
end
|
92
125
|
|
93
126
|
def flags
|
94
|
-
RPM::
|
127
|
+
RPM::C.rpmtsFlags(@ptr)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Determine package order in the transaction according to dependencies
|
131
|
+
#
|
132
|
+
# The final order ends up as installed packages followed by removed
|
133
|
+
# packages, with packages removed for upgrades immediately following
|
134
|
+
# the new package to be installed.
|
135
|
+
#
|
136
|
+
# @returns [Fixnum] no. of (added) packages that could not be ordered
|
137
|
+
def order
|
138
|
+
RPM::C.rpmtsOrder(@ptr)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Free memory needed only for dependency checks and ordering.
|
142
|
+
def clean
|
143
|
+
RPM::C.rpmtsClean(@ptr)
|
144
|
+
end
|
145
|
+
|
146
|
+
def check
|
147
|
+
rc = RPM::C.rpmtsCheck(@ptr)
|
148
|
+
probs = RPM::C.rpmtsProblems(@ptr)
|
149
|
+
|
150
|
+
return if rc < 0
|
151
|
+
begin
|
152
|
+
psi = RPM::C.rpmpsInitIterator(probs)
|
153
|
+
while (RPM::C.rpmpsNextIterator(psi) >= 0)
|
154
|
+
problem = Problem.from_ptr(RPM::C.rpmpsGetProblem(psi))
|
155
|
+
yield problem
|
156
|
+
end
|
157
|
+
ensure
|
158
|
+
RPM::C.rpmpsFree(probs)
|
159
|
+
end
|
95
160
|
end
|
96
161
|
|
97
162
|
# Performs the transaction.
|
98
163
|
# @param [Number] flag Transaction flags, default +RPM::TRANS_FLAG_NONE+
|
99
164
|
# @param [Number] filter Transaction filter, default +RPM::PROB_FILTER_NONE+
|
100
165
|
# @example
|
101
|
-
# transaction.commit
|
166
|
+
# transaction.commit
|
167
|
+
# You can supply your own callback
|
168
|
+
# @example
|
169
|
+
# transaction.commit do |data|
|
170
|
+
# end
|
102
171
|
# end
|
103
172
|
# @yield [CallbackData] sig Transaction progress
|
104
|
-
def commit
|
105
|
-
|
173
|
+
def commit(&user_callback)
|
174
|
+
flags = RPM::C::TransFlags[:none]
|
175
|
+
|
176
|
+
callback = Proc.new do |hdr, type, amount, total, key_ptr, data_ignored|
|
177
|
+
key_id = key_ptr.address
|
178
|
+
key = @keys.include?(key_id) ? @keys[key_id] : nil
|
179
|
+
|
180
|
+
case
|
181
|
+
when block_given?
|
182
|
+
package = hdr.null? ? nil : Package.new(hdr)
|
183
|
+
data = CallbackData.new(type, key, package, amount, total)
|
184
|
+
user_callback.call(data)
|
185
|
+
else
|
186
|
+
RPM::C.rpmShowProgress(hdr, type, amount, total, key, data_ignored)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
# We create a callback to pass to the C method and we
|
190
|
+
# call the user supplied callback from there
|
191
|
+
#
|
192
|
+
# The C callback expects you to return a file handle,
|
193
|
+
# We expect from the user to get a File, which we
|
194
|
+
# then convert to a file handle to return.
|
195
|
+
callback = Proc.new do |hdr, type, amount, total, key_ptr, data_ignored|
|
196
|
+
key_id = key_ptr.address
|
197
|
+
key = @keys.include?(key_id) ? @keys[key_id] : nil
|
106
198
|
|
107
|
-
|
108
|
-
|
199
|
+
case
|
200
|
+
when block_given?
|
201
|
+
package = hdr.null? ? nil : Package.new(hdr)
|
202
|
+
data = CallbackData.new(type, key, package, amount, total)
|
203
|
+
ret = user_callback.call(data)
|
204
|
+
|
205
|
+
# For OPEN_FILE we need to do some type conversion
|
206
|
+
# for certain callback types we need to do some
|
207
|
+
case type
|
208
|
+
when :inst_open_file
|
209
|
+
# For :inst_open_file the user callback has to
|
210
|
+
# return the open file
|
211
|
+
if !ret.is_a?(::File)
|
212
|
+
raise TypeError, "illegal return value type #{ret.class}. Expected File."
|
213
|
+
end
|
214
|
+
fdt = RPM::C.fdDup(ret.to_i)
|
215
|
+
if (fdt.null? || RPM::C.Ferror(fdt) != 0)
|
216
|
+
raise RuntimeError, "Can't use opened file #{data.key}: #{RPM::C.Fstrerror(fdt)}"
|
217
|
+
RPM::C.Fclose(fdt) if not fdt.nil?
|
218
|
+
else
|
219
|
+
fdt = RPM::C.fdLink(fdt)
|
220
|
+
@fdt = fdt
|
221
|
+
end
|
222
|
+
# return the (RPM type) file handle
|
223
|
+
fdt
|
224
|
+
when :inst_close_file
|
225
|
+
fdt = @fdt
|
226
|
+
RPM::C.Fclose(fdt)
|
227
|
+
@fdt = nil
|
228
|
+
else
|
229
|
+
ret
|
230
|
+
end
|
231
|
+
else
|
232
|
+
# No custom callback given, use the default to show progress
|
233
|
+
RPM::C.rpmShowProgress(hdr, type, amount, total, key, data_ignored)
|
234
|
+
end
|
109
235
|
end
|
110
236
|
|
111
|
-
RPM::
|
237
|
+
rc = RPM::C.rpmtsSetNotifyCallback(@ptr, callback, nil)
|
238
|
+
raise "Can't set commit callback" if rc != 0
|
239
|
+
|
240
|
+
rc = RPM::C.rpmtsRun(@ptr, nil, :none)
|
112
241
|
|
113
|
-
|
242
|
+
raise "#{self}: #{RPM::C.rpmlogMessage}" if rc < 0
|
114
243
|
|
115
|
-
raise "Transaction Error" if rc < 0
|
116
|
-
|
117
244
|
if rc > 0
|
118
|
-
ps = RPM::
|
119
|
-
psi = RPM::
|
120
|
-
while (RPM::
|
121
|
-
problem = RPM::
|
122
|
-
puts
|
245
|
+
ps = RPM::C.rpmtsProblems(@ptr)
|
246
|
+
psi = RPM::C.rpmpsInitIterator(ps)
|
247
|
+
while (RPM::C.rpmpsNextIterator(psi) >= 0)
|
248
|
+
problem = Problem.from_ptr(RPM::C.rpmpsGetProblem(psi))
|
249
|
+
STDERR.puts problem
|
123
250
|
end
|
124
|
-
RPM::
|
251
|
+
RPM::C.rpmpsFree(ps)
|
125
252
|
end
|
126
253
|
end
|
127
254
|
|
255
|
+
# @return [DB] the database associated with this transaction
|
256
|
+
def db
|
257
|
+
RPM::DB.new(self)
|
258
|
+
end
|
259
|
+
|
260
|
+
private
|
261
|
+
|
262
|
+
# @param [Package] pkg package to install
|
263
|
+
# @param [String] key e.g. filename where to install from
|
264
|
+
# @param opts options
|
265
|
+
# @option :upgrade Upgrade packages if true
|
266
|
+
def install_element(pkg, key, opts={})
|
267
|
+
raise TypeError, "illegal argument type" if not pkg.is_a?(RPM::Package)
|
268
|
+
raise ArgumentError, "#{self}: key '#{key}' must be unique" if @keys.include?(key.object_id)
|
269
|
+
|
270
|
+
# keep a reference to the key as rpmtsAddInstallElement will keep a copy
|
271
|
+
# of the passed pointer (we pass the object_id)
|
272
|
+
@keys[key.object_id] = key
|
273
|
+
|
274
|
+
ret = RPM::C.rpmtsAddInstallElement(@ptr, pkg.ptr, FFI::Pointer.new(key.object_id), opts[:upgrade] ? 1 : 0, nil)
|
275
|
+
raise RuntimeError if ret != 0
|
276
|
+
nil
|
277
|
+
end
|
278
|
+
|
128
279
|
end
|
129
280
|
|
130
281
|
end
|