Skip to content

Commit 657c9e6

Browse files
committed
Don't use StartParameter in enhanced plugin
StartParameter isn't documented API and thus it's possible that Gradle could change it in ways that could break plugins. Best not to use it and assume what we do know (projects using `ProjectLayout`, settings using `BuildLayout`, `Gradle#getGradleUserHomeDir`)
1 parent 0a2fc1d commit 657c9e6

File tree

7 files changed

+88
-16
lines changed

7 files changed

+88
-16
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ helps us standardize our buildscripts.
1616
| 2.4.0 - 2.4.9 | 17 | 8.6 |
1717
| 2.4.10 - 2.5.x | 17 | 8.1* |
1818
| 2.6.x | 17 | 7.3 |
19+
| 3.x | 17 | 9.0.0 |
1920

2021
\*Compatibility was not tested for this version, but this is the lowest recommended version as it was built
2122
against it.

gradleutils-shared/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# GradleUtils Shared
2+
3+
GradleUtils Shared is a shared plugin base used by all of Forge's Gradle
4+
plugins. This is meant to be a tool internal to Forge, but any one case use it
5+
if they want.
6+
7+
> [!NOTE]
8+
> The version number is intentionally shared with base GradleUtils. However, it
9+
> may not always be published alongside it. Check the
10+
> [Forge Files Site](https://files.minecraftforge.net/net/minecraftforge/gradleutils-shared/index.html)
11+
> for the latest version before using it.

gradleutils-shared/build.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ plugins {
1515
}
1616

1717
final projectDisplayName = 'Minecraft Forge Shared Plugin Base'
18-
final projectArtifactId = base.archivesName = 'gradleutils-shared'
18+
base.archivesName = 'gradleutils-shared'
1919
description = 'The shared base used by all of Minecraft Forge\'s Gradle plugins'
2020
group = 'net.minecraftforge'
2121
version = gitversion.tagOffset
@@ -90,7 +90,6 @@ publishing {
9090

9191
publications.register('mavenJava', MavenPublication) {
9292
from components.java
93-
artifactId = projectArtifactId
9493

9594
pom { pom ->
9695
name = projectDisplayName

gradleutils-shared/src/main/java/net/minecraftforge/gradleutils/shared/EnhancedPlugin.java

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
package net.minecraftforge.gradleutils.shared;
66

77
import org.codehaus.groovy.runtime.InvokerHelper;
8-
import org.gradle.StartParameter;
98
import org.gradle.api.Plugin;
109
import org.gradle.api.Project;
1110
import org.gradle.api.file.BuildLayout;
1211
import org.gradle.api.file.DirectoryProperty;
12+
import org.gradle.api.file.ProjectLayout;
13+
import org.gradle.api.initialization.Settings;
1314
import org.gradle.api.invocation.Gradle;
1415
import org.gradle.api.model.ObjectFactory;
1516
import org.gradle.api.provider.Provider;
@@ -37,6 +38,13 @@ public abstract class EnhancedPlugin<T> implements Plugin<T>, EnhancedPluginAddi
3738
/// Service Injection</a>
3839
protected abstract @Inject ObjectFactory getObjects();
3940

41+
/// The project layout provided by Gradle services.
42+
///
43+
/// @return The build layout
44+
/// @see <a href="https://docs.gradle.org/current/userguide/service_injection.html#buildlayout">BuildLayout
45+
/// Service Injection</a>
46+
protected abstract @Inject ProjectLayout getProjectLayout();
47+
4048
/// The build layout provided by Gradle services.
4149
///
4250
/// @return The build layout
@@ -116,16 +124,16 @@ public final DirectoryProperty globalCaches() {
116124

117125
private DirectoryProperty makeGlobalCaches() {
118126
try {
119-
StartParameter startParameter = ((Gradle) InvokerHelper.getPropertySafe(this.target, "gradle")).getStartParameter();
120-
DirectoryProperty gradleUserHomeDir = this.getObjects().directoryProperty().fileValue(startParameter.getGradleUserHomeDir());
127+
Gradle gradle = ((Gradle) InvokerHelper.getProperty(this.target, "gradle"));
128+
DirectoryProperty gradleUserHomeDir = this.getObjects().directoryProperty().fileValue(gradle.getGradleUserHomeDir());
121129

122130
return this.getObjects().directoryProperty().convention(
123131
gradleUserHomeDir.dir("caches/minecraftforge/" + this.name).map(this.problemsInternal.ensureFileLocation())
124132
);
125133
} catch (Exception e) {
126134
throw this.problemsInternal.illegalPluginTarget(
127135
new IllegalArgumentException(String.format("Failed to get %s global caches directory for target: %s", this.displayName, this.target), e),
128-
"types with access to Gradle (#getGradle()Lorg/gradle/api/invocation/Gradle), such as projects or settings."
136+
"projects or settings"
129137
);
130138
}
131139
}
@@ -141,11 +149,11 @@ private DirectoryProperty makeLocalCaches() {
141149
try {
142150
DirectoryProperty workingProjectBuildDir;
143151
if (this.target instanceof Project) {
144-
workingProjectBuildDir = ((Project) this.target).getLayout().getBuildDirectory();
152+
workingProjectBuildDir = this.getProjectLayout().getBuildDirectory();
153+
} else if (this.target instanceof Settings) {
154+
workingProjectBuildDir = this.getObjects().directoryProperty().fileValue(new File(this.getBuildLayout().getRootDirectory().getAsFile(), "build"));
145155
} else {
146-
StartParameter startParameter = ((Gradle) InvokerHelper.getPropertySafe(this.target, "gradle")).getStartParameter();
147-
File projectDir = startParameter.getProjectDir();
148-
workingProjectBuildDir = this.getObjects().directoryProperty().fileValue(new File(projectDir != null ? projectDir : this.getBuildLayout().getRootDirectory().getAsFile(), "build"));
156+
throw new IllegalStateException("Cannot make local caches with an unsupported type (must be project or settings)");
149157
}
150158

151159
return this.getObjects().directoryProperty().convention(
@@ -154,7 +162,32 @@ private DirectoryProperty makeLocalCaches() {
154162
} catch (Exception e) {
155163
throw this.problemsInternal.illegalPluginTarget(
156164
new IllegalArgumentException(String.format("Failed to get %s local caches directory for target: %s", this.displayName, this.getTarget()), e),
157-
"projects or types with access to Gradle (#getGradle()Lorg/gradle/api/invocation/Gradle), such as settings."
165+
"projects or settings"
166+
);
167+
}
168+
}
169+
170+
private final Lazy<DirectoryProperty> workingProjectDirectory = Lazy.simple(this::makeWorkingProjectDirectory);
171+
172+
@Override
173+
public final DirectoryProperty workingProjectDirectory() {
174+
return this.workingProjectDirectory.get();
175+
}
176+
177+
private DirectoryProperty makeWorkingProjectDirectory() {
178+
try {
179+
DirectoryProperty workingProjectDirectory = this.getObjects().directoryProperty();
180+
if (this.target instanceof Project) {
181+
return workingProjectDirectory.value(this.getProjectLayout().getProjectDirectory());
182+
} else if (this.target instanceof Settings) {
183+
return workingProjectDirectory.value(this.getBuildLayout().getRootDirectory());
184+
} else {
185+
throw new IllegalStateException("Cannot get working project directory with an unsupported type (must be project or settings)");
186+
}
187+
} catch (Exception e) {
188+
throw this.problemsInternal.illegalPluginTarget(
189+
new IllegalArgumentException(String.format("Failed to get %s working project directory for target: %s", this.displayName, this.getTarget()), e),
190+
"projects or settings"
158191
);
159192
}
160193
}

gradleutils-shared/src/main/java/net/minecraftforge/gradleutils/shared/EnhancedPluginAdditions.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* Copyright (c) Forge Development LLC and contributors
3+
* SPDX-License-Identifier: LGPL-2.1-only
4+
*/
15
package net.minecraftforge.gradleutils.shared;
26

37
import org.gradle.api.file.DirectoryProperty;
@@ -34,4 +38,16 @@ public interface EnhancedPluginAdditions {
3438
/// @throws RuntimeException If this plugin cannot access global caches (i.e. the target is not
3539
/// [org.gradle.api.Project] or [org.gradle.api.initialization.Settings])
3640
DirectoryProperty localCaches();
41+
42+
/// Gets the working project directory to be used for this plugin. This directory is either the
43+
/// [org.gradle.api.file.ProjectLayout#getProjectDirectory()] of the [org.gradle.api.Project] or the
44+
/// [org.gradle.api.file.BuildLayout#getRootDirectory()] of the [org.gradle.api.initialization.Settings]. Attempting
45+
/// to call this when the plugin target is not either type will throw an exception.
46+
///
47+
/// It is located in `project/build/minecraftforge/plugin`.
48+
///
49+
/// @return The working project directory
50+
/// @throws RuntimeException If this plugin cannot access the working project directory (i.e. the target is not
51+
/// [org.gradle.api.Project] or [org.gradle.api.initialization.Settings])
52+
DirectoryProperty workingProjectDirectory();
3753
}

gradleutils-shared/src/main/java/net/minecraftforge/gradleutils/shared/EnhancedTask.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ default DirectoryProperty localCaches() {
4848
return this.getPlugin().localCaches();
4949
}
5050

51+
@Override
52+
default DirectoryProperty workingProjectDirectory() {
53+
return this.getPlugin().workingProjectDirectory();
54+
}
55+
5156
/// The default output directory to use for this task if it outputs a directory.
5257
///
5358
/// @return A provider for the directory

src/main/groovy/net/minecraftforge/gradleutils/PomUtilsImpl.groovy

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import groovy.transform.CompileStatic
99
import groovy.transform.PackageScope
1010
import net.minecraftforge.gradleutils.shared.SharedUtil
1111
import org.gradle.api.Project
12+
import org.gradle.api.UnknownDomainObjectException
1213
import org.gradle.api.model.ObjectFactory
1314
import org.gradle.api.plugins.ExtensionAware
1415
import org.gradle.api.publish.maven.MavenPom
@@ -46,12 +47,18 @@ import javax.inject.Inject
4647
// If GradleUtils were to depend on Git Version, even as compile-only, it might lead to cyclic dependency issues.
4748
// Editing the PomUtilsImpl meta-class from the Git Version plugin itself is too risky.
4849
// As such, this contract must ALWAYS be true:
49-
// - Project contains an extension named 'gitversion'
50+
// - Project or Gradle contains an extension named 'gitversion'
51+
// - Applying Git Version to Settings will add the extension to settings and gradle
5052
// - The extension contains method '#getUrl()' or property 'url'
51-
this.target.extensions.getByName('gitversion').url
52-
53-
// IN CASE you need to migrate to Java, here is the Java equivalent of this, safe to compile:
54-
//org.codehaus.groovy.runtime.InvokerHelper.getProperty(this.project.extensions.getByName("gitversion"), "url")
53+
try {
54+
this.target.extensions.getByName('gitversion').url
55+
} catch (UnknownDomainObjectException e) {
56+
try {
57+
this.target.gradle.extensions.getByName('gitversion').url
58+
} catch (Exception suppressed) {
59+
throw e.tap { addSuppressed(suppressed) }
60+
}
61+
}
5562
} catch (Exception e) {
5663
throw this.problems.pomUtilsGitVersionMissing(e)
5764
}

0 commit comments

Comments
 (0)