parent
9cf2aabc65
commit
998f87cee3
@ -0,0 +1,8 @@
|
||||
*.gem
|
||||
.bundle
|
||||
Gemfile.lock
|
||||
pkg/*
|
||||
*.rbc
|
||||
.yardoc
|
||||
.idea
|
||||
test/test_many_files.rb
|
@ -0,0 +1 @@
|
||||
inherit_from: .rubocop_todo.yml
|
@ -0,0 +1,111 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config`
|
||||
# on 2016-07-09 11:50:54 +0200 using RuboCop version 0.41.2.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AlignWith, SupportedStyles, AutoCorrect.
|
||||
# SupportedStyles: keyword, variable, start_of_line
|
||||
Lint/EndAlignment:
|
||||
Exclude:
|
||||
- 'lib/rpm/dependency.rb'
|
||||
- 'lib/rpm/file.rb'
|
||||
- 'lib/rpm/package.rb'
|
||||
- 'lib/rpm/transaction.rb'
|
||||
- 'test/test_transaction.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/UnreachableCode:
|
||||
Exclude:
|
||||
- 'lib/rpm/transaction.rb'
|
||||
|
||||
# Offense count: 11
|
||||
Lint/UselessAssignment:
|
||||
Exclude:
|
||||
- 'lib/rpm.rb'
|
||||
- 'lib/rpm/package.rb'
|
||||
- 'lib/rpm/transaction.rb'
|
||||
- 'lib/rpm/version.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Lint/Void:
|
||||
Exclude:
|
||||
- 'test/test_rpm.rb'
|
||||
|
||||
# Offense count: 17
|
||||
Metrics/AbcSize:
|
||||
Max: 74
|
||||
|
||||
# Offense count: 1
|
||||
Metrics/BlockNesting:
|
||||
Max: 4
|
||||
|
||||
# Offense count: 3
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/ClassLength:
|
||||
Max: 225
|
||||
|
||||
# Offense count: 3
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 17
|
||||
|
||||
# Offense count: 66
|
||||
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
|
||||
# URISchemes: http, https
|
||||
Metrics/LineLength:
|
||||
Max: 129
|
||||
|
||||
# Offense count: 21
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/MethodLength:
|
||||
Max: 57
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/ModuleLength:
|
||||
Max: 295
|
||||
|
||||
# Offense count: 4
|
||||
# Configuration parameters: CountKeywordArgs.
|
||||
Metrics/ParameterLists:
|
||||
Max: 11
|
||||
|
||||
# Offense count: 2
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 19
|
||||
|
||||
# Offense count: 2
|
||||
Style/AccessorMethodName:
|
||||
Exclude:
|
||||
- 'lib/rpm/match_iterator.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Style/AsciiComments:
|
||||
Exclude:
|
||||
- 'lib/rpm/file.rb'
|
||||
|
||||
# Offense count: 34
|
||||
Style/Documentation:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 2
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: snake_case, camelCase
|
||||
Style/MethodName:
|
||||
Exclude:
|
||||
- 'lib/rpm/c/rpmprob.rb'
|
||||
- 'lib/rpm/c/rpmtag.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
|
||||
# NamePrefix: is_, has_, have_
|
||||
# NamePrefixBlacklist: is_, has_, have_
|
||||
# NameWhitelist: is_a?
|
||||
Style/PredicateName:
|
||||
Exclude:
|
||||
- 'spec/**/*'
|
||||
- 'lib/rpm/file.rb'
|
@ -0,0 +1,10 @@
|
||||
|
||||
2013-10-24 Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
||||
|
||||
* v0.0.4
|
||||
* Bugfix: too many open files on transaction with blocks
|
||||
|
||||
2012-02-23 Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
||||
|
||||
* RPM::FFI module is now RPM::C
|
||||
* implement Trasaction#commit, Trasaction#install, Trasaction#upgrade,
|
@ -0,0 +1,9 @@
|
||||
source 'http://rubygems.org'
|
||||
|
||||
# Specify your gem's dependencies in rpm.gemspec
|
||||
gemspec
|
||||
|
||||
group :test do
|
||||
gem 'minitest'
|
||||
gem 'rake'
|
||||
end
|
@ -0,0 +1,24 @@
|
||||
|
||||
Copyright © 2011 Duncan Mac-Vicar Prett <dmacvicar@suse.de>
|
||||
Copyright © 2011 SUSE Linux Products GmbH
|
||||
Copyright © 2002 Kenta Murata
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
@ -0,0 +1,378 @@
|
||||
|
||||
# RPM bindings for ruby
|
||||
|
||||
 [](https://travis-ci.org/dmacvicar/ruby-rpm-ffi)
|
||||
[](https://github.com/dmacvicar/ruby-rpm-ffi/actions/workflows/ci.yaml)
|
||||
|
||||
* http://github.com/dmacvicar/ruby-rpm-ffi
|
||||
|
||||
|
||||
# WARNING
|
||||
|
||||
This is an alpha release! There is still work to be done
|
||||
|
||||
# Quickstart
|
||||
|
||||
## Working with RPM package files
|
||||
|
||||
```ruby
|
||||
require 'rpm'
|
||||
|
||||
pkg = RPM::Package.open("file.rpm")
|
||||
pkg.arch => "x86_64"
|
||||
|
||||
pkg.files.each do |file|
|
||||
puts file.path
|
||||
end
|
||||
|
||||
pkg.changelog.each do |entry|
|
||||
puts "#{entry.name} #{entry.time} #{entry.text}"
|
||||
end
|
||||
```
|
||||
|
||||
## Querying the rpm database
|
||||
|
||||
```ruby
|
||||
require 'rpm'
|
||||
|
||||
RPM.transaction do |ts|
|
||||
ts.each do |pkg|
|
||||
puts pkg
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Install a package
|
||||
|
||||
```ruby
|
||||
require 'rpm'
|
||||
|
||||
pkg = RPM::Package.open('foo.rpm')
|
||||
|
||||
RPM.transaction(rootdir) do |t|
|
||||
t.install(pkg, 'foo.rpm')
|
||||
t.commit
|
||||
end
|
||||
```
|
||||
|
||||
## Introduction
|
||||
|
||||
This library is a replacement for the ruby-rpm gem, originally
|
||||
writen by Kenta Murata around 2002 for the Kondara distribution. Later
|
||||
mantained by David Lutterkort and myself.
|
||||
|
||||
Why?
|
||||
|
||||
* The original gem supports ancient rpm versions not in use anymore
|
||||
* The original gem was written in C using MRI API
|
||||
* The #ifdef'ing required to support multiple rpm versions made the code
|
||||
hard to maintain
|
||||
|
||||
This gem:
|
||||
|
||||
* Is pure ruby
|
||||
* Is documented
|
||||
* Has as a goal to support only the latest rpm version plus the ones in
|
||||
use some releases back in popular rpm based distros
|
||||
* Uses FFI, so it should work with other interpreters
|
||||
(Because https://github.com/rubinius/rubinius/issues/682 it currently does
|
||||
not work on Rubinius)
|
||||
* Does not target rpm5, but it may support it someday
|
||||
|
||||
As an example the code that implements RPM::Package was reduced
|
||||
from 1130 lines of code to 320.
|
||||
|
||||
# Architecture
|
||||
|
||||
The gem is divided in two modules:
|
||||
|
||||
* RPM::C:: which contains the 1:1 mapping to the librpm API
|
||||
Not all functions are attached, only the ones we actually use.
|
||||
* RPM:: contains the actual higher level API
|
||||
|
||||
# Status, Compatibility and Differences with ruby-rpm
|
||||
|
||||
* Only rpm 4.11.x or later will be supported
|
||||
* You can use symbols: instead of RPM::TAG_DESCRIPTION you
|
||||
can use just :description. 'rpm/compat' is by default loaded
|
||||
and provides compatibility with the RPM::TAG_* style constants
|
||||
* RPM::DB is not supported. Use RPM::Transaction
|
||||
* Spec and Source classes are not implemented yet
|
||||
|
||||
## TESTING
|
||||
|
||||
Unit tests can be run using the `rake test` command.
|
||||
|
||||
### Docker tests
|
||||
|
||||
In order to not damage your system, you can run the testsuite under docker:
|
||||
|
||||
* Build the docker images:
|
||||
|
||||
```console
|
||||
rake docker_images
|
||||
```
|
||||
|
||||
* Run the testsuite under Docker
|
||||
|
||||
```console
|
||||
rake docker_test
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
* Check Package#signature should return String?
|
||||
=> ruby-rpm seems to return symbol
|
||||
* Food for thought: Package dependencies and changelog
|
||||
methods could just use []. Calling headerGet directly saves
|
||||
us from doing one iteration per attribute
|
||||
* Not sure if Spec can be implemented as it was before with
|
||||
newer rpms.
|
||||
|
||||
## API Checklist and TODO
|
||||
|
||||
### Low level 1:1 RPM::C API
|
||||
|
||||
* http://rpm.org/wiki/Releases/4.14.0
|
||||
- [ ] Add rpmfiVerify() and rpmfilesVerify()
|
||||
- [ ] Add pmsqPoll(), rpmsqActivate(), rpmsqSetAction(), rpmsqBlock()
|
||||
- [ ] Add rpmDigestBundleAddID()
|
||||
- [ ] Add RPMTRANS_FLAG_NOCAPS flag to disable file capabilities
|
||||
- [ ] Add RPMVSF_NOPAYLOAD flag to disable payload digest verification
|
||||
- [ ] Add pgpPubkeyKeyID()
|
||||
- [X] Add rpmPushMacro() and rpmPopMacro() (to replace addMacro() and delMacro())
|
||||
- [ ] Remove headerNVR(), headerNEVRA(), headerGetNEVR(), headerGetNEVRA(), headerGetEVR(), headerGetColor(), rpmfiMD5(), expandMacros(), addMacro(), delMacro()
|
||||
|
||||
* http://rpm.org/wiki/Releases/4.13.0
|
||||
- [ ] Add rpmsqSetInterruptSafety()
|
||||
- [ ] Add/Change rpmPkgSign()
|
||||
- [ ] Add RPMCALLBACK_ELEM_PROGRESS callback type
|
||||
- [ ] Add rpmExpandMacros()
|
||||
|
||||
* http://rpm.org/wiki/Releases/4.12.0
|
||||
- [ ] Add rpmtxnBegin() and rpmtxnEnd()
|
||||
- [ ] Add rpmtsImportHeader()
|
||||
- [ ] Add rpmtsAddReinstallElement()
|
||||
- [ ] Add rpmdbIndexIteratorNextTd()
|
||||
- [ ] Add file info set iterator functions: rpmfiFLinks(), rpmfiFindFN(), rpmfiStat()
|
||||
- [ ] Add rpmfiOFN(), rpmfiOBN(), rpmfiODN(), rpmfiFindOFN()
|
||||
- [ ] Add rpmteFiles()
|
||||
- [ ] Add rpmdsTagF(), rpmdsTagEVR(), rpmdsD(), rpmdsPutToHeader(), rpmdsTi(), rpmdsTagTi() and rpmdsSinglePoolTix()
|
||||
|
||||
* http://rpm.org/wiki/Releases/4.11.0
|
||||
- [ ] Add rpmstrPool object + associated functions
|
||||
- [ ] Add rpmIsGlob()
|
||||
- [ ] Add rpmtdToPool()
|
||||
- [ ] Add rpmGetArchColor()
|
||||
|
||||
### RPM
|
||||
|
||||
- [ ] RPM#expand
|
||||
- [X] RPM#[]
|
||||
- [X] RPM#[]=
|
||||
- [ ] RPM#readrc
|
||||
- [ ] RPM#init_macros
|
||||
- [ ] RPM#verbosity
|
||||
- [ ] RPM#verbosity=
|
||||
|
||||
### RPM::Package
|
||||
|
||||
- [X] Package#open
|
||||
- [X] Package#new
|
||||
- [X] Package#create
|
||||
- [ ] Package#load
|
||||
- [ ] Package#clear_cache
|
||||
- [ ] Package#use_cache
|
||||
- [X] Package#[]
|
||||
- [ ] Package#delete_tag
|
||||
- [X] Package#sprintf
|
||||
[?] Package#signature
|
||||
- [X] Package#arch
|
||||
- [X] Package#name
|
||||
- [X] Package#version
|
||||
- [X] Package#files
|
||||
- [X] Package#provides
|
||||
- [X] Package#requires
|
||||
- [X] Package#conflicts
|
||||
- [X] Package#obsoletes
|
||||
- [X] Package#changelog
|
||||
- [ ] Package#add_dependency
|
||||
- [ ] Package#add_string
|
||||
- [ ] Package#add_string_array
|
||||
- [ ] Package#add_int32
|
||||
- [ ] Package#dump
|
||||
- [X] Package#to_s
|
||||
- [ ] Package#inspect
|
||||
- [ ] Package#copy_to
|
||||
|
||||
### RPM::Dependency
|
||||
|
||||
- [X] Dependency#initialize
|
||||
- [X] Dependency#name
|
||||
- [X] Dependency#version
|
||||
- [X] Dependency#flags
|
||||
- [X] Dependency#owner
|
||||
- [X] Dependency#lt?
|
||||
- [X] Dependency#gt?
|
||||
- [X] Dependency#eq?
|
||||
- [X] Dependency#le?
|
||||
- [X] Dependency#ge?
|
||||
- [X] Dependency#satisfy?
|
||||
- [X] Dependency#nametag
|
||||
- [X] Dependency#versiontag
|
||||
- [X] Dependency#flagstag
|
||||
|
||||
### RPM::Provide
|
||||
|
||||
- [X] Provide#initialize
|
||||
|
||||
### RPM::Require
|
||||
|
||||
- [X] Require#initialize
|
||||
- [ ] Require#pre?
|
||||
|
||||
### RPM::Conflict
|
||||
|
||||
- [X] Conflict#initialize
|
||||
|
||||
### RPM::Obsolete
|
||||
|
||||
- [X] Obsolete#initialize
|
||||
|
||||
### RPM::ChangeLog
|
||||
|
||||
- [X] ChangeLog#time
|
||||
- [X] ChangeLog#name
|
||||
- [X] ChangeLog#text
|
||||
|
||||
### RPM::Version
|
||||
|
||||
- [X] Version (Comparable)
|
||||
- [X] Version#initialize
|
||||
- [X] Version#<=>
|
||||
- [X] Version#newer?
|
||||
- [X] Version#older?
|
||||
- [X] Version#v
|
||||
- [X] Version#r
|
||||
- [X] Version#e
|
||||
- [X] Version#to_s
|
||||
- [X] Version#to_vre
|
||||
- [X] Version#inspect
|
||||
- [X] Version#hash
|
||||
|
||||
### RPM::File
|
||||
|
||||
- [X] File#initialize
|
||||
- [X] File#path
|
||||
- [ ] File#to_s (alias path)
|
||||
- [X] File#md5sum
|
||||
- [X] File#link_to
|
||||
- [X] File#size
|
||||
- [X] File#mtime
|
||||
- [X] File#owner
|
||||
- [X] File#group
|
||||
- [X] File#rdev
|
||||
- [X] File#mode
|
||||
- [X] File#attr
|
||||
- [X] File#state
|
||||
- [X] File#symlink?
|
||||
- [X] File#config?
|
||||
- [X] File#doc?
|
||||
- [X] File#donotuse?
|
||||
- [X] File#missingok?
|
||||
- [X] File#specfile?
|
||||
- [X] File#ghost?
|
||||
- [X] File#license?
|
||||
- [X] File#readme?
|
||||
- [X] File#exclude?
|
||||
- [X] File#replaced?
|
||||
- [X] File#notinstalled?
|
||||
- [X] File#netshared?
|
||||
|
||||
### RPM::DB
|
||||
|
||||
- [ ] DB (Enumerable)
|
||||
- [ ] DB#new
|
||||
- [ ] DB#open
|
||||
- [ ] DB#init
|
||||
- [ ] DB#rebuild
|
||||
- [ ] DB#close
|
||||
- [ ] DB#closed?
|
||||
- [ ] DB#root
|
||||
- [ ] DB#home
|
||||
- [ ] DB#writable?
|
||||
- [ ] DB#each_match
|
||||
- [ ] DB#each
|
||||
- [ ] DB#transaction
|
||||
- [ ] DB#init_iterator
|
||||
- [ ] DB#dup
|
||||
- [ ] DB#clone
|
||||
|
||||
### RPM::MatchIterator
|
||||
|
||||
- [X] MatchIterator (Enumerable)
|
||||
- [X] MatchIterator#each
|
||||
- [X] MatchIterator#next_iterator
|
||||
- [X] MatchIterator#offset
|
||||
- [X] MatchIterator#set_iterator_re
|
||||
- [X] MatchIterator#regexp
|
||||
- [X] MatchIterator#set_iterator_version
|
||||
- [X] MatchIterator#version
|
||||
- [X] MatchIterator#get_iterator_count
|
||||
- [X] MatchIterator#length
|
||||
|
||||
### RPM::Transaction
|
||||
|
||||
- [ ] Transaction#db
|
||||
- [ ] Transaction#script_file
|
||||
- [ ] Transaction#script_file=
|
||||
- [ ] Transaction#install
|
||||
- [ ] Transaction#upgrade
|
||||
- [ ] Transaction#available
|
||||
- [ ] Transaction#delete
|
||||
- [ ] Transaction#check
|
||||
- [ ] Transaction#order
|
||||
- [ ] Transaction#keys
|
||||
- [ ] Transaction#commit
|
||||
- [ ] Transaction#abort
|
||||
- [ ] Transaction#dup
|
||||
- [ ] Transaction#clone
|
||||
|
||||
### RPM::Source
|
||||
|
||||
- [ ] Source#initialize
|
||||
- [ ] Source#fullname
|
||||
- [ ] Source#to_s (alias fullname)
|
||||
- [ ] Source#num
|
||||
- [ ] Source#no?
|
||||
|
||||
### RPM::Patch
|
||||
|
||||
### RPM::Icon
|
||||
|
||||
### RPM::Spec
|
||||
|
||||
- [ ] Spec#open
|
||||
- [ ] Spec#new
|
||||
- [ ] Spec#buildroot
|
||||
- [ ] Spec#buildsubdir
|
||||
- [ ] Spec#buildarchs
|
||||
- [ ] Spec#buildrequires
|
||||
- [ ] Spec#build_restrictions
|
||||
- [ ] Spec#sources
|
||||
- [ ] Spec#packages
|
||||
- [ ] Spec#build
|
||||
- [ ] Spec#expand_macros
|
||||
- [ ] Spec#dup
|
||||
- [ ] Spec#clone
|
||||
|
||||
# LICENSE
|
||||
|
||||
* Copyright © 2011 Duncan Mac-Vicar Prett <dmacvicar@suse.de>
|
||||
* Copyright © 2011 SUSE Linux Products GmbH
|
||||
|
||||
* This gem is a pure-ruby rewrite of ruby-rpm:
|
||||
Copyright © 2002 Kenta Murata. Relicensed with his permission.
|
||||
|
||||
Licensed under the MIT license. See MIT-LICENSE for details.
|
||||
|
@ -0,0 +1,52 @@
|
||||
$LOAD_PATH.push(File.join(File.dirname(__FILE__), 'lib'))
|
||||
require 'bundler/gem_tasks'
|
||||
require 'rpm/gem_version'
|
||||
require 'rake/testtask'
|
||||
|
||||
task default: [:test]
|
||||
|
||||
Rake::TestTask.new do |t|
|
||||
t.libs << File.expand_path('../test', __FILE__)
|
||||
t.libs << File.expand_path('../', __FILE__)
|
||||
t.test_files = FileList['test/test*.rb']
|
||||
t.verbose = true
|
||||
t.loader = :direct
|
||||
end
|
||||
|
||||
extra_docs = ['README*', 'TODO*', 'CHANGELOG*']
|
||||
|
||||
begin
|
||||
require 'yard'
|
||||
YARD::Rake::YardocTask.new(:doc) do |t|
|
||||
t.files = ['lib/**/*.rb', *extra_docs]
|
||||
t.options = ['--no-private']
|
||||
end
|
||||
rescue LoadError
|
||||
STDERR.puts 'Install yard if you want prettier docs'
|
||||
begin
|
||||
require 'rdoc/task'
|
||||
Rake::RDocTask.new(:doc) do |rdoc|
|
||||
rdoc.rdoc_dir = 'doc'
|
||||
rdoc.title = "rpm for Ruby #{RPM::GEM_VERSION}"
|
||||
extra_docs.each { |ex| rdoc.rdoc_files.include ex }
|
||||
end
|
||||
rescue LoadError
|
||||
STDERR.puts 'rdoc not available'
|
||||
end
|
||||
end
|
||||
|
||||
desc "Build the docker images for test"
|
||||
task :docker_images do
|
||||
Dir.glob('_docker/Dockerfile.*').each do |dockerfile|
|
||||
tag = 'ruby-rpm-ffi:' + File.extname(dockerfile).delete('.')
|
||||
sh %(podman build -f #{dockerfile} -t #{tag} .)
|
||||
end
|
||||
end
|
||||
|
||||
desc "Run the tests from within the docker images"
|
||||
task :docker_test do
|
||||
Dir.glob('_docker/Dockerfile.*').each do |dockerfile|
|
||||
tag = 'ruby-rpm-ffi:' + File.extname(dockerfile).delete('.')
|
||||
sh %(podman run -ti -v #{Dir.pwd}:/src #{tag} rake test)
|
||||
end
|
||||
end
|
@ -0,0 +1,8 @@
|
||||
FROM docker.io/redhat/ubi8:latest
|
||||
RUN dnf module -y enable ruby:3.1
|
||||
RUN dnf install -y ruby git
|
||||
RUN gem install bundler
|
||||
WORKDIR /src
|
||||
RUN ls -lR
|
||||
COPY ../ /src
|
||||
RUN bundle install
|
@ -0,0 +1,8 @@
|
||||
FROM docker.io/redhat/ubi9:latest
|
||||
RUN dnf module -y enable ruby:3.3
|
||||
RUN dnf install -y ruby git
|
||||
RUN gem install bundler
|
||||
WORKDIR /src
|
||||
RUN ls -lR
|
||||
COPY ../ /src
|
||||
RUN bundle install
|
@ -0,0 +1,88 @@
|
||||
|
||||
require 'rpm/c'
|
||||
require 'rpm/package'
|
||||
require 'rpm/file'
|
||||
require 'rpm/db'
|
||||
require 'rpm/problem'
|
||||
require 'rpm/transaction'
|
||||
require 'rpm/match_iterator'
|
||||
require 'rpm/version'
|
||||
require 'rpm/dependency'
|
||||
require 'rpm/utils'
|
||||
|
||||
module RPM
|
||||
TAG = RPM::C::Tag
|
||||
LOG = RPM::C::Log
|
||||
SENSE = RPM::C::Sense
|
||||
FILE = RPM::C::FileAttrs
|
||||
FILE_STATE = RPM::C::FileState
|
||||
TRANS_FLAG = RPM::C::TransFlags
|
||||
PROB_FILTER = RPM::C::ProbFilter
|
||||
MIRE = RPM::C::RegexpMode
|
||||
|
||||
# Creates a new transaction and pass it
|
||||
# to the given block
|
||||
#
|
||||
# @param [String] root dir, default '/'
|
||||
#
|
||||
# @example
|
||||
# RPM.transaction do |ts|
|
||||
# ...
|
||||
# end
|
||||
#
|
||||
def self.transaction(root = '/')
|
||||
ts = Transaction.new
|
||||
ts.root_dir = root
|
||||
yield ts
|
||||
ensure
|
||||
ts.ptr.free
|
||||
end
|
||||
|
||||
# @param [String] name Name of the macro
|
||||
# @return [String] value of macro +name+
|
||||
def self.[](name)
|
||||
if C::rpm_version_code >= ((4 << 16) + (14 << 8) + (0 << 0))
|
||||
obuf = ::FFI::MemoryPointer.new(:pointer, 1)
|
||||
sbuf = FFI::MemoryPointer.from_string("%{#{name}}")
|
||||
ret = RPM::C.rpmExpandMacros(nil, sbuf, obuf, 0)
|
||||
raise if ret < 0
|
||||
|
||||
val = obuf.read_pointer
|
||||
val.nil? ? nil : val.read_string
|
||||
else
|
||||
buffer = ::FFI::MemoryPointer.new(:pointer, 1024)
|
||||
buffer.write_string("%{#{name}}")
|
||||
ret = RPM::C.expandMacros(nil, nil, buffer, 1024)
|
||||
raise if ret < 0
|
||||
|
||||
buffer.read_string
|
||||
end
|
||||
end
|
||||
|
||||
# Setup a macro
|
||||
# @param [String] name Name of the macro
|
||||
# @param [String] value Value of the macro or +nil+ to delete it
|
||||
def self.[]=(name, value)
|
||||
if value.nil?
|
||||
if C::rpm_version_code >= ((4 << 16) + (14 << 8) + (0 << 0))
|
||||
RPM::C.rpmPopMacro(nil, name.to_s)
|
||||
else
|
||||
RPM::C.delMacro(nil, name.to_s)
|
||||
end
|
||||
else
|
||||
if C::rpm_version_code >= ((4 << 16) + (14 << 8) + (0 << 0))
|
||||
RPM::C.rpmPushMacro(nil, name.to_s, '', value.to_s, RPM::C::RMIL_DEFAULT)
|
||||
else
|
||||
RPM::C.addMacro(nil, name.to_s, '', value.to_s, RPM::C::RMIL_DEFAULT)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RPM::C.rpmReadConfigFiles(nil, nil)
|
||||
RPM::C.rpmInitMacros(nil, RPM::C.MACROFILES)
|
||||
|
||||
# TODO
|
||||
# set verbosity
|
||||
|
||||
require 'rpm/compat'
|
@ -0,0 +1,49 @@
|
||||
require 'ffi'
|
||||
|
||||
module RPM
|
||||
module C
|
||||
extend ::FFI::Library
|
||||
|
||||
begin
|
||||
ffi_lib ['rpm',
|
||||
'librpm.so.9',
|
||||
'librpm.so.8', # Tumbleweed
|
||||
'librpm.so.7', # fedora 23
|
||||
'librpm.so.3', 'librpm.so.2', 'librpm.so.1']
|
||||
rescue LoadError => e
|
||||
raise(
|
||||
"Can't find rpm libs on your system: #{e.message}"
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'rpm/c/rpmtypes'
|
||||
require 'rpm/c/rpmcallback'
|
||||
require 'rpm/c/rpmtag'
|
||||
require 'rpm/c/rpmlib'
|
||||
|
||||
module RPM
|
||||
module C
|
||||
|
||||
def self.rpm_version_code
|
||||
ver = ::RPM::C.RPMVERSION.split('.', 3)
|
||||
return (ver[0].to_i<<16) + (ver[1].to_i<<8) + (ver[2].to_i<<0)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
require 'rpm/c/rpmlog'
|
||||
require 'rpm/c/rpmmacro'
|
||||
require 'rpm/c/rpmio'
|
||||
require 'rpm/c/header'
|
||||
require 'rpm/c/rpmprob'
|
||||
require 'rpm/c/rpmps'
|
||||
require 'rpm/c/rpmfi'
|
||||
require 'rpm/c/rpmdb'
|
||||
require 'rpm/c/rpmcallback'
|
||||
require 'rpm/c/rpmcli'
|
||||
require 'rpm/c/rpmts'
|
||||
require 'rpm/c/rpmds'
|
||||
require 'rpm/c/rpmtd'
|
@ -0,0 +1,36 @@
|
||||
|
||||
module RPM
|
||||
module C
|
||||
typedef :pointer, :header
|
||||
|
||||
attach_function 'headerNew', [], :header
|
||||
attach_function 'headerFree', [:header], :header
|
||||
attach_function 'headerLink', [:header], :header
|
||||
# ..
|
||||
HEADERGET_DEFAULT = [0,
|
||||
HEADERGET_MINMEM = (1 << 0)].freeze
|
||||
HEADERGET_EXT = (1 << 1)
|
||||
HEADERGET_RAW = (1 << 2)
|
||||
HEADERGET_ALLOC = (1 << 3)
|
||||
HEADERGET_ARGV = (1 << 4)
|
||||
|
||||
# ..
|
||||
attach_function 'headerGet', %i[header rpmTagVal pointer uint32], :int
|
||||
attach_function 'headerPut', %i[header pointer uint32], :int
|
||||
# ...
|
||||
attach_function 'headerFormat', %i[header string pointer], :pointer
|
||||
# ...
|
||||
# http://rpm.org/wiki/Releases/4.14.0 deprecated addMacro/delMacro
|
||||
unless rpm_version_code >= ((4 << 16) + (14 << 8) + (0 << 0))
|
||||
attach_function 'headerNVR', [:header, :pointer, :pointer, :pointer], :int
|
||||
end
|
||||
# ...
|
||||
attach_function 'headerGetAsString', %i[header rpmTagVal], :string
|
||||
# ...
|
||||
attach_function 'headerPutString', %i[header rpmTagVal string], :int
|
||||
# ...
|
||||
attach_function 'headerPutUint32', %i[header rpmTagVal pointer rpm_count_t], :int
|
||||
# ...
|
||||
attach_function 'rpmReadPackageFile', %i[header FD_t string pointer], Rc
|
||||
end
|
||||
end
|
@ -0,0 +1,27 @@
|
||||
|
||||
module RPM
|
||||
module C
|
||||
CallbackType = enum(:rpmCallbackType, [
|
||||
:unknown, 0,
|
||||
:inst_progress, (1 << 0),
|
||||
:inst_start, (1 << 1),
|
||||
:inst_open_file, (1 << 2),
|
||||
:inst_close_file, (1 << 3),
|
||||
:trans_progress, (1 << 4),
|
||||
:trans_start, (1 << 5),
|
||||
:trans_stop, (1 << 6),
|
||||
:uninst_progress, (1 << 7),
|
||||
:uninst_start, (1 << 8),
|
||||
:uninst_stop, (1 << 9),
|
||||
:repackage_progress, (1 << 10),
|
||||
:repackage_start, (1 << 11),
|
||||
:repackage_stop, (1 << 12),
|
||||
:unpack_error, (1 << 13),
|
||||
:cpio_error, (1 << 14),
|
||||
:script_error, (1 << 15)
|
||||
])
|
||||
|
||||
typedef :pointer, :rpmCallbackData
|
||||
callback :rpmCallbackFunction, %i[pointer rpmCallbackType rpm_loff_t rpm_loff_t fnpyKey rpmCallbackData], :pointer
|
||||
end
|
||||
end
|
@ -0,0 +1,6 @@
|
||||
|
||||
module RPM
|
||||
module C
|
||||
attach_function 'rpmShowProgress', %i[pointer rpmCallbackType rpm_loff_t rpm_loff_t fnpyKey pointer], :pointer
|
||||
end
|
||||
end
|
@ -0,0 +1,20 @@
|
||||
module RPM
|
||||
module C
|
||||
typedef :pointer, :rpmdb
|
||||
typedef :pointer, :rpmdbMatchIterator
|
||||
|
||||
RegexpMode = enum(:rpmMireMode, %i[
|
||||
default strcmp regex glob
|
||||
])
|
||||
|
||||
attach_function 'rpmdbCountPackages', %i[rpmdb string], :int
|
||||
attach_function 'rpmdbGetIteratorOffset', [:rpmdbMatchIterator], :uint
|
||||
attach_function 'rpmdbGetIteratorCount', [:rpmdbMatchIterator], :int
|
||||
attach_function 'rpmdbSetIteratorRE', %i[rpmdbMatchIterator rpmTagVal rpmMireMode string], :int
|
||||
|
||||
attach_function 'rpmdbInitIterator', %i[rpmdb rpmDbiTagVal pointer size_t], :rpmdbMatchIterator
|
||||
|
||||
attach_function 'rpmdbNextIterator', [:rpmdb], :header
|
||||
attach_function 'rpmdbFreeIterator', [:rpmdb], :rpmdbMatchIterator
|
||||
end
|
||||
end
|
@ -0,0 +1,43 @@
|
||||
|
||||
module RPM
|
||||
module C
|
||||
typedef :pointer, :rpmds
|
||||
|
||||
Sense = enum(:rpmsenseFlags_e, [
|
||||
:any, 0,
|
||||
:less, (1 << 1),
|
||||
:greater, (1 << 2),
|
||||
:equal, (1 << 3),
|
||||
# bit 4 unused
|
||||
:posttrans, (1 << 5),
|
||||
:prereq, (1 << 6),
|
||||
#
|
||||
:pretrans, (1 << 7),
|
||||
:interp, (1 << 8),
|
||||
:script_pre, (1 << 9),
|
||||
:script_post, (1 << 10),
|
||||
:script_preun, (1 << 11),
|
||||
:script_postun, (1 << 12),
|
||||
:script_verify, (1 << 13),
|
||||
:find_requires, (1 << 14),
|
||||
:find_provides, (1 << 15),
|
||||
#
|
||||
:triggerin, (1 << 16),
|
||||
:triggerun, (1 << 17),
|
||||
:triggerpostun, (1 << 18),
|
||||
:missingok, (1 << 19),
|
||||
# 20 23 unused
|
||||
:rpmlib, (1 << 24),
|
||||
:triggerprein, (1 << 25),
|
||||
:keyring, (1 << 26),
|
||||
:strong, (1 << 27),
|
||||
:config, (1 << 28)
|
||||
])
|
||||
typedef :rpmFlags, :rpmsenseFlags
|
||||
|
||||
# ...
|
||||
attach_function 'rpmdsSingle', %i[rpmTagVal string string rpmsenseFlags], :rpmds
|
||||
# ...
|
||||
attach_function 'rpmdsCompare', %i[rpmds rpmds], :int
|
||||
end
|
||||
end
|
@ -0,0 +1,31 @@
|
||||
|
||||
module RPM
|
||||
module C
|
||||
FileAttrs = enum(:rpmfileAttrs, [
|
||||
:none, 0,
|
||||
:config, (1 << 0),
|
||||
:doc, (1 << 1),
|
||||
:icon, (1 << 2),
|
||||
:missingok, (1 << 3),
|
||||
:noreplace, (1 << 4),
|
||||
:specfile, (1 << 5),
|
||||
:ghost, (1 << 6),
|
||||
:license, (1 << 7),
|
||||
:readme, (1 << 8),
|
||||
:exclude, (1 << 9),
|
||||
:unpatched, (1 << 10),
|
||||
:pubkey, (1 << 11)
|
||||
])
|
||||
typedef :rpmFlags, :rpmfileAttrs
|
||||
|
||||
FileState = enum(:rpmfileState,
|
||||
:missing, -1,
|
||||
:normal, 0,
|
||||
:replaced, 1,
|
||||
:notinstalled, 2,
|
||||
:netshared, 3,
|
||||
:wrongcolor, 4)
|
||||
|
||||
typedef :pointer, :rpmRelocation
|
||||
end
|
||||
end
|
@ -0,0 +1,19 @@
|
||||
module RPM
|
||||
module C
|
||||
typedef :pointer, :FD_t
|
||||
# RPMIO
|
||||
attach_function 'Fstrerror', [:FD_t], :string
|
||||
# ...
|
||||
attach_function 'Fclose', [:FD_t], :int
|
||||
# ...
|
||||
attach_function 'Fopen', %i[string string], :FD_t
|
||||
# ...
|
||||
attach_function 'Ferror', [:FD_t], :int
|
||||
|
||||
attach_function 'fdDup', [:int], :FD_t
|
||||
|
||||
attach_function 'Fstrerror', [:FD_t], :string
|
||||
|
||||
attach_function 'fdLink', [:pointer], :FD_t
|
||||
end
|
||||
end
|
@ -0,0 +1,12 @@
|
||||
|
||||
module RPM
|
||||
module C
|
||||
attach_variable :RPMVERSION, :RPMVERSION, :string
|
||||
attach_variable :RPMEVR, :rpmEVR, :string
|
||||
|
||||
attach_function 'rpmReadConfigFiles', %i[string string], :int
|
||||
|
||||
# ...
|
||||
attach_function 'rpmvercmp', %i[string string], :int
|
||||
end
|
||||
end
|
@ -0,0 +1,23 @@
|
||||
|
||||
module RPM
|
||||
module C
|
||||
# rpmlog
|
||||
RPMLOG_PRIMASK = 0x07
|
||||
|
||||
Log = enum(
|
||||
:emerg, 0,
|
||||
:alert, 1,
|
||||
:crit, 2,
|
||||
:err, 3,
|
||||
:warning, 4,
|
||||
:notice, 5,
|
||||
:info, 6,
|
||||
:debug, 7
|
||||
)
|
||||
|
||||
attach_function 'rpmlogSetMask', [:int], :int
|
||||
# TODO: defines to set verbosity
|
||||
# ...
|
||||
attach_function 'rpmlogMessage', [], :string
|
||||
end
|
||||
end
|
@ -0,0 +1,33 @@
|
||||
|
||||
module RPM
|
||||
module C
|
||||
attach_variable :MACROFILES, :macrofiles, :string
|
||||
# ...
|
||||
|
||||
# Markers for sources of macros added throughout rpm.
|
||||
RMIL_DEFAULT = -15
|
||||
RMIL_MACROFILES = -13
|
||||
RMIL_RPMRC = -11
|
||||
RMIL_CMDLINE = -7
|
||||
RMIL_TARBALL = -5
|
||||
RMIL_SPEC = -3
|
||||
RMIL_OLDSPEC = -1
|
||||
RMIL_GLOBAL = 0
|
||||
|
||||
# ...
|
||||
# http://rpm.org/wiki/Releases/4.14.0 deprecated addMacro/delMacro
|
||||
if rpm_version_code >= ((4 << 16) + (14 << 8) + (0 << 0))
|
||||
attach_function 'rpmPushMacro', [:pointer, :string, :string, :string, :int], :void
|
||||
attach_function 'rpmPopMacro', [:pointer, :string], :void
|
||||
attach_function 'rpmExpandMacros', [:pointer, :pointer, :pointer, :int], :int
|
||||
else
|
||||
attach_function 'addMacro', [:pointer, :string, :string, :string, :int], :void
|
||||
attach_function 'delMacro', [:pointer, :string], :void
|
||||
attach_function 'expandMacros', [:pointer, :pointer, :pointer, :size_t], :int
|
||||
end
|
||||
# ...
|
||||
# ...
|
||||
attach_function 'rpmInitMacros', %i[pointer string], :void
|
||||
# ...
|
||||
end
|
||||
end
|
@ -0,0 +1,53 @@
|
||||
|
||||
module RPM
|
||||
module C
|
||||
typedef :pointer, :rpmProblem
|
||||
|
||||
ProbFilter = enum(:rpmprobFilterFlags_e, [
|
||||
:none, 0,
|
||||
:ignoreos, (1 << 0),
|
||||
:ignorearch, (1 << 1),
|
||||
:replacepkg, (1 << 2),
|
||||
:forcerelocate, (1 << 3),
|
||||
:replacenewfiles, (1 << 4),
|
||||
:replaceoldfiles, (1 << 5),
|
||||
:oldpackage, (1 << 6),
|
||||
:diskspace, (1 << 7),
|
||||
:disknodes, (1 << 8)
|
||||
])
|
||||
|
||||
typedef :rpmFlags, :rpmprobFilterFlags
|
||||
|
||||
ProblemType = enum(:rpmProblemType, %i[
|
||||
badarch
|
||||
bados
|
||||
pkg_installed
|
||||
badrelocate
|
||||
requires
|
||||
conflict
|
||||
new_file_conflict
|
||||
file_conflict
|
||||
oldpackage
|
||||
diskspace
|
||||
disknodes
|
||||
obsoletes
|
||||
])
|
||||
|
||||
attach_function 'rpmProblemCreate', %i[rpmProblemType string fnpyKey string string uint64], :rpmProblem
|
||||
attach_function 'rpmProblemFree', [:rpmProblem], :rpmProblem
|
||||
attach_function 'rpmProblemLink', [:rpmProblem], :rpmProblem
|
||||
attach_function 'rpmProblemGetType', [:rpmProblem], :rpmProblemType
|
||||
attach_function 'rpmProblemGetKey', [:rpmProblem], :fnpyKey
|
||||
attach_function 'rpmProblemGetStr', [:rpmProblem], :string
|
||||
attach_function 'rpmProblemString', [:rpmProblem], :string
|
||||
|
||||
begin
|
||||
attach_function 'rpmProblemCompare', %i[rpmProblem rpmProblem], :int
|
||||
rescue ::FFI::NotFoundError
|
||||
# TODO: Implement this for librpm 4.8.
|
||||
def self.rpmProblemCompare(_a, _b)
|
||||
raise NotImplementedError, 'rpmProblemCompare is not present in librpm 4.8 and below'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,11 @@
|
||||
module RPM
|
||||
module C
|
||||
typedef :pointer, :rpmps
|
||||
typedef :pointer, :rpmpsi
|
||||
|
||||
attach_function 'rpmpsInitIterator', [:rpmps], :rpmpsi
|
||||
attach_function 'rpmpsNextIterator', [:rpmpsi], :int
|
||||
attach_function 'rpmpsGetProblem', [:rpmpsi], :rpmProblem
|
||||
attach_function 'rpmpsFree', [:rpmps], :rpmps
|
||||
end
|
||||
end
|
@ -0,0 +1,304 @@
|
||||
module RPM
|
||||
module C
|
||||
Tag = enum(:rpmTag, [
|
||||
:not_found, -1,
|
||||
:headerimage, 61,
|
||||
:headersignatures, 62,
|
||||
:headerimmutable, 63,
|
||||
:headerregions, 64,
|
||||
:headeri18ntable, 100,
|
||||
:sig_base, 256,
|
||||
:sigsize, 256 + 1,
|
||||
:siglemd5_1, 256 + 2,
|
||||
:sigpgp, 256 + 3,
|
||||
:siglemd5_2, 256 + 4,
|
||||
:sigmd5, 256 + 5,
|
||||
:siggpg, 256 + 6,
|
||||
:sigpgp5, 256 + 7,
|
||||
:badsha1_1, 256 + 8,
|
||||
:badsha1_2, 256 + 9,
|
||||
:pubkeys, 256 + 10,
|
||||
:dsaheader, 256 + 11,
|
||||
:rsaheader, 256 + 12,
|
||||
:sha1header, 256 + 13,
|
||||
:longsigsize, 256 + 14,
|
||||
:longarchivesize, 256 + 15,
|
||||
:name, 1000,
|
||||
:version, 1001,
|
||||
:release, 1002,
|
||||
:epoch, 1003,
|
||||
:summary, 1004,
|
||||
:description, 1005,
|
||||
:buildtime, 1006,
|
||||
:buildhost, 1007,
|
||||
:installtime, 1008,
|
||||
:size, 1009,
|
||||
:distribution, 1010,
|
||||
:vendor, 1011,
|
||||
:gif, 1012,
|
||||
:xpm, 1013,
|
||||
:license, 1014,
|
||||
:packager, 1015,
|
||||
:group, 1016,
|
||||
:changelog, 1017,
|
||||
:source, 1018,
|
||||
:patch, 1019,
|
||||
:url, 1020,
|
||||
:os, 1021,
|
||||
:arch, 1022,
|
||||
:prein, 1023,
|
||||
:postin, 1024,
|
||||
:preun, 1025,
|
||||
:postun, 1026,
|
||||
:oldfilenames, 1027,
|
||||
:filesizes, 1028,
|
||||
:filestates, 1029,
|
||||
:filemodes, 1030,
|
||||
:fileuids, 1031,
|
||||
:filegids, 1032,
|
||||
:filerdevs, 1033,
|
||||
:filemtimes, 1034,
|
||||
:filedigests, 1035,
|
||||
:filemd5s, 1035,
|
||||
:filelinktos, 1036,
|
||||
:fileflags, 1037,
|
||||
:root, 1038,
|
||||
:fileusername, 1039,
|
||||
:filegroupname, 1040,
|
||||
:exclude, 1041,
|
||||
:exclusive, 1042,
|
||||
:icon, 1043,
|
||||
:sourcerpm, 1044,
|
||||
:fileverifyflags, 1045,
|
||||
:archivesize, 1046,
|
||||
:providename, 1047,
|
||||
:requireflags, 1048,
|
||||
:requirename, 1049,
|
||||
:requireversion, 1050,
|
||||
:nosource, 1051,
|
||||
:nopatch, 1052,
|
||||
:conflictflags, 1053,
|
||||
:conflictname, 1054,
|
||||
:conflictversion, 1055,
|
||||
:defaultprefix, 1056,
|
||||
:buildroot, 1057,
|
||||
:installprefix, 1058,
|
||||
:excludearch, 1059,
|
||||
:excludeos, 1060,
|
||||
:exclusivearch, 1061,
|
||||
:exclusiveos, 1062,
|
||||
:autoreqprov, 1063,
|
||||
:rpmversion, 1064,
|
||||
:triggerscripts, 1065,
|
||||
:triggername, 1066,
|
||||
:triggerversion, 1067,
|
||||
:triggerflags, 1068,
|
||||
:triggerindex, 1069,
|
||||
:verifyscript, 1079,
|
||||
:changelogtime, 1080,
|
||||
:changelogname, 1081,
|
||||
:changelogtext, 1082,
|
||||
:brokenmd5, 1083,
|
||||
:prereq, 1084,
|
||||
:preinprog, 1085,
|
||||
:postinprog, 1086,
|
||||
:preunprog, 1087,
|
||||
:postunprog, 1088,
|
||||
:buildarchs, 1089,
|
||||
:obsoletename, 1090,
|
||||
:verifyscriptprog, 1091,
|
||||
:triggerscriptprog, 1092,
|
||||
:docdir, 1093,
|
||||
:cookie, 1094,
|
||||
:filedevices, 1095,
|
||||
:fileinodes, 1096,
|
||||
:filelangs, 1097,
|
||||
:prefixes, 1098,
|
||||
:instprefixes, 1099,
|
||||
:triggerin, 1100,
|
||||
:triggerun, 1101,
|
||||
:triggerpostun, 1102,
|
||||
:autoreq, 1103,
|
||||
:autoprov, 1104,
|
||||
:capability, 1105,
|
||||
:sourcepackage, 1106,
|
||||
:oldorigfilenames, 1107,
|
||||
:buildprereq, 1108,
|
||||
:buildrequires, 1109,
|
||||
:buildconflicts, 1110,
|
||||
:buildmacros, 1111,
|
||||
:provideflags, 1112,
|
||||
:provideversion, 1113,
|
||||
:obsoleteflags, 1114,
|
||||
:obsoleteversion, 1115,
|
||||
:dirindexes, 1116,
|
||||
:basenames, 1117,
|
||||
:dirnames, 1118,
|
||||
:origdirindexes, 1119,
|
||||
:origbasenames, 1120,
|
||||
:origdirnames, 1121,
|
||||
:optflags, 1122,
|
||||
:disturl, 1123,
|
||||
:payloadformat, 1124,
|
||||
:payloadcompressor, 1125,
|
||||
:payloadflags, 1126,
|
||||
:installcolor, 1127,
|
||||
:installtid, 1128,
|
||||
:removetid, 1129,
|
||||
:sha1rhn, 1130,
|
||||
:rhnplatform, 1131,
|
||||
:platform, 1132,
|
||||
:patchesname, 1133,
|
||||
:patchesflags, 1134,
|
||||
:patchesversion, 1135,
|
||||
:cachectime, 1136,
|
||||
:cachepkgpath, 1137,
|
||||
:cachepkgsize, 1138,
|
||||
:cachepkgmtime, 1139,
|
||||
:filecolors, 1140,
|
||||
:fileclass, 1141,
|
||||
:classdict, 1142,
|
||||
:filedependsx, 1143,
|
||||
:filedependsn, 1144,
|
||||
:dependsdict, 1145,
|
||||
:sourcepkgid, 1146,
|
||||
:filecontexts, 1147,
|
||||
:fscontexts, 1148,
|
||||
:recontexts, 1149,
|
||||
:policies, 1150,
|
||||
:pretrans, 1151,
|
||||
:posttrans, 1152,
|
||||
:pretransprog, 1153,
|
||||
:posttransprog, 1154,
|
||||
:disttag, 1155,
|
||||
:suggestsname, 1156,
|
||||
:suggestsversion, 1157,
|
||||
:suggestsflags, 1158,
|
||||
:enhancesname, 1159,
|
||||
:enhancesversion, 1160,
|
||||
:enhancesflags, 1161,
|
||||
:priority, 1162,
|
||||
:cvsid, 1163,
|
||||
:blinkpkgid, 1164,
|
||||
:blinkhdrid, 1165,
|
||||
:blinknevra, 1166,
|
||||
:flinkpkgid, 1167,
|
||||
:flinkhdrid, 1168,
|
||||
:flinknevra, 1169,
|
||||
:packageorigin, 1170,
|
||||
:triggerprein, 1171,
|
||||
:buildsuggests, 1172,
|
||||
:buildenhances, 1173,
|
||||
:scriptstates, 1174,
|
||||
:scriptmetrics, 1175,
|
||||
:buildcpuclock, 1176,
|
||||
:filedigestalgos, 1177,
|
||||
:variants, 1178,
|
||||
:xmajor, 1179,
|
||||
:xminor, 1180,
|
||||
:repotag, 1181,
|
||||
:keywords, 1182,
|
||||
:buildplatforms, 1183,
|
||||
:packagecolor, 1184,
|
||||
:packageprefcolor, 1185,
|
||||
:xattrsdict, 1186,
|
||||
:filexattrsx, 1187,
|
||||
:depattrsdict, 1188,
|
||||
:conflictattrsx, 1189,
|
||||
:obsoleteattrsx, 1190,
|
||||
:provideattrsx, 1191,
|
||||
:requireattrsx, 1192,
|
||||
:buildprovides, 1193,
|
||||
:buildobsoletes, 1194,
|
||||
:dbinstance, 1195,
|
||||
:nvra, 1196,
|
||||
:filenames, 5000,
|
||||
:fileprovide, 5001,
|
||||
:filerequire, 5002,
|
||||
:fsnames, 5003,
|
||||
:fssizes, 5004,
|
||||
:triggerconds, 5005,
|
||||
:triggertype, 5006,
|
||||
:origfilenames, 5007,
|
||||
:longfilesizes, 5008,
|
||||
:longsize, 5009,
|
||||
:filecaps, 5010,
|
||||
:filedigestalgo, 5011,
|
||||
:bugurl, 5012,
|
||||
:evr, 5013,
|
||||
:nvr, 5014,
|
||||
:nevr, 5015,
|
||||
:nevra, 5016,
|
||||
:headercolor, 5017,
|
||||
:verbose, 5018,
|
||||
:epochnum, 5019,
|
||||
:preinflags, 5020,
|
||||
:postinflags, 5021,
|
||||
:preunflags, 5022,
|
||||
:postunflags, 5023,
|
||||
:pretransflags, 5024,
|
||||
:posttransflags, 5025,
|
||||
:verifyscriptflags, 5026,
|
||||
:triggerscriptflags, 5027,
|
||||
:collections, 5029,
|
||||
:policynames, 5030,
|
||||
:policytypes, 5031,
|
||||
:policytypesindexes, 5032,
|
||||
:policyflags, 5033,
|
||||
:vcs, 5034,
|
||||
:ordername, 5035,
|
||||
:orderversion, 5036,
|
||||
:orderflags, 5037,
|
||||
:firstfree_tag
|
||||
])
|
||||
|
||||
Dbi = enum(:rpmDbiTag_e, [
|
||||
:packages, 0,
|
||||
:label, 2,
|
||||
:name, Tag[:name],
|
||||
:basenames, Tag[:basenames],
|
||||
:group, Tag[:group],
|
||||
:requirename, Tag[:requirename],
|
||||
:providename, Tag[:providename],
|
||||
:conflictname, Tag[:conflictname],
|
||||
:obsoletename, Tag[:obsoletename],
|
||||
:triggername, Tag[:triggername],
|
||||
:dirnames, Tag[:dirnames],
|
||||
:installtid, Tag[:installtid],
|
||||
:sigmd5, Tag[:sigmd5],
|
||||
:sha1header, Tag[:sha1header]
|
||||
])
|
||||
|
||||
TagType = enum(:rpmTagType, [
|
||||
:null_type, 0,
|
||||
:char_type, 1,
|
||||
:int8_type, 2,
|
||||
:int16_type, 3,
|
||||
:int32_type, 4,
|
||||
:int64_type, 5,
|
||||
:string_type, 6,
|
||||
:bin_type, 7,
|
||||
:string_array_type, 8,
|
||||
:i18nstring_type, 9
|
||||
])
|
||||
|
||||
TagReturnType = enum(:rpmTagReturnType_e, [
|
||||
:any_return_type, 0,
|
||||
:scalar_return_type, 0x00010000,
|
||||
:array_return_type, 0x00020000,
|
||||
:mapping_return_type, 0x00040000,
|
||||
:mask_return_type, 0xffff0000
|
||||
])
|
||||
typedef :rpmFlags, :rpmTagReturnType
|
||||
|
||||
begin
|
||||
attach_function 'rpmTagGetReturnType', [:rpmTagVal], :rpmTagReturnType
|
||||
rescue ::FFI::NotFoundError
|
||||
attach_function 'rpmTagGetType', [:rpmTagVal], :rpmTagType
|
||||
|
||||
def self.rpmTagGetReturnType(tag)
|
||||
TagReturnType[rpmTagGetType(tag) & TagReturnType[:mask_return_type]]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,34 @@
|
||||
module RPM
|
||||
module C
|
||||
typedef :pointer, :rpmtd
|
||||
|
||||
attach_function 'rpmtdNew', [], :pointer
|
||||
attach_function 'rpmtdFree', [:rpmtd], :pointer
|
||||
attach_function 'rpmtdReset', [:rpmtd], :void
|
||||
attach_function 'rpmtdFreeData', [:rpmtd], :void
|
||||
attach_function 'rpmtdCount', [:rpmtd], :uint32
|
||||
attach_function 'rpmtdTag', [:rpmtd], :rpmTagVal
|
||||
attach_function 'rpmtdType', [:rpmtd], TagType
|
||||
# ...
|
||||
attach_function 'rpmtdInit', [:rpmtd], :int
|
||||
attach_function 'rpmtdNext', [:rpmtd], :int
|
||||
# ...
|
||||
attach_function 'rpmtdNextUint32', [:rpmtd], :pointer
|
||||
attach_function 'rpmtdNextUint64', [:rpmtd], :pointer
|
||||
attach_function 'rpmtdNextString', [:rpmtd], :string
|
||||
attach_function 'rpmtdGetChar', [:rpmtd], :pointer
|
||||
attach_function 'rpmtdGetUint16', [:rpmtd], :pointer
|
||||
attach_function 'rpmtdGetUint32', [:rpmtd], :pointer
|
||||
attach_function 'rpmtdGetUint64', [:rpmtd], :pointer
|
||||
attach_function 'rpmtdGetString', [:rpmtd], :string
|
||||
attach_function 'rpmtdGetNumber', [:rpmtd], :uint64
|
||||
# ...
|
||||
attach_function 'rpmtdFromUint8', %i[rpmtd rpmTagVal pointer rpm_count_t], :int
|
||||
attach_function 'rpmtdFromUint16', %i[rpmtd rpmTagVal pointer rpm_count_t], :int
|
||||
attach_function 'rpmtdFromUint32', %i[rpmtd rpmTagVal pointer rpm_count_t], :int
|
||||
attach_function 'rpmtdFromUint64', %i[rpmtd rpmTagVal pointer rpm_count_t], :int
|
||||
attach_function 'rpmtdFromString', %i[rpmtd rpmTagVal string], :int
|
||||
attach_function 'rpmtdFromStringArray', %i[rpmtd rpmTagVal pointer rpm_count_t], :int
|
||||
# ...
|
||||
end
|
||||
end
|
@ -0,0 +1,71 @@
|
||||
module RPM
|
||||
module C
|
||||
TransFlags = enum(:rpmtransFlags_e, [
|
||||
:none, 0,
|
||||
:test, (1 << 0),
|
||||
:build_probs, (1 << 1),
|
||||
:noscripts, (1 << 2),
|
||||
:justdb, (1 << 3),
|
||||
:notriggers, (1 << 4),
|
||||
:nodocs, (1 << 5),
|
||||
:allfiles, (1 << 6),
|
||||
# bit 7 unused
|
||||
:nocontexts, (1 << 8),
|
||||
# bits 9-15 unused
|
||||
:notriggerprein, (1 << 16),
|
||||
:nopre, (1 << 17),
|
||||
:nopost, (1 << 18),
|
||||
:notriggerin, (1 << 19),
|
||||
:notriggerun, (1 << 20),
|
||||
:nopreun, (1 << 21),
|
||||
:nopostun, (1 << 22),
|
||||
:notriggerpostun, (11 << 23),
|
||||
# bits 24-25 unused
|
||||
:nocollections, (1 << 26),
|
||||
:nomd5, (1 << 27),
|
||||
:nofiledigest, (1 << 27),
|
||||
# bits 28-29 unused
|
||||
:noconfigs, (1 << 30),
|
||||
:deploops, (1 << 31)
|
||||
])
|
||||
|
||||
typedef :pointer, :rpmts
|
||||
typedef :pointer, :rpmps
|
||||
typedef :rpmFlags, :rpmtransFlags
|
||||
|
||||
attach_function 'rpmtsCheck', [:rpmts], :int
|
||||
attach_function 'rpmtsOrder', [:rpmts], :int
|
||||
attach_function 'rpmtsRun', %i[rpmts rpmps int], :int
|
||||
attach_function 'rpmtsLink', [:rpmts], :rpmts
|
||||
attach_function 'rpmtsCloseDB', [:rpmts], :int
|
||||
attach_function 'rpmtsOpenDB', %i[rpmts int], :int
|
||||
attach_function 'rpmtsInitDB', %i[rpmts int], :int
|
||||
attach_function 'rpmtsGetDBMode', [:rpmts], :int
|
||||
attach_function 'rpmtsSetDBMode', %i[rpmts int], :int
|
||||
attach_function 'rpmtsRebuildDB', [:rpmts], :int
|
||||
attach_function 'rpmtsVerifyDB', [:rpmts], :int
|
||||
attach_function 'rpmtsInitIterator', %i[rpmts rpmDbiTagVal pointer int], :rpmdbMatchIterator
|
||||
# ...
|
||||
attach_function 'rpmtsProblems', [:rpmts], :rpmps
|
||||
# ...
|
||||
attach_function 'rpmtsClean', [:rpmts], :void
|
||||
# more...
|
||||
attach_function 'rpmtsFree', [:rpmts], :pointer
|
||||
# ..
|
||||
attach_function 'rpmtsSetNotifyCallback', %i[rpmts rpmCallbackFunction rpmCallbackData], :int
|
||||
# ...
|
||||
attach_function 'rpmtsRootDir', [:rpmts], :string
|
||||
attach_function 'rpmtsSetRootDir', %i[rpmts string], :int
|
||||
# ...
|
||||
attach_function 'rpmtsGetRdb', [:rpmts], :rpmdb
|
||||
# ..
|
||||
attach_function 'rpmtsFlags', [:rpmts], :rpmtransFlags
|
||||
attach_function 'rpmtsSetFlags', %i[rpmts rpmtransFlags], :rpmtransFlags
|
||||
# ...
|
||||
attach_function 'rpmtsSetNotifyCallback', %i[rpmts rpmCallbackFunction rpmCallbackData], :int
|
||||
# ...
|
||||
attach_function 'rpmtsCreate', [], :rpmts
|
||||
attach_function 'rpmtsAddInstallElement', %i[rpmts header fnpyKey int rpmRelocation], :int
|
||||
attach_function 'rpmtsAddEraseElement', %i[rpmts header int], :int
|
||||
end
|
||||
end
|
@ -0,0 +1,28 @@
|
||||
|
||||
module RPM
|
||||
module C
|
||||
Rc = enum(
|
||||
:ok, 0,
|
||||
:notfound, 1,
|
||||
:fail, 2,
|
||||
:nottrusted, 3,
|
||||
:nokey, 4
|
||||
)
|
||||
|
||||
typedef :int32, :rpm_tag_t
|
||||
typedef :uint32, :rpm_tagtype_t
|
||||
typedef :uint32, :rpm_count_t
|
||||
typedef :rpm_tag_t, :rpmTagVal
|
||||
typedef :rpm_tag_t, :rpmDbiTagVal
|
||||
|
||||
typedef :uint32, :rpmFlags
|
||||
typedef :uint32, :rpm_off_t
|
||||
typedef :uint64, :rpm_loff_t
|
||||
|
||||
typedef :pointer, :FD_t
|
||||
typedef :pointer, :fnpyKey
|
||||
typedef :pointer, :rpmCallbackData
|
||||
|
||||
typedef :uint64, :rpm_loff_t
|
||||
end
|
||||
end
|
@ -0,0 +1,40 @@
|
||||
|
||||
module RPM
|
||||
# compatibility
|
||||
TAG.to_h.each do |k, v|
|
||||
const_set "TAG_#{k.to_s.upcase}", v.to_i
|
||||
end
|
||||
|
||||
LOG.to_h.each do |k, v|
|
||||
const_set "LOG_#{k.to_s.upcase}", v.to_i
|
||||
end
|
||||
|
||||
SENSE.to_h.each do |k, v|
|
||||
const_set "SENSE_#{k.to_s.upcase}", v.to_i
|
||||
end
|
||||
|
||||
# RPMFILE_*
|
||||
FILE.to_h.each do |k, v|
|
||||
const_set "FILE_#{k.to_s.upcase}", v.to_i
|
||||
end
|
||||
|
||||
# RPMFILE_STATE_*
|
||||
FILE_STATE.to_h.each do |k, v|
|
||||
const_set "FILE_STATE_#{k.to_s.upcase}", v.to_i
|
||||
end
|
||||
|
||||
# RPMTRANS_FLAG_*
|
||||
TRANS_FLAG.to_h.each do |k, v|
|
||||
const_set "TRANS_FLAG_#{k.to_s.upcase}", v.to_i
|
||||
end
|
||||
|
||||
# RPMPROB_FILTER_*
|
||||
PROB_FILTER.to_h.each do |k, v|
|
||||
const_set "PROB_FILTER_#{k.to_s.upcase}", v.to_i
|
||||
end
|
||||
|
||||
# RPMPROB_FILTER_*
|
||||
MIRE.to_h.each do |k, v|
|
||||
const_set "MIRE_#{k.to_s.upcase}", v.to_i
|
||||
end
|
||||
end
|
@ -0,0 +1,117 @@
|
||||
require 'fcntl'
|
||||
|
||||
module RPM
|
||||
class DB
|
||||
include Enumerable
|
||||
|
||||
# @visibility private
|
||||
# @param ts [Transaction] transaction object
|
||||
def initialize(ts, opts = {})
|
||||
opts[:writable] ||= false
|
||||
|
||||
@ts = ts
|
||||
RPM::C.rpmtsOpenDB(@ts.ptr, opts[:writable] ? Fcntl::O_RDWR | Fcntl::O_CREAT : Fcntl::O_RDONLY)
|
||||
end
|
||||
|
||||
# @return [RPM::MatchIterator] Creates an iterator for +tag+ and +val+
|
||||
def init_iterator(tag, val)
|
||||
@ts.init_iterator(tag, val)
|
||||
end
|
||||
|
||||
#
|
||||
# @yield [Package] Called for each match
|
||||
# @param [Number] key RPM tag key
|
||||
# @param [String] val Value to match
|
||||
# @example
|
||||
# RPM.transaction do |t|
|
||||
# t.each_match(RPM::TAG_ARCH, "x86_64") do |pkg|
|
||||
# puts pkg.name
|
||||
# end
|
||||
# end
|
||||
#
|
||||
def each_match(key, val, &block)
|
||||
@ts.each_match(key, val, &block)
|
||||
end
|
||||
|
||||
#
|
||||
# @yield [Package] Called for each package in the database
|
||||
# @example
|
||||
# db.each do |pkg|
|
||||
# puts pkg.name
|
||||
# end
|
||||
#
|
||||
def each(&block)
|
||||
@ts.each(&block)
|
||||
end
|
||||
|
||||
# @visibility private
|
||||
def ptr
|
||||
RPM::C.rpmtsGetRdb(@ts.ptr)
|
||||
end
|
||||
|
||||
def close
|
||||
RPM::C.rpmtsCloseDB(@ts.ptr)
|
||||
end
|
||||
|
||||
def closed?
|
||||
ptr.null?
|
||||
end
|
||||
|
||||
#
|
||||
# The package database is opened, but transactional processing
|
||||
# (@see RPM::DB#transaction) cannot be done for when +writable+ is false.
|
||||
# When +writable+ is +false+ then the generated object gets freezed.
|
||||
# @param [Boolean] writable Whether the database is writable. Default is +false+.
|
||||
# @param [String] root Root path for the database, default is empty.
|
||||
# @return [RPM::DB]
|
||||
#
|
||||
# @example
|
||||
# db = RPM::DB.open
|
||||
# db.each do |pkg|
|
||||
# puts pkg.name
|
||||
# end
|
||||
#
|
||||
def self.open(_writable = false, root = '/', &block)
|
||||
open_for_transaction(Transaction.new(root: root), writable: false, &block)
|
||||
end
|
||||
|
||||
# @visibility private
|
||||
def self.open_for_transaction(ts, opts = {})
|
||||
db = new(ts, opts)
|
||||
return db unless block_given?
|
||||
|
||||
begin
|
||||
yield db
|
||||
ensure
|
||||
db.close unless db.closed?
|
||||
end
|
||||
end
|
||||
|
||||
# @deprecated Not possible to get home value in
|
||||
# newer RPM versions
|
||||
def home
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# @return [String] The root path of the database
|
||||
def root
|
||||
RPM::C.rpmtsRootDir(@ts.ptr)
|
||||
end
|
||||
|
||||
# @deprecated Use RPM::Transaction#each
|
||||
def self.each
|
||||
DB.open do |db|
|
||||
it = MatchIterator.from_ptr(RPM::C.rpmdbInitIterator(db.ptr, 0, nil, 0))
|
||||
if block_given?
|
||||
it.each do |pkg|
|
||||
yield pkg
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @return number of instances of +name+ in the
|
||||
# database
|
||||
def count_packages(name); end
|
||||
end
|
||||
end
|
@ -0,0 +1,120 @@
|
||||
|
||||
module RPM
|
||||
class Dependency
|
||||
# @return [String] dependency name
|
||||
attr_accessor :name
|
||||
# @return [String] dependency version
|
||||
attr_accessor :version
|
||||
# @return [String] dependency flags
|
||||
attr_accessor :flags
|
||||
# @return [Package] package this dependency belongs to
|
||||
attr_accessor :owner
|
||||
|
||||
attr_accessor :nametag
|
||||
attr_accessor :versiontag
|
||||
attr_accessor :flagstag
|
||||
|
||||
def initialize(name, version, flags, owner)
|
||||
RPM::Utils.check_type(version, RPM::Version)
|
||||
|
||||
@name = name
|
||||
@version = version
|
||||
@flags = flags
|
||||
@owner = owner
|
||||
end
|
||||
|
||||
# @param [Package, Dependency, Version] other
|
||||
# @return [Boolean] true if +other+ satisfies this dependency
|
||||
def satisfy?(other)
|
||||
case other
|
||||
when RPM::Package then
|
||||
other.provides.each do |prov|
|
||||
return true if satisfy?(prov)
|
||||
end
|
||||
false
|
||||
when RPM::Dependency then
|
||||
RPM::C.rpmdsCompare(
|
||||
RPM::C.rpmdsSingle(:providename, other.name,
|
||||
other.version.to_vre, other.flags),
|
||||
RPM::C.rpmdsSingle(:providename, name,
|
||||
version.to_vre, flags)
|
||||
) != 0
|
||||
when RPM::Version then
|
||||
RPM::C.rpmdsCompare(
|
||||
RPM::C.rpmdsSingle(:providename, name,
|
||||
other.to_vre, other.to_vre.empty? ? 0 : :equal),
|
||||
RPM::C.rpmdsSingle(:providename, name,
|
||||
version.to_vre, flags)
|
||||
) != 0
|
||||
else
|
||||
raise(TypeError, "#{other} is not a Version or Dependency")
|
||||
end
|
||||
end
|
||||
|
||||
# @return [Boolean] true if '<' or '=<' are used to compare the version
|
||||
def lt?
|
||||
flags & RPM::SENSE[:less]
|
||||
end
|
||||
|
||||
# @return [Boolean] true if '>' or '>=' are used to compare the version
|
||||
def gt?
|
||||
flags & RPM::SENSE[:greater]
|
||||
end
|
||||
|
||||
# @return [Boolean] true if '=', '=<' or '>=' are used to compare the version
|
||||
def eq?
|
||||
flags & RPM::SENSE[:equal]
|
||||
end
|
||||
|
||||
# @return [Boolean] true if '=<' is used to compare the version
|
||||
def le?
|
||||
(flags & RPM::SENSE[:less]) && (flags & RPM::SENSE[:equal])
|
||||
end
|
||||
|
||||
# @return [Boolean] true if '>=' is used to compare the version
|
||||
def ge?
|
||||
(flags & RPM::SENSE[:greater]) && (flags & RPM::SENSE[:equal])
|
||||
end
|
||||
|
||||
# @return [Boolean] true if this is a pre-requires
|
||||
def pre?
|
||||
flags & RPM::SENSE[:prereq]
|
||||
end
|
||||
end
|
||||
|
||||
class Provide < Dependency
|
||||
def initialize(name, version, flags, owner)
|
||||
super(name, version, flags, owner)
|
||||
@nametag = RPM::TAG[:providename]
|
||||
@versiontag = RPM::TAG[:provideversion]
|
||||
@flagstag = RPM::TAG[:provideflags]
|
||||
end
|
||||
end
|
||||
|
||||
class Require < Dependency
|
||||
def initialize(name, version, flags, owner)
|
||||
super(name, version, flags, owner)
|
||||
@nametag = RPM::TAG[:requirename]
|
||||
@versiontag = RPM::TAG[:requireversion]
|
||||
@flagstag = RPM::TAG[:requireflags]
|
||||
end
|
||||
end
|
||||
|
||||
class Conflict < Dependency
|
||||
def initialize(name, version, flags, owner)
|
||||
super(name, version, flags, owner)
|
||||
@nametag = RPM::TAG[:conflictname]
|
||||
@versiontag = RPM::TAG[:conflictversion]
|
||||
@flagstag = RPM::TAG[:conflictflags]
|
||||
end
|
||||
end
|
||||
|
||||
class Obsolete < Dependency
|
||||
def initialize(name, version, flags, owner)
|
||||
super(name, version, flags, owner)
|
||||
@nametag = RPM::TAG[:obsoletename]
|
||||
@versiontag = RPM::TAG[:obsoleteversion]
|
||||
@flagstag = RPM::TAG[:obsoleteflags]
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,7 @@
|
||||
|
||||
# The reason this file is gem_version.rb and not version.rb
|
||||
# is because it conflicts with the version.rb class
|
||||
module RPM
|
||||
PKG_NAME = 'ruby-rpm'.freeze
|
||||
GEM_VERSION = '0.0.5'.freeze
|
||||
end
|
@ -0,0 +1,66 @@
|
||||
|
||||
module RPM
|
||||
class MatchIterator
|
||||
include Enumerable
|
||||
|
||||
# @visibility private
|
||||
def self.release(ptr)
|
||||
RPM::C.rpmdbFreeIterator(ptr)
|
||||
end
|
||||
|
||||
# Creates a managed MatchIterator from a raw pointer
|
||||
# @visibility private
|
||||
def self.from_ptr(ptr)
|
||||
new(::FFI::AutoPointer.new(ptr, MatchIterator.method(:release)))
|
||||
end
|
||||
|
||||
def initialize(ptr)
|
||||
@ptr = ptr
|
||||
end
|
||||
|
||||
def each
|
||||
while (pkg = next_iterator)
|
||||
yield pkg
|
||||
end
|
||||
end
|
||||
|
||||
def next_iterator
|
||||
pkg_ptr = RPM::C.rpmdbNextIterator(@ptr)
|
||||
return RPM::Package.new(pkg_ptr) unless pkg_ptr.null?
|
||||
nil
|
||||
end
|
||||
|
||||
# @ return header join key for current position of rpm
|
||||
# database iterator
|
||||
def offset
|
||||
RPM::C.rpmdbGetIteratorOffset(@ptr)
|
||||
end
|
||||
|
||||
def set_iterator_re(tag, mode, string)
|
||||
ret = RPM::C.rpmdbSetIteratorRE(@ptr, tag, mode, string)
|
||||
raise "Error when setting regular expression '#{string}'" if ret != 0
|
||||
self
|
||||
end
|
||||
|
||||
alias regexp set_iterator_re
|
||||
|
||||
def set_iterator_version(version)
|
||||
unless version.is_a?(RPM::Version)
|
||||
raise TypeError, 'illegal argument type'
|
||||
end
|
||||
|
||||
set_iterator_re(:version, :default, version.v)
|
||||
set_iterator_re(:release, :default, version.r) if version.r
|
||||
self
|
||||
end
|
||||
|
||||
alias version set_iterator_version
|
||||
|
||||
def get_iterator_count
|
||||
RPM::C.rpmdbGetIteratorCount(@ptr)
|
||||
end
|
||||
|
||||
alias count get_iterator_count
|
||||
alias length get_iterator_count
|
||||
end
|
||||
end
|
@ -0,0 +1,333 @@
|
||||
|
||||
module RPM
|
||||
class ChangeLog
|
||||
attr_accessor :time, :name, :text
|
||||
end
|
||||
|
||||
class Package
|
||||
# Create a new package object from data
|
||||
# @param [String] str Header data
|
||||
# @return [Package]
|
||||
def load(_data)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def self.create(name, version)
|
||||
unless name.is_a?(String)
|
||||
raise TypeError, 'illegal argument type: name should be String'
|
||||
end
|
||||
unless version.is_a?(RPM::Version)
|
||||
raise TypeError, 'illegal argument type: version should be RPM::Version'
|
||||
end
|
||||
hdr = RPM::C.headerNew
|
||||
if RPM::C.headerPutString(hdr, :name, name) != 1
|
||||
raise "Can't set package name: #{name}"
|
||||
end
|
||||
if RPM::C.headerPutString(hdr, :version, version.v) != 1
|
||||
raise "Can't set package version: #{version.v}"
|
||||
end
|
||||
if version.e
|
||||
if RPM::C.headerPutUint32(hdr, :epoch, version.e) != 1
|
||||
raise "Can't set package epoch: #{version.e}"
|
||||
end
|
||||
end
|
||||
Package.new(hdr)
|
||||
end
|
||||
|
||||
# Add a dependency to the package header
|
||||
# @param [Dependency] dep Dependency to add
|
||||
def add_dependency(dep)
|
||||
unless dep.is_a?(Dependency)
|
||||
raise TypeError, 'illegal argument type: must be a Dependency'
|
||||
end
|
||||
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Add a int32 value to the package header
|
||||
# @param [Number] tag Tag
|
||||
# @param [Number] val Value
|
||||
def add_int32(_tag, _val)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Add a list of strings to the package header
|
||||
# @param [Number] tag Tag
|
||||
# @param [Array<String>] val Strings to add
|
||||
def add_string_array(_tag, _val)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Add a binary value to the package header
|
||||
# @param [Number] tag Tag
|
||||
# @param [String] val String to add
|
||||
def add_string(_tag, _val)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Add a binary value to the package header
|
||||
# @param [Number] tag Tag
|
||||
# @param [String] val Value
|
||||
def add_binary(_tag, _val)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Deletes a tag of the package header
|
||||
# @param [Number] tag Tag
|
||||
def delete_tag(_tag)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# @return a formated string
|
||||
# @example
|
||||
# pkg.sprintf("%{name}") => "apache2"
|
||||
def sprintf(fmt)
|
||||
error = ::FFI::MemoryPointer.new(:pointer, 1)
|
||||
val = RPM::C.headerFormat(@hdr, fmt, error)
|
||||
raise error.get_pointer(0).read_string if val.null?
|
||||
val.read_string
|
||||
end
|
||||
|
||||
# @return [Number] This package signature
|
||||
def signature
|
||||
sprintf('%{sigmd5}')
|
||||
end
|
||||
|
||||
# @return [Array<RPM::File>] File list for this package
|
||||
def files
|
||||
basenames = self[:basenames]
|
||||
|
||||
return [] if basenames.nil?
|
||||
|
||||
dirnames = self[:dirnames]
|
||||
diridxs = self[:dirindexes]
|
||||
statelist = self[:filestates]
|
||||
flaglist = self[:fileflags]
|
||||
sizelist = self[:filesizes]
|
||||
modelist = self[:filemodes]
|
||||
mtimelist = self[:filemtimes]
|
||||
rdevlist = self[:filerdevs]
|
||||
linklist = self[:filelinktos]
|
||||
md5list = self[:filemd5s]
|
||||
ownerlist = self[:fileusername]
|
||||
grouplist = self[:filegroupname]
|
||||
|
||||
ret = []
|
||||
|
||||
basenames.each_with_index do |_basename, i|
|
||||
file = RPM::File.new("#{dirnames[diridxs[i]]}#{basenames[i]}",
|
||||
md5list[i],
|
||||
linklist[i],
|
||||
sizelist[i],
|
||||
mtimelist[i],
|
||||
ownerlist[i],
|
||||
grouplist[i],
|
||||
rdevlist[i],
|
||||
modelist[i],
|
||||
flaglist.nil? ? RPM::C::FileAttrs[:none] : flaglist[i],
|
||||
statelist.nil? ? RPM::C::FileState[:normal] : statelist[i])
|
||||
ret << file
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
# @return [Array<RPM::Dependency>] Dependencies for +klass+
|
||||
# @example
|
||||
# dependencies(RPM::Provide, :providename, :provideversion, :provideflags)
|
||||
#
|
||||
# @visibility private
|
||||
def dependencies(klass, nametag, versiontag, flagtag)
|
||||
deps = []
|
||||
|
||||
nametd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
||||
versiontd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
||||
flagtd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
||||
|
||||
min = RPM::C::HEADERGET_MINMEM
|
||||
return deps if RPM::C.headerGet(@hdr, nametag, nametd, min) != 1
|
||||
return deps if RPM::C.headerGet(@hdr, versiontag, versiontd, min) != 1
|
||||
return deps if RPM::C.headerGet(@hdr, flagtag, flagtd, min) != 1
|
||||
|
||||
RPM::C.rpmtdInit(nametd)
|
||||
while RPM::C.rpmtdNext(nametd) != -1
|
||||
deps << klass.new(RPM::C.rpmtdGetString(nametd),
|
||||
RPM::Version.new(RPM::C.rpmtdNextString(versiontd)),
|
||||
RPM::C.rpmtdNextUint32(flagtd).read_uint, self)
|
||||
end
|
||||
deps
|
||||
end
|
||||
|
||||
# @return [Array<RPM::Provide>] Provides list for this package
|
||||
def provides
|
||||
dependencies(RPM::Provide, :providename, :provideversion, :provideflags)
|
||||
end
|
||||
|
||||
# @return [Array<RPM::Require>] Requires list for this package
|
||||
def requires
|
||||
dependencies(RPM::Require, :requirename, :requireversion, :requireflags)
|
||||
end
|
||||
|
||||
# @return [Array<RPM::Conflicts>] Conflicts list for this package
|
||||
def conflicts
|
||||
dependencies(RPM::Conflict, :conflictname, :conflictversion, :conflictflags)
|
||||
end
|
||||
|
||||
# @return [Array<RPM::Obsolete>] Obsoletes list for this package
|
||||
def obsoletes
|
||||
dependencies(RPM::Obsolete, :obsoletename, :obsoleteversion, :obsoleteflags)
|
||||
end
|
||||
|
||||
# @return [Array<RPM::Changelog>] changelog of the package as an array
|
||||
def changelog
|
||||
entries = []
|
||||
nametd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
||||
timetd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
||||
texttd = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
||||
|
||||
min = RPM::C::HEADERGET_MINMEM
|
||||
return deps if RPM::C.headerGet(@hdr, :changelogtime, timetd, min) != 1
|
||||
return deps if RPM::C.headerGet(@hdr, :changelogname, nametd, min) != 1
|
||||
return deps if RPM::C.headerGet(@hdr, :changelogtext, texttd, min) != 1
|
||||
|
||||
RPM::C.rpmtdInit(timetd)
|
||||
while RPM::C.rpmtdNext(timetd) != -1
|
||||
entry = RPM::ChangeLog.new
|
||||
entry.time = RPM::C.rpmtdGetUint32(timetd)
|
||||
entry.name = RPM::C.rpmtdNextString(nametd)
|
||||
entry.text = RPM::C.rpmtdNextString(texttd)
|
||||
entries << entry
|
||||
end
|
||||
entries
|
||||
end
|
||||
|
||||
# Access a header entry
|
||||
# @param [Number] tag Tag to return
|
||||
# @return [] Value of the entry
|
||||
# @example
|
||||
# pkg => #<RPM::Package name="xmlgraphics-fop", version=#<RPM::Version v="1.0", r="22.4">>
|
||||
# pkg[:name] => "xmlgraphics-fop"
|
||||
#
|
||||
# or if you have the old ruby-rpm compat loaded
|
||||
#
|
||||
# require 'rpm/compat'
|
||||
# pkg[RPM::TAG_NAME] => "xmlgraphics-fop"
|
||||
#
|
||||
# @return [String, Fixnum, Array<String>, Array<Fixnum>, nil]
|
||||
# The value of the entry
|
||||
def [](tag)
|
||||
val = nil
|
||||
tagc = ::FFI::AutoPointer.new(RPM::C.rpmtdNew, Package.method(:release_td))
|
||||
|
||||
return nil if RPM::C.headerGet(ptr, tag, tagc,
|
||||
RPM::C::HEADERGET_MINMEM) == 0
|
||||
|
||||
type = RPM::C.rpmtdType(tagc)
|
||||
count = RPM::C.rpmtdCount(tagc)
|
||||
ret_type = RPM::C.rpmTagGetReturnType(tag)
|
||||
|
||||
method_name = case type
|
||||
when :int8_type, :char_type, :int16_type, :int32_type, :int64_type then :rpmtdGetNumber
|
||||
when :string_type, :string_array_type, :bin_type then :rpmtdGetString
|
||||
else raise NotImplementedError, "Don't know how to retrieve type '#{type}'"
|
||||
end
|
||||
|
||||
is_array = if count > 1 then true
|
||||
elsif ret_type == :array_return_type then true
|
||||
elsif type == :string_array_type then true
|
||||
else false
|
||||
end
|
||||
|
||||
if is_array
|
||||
ret = []
|
||||
RPM::C.rpmtdInit(tagc)
|
||||
ret << RPM::C.send(method_name, tagc) while RPM::C.rpmtdNext(tagc) != -1
|
||||
return ret
|
||||
end
|
||||
|
||||
RPM::C.send(method_name, tagc)
|
||||
end
|
||||
|
||||
# @return [String] This package name
|
||||
def name
|
||||
self[:name]
|
||||
end
|
||||
|
||||
# @return [String] This package architecture
|
||||
def arch
|
||||
self[:arch]
|
||||
end
|
||||
|
||||
# TODO: signature
|
||||
|
||||
# @return [Version] Version for this package
|
||||
def version
|
||||
Version.new(self[:version], self[:release], self[:epoch])
|
||||
end
|
||||
|
||||
# String representation of the package: "name-version-release-arch"
|
||||
# @return [String]
|
||||
def to_s
|
||||
return '' if name.nil?
|
||||
return name if version.nil?
|
||||
return "#{name}-#{version}" if arch.nil?
|
||||
"#{name}-#{version}-#{arch}"
|
||||
end
|
||||
|
||||
def self.open(filename)
|
||||
Package.new(filename)
|
||||
end
|
||||
|
||||
# @visibility private
|
||||
def self.release(ptr)
|
||||
RPM::C.headerFree(ptr)
|
||||
end
|
||||
|
||||
# @visibility private
|
||||
def self.release_td(ptr)
|
||||
RPM::C.rpmtdFree(ptr)
|
||||
end
|
||||
|
||||
# @visibility private
|
||||
def initialize(what)
|
||||
case what
|
||||
when String then initialize_from_filename(what)
|
||||
else initialize_from_header(what)
|
||||
end
|
||||
end
|
||||
|
||||
# @visibility private
|
||||
def initialize_from_header(hdr = nil)
|
||||
if hdr.nil?
|
||||
@hdr = ::FFI::AutoPointer.new(RPM::C.headerNew, Header.method(:release))
|
||||
elsif hdr.is_a?(::FFI::Pointer)
|
||||
# ref
|
||||
hdr = RPM::C.headerLink(hdr)
|
||||
@hdr = ::FFI::AutoPointer.new(hdr, Package.method(:release))
|
||||
else
|
||||
raise "Can't initialize header with '#{hdr}'"
|
||||
end
|
||||
end
|
||||
|
||||
def initialize_from_filename(filename)
|
||||
# it sucks not using the std File.open here
|
||||
hdr = ::FFI::MemoryPointer.new(:pointer)
|
||||
fd = nil
|
||||
begin
|
||||
fd = RPM::C.Fopen(filename, 'r')
|
||||
raise "#{filename} : #{RPM::C.Fstrerror(fd)}" if RPM::C.Ferror(fd) != 0
|
||||
RPM.transaction do |ts|
|
||||
rc = RPM::C.rpmReadPackageFile(ts.ptr, fd, filename, hdr)
|
||||
end
|
||||
ensure
|
||||
RPM::C.Fclose(fd) unless fd.nil?
|
||||
end
|
||||
initialize_from_header(hdr.get_pointer(0))
|
||||
end
|
||||
|
||||
# @return [RPM::C::Header] header pointer
|
||||
# @visibility private
|
||||
def ptr
|
||||
@hdr
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,65 @@
|
||||
|
||||
module RPM
|
||||
class Problem
|
||||
def self.release(ptr)
|
||||
RPM::C.rpmProblemFree(ptr)
|
||||
end
|
||||
|
||||
# Creates a problem from an existing C pointer, refcounting it
|
||||
# first.
|
||||
# @param [FFI::Pointer] ptr existing C pointer
|
||||
# @return [RPM::Problem] wrapped object
|
||||
def self.from_ptr(ptr)
|
||||
case ptr
|
||||
when FFI::Pointer
|
||||
new(FFI::AutoPointer.new(RPM::C.rpmProblemLink(ptr), Problem.method(:release)))
|
||||
else
|
||||
raise "Can't initialize header with '#{ptr}'"
|
||||
end
|
||||
end
|
||||
|
||||
# Create a problem item.
|
||||
# @param [RPM::ProblemType] type problem type
|
||||
# @param [String] pkg_nver name-version-edition-release of the related package
|
||||
# @param [String] key key of the related package
|
||||
# @param [String] alt_nver name-version-edition-release of the other related package
|
||||
# @param [String] str generic data string from a problem
|
||||
def self.create(type, pkg_nevr, key, alt_nevr, str, number)
|
||||
ptr = ::FFI::AutoPointer.new(RPM::C.rpmProblemCreate(type, pkg_nevr, key, alt_nevr, str, number), Problem.method(:release))
|
||||
new(ptr)
|
||||
end
|
||||
|
||||
# @visibility private
|
||||
def initialize(ptr)
|
||||
@ptr = ptr
|
||||
end
|
||||
|
||||
# @return [RPM::ProblemType] type of problem (dependency, diskpace etc).
|
||||
def type
|
||||
RPM::C.rpmProblemGetType(@ptr)
|
||||
end
|
||||
|
||||
# @return [String] filename or python object address of a problem.
|
||||
def key
|
||||
RPM::C.rpmProblemGetKey(@ptr).read_string
|
||||
end
|
||||
|
||||
# @return [String] a generic data string from a problem.
|
||||
def str
|
||||
RPM::C.rpmProblemGetStr(@ptr)
|
||||
end
|
||||
|
||||
# @return [String] formatted string representation of a problem
|
||||
def to_s
|
||||
RPM::C.rpmProblemString(@ptr)
|
||||
end
|
||||
|
||||
# @return [Fixnum] compare two problems for equality.
|
||||
def <=>(other)
|
||||
RPM::C.rpmProblemCompare(@ptr, other.ptr)
|
||||
end
|
||||
|
||||
# @visibility private
|
||||
attr_reader :ptr
|
||||
end
|
||||
end
|
@ -0,0 +1,270 @@
|
||||
|
||||
module RPM
|
||||
CallbackData = Struct.new(:type, :key, :package, :amount, :total) do
|
||||
def to_s
|
||||
"#{type} #{key} #{package} #{amount} #{total}"
|
||||
end
|
||||
end
|
||||
|
||||
class Transaction
|
||||
def self.release(ptr)
|
||||
RPM::C.rpmtsFree(ptr)
|
||||
end
|
||||
|
||||
def initialize(opts = {})
|
||||
# http://markmail.org/message/ypsiqxop442p7rzz
|
||||
# The key pointer needs to stay valid during commit
|
||||
# so we keep a reference to them mapping from
|
||||
# object_id to ruby object.
|
||||
@keys = {}
|
||||
opts[:root] ||= '/'
|
||||
|
||||
@ptr = ::FFI::AutoPointer.new(RPM::C.rpmtsCreate, Transaction.method(:release))
|
||||
RPM::C.rpmtsSetRootDir(@ptr, opts[:root])
|
||||
end
|
||||
|
||||
# @return [RPM::MatchIterator] Creates an iterator for +tag+ and +val+
|
||||
def init_iterator(tag, val)
|
||||
raise TypeError if val && !val.is_a?(String)
|
||||
|
||||
it_ptr = RPM::C.rpmtsInitIterator(@ptr, tag.nil? ? 0 : tag, val, 0)
|
||||
|
||||
raise "Can't init iterator for [#{tag}] -> '#{val}'" if it_ptr.null?
|
||||
MatchIterator.from_ptr(it_ptr)
|
||||
end
|
||||
|
||||
# @visibility private
|
||||
attr_reader :ptr
|
||||
|
||||
#
|
||||
# @yield [Package] Called for each match
|
||||
# @param [Number] key RPM tag key
|
||||
# @param [String] val Value to match
|
||||
# @example
|
||||
# RPM.transaction do |t|
|
||||
# t.each_match(RPM::TAG_ARCH, "x86_64") do |pkg|
|
||||
# puts pkg.name
|
||||
# end
|
||||
# end
|
||||
#
|
||||
def each_match(key, val, &block)
|
||||
it = init_iterator(key, val)
|
||||
|
||||
return it unless block_given?
|
||||
|
||||
it.each(&block)
|
||||
end
|
||||
|
||||
#
|
||||
# @yield [Package] Called for each package in the database
|
||||
# @example
|
||||
# db.each do |pkg|
|
||||
# puts pkg.name
|
||||
# end
|
||||
#
|
||||
def each(&block)
|
||||
each_match(0, nil, &block)
|
||||
end
|
||||
|
||||
# Add a install operation to the transaction
|
||||
# @param [Package] pkg Package to install
|
||||
# @param [String] key e.g. filename where to install from
|
||||
def install(pkg, key)
|
||||
install_element(pkg, key, upgrade: false)
|
||||
end
|
||||
|
||||
# Add an upgrade operation to the transaction
|
||||
# @param [Package] pkg Package to upgrade
|
||||
# @param [String] key e.g. filename where to install from
|
||||
def upgrade(pkg, key)
|
||||
install_element(pkg, key, upgrade: true)
|
||||
end
|
||||
|
||||
# Add a delete operation to the transaction
|
||||
# @param [String, Package, Dependency] pkg Package to delete
|
||||
def delete(pkg)
|
||||
iterator = case pkg
|
||||
when Package
|
||||
pkg[:sigmd5] ? each_match(:sigmd5, pkg[:sigmd5]) : each_match(:label, pkg[:label])
|
||||
when String
|
||||
each_match(:label, pkg)
|
||||
when Dependency
|
||||
each_match(:label, pkg.name).set_iterator_version(pkg.version)
|
||||
else
|
||||
raise TypeError, 'illegal argument type'
|
||||
end
|
||||
|
||||
iterator.each do |header|
|
||||
ret = RPM::C.rpmtsAddEraseElement(@ptr, header.ptr, iterator.offset)
|
||||
raise "Error while adding erase/#{pkg} to transaction" if ret != 0
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the root directory for this transaction
|
||||
# @param [String] root directory
|
||||
def root_dir=(dir)
|
||||
rc = RPM::C.rpmtsSetRootDir(@ptr, dir)
|
||||
raise "Can't set #{dir} as root directory" if rc < 0
|
||||
end
|
||||
|
||||
# @return [String ] the root directory for this transaction
|
||||
def root_dir
|
||||
RPM::C.rpmtsRootDir(@ptr)
|
||||
end
|
||||
|
||||
def flags=(fl)
|
||||
RPM::C.rpmtsSetFlags(@ptr, fl)
|
||||
end
|
||||
|
||||
def flags
|
||||
RPM::C.rpmtsFlags(@ptr)
|
||||
end
|
||||
|
||||
# Determine package order in the transaction according to dependencies
|
||||
#
|
||||
# The final order ends up as installed packages followed by removed
|
||||
# packages, with packages removed for upgrades immediately following
|
||||
# the new package to be installed.
|
||||
#
|
||||
# @returns [Fixnum] no. of (added) packages that could not be ordered
|
||||
def order
|
||||
RPM::C.rpmtsOrder(@ptr)
|
||||
end
|
||||
|
||||
# Free memory needed only for dependency checks and ordering.
|
||||
def clean
|
||||
RPM::C.rpmtsClean(@ptr)
|
||||
end
|
||||
|
||||
def check
|
||||
rc = RPM::C.rpmtsCheck(@ptr)
|
||||
probs = RPM::C.rpmtsProblems(@ptr)
|
||||
|
||||
return if rc < 0
|
||||
begin
|
||||
psi = RPM::C.rpmpsInitIterator(probs)
|
||||
while RPM::C.rpmpsNextIterator(psi) >= 0
|
||||
problem = Problem.from_ptr(RPM::C.rpmpsGetProblem(psi))
|
||||
yield problem
|
||||
end
|
||||
ensure
|
||||
RPM::C.rpmpsFree(probs)
|
||||
end
|
||||
end
|
||||
|
||||
# Performs the transaction.
|
||||
# @param [Number] flag Transaction flags, default +RPM::TRANS_FLAG_NONE+
|
||||
# @param [Number] filter Transaction filter, default +RPM::PROB_FILTER_NONE+
|
||||
# @example
|
||||
# transaction.commit
|
||||
# You can supply your own callback
|
||||
# @example
|
||||
# transaction.commit do |data|
|
||||
# end
|
||||
# end
|
||||
# @yield [CallbackData] sig Transaction progress
|
||||
def commit
|
||||
flags = RPM::C::TransFlags[:none]
|
||||
|
||||
callback = proc do |hdr, type, amount, total, key_ptr, data_ignored|
|
||||
key_id = key_ptr.address
|
||||
key = @keys.include?(key_id) ? @keys[key_id] : nil
|
||||
|
||||
if block_given?
|
||||
package = hdr.null? ? nil : Package.new(hdr)
|
||||
data = CallbackData.new(type, key, package, amount, total)
|
||||
yield(data)
|
||||
else
|
||||
RPM::C.rpmShowProgress(hdr, type, amount, total, key, data_ignored)
|
||||
end
|
||||
end
|
||||
# We create a callback to pass to the C method and we
|
||||
# call the user supplied callback from there
|
||||
#
|
||||
# The C callback expects you to return a file handle,
|
||||
# We expect from the user to get a File, which we
|
||||
# then convert to a file handle to return.
|
||||
callback = proc do |hdr, type, amount, total, key_ptr, data_ignored|
|
||||
key_id = key_ptr.address
|
||||
key = @keys.include?(key_id) ? @keys[key_id] : nil
|
||||
|
||||
if block_given?
|
||||
package = hdr.null? ? nil : Package.new(hdr)
|
||||
data = CallbackData.new(type, key, package, amount, total)
|
||||
ret = yield(data)
|
||||
|
||||
# For OPEN_FILE we need to do some type conversion
|
||||
# for certain callback types we need to do some
|
||||
case type
|
||||
when :inst_open_file
|
||||
# For :inst_open_file the user callback has to
|
||||
# return the open file
|
||||
unless ret.is_a?(::File)
|
||||
raise TypeError, "illegal return value type #{ret.class}. Expected File."
|
||||
end
|
||||
fdt = RPM::C.fdDup(ret.to_i)
|
||||
if fdt.null? || RPM::C.Ferror(fdt) != 0
|
||||
raise "Can't use opened file #{data.key}: #{RPM::C.Fstrerror(fdt)}"
|
||||
RPM::C.Fclose(fdt) unless fdt.nil?
|
||||
else
|
||||
fdt = RPM::C.fdLink(fdt)
|
||||
@fdt = fdt
|
||||
end
|
||||
# return the (RPM type) file handle
|
||||
fdt
|
||||
when :inst_close_file
|
||||
fdt = @fdt
|
||||
RPM::C.Fclose(fdt)
|
||||
@fdt = nil
|
||||
else
|
||||
ret
|
||||
end
|
||||
else
|
||||
# No custom callback given, use the default to show progress
|
||||
RPM::C.rpmShowProgress(hdr, type, amount, total, key, data_ignored)
|
||||
end
|
||||
end
|
||||
|
||||
rc = RPM::C.rpmtsSetNotifyCallback(@ptr, callback, nil)
|
||||
raise "Can't set commit callback" if rc != 0
|
||||
|
||||
rc = RPM::C.rpmtsRun(@ptr, nil, :none)
|
||||
|
||||
raise "#{self}: #{RPM::C.rpmlogMessage}" if rc < 0
|
||||
|
||||
if rc > 0
|
||||
ps = RPM::C.rpmtsProblems(@ptr)
|
||||
psi = RPM::C.rpmpsInitIterator(ps)
|
||||
while RPM::C.rpmpsNextIterator(psi) >= 0
|
||||
problem = Problem.from_ptr(RPM::C.rpmpsGetProblem(psi))
|
||||
STDERR.puts problem
|
||||
end
|
||||
RPM::C.rpmpsFree(ps)
|
||||
end
|
||||
end
|
||||
|
||||
# @return [DB] the database associated with this transaction
|
||||
def db
|
||||
RPM::DB.new(self)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# @param [Package] pkg package to install
|
||||
# @param [String] key e.g. filename where to install from
|
||||
# @param opts options
|
||||
# @option :upgrade Upgrade packages if true
|
||||
def install_element(pkg, key, opts = {})
|
||||
raise TypeError, 'illegal argument type' unless pkg.is_a?(RPM::Package)
|
||||
raise ArgumentError, "#{self}: key '#{key}' must be unique" if @keys.include?(key.object_id)
|
||||
|
||||
# keep a reference to the key as rpmtsAddInstallElement will keep a copy
|
||||
# of the passed pointer (we pass the object_id)
|
||||
@keys[key.object_id] = key
|
||||
|
||||
ret = RPM::C.rpmtsAddInstallElement(@ptr, pkg.ptr, FFI::Pointer.new(key.object_id), opts[:upgrade] ? 1 : 0, nil)
|
||||
raise RuntimeError if ret != 0
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,7 @@
|
||||
module RPM
|
||||
module Utils
|
||||
def self.check_type(var, type)
|
||||
raise(TypeError, "wrong argument type #{var.class} (expected #{type.class})") unless var.is_a?(type)
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,146 @@
|
||||
|
||||
module RPM
|
||||
class Version
|
||||
include Comparable
|
||||
|
||||
# Parses a "epoch:version-release" string
|
||||
# @return [Array] tuple [epoch, version, release]
|
||||
def self.parse_evr(evr)
|
||||
raise ArgumentError, "version can't be nil" if evr.nil?
|
||||
version = evr
|
||||
epoch = nil
|
||||
release = nil
|
||||
|
||||
idx = version.rindex('-')
|
||||
if idx
|
||||
release = version[idx + 1..-1]
|
||||
version = version[0..idx - 1]
|
||||
end
|
||||
|
||||
idx = version.index(/\D/)
|
||||
if idx && version[idx] == ':'
|
||||
epoch = version[0..idx - 1]
|
||||
version = version[idx + 1..-1]
|
||||
end
|
||||
[epoch ? epoch.to_i : nil, version, release]
|
||||
end
|
||||
|
||||
#
|
||||
# @overload new(vr, e = nil)
|
||||
# Creates a version object from a string representation
|
||||
# @param [String] vr version and release in the form "v-r"
|
||||
# @param [Number] e epoch
|
||||
# @return [Version]
|
||||
# @overload new(v, r, e = nil)
|
||||
# Creates a version object from a string representation
|
||||
# @param [String] v version
|
||||
# @param [String] r release
|
||||
# @param [Number] e epoch
|
||||
# @return [Version]
|
||||
# @example
|
||||
# RPM:: Version.new "1.0.0-3"
|
||||
# RPM:: Version.new "1.04"
|
||||
# RPM:: Version.new "1.0.0-3k", 1
|
||||
# RPM:: Version.new "2.0.3", "5k"
|
||||
#
|
||||
def initialize(*argv)
|
||||
case argv.size
|
||||
when 0
|
||||
raise(ArgumentError('wrong number of arguments (0 for 1..3)'))
|
||||
when 1
|
||||
RPM::Utils.check_type(argv[0], String)
|
||||
@e, @v, @r = RPM::Version.parse_evr(argv[0])
|
||||
when 2
|
||||
# (vr, e)
|
||||
RPM::Utils.check_type(argv[0], String)
|
||||
@e, @v, @r = RPM::Version.parse_evr(argv[0])
|
||||
raise(TypeError, 'illegal argument value') unless e.nil?
|
||||
@e = argv[1].to_i
|
||||
when 3
|
||||
RPM::Utils.check_type(argv[0], String)
|
||||
RPM::Utils.check_type(argv[1], String)
|
||||
@v = argv[0]
|
||||
@r = argv[1]
|
||||
@e = argv[2].to_i
|
||||
else
|
||||
raise(ArgumentError("too many arguments (#{args.size} for 1..3)"))
|
||||
end
|
||||
end
|
||||
|
||||
# @return [String] the version component
|
||||
attr_reader :v
|
||||
|
||||
# @return [String] the release component
|
||||
# or +nil+
|
||||
attr_reader :r
|
||||
|
||||
# @return [String] the epoch component
|
||||
# or +nil+
|
||||
attr_reader :e
|
||||
|
||||
# Comparison between versions
|
||||
# @param [Version] other
|
||||
# @return [Number] -1 if +other+ is greater than, 0 if +other+ is equal to,
|
||||
# and +1 if other is less than version.
|
||||
#
|
||||
# @example
|
||||
# v1 = RPM::Version.new("3.0-0",1)
|
||||
# v2 = RPM::Version.new("3.1-0",1)
|
||||
# v1 <=> v2
|
||||
# => -1
|
||||
#
|
||||
def <=>(other)
|
||||
RPM::Utils.check_type(other, RPM::Version)
|
||||
ret = RPM::C.rpmvercmp(to_vre_epoch_zero, other.to_vre_epoch_zero)
|
||||
end
|
||||
|
||||
# @param [Version] other Version to compare against
|
||||
# @return [Boolean] true if the version is newer than +other+
|
||||
def newer?(other)
|
||||
self > other
|
||||
end
|
||||
|
||||
# @param [Version] other Version to compare against
|
||||
# @return [Boolean] true if the version is older than +other+
|
||||
def older?(other)
|
||||
self < other
|
||||
end
|
||||
|
||||
# String representation in the form "v-r"
|
||||
# @return [String]
|
||||
# @note The epoch is not included
|
||||
def to_vr
|
||||
vr = @r.nil? ? @v.to_s : "#{@v}-#{@r}"
|
||||
end
|
||||
|
||||
# String representation in the form "e:v-r"
|
||||
# @return [String]
|
||||
# @note The epoch is included if present
|
||||
def to_vre(_opts = {})
|
||||
vr = to_vr
|
||||
vre = @e.nil? ? vr : "#{@e}:#{vr}"
|
||||
end
|
||||
|
||||
# Alias for +to_vr+
|
||||
# @see Version#to_vr
|
||||
def to_s
|
||||
to_vr
|
||||
end
|
||||
|
||||
# Hash based on the version content
|
||||
# @return [String]
|
||||
def hash
|
||||
h = @e.nil? ? 0 : @e
|
||||
h = (h << 1) ^ @r.hash
|
||||
h = (h << 1) ^ @v.hash
|
||||
end
|
||||
|
||||
# String representation in the form "e:v-r"
|
||||
# @return [String]
|
||||
# @note The epoch is included always. As 0 if not present
|
||||
def to_vre_epoch_zero
|
||||
vr = to_vr
|
||||
vre = @e.nil? ? "0:#{vr}" : "#{@e}:#{vr}"
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,25 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
||||
require 'rpm/gem_version'
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = 'rpm'
|
||||
s.version = RPM::GEM_VERSION
|
||||
s.authors = ['Duncan Mac-Vicar P.']
|
||||
s.email = ['dmacvicar@suse.de']
|
||||
s.homepage = ''
|
||||
s.summary = 'Ruby bindings for rpm (package manager)'
|
||||
s.description = 'Ruby bindings for rpm. Almost a drop-in replacement for ruby-rpm. Uses FFI.'
|
||||
|
||||
s.rubyforge_project = 'rpm'
|
||||
|
||||
s.files = `git ls-files`.split("\n")
|
||||
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
||||
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
||||
s.require_paths = ['lib']
|
||||
|
||||
# specify any dependencies here; for example:
|
||||
s.add_development_dependency 'rake'
|
||||
s.add_runtime_dependency 'ffi'
|
||||
end
|
@ -0,0 +1,49 @@
|
||||
Name: a
|
||||
Version: 1.0
|
||||
Release: 0
|
||||
License: GPLv2
|
||||
Summary: Minimal package example
|
||||
Url: http://www.a.com
|
||||
Group: Development
|
||||
Source: a-1.0.tar.gz
|
||||
BuildRequires: c d
|
||||
Provides: something
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
|
||||
%description
|
||||
Description
|
||||
|
||||
%package devel
|
||||
Summary: Development part
|
||||
%description devel
|
||||
Development headers
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
%configure
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
%make_install
|
||||
|
||||
%clean
|
||||
%{?buildroot:%__rm -rf "%{buildroot}"}
|
||||
|
||||
%post
|
||||
|
||||
%postun
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc ChangeLog README COPYING
|
||||
%{_datadir}/a/README
|
||||
|
||||
%files devel
|
||||
%{_includedir}/a.h
|
||||
|
||||
|
||||
|
||||
%changelog
|
||||
|
Binary file not shown.
@ -0,0 +1,38 @@
|
||||
Name: simple
|
||||
Version: 1.0
|
||||
Release: 0
|
||||
License: GPL
|
||||
Summary: Simple dummy package
|
||||
Summary(es): Paquete simple de muestra
|
||||
Url: http://www.dummmy.com
|
||||
Group: Development
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
|
||||
%description
|
||||
Dummy package
|
||||
|
||||
%description -l es
|
||||
Paquete de muestra
|
||||
|
||||
%prep
|
||||
|
||||
%build
|
||||
mkdir -p %{buildroot}%{_datadir}/%{name}
|
||||
echo "Hello" > %{buildroot}%{_datadir}/%{name}/README
|
||||
echo "Hola" > %{buildroot}%{_datadir}/%{name}/README.es
|
||||
|
||||
%install
|
||||
|
||||
%clean
|
||||
%{?buildroot:%__rm -rf "%{buildroot}"}
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%{_datadir}/%{name}/README
|
||||
%{_datadir}/%{name}/README.es
|
||||
|
||||
%changelog
|
||||
* Wed Nov 06 2011 Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
||||
- Fix something
|
||||
* Tue Nov 05 2011 Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
||||
- Fix something else
|
Binary file not shown.
@ -0,0 +1,41 @@
|
||||
Name: simple_with_deps
|
||||
Version: 1.0
|
||||
Release: 0
|
||||
License: GPL
|
||||
Summary: Simple dummy package
|
||||
Url: http://www.dummmy.com
|
||||
Group: Development
|
||||
Requires: a
|
||||
Requires: b > 1.0
|
||||
Conflicts: c d
|
||||
Obsoletes: f
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
|
||||
%description
|
||||
Dummy package
|
||||
|
||||
%description -l es
|
||||
Paquete de muestra
|
||||
|
||||
%prep
|
||||
|
||||
%build
|
||||
mkdir -p %{buildroot}%{_datadir}/%{name}
|
||||
echo "Hello" > %{buildroot}%{_datadir}/%{name}/README
|
||||
echo "Hola" > %{buildroot}%{_datadir}/%{name}/README.es
|
||||
|
||||
%install
|
||||
|
||||
%clean
|
||||
%{?buildroot:%__rm -rf "%{buildroot}"}
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%{_datadir}/%{name}/README
|
||||
%{_datadir}/%{name}/README.es
|
||||
|
||||
%changelog
|
||||
* Wed Nov 06 2011 Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
||||
- Fix something
|
||||
* Tue Nov 05 2011 Duncan Mac-Vicar P. <dmacvicar@suse.de>
|
||||
- Fix something else
|
@ -0,0 +1,7 @@
|
||||
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
||||
require 'minitest/autorun'
|
||||
require 'rpm'
|
||||
|
||||
def fixture(name)
|
||||
File.expand_path(File.join(File.dirname(__FILE__), 'data', name))
|
||||
end
|
@ -0,0 +1,28 @@
|
||||
require_relative('helper')
|
||||
require 'rpm/compat'
|
||||
|
||||
class RPMDependencyTests < Minitest::Test
|
||||
EQ = RPM::SENSE_EQUAL
|
||||
LT = RPM::SENSE_LESS
|
||||
GT = RPM::SENSE_GREATER
|
||||
|
||||
def test_satisfy
|
||||
prv = provides('foo', '2', '1', 0, EQ)
|
||||
req = requires('foo', '1', '1', 0, EQ | GT)
|
||||
assert(req.satisfy?(prv))
|
||||
assert(prv.satisfy?(req))
|
||||
|
||||
# Different names don't overlap
|
||||
prv = provides('foo', '2', '1', 0, EQ)
|
||||
req = requires('bar', '1', '1', 0, EQ | GT)
|
||||
assert(!req.satisfy?(prv))
|
||||
end
|
||||
|
||||
def provides(name, v, r, e, sense)
|
||||
RPM::Provide.new(name, RPM::Version.new(v, r, e), sense, nil)
|
||||
end
|
||||
|
||||
def requires(name, v, r, e, sense)
|
||||
RPM::Require.new(name, RPM::Version.new(v, r, e), sense, nil)
|
||||
end
|
||||
end
|
@ -0,0 +1,36 @@
|
||||
require File.join(File.dirname(__FILE__), 'helper')
|
||||
|
||||
class RPMFileTests < Minitest::Test
|
||||
def test_link_to
|
||||
f = RPM::File.new('path', 'md5sum', nil, 42, 1,
|
||||
'owner', 'group', 43, 0o777, 44, 45)
|
||||
assert_equal(nil, f.link_to)
|
||||
f = RPM::File.new('path', 'md5sum', 'link_to', 42, 1,
|
||||
'owner', 'group', 43, 0o777, 44, 45)
|
||||
assert_equal('link_to', f.link_to)
|
||||
end
|
||||
|
||||
def test_flags
|
||||
f = RPM::File.new('path', 'md5sum', nil, 42, 1,
|
||||
'owner', 'group', 43, 0o777, 44, 45)
|
||||
f.config?
|
||||
f.doc?
|
||||
f.is_missingok?
|
||||
f.is_noreplace?
|
||||
f.is_specfile?
|
||||
f.ghost?
|
||||
f.license?
|
||||
f.readme?
|
||||
f.replaced?
|
||||
f.notinstalled?
|
||||
f.netshared?
|
||||
|
||||
assert_raises NotImplementedError do
|
||||
f.exclude?
|
||||
end
|
||||
|
||||
assert_raises NotImplementedError do
|
||||
f.donotuse?
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,33 @@
|
||||
require File.join(File.dirname(__FILE__), 'helper')
|
||||
|
||||
class RPMLibTests < Minitest::Test
|
||||
def test_lib_lib
|
||||
assert_kind_of String, RPM::C.RPMVERSION
|
||||
# "x.y.z"
|
||||
assert(RPM::C.RPMVERSION.size >= 5)
|
||||
assert_kind_of Integer, RPM::C.rpm_version_code
|
||||
# >= 4.0.0
|
||||
assert(RPM::C.rpm_version_code >= ((4 << 16) + (0 << 8) + (0 << 0)))
|
||||
end
|
||||
|
||||
def test_lib_header
|
||||
ptr = RPM::C.headerNew
|
||||
RPM::C.headerFree(ptr)
|
||||
end
|
||||
|
||||
def test_lib_ts
|
||||
ts = RPM::C.rpmtsCreate
|
||||
RPM::C.rpmtsSetRootDir(ts, '/')
|
||||
it = RPM::C.rpmtsInitIterator(ts, 0, nil, 0)
|
||||
hdrs = []
|
||||
until (hdr = RPM::C.rpmdbNextIterator(it)).null?
|
||||
hdrs << hdr
|
||||
assert_kind_of String, RPM::C.headerGetAsString(hdr, :name)
|
||||
end
|
||||
RPM::C.rpmdbFreeIterator(it)
|
||||
end
|
||||
|
||||
def test_lib_macros
|
||||
assert_kind_of String, RPM::C.MACROFILES
|
||||
end
|
||||
end
|
@ -0,0 +1,76 @@
|
||||
require File.join(File.dirname(__FILE__), 'helper')
|
||||
|
||||
class RPMHeaderTests < Minitest::Test
|
||||
def test_create
|
||||
pkg = RPM::Package.create('foo', RPM::Version.new('1.0'))
|
||||
assert_equal 'foo', pkg.name
|
||||
assert_equal '(none)', pkg.signature
|
||||
end
|
||||
|
||||
def test_open
|
||||
pkg = RPM::Package.open(fixture('simple-1.0-0.i586.rpm'))
|
||||
|
||||
req = RPM::Require.new('simple', RPM::Version.new('1.0', '0'), RPM::SENSE_GREATER | RPM::SENSE_EQUAL, nil)
|
||||
assert req.satisfy?(pkg)
|
||||
|
||||
assert_equal 'simple-1.0-0-i586', pkg.to_s
|
||||
|
||||
assert_equal '3b5f9d468c877166532c662e29f43bc3', pkg.signature
|
||||
|
||||
assert_kind_of RPM::Package, pkg
|
||||
assert_equal 'simple', pkg[:name]
|
||||
assert_equal 'i586', pkg[:arch]
|
||||
assert_kind_of RPM::Version, pkg.version
|
||||
assert_equal '1.0-0', pkg.version.to_s
|
||||
|
||||
backup_lang = ENV['LC_ALL']
|
||||
|
||||
ENV['LC_ALL'] = 'C'
|
||||
assert_equal 'Simple dummy package', pkg[:summary]
|
||||
assert_equal 'Dummy package', pkg[:description]
|
||||
|
||||
ENV['LC_ALL'] = 'es_ES.UTF-8'
|
||||
assert_equal 'Paquete simple de muestra', pkg[:summary]
|
||||
assert_equal 'Paquete de muestra', pkg[:description]
|
||||
|
||||
ENV['LC_ALL'] = backup_lang
|
||||
|
||||
# Arrays
|
||||
assert_equal %w[root root], pkg[:fileusername]
|
||||
assert_equal [6, 5], pkg[:filesizes]
|
||||
|
||||
assert pkg.provides.map(&:name).include?('simple(x86-32)')
|
||||
assert pkg.provides.map(&:name).include?('simple')
|
||||
|
||||
assert pkg.files.map(&:path).include?('/usr/share/simple/README')
|
||||
assert pkg.files.map(&:path).include?('/usr/share/simple/README.es')
|
||||
|
||||
assert pkg.conflicts.empty?
|
||||
assert pkg.requires.map(&:name).include?('rpmlib(PayloadIsLzma)')
|
||||
assert pkg.obsoletes.empty?
|
||||
|
||||
file = pkg.files.select { |x| x.path == '/usr/share/simple/README' }.first
|
||||
assert_nil file.link_to
|
||||
assert !file.symlink?
|
||||
|
||||
assert_equal ['- Fix something', '- Fix something else'], pkg.changelog.map(&:text)
|
||||
end
|
||||
|
||||
def test_dependencies
|
||||
pkg = RPM::Package.open(fixture('simple_with_deps-1.0-0.i586.rpm'))
|
||||
assert_equal 'simple_with_deps', pkg.name
|
||||
|
||||
assert pkg.provides.map(&:name).include?('simple_with_deps(x86-32)')
|
||||
assert pkg.provides.map(&:name).include?('simple_with_deps')
|
||||
|
||||
assert pkg.requires.map(&:name).include?('a')
|
||||
b = pkg.requires.find { |x| x.name == 'b' }
|
||||
assert b
|
||||
assert_equal '1.0', b.version.to_s
|
||||
|
||||
assert pkg.conflicts.map(&:name).include?('c')
|
||||
assert pkg.conflicts.map(&:name).include?('d')
|
||||
|
||||
assert pkg.obsoletes.map(&:name).include?('f')
|
||||
end
|
||||
end
|
@ -0,0 +1,18 @@
|
||||
require File.join(File.dirname(__FILE__), 'helper')
|
||||
|
||||
class RPMHeaderTests < Minitest::Test
|
||||
def test_create
|
||||
problem = RPM::Problem.create(:requires, 'foo-1.0-0', 'foo.rpm', 'bar-1.0-0', 'Hello', 1)
|
||||
assert_equal 'foo.rpm', problem.key
|
||||
assert_equal :requires, problem.type
|
||||
assert_equal 'Hello', problem.str
|
||||
assert_equal 'Hello is needed by (installed) bar-1.0-0', problem.to_s
|
||||
|
||||
# Create a RPM::Problem from an existing pointer
|
||||
problem2 = RPM::Problem.new(problem.ptr)
|
||||
assert_equal problem.key, problem2.key
|
||||
assert_equal problem.type, problem2.type
|
||||
assert_equal problem.str, problem2.str
|
||||
assert_equal problem.to_s, problem2.to_s
|
||||
end
|
||||
end
|
@ -0,0 +1,35 @@
|
||||
require File.join(File.dirname(__FILE__), 'helper')
|
||||
|
||||
class RPMRPMTests < Minitest::Test
|
||||
def test_enum
|
||||
assert RPM::TAG[:not_found]
|
||||
end
|
||||
|
||||
def test_compat
|
||||
# puts RPM::LOG_ALERT
|
||||
# assert_raise(NameError) { RPM::LOG_ALERT }
|
||||
|
||||
# require 'rpm/compat'
|
||||
# Nothing should be raised by the following statement
|
||||
RPM::LOG_ALERT
|
||||
assert_equal RPM::LOG_ALERT, RPM::LOG[:alert]
|
||||
end
|
||||
|
||||
def test_iterator
|
||||
RPM.transaction do |t|
|
||||
assert_kind_of RPM::Transaction, t
|
||||
# t.each do |pkg|
|
||||
# puts pkg[:name]
|
||||
# end
|
||||
end
|
||||
end
|
||||
|
||||
def test_macro_read
|
||||
assert_equal '/usr', RPM['_usr']
|
||||
end
|
||||
|
||||
def test_macro_write
|
||||
RPM['hoge'] = 'hoge'
|
||||
assert_equal(RPM['hoge'], 'hoge')
|
||||
end
|
||||
end # class RPM_RPM_Tests < Test::Unit::TestCase
|
@ -0,0 +1,156 @@
|
||||
require_relative('helper')
|
||||
require 'tmpdir'
|
||||
require 'pathname'
|
||||
|
||||
class RPMTransactionTests < Minitest::Test
|
||||
PACKAGE_FILENAME = 'simple-1.0-0.i586.rpm'.freeze
|
||||
|
||||
def test_flags
|
||||
RPM.transaction do |t|
|
||||
assert_equal RPM::TRANS_FLAG_NONE, t.flags
|
||||
t.flags = RPM::TRANS_FLAG_TEST
|
||||
assert_equal RPM::TRANS_FLAG_TEST, t.flags
|
||||
end
|
||||
end
|
||||
|
||||
def test_iterator
|
||||
RPM.transaction do |t|
|
||||
it = t.init_iterator(nil, nil)
|
||||
assert_kind_of RPM::MatchIterator, it
|
||||
# assert it.count > 0
|
||||
end
|
||||
|
||||
RPM.transaction do |t|
|
||||
it = t.init_iterator(nil, nil)
|
||||
it.regexp(:name, :glob, '*audio*')
|
||||
it.each do |pkg|
|
||||
assert pkg.name.include?('audio'), "'#{pkg.name}' contains 'audio'"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# FIXME: this is not working
|
||||
def test_iterator_version
|
||||
RPM.transaction do |t|
|
||||
it = t.init_iterator(nil, nil)
|
||||
it.version(RPM::Version.new('2.1'))
|
||||
it.each do |sig|
|
||||
# FIXME: check that this worked
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_basic_transaction_setters
|
||||
Dir.mktmpdir do |dir|
|
||||
RPM.transaction do |t|
|
||||
assert_equal '/', t.root_dir
|
||||
t.root_dir = dir
|
||||
assert_equal dir + '/', t.root_dir
|
||||
end
|
||||
end
|
||||
|
||||
Dir.mktmpdir do |dir|
|
||||
RPM.transaction(dir) do |t|
|
||||
assert_equal dir + '/', t.root_dir
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_test_flag_install
|
||||
pkg = RPM::Package.open(fixture(PACKAGE_FILENAME))
|
||||
|
||||
Dir.mktmpdir do |dir|
|
||||
RPM.transaction(dir) do |t|
|
||||
t.flags = RPM::TRANS_FLAG_TEST
|
||||
t.install(pkg, fixture(PACKAGE_FILENAME))
|
||||
t.commit
|
||||
|
||||
rpmdb_file = RPM::C.rpmvercmp(RPM::C.RPMVERSION, '4.16.0') >= 0 ? 'rpmdb.sqlite' : 'Packages'
|
||||
|
||||
assert File.exist?(File.join(dir, RPM['_dbpath'], rpmdb_file)), 'rpm db exists'
|
||||
assert !File.exist?('/usr/share/simple/README'), "package #{pkg} was not installed"
|
||||
ensure
|
||||
# Force close so that RPM does not try to do it
|
||||
# when the tmpdir is deleted
|
||||
t.db.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_install_and_remove
|
||||
pkg = RPM::Package.open(fixture(PACKAGE_FILENAME))
|
||||
|
||||
Dir.mktmpdir do |dir|
|
||||
RPM.transaction(dir) do |t|
|
||||
begin
|
||||
t.install(pkg, fixture(PACKAGE_FILENAME))
|
||||
t.commit
|
||||
|
||||
rpmdb_file = RPM::C.rpmvercmp(RPM::C.RPMVERSION, '4.16.0') >= 0 ? 'rpmdb.sqlite' : 'Packages'
|
||||
|
||||
assert File.exist?(File.join(dir, RPM['_dbpath'], rpmdb_file)), 'rpm db exists'
|
||||
assert File.exist?(File.join(dir, '/usr/share/simple/README')), "package #{pkg} should be installed"
|
||||
ensure
|
||||
# Force close so that RPM does not try to do it
|
||||
# when the tmpdir is deleted
|
||||
t.db.close
|
||||
end
|
||||
end
|
||||
|
||||
skip("Commit hangs on package delete")
|
||||
|
||||
RPM.transaction(dir) do |t|
|
||||
begin
|
||||
assert_raises TypeError do
|
||||
t.delete(Object.new)
|
||||
end
|
||||
|
||||
t.delete(pkg)
|
||||
t.order
|
||||
t.clean
|
||||
t.commit
|
||||
|
||||
assert !File.exist?(File.join(dir, '/usr/share/simple/README')), "package #{pkg} should not be installed"
|
||||
ensure
|
||||
# Force close so that RPM does not try to do it
|
||||
# when the tmpdir is deleted
|
||||
t.db.close
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_install_with_custom_callback
|
||||
pkg = RPM::Package.open(fixture(PACKAGE_FILENAME))
|
||||
|
||||
Dir.mktmpdir do |dir|
|
||||
RPM.transaction(dir) do |t|
|
||||
begin
|
||||
t.install(pkg, fixture(PACKAGE_FILENAME))
|
||||
|
||||
t.check do |problem|
|
||||
STDERR.puts "Problem: #{problem}"
|
||||
end
|
||||
|
||||
t.order
|
||||
t.clean
|
||||
|
||||
t.commit do |data|
|
||||
next case data.type
|
||||
when :inst_open_file then
|
||||
@f = File.open(data.key, 'r')
|
||||
when :inst_close_file then @f.close
|
||||
end
|
||||
end
|
||||
|
||||
assert File.exist?(File.join(dir, '/usr/share/simple/README')),
|
||||
"package #{pkg} should be installed"
|
||||
ensure
|
||||
# Force close so that RPM does not try to do it
|
||||
# when the tmpdir is deleted
|
||||
t.db.close
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,64 @@
|
||||
require File.join(File.dirname(__FILE__), 'helper')
|
||||
|
||||
class RPMVersionTests < Minitest::Test
|
||||
def setup
|
||||
@a = RPM::Version.new('1.0.0-0.1m')
|
||||
@b = RPM::Version.new('0.9.0-1m')
|
||||
@c = RPM::Version.new('1.0.0-0.11m')
|
||||
@d = RPM::Version.new('0.9.0-1m', 1)
|
||||
end
|
||||
|
||||
def test_parse_evr
|
||||
assert_equal [23, '1.0.3', '1suse'],
|
||||
RPM::Version.parse_evr('23:1.0.3-1suse')
|
||||
assert_equal [nil, '1.0', nil],
|
||||
RPM::Version.parse_evr('1.0')
|
||||
assert_equal [nil, '2.0', '3'],
|
||||
RPM::Version.parse_evr('2.0-3')
|
||||
end
|
||||
|
||||
def test_version_compare
|
||||
assert(@a > @b)
|
||||
assert(@a < @c)
|
||||
assert(@a < @d)
|
||||
end
|
||||
|
||||
def test_version_newer?
|
||||
assert(@a.newer?(@b))
|
||||
assert(@c.newer?(@a))
|
||||
assert(@d.newer?(@a))
|
||||
assert(!@a.newer?(@a))
|
||||
end
|
||||
|
||||
def test_version_older?
|
||||
assert(@b.older?(@a))
|
||||
assert(@a.older?(@c))
|
||||
assert(@a.older?(@d))
|
||||
assert(!@a.older?(@a))
|
||||
end
|
||||
|
||||
def test_vre
|
||||
assert_equal('0.9.0', @d.v)
|
||||
assert_equal('1m', @d.r)
|
||||
assert_equal(1, @d.e)
|
||||
end
|
||||
|
||||
def test_to_s
|
||||
assert_equal('0.9.0-1m', @b.to_s)
|
||||
assert_equal('0.9.0-1m', @d.to_s)
|
||||
end
|
||||
|
||||
def test_to_vre
|
||||
assert_equal('0.9.0-1m', @b.to_vre)
|
||||
assert_equal('1:0.9.0-1m', @d.to_vre)
|
||||
end
|
||||
|
||||
def test_epoch_none_zero
|
||||
v1 = RPM::Version.new('1-2')
|
||||
v2 = RPM::Version.new('0:1-2')
|
||||
assert_nil v1.e
|
||||
assert_equal(0, v2.e)
|
||||
assert(v1 == v2)
|
||||
assert_equal(v1.hash, v2.hash)
|
||||
end
|
||||
end
|
Loading…
Reference in new issue