Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

yum meta-data is not created correctly for special rpm packages #36

Open
fruetschi opened this issue May 6, 2019 · 4 comments
Open

Comments

@fruetschi
Copy link

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

@ThorAsgardDev
Copy link
Contributor

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.

@ThorAsgardDev
Copy link
Contributor

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.

@ctron
Copy link
Owner

ctron commented Jan 30, 2023

@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.

ThorAsgardDev added a commit to ThorAsgardDev/rpm-builder that referenced this issue Jan 30, 2023
@ThorAsgardDev
Copy link
Contributor

@ctron I tried to create a pull request. I hope that everything is correct. I'm not familiar with git workflow.
#73

ThorAsgardDev added a commit to ThorAsgardDev/rpm-builder that referenced this issue Feb 1, 2023
ctron pushed a commit that referenced this issue Feb 6, 2023
ctron pushed a commit that referenced this issue Feb 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants