// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[repository-types]]
= Repository Types

Gradle supports various sources for resolving dependencies, accommodating different metadata formats and connectivity methods.
You can resolve dependencies from:

- <<#sec:maven-repo,Maven-compatible artifact repositories>> (e.g., Maven Central)
- <<#sec:ivy-repositories,Ivy-compatible artifact repositories>> (including custom layouts)
- <<#sec:flat-dir-resolver,Local (flat) directories>>

[[sec:maven-repo]]
== Maven repositories

Many organizations host dependencies in Maven repositories.
Gradle can declare Maven repositories by specifying their URL:

====
include::sample[dir="snippets/artifacts/defineRepository/kotlin",files="build.gradle.kts[tags=maven-like-repo]"]
include::sample[dir="snippets/artifacts/defineRepository/groovy",files="build.gradle[tags=maven-like-repo]"]
====

[[sec:custom-maven-repo]]
=== Composite Maven repository

Sometimes, POMs are published in one location, and JARs in another.
You can define such a repository as follows:

====
include::sample[dir="snippets/artifacts/defineRepository/kotlin",files="build.gradle.kts[tags=maven-like-repo-with-jar-repo]"]
include::sample[dir="snippets/artifacts/defineRepository/groovy",files="build.gradle[tags=maven-like-repo-with-jar-repo]"]
====

Gradle will first look for POMs and artifacts at the base URL, and if the artifact is not found, it will check the additional `artifactUrls`.

[[strict_limitation_to_declared_repositories]]
=== Strict limitation for Maven repositories

Maven POM metadata can specify additional repositories, but Gradle ignores them.
Instead, Gradle strictly uses only the repositories declared in the build script.

NOTE: This serves as both a reproducibility safeguard and a security measure.
Without this restriction, an updated dependency version could unexpectedly introduce artifacts from unverified sources into your build.

[[sec:accessing_secured_maven_repositories]]
=== Authenticated Maven repository

You can specify credentials for Maven repositories that require authentication.
See <<supported_repository_protocols.adoc#supported-transport-protocols, Supported Repository Protocols>> for authentication options.

[[sec:maven-local]]
=== Local Maven repository

Gradle can consume dependencies from a local Maven repository, that is repositories on the local file system:

====
include::sample[dir="snippets/plugins/customPlugin/kotlin/java-gradle-plugin",files="build.gradle.kts[tags=local-maven]"]
include::sample[dir="snippets/plugins/customPlugin/groovy/java-gradle-plugin",files="build.gradle[tags=local-maven]"]
====

Gradle can consume dependencies from the link:https://maven.apache.org/guides/introduction/introduction-to-repositories.html[local Maven repository].
This is useful for teams that want to test their setup locally before publishing their plugin.

You should ensure that using the local Maven repository is necessary before adding `mavenLocal()` to your build script:

====
include::sample[dir="snippets/artifacts/defineRepository/kotlin",files="build.gradle.kts[tags=maven-local]"]
include::sample[dir="snippets/artifacts/defineRepository/groovy",files="build.gradle[tags=maven-local]"]
====

NOTE: Gradle manages its own <<dependency_caching.adoc#sec:dependency-cache,cache>> and doesn't need to declare the local Maven repository even if you resolve dependencies from a remote Maven repository.

Gradle uses the same logic as Maven to identify the location of your local Maven cache.
If a `settings.xml` file is defined in the user’s home directory (`~/.m2/settings.xml`), this location takes precedence over `__M2_HOME__/conf`
Otherwise, Gradle defaults to `~/.m2/repository`.

[[sec:case-for-maven-local]]
==== The case against `mavenLocal()`

As a general rule, you should avoid adding `mavenLocal()` as a repository in your Gradle builds.
There are several issues with relying on it:

1. **Not a true repository, just a cache**:
* Maven treats `mavenLocal()` as a cache, not a reliable repository.
* It may contain incomplete modules—for example, missing sources or Javadoc files—leading to issues in Gradle when resolving dependencies.
2. **Trust and security issues**
* Gradle does **not** trust local repositories because artifacts’ origins cannot be verified.
* Dependencies can be easily overwritten, creating risks for *security, correctness, and reproducibility*.
3. **Performance degradation**
* Since metadata and artifacts can change at any time (see item 2), Gradle **disables caching** for local repositories.
* This results in *slower builds*—especially when `mavenLocal()` is declared **before remote repositories**, as Gradle checks it first.

Despite its drawbacks, there are rare cases where `mavenLocal()` can be useful:

1. **Interoperability with Maven**:
* Example: If *Project A (Maven)* and *Project B (Gradle)* share artifacts during development, `mavenLocal()` can act as a temporary bridge.
* Prefer an internal repository instead, but if that’s not feasible, limit `mavenLocal()` to local builds only.
2. **Interoperability with Gradle (Multi-Repo Development)**:
* Example: If you need to validate that *Project A’s changes work with Project B*, `mavenLocal()` might be used.
* Prefer composite builds for better dependency resolution.
* Only use `mavenLocal()` as a last resort.

To mitigate risks, consider restricting `mavenLocal()` to specific dependencies using a repository filter:

[source,groovy]
----
repositories {
    mavenLocal {
        content {
            includeGroup("com.example.myproject") // Only allow this group from mavenLocal
        }
    }
}
----

This ensures that `mavenLocal()` is only used for expected dependencies and avoids unexpected resolution issues.

[[sec:ivy-repositories]]
== Ivy repositories

Many organizations host dependencies in Ivy repositories.

[[sec:defining-an-ivy-repository-with-a-standard-layout]]
=== Standard layout Ivy repository

To declare an Ivy repository with the standard layout, simply specify the URL:

====
include::sample[dir="snippets/artifacts/defineRepository/kotlin",files="build.gradle.kts[tags=ivy-repo]"]
include::sample[dir="snippets/artifacts/defineRepository/groovy",files="build.gradle[tags=ivy-repo]"]
====

[[sec:defining-a-named-layout-for-an-ivy-repository]]
=== Named layout Ivy repository

You can specify that your repository follows the Ivy default layout:

====
include::sample[dir="snippets/artifacts/defineRepository/kotlin",files="build.gradle.kts[tags=ivy-repo-with-maven-layout]"]
include::sample[dir="snippets/artifacts/defineRepository/groovy",files="build.gradle[tags=ivy-repo-with-maven-layout]"]
====

Valid named layout values are `gradle` (default), `maven`, and `ivy`.
Refer to link:{groovyDslPath}/org.gradle.api.artifacts.repositories.IvyArtifactRepository.html#org.gradle.api.artifacts.repositories.IvyArtifactRepository:layout(java.lang.String)[IvyArtifactRepository.layout(java.lang.String)] in the API documentation for more details.

[[sec:defining-custom-pattern-layout-for-an-ivy-repository]]
=== Custom pattern layout Ivy repository

To define an Ivy repository with a non-standard layout, you can set up a pattern layout:

====
include::sample[dir="snippets/artifacts/defineRepository/kotlin",files="build.gradle.kts[tags=ivy-repo-with-pattern-layout]"]
include::sample[dir="snippets/artifacts/defineRepository/groovy",files="build.gradle[tags=ivy-repo-with-pattern-layout]"]
====

For an Ivy repository that fetches Ivy files and artifacts from different locations, define separate patterns:

====
include::sample[dir="snippets/artifacts/defineRepository/kotlin",files="build.gradle.kts[tags=ivy-repo-with-custom-pattern]"]
include::sample[dir="snippets/artifacts/defineRepository/groovy",files="build.gradle[tags=ivy-repo-with-custom-pattern]"]
====

Optionally, you can enable Maven-style layout for the 'organisation' part, with forward slashes replacing dots:

====
include::sample[dir="snippets/artifacts/defineRepository/kotlin",files="build.gradle.kts[tags=ivy-repo-with-m2compatible-layout]"]
include::sample[dir="snippets/artifacts/defineRepository/groovy",files="build.gradle[tags=ivy-repo-with-m2compatible-layout]"]
====

[[sec:accessing-secured-ivy-repositories]]
=== Authenticated Ivy repository

You can specify credentials for Ivy repositories that require authentication.
See <<supported_repository_protocols.adoc#supported-transport-protocols,Supported Repository Protocols>> for authentication options.

[[sec:ivy-local]]
=== Local Ivy repository

Gradle can consume dependencies from a local Ivy repository, that is repositories on the local file system:

====
include::sample[dir="snippets/artifacts/defineRepository/kotlin",files="build.gradle.kts[tags=local-ivy-repo]"]
include::sample[dir="snippets/artifacts/defineRepository/groovy",files="build.gradle[tags=local-ivy-repo]"]
====

[[sec:flat-dir-resolver]]
== Flat directory repository

Some projects store dependencies on a shared drive or within the project’s source code rather than using a binary repository.
To use a flat filesystem directory as a repository, you can configure it like this:

====
include::sample[dir="snippets/artifacts/defineRepository/kotlin",files="build.gradle.kts[tags=flat-dir-multi]"]
include::sample[dir="snippets/artifacts/defineRepository/groovy",files="build.gradle[tags=flat-dir-multi]"]
====

This configuration adds repositories that search specified directories for dependencies.

NOTE: Flat directory repositories are discouraged, as they do not support metadata formats like Ivy XML or Maven POM files.

In general, binary dependencies should be sourced from an external repository, but if storing dependencies externally is not an option, prefer declaring a Maven or Ivy repository using a local file URL instead.

When resolving dependencies from a flat dir repo, Gradle dynamically generates adhoc dependency metadata based on the presence of artifacts.
Gradle prefers modules with real metadata over those generated by flat directory repositories.
For this reason, flat directories cannot override artifacts with real metadata from other declared repositories.

For instance, if Gradle finds `jmxri-1.2.1.jar` in a flat directory and `jmxri-1.2.1.pom` in another repository, it will use the metadata from the latter.
