Merge remote-tracking branch 'FabricMC/dev/0.10' into dev/future

# Conflicts:
#	build.gradle
#	src/main/java/net/fabricmc/loom/LoomGradleExtension.java
#	src/main/java/net/fabricmc/loom/LoomRepositoryPlugin.java
#	src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java
#	src/main/java/net/fabricmc/loom/build/MixinRefmapHelper.java
#	src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java
#	src/main/java/net/fabricmc/loom/configuration/MavenPublication.java
#	src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java
#	src/main/java/net/fabricmc/loom/extension/MinecraftGradleExtension.java
#	src/main/java/net/fabricmc/loom/extension/MixinExtensionImpl.java
#	src/main/java/net/fabricmc/loom/task/RemapJarTask.java
#	src/main/java/net/fabricmc/loom/util/Constants.java
#	src/main/java/net/fabricmc/loom/util/SourceRemapper.java
#	src/test/groovy/net/fabricmc/loom/test/util/ProjectTestTrait.groovy
This commit is contained in:
shedaniel
2021-09-11 04:24:40 +08:00
80 changed files with 1391 additions and 901 deletions

2
.gitattributes vendored
View File

@@ -2,6 +2,8 @@
# and leave all files detected as binary untouched. # and leave all files detected as binary untouched.
* text=auto * text=auto
*.patch text eol=lf
# #
# The above will handle all files NOT found below # The above will handle all files NOT found below
# #

View File

@@ -48,6 +48,7 @@ repositories {
excludeGroupByRegex "org\\.eclipse\\.?.*" excludeGroupByRegex "org\\.eclipse\\.?.*"
} }
} }
mavenLocal()
} }
configurations { configurations {
@@ -74,8 +75,8 @@ dependencies {
// libraries // libraries
implementation ('commons-io:commons-io:2.8.0') implementation ('commons-io:commons-io:2.8.0')
implementation ('org.zeroturnaround:zt-zip:1.14') implementation ('org.zeroturnaround:zt-zip:1.14')
implementation ('com.google.code.gson:gson:2.8.7') implementation ('com.google.code.gson:gson:2.8.8')
implementation ('com.fasterxml.jackson.core:jackson-databind:2.12.4') implementation ('com.fasterxml.jackson.core:jackson-databind:2.12.5')
implementation ('com.google.guava:guava:30.1.1-jre') implementation ('com.google.guava:guava:30.1.1-jre')
implementation ('org.ow2.asm:asm:9.2') implementation ('org.ow2.asm:asm:9.2')
implementation ('org.ow2.asm:asm-analysis:9.2') implementation ('org.ow2.asm:asm-analysis:9.2')
@@ -148,9 +149,10 @@ dependencies {
testImplementation('org.spockframework:spock-core:2.0-groovy-3.0') { testImplementation('org.spockframework:spock-core:2.0-groovy-3.0') {
exclude module: 'groovy-all' exclude module: 'groovy-all'
} }
testImplementation 'io.javalin:javalin:3.13.9' testImplementation 'io.javalin:javalin:3.13.11'
testImplementation 'net.fabricmc:fabric-installer:0.7.4'
compileOnly 'org.jetbrains:annotations:21.0.1' compileOnly 'org.jetbrains:annotations:22.0.0'
} }
blossom { blossom {

View File

@@ -160,5 +160,10 @@
<module name="AtclauseOrder"> <module name="AtclauseOrder">
<property name="tagOrder" value="@param,@return,@throws,@deprecated"/> <property name="tagOrder" value="@param,@return,@throws,@deprecated"/>
</module> </module>
<!-- Prevent var for all cases other than new instance creation -->
<module name="MatchXpath">
<property name="query" value="//VARIABLE_DEF[./TYPE/IDENT[@text='var'] and not(./ASSIGN/EXPR/LITERAL_NEW)]"/>
</module>
</module> </module>
</module> </module>

View File

@@ -24,7 +24,7 @@ ruleset {
SpaceAfterSwitch SpaceAfterSwitch
SpaceAfterWhile SpaceAfterWhile
SpaceAroundClosureArrow SpaceAroundClosureArrow
SpaceAroundMapEntryColon SpaceAroundMapEntryColon(characterAfterColonRegex: /\ /)
SpaceAroundOperator SpaceAroundOperator
SpaceBeforeClosingBrace SpaceBeforeClosingBrace
SpaceBeforeOpeningBrace SpaceBeforeOpeningBrace
@@ -61,6 +61,13 @@ ruleset {
FieldTypeRequired FieldTypeRequired
MethodParameterTypeRequired MethodParameterTypeRequired
// Imports
UnusedImport
UnnecessaryGroovyImport
NoWildcardImports(ignoreStaticImports: true)
ImportFromSamePackage
DuplicateImport
//Misc //Misc
LongLiteralWithLowerCaseL LongLiteralWithLowerCaseL
} }

View File

@@ -50,7 +50,7 @@ import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider;
import net.fabricmc.loom.extension.LoomFiles; import net.fabricmc.loom.extension.LoomFiles;
import net.fabricmc.loom.extension.MixinApExtension; import net.fabricmc.loom.extension.MixinExtension;
public interface LoomGradleExtension extends LoomGradleExtensionAPI { public interface LoomGradleExtension extends LoomGradleExtensionAPI {
static LoomGradleExtension get(Project project) { static LoomGradleExtension get(Project project) {
@@ -109,7 +109,7 @@ public interface LoomGradleExtension extends LoomGradleExtensionAPI {
} }
@Override @Override
MixinApExtension getMixin(); MixinExtension getMixin();
// =================== // ===================
// Architectury Loom // Architectury Loom

View File

@@ -83,12 +83,12 @@ public class LoomGradlePlugin implements BootstrappedPlugin {
} }
// Apply default plugins // Apply default plugins
project.apply(ImmutableMap.of("plugin", "java")); project.apply(ImmutableMap.of("plugin", "java-library"));
project.apply(ImmutableMap.of("plugin", "eclipse")); project.apply(ImmutableMap.of("plugin", "eclipse"));
project.apply(ImmutableMap.of("plugin", "idea")); project.apply(ImmutableMap.of("plugin", "idea"));
// Setup extensions, minecraft wraps loom // Setup extensions, minecraft wraps loom
var extension = project.getExtensions().create(LoomGradleExtensionAPI.class, "loom", LoomGradleExtensionImpl.class, project, LoomFiles.create(project)); LoomGradleExtensionAPI extension = project.getExtensions().create(LoomGradleExtensionAPI.class, "loom", LoomGradleExtensionImpl.class, project, LoomFiles.create(project));
project.getExtensions().create(LoomGradleExtensionAPI.class, "minecraft", MinecraftGradleExtension.class, extension); project.getExtensions().create(LoomGradleExtensionAPI.class, "minecraft", MinecraftGradleExtension.class, extension);
project.getExtensions().create("fabricApi", FabricApiExtension.class, project); project.getExtensions().create("fabricApi", FabricApiExtension.class, project);

View File

@@ -38,6 +38,7 @@ import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import org.gradle.api.publish.maven.MavenPublication;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import net.fabricmc.loom.api.decompilers.LoomDecompiler; import net.fabricmc.loom.api.decompilers.LoomDecompiler;
@@ -160,11 +161,11 @@ public interface LoomGradleExtensionAPI {
NamedDomainObjectContainer<RunConfigSettings> getRunConfigs(); NamedDomainObjectContainer<RunConfigSettings> getRunConfigs();
@ApiStatus.Experimental void mixin(Action<MixinExtensionAPI> action);
void mixin(Action<MixinApExtensionAPI> action);
@ApiStatus.Experimental @ApiStatus.Experimental
MixinApExtensionAPI getMixin(); // TODO: move this from LoomGradleExtensionAPI to LoomGradleExtension once getRefmapName & setRefmapName is removed.
MixinExtensionAPI getMixin();
Property<String> getCustomMinecraftManifest(); Property<String> getCustomMinecraftManifest();
@@ -182,6 +183,35 @@ public interface LoomGradleExtensionAPI {
return getCustomMinecraftManifest().getOrNull(); return getCustomMinecraftManifest().getOrNull();
} }
/**
* If true, Loom will replace the {@code -dev} jars in the {@code *Elements} configurations
* with remapped outgoing variants.
*
* <p>Will only apply if {@link #getRemapArchives()} is also true.
*
* @return the property controlling the setup of remapped variants
*/
Property<Boolean> getSetupRemappedVariants();
/**
* Disables the deprecated POM generation for a publication.
* This is useful if you want to suppress deprecation warnings when you're not using software components.
*
* <p>Experimental API: Will be removed in Loom 0.12 together with the deprecated POM generation functionality.
*
* @param publication the maven publication
*/
@ApiStatus.Experimental
void disableDeprecatedPomGeneration(MavenPublication publication);
/**
* Reads the mod version from the fabric.mod.json file located in the main sourcesets resources.
* This is useful if you want to set the gradle version based of the version in the fabric.mod.json file.
*
* @return the version defined in the fabric.mod.json
*/
String getModVersion();
// =================== // ===================
// Architectury Loom // Architectury Loom
// =================== // ===================

View File

@@ -31,7 +31,9 @@ import org.gradle.api.tasks.util.PatternSet;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Experimental @ApiStatus.Experimental
public interface MixinApExtensionAPI { public interface MixinExtensionAPI {
Property<Boolean> getUseLegacyMixinAp();
Property<String> getDefaultRefmapName(); Property<String> getDefaultRefmapName();
/** /**
@@ -45,27 +47,27 @@ public interface MixinApExtensionAPI {
void add(SourceSet sourceSet, String refmapName, Action<PatternSet> action); void add(SourceSet sourceSet, String refmapName, Action<PatternSet> action);
/** /**
* Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. * Apply Mixin AP to sourceSet. See {@link MixinExtensionAPI#add(SourceSet, String, Action)} for more detail.
* @param sourceSet the sourceSet that applies Mixin AP. * @param sourceSet the sourceSet that applies Mixin AP.
* @param refmapName the output ref-map name. * @param refmapName the output ref-map name.
*/ */
void add(SourceSet sourceSet, String refmapName); void add(SourceSet sourceSet, String refmapName);
/** /**
* Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. * Apply Mixin AP to sourceSet. See {@link MixinExtensionAPI#add(SourceSet, String, Action)} for more detail.
* @param sourceSet the sourceSet that applies Mixin AP. * @param sourceSet the sourceSet that applies Mixin AP.
* @param action used for filter the mixin json files. * @param action used for filter the mixin json files.
*/ */
void add(SourceSet sourceSet, Action<PatternSet> action); void add(SourceSet sourceSet, Action<PatternSet> action);
/** /**
* Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. * Apply Mixin AP to sourceSet. See {@link MixinExtensionAPI#add(SourceSet, String, Action)} for more detail.
* @param sourceSet the sourceSet that applies Mixin AP. * @param sourceSet the sourceSet that applies Mixin AP.
*/ */
void add(SourceSet sourceSet); void add(SourceSet sourceSet);
/** /**
* Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. * Apply Mixin AP to sourceSet. See {@link MixinExtensionAPI#add(SourceSet, String, Action)} for more detail.
* @param sourceSetName the name of sourceSet that applies Mixin AP. * @param sourceSetName the name of sourceSet that applies Mixin AP.
* @param refmapName the output ref-map name. * @param refmapName the output ref-map name.
* @param action used for filter the mixin json files. * @param action used for filter the mixin json files.
@@ -73,21 +75,21 @@ public interface MixinApExtensionAPI {
void add(String sourceSetName, String refmapName, Action<PatternSet> action); void add(String sourceSetName, String refmapName, Action<PatternSet> action);
/** /**
* Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. * Apply Mixin AP to sourceSet. See {@link MixinExtensionAPI#add(SourceSet, String, Action)} for more detail.
* @param sourceSetName the name of sourceSet that applies Mixin AP. * @param sourceSetName the name of sourceSet that applies Mixin AP.
* @param refmapName the output ref-map name. * @param refmapName the output ref-map name.
*/ */
void add(String sourceSetName, String refmapName); void add(String sourceSetName, String refmapName);
/** /**
* Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. * Apply Mixin AP to sourceSet. See {@link MixinExtensionAPI#add(SourceSet, String, Action)} for more detail.
* @param sourceSetName the name of sourceSet that applies Mixin AP. * @param sourceSetName the name of sourceSet that applies Mixin AP.
* @param action used for filter the mixin json files. * @param action used for filter the mixin json files.
*/ */
void add(String sourceSetName, Action<PatternSet> action); void add(String sourceSetName, Action<PatternSet> action);
/** /**
* Apply Mixin AP to sourceSet. See {@link MixinApExtensionAPI#add(SourceSet, String, Action)} for more detail. * Apply Mixin AP to sourceSet. See {@link MixinExtensionAPI#add(SourceSet, String, Action)} for more detail.
* @param sourceSetName the name of sourceSet that applies Mixin AP. * @param sourceSetName the name of sourceSet that applies Mixin AP.
*/ */
void add(String sourceSetName); void add(String sourceSetName);

View File

@@ -48,7 +48,7 @@ import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.extension.MixinApExtension; import net.fabricmc.loom.extension.MixinExtension;
public final class MixinRefmapHelper { public final class MixinRefmapHelper {
private MixinRefmapHelper() { } private MixinRefmapHelper() { }
@@ -57,14 +57,14 @@ public final class MixinRefmapHelper {
public static boolean addRefmapName(Project project, Path outputPath) { public static boolean addRefmapName(Project project, Path outputPath) {
try { try {
MixinApExtension mixin = LoomGradleExtension.get(project).getMixin(); MixinExtension mixin = LoomGradleExtension.get(project).getMixin();
File output = outputPath.toFile(); File output = outputPath.toFile();
Collection<String> allMixinConfigs = getMixinConfigurationFiles(readFabricModJson(output)); Collection<String> allMixinConfigs = getMixinConfigurationFiles(readFabricModJson(output));
return mixin.getMixinSourceSetsStream().map(sourceSet -> { return mixin.getMixinSourceSetsStream().map(sourceSet -> {
MixinApExtension.MixinInformationContainer container = Objects.requireNonNull( MixinExtension.MixinInformationContainer container = Objects.requireNonNull(
MixinApExtension.getMixinInformationContainer(sourceSet) MixinExtension.getMixinInformationContainer(sourceSet)
); );
Stream<String> mixinConfigs = sourceSet.getResources() Stream<String> mixinConfigs = sourceSet.getResources()
@@ -113,7 +113,7 @@ public final class MixinRefmapHelper {
JsonArray mixins = fabricModJson.getAsJsonArray("mixins"); JsonArray mixins = fabricModJson.getAsJsonArray("mixins");
if (mixins == null) { if (mixins == null) {
return Collections.emptySet(); return Collections.emptyList();
} }
return StreamSupport.stream(mixins.spliterator(), false) return StreamSupport.stream(mixins.spliterator(), false)

View File

@@ -39,7 +39,7 @@ import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import net.fabricmc.loom.extension.MixinApExtension; import net.fabricmc.loom.extension.MixinExtension;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
@@ -65,7 +65,7 @@ public abstract class AnnotationProcessorInvoker<T extends Task> {
} }
protected static Collection<Configuration> getApConfigurations(Project project, Function<String, String> getApConfigNameFunc) { protected static Collection<Configuration> getApConfigurations(Project project, Function<String, String> getApConfigNameFunc) {
MixinApExtension mixin = LoomGradleExtension.get(project).getMixin(); MixinExtension mixin = LoomGradleExtension.get(project).getMixin();
return mixin.getApConfigurationsStream(getApConfigNameFunc).collect(Collectors.toList()); return mixin.getApConfigurationsStream(getApConfigNameFunc).collect(Collectors.toList());
} }
@@ -80,7 +80,7 @@ public abstract class AnnotationProcessorInvoker<T extends Task> {
private void passMixinArguments(T task, SourceSet sourceSet) { private void passMixinArguments(T task, SourceSet sourceSet) {
try { try {
LoomGradleExtension loom = LoomGradleExtension.get(project); LoomGradleExtension loom = LoomGradleExtension.get(project);
String refmapName = Objects.requireNonNull(MixinApExtension.getMixinInformationContainer(sourceSet)).refmapNameProvider().get(); String refmapName = Objects.requireNonNull(MixinExtension.getMixinInformationContainer(sourceSet)).refmapNameProvider().get();
Map<String, String> args = new HashMap<>() {{ Map<String, String> args = new HashMap<>() {{
put(Constants.MixinArguments.IN_MAP_FILE_NAMED_INTERMEDIARY, loom.getMappingsProvider().tinyMappings.toFile().getCanonicalPath()); put(Constants.MixinArguments.IN_MAP_FILE_NAMED_INTERMEDIARY, loom.getMappingsProvider().tinyMappings.toFile().getCanonicalPath());
put(Constants.MixinArguments.OUT_MAP_FILE_NAMED_INTERMEDIARY, loom.getNextMixinMappings().getCanonicalPath()); put(Constants.MixinArguments.OUT_MAP_FILE_NAMED_INTERMEDIARY, loom.getNextMixinMappings().getCanonicalPath());

View File

@@ -35,7 +35,7 @@ import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.compile.JavaCompile; import org.gradle.api.tasks.compile.JavaCompile;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.extension.MixinApExtension; import net.fabricmc.loom.extension.MixinExtension;
public class JavaApInvoker extends AnnotationProcessorInvoker<JavaCompile> { public class JavaApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
public JavaApInvoker(Project project) { public JavaApInvoker(Project project) {
@@ -46,7 +46,7 @@ public class JavaApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
} }
private static Map<SourceSet, JavaCompile> getInvokerTasks(Project project) { private static Map<SourceSet, JavaCompile> getInvokerTasks(Project project) {
MixinApExtension mixin = LoomGradleExtension.get(project).getMixin(); MixinExtension mixin = LoomGradleExtension.get(project).getMixin();
return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.JAVA) return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.JAVA)
.collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((JavaCompile) entry.getValue()))); .collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((JavaCompile) entry.getValue())));
} }

View File

@@ -40,7 +40,7 @@ import org.gradle.api.tasks.compile.JavaCompile;
import org.jetbrains.kotlin.gradle.plugin.KaptExtension; import org.jetbrains.kotlin.gradle.plugin.KaptExtension;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.extension.MixinApExtension; import net.fabricmc.loom.extension.MixinExtension;
public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> { public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
private final KaptExtension kaptExtension = project.getExtensions().getByType(KaptExtension.class); private final KaptExtension kaptExtension = project.getExtensions().getByType(KaptExtension.class);
@@ -66,7 +66,7 @@ public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
} }
private static Map<SourceSet, JavaCompile> getInvokerTasks(Project project) { private static Map<SourceSet, JavaCompile> getInvokerTasks(Project project) {
MixinApExtension mixin = LoomGradleExtension.get(project).getMixin(); MixinExtension mixin = LoomGradleExtension.get(project).getMixin();
return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.JAVA) return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.JAVA)
.collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((JavaCompile) entry.getValue()))); .collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((JavaCompile) entry.getValue())));
} }
@@ -82,7 +82,7 @@ public class KaptApInvoker extends AnnotationProcessorInvoker<JavaCompile> {
SourceSet sourceSet = entry.getKey(); SourceSet sourceSet = entry.getKey();
task.doLast(t -> { task.doLast(t -> {
try { try {
String refmapName = Objects.requireNonNull(MixinApExtension.getMixinInformationContainer(sourceSet)).refmapNameProvider().get(); String refmapName = Objects.requireNonNull(MixinExtension.getMixinInformationContainer(sourceSet)).refmapNameProvider().get();
Path src = Paths.get(getRefmapDestination(task, refmapName)); Path src = Paths.get(getRefmapDestination(task, refmapName));
Path dest = Paths.get(task.getDestinationDir().toString(), refmapName); Path dest = Paths.get(task.getDestinationDir().toString(), refmapName);

View File

@@ -35,7 +35,7 @@ import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.scala.ScalaCompile; import org.gradle.api.tasks.scala.ScalaCompile;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.extension.MixinApExtension; import net.fabricmc.loom.extension.MixinExtension;
public class ScalaApInvoker extends AnnotationProcessorInvoker<ScalaCompile> { public class ScalaApInvoker extends AnnotationProcessorInvoker<ScalaCompile> {
public ScalaApInvoker(Project project) { public ScalaApInvoker(Project project) {
@@ -47,7 +47,7 @@ public class ScalaApInvoker extends AnnotationProcessorInvoker<ScalaCompile> {
} }
private static Map<SourceSet, ScalaCompile> getInvokerTasks(Project project) { private static Map<SourceSet, ScalaCompile> getInvokerTasks(Project project) {
MixinApExtension mixin = LoomGradleExtension.get(project).getMixin(); MixinExtension mixin = LoomGradleExtension.get(project).getMixin();
return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.SCALA) return mixin.getInvokerTasksStream(AnnotationProcessorInvoker.SCALA)
.collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((ScalaCompile) entry.getValue()))); .collect(Collectors.toMap(Map.Entry::getKey, entry -> Objects.requireNonNull((ScalaCompile) entry.getValue())));
} }

View File

@@ -43,6 +43,7 @@ import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.DependencySet; import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.ProjectDependency; import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.artifacts.ResolvedConfiguration; import org.gradle.api.artifacts.ResolvedConfiguration;
import org.gradle.api.artifacts.ResolvedDependency; import org.gradle.api.artifacts.ResolvedDependency;
import org.gradle.api.tasks.bundling.AbstractArchiveTask; import org.gradle.api.tasks.bundling.AbstractArchiveTask;
@@ -133,7 +134,7 @@ public final class NestedDependencyProvider implements NestedJarProvider {
continue; continue;
} }
for (var artifact : dependency.getModuleArtifacts()) { for (ResolvedArtifact artifact : dependency.getModuleArtifacts()) {
fileList.add(new DependencyInfo<>( fileList.add(new DependencyInfo<>(
dependency, dependency,
new ResolvedDependencyMetaExtractor(), new ResolvedDependencyMetaExtractor(),

View File

@@ -25,14 +25,12 @@
package net.fabricmc.loom.configuration; package net.fabricmc.loom.configuration;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.javadoc.Javadoc; import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.jvm.tasks.Jar; import org.gradle.jvm.tasks.Jar;
import net.fabricmc.loom.extension.MixinApExtension;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.build.mixin.JavaApInvoker; import net.fabricmc.loom.build.mixin.JavaApInvoker;
import net.fabricmc.loom.build.mixin.KaptApInvoker; import net.fabricmc.loom.build.mixin.KaptApInvoker;
@@ -48,6 +46,7 @@ import net.fabricmc.loom.configuration.providers.forge.McpConfigProvider;
import net.fabricmc.loom.configuration.providers.forge.PatchProvider; import net.fabricmc.loom.configuration.providers.forge.PatchProvider;
import net.fabricmc.loom.configuration.providers.forge.SrgProvider; import net.fabricmc.loom.configuration.providers.forge.SrgProvider;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.extension.MixinExtension;
import net.fabricmc.loom.task.GenVsCodeProjectTask; import net.fabricmc.loom.task.GenVsCodeProjectTask;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
@@ -56,7 +55,6 @@ public final class CompileConfiguration {
} }
public static void setupConfigurations(Project project) { public static void setupConfigurations(Project project) {
final ConfigurationContainer configurations = project.getConfigurations();
LoomGradleExtension extension = LoomGradleExtension.get(project); LoomGradleExtension extension = LoomGradleExtension.get(project);
project.afterEvaluate(project1 -> { project.afterEvaluate(project1 -> {
@@ -121,11 +119,18 @@ public final class CompileConfiguration {
extension.createLazyConfiguration(entry.getRemappedConfiguration()) extension.createLazyConfiguration(entry.getRemappedConfiguration())
.configure(configuration -> configuration.setTransitive(false)); .configure(configuration -> configuration.setTransitive(false));
extendsFrom(entry.getTargetConfiguration(configurations), entry.getRemappedConfiguration(), project); if (entry.compileClasspath()) {
if (entry.isOnModCompileClasspath()) {
extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH, entry.sourceConfiguration(), project); extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH, entry.sourceConfiguration(), project);
extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration(), project); extendsFrom(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED, entry.getRemappedConfiguration(), project);
extendsFrom(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME, entry.getRemappedConfiguration(), project);
}
if (entry.runtimeClasspath()) {
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, entry.getRemappedConfiguration(), project);
}
if (entry.hasConsumerConfiguration()) {
extendsFrom(entry.consumerConfiguration(), entry.sourceConfiguration(), project);
} }
} }
@@ -137,7 +142,7 @@ public final class CompileConfiguration {
extendsFrom(Constants.Configurations.LOADER_DEPENDENCIES, Constants.Configurations.MINECRAFT_DEPENDENCIES, project); extendsFrom(Constants.Configurations.LOADER_DEPENDENCIES, Constants.Configurations.MINECRAFT_DEPENDENCIES, project);
extendsFrom(Constants.Configurations.MINECRAFT_NAMED, Constants.Configurations.LOADER_DEPENDENCIES, project); extendsFrom(Constants.Configurations.MINECRAFT_NAMED, Constants.Configurations.LOADER_DEPENDENCIES, project);
extendsFrom(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, Constants.Configurations.MAPPINGS_FINAL, project); extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.MAPPINGS_FINAL, project);
extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, project); extendsFrom(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, project);
extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, project); extendsFrom(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME, Constants.Configurations.LOOM_DEVELOPMENT_DEPENDENCIES, project);
@@ -195,25 +200,10 @@ public final class CompileConfiguration {
extension.getUnmappedModCollection().from(jarTask); extension.getUnmappedModCollection().from(jarTask);
} }
// Disable some things used by log4j via the mixin AP that prevent it from being garbage collected MixinExtension mixin = LoomGradleExtension.get(project).getMixin();
System.setProperty("log4j2.disable.jmx", "true");
System.setProperty("log4j.shutdownHookEnabled", "false");
System.setProperty("log4j.skipJansi", "true");
project.getLogger().info("Configuring compiler arguments for Java"); if (mixin.getUseLegacyMixinAp().get()) {
MixinApExtension mixinApExtension = LoomGradleExtension.get(project).getMixin(); setupMixinAp(project, mixin);
mixinApExtension.init();
new JavaApInvoker(project).configureMixin();
if (project.getPluginManager().hasPlugin("scala")) {
project.getLogger().info("Configuring compiler arguments for Scala");
new ScalaApInvoker(project).configureMixin();
}
if (project.getPluginManager().hasPlugin("org.jetbrains.kotlin.kapt")) {
project.getLogger().info("Configuring compiler arguments for Kapt plugin");
new KaptApInvoker(project).configureMixin();
} }
}); });
@@ -223,6 +213,29 @@ public final class CompileConfiguration {
} }
} }
private static void setupMixinAp(Project project, MixinExtension mixin) {
mixin.init();
// Disable some things used by log4j via the mixin AP that prevent it from being garbage collected
System.setProperty("log4j2.disable.jmx", "true");
System.setProperty("log4j.shutdownHookEnabled", "false");
System.setProperty("log4j.skipJansi", "true");
project.getLogger().info("Configuring compiler arguments for Java");
new JavaApInvoker(project).configureMixin();
if (project.getPluginManager().hasPlugin("scala")) {
project.getLogger().info("Configuring compiler arguments for Scala");
new ScalaApInvoker(project).configureMixin();
}
if (project.getPluginManager().hasPlugin("org.jetbrains.kotlin.kapt")) {
project.getLogger().info("Configuring compiler arguments for Kapt plugin");
new KaptApInvoker(project).configureMixin();
}
}
private static void extendsFrom(String a, String b, Project project) { private static void extendsFrom(String a, String b, Project project) {
project.getConfigurations().getByName(a, configuration -> configuration.extendsFrom(project.getConfigurations().getByName(b))); project.getConfigurations().getByName(a, configuration -> configuration.extendsFrom(project.getConfigurations().getByName(b)));
} }

View File

@@ -30,6 +30,7 @@ import java.util.jar.Manifest;
import dev.architectury.tinyremapper.TinyRemapper; import dev.architectury.tinyremapper.TinyRemapper;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.artifacts.Dependency;
import org.gradle.util.GradleVersion; import org.gradle.util.GradleVersion;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
@@ -46,7 +47,7 @@ public final record JarManifestConfiguration(Project project) {
LoomGradleExtension extension = LoomGradleExtension.get(project); LoomGradleExtension extension = LoomGradleExtension.get(project);
Attributes attributes = manifest.getMainAttributes(); Attributes attributes = manifest.getMainAttributes();
var tinyRemapperVersion = Optional.ofNullable(TinyRemapper.class.getPackage().getImplementationVersion()); Optional<String> tinyRemapperVersion = Optional.ofNullable(TinyRemapper.class.getPackage().getImplementationVersion());
attributes.putValue("Fabric-Gradle-Version", GradleVersion.current().getVersion()); attributes.putValue("Fabric-Gradle-Version", GradleVersion.current().getVersion());
attributes.putValue("Fabric-Loom-Version", LoomGradlePlugin.LOOM_VERSION); attributes.putValue("Fabric-Loom-Version", LoomGradlePlugin.LOOM_VERSION);
@@ -63,7 +64,7 @@ public final record JarManifestConfiguration(Project project) {
private void addMixinVersion(Attributes attributes) { private void addMixinVersion(Attributes attributes) {
// Not super ideal that this uses the mod compile classpath, should prob look into making this not a thing at somepoint // Not super ideal that this uses the mod compile classpath, should prob look into making this not a thing at somepoint
var dependency = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES) Optional<Dependency> dependency = project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES)
.getDependencies() .getDependencies()
.stream() .stream()
.filter(dep -> "sponge-mixin".equals(dep.getName())) .filter(dep -> "sponge-mixin".equals(dep.getName()))

View File

@@ -25,7 +25,6 @@
package net.fabricmc.loom.configuration; package net.fabricmc.loom.configuration;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -171,15 +170,7 @@ public class LoomDependencyManager {
ModCompileRemapper.remapDependencies(project, mappingsIdentifier, extension, sourceRemapper); ModCompileRemapper.remapDependencies(project, mappingsIdentifier, extension, sourceRemapper);
long start = System.currentTimeMillis(); sourceRemapper.remapAll();
try {
sourceRemapper.remapAll();
} catch (IOException exception) {
throw new RuntimeException("Failed to remap mod sources", exception);
}
project.getLogger().info("Source remapping took: %dms".formatted(System.currentTimeMillis() - start));
for (Runnable runnable : afterTasks) { for (Runnable runnable : afterTasks) {
runnable.run(); runnable.run();
@@ -200,7 +191,8 @@ public class LoomDependencyManager {
modDep.setTransitive(false); modDep.setTransitive(false);
loaderDepsConfig.getDependencies().add(modDep); loaderDepsConfig.getDependencies().add(modDep);
if (!extension.ideSync()) { // TODO: work around until https://github.com/FabricMC/Mixin/pull/60 and https://github.com/FabricMC/fabric-mixin-compile-extensions/issues/14 is fixed.
if (!extension.ideSync() && extension.getMixin().getUseLegacyMixinAp().get()) {
apDepsConfig.getDependencies().add(modDep); apDepsConfig.getDependencies().add(modDep);
} }

View File

@@ -24,9 +24,14 @@
package net.fabricmc.loom.configuration; package net.fabricmc.loom.configuration;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import groovy.util.Node; import groovy.util.Node;
import org.gradle.api.Project; import org.gradle.api.Project;
@@ -35,48 +40,70 @@ import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.ExcludeRule; import org.gradle.api.artifacts.ExcludeRule;
import org.gradle.api.artifacts.ModuleDependency; import org.gradle.api.artifacts.ModuleDependency;
import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logger;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.publish.Publication; import org.gradle.api.publish.Publication;
import org.gradle.api.publish.PublishingExtension; import org.gradle.api.publish.PublishingExtension;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.util.DeprecationHelper;
import net.fabricmc.loom.util.GroovyXmlUtil; import net.fabricmc.loom.util.GroovyXmlUtil;
public final class MavenPublication { public final class MavenPublication {
private static final Map<String, String> CONFIGURATION_TO_SCOPE = Map.of(
JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME, "compile",
JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME, "runtime"
);
private static final Set<Publication> EXCLUDED_PUBLICATIONS = Collections.newSetFromMap(new WeakHashMap<>());
private MavenPublication() { private MavenPublication() {
} }
public static void configure(Project project) { public static void configure(Project project) {
project.afterEvaluate((p) -> { project.afterEvaluate((p) -> {
// add modsCompile to maven-publish AtomicBoolean reportedDeprecation = new AtomicBoolean(false);
PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class);
if (mavenPublish == null) { CONFIGURATION_TO_SCOPE.forEach((configurationName, scope) -> {
p.getLogger().info("No maven publications for project [" + p.getName() + "], skipping configuration."); Configuration config = p.getConfigurations().getByName(configurationName);
return;
}
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { // add modsCompile to maven-publish
if (!entry.hasMavenScope()) { PublishingExtension mavenPublish = p.getExtensions().findByType(PublishingExtension.class);
continue;
if (mavenPublish != null) {
p.getLogger().info("Processing maven publication for project [" + p.getName() + "] of " + entry.sourceConfiguration());
processEntry(project, scope, config, mavenPublish, reportedDeprecation);
} }
});
Configuration compileModsConfig = p.getConfigurations().getByName(entry.sourceConfiguration());
p.getLogger().info("Processing maven publication for project [" + p.getName() + "] of " + entry.sourceConfiguration());
processEntry(p.getLogger(), entry, compileModsConfig, mavenPublish);
}
}); });
} }
private static void processEntry(Logger logger, RemappedConfigurationEntry entry, Configuration compileModsConfig, PublishingExtension mavenPublish) { private static boolean hasSoftwareComponent(Publication publication) {
try {
Method getComponent = publication.getClass().getMethod("getComponent");
return getComponent.invoke(publication) != null;
} catch (ReflectiveOperationException e) {
// our hacks have broken!
return false;
}
}
// TODO: Remove this in Loom 0.12
private static void processEntry(Project project, String scope, Configuration config, PublishingExtension mavenPublish, AtomicBoolean reportedDeprecation) {
mavenPublish.publications((publications) -> { mavenPublish.publications((publications) -> {
for (Publication publication : publications) { for (Publication publication : publications) {
if (!(publication instanceof org.gradle.api.publish.maven.MavenPublication)) { if (!(publication instanceof org.gradle.api.publish.maven.MavenPublication mavenPublication)) {
continue; continue;
} }
logger.info("Processing maven publication [" + publication.getName() + "]"); if (hasSoftwareComponent(publication) || EXCLUDED_PUBLICATIONS.contains(publication)) {
((org.gradle.api.publish.maven.MavenPublication) publication).pom((pom) -> pom.withXml((xml) -> { continue;
} else if (!reportedDeprecation.get()) {
DeprecationHelper deprecationHelper = LoomGradleExtension.get(project).getDeprecationHelper();
deprecationHelper.warn("Loom is applying dependency data manually to publications instead of using a software component (from(components[\"java\"])). This is deprecated and will be removed in Loom 0.12.");
reportedDeprecation.set(true);
}
project.getLogger().info("Processing maven publication [" + publication.getName() + "]");
mavenPublication.pom((pom) -> pom.withXml((xml) -> {
Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies"); Node dependencies = GroovyXmlUtil.getOrCreateNode(xml.asNode(), "dependencies");
Set<String> foundArtifacts = new HashSet<>(); Set<String> foundArtifacts = new HashSet<>();
@@ -89,7 +116,7 @@ public final class MavenPublication {
} }
}); });
for (Dependency dependency : compileModsConfig.getAllDependencies()) { for (Dependency dependency : config.getAllDependencies()) {
if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) { if (foundArtifacts.contains(dependency.getGroup() + ":" + dependency.getName())) {
logger.info("Found inserted artifact " + dependency.getGroup() + ":" + dependency.getName()); logger.info("Found inserted artifact " + dependency.getGroup() + ":" + dependency.getName());
continue; continue;
@@ -101,7 +128,7 @@ public final class MavenPublication {
depNode.appendNode("groupId", dependency.getGroup()); depNode.appendNode("groupId", dependency.getGroup());
depNode.appendNode("artifactId", dependency.getName()); depNode.appendNode("artifactId", dependency.getName());
depNode.appendNode("version", dependency.getVersion()); depNode.appendNode("version", dependency.getVersion());
depNode.appendNode("scope", entry.mavenScope()); depNode.appendNode("scope", scope);
if (!(dependency instanceof ModuleDependency)) { if (!(dependency instanceof ModuleDependency)) {
continue; continue;
@@ -125,4 +152,8 @@ public final class MavenPublication {
} }
}); });
} }
public static void excludePublication(Publication publication) {
EXCLUDED_PUBLICATIONS.add(publication);
}
} }

View File

@@ -32,6 +32,9 @@ import org.gradle.api.Action;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.UnknownTaskException; import org.gradle.api.UnknownTaskException;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.PublishArtifact;
import org.gradle.api.artifacts.dsl.ArtifactHandler;
import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.tasks.bundling.AbstractArchiveTask; import org.gradle.api.tasks.bundling.AbstractArchiveTask;
@@ -58,6 +61,40 @@ public class RemapConfiguration {
public static void setupDefaultRemap(Project project) { public static void setupDefaultRemap(Project project) {
setupRemap(project, true, DEFAULT_JAR_TASK_NAME, DEFAULT_SOURCES_JAR_TASK_NAME, DEFAULT_REMAP_JAR_TASK_NAME, DEFAULT_REMAP_SOURCES_JAR_TASK_NAME, DEFAULT_REMAP_ALL_JARS_TASK_NAME, DEFAULT_REMAP_ALL_SOURCES_TASK_NAME); setupRemap(project, true, DEFAULT_JAR_TASK_NAME, DEFAULT_SOURCES_JAR_TASK_NAME, DEFAULT_REMAP_JAR_TASK_NAME, DEFAULT_REMAP_SOURCES_JAR_TASK_NAME, DEFAULT_REMAP_ALL_JARS_TASK_NAME, DEFAULT_REMAP_ALL_SOURCES_TASK_NAME);
LoomGradleExtension extension = LoomGradleExtension.get(project);
extension.getSetupRemappedVariants().finalizeValue();
if (extension.getSetupRemappedVariants().get()) {
ArtifactHandler artifacts = project.getArtifacts();
project.getTasks().named(DEFAULT_REMAP_JAR_TASK_NAME, task -> {
artifacts.add(JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME, task);
artifacts.add(JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME, task);
});
project.getTasks().named(DEFAULT_REMAP_SOURCES_JAR_TASK_NAME, RemapSourcesJarTask.class, task -> {
if (!project.getConfigurations().getNames().contains(JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME)) {
// Sources jar may not have been created with withSourcesJar
return;
}
PublishArtifact artifact = artifacts.add(JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME, task.getOutput());
// Remove the existing artifact that does not run remapSourcesJar.
// It doesn't seem to hurt, but I'm not sure if the file-level duplicates cause issues.
Configuration configuration = project.getConfigurations().getByName(JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME);
configuration.getArtifacts().removeIf(a -> a != artifact && artifact.getFile().equals(a.getFile()));
});
// Remove -dev jars from the default jar task
for (String configurationName : new String[] { JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME, JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME }) {
Configuration configuration = project.getConfigurations().getByName(configurationName);
configuration.getArtifacts().removeIf(artifact -> {
Task jarTask = project.getTasks().getByName(DEFAULT_JAR_TASK_NAME);
// if the artifact is a -dev jar and "builtBy jar"
return "dev".equals(artifact.getClassifier()) && artifact.getBuildDependencies().getDependencies(null).contains(jarTask);
});
}
}
} }
@ApiStatus.Experimental // This is only an api if you squint really hard, expect it to explode every 5 mins. If you must call in afterEvaluate on all projects @ApiStatus.Experimental // This is only an api if you squint really hard, expect it to explode every 5 mins. If you must call in afterEvaluate on all projects
@@ -128,6 +165,7 @@ public class RemapConfiguration {
rootProject.getTasks().register(remapAllSourcesTaskName, RemapAllSourcesTask.class, task -> { rootProject.getTasks().register(remapAllSourcesTaskName, RemapAllSourcesTask.class, task -> {
task.sourceRemapper = sourceRemapper; task.sourceRemapper = sourceRemapper;
task.doLast(t -> sourceRemapper.remapAll());
}); });
parentTask = rootProject.getTasks().getByName(remapAllSourcesTaskName); parentTask = rootProject.getTasks().getByName(remapAllSourcesTaskName);

View File

@@ -28,13 +28,13 @@ import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPlugin;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public record RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope, @Nullable String replacedWith) { public record RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean compileClasspath, boolean runtimeClasspath, String consumerConfiguration, @Nullable String replacedWith) {
public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean isOnModCompileClasspath, String mavenScope) { public RemappedConfigurationEntry(String sourceConfiguration, String targetConfiguration, boolean compileClasspath, boolean runtimeClasspath, String consumerConfiguration) {
this(sourceConfiguration, targetConfiguration, isOnModCompileClasspath, mavenScope, null); this(sourceConfiguration, targetConfiguration, compileClasspath, runtimeClasspath, consumerConfiguration, null);
} }
public boolean hasMavenScope() { public boolean hasConsumerConfiguration() {
return mavenScope != null && !mavenScope.isEmpty(); return consumerConfiguration != null && !consumerConfiguration.isEmpty();
} }
public String getRemappedConfiguration() { public String getRemappedConfiguration() {

View File

@@ -0,0 +1,76 @@
/*
* 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.configuration.mods;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import com.google.gson.JsonObject;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPluginConvention;
import net.fabricmc.loom.LoomGradlePlugin;
public class ModVersionParser {
private final Project project;
private String version = null;
public ModVersionParser(Project project) {
this.project = project;
}
public String getModVersion() {
if (version != null) {
return version;
}
File json = locateModJsonFile();
JsonObject jsonObject;
try (var reader = new FileReader(json)) {
jsonObject = LoomGradlePlugin.GSON.fromJson(reader, JsonObject.class);
} catch (IOException e) {
throw new RuntimeException("Failed to read fabric.mod.json file");
}
if (!jsonObject.has("version") || !jsonObject.get("version").isJsonPrimitive()) {
throw new UnsupportedOperationException("Could not find valid version in the fabric.mod.json file");
}
version = jsonObject.get("version").getAsString();
return version;
}
private File locateModJsonFile() {
return project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets()
.getByName("main")
.getResources()
.matching(patternFilterable -> patternFilterable.include("fabric.mod.json"))
.getSingleFile();
}
}

View File

@@ -56,7 +56,7 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider {
if (jarProcessorManager.isInvalid(projectMappedJar) || isRefreshDeps() || isForgeAtDirty) { if (jarProcessorManager.isInvalid(projectMappedJar) || isRefreshDeps() || isForgeAtDirty) {
getProject().getLogger().info(":processing mapped jar"); getProject().getLogger().info(":processing mapped jar");
invalidateJars(); invalidateJar();
try { try {
FileUtils.copyFile(super.getMappedJar(), projectMappedJar); FileUtils.copyFile(super.getMappedJar(), projectMappedJar);
@@ -71,16 +71,14 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider {
getProject().getDependencies().module("net.minecraft:minecraft-" + projectMappedClassifier + ":" + getMinecraftProvider().minecraftVersion() + "/" + getExtension().getMappingsProvider().mappingsIdentifier())); getProject().getDependencies().module("net.minecraft:minecraft-" + projectMappedClassifier + ":" + getMinecraftProvider().minecraftVersion() + "/" + getExtension().getMappingsProvider().mappingsIdentifier()));
} }
private void invalidateJars() { private void invalidateJar() {
File dir = projectMappedJar.getParentFile(); if (projectMappedJar.exists()) {
getProject().getLogger().warn("Invalidating project jar");
if (dir.exists()) {
getProject().getLogger().warn("Invalidating project jars");
try { try {
FileUtils.cleanDirectory(dir); FileUtils.forceDelete(projectMappedJar);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("Failed to invalidate jars, try stopping gradle daemon or closing the game", e); throw new RuntimeException("Failed to invalidate jar, try stopping gradle daemon or closing the game", e);
} }
} }
} }

View File

@@ -40,6 +40,7 @@ import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.logging.configuration.ConsoleOutput;
import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPlugin;
import net.fabricmc.loom.configuration.DependencyProvider; import net.fabricmc.loom.configuration.DependencyProvider;
@@ -120,10 +121,13 @@ public class LaunchProvider extends DependencyProvider {
} }
} }
//Enable ansi by default for idea and vscode final boolean plainConsole = getProject().getGradle().getStartParameter().getConsoleOutput() == ConsoleOutput.Plain;
if (new File(getProject().getRootDir(), ".vscode").exists() final boolean ansiSupportedIDE = new File(getProject().getRootDir(), ".vscode").exists()
|| new File(getProject().getRootDir(), ".idea").exists() || new File(getProject().getRootDir(), ".idea").exists()
|| (Arrays.stream(getProject().getRootDir().listFiles()).anyMatch(file -> file.getName().endsWith(".iws")))) { || (Arrays.stream(getProject().getRootDir().listFiles()).anyMatch(file -> file.getName().endsWith(".iws")));
//Enable ansi by default for idea and vscode when gradle is not ran with plain console.
if (ansiSupportedIDE && !plainConsole) {
launchConfig.property("fabric.log.disableAnsi", "false"); launchConfig.property("fabric.log.disableAnsi", "false");
} }

View File

@@ -220,7 +220,7 @@ public class MinecraftProviderImpl extends DependencyProvider implements Minecra
String expVersionManifest = Files.asCharSource(experimentalVersionsJson, StandardCharsets.UTF_8).read(); String expVersionManifest = Files.asCharSource(experimentalVersionsJson, StandardCharsets.UTF_8).read();
ManifestVersion expManifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(expVersionManifest, ManifestVersion.class); ManifestVersion expManifest = LoomGradlePlugin.OBJECT_MAPPER.readValue(expVersionManifest, ManifestVersion.class);
var result = expManifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst(); Optional<ManifestVersion.Versions> result = expManifest.versions().stream().filter(versions -> versions.id.equalsIgnoreCase(minecraftVersion)).findFirst();
if (result.isPresent()) { if (result.isPresent()) {
getProject().getLogger().lifecycle("Using fallback experimental version {}", minecraftVersion); getProject().getLogger().lifecycle("Using fallback experimental version {}", minecraftVersion);

View File

@@ -57,7 +57,7 @@ public class LayeredMappingSpecBuilder {
} }
public LayeredMappingSpecBuilder parchment(String mavenNotation, Action<ParchmentMappingsSpecBuilder> action) { public LayeredMappingSpecBuilder parchment(String mavenNotation, Action<ParchmentMappingsSpecBuilder> action) {
var builder = ParchmentMappingsSpecBuilder.builder(mavenNotation); ParchmentMappingsSpecBuilder builder = ParchmentMappingsSpecBuilder.builder(mavenNotation);
action.execute(builder); action.execute(builder);
layers.add(builder.build()); layers.add(builder.build());
return this; return this;

View File

@@ -493,6 +493,8 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings
if (Files.exists(mappingsWorkingDir)) { if (Files.exists(mappingsWorkingDir)) {
Files.walkFileTree(mappingsWorkingDir, new DeletingFileVisitor()); Files.walkFileTree(mappingsWorkingDir, new DeletingFileVisitor());
} }
Files.createDirectories(mappingsWorkingDir);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -46,14 +46,19 @@ import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.api.MixinExtensionAPI;
import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.api.ForgeExtensionAPI; import net.fabricmc.loom.api.ForgeExtensionAPI;
import net.fabricmc.loom.api.LoomGradleExtensionAPI; import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.api.MixinApExtensionAPI; import net.fabricmc.loom.api.MixinApExtensionAPI;
import net.fabricmc.loom.api.decompilers.LoomDecompiler; import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.configuration.ide.RunConfig; import net.fabricmc.loom.configuration.ide.RunConfig;
import net.fabricmc.loom.configuration.ide.RunConfigSettings; import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.mods.ModVersionParser;
import net.fabricmc.loom.configuration.launch.LaunchProviderSettings; import net.fabricmc.loom.configuration.launch.LaunchProviderSettings;
import net.fabricmc.loom.configuration.processors.JarProcessor; import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext; import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext;
@@ -80,6 +85,9 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
protected final Property<Boolean> shareCaches; protected final Property<Boolean> shareCaches;
protected final Property<Boolean> remapArchives; protected final Property<Boolean> remapArchives;
protected final Property<String> customManifest; protected final Property<String> customManifest;
protected final Property<Boolean> setupRemappedVariants;
private final ModVersionParser versionParser;
private NamedDomainObjectContainer<RunConfigSettings> runConfigs; private NamedDomainObjectContainer<RunConfigSettings> runConfigs;
@@ -114,6 +122,10 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
this.remapArchives = project.getObjects().property(Boolean.class) this.remapArchives = project.getObjects().property(Boolean.class)
.convention(true); .convention(true);
this.customManifest = project.getObjects().property(String.class); this.customManifest = project.getObjects().property(String.class);
this.setupRemappedVariants = project.getObjects().property(Boolean.class)
.convention(true);
this.versionParser = new ModVersionParser(project);
this.deprecationHelper = new DeprecationHelper.ProjectBased(project); this.deprecationHelper = new DeprecationHelper.ProjectBased(project);
this.platform = project.getObjects().property(ModPlatform.class).convention(project.provider(Suppliers.memoize(() -> { this.platform = project.getObjects().property(ModPlatform.class).convention(project.provider(Suppliers.memoize(() -> {
@@ -193,7 +205,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
} }
@Override @Override
public void mixin(Action<MixinApExtensionAPI> action) { public void mixin(Action<MixinExtensionAPI> action) {
action.execute(getMixin()); action.execute(getMixin());
} }
@@ -202,10 +214,25 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
return customManifest; return customManifest;
} }
@Override
public Property<Boolean> getSetupRemappedVariants() {
return setupRemappedVariants;
}
@Override
public String getModVersion() {
return versionParser.getModVersion();
}
protected abstract Project getProject(); protected abstract Project getProject();
protected abstract LoomFiles getFiles(); protected abstract LoomFiles getFiles();
@Override
public void disableDeprecatedPomGeneration(MavenPublication publication) {
net.fabricmc.loom.configuration.MavenPublication.excludePublication(publication);
}
@Override @Override
public void silentMojangMappingsLicense() { public void silentMojangMappingsLicense() {
this.silentMojangMappingsLicense = true; this.silentMojangMappingsLicense = true;
@@ -362,7 +389,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
} }
@Override @Override
public MixinApExtension getMixin() { public MixinExtension getMixin() {
throw new RuntimeException("Yeah... something is really wrong"); throw new RuntimeException("Yeah... something is really wrong");
} }

View File

@@ -50,7 +50,7 @@ import net.fabricmc.loom.util.ModPlatform;
public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implements LoomGradleExtension { public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implements LoomGradleExtension {
private final Project project; private final Project project;
private final MixinApExtension mixinApExtension; private final MixinExtension mixinApExtension;
private final LoomFiles loomFiles; private final LoomFiles loomFiles;
private final ConfigurableFileCollection unmappedMods; private final ConfigurableFileCollection unmappedMods;
private final Supplier<ForgeExtensionAPI> forgeExtension; private final Supplier<ForgeExtensionAPI> forgeExtension;
@@ -68,7 +68,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
super(project, files); super(project, files);
this.project = project; this.project = project;
// Initiate with newInstance to allow gradle to decorate our extension // Initiate with newInstance to allow gradle to decorate our extension
this.mixinApExtension = project.getObjects().newInstance(MixinApExtensionImpl.class, project); this.mixinApExtension = project.getObjects().newInstance(MixinExtensionImpl.class, project);
this.loomFiles = files; this.loomFiles = files;
this.unmappedMods = project.files(); this.unmappedMods = project.files();
this.forgeExtension = Suppliers.memoize(() -> isForge() ? project.getObjects().newInstance(ForgeExtensionImpl.class, project) : null); this.forgeExtension = Suppliers.memoize(() -> isForge() ? project.getObjects().newInstance(ForgeExtensionImpl.class, project) : null);
@@ -172,7 +172,7 @@ public class LoomGradleExtensionImpl extends LoomGradleExtensionApiImpl implemen
} }
@Override @Override
public MixinApExtension getMixin() { public MixinExtension getMixin() {
return this.mixinApExtension; return this.mixinApExtension;
} }

View File

@@ -37,11 +37,12 @@ import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.RegularFileProperty; import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import net.fabricmc.loom.api.ForgeExtensionAPI; import net.fabricmc.loom.api.ForgeExtensionAPI;
import net.fabricmc.loom.api.LoomGradleExtensionAPI; import net.fabricmc.loom.api.LoomGradleExtensionAPI;
import net.fabricmc.loom.api.MixinApExtensionAPI; import net.fabricmc.loom.api.MixinExtensionAPI;
import net.fabricmc.loom.api.decompilers.LoomDecompiler; import net.fabricmc.loom.api.decompilers.LoomDecompiler;
import net.fabricmc.loom.configuration.ide.RunConfig; import net.fabricmc.loom.configuration.ide.RunConfig;
import net.fabricmc.loom.configuration.ide.RunConfigSettings; import net.fabricmc.loom.configuration.ide.RunConfigSettings;
@@ -126,13 +127,13 @@ public class MinecraftGradleExtension implements LoomGradleExtensionAPI {
} }
@Override @Override
public void mixin(Action<MixinApExtensionAPI> action) { public void mixin(Action<MixinExtensionAPI> action) {
reportDeprecation(); reportDeprecation();
parent.mixin(action); parent.mixin(action);
} }
@Override @Override
public MixinApExtensionAPI getMixin() { public MixinExtensionAPI getMixin() {
reportDeprecation(); reportDeprecation();
return parent.getMixin(); return parent.getMixin();
} }
@@ -143,6 +144,24 @@ public class MinecraftGradleExtension implements LoomGradleExtensionAPI {
return parent.getCustomMinecraftManifest(); return parent.getCustomMinecraftManifest();
} }
@Override
public Property<Boolean> getSetupRemappedVariants() {
reportDeprecation();
return parent.getSetupRemappedVariants();
}
@Override
public void disableDeprecatedPomGeneration(MavenPublication publication) {
reportDeprecation();
parent.disableDeprecatedPomGeneration(publication);
}
@Override
public String getModVersion() {
reportDeprecation();
throw new UnsupportedOperationException("Use loom extension");
}
@Override @Override
public void silentMojangMappingsLicense() { public void silentMojangMappingsLicense() {
reportDeprecation(); reportDeprecation();

View File

@@ -41,13 +41,13 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import net.fabricmc.loom.api.MixinApExtensionAPI; import net.fabricmc.loom.api.MixinExtensionAPI;
/** /**
* A gradle extension to configure mixin annotation processor. * A gradle extension to configure mixin annotation processor.
*/ */
@ApiStatus.Experimental @ApiStatus.Experimental
public interface MixinApExtension extends MixinApExtensionAPI { public interface MixinExtension extends MixinExtensionAPI {
String MIXIN_INFORMATION_CONTAINER = "mixin"; String MIXIN_INFORMATION_CONTAINER = "mixin";
/** /**

View File

@@ -24,6 +24,8 @@
package net.fabricmc.loom.extension; package net.fabricmc.loom.extension;
import java.util.Objects;
import org.gradle.api.Action; import org.gradle.api.Action;
import org.gradle.api.InvalidUserDataException; import org.gradle.api.InvalidUserDataException;
import org.gradle.api.Project; import org.gradle.api.Project;
@@ -33,17 +35,29 @@ import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.util.PatternSet; import org.gradle.api.tasks.util.PatternSet;
import net.fabricmc.loom.api.MixinApExtensionAPI; import net.fabricmc.loom.api.MixinExtensionAPI;
public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI { public abstract class MixinExtensionApiImpl implements MixinExtensionAPI {
protected abstract Project getProject(); protected final Project project;
protected final Property<Boolean> useMixinAp;
public MixinExtensionApiImpl(Project project) {
this.project = Objects.requireNonNull(project);
this.useMixinAp = project.getObjects().property(Boolean.class)
.convention(false);
}
protected final PatternSet add0(SourceSet sourceSet, String refmapName) { protected final PatternSet add0(SourceSet sourceSet, String refmapName) {
return add0(sourceSet, getProject().provider(() -> refmapName)); return add0(sourceSet, project.provider(() -> refmapName));
} }
protected abstract PatternSet add0(SourceSet sourceSet, Provider<String> refmapName); protected abstract PatternSet add0(SourceSet sourceSet, Provider<String> refmapName);
@Override
public Property<Boolean> getUseLegacyMixinAp() {
return useMixinAp;
}
@Override @Override
public void add(SourceSet sourceSet, String refmapName, Action<PatternSet> action) { public void add(SourceSet sourceSet, String refmapName, Action<PatternSet> action) {
PatternSet pattern = add0(sourceSet, refmapName); PatternSet pattern = add0(sourceSet, refmapName);
@@ -57,7 +71,7 @@ public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI {
@Override @Override
public void add(String sourceSetName, String refmapName, Action<PatternSet> action) { public void add(String sourceSetName, String refmapName, Action<PatternSet> action) {
add(sourceSetName, getProject().provider(() -> refmapName), action); add(sourceSetName, project.provider(() -> refmapName), action);
} }
public void add(String sourceSetName, Provider<String> refmapName, Action<PatternSet> action) { public void add(String sourceSetName, Provider<String> refmapName, Action<PatternSet> action) {
@@ -96,7 +110,7 @@ public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI {
private SourceSet resolveSourceSet(String sourceSetName) { private SourceSet resolveSourceSet(String sourceSetName) {
// try to find sourceSet with name sourceSetName in this project // try to find sourceSet with name sourceSetName in this project
SourceSet sourceSet = getProject().getConvention().getPlugin(JavaPluginConvention.class) SourceSet sourceSet = project.getConvention().getPlugin(JavaPluginConvention.class)
.getSourceSets().findByName(sourceSetName); .getSourceSets().findByName(sourceSetName);
if (sourceSet == null) { if (sourceSet == null) {
@@ -107,17 +121,12 @@ public abstract class MixinApExtensionApiImpl implements MixinApExtensionAPI {
} }
// This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods // This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods
private final class EnsureCompile extends MixinApExtensionApiImpl { private final class EnsureCompile extends MixinExtensionApiImpl {
private EnsureCompile() { private EnsureCompile() {
super(); super(null);
throw new RuntimeException(); throw new RuntimeException();
} }
@Override
protected Project getProject() {
throw new RuntimeException("Yeah... something is really wrong");
}
@Override @Override
public Property<String> getDefaultRefmapName() { public Property<String> getDefaultRefmapName() {
throw new RuntimeException("Yeah... something is really wrong"); throw new RuntimeException("Yeah... something is really wrong");

View File

@@ -47,44 +47,42 @@ import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.util.PatternSet; import org.gradle.api.tasks.util.PatternSet;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class MixinApExtensionImpl extends MixinApExtensionApiImpl implements MixinApExtension { public class MixinExtensionImpl extends MixinExtensionApiImpl implements MixinExtension {
private boolean isDefault; private boolean isDefault;
private final Project project;
private final Property<String> defaultRefmapName; private final Property<String> defaultRefmapName;
@Inject @Inject
public MixinApExtensionImpl(Project project) { public MixinExtensionImpl(Project project) {
super(project);
this.isDefault = true; this.isDefault = true;
this.project = project;
this.defaultRefmapName = project.getObjects().property(String.class) this.defaultRefmapName = project.getObjects().property(String.class)
.convention(project.provider(this::getDefaultMixinRefmapName)); .convention(project.provider(this::getDefaultMixinRefmapName));
} }
@Override
public Project getProject() {
return this.project;
}
@Override @Override
public Property<String> getDefaultRefmapName() { public Property<String> getDefaultRefmapName() {
if (!super.getUseLegacyMixinAp().get()) throw new IllegalStateException("You need to set useLegacyMixinAp = true to configure Mixin annotation processor.");
return defaultRefmapName; return defaultRefmapName;
} }
private String getDefaultMixinRefmapName() { private String getDefaultMixinRefmapName() {
String defaultRefmapName = getProject().getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-refmap.json"; String defaultRefmapName = project.getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-refmap.json";
if (getProject().getRootProject() != getProject()) { if (project.getRootProject() != project) {
defaultRefmapName = getProject().getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-" + getProject().getPath().replaceFirst(":", "").replace(':', '_') + "-refmap.json"; defaultRefmapName = project.getConvention().getPlugin(BasePluginConvention.class).getArchivesBaseName() + "-" + getProject().getPath().replaceFirst(":", "").replace(':', '_') + "-refmap.json";
} }
getProject().getLogger().info("Could not find refmap definition, will be using default name: " + defaultRefmapName); project.getLogger().info("Could not find refmap definition, will be using default name: " + defaultRefmapName);
return defaultRefmapName; return defaultRefmapName;
} }
@Override @Override
protected PatternSet add0(SourceSet sourceSet, Provider<String> refmapName) { protected PatternSet add0(SourceSet sourceSet, Provider<String> refmapName) {
if (!super.getUseLegacyMixinAp().get()) throw new IllegalStateException("You need to set useLegacyMixinAp = true to configure Mixin annotation processor.");
PatternSet pattern = new PatternSet().setIncludes(Collections.singletonList("*.json")); PatternSet pattern = new PatternSet().setIncludes(Collections.singletonList("*.json"));
MixinApExtension.setMixinInformationContainer(sourceSet, new MixinApExtension.MixinInformationContainer(sourceSet, refmapName, pattern)); MixinExtension.setMixinInformationContainer(sourceSet, new MixinExtension.MixinInformationContainer(sourceSet, refmapName, pattern));
isDefault = false; isDefault = false;
@@ -95,7 +93,7 @@ public class MixinApExtensionImpl extends MixinApExtensionApiImpl implements Mix
@NotNull @NotNull
public Stream<SourceSet> getMixinSourceSetsStream() { public Stream<SourceSet> getMixinSourceSetsStream() {
return project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().stream() return project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().stream()
.filter(sourceSet -> MixinApExtension.getMixinInformationContainer(sourceSet) != null); .filter(sourceSet -> MixinExtension.getMixinInformationContainer(sourceSet) != null);
} }
@Override @Override

View File

@@ -24,10 +24,7 @@
package net.fabricmc.loom.task; package net.fabricmc.loom.task;
import java.io.IOException;
import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.TaskAction;
import net.fabricmc.loom.util.SourceRemapper; import net.fabricmc.loom.util.SourceRemapper;
@@ -38,13 +35,4 @@ public class RemapAllSourcesTask extends AbstractLoomTask {
public SourceRemapper getSourceRemapper() { public SourceRemapper getSourceRemapper() {
return sourceRemapper; return sourceRemapper;
} }
@TaskAction
public void remap() {
try {
sourceRemapper.remapAll();
} catch (IOException exception) {
throw new RuntimeException("Failed to remap mod", exception);
}
}
} }

View File

@@ -71,6 +71,7 @@ import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFileProperty; import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.provider.Property; import org.gradle.api.provider.Property;
import org.gradle.api.provider.SetProperty; import org.gradle.api.provider.SetProperty;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
@@ -107,6 +108,9 @@ import net.fabricmc.mapping.tree.FieldDef;
import net.fabricmc.mapping.tree.MethodDef; import net.fabricmc.mapping.tree.MethodDef;
import net.fabricmc.mapping.tree.TinyTree; import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.stitch.util.Pair; import net.fabricmc.stitch.util.Pair;
import net.fabricmc.tinyremapper.TinyRemapper;
import net.fabricmc.tinyremapper.TinyUtils;
import net.fabricmc.tinyremapper.extension.mixin.MixinExtension;
public class RemapJarTask extends Jar { public class RemapJarTask extends Jar {
private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF"; private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
@@ -137,6 +141,10 @@ public class RemapJarTask extends Jar {
// false by default, I have no idea why I have to do it for this property and not the other one // false by default, I have no idea why I have to do it for this property and not the other one
remapAccessWidener.set(false); remapAccessWidener.set(false);
addDefaultNestedDependencies.set(true); addDefaultNestedDependencies.set(true);
if (!LoomGradleExtension.get(getProject()).getMixin().getUseLegacyMixinAp().get()) {
remapOptions.add(b -> b.extension(new MixinExtension()));
}
} }
@TaskAction @TaskAction
@@ -284,8 +292,10 @@ public class RemapJarTask extends Jar {
throw new RuntimeException("Failed to remap " + input + " to " + output + " - file missing!"); throw new RuntimeException("Failed to remap " + input + " to " + output + " - file missing!");
} }
if (MixinRefmapHelper.addRefmapName(project, output)) { if (extension.getMixin().getUseLegacyMixinAp().get()) {
project.getLogger().debug("Transformed mixin reference maps in output JAR!"); if (MixinRefmapHelper.addRefmapName(project, output)) {
project.getLogger().debug("Transformed mixin reference maps in output JAR!");
}
} }
if (!toM.equals("intermediary")) { if (!toM.equals("intermediary")) {
@@ -446,7 +456,7 @@ public class RemapJarTask extends Jar {
FileCollection files = this.classpath; FileCollection files = this.classpath;
if (files == null) { if (files == null) {
files = getProject().getConfigurations().getByName("compileClasspath"); files = getProject().getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME);
} }
return files.getFiles().stream() return files.getFiles().stream()

View File

@@ -45,14 +45,16 @@ public class Constants {
public static final int ASM_VERSION = Opcodes.ASM9; public static final int ASM_VERSION = Opcodes.ASM9;
public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of( public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of(
new RemappedConfigurationEntry("modApi", JavaPlugin.API_CONFIGURATION_NAME, true, "compile"), new RemappedConfigurationEntry("modApi", JavaPlugin.API_CONFIGURATION_NAME, true, true, JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME),
new RemappedConfigurationEntry("modImplementation", JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, true, "runtime"), new RemappedConfigurationEntry("modImplementation", JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, true, true, JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME),
new RemappedConfigurationEntry("modRuntime", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, "", "modRuntimeOnly"), new RemappedConfigurationEntry("modRuntime", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, true, "", "modRuntimeOnly"),
new RemappedConfigurationEntry("modCompileOnly", JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, true, ""), new RemappedConfigurationEntry("modCompileOnly", JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, true, false, ""),
new RemappedConfigurationEntry("modCompileOnlyApi", JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME, true, "compile"), new RemappedConfigurationEntry("modCompileOnlyApi", JavaPlugin.COMPILE_ONLY_API_CONFIGURATION_NAME, true, false, JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME),
new RemappedConfigurationEntry("modRuntimeOnly", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, "runtime") new RemappedConfigurationEntry("modRuntimeOnly", JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME, false, true, JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME)
); );
public static final String SOFTWARE_COMPONENT_NAME = "loom";
private Constants() { private Constants() {
} }
@@ -108,10 +110,10 @@ public class Constants {
* Constants for versions of dependencies. * Constants for versions of dependencies.
*/ */
public static final class Versions { public static final class Versions {
public static final String MIXIN_COMPILE_EXTENSIONS = "0.4.4"; public static final String MIXIN_COMPILE_EXTENSIONS = "0.4.6";
public static final String DEV_LAUNCH_INJECTOR = "0.2.1+build.8"; public static final String DEV_LAUNCH_INJECTOR = "0.2.1+build.8";
public static final String TERMINAL_CONSOLE_APPENDER = "1.2.0"; public static final String TERMINAL_CONSOLE_APPENDER = "1.2.0";
public static final String JETBRAINS_ANNOTATIONS = "19.0.0"; public static final String JETBRAINS_ANNOTATIONS = "22.0.0";
public static final String JAVAX_ANNOTATIONS = "3.0.2"; public static final String JAVAX_ANNOTATIONS = "3.0.2";
public static final String FORGE_RUNTIME = "1.0.1"; public static final String FORGE_RUNTIME = "1.0.1";
public static final String ACCESS_TRANSFORMERS = "3.0.1"; public static final String ACCESS_TRANSFORMERS = "3.0.1";

View File

@@ -32,26 +32,20 @@ import java.util.ArrayList;
import java.util.Deque; import java.util.Deque;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.function.Consumer;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import org.cadixdev.lorenz.MappingSet; import org.cadixdev.lorenz.MappingSet;
import org.cadixdev.mercury.Mercury; import org.cadixdev.mercury.Mercury;
import org.cadixdev.mercury.SourceProcessor;
import org.cadixdev.mercury.remapper.MercuryRemapper; import org.cadixdev.mercury.remapper.MercuryRemapper;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlugin;
import org.zeroturnaround.zip.ZipUtil; import org.zeroturnaround.zip.ZipUtil;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.RemappedConfigurationEntry; import net.fabricmc.loom.configuration.RemappedConfigurationEntry;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl;
import net.fabricmc.loom.util.gradle.ProgressLogger;
import net.fabricmc.lorenztiny.TinyMappingsReader; import net.fabricmc.lorenztiny.TinyMappingsReader;
import net.fabricmc.mapping.tree.TinyTree; import net.fabricmc.mapping.tree.TinyTree;
import net.fabricmc.stitch.util.StitchUtil; import net.fabricmc.stitch.util.StitchUtil;
@@ -60,8 +54,9 @@ public class SourceRemapper {
private final Project project; private final Project project;
private String from; private String from;
private String to; private String to;
private final List<RemapTask> remapTasks = new ArrayList<>(); private final List<Consumer<ProgressLogger>> remapTasks = new ArrayList<>();
private boolean hasStartedRemap = false;
private Mercury mercury;
public SourceRemapper(Project project, boolean named) { public SourceRemapper(Project project, boolean named) {
this(project, named ? intermediary(project) : "named", !named ? intermediary(project) : "named"); this(project, named ? intermediary(project) : "named", !named ? intermediary(project) : "named");
@@ -78,165 +73,106 @@ public class SourceRemapper {
this.to = to; this.to = to;
} }
public static void remapSources(Project project, File input, File output, String from, String to, boolean reproducibleFileOrder, boolean preserveFileTimestamps) throws IOException { public static void remapSources(Project project, File input, File output, String from, String to, boolean reproducibleFileOrder, boolean preserveFileTimestamps) {
SourceRemapper sourceRemapper = new SourceRemapper(project, from, to); SourceRemapper sourceRemapper = new SourceRemapper(project, from, to);
sourceRemapper.scheduleRemapSources(input, output, reproducibleFileOrder, preserveFileTimestamps); sourceRemapper.scheduleRemapSources(input, output, reproducibleFileOrder, preserveFileTimestamps);
sourceRemapper.remapAll(); sourceRemapper.remapAll();
} }
public void scheduleRemapSources(File source, File destination, boolean reproducibleFileOrder, boolean preserveFileTimestamps) { public void scheduleRemapSources(File source, File destination, boolean reproducibleFileOrder, boolean preserveFileTimestamps) {
this.scheduleRemapSources(new RemapTask(source, destination, reproducibleFileOrder, preserveFileTimestamps)); remapTasks.add((logger) -> {
try {
logger.progress("remapping sources - " + source.getName());
remapSourcesInner(source, destination);
ZipReprocessorUtil.reprocessZip(destination, reproducibleFileOrder, preserveFileTimestamps);
// Set the remapped sources creation date to match the sources if we're likely succeeded in making it
destination.setLastModified(source.lastModified());
} catch (Exception e) {
// Failed to remap, lets clean up to ensure we try again next time
destination.delete();
throw new RuntimeException("Failed to remap sources for " + source, e);
}
});
} }
public synchronized void scheduleRemapSources(RemapTask data) { public void remapAll() {
if (hasStartedRemap) {
throw new UnsupportedOperationException("Cannot add data after remapping has started");
}
this.remapTasks.add(data);
}
public void remapAll() throws IOException {
hasStartedRemap = true;
if (remapTasks.isEmpty()) { if (remapTasks.isEmpty()) {
return; return;
} }
Stopwatch stopwatch = Stopwatch.createStarted(); project.getLogger().lifecycle(":remapping sources");
project.getLogger().lifecycle(":remapping " + remapTasks.size() + " sources");
int threads = Math.min(remapTasks.size(), Math.max(2, Runtime.getRuntime().availableProcessors()));
ExecutorService ioExecutor = Executors.newFixedThreadPool(2);
ExecutorService remapExecutor = Executors.newFixedThreadPool(threads);
List<CompletableFuture<Void>> completableFutures = new ArrayList<>(); ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, SourceRemapper.class.getName());
progressLogger.start("Remapping dependency sources", "sources");
{ remapTasks.forEach(consumer -> consumer.accept(progressLogger));
// We have to build the Mercury instances on the main thread as createMercuryRemapper resolves gradle stuff
// TODO refactor this a bit to not do that.
Deque<Mercury> mercuryQueue = new ConcurrentLinkedDeque<>();
final SourceProcessor remapper = createMercuryRemapper(); progressLogger.completed();
final Set<Path> inputClasspath = getInputClasspath(project);
for (int i = 0; i < threads; i++) {
Mercury mercury = createMercuryWithClassPath(project, to.equals("named"));
mercury.getProcessors().add(remapper);
mercury.getClassPath().addAll(inputClasspath);
mercuryQueue.add(mercury);
}
ThreadLocal<Mercury> mercuryThreadLocal = ThreadLocal.withInitial(() -> Objects.requireNonNull(mercuryQueue.pop(), "No Mercury instances left"));
for (RemapTask remapTask : this.remapTasks) {
completableFutures.add(
CompletableFuture.supplyAsync(() ->
prepareForRemap(remapTask), ioExecutor)
.thenApplyAsync(remapData -> doRemap(mercuryThreadLocal.get(), remapData), remapExecutor)
.thenAcceptAsync(remapData -> completeRemap(remapData, remapTask), ioExecutor)
);
}
}
for (CompletableFuture<Void> future : completableFutures) {
try {
future.join();
} catch (CompletionException e) {
try {
throw e.getCause();
} catch (IOException ioe) {
throw ioe;
} catch (Throwable unknown) {
throw new RuntimeException("An unknown exception occured when remapping", unknown);
}
}
}
ioExecutor.shutdown();
remapExecutor.shutdown();
// TODO: FIXME - WORKAROUND https://github.com/FabricMC/fabric-loom/issues/45 // TODO: FIXME - WORKAROUND https://github.com/FabricMC/fabric-loom/issues/45
System.gc(); System.gc();
} }
private RemapData prepareForRemap(RemapTask remapTask) { private void remapSourcesInner(File source, File destination) throws Exception {
try { project.getLogger().info(":remapping source jar");
File source = remapTask.source(); Mercury mercury = getMercuryInstance();
final File destination = remapTask.destination();
if (source.equals(destination)) { if (source.equals(destination)) {
if (source.isDirectory()) { if (source.isDirectory()) {
throw new RuntimeException("Directories must differ!"); throw new RuntimeException("Directories must differ!");
}
source = new File(destination.getAbsolutePath().substring(0, destination.getAbsolutePath().lastIndexOf('.')) + "-dev.jar");
try {
com.google.common.io.Files.move(destination, source);
} catch (IOException e) {
throw new RuntimeException("Could not rename " + destination.getName() + "!", e);
}
} }
Path srcPath = source.toPath(); source = new File(destination.getAbsolutePath().substring(0, destination.getAbsolutePath().lastIndexOf('.')) + "-dev.jar");
boolean isSrcTmp = false;
if (!source.isDirectory()) { try {
// create tmp directory com.google.common.io.Files.move(destination, source);
isSrcTmp = true; } catch (IOException e) {
srcPath = Files.createTempDirectory("fabric-loom-src"); throw new RuntimeException("Could not rename " + destination.getName() + "!", e);
ZipUtil.unpack(source, srcPath.toFile());
} }
if (!destination.isDirectory() && destination.exists()) {
if (!destination.delete()) {
throw new RuntimeException("Could not delete " + destination.getName() + "!");
}
}
StitchUtil.FileSystemDelegate dstFs = remapTask.destination().isDirectory() ? null : StitchUtil.getJarFileSystem(remapTask.destination(), true);
Path dstPath = dstFs != null ? dstFs.get().getPath("/") : remapTask.destination().toPath();
return new RemapData(Objects.requireNonNull(srcPath, "srcPath"), Objects.requireNonNull(dstPath, "dstPath"), dstFs, isSrcTmp);
} catch (IOException e) {
throw new CompletionException("Failed to prepare for remap", e);
} }
}
private RemapData doRemap(Mercury mercury, RemapData remapData) { Path srcPath = source.toPath();
boolean isSrcTmp = false;
if (!source.isDirectory()) {
// create tmp directory
isSrcTmp = true;
srcPath = Files.createTempDirectory("fabric-loom-src");
ZipUtil.unpack(source, srcPath.toFile());
}
if (!destination.isDirectory() && destination.exists()) {
if (!destination.delete()) {
throw new RuntimeException("Could not delete " + destination.getName() + "!");
}
}
StitchUtil.FileSystemDelegate dstFs = destination.isDirectory() ? null : StitchUtil.getJarFileSystem(destination, true);
Path dstPath = dstFs != null ? dstFs.get().getPath("/") : destination.toPath();
try { try {
mercury.rewrite(remapData.source(), remapData.destination()); mercury.rewrite(srcPath, dstPath);
} catch (Exception e) { } catch (Exception e) {
project.getLogger().warn("Could not remap " + remapData.source().toString() + " fully!", e); project.getLogger().warn("Could not remap " + source.getName() + " fully!", e);
// TODO do something more with this error? delete the dst file in complete remap?
} }
return remapData; copyNonJavaFiles(srcPath, dstPath, project, source);
}
private void completeRemap(RemapData remapData, RemapTask remapTask) { if (dstFs != null) {
try { dstFs.close();
copyNonJavaFiles(remapData.source(), remapData.destination(), project, remapTask.source()); }
if (remapData.dstFs() != null) { if (isSrcTmp) {
remapData.dstFs().close(); Files.walkFileTree(srcPath, new DeletingFileVisitor());
}
if (remapData.isSrcTmp()) {
Files.walkFileTree(remapData.source(), new DeletingFileVisitor());
}
ZipReprocessorUtil.reprocessZip(remapTask.destination(), remapTask.reproducibleFileOrder(), remapTask.preserveFileTimestamps());
// Set the remapped sources creation date to match the sources if we're likely succeeded in making it
remapTask.destination().setLastModified(remapTask.source().lastModified());
} catch (IOException e) {
throw new CompletionException("Failed to complete remap", e);
} }
} }
private SourceProcessor createMercuryRemapper() { private Mercury getMercuryInstance() {
if (this.mercury != null) {
return this.mercury;
}
LoomGradleExtension extension = LoomGradleExtension.get(project); LoomGradleExtension extension = LoomGradleExtension.get(project);
MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); MappingsProviderImpl mappingsProvider = extension.getMappingsProvider();
@@ -259,7 +195,35 @@ public class SourceRemapper {
} }
}); });
return MercuryRemapper.create(mappings); Mercury mercury = extension.getOrCreateSrcMercuryCache(toNamed ? 1 : 0, () -> {
Mercury m = createMercuryWithClassPath(project, toNamed);
for (File file : extension.getUnmappedModCollection()) {
Path path = file.toPath();
if (Files.isRegularFile(path)) {
m.getClassPath().add(path);
}
}
m.getClassPath().add(extension.getMinecraftMappedProvider().getMappedJar().toPath());
m.getClassPath().add(extension.getMinecraftMappedProvider().getIntermediaryJar().toPath());
Set<File> files = project.getConfigurations()
.detachedConfiguration(project.getDependencies().create(Constants.Dependencies.JETBRAINS_ANNOTATIONS + Constants.Dependencies.Versions.JETBRAINS_ANNOTATIONS))
.resolve();
for (File file : files) {
m.getClassPath().add(file.toPath());
}
m.getProcessors().add(MercuryRemapper.create(mappings));
return m;
});
this.mercury = mercury;
return mercury;
} }
private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException { private static void copyNonJavaFiles(Path from, Path to, Project project, File source) throws IOException {
@@ -277,49 +241,23 @@ public class SourceRemapper {
} }
public static Mercury createMercuryWithClassPath(Project project, boolean toNamed) { public static Mercury createMercuryWithClassPath(Project project, boolean toNamed) {
Mercury mercury = new Mercury(); Mercury m = new Mercury();
mercury.setGracefulClasspathChecks(true); m.setGracefulClasspathChecks(true);
List<Path> classpath = mercury.getClassPath();
classpath.addAll(getCompileClasspath(project, toNamed));
return mercury;
}
private static Set<Path> getCompileClasspath(Project project, boolean toNamed) {
Set<Path> classpath = new HashSet<>();
for (File file : project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES).getFiles()) { for (File file : project.getConfigurations().getByName(Constants.Configurations.LOADER_DEPENDENCIES).getFiles()) {
classpath.add(file.toPath()); m.getClassPath().add(file.toPath());
} }
if (!toNamed) { if (!toNamed) {
for (File file : project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME).getFiles()) { for (File file : project.getConfigurations().getByName("compileClasspath").getFiles()) {
classpath.add(file.toPath()); m.getClassPath().add(file.toPath());
} }
} else { } else {
for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) { for (RemappedConfigurationEntry entry : Constants.MOD_COMPILE_ENTRIES) {
for (File inputFile : project.getConfigurations().getByName(entry.sourceConfiguration()).getFiles()) { for (File inputFile : project.getConfigurations().getByName(entry.sourceConfiguration()).getFiles()) {
classpath.add(inputFile.toPath()); m.getClassPath().add(inputFile.toPath());
} }
} }
}
return classpath;
}
private static Set<Path> getInputClasspath(Project project) {
LoomGradleExtension extension = LoomGradleExtension.get(project);
Set<Path> classpath = new HashSet<Path>();
for (File file : extension.getUnmappedModCollection()) {
Path path = file.toPath();
if (Files.isRegularFile(path)) {
classpath.add(path);
}
}
classpath.add(extension.getMinecraftMappedProvider().getMappedJar().toPath()); classpath.add(extension.getMinecraftMappedProvider().getMappedJar().toPath());
classpath.add(extension.getMinecraftMappedProvider().getIntermediaryJar().toPath()); classpath.add(extension.getMinecraftMappedProvider().getIntermediaryJar().toPath());
@@ -339,7 +277,7 @@ public class SourceRemapper {
classpath.add(file.toPath()); classpath.add(file.toPath());
} }
return classpath; return m;
} }
private static boolean isJavaFile(Path path) { private static boolean isJavaFile(Path path) {
@@ -347,10 +285,4 @@ public class SourceRemapper {
// ".java" is not a valid java file // ".java" is not a valid java file
return name.endsWith(".java") && name.length() != 5; return name.endsWith(".java") && name.length() != 5;
} }
public static record RemapTask(File source, File destination, boolean reproducibleFileOrder, boolean preserveFileTimestamps) {
}
public static record RemapData(Path source, Path destination, StitchUtil.FileSystemDelegate dstFs, boolean isSrcTmp) {
}
} }

View File

@@ -1,7 +1,7 @@
/* /*
* This file is part of fabric-loom, licensed under the MIT License (MIT). * This file is part of fabric-loom, licensed under the MIT License (MIT).
* *
* Copyright (c) 2016-2021 FabricMC * Copyright (c) 2021 FabricMC
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -22,25 +22,11 @@
* SOFTWARE. * SOFTWARE.
*/ */
package net.fabricmc.loom.test.util package net.fabricmc.loom.test
import org.zeroturnaround.zip.ZipUtil class LoomTestConstants {
public final static String DEFAULT_GRADLE = "7.0.1"
public final static String PRE_RELEASE_GRADLE = "7.3-20210906222431+0000"
trait ArchiveAssertionsTrait { public final static String[] STANDARD_TEST_VERSIONS = [DEFAULT_GRADLE, PRE_RELEASE_GRADLE]
String getArchiveEntry(String name, String entry, String project = "") { }
def file = getOutputFile(name, project)
def bytes = ZipUtil.unpackEntry(file, entry)
if (bytes == null) {
throw new FileNotFoundException("Could not find ${entry} in ${name}")
}
new String(bytes as byte[])
}
boolean hasArchiveEntry(String name, String entry, String project = "") {
def file = getOutputFile(name, project)
ZipUtil.unpackEntry(file, entry) != null
}
}

View File

@@ -24,30 +24,25 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ArchiveAssertionsTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import net.fabricmc.loom.test.util.ProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class AccessWidenerTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait { class AccessWidenerTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"accesswidener"
}
@Unroll @Unroll
def "accesswidener (gradle #gradle)"() { def "accesswidener (gradle #version)"() {
setup:
def gradle = gradleProject(project: "accesswidener", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
getArchiveEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected().replaceAll('\r', '') gradle.getOutputZipEntry("fabric-example-mod-1.0.0.jar", "modid.accesswidener") == expected().replaceAll('\r', '')
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
String expected() { String expected() {

View File

@@ -24,42 +24,36 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class CustomManifestTest extends Specification implements ProjectTestTrait { class CustomManifestTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"minimalBase"
}
@Override
def filesReady() {
buildGradle() << '''
loom {
customMinecraftManifest = "https://maven.fabricmc.net/net/minecraft/1_18_experimental-snapshot-1.json"
}
dependencies {
minecraft "com.mojang:minecraft:1.18_experimental-snapshot-1"
mappings "net.fabricmc:yarn:1.18_experimental-snapshot-1+build.2:v2"
modImplementation "net.fabricmc:fabric-loader:0.11.6"
}
'''
}
@Unroll @Unroll
def "customManifest (gradle #gradle)"() { def "customManifest (gradle #version)"() {
setup:
def gradle = gradleProject(project: "minimalBase", version: version)
gradle.buildGradle << '''
loom {
customMinecraftManifest = "https://maven.fabricmc.net/net/minecraft/1_18_experimental-snapshot-1.json"
}
dependencies {
minecraft "com.mojang:minecraft:1.18_experimental-snapshot-1"
mappings "net.fabricmc:yarn:1.18_experimental-snapshot-1+build.2:v2"
modImplementation "net.fabricmc:fabric-loader:0.11.6"
}
'''
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -24,28 +24,27 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class DecompileTest extends Specification implements ProjectTestTrait { class DecompileTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"decompile"
}
@Unroll @Unroll
def "#decompiler gradle #gradle"() { def "#decompiler gradle #version"() {
setup:
def gradle = gradleProject(project: "decompile", version: version)
when: when:
def result = create(task, gradle) def result = gradle.run(task: task)
then: then:
result.task(":${task}").outcome == SUCCESS result.task(":${task}").outcome == SUCCESS
where: where:
decompiler | task | gradle decompiler | task | version
'fernflower' | "genSources" | DEFAULT_GRADLE 'fernflower' | "genSources" | DEFAULT_GRADLE
'fernflower' | "genSources" | PRE_RELEASE_GRADLE 'fernflower' | "genSources" | PRE_RELEASE_GRADLE
'cfr' | "genSourcesWithExperimentalCfr" | DEFAULT_GRADLE 'cfr' | "genSourcesWithExperimentalCfr" | DEFAULT_GRADLE

View File

@@ -24,29 +24,27 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class DependencyResolutionManagementTest extends Specification implements ProjectTestTrait { class DependencyResolutionManagementTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"dependencyResolutionManagement"
}
@Unroll @Unroll
def "build (gradle #gradle)"() { def "build (gradle #version)"() {
setup:
def gradle = gradleProject(project: "dependencyResolutionManagement", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":basic:build").outcome == SUCCESS result.task(":basic:build").outcome == SUCCESS
result.task(":projmap:build").outcome == SUCCESS result.task(":projmap:build").outcome == SUCCESS
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -24,38 +24,34 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class ExperimentalVersionsTest extends Specification implements ProjectTestTrait { class ExperimentalVersionsTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"minimalBase"
}
@Override
def filesReady() {
buildGradle() << '''
dependencies {
minecraft "com.mojang:minecraft:1.18_experimental-snapshot-1"
mappings "net.fabricmc:yarn:1.18_experimental-snapshot-1+build.2:v2"
modImplementation "net.fabricmc:fabric-loader:0.11.6"
}
'''
}
@Unroll @Unroll
def "experimental versions (gradle #gradle)"() { def "experimental versions (gradle #version)"() {
setup:
def gradle = gradleProject(project: "minimalBase", version: version)
gradle.buildGradle << '''
dependencies {
minecraft "com.mojang:minecraft:1.18_experimental-snapshot-1"
mappings "net.fabricmc:yarn:1.18_experimental-snapshot-1+build.2:v2"
modImplementation "net.fabricmc:fabric-loader:0.11.6"
}
'''
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -0,0 +1,70 @@
/*
* 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.test.integration
import net.fabricmc.loom.test.util.GradleProjectTestTrait
import net.fabricmc.loom.test.util.ServerRunner
import spock.lang.Specification
import spock.lang.Timeout
import spock.lang.Unroll
import java.util.concurrent.TimeUnit
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
@Timeout(value = 30, unit = TimeUnit.MINUTES)
class FabricAPITest extends Specification implements GradleProjectTestTrait {
private static final String API_VERSION = "0.0.0+loom"
@Unroll
def "build and run (gradle #version)"() {
setup:
def gradle = gradleProject(
repo: "https://github.com/FabricMC/fabric.git",
commit: "fc40aa9d88e9457957bdf3f8cec9698846828cd3",
version: version,
patch: "fabric_api"
)
// Set the version to something constant
gradle.buildGradle.text = gradle.buildGradle.text.replace('Globals.baseVersion + "+" + (ENV.GITHUB_RUN_NUMBER ? "" : "local-") + getBranch()', "\"$API_VERSION\"")
def server = ServerRunner.create(gradle.projectDir, "1.17.1")
.withMod(gradle.getOutputFile("fabric-api-${API_VERSION}.jar"))
when:
def result = gradle.run(tasks: ["build", "publishToMavenLocal"], args: ["--parallel", "-x", "check"]) // Note: checkstyle does not appear to like being ran in a test runner
gradle.printOutputFiles()
def serverResult = server.run()
then:
result.task(":build").outcome == SUCCESS
serverResult.successful()
serverResult.output.contains("fabric@$API_VERSION")
where:
version << STANDARD_TEST_VERSIONS
}
}

View File

@@ -24,27 +24,26 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class Java16ProjectTest extends Specification implements ProjectTestTrait { class Java16ProjectTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"java16"
}
@Unroll @Unroll
def "build (gradle #gradle)"() { def "build (gradle #version)"() {
setup:
def gradle = gradleProject(project: "java16", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -24,28 +24,26 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.IgnoreIf
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class KotlinTest extends Specification implements ProjectTestTrait { class KotlinTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"kotlin"
}
@Unroll @Unroll
def "kotlin build (gradle #gradle)"() { def "kotlin build (gradle #version)"() {
setup:
def gradle = gradleProject(project: "kotlin", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -24,24 +24,27 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
// This test uses gradle 4.9 and 1.14.4 v1 mappings // This test uses gradle 4.9 and 1.14.4 v1 mappings
class LegacyProjectTest extends Specification implements ProjectTestTrait { class LegacyProjectTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"legacy"
}
@Unroll @Unroll
def "build"() { def "legacy build (gradle #version)"() {
setup:
def gradle = gradleProject(project: "legacy", version: version)
when: when:
def result = create("build", DEFAULT_GRADLE) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
where:
version << STANDARD_TEST_VERSIONS
} }
} }

View File

@@ -24,27 +24,26 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class LocalFileDependencyTest extends Specification implements ProjectTestTrait { class LocalFileDependencyTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"localFileDependency"
}
@Unroll @Unroll
def "build (gradle #gradle)"() { def "build (gradle #version)"() {
setup:
def gradle = gradleProject(project: "localFileDependency", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -24,13 +24,14 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ArchiveAssertionsTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import net.fabricmc.loom.test.util.MockMavenServerTrait import net.fabricmc.loom.test.util.MockMavenServerTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Stepwise import spock.lang.Stepwise
import spock.lang.Unroll import spock.lang.Unroll
import spock.util.environment.RestoreSystemProperties import spock.util.environment.RestoreSystemProperties
import static net.fabricmc.loom.test.LoomTestConstants.*
import static java.lang.System.setProperty import static java.lang.System.setProperty
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
@@ -38,20 +39,23 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
* This tests publishing a range of versions and then tries to resolve and build against them * This tests publishing a range of versions and then tries to resolve and build against them
*/ */
@Stepwise @Stepwise
class MavenProjectTest extends Specification implements MockMavenServerTrait, ArchiveAssertionsTrait { class MavenProjectTest extends Specification implements MockMavenServerTrait, GradleProjectTestTrait {
@RestoreSystemProperties @RestoreSystemProperties
@Unroll @Unroll
def "publish lib #version #gradle"() { def "publish lib #version #gradleVersion"() {
given: setup:
setProperty('loom.test.version', version) setProperty('loom.test.version', version)
library = true def gradle = gradleProject(project: "mavenLibrary", version: gradleVersion, sharedFiles: true)
when: when:
def result = create("publish", gradle) def result = gradle.run(tasks: ["clean", "publish"])
then: then:
result.task(":publish").outcome == SUCCESS result.task(":publish").outcome == SUCCESS
hasArchiveEntry("fabric-example-lib-${version}.jar", "net/fabricmc/example/ExampleLib.class") gradle.hasOutputZipEntry("fabric-example-lib-${version}.jar", "net/fabricmc/example/ExampleLib.class")
where: where:
version | gradle version | gradleVersion
'1.0.0' | DEFAULT_GRADLE '1.0.0' | DEFAULT_GRADLE
'1.0.0' | PRE_RELEASE_GRADLE '1.0.0' | PRE_RELEASE_GRADLE
'1.1.0' | DEFAULT_GRADLE '1.1.0' | DEFAULT_GRADLE
@@ -64,17 +68,20 @@ class MavenProjectTest extends Specification implements MockMavenServerTrait, Ar
@RestoreSystemProperties @RestoreSystemProperties
@Unroll @Unroll
def "resolve #version #gradle"() { def "resolve #version #gradleVersion"() {
given: given:
setProperty('loom.test.resolve', "com.example:fabric-example-lib:${version}") setProperty('loom.test.resolve', "com.example:fabric-example-lib:${version}")
library = false def gradle = gradleProject(project: "maven", version: gradleVersion, sharedFiles: true)
when: when:
def result = create("build", gradle) def result = gradle.run(tasks: ["clean", "build"])
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
hasArchiveEntry("fabric-example-mod-1.0.0.jar", "net/fabricmc/examplemod/ExampleMod.class") gradle.hasOutputZipEntry("fabric-example-mod-1.0.0.jar", "net/fabricmc/examplemod/ExampleMod.class")
where: where:
version | gradle version | gradleVersion
'1.0.0' | DEFAULT_GRADLE '1.0.0' | DEFAULT_GRADLE
'1.0.0' | PRE_RELEASE_GRADLE '1.0.0' | PRE_RELEASE_GRADLE
'1.1.+' | DEFAULT_GRADLE '1.1.+' | DEFAULT_GRADLE
@@ -87,12 +94,4 @@ class MavenProjectTest extends Specification implements MockMavenServerTrait, Ar
'2.0.0-SNAPSHOT:classifier' | DEFAULT_GRADLE '2.0.0-SNAPSHOT:classifier' | DEFAULT_GRADLE
'master-SNAPSHOT:classifier' | DEFAULT_GRADLE 'master-SNAPSHOT:classifier' | DEFAULT_GRADLE
} }
// Set to true when to build and publish the mavenLibrary
private boolean library = false
@Override
String name() {
library ? "mavenLibrary" : "maven"
}
} }

View File

@@ -24,53 +24,50 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import java.util.jar.JarFile import java.util.jar.JarFile
import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class MixinApAutoRefmapTest extends Specification implements ProjectTestTrait { class MixinApAutoRefmapTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"mixinApAutoRefmap"
}
@Unroll @Unroll
def "build (gradle #gradle)"() { def "build (gradle #version)"() {
setup:
def gradle = gradleProject(project: "mixinApAutoRefmap", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
// verify the ref-map name is correctly generated // verify the ref-map name is correctly generated
def jar = new JarFile(getOutputFile("fabric-example-mod-1.0.0-universal.jar").absoluteFile) def jar = new JarFile(gradle.getOutputFile("fabric-example-mod-1.0.0-universal.jar").absoluteFile)
jar.getEntry("refmap0000.json") == null jar.getEntry("refmap0000.json") == null
jar.getEntry("refmap0001.json") != null jar.getEntry("refmap0001.json") != null
jar.getEntry("refmap0002.json") != null jar.getEntry("refmap0002.json") != null
jar.getEntry("refmap0003.json") != null jar.getEntry("refmap0003.json") != null
def j1 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("main.mixins.json")))) def j1 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("main.mixins.json"))))
j1.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0001.json" j1.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0001.json"
def j2 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("blabla.json")))) def j2 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("blabla.json"))))
j2.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0002.json" j2.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0002.json"
def j3 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m1_1.mixins.json")))) def j3 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m1_1.mixins.json"))))
j3.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0003.json" j3.asJsonObject.getAsJsonPrimitive("refmap").getAsString() == "refmap0003.json"
def j4 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m1_2.mixins.json")))) def j4 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("m1_2.mixins.json"))))
!j4.asJsonObject.has("refmap") !j4.asJsonObject.has("refmap")
def j5 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("irrelevant.mixins.json")))) def j5 = JsonParser.parseReader(new InputStreamReader(jar.getInputStream(jar.getEntry("irrelevant.mixins.json"))))
!j5.asJsonObject.has("refmap") !j5.asJsonObject.has("refmap")
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -24,40 +24,38 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import java.util.jar.JarFile import java.util.jar.JarFile
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class MixinApSimpleTest extends Specification implements ProjectTestTrait { class MixinApSimpleTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"mixinApSimple"
}
@Unroll @Unroll
def "build (gradle #gradle)"() { def "build (gradle #version)"() {
setup:
def gradle = gradleProject(project: "mixinApSimple", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
// verify the ref-map name is correctly generated // verify the ref-map name is correctly generated
def main = new JarFile(getOutputFile("fabric-example-mod-1.0.0-dev.jar").absoluteFile) def main = new JarFile(gradle.getOutputFile("fabric-example-mod-1.0.0-dev.jar").absoluteFile)
main.getEntry("main-refmap0000.json") != null main.getEntry("main-refmap0000.json") != null
def mixin = new JarFile(getOutputFile("fabric-example-mod-1.0.0-mixin.jar").absoluteFile) def mixin = new JarFile(gradle.getOutputFile("fabric-example-mod-1.0.0-mixin.jar").absoluteFile)
mixin.getEntry("default-refmap0000.json") != null mixin.getEntry("default-refmap0000.json") != null
def mixin1 = new JarFile(getOutputFile("fabric-example-mod-1.0.0-mixin1.jar").absoluteFile) def mixin1 = new JarFile(gradle.getOutputFile("fabric-example-mod-1.0.0-mixin1.jar").absoluteFile)
mixin1.getEntry("main-refmap0000.json") == null mixin1.getEntry("main-refmap0000.json") == null
mixin1.getEntry("default-refmap0000.json") == null mixin1.getEntry("default-refmap0000.json") == null
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -24,27 +24,26 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class MojangMappingsProjectTest extends Specification implements ProjectTestTrait { class MojangMappingsProjectTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"mojangMappings"
}
@Unroll @Unroll
def "build (gradle #gradle)"() { def "build (gradle #version)"() {
setup:
def gradle = gradleProject(project: "mojangMappings", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -24,23 +24,22 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ArchiveAssertionsTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import net.fabricmc.loom.test.util.ProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class MultiProjectTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait { class MultiProjectTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"multiproject"
}
@Unroll @Unroll
def "build (gradle #gradle)"() { def "build (gradle #version)"() {
setup:
def gradle = gradleProject(project: "multiproject", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
result.task(":core:build").outcome == SUCCESS result.task(":core:build").outcome == SUCCESS
@@ -49,13 +48,11 @@ class MultiProjectTest extends Specification implements ProjectTestTrait, Archiv
result.task(":remapAllJars").outcome == SUCCESS result.task(":remapAllJars").outcome == SUCCESS
result.task(":remapAllSources").outcome == SUCCESS result.task(":remapAllSources").outcome == SUCCESS
hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/example-1.0.0.jar") gradle.hasOutputZipEntry("multiproject-1.0.0.jar", "META-INF/jars/example-1.0.0.jar")
hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/core-1.0.0.jar") gradle.hasOutputZipEntry("multiproject-1.0.0.jar", "META-INF/jars/core-1.0.0.jar")
hasArchiveEntry("multiproject-1.0.0.jar", "META-INF/jars/fabric-api-base-0.2.1+9354966b7d.jar") gradle.hasOutputZipEntry("multiproject-1.0.0.jar", "META-INF/jars/fabric-api-base-0.2.1+9354966b7d.jar")
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -24,29 +24,26 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class ParchmentTest extends Specification implements ProjectTestTrait { class ParchmentTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"parchment"
}
@Unroll @Unroll
def "parchment #gradle"() { def "parchment #version"() {
setup:
def gradle = gradleProject(project: "parchment", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
} }

View File

@@ -27,40 +27,37 @@ package net.fabricmc.loom.test.integration
import com.google.common.hash.HashCode import com.google.common.hash.HashCode
import com.google.common.hash.Hashing import com.google.common.hash.Hashing
import com.google.common.io.Files import com.google.common.io.Files
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import spock.util.environment.RestoreSystemProperties import spock.util.environment.RestoreSystemProperties
import static net.fabricmc.loom.test.LoomTestConstants.*
import static java.lang.System.setProperty import static java.lang.System.setProperty
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class ReproducibleBuildTest extends Specification implements ProjectTestTrait { class ReproducibleBuildTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"reproducible"
}
@RestoreSystemProperties @RestoreSystemProperties
@Unroll @Unroll
def "build (gradle #gradle)"() { def "build (gradle #version)"() {
setup:
def gradle = gradleProject(project: "reproducible", version: version)
when: when:
setProperty('loom.test.reproducible', 'true') setProperty('loom.test.reproducible', 'true')
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
getOutputHash("fabric-example-mod-1.0.0.jar") == modHash generateMD5(gradle.getOutputFile("fabric-example-mod-1.0.0.jar")) == modHash
getOutputHash("fabric-example-mod-1.0.0-sources.jar") in sourceHash // Done for different line endings. generateMD5(gradle.getOutputFile("fabric-example-mod-1.0.0-sources.jar")) in sourceHash // Done for different line endings.
where: where:
gradle | modHash | sourceHash version | modHash | sourceHash
DEFAULT_GRADLE | "ed3306ef60f434c55048cba8de5dab95" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"] DEFAULT_GRADLE | "ed3306ef60f434c55048cba8de5dab95" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"]
PRE_RELEASE_GRADLE | "ed3306ef60f434c55048cba8de5dab95" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"] PRE_RELEASE_GRADLE | "ed3306ef60f434c55048cba8de5dab95" | ["be31766e6cafbe4ae3bca9e35ba63169", "7348b0bd87d36d7ec6f3bca9c2b66062"]
} }
String getOutputHash(String name) {
generateMD5(getOutputFile(name))
}
String generateMD5(File file) { String generateMD5(File file) {
HashCode hash = Files.asByteSource(file).hash(Hashing.md5()) HashCode hash = Files.asByteSource(file).hash(Hashing.md5())
return hash.asBytes().encodeHex() as String return hash.asBytes().encodeHex() as String

View File

@@ -24,25 +24,25 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll import spock.lang.Unroll
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
// This test runs a mod that exits on mod init // This test runs a mod that exits on mod init
class RunConfigTest extends Specification implements ProjectTestTrait { class RunConfigTest extends Specification implements GradleProjectTestTrait {
@Override
String name() {
"runconfigs"
}
@Unroll @Unroll
def "#task"() { def "Run config #task"() {
setup:
def gradle = gradleProject(project: "runconfigs", sharedFiles: true)
when: when:
def result = create(task) def result = gradle.run(task: task)
then: then:
result.task(":${task}").outcome == SUCCESS result.task(":${task}").outcome == SUCCESS
where: where:
task | _ task | _
'runClient' | _ 'runClient' | _

View File

@@ -24,14 +24,14 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ArchiveAssertionsTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import net.fabricmc.loom.test.util.MockMavenServerTrait import net.fabricmc.loom.test.util.MockMavenServerTrait
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Stepwise import spock.lang.Stepwise
import spock.lang.Unroll import spock.lang.Unroll
import spock.util.environment.RestoreSystemProperties import spock.util.environment.RestoreSystemProperties
import static net.fabricmc.loom.test.LoomTestConstants.*
import static java.lang.System.setProperty import static java.lang.System.setProperty
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
@@ -39,25 +39,22 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
* This tests publishing signed artifacts to a maven server * This tests publishing signed artifacts to a maven server
*/ */
@Stepwise @Stepwise
class SignedProjectTest extends Specification implements MockMavenServerTrait, ArchiveAssertionsTrait { class SignedProjectTest extends Specification implements MockMavenServerTrait, GradleProjectTestTrait {
@Unroll @Unroll
@RestoreSystemProperties @RestoreSystemProperties
def "sign and publish lib #gradle"() { def "sign and publish lib #version"() {
given: setup:
setProperty('loom.test.secretKey', PRIVATE_KEY) setProperty('loom.test.secretKey', PRIVATE_KEY)
def gradle = gradleProject(project: "signed", version: version)
when: when:
def result = create("publish", gradle) def result = gradle.run(task: "publish")
then: then:
result.task(":publish").outcome == SUCCESS result.task(":publish").outcome == SUCCESS
where:
gradle | _
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
}
@Override where:
String name() { version << STANDARD_TEST_VERSIONS
"signed"
} }
static final String PRIVATE_KEY = """ static final String PRIVATE_KEY = """

View File

@@ -24,36 +24,48 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ArchiveAssertionsTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.ServerRunner
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Timeout
import spock.lang.Unroll import spock.lang.Unroll
import java.util.concurrent.TimeUnit
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
import static net.fabricmc.loom.test.LoomTestConstants.*
class SimpleProjectTest extends Specification implements ProjectTestTrait, ArchiveAssertionsTrait { @Timeout(value = 20, unit = TimeUnit.MINUTES)
@Override class SimpleProjectTest extends Specification implements GradleProjectTestTrait {
String name() {
"simple"
}
@Unroll @Unroll
def "build (gradle #gradle)"() { def "build and run (gradle #version)"() {
setup:
def gradle = gradleProject(project: "simple", version: version)
def server = ServerRunner.create(gradle.projectDir, "1.16.5")
.withMod(gradle.getOutputFile("fabric-example-mod-1.0.0.jar"))
.withFabricApi()
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
def serverResult = server.run()
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
getArchiveEntry("fabric-example-mod-1.0.0.jar", "META-INF/MANIFEST.MF").contains("Fabric-Loom-Version: 0.0.0+unknown") gradle.getOutputZipEntry("fabric-example-mod-1.0.0.jar", "META-INF/MANIFEST.MF").contains("Fabric-Loom-Version: 0.0.0+unknown")
serverResult.successful()
serverResult.output.contains("Hello simple Fabric mod") // A check to ensure our mod init was actually called
where: where:
gradle | _ version | _
DEFAULT_GRADLE | _ DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _ PRE_RELEASE_GRADLE | _
} }
@Unroll @Unroll
def "#ide config generation"() { def "#ide config generation"() {
setup:
def gradle = gradleProject(project: "simple", sharedFiles: true)
when: when:
def result = create(ide) def result = gradle.run(task: ide)
then: then:
result.task(":${ide}").outcome == SUCCESS result.task(":${ide}").outcome == SUCCESS
where: where:

View File

@@ -24,47 +24,48 @@
package net.fabricmc.loom.test.integration package net.fabricmc.loom.test.integration
import net.fabricmc.loom.test.util.ProjectTestTrait import net.fabricmc.loom.test.util.GradleProjectTestTrait
import org.zeroturnaround.zip.ZipUtil import org.zeroturnaround.zip.ZipUtil
import spock.lang.Specification import spock.lang.Specification
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import static net.fabricmc.loom.test.LoomTestConstants.*
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS import static org.gradle.testkit.runner.TaskOutcome.SUCCESS
class UnpickTest extends Specification implements ProjectTestTrait { class UnpickTest extends Specification implements GradleProjectTestTrait {
static final String MAPPINGS = "21w13a/net.fabricmc.yarn.21w13a.21w13a+build.30-v2" static final String MAPPINGS = "21w13a/net.fabricmc.yarn.21w13a.21w13a+build.30-v2"
@Override
String name() {
"unpick"
}
def "unpick decompile"() { def "unpick decompile"() {
setup:
def gradle = gradleProject(project: "unpick", version: version)
when: when:
def result = create("genSources", gradle) def result = gradle.run(task: "genSources")
then: then:
result.task(":genSources").outcome == SUCCESS result.task(":genSources").outcome == SUCCESS
getClassSource("net/minecraft/block/CakeBlock.java").contains("Block.DEFAULT_SET_BLOCK_STATE_FLAG") getClassSource(gradle, "net/minecraft/block/CakeBlock.java").contains("Block.DEFAULT_SET_BLOCK_STATE_FLAG")
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
def "unpick build"() { def "unpick build"() {
setup:
def gradle = gradleProject(project: "unpick", version: version)
when: when:
def result = create("build", gradle) def result = gradle.run(task: "build")
then: then:
result.task(":build").outcome == SUCCESS result.task(":build").outcome == SUCCESS
where: where:
gradle | _ version << STANDARD_TEST_VERSIONS
DEFAULT_GRADLE | _
PRE_RELEASE_GRADLE | _
} }
String getClassSource(String classname, String mappings = MAPPINGS) { private static String getClassSource(GradleProject gradle, String classname, String mappings = MAPPINGS) {
File sourcesJar = getGeneratedSources(mappings) File sourcesJar = gradle.getGeneratedSources(mappings)
return new String(ZipUtil.unpackEntry(sourcesJar, classname), StandardCharsets.UTF_8) return new String(ZipUtil.unpackEntry(sourcesJar, classname), StandardCharsets.UTF_8)
} }
} }

View File

@@ -30,10 +30,12 @@ import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsProcessor import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsProcessor
import net.fabricmc.loom.configuration.providers.mappings.MappingContext import net.fabricmc.loom.configuration.providers.mappings.MappingContext
import net.fabricmc.loom.configuration.providers.mappings.MappingLayer import net.fabricmc.loom.configuration.providers.mappings.MappingLayer
import net.fabricmc.loom.configuration.providers.mappings.MappingNamespace
import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider
import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec import net.fabricmc.loom.configuration.providers.mappings.MappingsSpec
import net.fabricmc.mappingio.adapter.MappingDstNsReorder
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch
import net.fabricmc.mappingio.format.Tiny2Writer import net.fabricmc.mappingio.format.Tiny2Writer
import net.fabricmc.mappingio.tree.MappingTree
import net.fabricmc.mappingio.tree.MemoryMappingTree import net.fabricmc.mappingio.tree.MemoryMappingTree
import org.gradle.api.logging.Logger import org.gradle.api.logging.Logger
import spock.lang.Specification import spock.lang.Specification
@@ -90,6 +92,14 @@ abstract class LayeredMappingsSpecification extends Specification implements Lay
return sw.toString() return sw.toString()
} }
MemoryMappingTree reorder(MemoryMappingTree mappingTree) {
def reorderedMappings = new MemoryMappingTree()
def nsReorder = new MappingDstNsReorder(reorderedMappings, Collections.singletonList(MappingNamespace.NAMED.stringValue()))
def nsSwitch = new MappingSourceNsSwitch(nsReorder, MappingNamespace.INTERMEDIARY.stringValue(), true)
mappingTree.accept(nsSwitch)
return reorderedMappings
}
@CompileStatic @CompileStatic
class TestMappingContext implements MappingContext { class TestMappingContext implements MappingContext {
@Override @Override

View File

@@ -31,14 +31,14 @@ interface LayeredMappingsTestConstants {
public static final String INTERMEDIARY_1_16_5_URL = "https://maven.fabricmc.net/net/fabricmc/intermediary/1.16.5/intermediary-1.16.5-v2.jar" public static final String INTERMEDIARY_1_16_5_URL = "https://maven.fabricmc.net/net/fabricmc/intermediary/1.16.5/intermediary-1.16.5-v2.jar"
public static final Map<String, MinecraftVersionMeta.Download> DOWNLOADS_1_17 = [ public static final Map<String, MinecraftVersionMeta.Download> DOWNLOADS_1_17 = [
client_mappings:new MinecraftVersionMeta.Download(null, "227d16f520848747a59bef6f490ae19dc290a804", 6431705, "https://launcher.mojang.com/v1/objects/227d16f520848747a59bef6f490ae19dc290a804/client.txt"), client_mappings: new MinecraftVersionMeta.Download(null, "227d16f520848747a59bef6f490ae19dc290a804", 6431705, "https://launcher.mojang.com/v1/objects/227d16f520848747a59bef6f490ae19dc290a804/client.txt"),
server_mappings:new MinecraftVersionMeta.Download(null, "84d80036e14bc5c7894a4fad9dd9f367d3000334", 4948536, "https://launcher.mojang.com/v1/objects/84d80036e14bc5c7894a4fad9dd9f367d3000334/server.txt") server_mappings: new MinecraftVersionMeta.Download(null, "84d80036e14bc5c7894a4fad9dd9f367d3000334", 4948536, "https://launcher.mojang.com/v1/objects/84d80036e14bc5c7894a4fad9dd9f367d3000334/server.txt")
] ]
public static final MinecraftVersionMeta VERSION_META_1_17 = new MinecraftVersionMeta(null, null, null, 0, DOWNLOADS_1_17, null, null, null, null, 0, null, null, null) public static final MinecraftVersionMeta VERSION_META_1_17 = new MinecraftVersionMeta(null, null, null, 0, DOWNLOADS_1_17, null, null, null, null, 0, null, null, null)
public static final Map<String, MinecraftVersionMeta.Download> DOWNLOADS_1_16_5 = [ public static final Map<String, MinecraftVersionMeta.Download> DOWNLOADS_1_16_5 = [
client_mappings:new MinecraftVersionMeta.Download(null, "e3dfb0001e1079a1af72ee21517330edf52e6192", 5746047, "https://launcher.mojang.com/v1/objects/e3dfb0001e1079a1af72ee21517330edf52e6192/client.txt"), client_mappings: new MinecraftVersionMeta.Download(null, "e3dfb0001e1079a1af72ee21517330edf52e6192", 5746047, "https://launcher.mojang.com/v1/objects/e3dfb0001e1079a1af72ee21517330edf52e6192/client.txt"),
server_mappings:new MinecraftVersionMeta.Download(null, "81d5c793695d8cde63afddb40dde88e3a88132ac", 4400926, "https://launcher.mojang.com/v1/objects/81d5c793695d8cde63afddb40dde88e3a88132ac/server.txt") server_mappings: new MinecraftVersionMeta.Download(null, "81d5c793695d8cde63afddb40dde88e3a88132ac", 4400926, "https://launcher.mojang.com/v1/objects/81d5c793695d8cde63afddb40dde88e3a88132ac/server.txt")
] ]
public static final MinecraftVersionMeta VERSION_META_1_16_5 = new MinecraftVersionMeta(null, null, null, 0, DOWNLOADS_1_16_5, null, null, null, null, 0, null, null, null) public static final MinecraftVersionMeta VERSION_META_1_16_5 = new MinecraftVersionMeta(null, null, null, 0, DOWNLOADS_1_16_5, null, null, null, null, 0, null, null, null)

View File

@@ -27,7 +27,6 @@ package net.fabricmc.loom.test.unit.layeredmappings
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec
import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpec
import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpec import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpec
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionMeta
class ParchmentMappingLayerTest extends LayeredMappingsSpecification { class ParchmentMappingLayerTest extends LayeredMappingsSpecification {
def "Read parchment mappings" () { def "Read parchment mappings" () {
@@ -39,16 +38,18 @@ class ParchmentMappingLayerTest extends LayeredMappingsSpecification {
def mappings = getLayeredMappings( def mappings = getLayeredMappings(
new IntermediaryMappingsSpec(), new IntermediaryMappingsSpec(),
new MojangMappingsSpec(), new MojangMappingsSpec(),
new ParchmentMappingsSpec(PARCHMENT_NOTATION, false) new ParchmentMappingsSpec(PARCHMENT_NOTATION, true)
) )
def tiny = getTiny(mappings) def tiny = getTiny(mappings)
def reorderedMappings = reorder(mappings)
then: then:
mappings.srcNamespace == "named" mappings.srcNamespace == "named"
mappings.dstNamespaces == ["intermediary", "official"] mappings.dstNamespaces == ["intermediary", "official"]
mappings.classes.size() == 5747 mappings.classes.size() == 5747
mappings.classes[0].srcName.hashCode() == -1112444138 // MojMap name, just check the hash mappings.classes[0].srcName.hashCode() == -1112444138 // MojMap name, just check the hash
mappings.classes[0].getDstName(0) == "net/minecraft/class_2573" mappings.classes[0].getDstName(0) == "net/minecraft/class_2573"
mappings.classes[0].methods[0].args[0].srcName == "pStack" mappings.classes[0].methods[0].args[0].srcName.hashCode() == 109757064
reorderedMappings.getClass("net/minecraft/class_2573").getMethod("method_10913", "(Lnet/minecraft/class_1799;Lnet/minecraft/class_1767;)V").args.size() > 0
} }
def "Read parchment mappings remove prefix" () { def "Read parchment mappings remove prefix" () {

View File

@@ -0,0 +1,213 @@
/*
* 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.test.util
import groovy.transform.Immutable
import net.fabricmc.loom.test.LoomTestConstants
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import org.zeroturnaround.zip.ZipUtil
import spock.lang.Shared
trait GradleProjectTestTrait {
@Lazy
@Shared
private static File sharedProjectDir = File.createTempDir()
@Lazy
@Shared
private static File sharedGradleHomeDir = File.createTempDir()
GradleProject gradleProject(Map options) {
String gradleVersion = options.version as String ?: LoomTestConstants.DEFAULT_GRADLE
String warningMode = options.warningMode as String ?: "fail"
File projectDir = options.projectDir as File ?: options.sharedFiles ? sharedProjectDir : File.createTempDir()
File gradleHomeDir = options.gradleHomeDir as File ?: options.sharedFiles ? sharedGradleHomeDir : File.createTempDir()
setupProject(options, projectDir)
return new GradleProject(
gradleVersion: gradleVersion,
projectDir: projectDir.absolutePath,
gradleHomeDir: gradleHomeDir.absolutePath,
warningMode: warningMode
)
}
private void setupProject(Map options, File projectDir) {
if (options.project) {
copyProjectFromResources(options.project as String, projectDir)
return
}
if (options.repo) {
String repo = options.repo
String commit = options.commit
exec(projectDir, "git", "clone", repo, ".")
exec(projectDir, "git", "checkout", commit)
if (options.patch) {
def patchFile = new File("src/test/resources/patches/${options.patch}.patch")
if (!patchFile.exists()) {
throw new FileNotFoundException("Could not find patch file at: " + patchFile.absolutePath)
}
exec(projectDir, "git", "apply", patchFile.absolutePath)
}
return
}
throw new UnsupportedOperationException("No project setup method was supplied")
}
private void exec(File projectDir, String... args) {
def process = args.execute([], projectDir)
process.consumeProcessOutput(System.out, System.err)
def exitCode = process.waitFor()
if (exitCode != 0) {
throw new RuntimeException("Command failed with exit code: $exitCode")
}
}
private void copyProjectFromResources(String project, File projectDir) {
def projectSourceDir = new File("src/test/resources/projects/$project")
if (!projectSourceDir.exists()) {
throw new FileNotFoundException("Failed to find project directory at: $projectSourceDir.absolutePath")
}
// Cleanup some basic things if they already exists
new File(projectDir, "src").deleteDir()
new File(projectDir, "build.gradle").delete()
new File(projectDir, "settings.gradle").delete()
projectSourceDir.eachFileRecurse { file ->
if (file.isDirectory()) {
return
}
def path = file.path.replace(projectSourceDir.path, "")
File tempFile = new File(projectDir, path)
if (tempFile.exists()) {
tempFile.delete()
}
tempFile.parentFile.mkdirs()
tempFile.bytes = file.bytes
}
}
@Immutable
static class GradleProject {
private String gradleVersion
private String projectDir
private String gradleHomeDir
private String warningMode
BuildResult run(Map options) {
// Setup the system props to tell loom that its running in a test env
// And override the CI check to ensure that everything is ran
System.setProperty("fabric.loom.test", "true")
System.setProperty("fabric.loom.ci", "false")
System.setProperty("maven.repo.local", new File(getGradleHomeDir(), "m2").absolutePath)
def runner = this.runner
def args = []
if (options.task) {
args << options.task
}
args.addAll(options.tasks ?: [])
args << "--stacktrace"
args << "--warning-mode" << warningMode
args << "--gradle-user-home" << gradleHomeDir
args.addAll(options.args ?: [])
runner.withArguments(args as String[])
return runner.build()
}
private GradleRunner getRunner() {
return GradleRunner.create()
.withProjectDir(getProjectDir())
.withPluginClasspath()
.withGradleVersion(gradleVersion)
.forwardOutput()
.withDebug(true)
}
File getProjectDir() {
return new File(projectDir)
}
File getGradleHomeDir() {
return new File(gradleHomeDir)
}
File getOutputFile(String filename) {
return new File(getProjectDir(), "build/libs/$filename")
}
void printOutputFiles() {
new File(getProjectDir(), "build/libs/").listFiles().each {
println(it.name)
}
}
File getBuildGradle() {
return new File(getProjectDir(), "build.gradle")
}
String getOutputZipEntry(String filename, String entryName) {
def file = getOutputFile(filename)
def bytes = ZipUtil.unpackEntry(file, entryName)
if (bytes == null) {
throw new FileNotFoundException("Could not find ${entryName} in ${entryName}")
}
new String(bytes as byte[])
}
boolean hasOutputZipEntry(String filename, String entryName) {
def file = getOutputFile(filename)
return ZipUtil.unpackEntry(file, entryName) != null
}
File getGeneratedSources(String mappings) {
return new File(getGradleHomeDir(), "caches/fabric-loom/${mappings}/minecraft-mapped-sources.jar")
}
}
}

View File

@@ -27,7 +27,7 @@ package net.fabricmc.loom.test.util
import io.javalin.Javalin import io.javalin.Javalin
import org.apache.commons.io.IOUtils import org.apache.commons.io.IOUtils
trait MockMavenServerTrait extends ProjectTestTrait { trait MockMavenServerTrait {
public final int mavenServerPort = 9876 public final int mavenServerPort = 9876
public final File testMavenDir = File.createTempDir() public final File testMavenDir = File.createTempDir()
private Javalin server private Javalin server
@@ -74,7 +74,6 @@ trait MockMavenServerTrait extends ProjectTestTrait {
@SuppressWarnings('unused') @SuppressWarnings('unused')
def cleanupSpec() { def cleanupSpec() {
server.stop() server.stop()
super.cleanupSpec()
} }
File getMavenDirectory() { File getMavenDirectory() {

View File

@@ -1,126 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-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.test.util
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
trait ProjectTestTrait {
final static String DEFAULT_GRADLE = "7.0.1"
final static String PRE_RELEASE_GRADLE = "7.3-20210807021145+0000"
static File gradleHome = File.createTempDir()
File testProjectDir = File.createTempDir()
abstract String name()
def copyInputFiles() {
println "Project directory: ${testProjectDir}"
def baseProjectDir = new File("src/test/resources/projects/" + name())
if (!baseProjectDir.exists()) {
throw new FileNotFoundException("Failed to find project directory at:" + baseProjectDir.absolutePath)
}
baseProjectDir.eachFileRecurse { file ->
if (file.isDirectory()) {
return
}
def path = file.path.replace(baseProjectDir.path, "")
File tempFile = new File(testProjectDir, path)
if (tempFile.exists()) {
tempFile.delete()
}
tempFile.parentFile.mkdirs()
tempFile.bytes = file.bytes
}
// Disable the CI checks to ensure nothing is skipped
System.setProperty("fabric.loom.ci", "false")
}
@SuppressWarnings('unused')
def cleanup() {
// Clean after each test
new File(testProjectDir, "build").deleteDir()
new File(testProjectDir, ".gradle").deleteDir()
}
@SuppressWarnings('unused')
def cleanupSpec() {
testProjectDir.deleteDir()
gradleHome.deleteDir()
}
File buildGradle() {
return new File(testProjectDir, "build.gradle")
}
def filesReady() {
}
BuildResult create(String task, String gradleVersion = DEFAULT_GRADLE) {
System.setProperty("fabric.loom.test", "true")
copyInputFiles()
filesReady()
GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments(task, "--stacktrace", "--warning-mode", warningMode(gradleVersion), "--gradle-user-home", gradleHomeDirectory(gradleVersion))
.withPluginClasspath()
.withGradleVersion(gradleVersion)
.forwardOutput()
.withDebug(true)
.build()
}
String warningMode(String gradleVersion) {
'fail'
}
String gradleHomeDirectory(String gradleVersion) {
// Each gradle version gets its own dir to run on, to ensure that a full run is done.
new File(gradleHome, gradleVersion).absolutePath
}
File getOutputFile(String name, String project = "") {
def file = new File(testProjectDir, "${project}build/libs/${name}")
if (!file.exists()) {
throw new FileNotFoundException("Could not find ${name} at ${file.absolutePath}")
}
return file
}
File getGeneratedSources(String mappings, String gradleVersion = DEFAULT_GRADLE) {
return new File(gradleHomeDirectory(gradleVersion), "caches/fabric-loom/${mappings}/minecraft-mapped-sources.jar")
}
}

View File

@@ -0,0 +1,208 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2016-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.test.util
import groovy.transform.Immutable
import java.util.concurrent.TimeUnit
class ServerRunner {
static final String LOADER_VERSION = "0.11.6"
static final Map<String, String> FABRIC_API_URLS = [
"1.16.5": "https://github.com/FabricMC/fabric/releases/download/0.37.1%2B1.16/fabric-api-0.37.1+1.16.jar",
"1.17.1": "https://github.com/FabricMC/fabric/releases/download/0.37.1%2B1.17/fabric-api-0.37.1+1.17.jar"
]
final File serverDir
final String minecraftVersion
final List<File> mods = []
private ServerRunner(File serverDir, String minecraftVersion) {
this.serverDir = serverDir
this.minecraftVersion = minecraftVersion
this.serverDir.mkdirs()
}
static ServerRunner create(File testProjectDir, String minecraftVersion) {
return new ServerRunner(new File(testProjectDir, "server"), minecraftVersion)
}
def install() {
def args = [
"server",
"-dir",
serverDir.absolutePath,
"-mcversion",
minecraftVersion,
"-loader",
LOADER_VERSION,
"-downloadMinecraft"
]
//noinspection UnnecessaryQualifiedReference
net.fabricmc.installer.Main.main(args as String[])
def eulaFile = new File(serverDir, "eula.txt")
eulaFile << "eula=true"
def serverPropsFile = new File(serverDir, "server.properties")
serverPropsFile << "level-type=FLAT" // Generates the world faster
}
ServerRunner withMod(File file) {
mods << file
return this
}
ServerRunner downloadMod(String url, String filename) {
File modFile = new File(serverDir, "downloadedMods/" + filename)
modFile.parentFile.mkdirs()
println("Downloading " + url)
modFile.bytes = new URL(url).bytes
return withMod(modFile)
}
ServerRunner withFabricApi() {
if (!FABRIC_API_URLS[minecraftVersion]) {
throw new UnsupportedOperationException("No Fabric api url for " + minecraftVersion)
}
return downloadMod(FABRIC_API_URLS[minecraftVersion], "fabricapi.jar")
}
ServerRunResult run() {
install()
// Copy the mods here so we can
mods.each {
if (!it.exists()) {
throw new FileNotFoundException(it.absolutePath)
}
File modFile = new File(serverDir, "mods/" + it.name)
modFile.parentFile.mkdirs()
modFile.bytes = it.bytes
}
String javaExecutablePath = ProcessHandle.current()
.info()
.command()
.orElseThrow()
var builder = new ProcessBuilder()
builder.directory(serverDir)
builder.command(javaExecutablePath, "-Xmx1G", "-jar", "fabric-server-launch.jar", "nogui")
Process process = builder.start()
def out = new StringBuffer()
def isStopping = false
process.consumeProcessOutput(
new ForwardingAppendable([System.out, out], {
if (!isStopping && out.contains("Done ") && out.contains("For help, type \"help\"")) {
isStopping = true
Thread.start {
println("Stopping server in 5 seconds")
sleep(5000)
println("Sending stop command")
process.outputStream.withCloseable {
it.write("stop\n".bytes)
}
}
}
}),
new ForwardingAppendable([System.err, out])
)
addShutdownHook {
if (process.alive) {
process.destroy()
}
}
assert process.waitFor(10, TimeUnit.MINUTES)
int exitCode = process.exitValue()
println("Sever closed with exit code: " + exitCode)
return new ServerRunResult(exitCode, out.toString())
}
@Immutable
class ServerRunResult {
int exitCode
String output
boolean successful() {
return exitCode == 0 && output.contains("Done ")
}
}
private class ForwardingAppendable implements Appendable {
final List<Appendable> appendables
final Closure onAppended
ForwardingAppendable(List<Appendable> appendables, Closure onAppended = {}) {
this.appendables = appendables
this.onAppended = onAppended
}
@Override
Appendable append(CharSequence csq) throws IOException {
appendables.each {
it.append(csq)
}
onAppended.run()
return this
}
@Override
Appendable append(CharSequence csq, int start, int end) throws IOException {
appendables.each {
it.append(csq, start, end)
}
onAppended.run()
return this
}
@Override
Appendable append(char c) throws IOException {
appendables.each {
it.append(c)
}
onAppended.run()
return this
}
}
}

View File

@@ -0,0 +1,22 @@
diff --git a/build.gradle b/build.gradle
--- a/build.gradle (revision fc40aa9d88e9457957bdf3f8cec9698846828cd3)
+++ b/build.gradle (date 1631009569915)
@@ -257,6 +257,9 @@
setupRepositories(repositories)
}
+ // Required as moduleDependencies modifies the pom
+ loom.disableDeprecatedPomGeneration(publishing.publications.mavenJava)
+
javadoc.enabled = false
}
@@ -296,6 +299,8 @@
setupRepositories(repositories)
}
+loom.disableDeprecatedPomGeneration(publishing.publications.mavenJava)
+
void setupRepositories(RepositoryHandler repositories) {
//repositories.mavenLocal() // uncomment for testing
def ENV = System.getenv()

View File

@@ -76,13 +76,7 @@ jar {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven from components.java
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
} }
} }

View File

@@ -72,13 +72,7 @@ jar {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven from components.java
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
} }
} }

View File

@@ -76,13 +76,7 @@ loom {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven from components.java
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
} }
} }

View File

@@ -80,13 +80,7 @@ jar {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven from components.java
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
} }
} }

View File

@@ -30,16 +30,11 @@ java {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
from components.java
artifact(remapJar) { artifact(remapJar) {
builtBy remapJar
}
artifact(remapJar) {
builtBy remapJar
classifier "classifier" classifier "classifier"
} }
artifact(sourcesJar) {
builtBy remapSourcesJar
}
} }
} }

View File

@@ -69,6 +69,8 @@ java {
loom { loom {
mixin { mixin {
useLegacyMixinAp = true
defaultRefmapName = "refmap0000.json" defaultRefmapName = "refmap0000.json"
add(sourceSets["main"], "refmap0001.json") add(sourceSets["main"], "refmap0001.json")
add(sourceSets["mixin"], "refmap0002.json") add(sourceSets["mixin"], "refmap0002.json")
@@ -118,13 +120,7 @@ assemble {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven from components.java
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
} }
} }

View File

@@ -68,6 +68,8 @@ java {
loom { loom {
mixin { mixin {
useLegacyMixinAp = true
defaultRefmapName = "default-refmap0000.json" defaultRefmapName = "default-refmap0000.json"
add(sourceSets["main"], "main-refmap0000.json") add(sourceSets["main"], "main-refmap0000.json")
add(sourceSets["mixin"]) add(sourceSets["mixin"])
@@ -99,13 +101,7 @@ assemble {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven from components.java
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
} }
} }

View File

@@ -72,13 +72,7 @@ jar {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven from components.java
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
} }
} }

View File

@@ -10,6 +10,12 @@ archivesBaseName = project.archives_base_name
version = project.mod_version version = project.mod_version
group = project.maven_group group = project.maven_group
loom {
mixin {
useLegacyMixinAp = true
}
}
dependencies { dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}" minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"

View File

@@ -29,16 +29,11 @@ java {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
artifact(remapJar) { from components.java
builtBy remapJar
}
artifact(remapJar) { artifact(remapJar) {
builtBy remapJar builtBy remapJar
classifier "classifier" classifier "classifier"
} }
artifact(sourcesJar) {
builtBy remapSourcesJar
}
} }
} }

View File

@@ -7,7 +7,7 @@ sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
archivesBaseName = project.archives_base_name archivesBaseName = project.archives_base_name
version = project.mod_version version = loom.modVersion
group = project.maven_group group = project.maven_group
repositories { repositories {
@@ -31,14 +31,6 @@ dependencies {
// You may need to force-disable transitiveness on them. // You may need to force-disable transitiveness on them.
} }
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
tasks.withType(JavaCompile).configureEach { tasks.withType(JavaCompile).configureEach {
// ensure that the encoding is set to UTF-8, no matter what the system default is // ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly // this fixes some edge cases with special characters not displaying correctly
@@ -72,13 +64,7 @@ jar {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven from components.java
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
} }
} }

View File

@@ -8,7 +8,6 @@ org.gradle.jvmargs=-Xmx1G
loader_version=0.11.2 loader_version=0.11.2
# Mod Properties # Mod Properties
mod_version = 1.0.0
maven_group = com.example maven_group = com.example
archives_base_name = fabric-example-mod archives_base_name = fabric-example-mod

View File

@@ -9,6 +9,6 @@ public class ExampleMod implements ModInitializer {
// However, some things (like resources) may still be uninitialized. // However, some things (like resources) may still be uninitialized.
// Proceed with mild caution. // Proceed with mild caution.
System.out.println("Hello Fabric world!"); System.out.println("Hello simple Fabric mod");
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"id": "modid", "id": "modid",
"version": "${version}", "version": "1.0.0",
"name": "Example Mod", "name": "Example Mod",
"description": "This is an example description! Tell everyone what your mod is about!", "description": "This is an example description! Tell everyone what your mod is about!",