rpm-builder
rpm-builder copied to clipboard
yum meta-data is not created correctly for special rpm packages
The yum metadata created by the plugin does not contain the right data in some cases. When a package declares itself to require some file that itself provides (see real-world example below), then yum is unable to install this package from a repo that has been created with this maven plugin.
For example, the package ruby defines to require /usr/bin/ruby:
# list rpm requirements of ruby
$ rpm -qpR ruby-2.0.0.648-34.el7_6.x86_64.rpm
/usr/bin/ruby
libc.so.6()(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libcrypt.so.1()(64bit)
libdl.so.2()(64bit)
libm.so.6()(64bit)
libpthread.so.0()(64bit)
librt.so.1()(64bit)
libruby.so.2.0()(64bit)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rtld(GNU_HASH)
ruby(rubygems) >= 2.0.14.1
ruby-libs(x86-64) = 2.0.0.648-34.el7_6
rubygem(bigdecimal) >= 1.2.0
rpmlib(PayloadIsXz) <= 5.2-1
However, itself provides /usr/bin/ruby:
# list files provided by this rpm
$ rpm -qpl ruby-2.0.0.648-34.el7_6.x86_64.rpm
/usr/bin/erb
/usr/bin/ruby
/usr/bin/testrb
/usr/share/doc/ruby-2.0.0.648
/usr/share/doc/ruby-2.0.0.648/COPYING
/usr/share/doc/ruby-2.0.0.648/COPYING.ja
/usr/share/doc/ruby-2.0.0.648/GPL
/usr/share/doc/ruby-2.0.0.648/LEGAL
/usr/share/man/man1/erb.1.gz
/usr/share/man/man1/ruby.1.gz
The resulting XML metadata generated by the maven plugin reflects it exactly like this:
<package type="rpm">
<name>ruby</name>
<arch>x86_64</arch>
<version epoch="0" rel="34.el7_6" ver="2.0.0.648"/>
...
<rpm:provides>
<rpm:entry epoch="0" flags="EQ" name="ruby" rel="34.el7_6" ver="2.0.0.648"/>
<rpm:entry epoch="0" flags="EQ" name="ruby(runtime_executable)" ver="2.0.0"/>
<rpm:entry epoch="0" flags="EQ" name="ruby(x86-64)" rel="34.el7_6" ver="2.0.0.648"/>
</rpm:provides>
<rpm:requires>
<rpm:entry name="/usr/bin/ruby"/>
<rpm:entry name="libc.so.6()(64bit)"/>
<rpm:entry name="libc.so.6(GLIBC_2.2.5)(64bit)"/>
<rpm:entry name="libcrypt.so.1()(64bit)"/>
<rpm:entry name="libdl.so.2()(64bit)"/>
<rpm:entry name="libm.so.6()(64bit)"/>
<rpm:entry name="libpthread.so.0()(64bit)"/>
<rpm:entry name="librt.so.1()(64bit)"/>
<rpm:entry name="libruby.so.2.0()(64bit)"/>
<rpm:entry name="rtld(GNU_HASH)"/>
<rpm:entry epoch="0" flags="GE" name="ruby(rubygems)" ver="2.0.14.1"/>
<rpm:entry epoch="0" flags="EQ" name="ruby-libs(x86-64)" rel="34.el7_6" ver="2.0.0.648"/>
<rpm:entry epoch="0" flags="GE" name="rubygem(bigdecimal)" ver="1.2.0"/>
</rpm:requires>
<rpm:conflicts/>
<rpm:obsoletes/>
</format>
<file>/usr/bin/erb</file>
<file>/usr/bin/ruby</file>
<file>/usr/bin/testrb</file>
</package>
When trying to install ruby, it fails because it says that it cannot resolve the dependency to /usr/bin/ruby.
When generating the repo-metadata with 'createrepo', the meta-data looks like the following:
<package type="rpm">
<name>ruby</name>
<arch>x86_64</arch>
<version epoch="0" ver="2.0.0.648" rel="34.el7_6"/>
...
<rpm:provides>
<rpm:entry name="ruby" flags="EQ" epoch="0" ver="2.0.0.648" rel="34.el7_6"/>
<rpm:entry name="ruby(runtime_executable)" flags="EQ" epoch="0" ver="2.0.0"/>
<rpm:entry name="ruby(x86-64)" flags="EQ" epoch="0" ver="2.0.0.648" rel="34.el7_6"/>
</rpm:provides>
<rpm:requires>
<rpm:entry name="libc.so.6(GLIBC_2.2.5)(64bit)"/>
<rpm:entry name="libcrypt.so.1()(64bit)"/>
<rpm:entry name="libdl.so.2()(64bit)"/>
<rpm:entry name="libm.so.6()(64bit)"/>
<rpm:entry name="libpthread.so.0()(64bit)"/>
<rpm:entry name="librt.so.1()(64bit)"/>
<rpm:entry name="libruby.so.2.0()(64bit)"/>
<rpm:entry name="rtld(GNU_HASH)"/>
<rpm:entry name="ruby(rubygems)" flags="GE" epoch="0" ver="2.0.14.1"/>
<rpm:entry name="ruby-libs(x86-64)" flags="EQ" epoch="0" ver="2.0.0.648" rel="34.el7_6"/>
<rpm:entry name="rubygem(bigdecimal)" flags="GE" epoch="0" ver="1.2.0"/>
</rpm:requires>
<file>/usr/bin/erb</file>
<file>/usr/bin/ruby</file>
<file>/usr/bin/testrb</file>
</format>
</package>
As it can be seen, the "requires" entry for /usr/bin/ruby is removed automatically by createrepo.
This special-case is handled in createrepo (actually in a class of yum) here: https://github.com/rpm-software-management/yum/blob/master/yum/packages.py#L1294
Hello, Any news about this issue ? I'm facing the same problem. I have to create a yum repo from an Ubuntu and, unfortunately, one rpm in this repo declares itself to require some files that itself provides.
There is a workaround. In the YumMojo.java file, in the addSinglePackage method, before the context.addPackage call, add this code block:
try (RpmInputStream ris = new RpmInputStream(Files.newInputStream(path))) {
ris.getPayloadHeader();
ris.getSignatureHeader();
final CpioArchiveInputStream cpio = ris.getCpioStream();
CpioArchiveEntry cpioEntry;
while ((cpioEntry = cpio.getNextCPIOEntry()) != null) {
providedFiles.add(RpmInformations.normalize(cpioEntry.getName()));
}
cpio.close();
}
List<org.eclipse.packager.rpm.info.RpmInformation.Dependency> requiresToKeep = new java.util.ArrayList<>();
for (org.eclipse.packager.rpm.info.RpmInformation.Dependency requiredDep : rpmInformation.getRequires()) {
boolean fileProvided = false;
for (String providedFile : providedFiles) {
if (requiredDep.getName().equals(providedFile)) {
fileProvided = true;
break;
}
}
if (!fileProvided) {
for (org.eclipse.packager.rpm.info.RpmInformation.Dependency providedDep : rpmInformation.getProvides()) {
if (requiredDep.getName().equals(providedDep.getName())) {
fileProvided = true;
break;
}
}
}
if (!fileProvided) {
requiresToKeep.add(requiredDep);
}
}
rpmInformation.setRequires(requiresToKeep);
It works but it is not very optimal. The correct way would be to update the eclipse packager library to return the correct file list (including symlink), and use this file list to check if the file is provided by the package or not.
@ThorAsgardDev thanks for digging into this! Would you be able to come up with a PR? I would be happy to help you get this merged, but I don't have the bandwidth to work on this myself.
@ctron I tried to create a pull request. I hope that everything is correct. I'm not familiar with git workflow. https://github.com/ctron/rpm-builder/pull/73