Gradle: Use BuildScript RepositoryHandler as Project Repository Handler - gradle

I'm implementing a custom plugin and inside this plugin I am providing a default repository configuration like so:
class MyPlugin implements Plugin<Project> {
...
...
...
#Override
void apply(Project project) {
project.repositories {
mavenLocal()
mavenCentral()
jcenter()
}
...
...
...
}
}
However, in order to be able to apply my plugin inside a build script, the client code will have a add a section like this in their build script anyway:
buildscript {
repositories {
mavenLocal()
maven { url "<organization maven repo url>" }
mavenCentral()
}
dependencies {
classpath 'com.organization.xxx:my-plugin:1.0.130'
}
}
apply plugin: 'com.organization.my-plugin'
Given, that, I'd like to be able to do something like this:
class MyPlugin implements Plugin<Project> {
...
...
...
#Override
void apply(Project project) {
project.repositories = project.buildscript.repositories
...
...
...
}
}
But, when I do that, I get an error, understandably, as the project.repositories property is read-only.
So, is there a proper way I could achieve what I want?

I think the error is because you are trying to assign a value to the property project.repositories. Fortunately, you just need to add repositories, so maybe this will work (untested)
#Override
void apply(Project project) {
project.repositories.addAll(project.buildscript.repositories)
}
By the way, I'm not sure you really want to do this. Better would be to define common repositories somewhere else and then maybe add to both buildscript and project

Related

How to add a custom gradle plugin to Intellij Idea?

I created a simple gradle plugin according to the documentation.
class MyBuild implements Plugin<Project> {
#Override
void apply(Project project) {
project.task("test") {
doLast{
println 'Yeaaa boy!'
}
}
}
}
apply plugin: MyBuild
But the plugin does not appear at the Idea Gradle toolar:
I have also tried to add the following code, but it does not make any diffirence:
idea {
project {
jdkName = '1.8'
languageLevel = '1.8'
}
apply plugin: MyBuild
}
What should I do to make it appear there?
What exactly do you expect to see there? For example, I see the custom task, that the plugin adds here, in Gradle tool window:

Gradle get dependency programatically without configuration

Is there an option to get Maven dependency in Gradle without using custom configuration for it? For example in custom plugin to just obtain dependency provided from extension? Something like
class DependencyPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create("deps", DepsExtension)
project.task('useDependency') {
doLast {
//use Gradle api to resolve dependency without custom configuration
project.resolve(project.deps.dependency)
}
}
}
}
class DepsExtension {
def dependency = 'custom:maven:1.0'
}
Something like this:
Configuration config = project.configurations.create('myPrivateConfig')
Dependency dep = project.dependencies.create('custom:maven:1.0') {
exclude group: 'foo', module: 'bar'
}
config.dependencies.add(dep)
Set<File> files = config.files
I do a similar thing in a gradle plugin here
References
https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/Configuration.html
https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/DependencySet.html
https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/dsl/DependencyHandler.html

How to I preset a repository section in a gradle plugin?

I would like to define a plugin which sets the repositories{...} section in a gradle project to use our approved proxies and repos, and removes the need to define them in every project. How do I do that?
You can do it e.g. in the following way:
apply plugin: 'java'
apply plugin: Lol
dependencies {
compile 'com.google.guava:guava:18.0'
}
task cl(type: Copy) {
from configurations.compile
into 'libs'
}
class Lol implements Plugin<Project> {
void apply(Project p) {
def repositoriesConf = {
mavenCentral()
jcenter()
}
p.repositories(repositoriesConf)
}
}
There're really many different ways of implementing this task. Pay attention to the fact that also java plugin will be needed and maybe the plugin you need to implement should apply java plugin as well.

Do gradle configurations merge or override?

Say I define a plugin, like so:
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.Project
import org.gradle.api.Plugin
class MyRepos implements Plugin<Project> {
static final String NEXUS_URL = 'http://nexus.mine.com/nexus/content/repositories/'
static final List<String> NEXUS_REPOS = [
'central',
'build',
'snapshots',
'release-candidates',
'releases',
]
void apply(Project project) {
project.repositories {
NEXUS_REPOS.each {
maven {
url (NEXUS_URL + it)
}
}
mavenLocal()
}
project.buildscript {
repositories {
maven {
url (NEXUS_URL + 'central')
}
mavenLocal()
}
}
}
}
and in a local build.gradle, I write
apply plugin: MyRepos
buildscript {
dependencies {
...
}
}
My desire is for the two buildscript sections to be merged such that the repositories are defined in the plugin and the dependencies in build.gradle, but it appears that the local declaration overrides the plugin and I end up with an error indicating "no repositories defined".
If I do this via configuration injection from the top level build.gradle, is the result the same?
Maybe the right solution is for the plugin to provide an ext closure to define useMyRepos() similar to the way mavenCentral() is used...
Generally configuration items in gradle are merged so you can apply configurations in different locations. You can, for example, configure some of the dependencies in one build script that will be applied to another build script that will add additional dependencies.
However, your case is a bit different since you're using buildScript configuration which is can be used to define the dependencies for the build script itself rather than the root repositories node which is intended for defining the dependencies of the project you build.
In this case, according to Purpose of buildScript in Gradle as these are different configurations you'll have to define your dependency twice.

How to apply a Gradle plugin from another plugin?

I'm trying to encapsulate android plugin in my own plugin, but when I'm trying to apply my plugin build fails with an exception:
A problem occurred evaluating root project 'myproj'.
> Failed to apply plugin [id 'com.mycomp.build']
> Failed to apply plugin [id 'android-library']
> Plugin with id 'android-library' not found.
Here is how I'm applying android plugin inside my own plugin's implementation:
// build.gradle
apply plugin: 'groovy'
version = '1.0'
group = 'com.mycomp'
dependencies {
compile gradleApi()
compile localGroovy()
}
// Build.groovy
package com.mycomp
import org.gradle.api.Plugin
import org.gradle.api.Project
class Build implements Plugin<Project> {
void apply(Project project) {
println 'Hello from com.mycomp.Build'
project.beforeEvaluate {
buildscript.configurations.classpath +=
'com.android.tools.build:gradle:1.0.0-rc1'
}
project.configure(project) {
buildscript.repositories.mavenCentral()
apply plugin: 'android-library'
}
}
}
For some reason a classpath is not being properly loaded, what am I doing wrong?
I guess that at the time you'd like to add the plugin dependencies for the build script have been already resolved, thus it won't work that way. You need to specify the plugin You'd like to apply as a script dependency itself.
It will work that way:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0-rc1'
}
}
apply plugin: 'groovy'
apply plugin: Build
version = '1.0'
group = 'com.mycomp'
dependencies {
compile gradleApi()
compile localGroovy()
}
import org.gradle.api.Plugin
import org.gradle.api.Project
class Build implements Plugin<Project> {
void apply(Project project) {
project.configure(project) {
apply plugin: 'android-library'
}
}
}
Now, android-plugin is found but it fails because of the fact that groovy plugin had been applied earlier and there's a conflict.
Use the project's PluginManager. For example, the war plugin pulls in the java plugin like this:
public class WarPlugin implements Plugin<Project> {
// ...
public void apply(final Project project) {
project.getPluginManager().apply(org.gradle.api.plugins.JavaPlugin.class);
// ...
}
// ...
}

Resources