Disclaimer: Authoring p2 metadata is something we expect to support with better tooling in a future release. The support for customizing metadata with a p2.inf file is provisional although we expect to maintain a basic level of compatibility for common tasks.
On occasion the metadata that is automatically generated by p2 for bundles, features and products does not provide everything required to successfully provision an installable unit. For those cases p2 supports the use of an advice file (a p2.inf file) that can be used to augment the metadata for an installable unit. In this release the p2.inf file will allow an author to customize capabilities, properties, and instructions. In addition support is provided for defining additional installable units that are related to the container IU.
The touchpoint advice file is a java properties file and can be placed:Version substitution is a common practice and two special version parameters are supported:
One common use for advice files is to allow more fine grained control of the generation of categories used by the UI to group installable features
Note: Capability advice will "replace" an existing capability of the same type on the IU if the name and namespace match.
There are three different type of capability advice:
provides.{#}.namespace = {namespace} provides.{#}.name = {name} provides.{#}.version = {version} (optional / default: 1.0.0) requires.{#}.namespace = {namespace} requires.{#}.name = {name} requires.{#}.range = {range} (optional / default: 0.0.0)] requires.{#}.matchExp = {p2QL expression} (note that in this case the namespace, name and range attributes are not used) requires.{#}.greedy = {true|false} (optional / default: true) requires.{#}.optional = {true|false} (optional / default: false) requires.{#}.multiple = {true|false} (optional / default: false) requires.{#}.min = {integer} requires.{#}.max = {integer} (when min and max are specified the optional flag is ignored) metaRequirements.{#}.namespace = {namespace} metaRequirements.{#}.name = {name} metaRequirements.{#}.range = {range} (optional / default: 0.0.0) metaRequirements.{#}.matchExp = {p2QL expression} (note that in this case the namespace, name and range attributes are not used) metaRequirements.{#}.greedy = {true|false} (optional / default: true) metaRequirements.{#}.optional = {true|false} (optional / default: false) metaRequirements.{#}.multiple = {true|false} (optional / default: false) metaRequirements.{#}.min = {integer} metaRequirements.{#}.max = {integer} (when min and max are specified the optional flag is ignored)Where {#} is an index for the property, {namespace}, and {name} are the associated named strings, {version} and {range} are version and version range strings respectively.
provides.0.namespace = testNamespace1 provides.0.name = testName1 provides.0.version = 1.2.3.$qualifier$ provides.1.namespace = testNamespace2 provides.1.name = testName2 provides.1.version = $version$ requires.0.namespace = testNamespace1 requires.0.name = testName1 requires.0.range = [1.2.3.$qualifier$, 2) requires.0.greedy = true requires.0.optional = true requires.0.multiple = true requires.1.namespace = testNamespace2 requires.1.name = testName2 requires.1.range = [$version$, $version$] requires.1.greedy = false metaRequirements.0.namespace = testNamespace1 metaRequirements.0.name = testName1 metaRequirements.0.range = [1.2.3, 2) metaRequirements.0.greedy = true metaRequirements.0.optional = true metaRequirements.0.multiple = true metaRequirements.1.namespace = testNamespace2 metaRequirements.1.name = testName2 metaRequirements.1.range = $version$ metaRequirements.1.greedy = false
properties.{#}.name = {propertyName} properties.{#}.value = {propertyValue}
Where {#} is an index for the property, {propertyName}, and {propertyValue} hold the name and value strings for the property.
For example:
properties.0.name = testName1 properties.0.value = testValue1 properties.1.name = testName2 properties.1.value = testValue2
The update descriptor advice allows to override the default update descriptor generated by p2. Typically this is useful if an IU has been renamed and automatic update detection is still desired.
update.id = {id of IU} update.range = {range of the IU being updated} update.matchExp = {a match expression identifying the IU being updated}. (When this is specified the values of id and range are ignored) update.severity = {0|1}
instructions.{phase} = {raw actions} instructions.{phase}.import = {qualified action name} [,{qualified action name}]* (optional)Where {phase} is a p2 installation phase (collect, configure, install, uninstall, unconfigure, etc). Note:
instructions.install = \ ln(targetDir:@artifact,linkTarget:foo/lib.1.so,linkName:lib.so);\ chmod(targetDir:@artifact,targetFile:lib/lib.so,permissions:755); instructions.install.import= \ org.eclipse.equinox.p2.touchpoint.natives.ln,\ org.eclipse.equinox.p2.touchpoint.natives.chmodAdditional information on touchpoint instructions and action syntax can be found here.
In addition to customizing attributes of the containing IU one can also author additional installable units that work with the container IU. Typically this mechanism is used to author an IU fragment that customizes the containing IU or one of its dependencies.
iu.{#}.id = {identifier} iu.{#}.version = {version} (optional)
Where {#} is an index for the installable unit, so multiple installable units can be declared. A full range of IU customizations are supported including:
id version singleton copyright licenses filter touchpoint update artifacts properties provides requires metaRequirements hostRequirements instructions
To illustrate all the various settings for these customizations here's a more complete example of: (unit.0) a minimal IU and (unit.1) a full featured IU:
units.0.id = testid0 units.0.version = 1.2.3 units.1.id = testid1 units.1.version = 1.2.4 units.1.singleton = true units.1.copyright = testCopyright units.1.copyright.location = http://localhost/test units.1.filter = test=testFilter units.1.touchpoint.id = testTouchpointId units.1.touchpoint.version = 1.2.5 units.1.update.id = testid1 units.1.update.range = (1,2) units.1.update.severity = 1 units.1.update.description = some description units.1.artifacts.0.id = testArtifact1 units.1.artifacts.0.version = 1.2.6 units.1.artifacts.0.classifier = testClassifier1 units.1.artifacts.1.id = testArtifact2 units.1.artifacts.1.version = 1.2.7 units.1.artifacts.1.classifier = testClassifier2 units.1.licenses.0 = testLicense units.1.licenses.0.location = http://localhost/license units.1.properties.0.name = testName1 units.1.properties.0.value = testValue1 units.1.properties.1.name = testName2 units.1.properties.1.value = testValue2 units.1.requires.0.namespace = testNamespace1 units.1.requires.0.name = testName1 units.1.requires.0.range = [1.2.3.$qualifier$, 2) units.1.requires.0.greedy = true units.1.requires.0.optional = true units.1.requires.0.multiple = true units.1.requires.1.namespace = testNamespace2 units.1.requires.1.name = testName2 units.1.requires.1.range = $version$ units.1.requires.1.greedy = false units.1.requires.1.optional = false units.1.metaRequirements.0.namespace = testNamespace1 units.1.metaRequirements.0.name = testName1 units.1.metaRequirements.0.range = [1.2.3.$qualifier$, 2) units.1.metaRequirements.0.greedy = true units.1.metaRequirements.0.optional = true units.1.metaRequirements.0.multiple = true units.1.metaRequirements.1.namespace = testNamespace2 units.1.metaRequirements.1.name = testName2 units.1.metaRequirements.1.range = $version$ units.1.metaRequirements.1.greedy = false units.1.metaRequirements.1.optional = false units.1.provides.0.namespace = testNamespace1 units.1.provides.0.name = testName1 units.1.provides.0.version = 1.2.3.$qualifier$ units.1.provides.1.namespace = testNamespace2 units.1.provides.1.name = testName2 units.1.provides.1.version = $version$ units.1.instructions.configure = addProgramArg(programArg:-startup); addProgramArg(programArg:@artifact); units.1.instructions.unconfigure = removeProgramArg(programArg:-startup); removeProgramArg(programArg:@artifact);) units.1.instructions.unconfigure.import = some.removeProgramArg units.1.hostRequirements.0.namespace = testNamespace1 units.1.hostRequirements.0.name = testName1 units.1.hostRequirements.0.range = [1.2.3.$qualifier$, 2) units.1.hostRequirements.0.greedy = true units.1.hostRequirements.0.optional = true units.1.hostRequirements.0.multiple = true
The p2 UI allows for hierarchical organization of installable units based on the concept of "categories" where the children of categories are what's installable. On occasion we might want to take finer grained control of the contents of a category and what it contains. For example we might want to support further categorization of a feature's contents to allow individual plug-ins to be installed instead of the more typical features.
To support this we can tag a feature as a category as follows:
properties.1.name=org.eclipse.equinox.p2.type.category properties.1.value=true
Another possibility is to use "additional IU advice" to create a specialized category IU like this:
units.1.id=my.product.category units.1.version=1.0.0 units.1.provides.1.namespace=org.eclipse.equinox.p2.iu units.1.provides.1.name=my.product.category units.1.provides.1.version=1.0.0 units.1.properties.1.name=org.eclipse.equinox.p2.type.category units.1.properties.1.value=true units.1.properties.2.name=org.eclipse.equinox.p2.name units.1.properties.2.value=My Category Name requires.1.namespace=org.eclipse.equinox.p2.iu requires.1.name=my.product requires.1.range=[1.0.0,1.0.0] requires.1.greedy=true