Composite repositories make it easy to maintain different versions of a software in a single repository. The idea is to have one public p2 repository that delegates to a number of child repositories. Once you have a new build, you can easily add it to the composite repository and remove some obsolete builds. The child repositories can be anywhere, but it’s simple to keep them in subdirectories. Here’s an example:
There are three child repositories build-01 … build-03, each with its own metadata (content.jar and artifacts.jar). The composite repository itself has a compositeContent.jar and a compositeArtifacts.jar. But how do you create those composite repositories? There’s an ant task, but If you want to add child repos manually, ant is not the tool of choice. Therefore I came up with a little shell script comp-repo.sh that does the job. Maybe it’s helpful for you, too.
Here’s how can you use this script to create a composite repository with a single child repo:
$ comp-repo.sh /path/to/repo --name "Foo Updates" add build-01
And now, let’s assume we have a new build build-05, we want to add this one and remove the old builds build-01 and build-02 from the composite repository:
$ comp-repo.sh /path/to/repo add build-05 remove build-01 remove build-02
The script needs an eclipse installation (3.6 or newer), and it reads the location of the eclipse to use from the environment variable ECLIPSE_DIR. To use the script you have to create this variable:
$ export ECLIPSE_DIR=/path/to/your/eclipse
Alternatively, you can also use the parameter
--eclipse to point the script to your eclipse installation directory.
Checking the generated metadata
The composite metadata have a simple xml format, that is zipped to a .jar. You can easily check the contents of the created metadata files by:
$ zless /path/to/repo/compositeContent.jar
The contents should look like this:
<xml version='1.0' encoding='UTF-8'?> <?compositeMetadataRepository version='1.0.0'?> <repository name='Foo Updates' type='org.eclipse.equinox.internal.p2.metadata.repository.CompositeMetadataRepository' version='1'> <properties size='2'> <property name='p2.timestamp' value='1339153450680'/> <property name='p2.compressed' value='true'/> </properties> <children size='2'> <child location='build-01'/> <child location='build-02'/> </children> </repository>
Performance of composite repositories
By default, a client will first try to find a p2.index file in the repository, and then proceed to look for content.jar or content.xml, before it tries compositeContent.jar. To reduce the number of requests and speed up the lookup by the client, you should add a p2.index file with these contents:
version = 1 metadata.repository.factory.order=compositeContent.xml,\! artifact.repository.factory.order=compositeArtifacts.xml,\!
Note that it’s indeed *.xml even though the files are compressed metadata (*.jar).
Even with the p2.index in place, the client has to request the metadata of all child repositories, so adding a lot of children will increase the number of requests a client has to make. Composite repositories delegate to their children, they do not aggregate them. I’m using composite repositories for the RAP update sites and with a small number of child repos, and compared to the real contents, I think this overhead is bearable.
However, if you know a tool that aggregates (merges) p2 metadata, but still provides the option to easily add and remove child repositories, I’d like to hear about it!