Java Ecosystem, Kotlin, Distributed Systems, Sociology of Software Development

Local Copy of an Eclipse P2 Repository

Posted on Feb 9, 2015

Sometimes you want to create a local (offline) copy of a remote Eclipse p2 repository to achieve independence, stability or simply higher speed. This post discusses approaches to achieve this.

How to mirror a p2 Repository?

Using Artifact Repositories

You can set up your own artifact repository, like Nexus. Support for p2 repository can be added via Nexus plugins. You can create proxy repositories serving as a local cache for the remote repository. This speeds up the access to p2 artifacts significantly. However, I recognized that the Nexus proxy repositories somehow have a problem with retrieving artifacts from certain p2 repositories. That’s why I started to look out for alternatives.

Creating a Local Copy Manually

There are three options for mirroring a p2 repository:

  • Using the Ant task p2.mirror
  • Invoke Eclipse’s mirrorApplication operation via the command line
  • Using the Eclipse b3 aggregator.

Ant Task: p2.mirror

You can write a small Ant script. Please notice the following:

  • Always run the Ant task out of Eclipse (Package Explorer View: right-click on the Ant xml. Run as > Ant Build)
  • Run the task in the same JRE as the workspace (External Tools Configurations > Tab JRE. “Run in same JRE as the workspace”). This will give Ant the access to the p2 tasks (like p2.mirror).

Let’s take a look at an example:

<property name="destinationFolder" value="file:/home/username/offline-p2-repo-copies/"/>

<target name="subversive">
  <p2.mirror
    source="http://community.polarion.com/projects/subversive/download/eclipse/4.0/update-site/"
    destination="${destinationFolder}${ant.project.invoked-targets}">
    <slicingOptions followStrict="true" />
      <iu id="org.polarion.eclipse.team.svn.connector.feature.group"/>
      <iu id="org.polarion.eclipse.team.svn.connector.svnkit18.feature.group"/>
  </p2.mirror>
</target>

This task creates a folder with the target name “subversive” within the destinationFolder and copies the requested artifacts (iu=Installable Unit) with their dependencies to this folder. If you omit all <iu> tags the whole repository will be mirrored.

You can also specify a certain version of an artifact. Don’t forget to append the snapshot part in the version string. If you omit the version attribute, the latest version is retrieved.

<target name="xtext-xtend">
  <p2.mirror
    source="http://download.eclipse.org/modeling/tmf/xtext/updates/composite/archive/"
    destination="${destinationFolder}${ant.project.invoked-targets}">
    <slicingOptions followStrict="true" />
      <iu id="org.eclipse.xtext.sdk.feature.group" version="2.5.3.v201402240820"/>
    <iu id="org.eclipse.xtend.sdk.feature.group" version="2.5.3.v201402240820"/>
  </p2.mirror>
</target>

You can also merge several remote repositories into a single offline copy.

<target name="m2e-connectors">
  <p2.mirror>
    <repository location="${destinationFolder}${ant.project.invoked-targets}"/>
    <source>
      <repository location="http://repo1.maven.org/maven2/.m2e/connectors/m2eclipse-buildhelper/0.15.0/N/0.15.0.201405280027/"/>
      <repository location="http://m2e-code-quality.github.com/m2e-code-quality/site/1.0.0/"/><!-- checkstyle & findbugs -->
      <repository location="http://repo1.maven.org/maven2/.m2e/connectors/m2eclipse-subversive/0.13.0/N/0.13.0.201302121311/"/><!-- subversive -->
      <repository location="http://repo1.maven.org/maven2/.m2e/connectors/m2eclipse-mavenarchiver/0.16.0/N/0.16.0.201405271551/"/><!-- mavenarchiver -->
    </source>
    <slicingOptions followStrict="true" />
      <iu id="org.sonatype.m2e.buildhelper.feature.feature.group" version="0.15.0.201405280027"/>
      <iu id="com.basistech.m2e.code.quality.checkstyle.feature.feature.group" version="1.0.0.201408150901"/>
      <iu id="com.basistech.m2e.code.quality.findbugs.feature.feature.group" version="1.0.0.201408150901"/>
      <iu id="org.sonatype.m2e.subversive.feature.feature.group" version="0.13.0.201302121311"/>
      <iu id="org.sonatype.m2e.mavenarchiver.feature.feature.group" version="0.16.0.201405271551"/>
  </p2.mirror>
</target>

This was just a short introduction. There are a lot of further configuration options. Just take a look at the documentation for the p2 Ant tasks on Eclipse.org or in the Eclipse help.

My personal assessment:

  • Advantages:
    • Fine-grained copy (select only certain artifacts or versions)
    • Tooling in Eclipse (Outline View) and comfortable documentation (one Ant target for each remote repository; easy tracking of the origin URL)
    • Merge multiple remote repositories to one local repository (aggregation)
  • Drawbacks:
    • Somehow doesn’t work with certain repositories
    • Slower

Command Line: Eclipse’s mirrorApplication

The second approach is using the Eclipse’s mirrorApplication operation of your Eclipse installation (p2 plugins have to be installed). Here is an example shell script:

#!/bin/bash

source=http://download.eclipse.org/eclipse/updates/4.4
dest=file:///home/username/eclipse-4-4-repository-copy
eclipseLocation=/home/username/eclipse/eclipse

#download the metadata (content.jar)
$eclipseLocation -nosplash -verbose -application org.eclipse.equinox.p2.metadata.repository.mirrorApplication -source $source -destination $dest

#download the artifacts
$eclipseLocation -nosplash -verbose -application org.eclipse.equinox.p2.artifact.repository.mirrorApplication -source $source -destination $dest

For further information, see the documentation on eclipse.org or the blog post of Matthias Zimmermann.

My personal assessment:

  • Advantages:
    • Works stable
    • Quite fast (well the p2 repository mirrors and the p2 protocol are still not fast at all…)
  • Drawbacks:
    • Only full copies possible
    • Less configuration options
    • Less comfortable to document the origin URL for a local copy.

The b3 Aggregator

The Eclipse b3 Aggregator provides is a powerful tool to create aggregated p2 repositories. It provides an Eclipse-based editor to create a configuration file for the repository aggregation (*.b3aggr file).

The b3 Editor to create a *.b3aggr file. This can be used to mirror multiple repositories.

The b3 Editor to create a *.b3aggr file. This can be used to mirror multiple repositories.

You can right-click on any node and select “Clean then Build Aggregation”. This will create the repository. Moreover, you can decide if you want to actually copy/mirror the repositories or to create a composite repository that just links to the other repositories (see the “Mirror Artifacts” property of the “Mapped Repository” nodes). Both can be useful. If you want to learn more, please see the good documentation.

The b3 aggregator looks promising, but I still have to gain more experience with this tool in order to assess it finally. However, here’s my intermediate assessment:

  • Advantages:
    • Nice tooling via Eclipse-based editor
    • Supports aggregation of repositories
    • Supports both mirroring and linking (composite repositories)
    • b3aggr file is a nice documentation to track the origin repository URLs.
  • Drawbacks:
    • Maybe a little bit overkill if you just want to copy a single repository.