We discussed patch management recently on the
Kolab development mailing list and today it was time to upgrade to
php-5.2.5. I had to run a patch update cycle again.
Some time ago
Thomas recommended using
mercurial for the patch management.
And I must admit that this completely changed the way I deal with code patches and it made my life a lot easier.
Let me describe how I currently deal with patches when upstream delivers a new version.
Setup
Some time ago I started the patch management on php by downloading the package ...
> wget ftp://php.net/distributions/php-5.2.4.tar.bz2
... and unpacking it:
> tar xfj php-5.2.4.tar.bz2
Now I turned this version into a
mercurial repository and added all files to version control:
> cd php-5.2.4
> hg init
> hg commit --addremove -m "php-5.2.4"
> cd ..
Since I needed to patch php I derived (
cloned) a second repository from the original one:
> hg clone php-5.2.4 php-PATCHED
In order to add patches to a repository you have to activate the
queue extension within
mercurial:
> cat ~/.hgrc
[ui]
username = Gunnar Wrobel
[extensions]
hgext.mq =
That allows to add patches on top of a version controlled repository. This had to be activated on the
php-PATCHED repository:
> cd php-PATCHED
> hg qinit -c
The
-c option makes the new patch directory that got created by
qinit under
php-PATCHES/.hg/patches a version controlled directory. This is not strictly necessary but I find it convenient to version control the patches, too.
For the Kolab specific patching one patch had to be added to
php-PATCHED:
> hg qnew KOLAB_Annotation.patch
> patch -p1 < ~/Kolab-php.patch
> hg qrefresh -m "Provides get/set ANNOTATIONS support to PHP. [Version: 5.2.4]"
qrefresh compiled the changes in
php-PATCHED into the
KOLAB_Annotation.patch within
php-PATCHES/.hg/patches.
Now I was able to grab the patch from that location and apply it to the modified packages on both the
OpenPKG platform and
Gentoo
Update
The whole setup would be useless if we wouldn't need to upgrade our patches from time to time.
The following describes the cycle that I perform once upstream released a new version.
Fetch the new version:
> wget ftp://php.net/distributions/php-5.2.5.tar.bz2
Now we clone the original version ...
> hg clone php-5.2.4 php-5.2.5
... and replace it with the new one:
> cd php-5.2.5
> hg locate -0 | xargs -0 rm
> cd ..
> tar xfj php-5.2.5.tar.bz2
> cd php-5.2.5
> hg commit --addremove -m "php-5.2.5"
> cd ..
Now the original repository holds the new version and we need to update our patched version to this.
For this we first need to remove all applied patches since we don't know if they apply any longer:
> cd php-PATCHED
> hg qpop -a
qpop -a removes all currently applied patches. They are of course still present in our
php-PATCHED/.hg/patches directory. But they are not applied.
This allows to cleanly update our base php version now:
> hg pull ../php-5.2.5
> hg update
Pulling and updating brings the
php-PATCHED directory to the
php-5.2.5 version.
Now we can push the stack of patches again and fix any that do not cleanly apply:
> hg qpush
In
case our patch fails we need to modify the source until everything is
working fine again. Often the changes will be minimal. After the
updates the patch has to be refreshed:
> hg qrefresh -m "Provides get/set ANNOTATIONS support to PHP. [Version: 5.2.5]"
> hg qci -m "PHP patch for 5.2.5"
The final command runs
hg commit within the
php-PATCHED/.hg/patches directory.
For a single patch the whole procedure might be a little bit too complicated. It is rather clean though.
But the whole story gets really efficient once you have about twenty patches on an application. In that case the
mercurial queue extensions comes in really handy.