mirror of
https://github.com/architectury/architectury-loom.git
synced 2026-03-28 04:07:01 -05:00
Merge commit '3c3225900123390868a718f5553d552bd0385000' into dev/1.8
This commit is contained in:
@@ -14,7 +14,7 @@ import org.gradle.util.GradleVersion;
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LoomGradlePluginBootstrap implements Plugin<PluginAware> {
|
||||
private static final String MIN_SUPPORTED_GRADLE_VERSION = "8.8";
|
||||
private static final String MIN_SUPPORTED_GRADLE_VERSION = "8.10";
|
||||
private static final int MIN_SUPPORTED_MAJOR_JAVA_VERSION = 17;
|
||||
private static final int MIN_SUPPORTED_MAJOR_IDEA_VERSION = 2021;
|
||||
|
||||
|
||||
@@ -65,7 +65,11 @@ if (!isSnapshot) {
|
||||
logger.lifecycle(":building plugin v${version}")
|
||||
|
||||
// We must build against the version of Kotlin Gradle ships with.
|
||||
def kotlinVersion = KotlinDslVersion.current().getKotlinVersion()
|
||||
def props = new Properties()
|
||||
Project.class.getClassLoader().getResource("gradle-kotlin-dsl-versions.properties").openStream().withCloseable {
|
||||
props.load(it)
|
||||
}
|
||||
def kotlinVersion = props.getProperty("kotlin")
|
||||
if (libs.versions.kotlin.get() != kotlinVersion) {
|
||||
throw new IllegalStateException("Requires Kotlin version: ${kotlinVersion}")
|
||||
}
|
||||
@@ -334,7 +338,6 @@ tasks.withType(Test).configureEach {
|
||||
|
||||
|
||||
import org.gradle.api.internal.artifacts.configurations.ConfigurationRoles
|
||||
import org.gradle.launcher.cli.KotlinDslVersion
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.w3c.dom.Document
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[versions]
|
||||
kotlin = "1.9.22"
|
||||
kotlin = "1.9.24"
|
||||
asm = "9.6"
|
||||
commons-io = "2.15.1"
|
||||
gson = "2.10.1"
|
||||
|
||||
@@ -6,7 +6,7 @@ mockito = "5.12.0"
|
||||
java-debug = "0.52.0"
|
||||
mixin = "0.12.5+mixin.0.8.5"
|
||||
|
||||
gradle-nightly = "8.10-20240613003017+0000"
|
||||
gradle-nightly = "8.11-20240814172604+0000"
|
||||
fabric-loader = "0.15.11"
|
||||
fabric-installer = "1.0.1"
|
||||
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
5
gradlew
vendored
5
gradlew
vendored
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -84,7 +86,8 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
2
gradlew.bat
vendored
2
gradlew.bat
vendored
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
|
||||
@@ -141,14 +141,6 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
|
||||
|
||||
void setRefreshDeps(boolean refreshDeps);
|
||||
|
||||
/**
|
||||
* If true, multi-project optimisation mode is enabled. This mode makes builds with many Loom projects
|
||||
* much faster by increasing sharing and disabling some functionality.
|
||||
*
|
||||
* <p>You can enable it by setting the Gradle property {@code fabric.loom.multiProjectOptimisation} to {@code true}.
|
||||
*/
|
||||
boolean multiProjectOptimisation();
|
||||
|
||||
ListProperty<LibraryProcessorManager.LibraryProcessorFactory> getLibraryProcessors();
|
||||
|
||||
ListProperty<RemapperExtensionHolder> getRemapperExtensions();
|
||||
|
||||
@@ -47,7 +47,6 @@ import net.fabricmc.loom.build.IntermediaryNamespaces;
|
||||
import net.fabricmc.loom.configuration.ide.idea.IdeaUtils;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets;
|
||||
import net.fabricmc.loom.extension.MixinExtension;
|
||||
import net.fabricmc.loom.task.PrepareJarRemapTask;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.LoomVersions;
|
||||
|
||||
@@ -124,11 +123,6 @@ public abstract class AnnotationProcessorInvoker<T extends Task> {
|
||||
args.put("MSG_" + key, value);
|
||||
});
|
||||
|
||||
if (loomExtension.multiProjectOptimisation()) {
|
||||
// Ensure that all of the mixin mappings have been generated before we create the mixin mappings.
|
||||
runBeforePrepare(project, task);
|
||||
}
|
||||
|
||||
project.getLogger().debug("Outputting refmap to dir: " + getRefmapDestinationDir(task) + " for compile task: " + task);
|
||||
args.forEach((k, v) -> passArgument(task, k, v));
|
||||
} catch (IOException e) {
|
||||
@@ -160,12 +154,6 @@ public abstract class AnnotationProcessorInvoker<T extends Task> {
|
||||
}
|
||||
}
|
||||
|
||||
private void runBeforePrepare(Project project, Task compileTask) {
|
||||
project.getGradle().allprojects(otherProject -> {
|
||||
otherProject.getTasks().withType(PrepareJarRemapTask.class, prepareRemapTask -> prepareRemapTask.mustRunAfter(compileTask));
|
||||
});
|
||||
}
|
||||
|
||||
private static void checkPattern(String input, Pattern pattern) {
|
||||
final Matcher matcher = pattern.matcher(input);
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.gradle.api.configuration.BuildFeatures;
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.provider.ListProperty;
|
||||
import org.gradle.api.provider.Provider;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.ForgeExtensionAPI;
|
||||
@@ -63,11 +62,9 @@ import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMi
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MojangMappedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.NamedMinecraftProvider;
|
||||
import net.fabricmc.loom.configuration.providers.minecraft.mapped.SrgMinecraftProvider;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.ModPlatform;
|
||||
import net.fabricmc.loom.util.download.Download;
|
||||
import net.fabricmc.loom.util.download.DownloadBuilder;
|
||||
import net.fabricmc.loom.util.gradle.GradleUtils;
|
||||
|
||||
public abstract class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implements LoomGradleExtension {
|
||||
private final Project project;
|
||||
@@ -86,7 +83,6 @@ public abstract class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl
|
||||
private MojangMappedMinecraftProvider<?> mojangMappedMinecraftProvider;
|
||||
private InstallerData installerData;
|
||||
private boolean refreshDeps;
|
||||
private final Provider<Boolean> multiProjectOptimisation;
|
||||
private final ListProperty<LibraryProcessorManager.LibraryProcessorFactory> libraryProcessorFactories;
|
||||
private final LoomProblemReporter problemReporter;
|
||||
private final boolean configurationCacheActive;
|
||||
@@ -124,7 +120,6 @@ public abstract class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl
|
||||
});
|
||||
|
||||
refreshDeps = manualRefreshDeps();
|
||||
multiProjectOptimisation = GradleUtils.getBooleanPropertyProvider(project, Constants.Properties.MULTI_PROJECT_OPTIMISATION);
|
||||
libraryProcessorFactories = project.getObjects().listProperty(LibraryProcessorManager.LibraryProcessorFactory.class);
|
||||
libraryProcessorFactories.addAll(LibraryProcessorManager.DEFAULT_LIBRARY_PROCESSORS);
|
||||
libraryProcessorFactories.finalizeValueOnRead();
|
||||
@@ -132,15 +127,6 @@ public abstract class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl
|
||||
configurationCacheActive = getBuildFeatures().getConfigurationCache().getActive().get();
|
||||
isolatedProjectsActive = getBuildFeatures().getIsolatedProjects().getActive().get();
|
||||
|
||||
// Fundamentally impossible to support multi-project optimisation with the configuration cache and/or isolated projects.
|
||||
if (multiProjectOptimisation.get() && configurationCacheActive) {
|
||||
throw new UnsupportedOperationException("Multi-project optimisation is not supported with the configuration cache");
|
||||
}
|
||||
|
||||
if (multiProjectOptimisation.get() && isolatedProjectsActive) {
|
||||
throw new UnsupportedOperationException("Isolated projects are not supported with multi-project optimisation");
|
||||
}
|
||||
|
||||
if (configurationCacheActive) {
|
||||
project.getLogger().warn("Loom support for the Gradle configuration cache is highly experimental and may not work as expected. Please report any issues you encounter.");
|
||||
}
|
||||
@@ -315,11 +301,6 @@ public abstract class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl
|
||||
this.refreshDeps = refreshDeps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean multiProjectOptimisation() {
|
||||
return multiProjectOptimisation.getOrElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListProperty<LibraryProcessorManager.LibraryProcessorFactory> getLibraryProcessors() {
|
||||
return libraryProcessorFactories;
|
||||
|
||||
@@ -84,12 +84,6 @@ public abstract class AbstractRemapJarTask extends Jar {
|
||||
@Input
|
||||
public abstract Property<String> getTargetNamespace();
|
||||
|
||||
/**
|
||||
* When enabled the TinyRemapperService will not be shared across sub projects.
|
||||
*/
|
||||
@Input
|
||||
public abstract Property<Boolean> getRemapperIsolation();
|
||||
|
||||
@Inject
|
||||
protected abstract WorkerExecutor getWorkerExecutor();
|
||||
|
||||
@@ -117,7 +111,6 @@ public abstract class AbstractRemapJarTask extends Jar {
|
||||
public AbstractRemapJarTask() {
|
||||
getSourceNamespace().convention(MappingsNamespace.NAMED.toString()).finalizeValueOnRead();
|
||||
getTargetNamespace().convention(getProject().provider(() -> IntermediaryNamespaces.runtimeIntermediary(getProject()))).finalizeValueOnRead();
|
||||
getRemapperIsolation().convention(true).finalizeValueOnRead();
|
||||
getIncludesClientOnlyClasses().convention(false).finalizeValueOnRead();
|
||||
getJarType().finalizeValueOnRead();
|
||||
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.task;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.InputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.workers.WorkAction;
|
||||
import org.gradle.workers.WorkParameters;
|
||||
import org.gradle.workers.WorkQueue;
|
||||
import org.gradle.workers.WorkerExecutor;
|
||||
|
||||
import net.fabricmc.loom.task.service.TinyRemapperService;
|
||||
import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper;
|
||||
|
||||
/**
|
||||
* The prepare remap task runs before all other jar remap tasks, should be used to setup tiny remapper.
|
||||
*/
|
||||
public abstract class PrepareJarRemapTask extends AbstractLoomTask {
|
||||
private final RemapJarTask remapJarTask;
|
||||
@InputFile
|
||||
public abstract RegularFileProperty getInputFile();
|
||||
|
||||
@Inject
|
||||
public PrepareJarRemapTask(RemapJarTask remapJarTask) {
|
||||
this.remapJarTask = remapJarTask;
|
||||
|
||||
getInputFile().set(remapJarTask.getInputFile());
|
||||
// TODO can this be up-to-date when the main task is up-to date?
|
||||
getOutputs().upToDateWhen((o) -> false);
|
||||
|
||||
getProject().getGradle().allprojects(project -> {
|
||||
project.getTasks().withType(PrepareJarRemapTask.class, otherTask -> {
|
||||
if (otherTask == this) return;
|
||||
|
||||
// Ensure that all other prepare tasks inputs have completed
|
||||
dependsOn(otherTask.getInputs());
|
||||
mustRunAfter(otherTask.getInputs());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Inject
|
||||
protected abstract WorkerExecutor getWorkerExecutor();
|
||||
|
||||
@TaskAction
|
||||
public void run() {
|
||||
final WorkQueue workQueue = getWorkerExecutor().noIsolation();
|
||||
|
||||
workQueue.submit(ReadInputsAction.class, params -> {
|
||||
params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(remapJarTask.getTinyRemapperService()));
|
||||
params.getInputFile().set(getInputFile());
|
||||
});
|
||||
}
|
||||
|
||||
public interface ReadInputsParams extends WorkParameters {
|
||||
Property<String> getTinyRemapperBuildServiceUuid();
|
||||
RegularFileProperty getInputFile();
|
||||
}
|
||||
|
||||
public abstract static class ReadInputsAction implements WorkAction<ReadInputsParams> {
|
||||
private final TinyRemapperService tinyRemapperService;
|
||||
|
||||
public ReadInputsAction() {
|
||||
this.tinyRemapperService = UnsafeWorkQueueHelper.get(getParameters().getTinyRemapperBuildServiceUuid(), TinyRemapperService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Path inputFile = getParameters().getInputFile().getAsFile().get().toPath();
|
||||
prepare(tinyRemapperService, inputFile);
|
||||
}
|
||||
}
|
||||
|
||||
static void prepare(TinyRemapperService tinyRemapperService, Path inputFile) {
|
||||
tinyRemapperService.getTinyRemapperForInputs().readInputsAsync(tinyRemapperService.getOrCreateTag(inputFile), inputFile);
|
||||
}
|
||||
}
|
||||
@@ -157,10 +157,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
|
||||
getUseMixinAP().set(LoomGradleExtension.get(getProject()).getMixin().getUseLegacyMixinAp());
|
||||
|
||||
if (getLoomExtension().multiProjectOptimisation()) {
|
||||
setupPreparationTask();
|
||||
}
|
||||
|
||||
// Make outputs reproducible by default
|
||||
setReproducibleFileOrder(true);
|
||||
setPreserveFileTimestamps(false);
|
||||
@@ -168,19 +164,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
getJarType().set("classes");
|
||||
}
|
||||
|
||||
private void setupPreparationTask() {
|
||||
PrepareJarRemapTask prepareJarTask = getProject().getTasks().create("prepare" + getName().substring(0, 1).toUpperCase() + getName().substring(1), PrepareJarRemapTask.class, this);
|
||||
|
||||
dependsOn(prepareJarTask);
|
||||
mustRunAfter(prepareJarTask);
|
||||
|
||||
getProject().getGradle().allprojects(project -> {
|
||||
project.getTasks()
|
||||
.withType(PrepareJarRemapTask.class)
|
||||
.configureEach(this::mustRunAfter);
|
||||
});
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void run() {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(getProject());
|
||||
@@ -194,8 +177,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
params.getTinyRemapperBuildServiceUuid().set(UnsafeWorkQueueHelper.create(getTinyRemapperService()));
|
||||
params.getRemapClasspath().from(getClasspath());
|
||||
|
||||
params.getMultiProjectOptimisation().set(getLoomExtension().multiProjectOptimisation());
|
||||
|
||||
final boolean mixinAp = getUseMixinAP().get();
|
||||
params.getUseMixinExtension().set(!mixinAp);
|
||||
|
||||
@@ -280,7 +261,6 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
SetProperty<String> getAtAccessWideners();
|
||||
|
||||
Property<Boolean> getUseMixinExtension();
|
||||
Property<Boolean> getMultiProjectOptimisation();
|
||||
Property<Boolean> getOptimizeFmj();
|
||||
|
||||
record RefmapData(List<String> mixinConfigs, String refmapName) implements Serializable { }
|
||||
@@ -307,9 +287,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
try {
|
||||
LOGGER.info("Remapping {} to {}", inputFile, outputFile);
|
||||
|
||||
if (!getParameters().getMultiProjectOptimisation().getOrElse(false)) {
|
||||
prepare();
|
||||
}
|
||||
prepare();
|
||||
|
||||
if (tinyRemapperService != null) {
|
||||
tinyRemapper = tinyRemapperService.getTinyRemapperForRemapping();
|
||||
@@ -341,7 +319,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
optimizeFMJ();
|
||||
}
|
||||
|
||||
if (tinyRemapperService != null && !getParameters().getMultiProjectOptimisation().get()) {
|
||||
if (tinyRemapperService != null) {
|
||||
tinyRemapperService.close();
|
||||
}
|
||||
|
||||
@@ -361,7 +339,7 @@ public abstract class RemapJarTask extends AbstractRemapJarTask {
|
||||
final Path inputFile = getParameters().getInputFile().getAsFile().get().toPath();
|
||||
|
||||
if (tinyRemapperService != null) {
|
||||
PrepareJarRemapTask.prepare(tinyRemapperService, inputFile);
|
||||
tinyRemapperService.getTinyRemapperForInputs().readInputsAsync(tinyRemapperService.getOrCreateTag(inputFile), inputFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,34 +33,33 @@ import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Nested;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.loom.task.service.SourceRemapperService;
|
||||
import net.fabricmc.loom.util.service.BuildSharedServiceManager;
|
||||
import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper;
|
||||
import net.fabricmc.loom.util.newService.ScopedServiceFactory;
|
||||
|
||||
public abstract class RemapSourcesJarTask extends AbstractRemapJarTask {
|
||||
private final Provider<BuildSharedServiceManager> serviceManagerProvider;
|
||||
@Nested
|
||||
abstract Property<SourceRemapperService.Options> getSourcesRemapperServiceOptions();
|
||||
|
||||
@Inject
|
||||
public RemapSourcesJarTask() {
|
||||
super();
|
||||
serviceManagerProvider = BuildSharedServiceManager.createForTask(this, getBuildEventsListenerRegistry());
|
||||
|
||||
getClasspath().from(getProject().getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME));
|
||||
getJarType().set("sources");
|
||||
|
||||
getSourcesRemapperServiceOptions().set(SourceRemapperService.createOptions(this));
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void run() {
|
||||
submitWork(RemapSourcesAction.class, params -> {
|
||||
if (!params.namespacesMatch()) {
|
||||
params.getSourcesRemapperServiceUuid().set(UnsafeWorkQueueHelper.create(SourceRemapperService.create(serviceManagerProvider.get().get(), this)));
|
||||
params.getSourcesRemapperServiceOptions().set(getSourcesRemapperServiceOptions());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -73,27 +72,24 @@ public abstract class RemapSourcesJarTask extends AbstractRemapJarTask {
|
||||
}
|
||||
|
||||
public interface RemapSourcesParams extends AbstractRemapParams {
|
||||
Property<String> getSourcesRemapperServiceUuid();
|
||||
Property<SourceRemapperService.Options> getSourcesRemapperServiceOptions();
|
||||
}
|
||||
|
||||
public abstract static class RemapSourcesAction extends AbstractRemapAction<RemapSourcesParams> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RemapSourcesAction.class);
|
||||
|
||||
private final @Nullable SourceRemapperService sourceRemapperService;
|
||||
|
||||
public RemapSourcesAction() {
|
||||
super();
|
||||
|
||||
sourceRemapperService = getParameters().getSourcesRemapperServiceUuid().isPresent()
|
||||
? UnsafeWorkQueueHelper.get(getParameters().getSourcesRemapperServiceUuid(), SourceRemapperService.class)
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
if (sourceRemapperService != null) {
|
||||
sourceRemapperService.remapSourcesJar(inputFile, outputFile);
|
||||
if (!getParameters().namespacesMatch()) {
|
||||
try (var serviceFactory = new ScopedServiceFactory()) {
|
||||
SourceRemapperService sourceRemapperService = serviceFactory.get(getParameters().getSourcesRemapperServiceOptions());
|
||||
sourceRemapperService.remapSourcesJar(inputFile, outputFile);
|
||||
}
|
||||
} else {
|
||||
Files.copy(inputFile, outputFile, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.task.service;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.InputFile;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
|
||||
import net.fabricmc.loom.util.TinyRemapperHelper;
|
||||
import net.fabricmc.loom.util.newService.Service;
|
||||
import net.fabricmc.loom.util.newService.ServiceFactory;
|
||||
import net.fabricmc.loom.util.newService.ServiceType;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.tree.MemoryMappingTree;
|
||||
import net.fabricmc.tinyremapper.IMappingProvider;
|
||||
|
||||
/**
|
||||
* A service that provides mappings for remapping.
|
||||
*/
|
||||
public final class NewMappingsService extends Service<NewMappingsService.Options> implements Closeable {
|
||||
public static ServiceType<Options, NewMappingsService> TYPE = new ServiceType<>(Options.class, NewMappingsService.class);
|
||||
|
||||
public interface Options extends Service.Options {
|
||||
@InputFile
|
||||
RegularFileProperty getMappingsFile();
|
||||
@Input
|
||||
Property<String> getFrom();
|
||||
@Input
|
||||
Property<String> getTo();
|
||||
@Input
|
||||
Property<Boolean> getRemapLocals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns options for creating a new mappings service, with a given mappings file.
|
||||
*/
|
||||
public static Provider<Options> createOptions(Project project, Path mappingsFile, String from, String to, boolean remapLocals) {
|
||||
return TYPE.create(project, o -> {
|
||||
o.getMappingsFile().set(project.file(mappingsFile));
|
||||
o.getFrom().set(from);
|
||||
o.getTo().set(to);
|
||||
o.getRemapLocals().set(remapLocals);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns options for creating a new mappings service, using the mappings as specified in the project's mapping configuration.
|
||||
*/
|
||||
public static Provider<Options> createOptionsWithProjectMappings(Project project, String from, String to) {
|
||||
final MappingConfiguration mappingConfiguration = LoomGradleExtension.get(project).getMappingConfiguration();
|
||||
return createOptions(project, mappingConfiguration.tinyMappings, from, to, false);
|
||||
}
|
||||
|
||||
public NewMappingsService(Options options, ServiceFactory serviceFactory) {
|
||||
super(options, serviceFactory);
|
||||
}
|
||||
|
||||
private IMappingProvider mappingProvider = null;
|
||||
private MemoryMappingTree memoryMappingTree = null;
|
||||
|
||||
public IMappingProvider getMappingsProvider() {
|
||||
if (mappingProvider == null) {
|
||||
try {
|
||||
mappingProvider = TinyRemapperHelper.create(
|
||||
getMappingsPath(),
|
||||
getFrom(),
|
||||
getTo(),
|
||||
getOptions().getRemapLocals().get()
|
||||
);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read mappings from: " + getMappingsPath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return mappingProvider;
|
||||
}
|
||||
|
||||
public MemoryMappingTree getMemoryMappingTree() {
|
||||
if (memoryMappingTree == null) {
|
||||
memoryMappingTree = new MemoryMappingTree();
|
||||
|
||||
try {
|
||||
MappingReader.read(getMappingsPath(), memoryMappingTree);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read mappings from: " + getMappingsPath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return memoryMappingTree;
|
||||
}
|
||||
|
||||
public String getFrom() {
|
||||
return getOptions().getFrom().get();
|
||||
}
|
||||
|
||||
public String getTo() {
|
||||
return getOptions().getTo().get();
|
||||
}
|
||||
|
||||
public Path getMappingsPath() {
|
||||
return getOptions().getMappingsFile().get().getAsFile().toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
mappingProvider = null;
|
||||
}
|
||||
}
|
||||
@@ -26,55 +26,58 @@ package net.fabricmc.loom.task.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import org.cadixdev.lorenz.MappingSet;
|
||||
import org.cadixdev.mercury.Mercury;
|
||||
import org.cadixdev.mercury.remapper.MercuryRemapper;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.InputFiles;
|
||||
import org.gradle.api.tasks.Nested;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.task.RemapSourcesJarTask;
|
||||
import net.fabricmc.loom.util.DeletingFileVisitor;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.SourceRemapper;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.loom.util.service.SharedService;
|
||||
import net.fabricmc.loom.util.service.SharedServiceManager;
|
||||
import net.fabricmc.loom.util.newService.Service;
|
||||
import net.fabricmc.loom.util.newService.ServiceFactory;
|
||||
import net.fabricmc.loom.util.newService.ServiceType;
|
||||
import net.fabricmc.lorenztiny.TinyMappingsReader;
|
||||
|
||||
public final class SourceRemapperService implements SharedService {
|
||||
public static synchronized SourceRemapperService create(SharedServiceManager serviceManager, RemapSourcesJarTask task) {
|
||||
final Project project = task.getProject();
|
||||
final String to = task.getTargetNamespace().get();
|
||||
final String from = task.getSourceNamespace().get();
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
final String id = extension.getMappingConfiguration().getBuildServiceName("sourceremapper", from, to);
|
||||
final int javaCompileRelease = SourceRemapper.getJavaCompileRelease(project);
|
||||
public final class SourceRemapperService extends Service<SourceRemapperService.Options> {
|
||||
public static ServiceType<Options, SourceRemapperService> TYPE = new ServiceType<>(Options.class, SourceRemapperService.class);
|
||||
|
||||
return serviceManager.getOrCreateService(id, () ->
|
||||
new SourceRemapperService(MappingsService.createDefault(project, serviceManager, from, to), task.getClasspath(), javaCompileRelease));
|
||||
public interface Options extends Service.Options {
|
||||
@Nested
|
||||
Property<NewMappingsService.Options> getMappings();
|
||||
@Input
|
||||
Property<Integer> getJavaCompileRelease();
|
||||
@InputFiles
|
||||
ConfigurableFileCollection getClasspath();
|
||||
}
|
||||
|
||||
public static Provider<Options> createOptions(RemapSourcesJarTask task) {
|
||||
return TYPE.create(task.getProject(), o -> {
|
||||
o.getMappings().set(NewMappingsService.createOptionsWithProjectMappings(
|
||||
task.getProject(),
|
||||
task.getSourceNamespace().get(),
|
||||
task.getTargetNamespace().get()
|
||||
));
|
||||
o.getJavaCompileRelease().set(SourceRemapper.getJavaCompileRelease(task.getProject()));
|
||||
o.getClasspath().from(task.getClasspath());
|
||||
});
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SourceRemapperService.class);
|
||||
|
||||
private final MappingsService mappingsService;
|
||||
private final ConfigurableFileCollection classpath;
|
||||
private final int javaCompileRelease;
|
||||
|
||||
private final Supplier<Mercury> mercury = Suppliers.memoize(this::createMercury);
|
||||
|
||||
private SourceRemapperService(MappingsService mappingsService, ConfigurableFileCollection classpath, int javaCompileRelease) {
|
||||
this.mappingsService = mappingsService;
|
||||
this.classpath = classpath;
|
||||
this.javaCompileRelease = javaCompileRelease;
|
||||
public SourceRemapperService(Options options, ServiceFactory serviceFactory) {
|
||||
super(options, serviceFactory);
|
||||
}
|
||||
|
||||
public void remapSourcesJar(Path source, Path destination) throws IOException {
|
||||
@@ -96,10 +99,17 @@ public final class SourceRemapperService implements SharedService {
|
||||
Files.delete(destination);
|
||||
}
|
||||
|
||||
Mercury mercury = createMercury();
|
||||
|
||||
try (FileSystemUtil.Delegate dstFs = Files.isDirectory(destination) ? null : FileSystemUtil.getJarFileSystem(destination, true)) {
|
||||
Path dstPath = dstFs != null ? dstFs.get().getPath("/") : destination;
|
||||
|
||||
doRemap(srcPath, dstPath, source);
|
||||
try {
|
||||
mercury.rewrite(srcPath, dstPath);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Could not remap " + source + " fully!", e);
|
||||
}
|
||||
|
||||
SourceRemapper.copyNonJavaFiles(srcPath, dstPath, LOGGER, source);
|
||||
} finally {
|
||||
if (isSrcTmp) {
|
||||
@@ -108,30 +118,16 @@ public final class SourceRemapperService implements SharedService {
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void doRemap(Path srcPath, Path dstPath, Path source) {
|
||||
try {
|
||||
mercury.get().rewrite(srcPath, dstPath);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Could not remap " + source + " fully!", e);
|
||||
}
|
||||
}
|
||||
|
||||
private MappingSet getMappings() throws IOException {
|
||||
return new TinyMappingsReader(mappingsService.getMemoryMappingTree(), mappingsService.getFromNamespace(), mappingsService.getToNamespace()).read();
|
||||
}
|
||||
|
||||
private Mercury createMercury() {
|
||||
private Mercury createMercury() throws IOException {
|
||||
var mercury = new Mercury();
|
||||
mercury.setGracefulClasspathChecks(true);
|
||||
mercury.setSourceCompatibilityFromRelease(javaCompileRelease);
|
||||
mercury.setSourceCompatibilityFromRelease(getOptions().getJavaCompileRelease().get());
|
||||
|
||||
try {
|
||||
mercury.getProcessors().add(MercuryRemapper.create(getMappings()));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to read mercury mappings", e);
|
||||
}
|
||||
NewMappingsService mappingsService = getServiceFactory().get(getOptions().getMappings());
|
||||
var tinyMappingsReader = new TinyMappingsReader(mappingsService.getMemoryMappingTree(), mappingsService.getFrom(), mappingsService.getTo()).read();
|
||||
mercury.getProcessors().add(MercuryRemapper.create(tinyMappingsReader));
|
||||
|
||||
for (File file : classpath.getFiles()) {
|
||||
for (File file : getOptions().getClasspath().getFiles()) {
|
||||
if (file.exists()) {
|
||||
mercury.getClassPath().add(file.toPath());
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ import org.gradle.api.tasks.SourceSet;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.build.IntermediaryNamespaces;
|
||||
import net.fabricmc.loom.build.mixin.AnnotationProcessorInvoker;
|
||||
import net.fabricmc.loom.extension.RemapperExtensionHolder;
|
||||
@@ -71,7 +70,6 @@ public class TinyRemapperService implements SharedService {
|
||||
final LoomGradleExtension extension = LoomGradleExtension.get(project);
|
||||
final boolean legacyMixin = extension.getMixin().getUseLegacyMixinAp().get();
|
||||
final @Nullable KotlinClasspathService kotlinClasspathService = KotlinClasspathService.getOrCreateIfRequired(serviceManager, project);
|
||||
boolean multiProjectOptimisation = extension.multiProjectOptimisation();
|
||||
|
||||
// Generates an id that is used to share the remapper across projects. This tasks in the remap jar task name to handle custom remap jar tasks separately.
|
||||
final var joiner = new StringJoiner(":");
|
||||
@@ -82,9 +80,8 @@ public class TinyRemapperService implements SharedService {
|
||||
joiner.add("kotlin-" + kotlinClasspathService.version());
|
||||
}
|
||||
|
||||
if (remapJarTask.getRemapperIsolation().get() || !multiProjectOptimisation) {
|
||||
joiner.add(project.getPath());
|
||||
}
|
||||
// TODO remove this when removing shared service manager.
|
||||
joiner.add(project.getPath());
|
||||
|
||||
extension.getKnownIndyBsms().get().stream().sorted().forEach(joiner::add);
|
||||
|
||||
@@ -108,20 +105,6 @@ public class TinyRemapperService implements SharedService {
|
||||
final ConfigurationContainer configurations = project.getConfigurations();
|
||||
ConfigurableFileCollection excludedMinecraftJars = project.files();
|
||||
|
||||
// Exclude none root minecraft jars.
|
||||
if (multiProjectOptimisation && !extension.isRootProject()) {
|
||||
MappingsNamespace mappingsNamespace = MappingsNamespace.of(from);
|
||||
|
||||
if (mappingsNamespace != null) {
|
||||
for (Path minecraftJar : extension.getMinecraftJars(mappingsNamespace)) {
|
||||
excludedMinecraftJars.from(minecraftJar.toFile());
|
||||
}
|
||||
} else {
|
||||
// None fatal as this is a performance optimisation.
|
||||
project.getLogger().warn("Unable to find minecraft jar for namespace {}", from);
|
||||
}
|
||||
}
|
||||
|
||||
List<Path> classPath = remapJarTask.getClasspath()
|
||||
.minus(configurations.getByName(Constants.Configurations.MINECRAFT_COMPILE_LIBRARIES))
|
||||
.minus(configurations.getByName(Constants.Configurations.MINECRAFT_RUNTIME_LIBRARIES))
|
||||
|
||||
@@ -155,7 +155,6 @@ public class Constants {
|
||||
}
|
||||
|
||||
public static final class Properties {
|
||||
public static final String MULTI_PROJECT_OPTIMISATION = "fabric.loom.multiProjectOptimisation";
|
||||
public static final String DONT_REMAP = "fabric.loom.dontRemap";
|
||||
public static final String DISABLE_REMAPPED_VARIANTS = "fabric.loom.disableRemappedVariants";
|
||||
public static final String DISABLE_PROJECT_DEPENDENT_MODS = "fabric.loom.disableProjectDependentMods";
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.util.gradle;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.TypeAdapterFactory;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.ListProperty;
|
||||
import org.gradle.api.provider.MapProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public class GradleTypeAdapter implements TypeAdapterFactory {
|
||||
public static final Gson GSON = new Gson().newBuilder()
|
||||
.registerTypeAdapterFactory(new GradleTypeAdapter())
|
||||
.create();
|
||||
|
||||
@Override
|
||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||
final Class<? super T> rawClass = type.getRawType();
|
||||
|
||||
if (FileCollection.class.isAssignableFrom(rawClass)) {
|
||||
return new FileCollectionTypeAdapter();
|
||||
} else if (RegularFileProperty.class.isAssignableFrom(rawClass)) {
|
||||
return new RegularFilePropertyTypeAdapter();
|
||||
} else if (ListProperty.class.isAssignableFrom(rawClass)) {
|
||||
return new ListPropertyTypeAdapter(gson);
|
||||
} else if (MapProperty.class.isAssignableFrom(rawClass)) {
|
||||
return new MapPropertyTypeAdapter(gson);
|
||||
} else if (Property.class.isAssignableFrom(rawClass)) {
|
||||
return new PropertyTypeAdapter(gson);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class PropertyTypeAdapter<T extends Property<?>> extends WriteOnlyTypeAdapter<T> {
|
||||
private final Gson gson;
|
||||
|
||||
private PropertyTypeAdapter(Gson gson) {
|
||||
this.gson = gson;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter out, T property) throws IOException {
|
||||
final Object o = property.get();
|
||||
final TypeAdapter adapter = gson.getAdapter(o.getClass());
|
||||
adapter.write(out, o);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class FileCollectionTypeAdapter<T extends FileCollection> extends WriteOnlyTypeAdapter<T> {
|
||||
@Override
|
||||
public void write(JsonWriter out, T fileCollection) throws IOException {
|
||||
out.beginArray();
|
||||
|
||||
final List<String> files = fileCollection.getFiles().stream()
|
||||
.map(File::getAbsolutePath)
|
||||
.sorted()
|
||||
.toList();
|
||||
|
||||
for (String file : files) {
|
||||
out.value(file);
|
||||
}
|
||||
|
||||
out.endArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class RegularFilePropertyTypeAdapter<T extends RegularFileProperty> extends WriteOnlyTypeAdapter<T> {
|
||||
@Override
|
||||
public void write(JsonWriter out, T property) throws IOException {
|
||||
final File file = property.get().getAsFile();
|
||||
out.value(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ListPropertyTypeAdapter<T extends ListProperty<?>> extends WriteOnlyTypeAdapter<T> {
|
||||
private final Gson gson;
|
||||
|
||||
private ListPropertyTypeAdapter(Gson gson) {
|
||||
this.gson = gson;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter out, T property) throws IOException {
|
||||
List<?> objects = property.get();
|
||||
out.beginArray();
|
||||
|
||||
for (Object o : objects) {
|
||||
final TypeAdapter adapter = gson.getAdapter(o.getClass());
|
||||
adapter.write(out, o);
|
||||
}
|
||||
|
||||
out.endArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MapPropertyTypeAdapter<T extends MapProperty<?, ?>> extends WriteOnlyTypeAdapter<T> {
|
||||
private final Gson gson;
|
||||
|
||||
private MapPropertyTypeAdapter(Gson gson) {
|
||||
this.gson = gson;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter out, T property) throws IOException {
|
||||
out.beginObject();
|
||||
|
||||
for (Map.Entry<?, ?> entry : property.get().entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (!(key instanceof String)) {
|
||||
throw new UnsupportedOperationException("Map keys must be strings");
|
||||
}
|
||||
|
||||
out.name(entry.getKey().toString());
|
||||
final TypeAdapter adapter = gson.getAdapter(value.getClass());
|
||||
adapter.write(out, value);
|
||||
}
|
||||
|
||||
out.endObject();
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class WriteOnlyTypeAdapter<T> extends TypeAdapter<T> {
|
||||
@Override
|
||||
public final T read(JsonReader in) {
|
||||
throw new UnsupportedOperationException("This type adapter is write-only");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
* Copyright (c) 2022-2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -41,6 +41,7 @@ import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.plugins.JavaPluginExtension;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.SourceSetContainer;
|
||||
@@ -53,6 +54,7 @@ import org.xml.sax.InputSource;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.api.ModSettings;
|
||||
import net.fabricmc.loom.configuration.ide.idea.IdeaUtils;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
|
||||
public final class SourceSetHelper {
|
||||
@VisibleForTesting
|
||||
@@ -123,7 +125,7 @@ public final class SourceSetHelper {
|
||||
}
|
||||
|
||||
public static List<File> getClasspath(SourceSetReference reference, Project project) {
|
||||
final List<File> classpath = getGradleClasspath(reference);
|
||||
final List<File> classpath = getGradleClasspath(reference, project);
|
||||
|
||||
classpath.addAll(getIdeaClasspath(reference, project));
|
||||
classpath.addAll(getEclipseClasspath(reference, project));
|
||||
@@ -132,7 +134,7 @@ public final class SourceSetHelper {
|
||||
return classpath;
|
||||
}
|
||||
|
||||
private static List<File> getGradleClasspath(SourceSetReference reference) {
|
||||
private static List<File> getGradleClasspath(SourceSetReference reference, Project project) {
|
||||
final SourceSetOutput output = reference.sourceSet().getOutput();
|
||||
final File resources = output.getResourcesDir();
|
||||
|
||||
@@ -144,6 +146,19 @@ public final class SourceSetHelper {
|
||||
classpath.add(resources);
|
||||
}
|
||||
|
||||
// Add dev jars from dependency projects if the source set is "main".
|
||||
if (SourceSet.MAIN_SOURCE_SET_NAME.equals(reference.sourceSet().getName()) && !reference.project().getPath().equals(project.getPath())
|
||||
&& GradleUtils.isLoomProject(reference.project())) {
|
||||
final Configuration namedElements = reference.project().getConfigurations().getByName(Constants.Configurations.NAMED_ELEMENTS);
|
||||
|
||||
// Note: We're not looking at the artifacts from configuration variants. It's probably not needed
|
||||
// (certainly not with Loom's setup), but technically someone could add child variants that add additional
|
||||
// dev jars that wouldn't be picked up by this.
|
||||
for (File artifact : namedElements.getOutgoing().getArtifacts().getFiles()) {
|
||||
classpath.add(artifact);
|
||||
}
|
||||
}
|
||||
|
||||
return classpath;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.util.newService;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Nested;
|
||||
|
||||
// Note: This file mostly acts as documentation for the new service system.
|
||||
// Services are classes that wrap expensive to create objects, such as mappings or tiny remapper.
|
||||
// Services can be reused multiple times within a given scope, such as configuration or a single task action.
|
||||
// Services need to have serializable inputs, used as a cache key and serialised to be passed between Gradle contexts. E.g task inputs, or work action params.
|
||||
public final class ExampleService extends Service<ExampleService.Options> implements Closeable {
|
||||
public static ServiceType<Options, ExampleService> TYPE = new ServiceType<>(Options.class, ExampleService.class);
|
||||
|
||||
// Options use Gradle's Property's thus can be used in task inputs.
|
||||
public interface Options extends Service.Options {
|
||||
@Nested
|
||||
Property<AnotherService.Options> getNested();
|
||||
}
|
||||
|
||||
// Options can be created using data from the Project
|
||||
static Provider<Options> createOptions(Project project) {
|
||||
return TYPE.create(project, o -> {
|
||||
o.getNested().set(AnotherService.createOptions(project, "example"));
|
||||
});
|
||||
}
|
||||
|
||||
// An example of how a service could be used, this could be within a task action.
|
||||
// ServiceFactory would be similar to the existing ScopedSharedServiceManager
|
||||
// Thus if a service with the same options has previously been created it will be reused.
|
||||
static void howToUse(Options options, ServiceFactory factory) {
|
||||
ExampleService exampleService = factory.get(options);
|
||||
exampleService.doSomething();
|
||||
}
|
||||
|
||||
public ExampleService(Options options, ServiceFactory serviceFactory) {
|
||||
super(options, serviceFactory);
|
||||
}
|
||||
|
||||
public void doSomething() {
|
||||
// The service factory used to the creation the current service can be used to get or create other services based on the current service's options.
|
||||
AnotherService another = getServiceFactory().get(getOptions().getNested());
|
||||
System.out.println("ExampleService: " + another.getExample());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// Anything that needs to be cleaned up when the service is no longer needed.
|
||||
}
|
||||
|
||||
public static final class AnotherService extends Service<AnotherService.Options> {
|
||||
public static ServiceType<Options, AnotherService> TYPE = new ServiceType<>(Options.class, AnotherService.class);
|
||||
|
||||
public interface Options extends Service.Options {
|
||||
@Input
|
||||
Property<String> getExample();
|
||||
}
|
||||
|
||||
static Provider<AnotherService.Options> createOptions(Project project, String example) {
|
||||
return TYPE.create(project, o -> {
|
||||
o.getExample().set(example);
|
||||
});
|
||||
}
|
||||
|
||||
public AnotherService(Options options, ServiceFactory serviceFactory) {
|
||||
super(options, serviceFactory);
|
||||
}
|
||||
|
||||
// Services can expose any methods they wish, either to return data or do a job.
|
||||
public String getExample() {
|
||||
return getOptions().getExample().get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.util.newService;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.fabricmc.loom.util.gradle.GradleTypeAdapter;
|
||||
|
||||
/**
|
||||
* An implementation of {@link ServiceFactory} that creates services scoped to the factory instance.
|
||||
* When the factory is closed, all services created by it are closed and discarded.
|
||||
*/
|
||||
public final class ScopedServiceFactory implements ServiceFactory, Closeable {
|
||||
private final Map<Service.Options, Service<?>> servicesIdentityMap = new IdentityHashMap<>();
|
||||
private final Map<String, Service<?>> servicesJsonMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public <O extends Service.Options, S extends Service<O>> S get(O options) {
|
||||
// First check if the service is already created, using the identity map saving the need to serialize the options
|
||||
//noinspection unchecked
|
||||
S service = (S) servicesIdentityMap.get(options);
|
||||
|
||||
if (service != null) {
|
||||
return service;
|
||||
}
|
||||
|
||||
// TODO skip serialization if we know there is no service with the same type
|
||||
|
||||
// If the service is not already created, serialize the options and check the json map as it may be an equivalent service
|
||||
String key = getOptionsCacheKey(options);
|
||||
//noinspection unchecked
|
||||
service = (S) servicesJsonMap.get(key);
|
||||
|
||||
if (service != null) {
|
||||
return service;
|
||||
}
|
||||
|
||||
service = createService(options, this);
|
||||
|
||||
servicesIdentityMap.put(options, service);
|
||||
servicesJsonMap.put(key, service);
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
private static <O extends Service.Options, S extends Service<O>> S createService(O options, ServiceFactory serviceFactory) {
|
||||
// We need to create the service from the provided options
|
||||
final Class<? extends S> serviceClass;
|
||||
|
||||
// Find the service class
|
||||
try {
|
||||
//noinspection unchecked
|
||||
serviceClass = (Class<? extends S>) Class.forName(options.getServiceClass().get());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Failed to find service class: " + options.getServiceClass().get(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
// Check there is only 1 constructor
|
||||
if (serviceClass.getDeclaredConstructors().length != 1) {
|
||||
throw new RuntimeException("Service class must have exactly 1 constructor");
|
||||
}
|
||||
|
||||
// Check the constructor takes the correct types, the options class and a ScopedServiceFactory
|
||||
Class<?>[] parameterTypes = serviceClass.getDeclaredConstructors()[0].getParameterTypes();
|
||||
|
||||
if (parameterTypes.length != 2 || !parameterTypes[0].isAssignableFrom(options.getClass()) || !parameterTypes[1].isAssignableFrom(ServiceFactory.class)) {
|
||||
throw new RuntimeException("Service class" + serviceClass.getName() + " constructor must take the options class and a ScopedServiceFactory");
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return (S) serviceClass.getDeclaredConstructors()[0].newInstance(options, serviceFactory);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException("Failed to create service instance", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getOptionsCacheKey(Service.Options options) {
|
||||
return GradleTypeAdapter.GSON.toJson(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
for (Service<?> service : servicesIdentityMap.values()) {
|
||||
if (service instanceof Closeable closeable) {
|
||||
closeable.close();
|
||||
}
|
||||
}
|
||||
|
||||
servicesIdentityMap.clear();
|
||||
servicesJsonMap.clear();
|
||||
}
|
||||
}
|
||||
71
src/main/java/net/fabricmc/loom/util/newService/Service.java
Normal file
71
src/main/java/net/fabricmc/loom/util/newService/Service.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.util.newService;
|
||||
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* A service is used to manage a set of data or a task that may be reused multiple times.
|
||||
*
|
||||
* @param <O> The options type.
|
||||
*/
|
||||
public abstract class Service<O extends Service.Options> {
|
||||
private final O options;
|
||||
private final ServiceFactory serviceFactory;
|
||||
|
||||
public Service(O options, ServiceFactory serviceFactory) {
|
||||
this.options = options;
|
||||
this.serviceFactory = serviceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the options for this service.
|
||||
*
|
||||
* @return The options.
|
||||
*/
|
||||
protected final O getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the factory that created this service, this can be used to get nested services.
|
||||
*
|
||||
* @return The {@link ServiceFactory} instance.
|
||||
*/
|
||||
protected ServiceFactory getServiceFactory() {
|
||||
return serviceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* The base type of options class for a service.
|
||||
*/
|
||||
public interface Options {
|
||||
@Input
|
||||
@ApiStatus.Internal
|
||||
Property<String> getServiceClass();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.util.newService;
|
||||
|
||||
import org.gradle.api.provider.Property;
|
||||
|
||||
/**
|
||||
* A factory for creating {@link Service} instances.
|
||||
*/
|
||||
public interface ServiceFactory {
|
||||
/**
|
||||
* Gets or creates a service instance with the given options.
|
||||
*
|
||||
* @param options The options to use.
|
||||
* @param <O> The options type.
|
||||
* @param <S> The service type.
|
||||
* @return The service instance.
|
||||
*/
|
||||
default <O extends Service.Options, S extends Service<O>> S get(Property<O> options) {
|
||||
return get(options.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or creates a service instance with the given options.
|
||||
*
|
||||
* @param options The options to use.
|
||||
* @param <O> The options type.
|
||||
* @param <S> The service type.
|
||||
* @return The service instance.
|
||||
*/
|
||||
<O extends Service.Options, S extends Service<O>> S get(O options);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.util.newService;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.provider.Provider;
|
||||
|
||||
/**
|
||||
* A record to hold the options and service class for a service.
|
||||
* @param optionsClass The options class for the service.
|
||||
* @param serviceClass The service class.
|
||||
*/
|
||||
public record ServiceType<O extends Service.Options, S extends Service<O>>(Class<O> optionsClass, Class<S> serviceClass) {
|
||||
/**
|
||||
* Create an instance of the options class for the given service class.
|
||||
* @param project The {@link Project} to create the options for.
|
||||
* @param action An action to configure the options.
|
||||
* @return The created options instance.
|
||||
*/
|
||||
public Provider<O> create(Project project, Action<O> action) {
|
||||
return project.provider(() -> {
|
||||
O options = project.getObjects().newInstance(optionsClass);
|
||||
options.getServiceClass().set(serviceClass.getName());
|
||||
options.getServiceClass().finalizeValue();
|
||||
action.execute(options);
|
||||
return options;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -48,8 +48,6 @@ class FabricAPIBenchmark implements GradleProjectTestTrait {
|
||||
patch: "fabric_api"
|
||||
)
|
||||
|
||||
gradle.enableMultiProjectOptimisation()
|
||||
|
||||
if (!gradle.buildGradle.text.contains("loom.mixin.useLegacyMixinAp")) {
|
||||
gradle.buildGradle << """
|
||||
allprojects {
|
||||
|
||||
@@ -60,6 +60,7 @@ class ConfigurationCacheTest extends Specification implements GradleProjectTestT
|
||||
"configureClientLaunch" | _
|
||||
"jar" | _
|
||||
"check" | _
|
||||
"remapSourcesJar" | _
|
||||
}
|
||||
|
||||
// Test GradleUtils.configurationInputFile invalidates the cache when the file changes
|
||||
|
||||
@@ -49,8 +49,6 @@ class FabricAPITest extends Specification implements GradleProjectTestTrait {
|
||||
patch: "fabric_api"
|
||||
)
|
||||
|
||||
gradle.enableMultiProjectOptimisation()
|
||||
|
||||
// Disable the mixin ap if needed. Fabric API is a large enough test project to see if something breaks.
|
||||
if (disableMixinAp) {
|
||||
gradle.buildGradle << """
|
||||
@@ -108,7 +106,6 @@ class FabricAPITest extends Specification implements GradleProjectTestTrait {
|
||||
|
||||
then:
|
||||
result.task(":build").outcome == SUCCESS
|
||||
result.task(":prepareRemapJar").outcome == SUCCESS
|
||||
|
||||
def biomeApiJar = new File(gradle.mavenLocalDir, "net/fabricmc/fabric-api/fabric-biome-api-v1/999.0.0/fabric-biome-api-v1-999.0.0.jar")
|
||||
new File(gradle.mavenLocalDir, "net/fabricmc/fabric-api/fabric-biome-api-v1/999.0.0/fabric-biome-api-v1-999.0.0-sources.jar").exists()
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.gradle.internal.remote.internal.inet.InetAddressFactory
|
||||
import org.gradle.internal.service.ServiceRegistry
|
||||
import org.gradle.invocation.DefaultGradle
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import org.gradle.launcher.daemon.configuration.DaemonParameters
|
||||
import org.gradle.launcher.daemon.configuration.DaemonPriority
|
||||
import org.gradle.launcher.daemon.context.DefaultDaemonContext
|
||||
import org.gradle.launcher.daemon.protocol.DaemonMessageSerializer
|
||||
import org.gradle.launcher.daemon.protocol.Finished
|
||||
@@ -52,7 +52,7 @@ import org.gradle.launcher.daemon.server.DaemonTcpServerConnector
|
||||
import org.gradle.launcher.daemon.server.DefaultDaemonConnection
|
||||
import org.gradle.launcher.daemon.server.IncomingConnectionHandler
|
||||
import org.gradle.launcher.daemon.server.SynchronizedDispatchConnection
|
||||
import org.gradle.launcher.daemon.server.api.DaemonStateControl
|
||||
import org.gradle.launcher.daemon.server.api.DaemonState
|
||||
import org.gradle.util.GradleVersion
|
||||
|
||||
import net.fabricmc.loom.util.gradle.daemon.DaemonUtils
|
||||
@@ -78,7 +78,7 @@ class TestPlugin implements Plugin<Project> {
|
||||
|
||||
// Write it in the registry
|
||||
def registry = new PersistentDaemonRegistry(registryBin.toFile(), services.get(FileLockManager.class), services.get(Chmod.class))
|
||||
def daemonInfo = new DaemonInfo(address, createDaemonContext(), "token".bytes, DaemonStateControl.State.Busy)
|
||||
def daemonInfo = new DaemonInfo(address, createDaemonContext(), "token".bytes, DaemonState.Busy)
|
||||
registry.store(daemonInfo)
|
||||
|
||||
// When we get a connection, wait for a stop message and process it by responding with a success message
|
||||
@@ -99,36 +99,19 @@ class TestPlugin implements Plugin<Project> {
|
||||
}
|
||||
}
|
||||
|
||||
// Thanks groovy for allowing me to do this :D
|
||||
static DefaultDaemonContext createDaemonContext() {
|
||||
int constructorArgsCount = DefaultDaemonContext.class.getConstructors()[0].getParameterCount()
|
||||
|
||||
if (constructorArgsCount == 10) {
|
||||
// Gradle 8.9+ adds a JavaVersion and NativeServicesMode parameter to the constructor
|
||||
//noinspection GroovyAssignabilityCheck
|
||||
return new DefaultDaemonContext(
|
||||
UUID.randomUUID().toString(),
|
||||
new File("."),
|
||||
JavaLanguageVersion.current(),
|
||||
new File("."),
|
||||
ProcessHandle.current().pid(),
|
||||
0,
|
||||
List.of(),
|
||||
false,
|
||||
NativeServices.NativeServicesMode.NOT_SET,
|
||||
DaemonParameters.Priority.NORMAL
|
||||
)
|
||||
}
|
||||
|
||||
return new DefaultDaemonContext(
|
||||
UUID.randomUUID().toString(),
|
||||
new File("."),
|
||||
JavaLanguageVersion.current(),
|
||||
"",
|
||||
new File("."),
|
||||
ProcessHandle.current().pid(),
|
||||
0,
|
||||
List.of(),
|
||||
false,
|
||||
DaemonParameters.Priority.NORMAL
|
||||
NativeServices.NativeServicesMode.NOT_SET,
|
||||
DaemonPriority.NORMAL
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.test.unit
|
||||
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.RegularFile
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.MapProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import spock.lang.IgnoreIf
|
||||
import spock.lang.Specification
|
||||
|
||||
import net.fabricmc.loom.util.gradle.GradleTypeAdapter
|
||||
|
||||
class GradleTypeAdapterTest extends Specification {
|
||||
def "Property"() {
|
||||
given:
|
||||
def property = Mock(Property)
|
||||
|
||||
when:
|
||||
def json = GradleTypeAdapter.GSON.toJson(property)
|
||||
|
||||
then:
|
||||
1 * property.get() >> "value"
|
||||
json == "\"value\""
|
||||
}
|
||||
|
||||
@IgnoreIf({ os.windows })
|
||||
def "FileCollection"() {
|
||||
given:
|
||||
def file1 = new File("file1")
|
||||
def file2 = new File("file2")
|
||||
def fileCollection = Mock(FileCollection)
|
||||
|
||||
when:
|
||||
def json = GradleTypeAdapter.GSON.toJson(fileCollection)
|
||||
|
||||
then:
|
||||
1 * fileCollection.getFiles() >> [file1, file2].shuffled()
|
||||
json == "[\"${file1.getAbsolutePath()}\",\"${file2.getAbsolutePath()}\"]"
|
||||
}
|
||||
|
||||
@IgnoreIf({ os.windows })
|
||||
def "RegularFileProperty"() {
|
||||
given:
|
||||
def file = new File("file")
|
||||
def regularFileProperty = Mock(RegularFileProperty)
|
||||
def regularFile = Mock(RegularFile)
|
||||
|
||||
when:
|
||||
def json = GradleTypeAdapter.GSON.toJson(regularFileProperty)
|
||||
|
||||
then:
|
||||
1 * regularFileProperty.get() >> regularFile
|
||||
1 * regularFile.getAsFile() >> file
|
||||
json == "\"${file.getAbsolutePath()}\""
|
||||
}
|
||||
|
||||
def "ListProperty"() {
|
||||
given:
|
||||
def listProperty = Mock(ListProperty)
|
||||
def list = ["value1", "value2"]
|
||||
|
||||
when:
|
||||
def json = GradleTypeAdapter.GSON.toJson(listProperty)
|
||||
|
||||
then:
|
||||
1 * listProperty.get() >> list
|
||||
json == "[\"value1\",\"value2\"]"
|
||||
}
|
||||
|
||||
def "MapProperty"() {
|
||||
given:
|
||||
def mapProperty = Mock(MapProperty)
|
||||
def map = ["key1": "value1", "key2": "value2"]
|
||||
|
||||
when:
|
||||
def json = GradleTypeAdapter.GSON.toJson(mapProperty)
|
||||
|
||||
then:
|
||||
1 * mapProperty.get() >> map
|
||||
json == "{\"key1\":\"value1\",\"key2\":\"value2\"}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.test.unit.service
|
||||
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
|
||||
import net.fabricmc.loom.task.service.NewMappingsService
|
||||
import net.fabricmc.loom.test.util.GradleTestUtil
|
||||
|
||||
class MappingsServiceTest extends ServiceTestBase {
|
||||
def "get mapping tree"() {
|
||||
given:
|
||||
NewMappingsService service = factory.get(new TestOptions(
|
||||
mappingsFile: GradleTestUtil.mockRegularFileProperty(new File("src/test/resources/mappings/PosInChunk.mappings")),
|
||||
from: GradleTestUtil.mockProperty("intermediary"),
|
||||
to: GradleTestUtil.mockProperty("named"),
|
||||
))
|
||||
|
||||
when:
|
||||
def mappingTree = service.memoryMappingTree
|
||||
|
||||
then:
|
||||
mappingTree.getClasses().size() == 2
|
||||
|
||||
service.from == "intermediary"
|
||||
service.to == "named"
|
||||
}
|
||||
|
||||
static class TestOptions implements NewMappingsService.Options {
|
||||
RegularFileProperty mappingsFile
|
||||
Property<String> from
|
||||
Property<String> to
|
||||
Property<Boolean> remapLocals = GradleTestUtil.mockProperty(false)
|
||||
Property<String> serviceClass = serviceClassProperty(NewMappingsService.TYPE)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.test.unit.service
|
||||
|
||||
import groovy.transform.InheritConstructors
|
||||
import groovy.transform.TupleConstructor
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import spock.lang.Specification
|
||||
|
||||
import net.fabricmc.loom.test.util.GradleTestUtil
|
||||
import net.fabricmc.loom.util.newService.ScopedServiceFactory
|
||||
import net.fabricmc.loom.util.newService.Service
|
||||
import net.fabricmc.loom.util.newService.ServiceType
|
||||
|
||||
class ScopedServiceFactoryTest extends Specification {
|
||||
def "create service"() {
|
||||
given:
|
||||
def options = new TestServiceOptions(GradleTestUtil.mockProperty("hello"))
|
||||
def factory = new ScopedServiceFactory()
|
||||
|
||||
when:
|
||||
TestService service = factory.get(options)
|
||||
|
||||
then:
|
||||
service.getExample() == "hello"
|
||||
|
||||
cleanup:
|
||||
factory.close()
|
||||
}
|
||||
|
||||
def "reuse service"() {
|
||||
given:
|
||||
def options = new TestServiceOptions(GradleTestUtil.mockProperty("hello"))
|
||||
def factory = new ScopedServiceFactory()
|
||||
|
||||
when:
|
||||
TestService service = factory.get(options)
|
||||
TestService service2 = factory.get(options)
|
||||
|
||||
then:
|
||||
service === service2
|
||||
|
||||
cleanup:
|
||||
factory.close()
|
||||
}
|
||||
|
||||
def "reuse service different options instance"() {
|
||||
given:
|
||||
def options = new TestServiceOptions(GradleTestUtil.mockProperty("hello"))
|
||||
def options2 = new TestServiceOptions(GradleTestUtil.mockProperty("hello"))
|
||||
def factory = new ScopedServiceFactory()
|
||||
|
||||
when:
|
||||
TestService service = factory.get(options)
|
||||
TestService service2 = factory.get(options2)
|
||||
|
||||
then:
|
||||
service === service2
|
||||
|
||||
cleanup:
|
||||
factory.close()
|
||||
}
|
||||
|
||||
def "Separate instances"() {
|
||||
given:
|
||||
def options = new TestServiceOptions(GradleTestUtil.mockProperty("hello"))
|
||||
def options2 = new TestServiceOptions(GradleTestUtil.mockProperty("world"))
|
||||
def factory = new ScopedServiceFactory()
|
||||
|
||||
when:
|
||||
TestService service = factory.get(options)
|
||||
TestService service2 = factory.get(options2)
|
||||
|
||||
then:
|
||||
service !== service2
|
||||
service.example == "hello"
|
||||
service2.example == "world"
|
||||
|
||||
cleanup:
|
||||
factory.close()
|
||||
}
|
||||
|
||||
def "close service"() {
|
||||
given:
|
||||
def options = new TestServiceOptions(GradleTestUtil.mockProperty("hello"))
|
||||
def factory = new ScopedServiceFactory()
|
||||
|
||||
when:
|
||||
TestService service = factory.get(options)
|
||||
factory.close()
|
||||
|
||||
then:
|
||||
service.closed
|
||||
}
|
||||
|
||||
@InheritConstructors
|
||||
static class TestService extends Service<Options> implements Closeable {
|
||||
static ServiceType<TestService.Options, TestService> TYPE = new ServiceType(TestService.Options.class, TestService.class)
|
||||
|
||||
interface Options extends Service.Options {
|
||||
@Input
|
||||
Property<String> getExample();
|
||||
}
|
||||
|
||||
boolean closed = false
|
||||
|
||||
String getExample() {
|
||||
return options.example.get()
|
||||
}
|
||||
|
||||
@Override
|
||||
void close() throws Exception {
|
||||
closed = true
|
||||
}
|
||||
}
|
||||
|
||||
@TupleConstructor
|
||||
static class TestServiceOptions implements TestService.Options {
|
||||
Property<String> example
|
||||
Property<String> serviceClass = ServiceTestBase.serviceClassProperty(TestService.TYPE)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.test.unit.service
|
||||
|
||||
import org.gradle.api.provider.Property
|
||||
import spock.lang.Specification
|
||||
|
||||
import net.fabricmc.loom.test.util.GradleTestUtil
|
||||
import net.fabricmc.loom.util.newService.ScopedServiceFactory
|
||||
import net.fabricmc.loom.util.newService.Service
|
||||
import net.fabricmc.loom.util.newService.ServiceType
|
||||
|
||||
abstract class ServiceTestBase extends Specification {
|
||||
ScopedServiceFactory factory
|
||||
|
||||
def setup() {
|
||||
factory = new ScopedServiceFactory()
|
||||
}
|
||||
|
||||
def cleanup() {
|
||||
factory.close()
|
||||
factory = null
|
||||
}
|
||||
|
||||
static Property<String> serviceClassProperty(ServiceType<? extends Service.Options, ? extends Service> type) {
|
||||
return GradleTestUtil.mockProperty(type.serviceClass().name)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2024 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.test.unit.service
|
||||
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.provider.Property
|
||||
import org.intellij.lang.annotations.Language
|
||||
|
||||
import net.fabricmc.loom.task.service.NewMappingsService
|
||||
import net.fabricmc.loom.task.service.SourceRemapperService
|
||||
import net.fabricmc.loom.test.util.GradleTestUtil
|
||||
import net.fabricmc.loom.util.DeletingFileVisitor
|
||||
|
||||
class SourceRemapperServiceTest extends ServiceTestBase {
|
||||
def "remap sources"() {
|
||||
given:
|
||||
Path tempDirectory = Files.createTempDirectory("test")
|
||||
Path sourceDirectory = tempDirectory.resolve("source")
|
||||
Path destDirectory = tempDirectory.resolve("dst")
|
||||
Path mappings = tempDirectory.resolve("mappings.tiny")
|
||||
|
||||
Files.createDirectories(sourceDirectory)
|
||||
Files.createDirectories(destDirectory)
|
||||
Files.writeString(sourceDirectory.resolve("Source.java"), SOURCE)
|
||||
Files.writeString(mappings, MAPPINGS)
|
||||
|
||||
SourceRemapperService service = factory.get(new TestOptions(
|
||||
mappings: GradleTestUtil.mockProperty(
|
||||
new MappingsServiceTest.TestOptions(
|
||||
mappingsFile: GradleTestUtil.mockRegularFileProperty(mappings.toFile()),
|
||||
from: GradleTestUtil.mockProperty("named"),
|
||||
to: GradleTestUtil.mockProperty("intermediary"),
|
||||
)
|
||||
),
|
||||
))
|
||||
|
||||
when:
|
||||
service.remapSourcesJar(sourceDirectory, destDirectory)
|
||||
|
||||
then:
|
||||
// This isn't actually remapping, as we dont have the classpath setup at all. But that's not what we're testing here.
|
||||
!Files.readString(destDirectory.resolve("Source.java")).isEmpty()
|
||||
|
||||
cleanup:
|
||||
Files.walkFileTree(tempDirectory, new DeletingFileVisitor())
|
||||
}
|
||||
|
||||
@Language("java")
|
||||
static String SOURCE = """
|
||||
class Source {
|
||||
public void test() {
|
||||
System.out.println("Hello");
|
||||
}
|
||||
}
|
||||
""".trim()
|
||||
|
||||
// Tiny v2 mappings to rename println
|
||||
static String MAPPINGS = """
|
||||
tiny 2 0 intermediary named
|
||||
c Source Source
|
||||
m ()V println test
|
||||
""".trim()
|
||||
|
||||
static class TestOptions implements SourceRemapperService.Options {
|
||||
Property<NewMappingsService.Options> mappings
|
||||
Property<Integer> javaCompileRelease = GradleTestUtil.mockProperty(17)
|
||||
ConfigurableFileCollection classpath = GradleTestUtil.mockConfigurableFileCollection()
|
||||
Property<String> serviceClass = serviceClassProperty(SourceRemapperService.TYPE)
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,6 @@ import org.gradle.util.GradleVersion
|
||||
import spock.lang.Shared
|
||||
|
||||
import net.fabricmc.loom.test.LoomTestConstants
|
||||
import net.fabricmc.loom.util.Constants
|
||||
import net.fabricmc.loom.util.ZipUtils
|
||||
|
||||
trait GradleProjectTestTrait {
|
||||
@@ -332,9 +331,5 @@ trait GradleProjectTestTrait {
|
||||
}
|
||||
"""
|
||||
}
|
||||
|
||||
void enableMultiProjectOptimisation() {
|
||||
getGradleProperties() << "\n${Constants.Properties.MULTI_PROJECT_OPTIMISATION}=true"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ package net.fabricmc.loom.test.util
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFile
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
@@ -132,6 +133,12 @@ class GradleTestUtil {
|
||||
return mock
|
||||
}
|
||||
|
||||
static ConfigurableFileCollection mockConfigurableFileCollection(File... files) {
|
||||
def mock = mock(ConfigurableFileCollection.class)
|
||||
when(mock.getFiles()).thenReturn(Set.of(files))
|
||||
return mock
|
||||
}
|
||||
|
||||
static RepositoryHandler mockRepositoryHandler() {
|
||||
def mock = mock(RepositoryHandler.class)
|
||||
return mock
|
||||
|
||||
Reference in New Issue
Block a user