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="firstname.lastname@example.org" 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 /
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!
$ sudo apt-get update && sudo apt-get upgrade
$ p-update && p-upgrade
Nice! I will give it a try 🙂
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.
Cool! I will take a look to it 🙂