reprepro: How to add the same package for multiple distributions

reprepro doesn’t like package clones

If you use reprepro for managing your Debian package repository you might have found out that this tool has some limits. One of them is that the same Debian package can only be added once to the whole repository. This mainly has two reasons:

  • All files are stored within the package pool, so packages with similar names tend to be stored in the same directories (some fictional path example: pool/custom/a/awesome_package_1.0_all.deb)
  • reprepro will have a look at the package version – if the combination of package name and version are already present somewhere in the repository, reprepro will refuse to let you add another copy, even when it shall be managed within another configured distribution

So when a package is already present and you try to add it to another distribution, reprepro will throw an error message similar to this one:


reprepro -b /opt/repo  includedeb somecooldistri awesome_package_1.0_all.deb

Already existing files can only be included again, if they are the same, but:

[..]

So – why would someone need the same package added again if it’s already present?

Well, one example could be that you obtained a package source from some external repository and want to build it against different Debian versions (e.g. Debian 7 and Debian 8). You would then add the package into some distribution which might be called custom-wheezy and custom-jessie. The package would differ, of course (e.g. different dependencies), but from reprepro’s perspective they would be the same.

 

So – how to add them multiple times?

In my cases, I already added several Debian packages to the distribution called example1 and I already had the equivalent packages ready for a distribution called example2.

I had several possibilities, including (but not limited to):

  • Rebuild the package with a different name and version (this was not possible for me)
  • Extract/edit the package with some packaging helpers (e.g. fpm or deb-edit), change the version and re-build it (which might overwrite some file permissions which is something you really don’t want to have)
  • Find a third solution which won’t change anything EXCEPT the version of the package

After a couple of minutes of Googling and playing around I realized that Debian packages are only some sort of archive files – so why not exctract the Debian/control file, edit it and put it back? This would change only one small part and now the whole package; in addition, you won’t have to re-build it.

 

Let’s do this!

You need to both rename the package files and change their versions.

Step one – the renaming part – can be achieved with the Linux command line tool “rename”. In my case, I wanted to change the version from “dotdeb” to “dotdeb_jessie”, hence the files should be renamed in a similar manner:


rename "s/dotdeb/dotdeb_jessie/g" *

In the next step (the “changing the version” part) could be done manually for all packages, but this would cost too much time. Instead I wrote a small script which can be used later:


cat fix_version
#!/bin/bash
# Written by Valentin Hoebel <valentin@xenuser.org>
mkdir tmp
cd tmp
ar p ../$1 control.tar.gz |tar -xz # Extracts the control file
sed -i 's/dotdeb/dotdeb_jessie/g' control # Changes the version
tar czf control.tar.gz *[!z] # Create a .tar.gz archive for the control file again
ar r ../$1 control.tar.gz # Put it back into the Debian package
cd ..
rm tmp -rf

In the next step we would loop over the packages and apply the script to them:

</span>

for i in $(ls *.deb); do ./fix_version $i; done

Depending on the amount of packages to be changed, this will take less or more than a few seconds. In my case, 20 packages were changed within 2-3 seconds.

 

Congratulations! You should now be able to include those packages to your reprepro distribution and only had to invest 3 minutes of your valuable time. Feel free to post a comment if you have any feedback or even know a better way of doing this!