[[resolution_rules]]
= Customizing resolution of a dependency directly

[WARNING]
====
This section covers mechanisms Gradle offers to directly influence the behavior of the dependency resolution engine.
In contrast to the other concepts covered in this chapter, like <<dependency_constraints.adoc#dependency-constraints,dependency constraints>> or <<component_metadata_rules.adoc#sec:component_metadata_rules,component metadata rules>>, which are all *inputs* to resolution, the following mechanisms allow you to write rules which are directly injected into the resolution engine.
Because of this, they can be seen as _brute force_ solutions, that may hide future problems (e.g. if new dependencies are added).
Therefore, the general advice is to only use the following mechanisms if other means are not sufficient.
If you are authoring a <<library_vs_application.adoc#sec:understanding-diff-libraries-and-apps,library>>, you should always prefer <<dependency_constraints.adoc#dependency-constraints,dependency constraints>> as they are published for your consumers.
====

[[sec:dependency_resolve_rules]]
== Using dependency resolve rules

A dependency resolve rule is executed for each resolved dependency, and offers a powerful api for manipulating a requested dependency prior to that dependency being resolved.
The feature currently offers the ability to change the group, name and/or version of a requested dependency, allowing a dependency to be substituted with a completely different module during resolution.

Dependency resolve rules provide a very powerful way to control the dependency resolution process, and can be used to implement all sorts of advanced patterns in dependency management.
Some of these patterns are outlined below.
For more information and code samples see the link:{groovyDslPath}/org.gradle.api.artifacts.ResolutionStrategy.html[ResolutionStrategy] class in the API documentation.

[[sec:custom_versioning_scheme]]
=== Implementing a custom versioning scheme

In some corporate environments, the list of module versions that can be declared in Gradle builds is maintained and audited externally.
Dependency resolve rules provide a neat implementation of this pattern:

* In the build script, the developer declares dependencies with the module group and name, but uses a placeholder version, for example: `default`.
* The `default` version is resolved to a specific version via a dependency resolve rule, which looks up the version in a corporate catalog of approved modules.

This rule implementation can be neatly encapsulated in a corporate plugin, and shared across all builds within the organisation.

.Using a custom versioning scheme
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-resolutionStrategy/kotlin",files="build.gradle.kts[tags=custom-versioning-scheme]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-resolutionStrategy/groovy",files="build.gradle[tags=custom-versioning-scheme]"]
====

[[sec:denying_version]]
=== Denying a particular version with a replacement

Dependency resolve rules provide a mechanism for denying a particular version of a dependency and providing a replacement version.
This can be useful if a certain dependency version is broken and should not be used, where a dependency resolve rule causes this version to be replaced with a known good version.
One example of a broken module is one that declares a dependency on a library that cannot be found in any of the public repositories, but there are many other reasons why a particular module version is unwanted and a different version is preferred.

In example below, imagine that version `1.2.1` contains important fixes and should always be used in preference to `1.2`.
The rule provided will enforce just this: any time version `1.2` is encountered it will be replaced with `1.2.1`.
Note that this is different from a forced version as described above, in that any other versions of this module would not be affected.
This means that the 'newest' conflict resolution strategy would still select version `1.3` if this version was also pulled transitively.

.Example: Blacklisting a version with a replacement
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-resolutionStrategy/kotlin",files="build.gradle.kts[tags=denying_version]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-resolutionStrategy/groovy",files="build.gradle[tags=denying_version]"]
====

[NOTE]
====
There's a difference with using the _reject_ directive of <<rich_versions.adoc#rich-version-constraints,rich version constraints>>: rich versions will cause the build to fail if a rejected version is found in the graph, or select a non rejected version when using dynamic dependencies.
Here, we _manipulate the requested versions_ in order to select a different version when we find a rejected one.
In other words, this is a _solution_ to rejected versions, while rich version constraints allow declaring the _intent_ (you should not use this version).
====

[[sec:module_replacement]]
== Using module replacement rules

It is preferable to express module conflicts in terms of <<dependency_capability_conflict.adoc#sub:capabilities, capabilities conflicts>>.
However, if there's no such rule declared or that you are working on versions of Gradle which do not support capabilities, Gradle provides tooling to work around those issues.

Module replacement rules allow a build to declare that a legacy library has been replaced by a new one.
A good example when a new library replaced a legacy one is the `google-collections` -&gt; `guava` migration.
The team that created google-collections decided to change the module name from `com.google.collections:google-collections` into `com.google.guava:guava`.
This is a legal scenario in the industry: teams need to be able to change the names of products they maintain, including the module coordinates. Renaming of the module coordinates has impact on conflict resolution.

To explain the impact on conflict resolution, let's consider the `google-collections` -&gt; `guava` scenario.
It may happen that both libraries are pulled into the same dependency graph.
For example, _our project_ depends on `guava` but some of _our dependencies_ pull in a legacy version of `google-collections`.
This can cause runtime errors, for example during test or application execution.
Gradle does not automatically resolve the `google-collections` -&gt; `guava` conflict because it is not considered as a _version conflict_.
It's because the module coordinates for both libraries are completely different and conflict resolution is activated when `group` and `module` coordinates are the same but there are different versions available in the dependency graph (for more info, refer to the section on conflict resolution).
Traditional remedies to this problem are:

* Declare exclusion rule to avoid pulling in `google-collections` to graph. It is probably the most popular approach.
* Avoid dependencies that pull in legacy libraries.
* Upgrade the dependency version if the new version no longer pulls in a legacy library.
* Downgrade to `google-collections`. It's not recommended, just mentioned for completeness.

Traditional approaches work but they are not general enough.
For example, an organisation wants to resolve the `google-collections` -&gt; `guava` conflict resolution problem in all projects.
It is possible to declare that certain module was replaced by other.
This enables organisations to include the information about module replacement in the corporate plugin suite and resolve the problem holistically for all Gradle-powered projects in the enterprise.

.Declaring a module replacement
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-replacementRule/kotlin",files="build.gradle.kts[tags=module_replacement_declaration]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-replacementRule/groovy",files="build.gradle[tags=module_replacement_declaration]"]
====

For more examples and detailed API, refer to the DSL reference for link:{javadocPath}/org/gradle/api/artifacts/dsl/ComponentMetadataHandler.html[ComponentMetadataHandler].

What happens when we declare that `google-collections` is replaced by `guava`?
Gradle can use this information for conflict resolution. Gradle will consider every version of `guava` newer/better than any version of `google-collections`.
Also, Gradle will ensure that only guava jar is present in the classpath / resolved file list.
Note that if only `google-collections` appears in the dependency graph (e.g. no `guava`) Gradle will not eagerly replace it with `guava`.
Module replacement is an information that Gradle uses for resolving conflicts.
If there is no conflict (e.g. only `google-collections` or only `guava` in the graph) the replacement information is not used.

Currently it is not possible to declare that a given module is replaced by a set of modules.
However, it is possible to declare that multiple modules are replaced by a single module.

[[sec:dependency_substitution_rules]]
== Using dependency substitution rules

Dependency substitution rules work similarly to dependency resolve rules.
In fact, many capabilities of dependency resolve rules can be implemented with dependency substitution rules.
 They allow project and module dependencies to be transparently substituted with specified replacements.
 Unlike dependency resolve rules, dependency substitution rules allow project and module dependencies to be substituted interchangeably.

_Adding a dependency substitution rule to a configuration changes the timing of when that configuration is resolved._
Instead of being resolved on first use, the configuration is instead resolved when the task graph is being constructed.
This can have unexpected consequences if the configuration is being further modified during task execution, or if the configuration relies on modules that are published during execution of another task.

To explain:

* A `Configuration` can be declared as an input to any Task, and that configuration can include project dependencies when it is resolved.
* If a project dependency is an input to a Task (via a configuration), then tasks to build the project artifacts must be added to the task dependencies.
* In order to determine the project dependencies that are inputs to a task, Gradle needs to resolve the `Configuration` inputs.
* Because the Gradle task graph is fixed once task execution has commenced, Gradle needs to perform this resolution prior to executing any tasks.

In the absence of dependency substitution rules, Gradle knows that an external module dependency will never transitively reference a project dependency.
This makes it easy to determine the full set of project dependencies for a configuration through simple graph traversal.
With this functionality, Gradle can no longer make this assumption, and must perform a full resolve in order to determine the project dependencies.

[[sub:module_to_project_substitution]]
=== Substituting an external module dependency with a project dependency

One use case for dependency substitution is to use a locally developed version of a module in place of one that is downloaded from an external repository.
This could be useful for testing a local, patched version of a dependency.

The module to be replaced can be declared with or without a version specified.

.Substituting a module with a project
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-substitutionRule/kotlin",files="build.gradle.kts[tags=module_to_project_substitution]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-substitutionRule/groovy",files="build.gradle[tags=module_to_project_substitution]"]
====

Note that a project that is substituted must be included in the multi-project build (via `settings.gradle`).
Dependency substitution rules take care of replacing the module dependency with the project dependency and wiring up any task dependencies, but do not implicitly include the project in the build.

[[sub:project_to_module_substitution]]
=== Substituting a project dependency with a module replacement

Another way to use substitution rules is to replace a project dependency with a module in a multi-project build.
This can be useful to speed up development with a large multi-project build, by allowing a subset of the project dependencies to be downloaded from a repository rather than being built.

The module to be used as a replacement must be declared with a version specified.

.Substituting a project with a module
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-substitutionRule/kotlin",files="build.gradle.kts[tags=project_to_module_substitution]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-substitutionRule/groovy",files="build.gradle[tags=project_to_module_substitution]"]
====

When a project dependency has been replaced with a module dependency, that project is still included in the overall multi-project build.
However, tasks to build the replaced dependency will not be executed in order to resolve the depending `Configuration`.

[[sub:conditional_dependency_substitution]]
=== Conditionally substituting a dependency

A common use case for dependency substitution is to allow more flexible assembly of sub-projects within a multi-project build.
This can be useful for developing a local, patched version of an external dependency or for building a subset of the modules within a large multi-project build.

The following example uses a dependency substitution rule to replace any module dependency with the group `org.example`, but only if a local project matching the dependency name can be located.

.Conditionally substituting a dependency
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-conditionalSubstitutionRule/kotlin/consumer",files="build.gradle.kts[tags=project_substitution]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-conditionalSubstitutionRule/groovy/consumer",files="build.gradle[tags=project_substitution]"]
====

Note that a project that is substituted must be included in the multi-project build (via `settings.gradle`).
Dependency substitution rules take care of replacing the module dependency with the project dependency, but do not implicitly include the project in the build.

[[sec:variant_aware_substitutions]]
=== Substituting a dependency with another variant

Gradle's dependency management engine is <<variant_model.adoc#understanding-variant-selection,variant-aware>> meaning that for a single component, the engine may select different artifacts and transitive dependencies.

What to select is determined by the attributes of the consumer configuration and the attributes of the variants found on the producer side.
It is, however, possible that some specific dependencies override attributes from the configuration itself.
This is typically the case when using the <<java_platform_plugin.adoc#java_platform_plugin,Java Platform plugin>>: this plugin builds a special kind of component which is called a "platform" and can be addressed by setting the component category attribute to `platform`, in opposition to typical dependencies which are targetting libraries.

Therefore, you may face situations where you want to substitute a platform dependency with a regular dependency, or the other way around.

[[sec:substitution_with_attributes]]
==== Substituting a dependency with attributes

Let's imagine that you want to substitute a platform dependency with a regular dependency.
This means that the library you are consuming declared something like this:

.An incorrect dependency on a platform
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-attributeSubstitutionRule/kotlin",files="lib/build.gradle.kts[tags=dependencies]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-attributeSubstitutionRule/groovy",files="lib/build.gradle[tags=dependencies]"]
====

The `platform` keyword is actually a short-hand notation for a _dependency with attributes_.
If we want to substitute this dependency with a regular dependency, then we need to select precisely the dependencies which have the `platform` attribute.

This can be done by using a substitution rule:

.Substitute a platform dependency with a regular dependency
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-attributeSubstitutionRule/kotlin",files="consumer/build.gradle.kts[tags=substitution_rule]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-attributeSubstitutionRule/groovy",files="consumer/build.gradle[tags=substitution_rule]"]
====

The same rule _without_ the `platform` keyword would try to substitute _regular dependencies_ with a regular dependency, which is not what you want, so it's important to understand that the substitution rules apply on a _dependency specification_: it matches the requested dependency (`substitute XXX`) with a substitute (`using YYY`).

You can have attributes on both the requested dependency _or_ the substitute and the substitution is not limited to `platform`: you can actually specify the whole set of dependency attributes using the `variant` notation.
The following rule is _strictly equivalent_ to the rule above:

.Substitute a platform dependency with a regular dependency using the variant notation
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-attributeSubstitutionRule/kotlin",files="consumer/build.gradle.kts[tags=substitution_rule_alternative]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-attributeSubstitutionRule/groovy",files="consumer/build.gradle[tags=substitution_rule_alternative]"]
====

Please refer to the link:{javadocPath}/org/gradle/api/artifacts/DependencySubstitutions.html#variant-org.gradle.api.artifacts.component.ComponentSelector-org.gradle.api.Action-[Substitution DSL API docs] for a complete reference of the variant substitution API.

[WARNING]
====
In <<composite_builds.adoc#composite_build_intro,composite builds>>, the rule that you have to match the exact requested dependency attributes is not applied: when using composites, Gradle will automatically match the requested attributes.
In other words, it is implicit that if you include another build, you are substituting _all variants_ of the substituted module with an equivalent variant in the included build.
====

[[sec:substitution_with_capabilities]]
==== Substituting a dependency with a dependency with capabilities

Similarly to <<resolution_rules.adoc#sec:substitution_with_attributes,attributes substitution>>, Gradle lets you substitute a dependency with or without capabilities with another dependency with or without capabilities.

For example, let's imagine that you need to substitute a regular dependency with its <<java_testing.adoc#sec:java_test_fixtures,test fixtures>> instead.
You can achieve this by using the following dependency substitution rule:

.Substitute a dependency with its test fixtures
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-capabilitySubstitutionRule/kotlin",files="build.gradle.kts[tags=substitution_rule]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-capabilitySubstitutionRule/groovy",files="build.gradle[tags=substitution_rule]"]
====

Capabilities which are declared in a substitution rule on the requested dependency constitute part of the dependency match specification, and therefore dependencies which do _not_ require the capabilities will not be matched.

Please refer to the link:{javadocPath}/org/gradle/api/artifacts/DependencySubstitutions.html#variant-org.gradle.api.artifacts.component.ComponentSelector-org.gradle.api.Action-[Substitution DSL API docs] for a complete reference of the variant substitution API.

[WARNING]
====
In <<composite_builds.adoc#composite_build_intro,composite builds>>, the rule that you have to match the exact requested dependency capabilities is not applied: when using composites, Gradle will automatically match the requested capabilities. In other words, it is implicit that if you include another build, you are substituting _all variants_ of the substituted module with an equivalent variant in the included build.
====

[[sec:substitution_with_classifier]]
=== Substituting a dependency with a classifier or artifact

While external modules are in general addressed via their group/artifact/version coordinates, it is common that such modules are published with additional artifacts that you may want to use in place of the main artifact.
This is typically the case for _classified_ artifacts, but you may also need to select an artifact with a different file type or extension.
Gradle discourages use of classifiers in dependencies and prefers to model such artifacts as <<variant_model.adoc#understanding-variant-selection,additional variants of a module>>.
There are lots of advantages of using variants instead of classified artifacts, including, but not only, a different set of dependencies for those artifacts.

However, in order to help bridging the two models, Gradle provides means to change or remove a classifier in a substitution rule.

.Dependencies which will lead to a resolution error
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-classifierSubstitutionRule/kotlin",files="consumer/build.gradle.kts[tags=dependencies]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-classifierSubstitutionRule/groovy",files="consumer/build.gradle[tags=dependencies]"]
====

In the example above, the first level dependency on `quasar` makes us think that Gradle would resolve `quasar-core-0.8.0.jar` but it's not the case: the build would fail with this message:

[source]
----
Execution failed for task ':resolve'.
> Could not resolve all files for configuration ':runtimeClasspath'.
   > Could not find quasar-core-0.8.0-jdk8.jar (co.paralleluniverse:quasar-core:0.8.0).
     Searched in the following locations:
         https://repo1.maven.org/maven2/co/paralleluniverse/quasar-core/0.8.0/quasar-core-0.8.0-jdk8.jar
----

That's because there's a dependency on another project, `lib`, which itself depends on a different version of `quasar-core`:

.A "classified" dependency
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-classifierSubstitutionRule/kotlin",files="lib/build.gradle.kts[tags=dependencies]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-classifierSubstitutionRule/groovy",files="lib/build.gradle[tags=dependencies]"]
====

What happens is that Gradle would perform conflict resolution between `quasar-core` 0.8.0 and `quasar-core` 0.7.10.
Because 0.8.0 is higher, we select this version, but the dependency in `lib` has a classifier, `jdk8` and this classifier _doesn't exist anymore_ in release 0.8.0.

To fix this problem, you can ask Gradle to resolve both dependencies _without classifier_:

.A resolution rule to disable selection of a classifier
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-classifierSubstitutionRule/kotlin",files="consumer/build.gradle.kts[tags=substitution_rule]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-classifierSubstitutionRule/groovy",files="consumer/build.gradle[tags=substitution_rule]"]
====

This rule effectively replaces any dependency on `quasar-core` found in the graph with a dependency without classifier.

Alternatively, it's possible to select a dependency _with_ a specific classifier or, for more specific use cases, substitute with a very specific artifact (type, extension and classifier).

For more information, please refer to the following API documentation:

- artifact selection via the link:{javadocPath}/org/gradle/api/artifacts/DependencySubstitutions.Substitution.html[Substitution DSL]
- artifact selection via the link:{javadocPath}/org/gradle/api/artifacts/DependencySubstitution.html#artifactSelection-org.gradle.api.Action-[DependencySubstitution API]
- artifact selection via the link:{javadocPath}/org/gradle/api/artifacts/ResolutionStrategy.html#dependencySubstitution-org.gradle.api.Action-[ResolutionStrategy API]

[[sec:disabling_resolution_transitive_dependencies]]
== Disabling transitive resolution

By default Gradle resolves all transitive dependencies specified by the dependency metadata.
Sometimes this behavior may not be desirable e.g. if the metadata is incorrect or defines a large graph of transitive dependencies.
You can tell Gradle to disable transitive dependency management for a dependency by setting link:{javadocPath}/org/gradle/api/artifacts/ModuleDependency.html#setTransitive-boolean-[ModuleDependency.setTransitive(boolean)] to `false`.
As a result only the main artifact will be resolved for the declared dependency.

.Disabling transitive dependency resolution for a declared dependency
====
include::sample[dir="snippets/dependencyManagement/managingTransitiveDependencies-disableForDependency/kotlin",files="build.gradle.kts[tags=transitive-per-dependency]"]
include::sample[dir="snippets/dependencyManagement/managingTransitiveDependencies-disableForDependency/groovy",files="build.gradle[tags=transitive-per-dependency]"]
====

[NOTE]
====
Disabling transitive dependency resolution will likely require you to declare the necessary runtime dependencies in your build script which otherwise would have been resolved automatically. Not doing so might lead to runtime classpath issues.
====

A project can decide to disable transitive dependency resolution completely.
You either don't want to rely on the metadata published to the consumed repositories or you want to gain full control over the dependencies in your graph.
For more information, see link:{javadocPath}/org/gradle/api/artifacts/Configuration.html#setTransitive-boolean-[Configuration.setTransitive(boolean)].

.Disabling transitive dependency resolution on the configuration-level
====
include::sample[dir="snippets/dependencyManagement/managingTransitiveDependencies-disableForConfiguration/kotlin",files="build.gradle.kts[tags=transitive-per-configuration]"]
include::sample[dir="snippets/dependencyManagement/managingTransitiveDependencies-disableForConfiguration/groovy",files="build.gradle[tags=transitive-per-configuration]"]
====

== Changing configuration dependencies prior to resolution

At times, a plugin may want to modify the dependencies of a configuration before it is resolved.
The `withDependencies` method permits dependencies to be added, removed or modified programmatically.

.Modifying dependencies on a configuration
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-withDependencies/kotlin",files="build.gradle.kts[tags=configuration-with-dependencies]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-withDependencies/groovy",files="build.gradle[tags=configuration-with-dependencies]"]
====

[[sec:configuration_defaults]]
== Setting default configuration dependencies

A configuration can be configured with default dependencies to be used if no dependencies are explicitly set for the configuration.
A primary use case of this functionality is for developing plugins that make use of versioned tools that the user might override.
By specifying default dependencies, the plugin can use a default version of the tool only if the user has not specified a particular version to use.

.Specifying default dependencies on a configuration
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-defaultDependency/kotlin",files="build.gradle.kts[tags=configuration-default-dependencies]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-defaultDependency/groovy",files="build.gradle[tags=configuration-default-dependencies]"]
====

== Excluding a dependency from a configuration completely

Similar to <<dependency_downgrade_and_exclude.adoc#sec:excluding-transitive-deps,excluding a dependency in a dependency declaration>>, you can exclude a transitive dependency for a particular configuration completely by using link:{groovyDslPath}/org.gradle.api.artifacts.Configuration.html#org.gradle.api.artifacts.Configuration:exclude(java.util.Map)[Configuration.exclude(java.util.Map)].
This will automatically exclude the transitive dependency for all dependencies declared on the configuration.

.Excluding transitive dependency for a particular configuration
====
include::sample[dir="snippets/dependencyManagement/managingTransitiveDependencies-excludeForConfiguration/kotlin",files="build.gradle.kts[tags=exclude-transitive-dependencies]"]
include::sample[dir="snippets/dependencyManagement/managingTransitiveDependencies-excludeForConfiguration/groovy",files="build.gradle[tags=exclude-transitive-dependencies]"]
====

== Matching dependencies to repositories

Gradle exposes an API to declare what a repository may or may not contain.
This feature offers a fine grained control on which repository serve which artifacts, which can be one way of controlling the source of dependencies.

Head over to <<declaring_repositories.adoc#sec:repository-content-filtering,the section on repository content filtering>> to know more about this feature.

[[sec:ivy_dynamic_resolve_mode]]
== Enabling Ivy dynamic resolve mode

Gradle's Ivy repository implementations support the equivalent to Ivy's dynamic resolve mode.
Normally, Gradle will use the `rev` attribute for each dependency definition included in an `ivy.xml` file.
In dynamic resolve mode, Gradle will instead prefer the `revConstraint` attribute over the `rev` attribute for a given dependency definition.
If the `revConstraint` attribute is not present, the `rev` attribute is used instead.

To enable dynamic resolve mode, you need to set the appropriate option on the repository definition.
A couple of examples are shown below.
Note that dynamic resolve mode is only available for Gradle's Ivy repositories.
It is not available for Maven repositories, or custom Ivy `DependencyResolver` implementations.

.Enabling dynamic resolve mode
====
include::sample[dir="snippets/dependencyManagement/customizingResolution-ivyDynamicMode/kotlin",files="build.gradle.kts[tags=ivy-repo-dynamic-mode]"]
include::sample[dir="snippets/dependencyManagement/customizingResolution-ivyDynamicMode/groovy",files="build.gradle[tags=ivy-repo-dynamic-mode]"]
====
