## Dependency version convergence

This chapter describes how Galleon picks the version of a dependency to install when multiple versions of that dependency appear on the installation's dependency tree.

IMPORTANT: *The first rule is:* versions specified in the provisioning configuration of the installation, e.g. `provisioning.xml`, for direct or transitive feature-pack dependencies, represent the user's choice and are always installed, even if the dependency hierarchy of the installation includes other versions of those feature-packs.

Suppose we have these feature-packs

.Feature-pack fp1
[source,xml]
----
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <dependencies>
        <dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0"/>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
----

.Feature-pack fp2
[source,xml]
----
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0" >
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
----

Feature-pack `fp1` declares a dependency on version `2.0.0` of `fp2`. Even if later backward compatible versions of `fp2` are available, provisioning a distribution from `fp1` will get `fp2` version `2.0.0` installed. If we still want to upgrade `fp2` there are two ways to do that

1) install the desired version of `fp2` directly as

[source,xml]
----
 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <feature-pack location="fp2@maven(org.jboss.universe:community-universe):2#2.0.1"/>
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>
----

2) use `transitive` element to override the version of `fp2` specified in `feature-pack.xml` of `fp1`

[source,xml]
----
 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <transitive>
         <feature-pack location="fp2@maven(org.jboss.universe:community-universe):2#2.0.1"/>
     </transitive>
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>
----

The advantage of specifying the version in the transitive dependency is that it will override only the version of `fp2` w/o affecting its customizations (if any) applied to `fp2` by `fp1`. While installing the new version directly will install the default configuration of `fp2`.

IMPORTANT: Feature-pack versions that appear higher in the feature-pack dependency hierarchy (i.e. closer to the root in the provisioning configuration) override the versions that appear further down in the dependency hierarchy, no matter whether they are higher or lower in comparison.

### Version convergence of dependency branches

It is possible to run into a version conflict when feature-packs on different dependency branches delcare dependencies on different versions of the same feature-pack. Here is an example

.Feature-pack fp1
[source,xml]
----
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <dependencies>
        <dependency location="fp3@maven(org.jboss.universe:community-universe):1#1.2.0"/>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
----

.Feature-pack fp2
[source,xml]
----
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <dependencies>
        <dependency location="fp3@maven(org.jboss.universe:community-universe):1#1.3.0"/>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
----

.Provisioning configuration
[source,xml]
----
 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
     <feature-pack location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>
----

In this case, Galleon will pick version `1.2.0` of `fp3` simply because it was processed first as the dependency of `fp1`.

IMPORTANT: By default Galleon will pick the first processed feature-pack version even if other feature-packs of the installation depend on a newer compatible version of the feature-pack from the same channel.

IMPORTANT: This behaviour may change in the future in favor of picking the latest compatible version of the feature-pack.

NOTE: In the example above both `fp1` and `fp2` depend on the same channel of `fp3`. If they depended on different channels of `fp3`, the provisioning would fail because different channels represent different compatibilty streams.

The user can also resolve this kind of version conflict by either installing `fp3` directly or specifying its desired version in the `transitive` element of the `installation`. E.g.
[source,xml]
----
 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <transitive>
         <feature-pack location="fp3@maven(org.jboss.universe:community-universe):1#1.4.0"/>
     </transitive>
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
     <feature-pack location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>
----

### Disabling version convergence

There is a provisioning property called `version-convergence` which can be set to `fail` to disable the dependency version convergence that happens when merging dependency branches.

IMPORTANT: Even if `version-convergence` is set to `fail`, feature-pack versions that appear higher in the feature-pack dependency hierarchy (i.e. closer to the root in the provisioning configuration) will still override the versions that appear further down in the dependency hierarchy, no matter whether they are higher or lower in comparison.

