Quickly publishing in your Ubuntu PPA

This is more a note pad for myself with quick instructions about how to upload a (usually patched) package to my own PPAs.

Patching an existing package

First thing is downloading the sources of the package from the repository that is providing the buggy binary package installed in my system.

For example, when patching webkitgtk, if my installed package is from a vanilla Ubuntu release, I only have to check that I have the source from the official Ubuntu repositories. However, if my installed package is from another PPA, I will have to check that I have the source from it or, if not, I would have to download the needed packages manually. Let’s assume my installed package is coming from the GNOME3 Team Ubuntu PPA:

$ cd ~/ppa/ && mkdir -p webkitgtk/gnome3 && cd webkitgtk/gnome3
$ apt-get source webkitgtk
Reading package lists... Done
Building dependency tree
Reading state information... Done
NOTICE: 'webkitgtk' packaging is maintained in the 'Git' version control system at:
git://git.debian.org/git/pkg-webkit/webkit.git
Need to get 9,440 kB of source archives.
Get:1 http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu/ saucy/main webkitgtk 2.3.2-1ubuntu6~saucy1 (tar) [9,353 kB]
Get:2 http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu/ saucy/main webkitgtk 2.3.2-1ubuntu6~saucy1 (diff) [82.2 kB]
Get:3 http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu/ saucy/main webkitgtk 2.3.2-1ubuntu6~saucy1 (dsc) [4,577 B]
Fetched 9,440 kB in 3s (2,769 kB/s)
gpgv: Signature made Sun 22 Dec 2013 01:34:25 AM EET using RSA key ID 153ACABA
gpgv: Can't check signature: public key not found
dpkg-source: warning: failed to verify signature on ./webkitgtk_2.3.2-1ubuntu6~saucy1.dsc
dpkg-source: info: extracting webkitgtk in webkitgtk-2.3.2
dpkg-source: info: unpacking webkitgtk_2.3.2.orig.tar.xz
dpkg-source: info: unpacking webkitgtk_2.3.2-1ubuntu6~saucy1.debian.tar.gz
dpkg-source: info: applying 02_notebook_scroll.patch
dpkg-source: info: applying aarch64.patch
dpkg-source: info: applying fix-ppc.diff
dpkg-source: info: applying fix-aarch64.patch
dpkg-source: info: applying remove-use-lockfree-threadsaferefcounted.patch
dpkg-source: info: applying no-jit-build-failure.patch
dpkg-source: info: applying 0001-GTK-Fails-to-build-with-freetype-2.5.1.patch
dpkg-source: info: applying disable-jit-harder.patch
dpkg-source: info: applying fix-llint-c-loop.patch
dpkg-source: info: applying fix-armv7.patch
dpkg-source: info: applying bugzilla_clear_surface.patch
dpkg-source: info: applying ppc64el.patch
$ cd webkitgtk-2.3.2

Just in case, something I like to do is to add the code from the downloaded package to a local git:

$ git init
$ git add *
$ git commit -m "Initial commit"
...

Then, it is time to apply the needed changes to the source code. This is the reason why git comes handy, in case these changes are not trivial and they need actually some more work. When we are done with the changes, we have to add them to the debian package as an additional patch to the original source. We use dpkg-source for this:

$ dpkg-source --commit
dpkg-source: info: local changes detected, the modified files are:
 webkitgtk-2.3.2/Source/WebKit2/GNUmakefile.am
 webkitgtk-2.3.2/Source/WebKit2/GNUmakefile.list.am
 webkitgtk-2.3.2/Source/WebKit2/Shared/Plugins/Netscape/NetscapePluginModule.h
 webkitgtk-2.3.2/Source/WebKit2/Shared/Plugins/Netscape/x11/NetscapePluginModuleX11.cpp
 webkitgtk-2.3.2/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.cpp
 webkitgtk-2.3.2/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.h
 webkitgtk-2.3.2/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp
Enter the desired patch name: 0001-GTK-WK2-Blocks-when-fetching-plugins-information.patch
...

We enter the patch name and the description of the changes:

$ cat debian/patches/0001-GTK-WK2-Blocks-when-fetching-plugins-information.patch
Description: [GTK][WK2] Blocks when fetching plugins information
 https://bugs.webkit.org/show_bug.cgi?id=115650
 .
 Patch by Carlos Garcia Campos.
 Reviewed by Gustavo Noronha Silva.
 .
 Use a persistent cache to store the plugins metadata to avoid
 having to load all the plugins everytime a plugin is used for the
 first time.
 .
 * GNUmakefile.am:
 * GNUmakefile.list.am:
 * Shared/Plugins/Netscape/NetscapePluginModule.h:
 * Shared/Plugins/Netscape/x11/NetscapePluginModuleX11.cpp:
 (WebKit::NetscapePluginModule::parseMIMEDescription): Make this
 method public.
 (WebKit::NetscapePluginModule::buildMIMEDescription): Added this
 helper to build the MIME description string.
 * UIProcess/Plugins/gtk/PluginInfoCache.cpp: Added.
 (WebKit::PluginInfoCache::shared):
 (WebKit::PluginInfoCache::PluginInfoCache):
 (WebKit::PluginInfoCache::~PluginInfoCache):
 (WebKit::PluginInfoCache::saveToFileIdleCallback):
 (WebKit::PluginInfoCache::saveToFile):
 (WebKit::PluginInfoCache::getPluginInfo):
 (WebKit::PluginInfoCache::updatePluginInfo):
 * UIProcess/Plugins/gtk/PluginInfoCache.h: Added.
 * UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp:
 (WebKit::PluginInfoStore::getPluginInfo): Check first if we have
 metadata of the plugin in the cache and update the cache if we
 loaded the plugin to get its metadata.
...

Finally, we modify the release information adding or increasing the non-maintainer digit. For example, in this case the downloaded source version was 2.3.2-1ubuntu6~saucy1, so I’m setting 2.3.2-1ubuntu6~saucy1.1. Also, remember to provide the proper distribution name or to modify it when writing down the log of the changes. In this case, we are using saucy. Check also that you are using the proper email for the log. In my PPAs I use my personal one:

$ DEBEMAIL="my@personal.email" dch -n -D saucy
$ cat debian/changelog
webkitgtk (2.3.2-1ubuntu6~saucy1.1) saucy; urgency=low

  * Fixes #115650:
    - debian/patches/0001-GTK-WK2-Blocks-when-fetching-plugins-information.patch

 -- Andres Gomez   Wed, 19 Mar 2014 14:26:19 +0200
...

With this, we are done modifying the source of the package.

Importing patch alternative

Maybe this is a cleaner and quicker way of patching the downloaded sources. Instead of modifying the sources and running dpkg-source –commit, we can just import an existent patch that would apply on the source code.

To do this, we just have to run:

$ quilt import //my_patch.patch

This will also work in Debian packages for which version dpkg-source –commit won’t work. In addition, is the quickest way to reuse a patch from a package in a previous Ubuntu distribution into a newer one, for example.

From here we will retake the same steps than above to add the release information.

Building the source package

We just have to take into account that, when you have more than one GPG key available, the signature of the package will fail during the process, as in:

$ debuild -S -rfakeroot
...
Finished running lintian.
Now signing changes and any dsc files...
 signfile webkitgtk_2.3.2-1ubuntu6~saucy1.1.dsc Andres Gomez 
gpg: skipped "Andres Gomez ": secret key not available
gpg: /tmp/debsign.vhpVY32w/webkitgtk_2.3.2-1ubuntu6~saucy1.1.dsc: clearsign failed: secret key not available
debsign: gpg error occurred!  Aborting....
debuild: fatal error at line 1280:
running debsign failed

Hence, you have to provide the key id to use in the -k parameter.

In addition, if the sources used for the package are not coming from one of the official Ubuntu repositories you will need to provide also the sources when uploading to the PPA. For this, you have to pass the -sa parameter. For the used example, as we are taking the source from the GNOME3 Team Ubuntu PPA, we will pass this parameter as in:

$ debuild -S -sa -rfakeroot -k3FEA1034

While for other packages which we modify directly from the sources of the official packages provided by Ubuntu, we just use:

$ debuild -S -rfakeroot -k3FEA1034

Optional local build

A local build is not really necessary but it will tell you if your applied changes are breaking or not the compilation of the package.

The best way of doing a trustful local build is using pbuilder.

When using pbuilder we have to be sure that we are using the proper packages not only from Ubuntu’s official repositories but also from the PPAs our target PPA depends on and also our own PPA itself.

I’ve already created the tarballs with the chroot distributions for my own PPAs. However, in order to show an example, we would be using a line like the following one for creating a new tarball for my gnome3 PPA which depends in my ppa PPA and also in GNOME3 Team’s gnome3 PPA:

$ sudo pbuilder --create --distribution saucy --mirror "http://fi.archive.ubuntu.com/ubuntu/" --othermirror "deb http://fi.archive.ubuntu.com/ubuntu/ saucy restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-updates main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-proposed main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-security main restricted universe multiverse|deb http://archive.canonical.com/ubuntu saucy partner|deb http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu trusty main|deb http://ppa.launchpad.net/tanty/ppa/ubuntu saucy main|deb http://ppa.launchpad.net/tanty/gnome3/ubuntu saucy main" --basetgz //saucy-gnome3.tgz --buildplace //build --aptcache  "//aptcache/"

I make use of the <path_to_base_pbuilder> because by default it is all done at /var and I do not always have enough space there.

Once created, and following our example, we would be building our package for the target gnome3 PPA as follows:

$ sudo pbuilder --build --mirror "http://fi.archive.ubuntu.com/ubuntu/" --othermirror "deb http://fi.archive.ubuntu.com/ubuntu/ saucy main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-updates main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-proposed main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-security main restricted universe multiverse|deb http://archive.canonical.com/ubuntu saucy partner|deb http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu trusty main|deb http://ppa.launchpad.net/tanty/ppa/ubuntu saucy main|deb http://ppa.launchpad.net/tanty/gnome3/ubuntu saucy main" --basetgz //saucy-gnome3.tgz --buildplace //build --aptcache  "//aptcache/" ../webkitgtk_2.3.2-1ubuntu6~saucy1.1.dsc

Now, it is just a matter of waiting and checking the results.

Uploading to your PPA

The final step is uploading the package with the new changes to your PPA.

I actually have one sandbox PPA per each stable PPA. These PPAs are not intended for the general users but for being able to play with the changes until I feel they are stable enough to be published in the stable PPAs. Hence, I have 4 PPAs:

  • ppa: Where I keep changes from official Ubuntu packages that are useful to me.
  • ppa-next: Not intended for general users. Where I keep unstable packages with the changes that I will move to the ppa one once I feel they are stable enough.
  • gnome3: Where I keep changes on packages which source has been obtained from the GNOME3 Team PPA.
  • gnome3-next: Not intended for general users. Where I keep unstable packages with the changes that I will move to the gnome3 one once I feel they are stable enough.

With this, during the first cycles of development I will be uploading the changes to my unstable PPAs before uploading them to the stables. For this example, I would be uploading first to the gnome3-next one:

$ dput ppa:tanty/gnome3-next ../webkitgtk_2.3.2-1ubuntu6~saucy1.1_source.changes

Once I’m happy enough I would be uploading the changes to the stable PPA:

$ dput -f ppa:tanty/gnome3 ../webkitgtk_2.3.2-1ubuntu6~saucy1.1_source.changes

The -f flag is avoid the error that is triggered when there is already a “log” file from a previous upload with dput of a certain “.changes” package.

With this, you only have to wait for the package to be built on the PPA bots, upload your repositories and upgrade:

$ sudo apt-get update && sudo apt-get upgrade

Enjoy your newly patched package!

4 thoughts on “Quickly publishing in your Ubuntu PPA

  1. Another alternative is git-buildpackage. Basically it takes your debian sources and creates a repository with everything there. Afterwards, you can do the changes and commit there.

    Great stuff about it is that it creates an ‘upstream’ branch that contains the upstream code, without the debian files. And also it is in charge of creating the patches to put in the debian/patches automatically.

Leave a Reply

Your email address will not be published. Required fields are marked *