Monday, June 15, 2009

Patching Features (Part 2)

In my last post I showed how to create a simple feature patch. However, this patch leaves us in a state where we can no longer upgrade the platform because the patch itself requires a specific version of the feature it is patching.

Making the patch Optional

If we make the inclusion of the patch in our org.example.feature optional, then we no longer block upgrading the platform underneath us.

When a new version of the platform is available, there is a conflict between the version of the p2.user.ui feature required by the patch and the one required by the new platform. By making the patch optional, p2 will not install the patch if there is a conflict.

This is fine if the new version of the platform includes the fix we want. But what if it doesn't? What if we need to have our patch apply to several different versions of the platform?

Relaxing version ranges

Unfortunately, currently the only way to do the following is to edit the metadata by hand. (Paul Webster uses XSLT transforms, I have also raised a bug to allow changing things using the p2.inf file.)

Looking at the metadata for the patch, we see a few interesting sections:

The Patch Scope

The scope section of the patch's metadata specifies which feature(s) the patch applies to:

<requires size='1'>
<required namespace='org.eclipse.equinox.p2.iu'

Here we see the patch applies to a specific version of the org.eclipse.equinox.p2.user.ui feature. By relaxing the version range here we can make the patch apply to other versions of the platform. For example, say we knew our bug was fixed on June 11, but there were several version between June 5th and the 10th that still contained the bug. We could instead use a version range like [1.1.0.v20090605-1440,1.1.0.v20090611) (the upper end of the range is open, it includes everything up to but not including v20090611).

Note that the patch Installable Unit also has normal requirements on the feature it is patching. When widening the scope range, the regular requirements should also be widened to match.

Change From / Change To

The 'changes' section of the patch's metadata specifies which plug-in we are patching, and the version to change it to.
<required namespace='org.eclipse.equinox.p2.iu'
<required namespace='org.eclipse.equinox.p2.iu'

In the above example, we are changing the org.eclipse.equinox.p2.touchpoint.eclipse bundle from any version ("0.0.0") to version 1.0.101.v20090611.
We could imagine changing these ranges in the following ways:
  • Change the "scope" range to "0.0.0" to match any version of the p2.user.ui feature, and then change the "change from" range to [1.0.101, 1.0.101.v20090611). This would result in patching any version of the p2.user.ui feature that includes any 1.0.101 versioned bundle up to v20090611 (which is the version with the proper fix).
  • Change the "change to" range to something like [1.0.101.v20090611, 1.0.102). We know v20090611 contains the fix we want, but the in the future there will be more bug fixes before the maintenance stream is released. By widening the range here, we allow future bug fixes to also be included in our patch.


Sean Flanigan said...

Andrew, thanks for the article, it's good to see some information about feature patches!

For anyone else in the dark (I was), the installable unit metadata for the patch ends up inside content.jar/content.xml when you export the patch for deployment. (This metadata is the <unit> XML which needs tweaking if you want to change the version range.)

Andrew Eisenberg said...

Thanks for the information. I found that your instructions were not entirely correct. See here:

There was a second place where the feature patch range had to be relaxed.