From f4791f272dbd6f4df2feb209772ce1560931b27f Mon Sep 17 00:00:00 2001 From: Joe Date: Sun, 3 Oct 2021 16:07:37 +0100 Subject: [PATCH 01/15] Work so far --- subprojects/gradle-plugin/build.gradle.kts | 4 + .../gradle/vanilla/MinecraftExtension.java | 17 +++ .../internal/MinecraftExtensionImpl.java | 74 +++++++++- .../repository/MinecraftProviderService.java | 10 +- .../mappings/MappingsBuilderImpl.java | 132 ++++++++++++++++++ .../mappings/ProGuardMappingsReader.java | 26 ++++ .../modifier/AccessWidenerModifier.java | 3 +- .../repository/modifier/ArtifactModifier.java | 13 +- .../repository/modifier/MappingsModifier.java | 85 +++++++++++ .../modifier/OfficialMappingsModifier.java | 98 +++++++++++++ .../vanilla/repository/MappingsBuilder.java | 5 + .../vanilla/repository/MappingsReader.java | 11 ++ .../vanilla/repository/MinecraftResolver.java | 23 ++- .../repository/MinecraftResolverImpl.java | 54 ++----- .../gradle/vanilla/task/DecompileJarTask.java | 3 +- 15 files changed, 496 insertions(+), 62 deletions(-) create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/MappingsBuilderImpl.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingsReader.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsBuilder.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsReader.java diff --git a/subprojects/gradle-plugin/build.gradle.kts b/subprojects/gradle-plugin/build.gradle.kts index 92cfa0d9..8b29fa0f 100644 --- a/subprojects/gradle-plugin/build.gradle.kts +++ b/subprojects/gradle-plugin/build.gradle.kts @@ -16,6 +16,9 @@ val jarMerge by sourceSets.creating { val jarDecompile by sourceSets.creating { configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } } +val jarRemap by sourceSets.creating { + configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } +} val accessWiden by sourceSets.creating { configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } } @@ -123,6 +126,7 @@ tasks { jar { from(jarMerge.output) from(jarDecompile.output) + from(jarRemap.output) from(accessWiden.output) from(shadow.output) } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java index 4dd0df49..28501ca5 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java @@ -28,7 +28,10 @@ import groovy.lang.DelegatesTo; import org.gradle.api.Action; import org.gradle.api.Project; +import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; +import org.spongepowered.gradle.vanilla.repository.MappingsBuilder; +import org.spongepowered.gradle.vanilla.repository.MappingsReader; import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; import org.spongepowered.gradle.vanilla.repository.MinecraftRepositoryExtension; import org.spongepowered.gradle.vanilla.runs.RunConfigurationContainer; @@ -113,6 +116,20 @@ public interface MinecraftExtension extends MinecraftRepositoryExtension { */ void accessWideners(Object... file); + Property useOfficialMappings(); + + void useOfficialMappings(boolean useOfficialMappings); + + ListProperty mappingsReaders(); + + void mappingsReader(MappingsReader... readers); + + MappingsBuilder mappings(); + + void mappings(Action configure); + + void mappings(Closure configureClosure); + /** * Get run configurations configured for this project. * diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java index ef7caf7b..2ef2a163 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java @@ -33,12 +33,19 @@ import org.gradle.api.file.DirectoryProperty; import org.gradle.api.invocation.Gradle; import org.gradle.api.model.ObjectFactory; +import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; import org.gradle.util.ConfigureUtil; import org.spongepowered.gradle.vanilla.MinecraftExtension; import org.spongepowered.gradle.vanilla.internal.model.VersionClassifier; import org.spongepowered.gradle.vanilla.internal.model.VersionDescriptor; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.MappingsBuilderImpl; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.ProGuardMappingsReader; +import org.spongepowered.gradle.vanilla.internal.repository.modifier.MappingsModifier; +import org.spongepowered.gradle.vanilla.internal.repository.modifier.OfficialMappingsModifier; +import org.spongepowered.gradle.vanilla.repository.MappingsBuilder; +import org.spongepowered.gradle.vanilla.repository.MappingsReader; import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; import org.spongepowered.gradle.vanilla.internal.repository.MinecraftProviderService; import org.spongepowered.gradle.vanilla.internal.repository.MinecraftRepositoryPlugin; @@ -51,10 +58,10 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; +import java.util.List; import java.util.Objects; -import java.util.Set; import java.util.concurrent.ExecutionException; import javax.inject.Inject; @@ -66,6 +73,8 @@ public class MinecraftExtensionImpl implements MinecraftExtension { private final Property version; private final Property platform; private final Property injectRepositories; + private final Property useOfficialMappings; + private final ListProperty mappingsReaders; private final DirectoryProperty sharedCache; private final DirectoryProperty projectCache; private final ConfigurableFileCollection accessWideners; @@ -76,16 +85,24 @@ public class MinecraftExtensionImpl implements MinecraftExtension { // Internals private final Project project; + private final MappingsBuilderImpl mappingsBuilder; private final RunConfigurationContainer runConfigurations; - private volatile Set lazyModifiers; + private volatile List lazyModifiers; @Inject public MinecraftExtensionImpl(final Gradle gradle, final ObjectFactory factory, final Project project, final Provider providerService) { this.project = project; this.providerService = providerService; + this.mappingsBuilder = new MappingsBuilderImpl(project); this.version = factory.property(String.class); this.platform = factory.property(MinecraftPlatform.class).convention(MinecraftPlatform.JOINED); this.injectRepositories = factory.property(Boolean.class).convention(project.provider(() -> !gradle.getPlugins().hasPlugin(MinecraftRepositoryPlugin.class))); // only inject if we aren't already in Settings + this.useOfficialMappings = factory.property(Boolean.class).convention(project.provider(mappingsBuilder::isEmpty)); + this.mappingsReaders = factory.listProperty(MappingsReader.class).convention(project.provider(() -> { + List readers = new ArrayList<>(); + readers.add(new ProGuardMappingsReader()); + return readers; + })); this.accessWideners = factory.fileCollection(); this.assetsDirectory = factory.directoryProperty(); @@ -227,14 +244,59 @@ public ConfigurableFileCollection accessWideners() { return this.accessWideners; } - public synchronized Set modifiers() { + @Override + public Property useOfficialMappings() { + return useOfficialMappings; + } + + @Override + public void useOfficialMappings(boolean useOfficialMappings) { + this.useOfficialMappings.set(useOfficialMappings); + } + + @Override + public ListProperty mappingsReaders() { + return this.mappingsReaders; + } + + @Override + public void mappingsReader(MappingsReader... readers) { + this.mappingsReaders.addAll(readers); + } + + @Override + public MappingsBuilderImpl mappings() { + return mappingsBuilder; + } + + @Override + public void mappings(Action configure) { + configure.execute(mappingsBuilder); + } + + @Override + public void mappings(Closure configureClosure) { + configureClosure.setDelegate(mappingsBuilder); + configureClosure.call(); + } + + public synchronized List modifiers() { if (this.lazyModifiers == null) { + final List modifiers = new ArrayList<>(); + + if (useOfficialMappings.get()) { + modifiers.add(new OfficialMappingsModifier()); + } + + if (!mappingsBuilder.isEmpty()) { + modifiers.add(new MappingsModifier(mappingsBuilder, mappingsReaders)); + } + this.accessWideners.disallowChanges(); - final Set modifiers = new HashSet<>(); if (!this.accessWideners.isEmpty()) { modifiers.add(new AccessWidenerModifier(this.accessWideners.getFiles())); } - return this.lazyModifiers = Collections.unmodifiableSet(modifiers); + return this.lazyModifiers = Collections.unmodifiableList(modifiers); } return this.lazyModifiers; } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftProviderService.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftProviderService.java index 2f0ce91f..90629a62 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftProviderService.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftProviderService.java @@ -49,7 +49,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Path; -import java.util.Set; +import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -97,15 +97,15 @@ public void onFinish(final FinishEvent finishEvent) { * @param project the project to use for resolving dependencies * @param modifiers the artifact modifiers to apply to the eventual output artifact */ - public void primeResolver(final Project project, final Set modifiers) { + public void primeResolver(final Project project, final List modifiers) { final ResolverState state = this.activeState.get(); state.configurationSource = project.getConfigurations(); state.modifiers = modifiers; } - public Set peekModifiers() { + public List peekModifiers() { final ResolverState state = this.activeState.get(); - final @Nullable Set modifiers = state.modifiers; + final @Nullable List modifiers = state.modifiers; if (modifiers == null) { throw new GradleException("No artifact modifiers were staged for resolution operation!"); } @@ -222,7 +222,7 @@ public void close() throws IOException { static final class ResolverState { @MonotonicNonNull ConfigurationContainer configurationSource; - @Nullable Set modifiers; + @Nullable List modifiers; } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/MappingsBuilderImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/MappingsBuilderImpl.java new file mode 100644 index 00000000..a8402c75 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/MappingsBuilderImpl.java @@ -0,0 +1,132 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import groovy.lang.GroovyObjectSupport; +import groovy.lang.MissingMethodException; +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.artifacts.DependencyArtifact; +import org.gradle.api.artifacts.FileCollectionDependency; +import org.gradle.api.artifacts.ModuleDependency; +import org.spongepowered.gradle.vanilla.repository.MappingsBuilder; +import org.spongepowered.gradle.vanilla.repository.MappingsReader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.Set; + +public class MappingsBuilderImpl extends GroovyObjectSupport implements MappingsBuilder { + private final Project project; + private final List layers = new ArrayList<>(); + + public MappingsBuilderImpl(final Project project) { + this.project = project; + } + + @Override + public void add(@NonNull final String formatName, @NonNull final Object dependencyNotation) { + final String configName = "mappingsLayer" + layers.size(); + project.getConfigurations().register(configName, config -> { + config.setVisible(false); + config.setCanBeConsumed(false); + config.setCanBeResolved(true); + }); + Dependency dependency = project.getDependencies().add(configName, dependencyNotation); + layers.add(new Layer(formatName, configName, dependency)); + } + + public boolean isEmpty() { + return layers.isEmpty(); + } + + public @Nullable MappingSet create(List readers) { + return layers.stream().map(layer -> layer.resolve(project, readers)).reduce(MappingSet::merge).orElse(null); + } + + public void computeStateKey(MessageDigest digest) { + for (Layer layer : layers) { + layer.computeStateKey(digest); + } + } + + @Override + public Object invokeMethod(String name, Object arg) { + try { + return super.invokeMethod(name, arg); + } catch (MissingMethodException e) { + final Object[] args = (Object[]) arg; + if (args.length == 1) { + add(name, args[0]); + return null; + } else { + throw e; + } + } + } + + private static class Layer { + private final String format; + private final String config; + private final Dependency dependency; + + Layer(String format, String config, Dependency dependency) { + this.format = format; + this.config = config; + this.dependency = dependency; + } + + MappingSet resolve(final Project project, final List readers) { + Set files = project.getConfigurations().getByName(config).resolve(); + if (files.size() != 1) { + throw new IllegalStateException("Mappings configuration didn't resolve to exactly one file"); + } + for (MappingsReader reader : readers) { + if (reader.getName().equals(format)) { + try { + return reader.read(files.iterator().next().toPath()); + } catch (IOException e) { + throw new UncheckedIOException("Failed to read mappings file", e); + } + } + } + throw new IllegalStateException("Could not find a mappings reader for format \"" + format + "\". Maybe there is a Gradle plugin missing."); + } + + void computeStateKey(MessageDigest digest) { + // we can't resolve the dependency at this point, try some heuristics + + if (dependency instanceof ModuleDependency) { + for (DependencyArtifact artifact : ((ModuleDependency) dependency).getArtifacts()) { + digest.update(artifact.getUrl().getBytes(StandardCharsets.UTF_8)); + } + } else if (dependency instanceof FileCollectionDependency) { + for (File file : ((FileCollectionDependency) dependency).getFiles()) { + try (final InputStream is = new FileInputStream(file)) { + final byte[] buf = new byte[4096]; + int read; + while ((read = is.read(buf)) != -1) { + digest.update(buf, 0, read); + } + } catch (final IOException ex) { + // ignore, will show up when we try to actually read the mappings + } + } + } else { + // the best we can do + byte[] bytes = new byte[32]; + new Random().nextBytes(bytes); + digest.update(bytes); + } + } + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingsReader.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingsReader.java new file mode 100644 index 00000000..25edf88a --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingsReader.java @@ -0,0 +1,26 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.cadixdev.lorenz.io.proguard.ProGuardReader; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.gradle.vanilla.repository.MappingsReader; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class ProGuardMappingsReader implements MappingsReader { + @Override + public @NonNull String getName() { + return "proguard"; + } + + @Override + public @NonNull MappingSet read(final @NonNull Path file) throws IOException { + final MappingSet scratchMappings = MappingSet.create(); + try (ProGuardReader proguard = new ProGuardReader(Files.newBufferedReader(file))) { + proguard.read(scratchMappings); + } + return scratchMappings.reverse(); // ProGuard mappings are backwards + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/AccessWidenerModifier.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/AccessWidenerModifier.java index 4d96a6f2..99b06145 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/AccessWidenerModifier.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/AccessWidenerModifier.java @@ -28,6 +28,7 @@ import org.cadixdev.bombe.jar.JarEntryTransformer; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; import org.spongepowered.gradle.vanilla.resolver.HashAlgorithm; import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; import org.spongepowered.gradle.vanilla.internal.repository.ResolvableTool; @@ -102,7 +103,7 @@ public CompletableFuture providePopulator( .newInstance(); @Override - public JarEntryTransformer provide(final AtlasTransformerContext context) { + public JarEntryTransformer provide(final AtlasTransformerContext context, final MinecraftResolver.MinecraftEnvironment result, MinecraftPlatform side, SharedArtifactSupplier sharedArtifactProvider) { if (this.accessWidenerLoader == null) { throw new IllegalStateException("Already closed!"); } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/ArtifactModifier.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/ArtifactModifier.java index e1df8ddd..c18ecb4a 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/ArtifactModifier.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/ArtifactModifier.java @@ -27,10 +27,12 @@ import org.cadixdev.atlas.Atlas; import org.cadixdev.atlas.AtlasTransformerContext; import org.cadixdev.bombe.jar.JarEntryTransformer; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; import java.io.IOException; -import java.util.Set; +import java.util.List; import java.util.concurrent.CompletableFuture; /** @@ -42,7 +44,7 @@ public interface ArtifactModifier { char KEY_VALUE_SEPARATOR = '-'; - static String decorateArtifactId(final String originalId, final Set modifiers) { + static String decorateArtifactId(final String originalId, final List modifiers) { if (modifiers.isEmpty()) { return originalId; } @@ -102,11 +104,16 @@ static String decorateArtifactId(final String originalId, final Set readers; + private @Nullable String stateKey; + + public MappingsModifier(final MappingsBuilderImpl mappingsBuilder, ListProperty readers) { + this.mappingsBuilder = mappingsBuilder; + this.readers = readers; + } + + @Override + public String key() { + return KEY; + } + + @Override + public String stateKey() { + if (stateKey == null) { + final MessageDigest digest = HashAlgorithm.SHA1.digest(); + mappingsBuilder.computeStateKey(digest); + return this.stateKey = HashAlgorithm.toHexString(digest.digest()); + } + return stateKey; + } + + @Override + public CompletableFuture providePopulator(MinecraftResolver.Context context) { + return AsyncUtils.failableFuture(() -> new AtlasPopulator() { + private JarFile jarFile; + + @Override + public JarEntryTransformer provide(AtlasTransformerContext atlasContext, MinecraftResolver.MinecraftEnvironment result, MinecraftPlatform side, SharedArtifactSupplier sharedArtifactProvider) { + MappingSet mappings = mappingsBuilder.create(readers.get()); + try { + jarFile = new JarFile(result.jar()); + } catch (IOException e) { + throw new UncheckedIOException("Could not read result jar file", e); + } + ArrayList providers = new ArrayList<>(); + providers.add(jarFile); + return AtlasTransformers.remap(mappings, new ClassProviderInheritanceProvider(Constants.ASM_VERSION, new CascadingClassProvider(providers))); + } + + @Override + public void close() throws IOException { + if (jarFile != null) { + jarFile.close(); + } + } + }, context.executor()); + } + + @Override + public boolean requiresLocalStorage() { + return false; + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java new file mode 100644 index 00000000..f726457c --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java @@ -0,0 +1,98 @@ +package org.spongepowered.gradle.vanilla.internal.repository.modifier; + +import org.cadixdev.atlas.AtlasTransformerContext; +import org.cadixdev.atlas.jar.JarFile; +import org.cadixdev.atlas.util.CascadingClassProvider; +import org.cadixdev.bombe.asm.analysis.ClassProviderInheritanceProvider; +import org.cadixdev.bombe.asm.jar.ClassProvider; +import org.cadixdev.bombe.jar.JarEntryTransformer; +import org.cadixdev.lorenz.MappingSet; +import org.cadixdev.lorenz.io.proguard.ProGuardReader; +import org.spongepowered.gradle.vanilla.internal.Constants; +import org.spongepowered.gradle.vanilla.internal.model.Download; +import org.spongepowered.gradle.vanilla.internal.resolver.AsyncUtils; +import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; +import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; +import org.spongepowered.gradle.vanilla.resolver.HashAlgorithm; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +public class OfficialMappingsModifier implements ArtifactModifier { + private static final String KEY = "map"; + + @Override + public String key() { + return KEY; + } + + @Override + public String stateKey() { + return ""; + } + + @Override + public CompletableFuture providePopulator(MinecraftResolver.Context context) { + return AsyncUtils.failableFuture(() -> new AtlasPopulator() { + private JarFile jarFile; + + @Override + public JarEntryTransformer provide(AtlasTransformerContext atlasContext, MinecraftResolver.MinecraftEnvironment result, MinecraftPlatform platform, SharedArtifactSupplier sharedArtifactProvider) { + @SuppressWarnings("unchecked") + CompletableFuture[] mappingsFutures = platform.activeSides().stream().map(side -> { + Download mappingsDownload = result.metadata().requireDownload(side.mappingsArtifact()); + return context.downloader().downloadAndValidate( + mappingsDownload.url(), + sharedArtifactProvider.supply(side.name().toLowerCase(Locale.ROOT) + "_m-obf", "mappings", "txt"), + HashAlgorithm.SHA1, + mappingsDownload.sha1() + ).thenApplyAsync(downloadResult -> { + if (!downloadResult.isPresent()) { + throw new IllegalArgumentException("No mappings were available for Minecraft " + result.metadata().id() + "side " + side.name() + + "! Official mappings are only available for releases 1.14.4 and newer."); + } + MappingSet mappings = MappingSet.create(); + try (ProGuardReader reader = new ProGuardReader(Files.newBufferedReader(downloadResult.get()))) { + reader.read(mappings); + } catch (IOException e) { + throw new CompletionException(e); + } + return mappings; + }, context.executor()); + }).toArray(CompletableFuture[]::new); + CompletableFuture mappingFuture = CompletableFuture.allOf(mappingsFutures) + .thenApplyAsync($ -> Arrays.stream(mappingsFutures).map(CompletableFuture::join).reduce(MappingSet::merge).orElseGet(MappingSet::create)); + + + MappingSet mappings = mappingFuture.join(); + try { + jarFile = new JarFile(result.jar()); + } catch (IOException e) { + throw new UncheckedIOException("Could not read result jar file", e); + } + ArrayList providers = new ArrayList<>(); + providers.add(jarFile); + return AtlasTransformers.remap(mappings, new ClassProviderInheritanceProvider(Constants.ASM_VERSION, new CascadingClassProvider(providers))); + } + + @Override + public void close() throws IOException { + if (jarFile != null) { + jarFile.close(); + } + } + }, context.executor()); + } + + @Override + public boolean requiresLocalStorage() { + return false; + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsBuilder.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsBuilder.java new file mode 100644 index 00000000..255f3487 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsBuilder.java @@ -0,0 +1,5 @@ +package org.spongepowered.gradle.vanilla.repository; + +public interface MappingsBuilder { + void add(String formatName, Object dependencyNotation); +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsReader.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsReader.java new file mode 100644 index 00000000..d38de43b --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsReader.java @@ -0,0 +1,11 @@ +package org.spongepowered.gradle.vanilla.repository; + +import org.cadixdev.lorenz.MappingSet; + +import java.io.IOException; +import java.nio.file.Path; + +public interface MappingsReader { + String getName(); + MappingSet read(final Path file) throws IOException; +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolver.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolver.java index b872824d..81c6d5ee 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolver.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolver.java @@ -35,6 +35,8 @@ import java.net.URLClassLoader; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -50,14 +52,14 @@ public interface MinecraftResolver { * detected by existing input detection, or would make data unreadable by * older versions of the resolver, this version will be incremented.

*/ - int STORAGE_VERSION = 1; + int STORAGE_VERSION = 2; /** * A version for stored metadata. * *

Whenever the {@link #STORAGE_VERSION} is incremented, this version * will be reset to {@code 1}

*/ - int METADATA_VERSION = 2; + int METADATA_VERSION = 1; /** * Get the version manifest repository managed by this resolver. @@ -73,7 +75,12 @@ public interface MinecraftResolver { CompletableFuture> provide(final MinecraftPlatform side, final String version); - CompletableFuture> provide(final MinecraftPlatform side, final String version, final Set modifiers); + CompletableFuture> provide(final MinecraftPlatform side, final String version, final List modifiers); + + @Deprecated // use the version with an ordered list of modifiers instead + default CompletableFuture> provide(final MinecraftPlatform side, final String version, final Set modifiers) { + return provide(side, version, new ArrayList<>(modifiers)); + } /** * Given a standard Minecraft artifact, produce a variant of that artifact. @@ -96,7 +103,15 @@ public interface MinecraftResolver { * environment and a target path * @return a future returning the result of resolving a jar path */ - CompletableFuture> produceAssociatedArtifactSync(final MinecraftPlatform side, final String version, final Set modifiers, final String id, final Set flags, final BiConsumer action); + CompletableFuture> produceAssociatedArtifactSync(final MinecraftPlatform side, final String version, final List modifiers, final String id, final Set flags, final BiConsumer action); + + /** + * @deprecated Use the version with an ordered list of modifiers instead. + */ + @Deprecated + default CompletableFuture> produceAssociatedArtifactSync(final MinecraftPlatform side, final String version, final Set modifiers, final String id, final Set flags, final BiConsumer action) { + return produceAssociatedArtifactSync(side, version, new ArrayList<>(modifiers), id, flags, action); + } interface MinecraftEnvironment { diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java index 2acc322f..fa8bb0f2 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java @@ -26,17 +26,10 @@ import org.cadixdev.atlas.Atlas; import org.cadixdev.atlas.jar.JarFile; -import org.cadixdev.atlas.util.CascadingClassProvider; -import org.cadixdev.bombe.asm.analysis.ClassProviderInheritanceProvider; -import org.cadixdev.bombe.asm.jar.ClassProvider; -import org.cadixdev.lorenz.MappingSet; -import org.cadixdev.lorenz.io.proguard.ProGuardReader; import org.checkerframework.checker.nullness.qual.Nullable; -import org.gradle.api.GradleException; import org.immutables.value.Value; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.spongepowered.gradle.vanilla.internal.Constants; import org.spongepowered.gradle.vanilla.internal.bundler.BundlerMetadata; import org.spongepowered.gradle.vanilla.internal.model.Download; import org.spongepowered.gradle.vanilla.internal.model.GroupArtifactVersion; @@ -56,16 +49,15 @@ import org.spongepowered.gradle.vanilla.resolver.ResolutionResult; import java.io.IOException; +import java.io.UncheckedIOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; import java.net.URLClassLoader; -import java.nio.charset.StandardCharsets; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; @@ -154,12 +146,15 @@ CompletableFuture> provide(final Minecraf } final VersionDescriptor.Full descriptor = potentialDescriptor.get(); final Download jarDownload = descriptor.requireDownload(side.executableArtifact()); - final Download mappingsDownload = descriptor.requireDownload(side.mappingsArtifact()); // download to temp path final String tempJarPath = this.sharedArtifactFileName(platform.artifactId() + "_m-obf_b-bundled", version, null, "jar"); final String jarPath = this.sharedArtifactFileName(platform.artifactId() + "_m-obf", version, null, "jar"); - final String mappingsPath = this.sharedArtifactFileName(platform.artifactId() + "_m-obf", version, "mappings", "txt"); + try { + FileUtils.createDirectoriesSymlinkSafe(this.downloader.baseDir().resolve(jarPath).getParent()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } final CompletableFuture> jarFuture = this.downloader.downloadAndValidate( jarDownload.url(), @@ -167,14 +162,8 @@ CompletableFuture> provide(final Minecraf HashAlgorithm.SHA1, jarDownload.sha1() ); - final CompletableFuture> mappingsFuture = this.downloader.downloadAndValidate( - mappingsDownload.url(), - mappingsPath, - HashAlgorithm.SHA1, - mappingsDownload.sha1() - ); - return jarFuture.thenCombineAsync(mappingsFuture, (jar, mappingsFile) -> { + return jarFuture.thenApplyAsync(jar -> { try { final boolean outputExists = Files.exists(outputJar); final @Nullable BundlerMetadata bundlerMeta = BundlerMetadata.read(jar.get()).orElse(null); @@ -184,7 +173,7 @@ CompletableFuture> provide(final Minecraf MinecraftResolverImpl.LOGGER.info("No bundler metadata found in jar {}", jar.get()); } final Supplier> dependencies = () -> side.dependencies(descriptor, bundlerMeta); - if (!this.forceRefresh && jar.upToDate() && mappingsFile.upToDate() && outputExists) { + if (!this.forceRefresh && jar.upToDate() && outputExists) { // Our inputs are up-to-date, and the output exists, so we can assume (for now) that the output is up-to-date // Check meta here too, before returning this.writeMetaIfNecessary(platform, potentialDescriptor, dependencies, outputJar.getParent()); @@ -193,9 +182,6 @@ CompletableFuture> provide(final Minecraf } else if (!jar.isPresent()) { throw new IllegalArgumentException("No jar was available for Minecraft " + descriptor.id() + "side " + side.name() + "! Are you sure the data file is correct?"); - } else if (!mappingsFile.isPresent()) { - throw new IllegalArgumentException("No mappings were available for Minecraft " + descriptor.id() + "side " + side.name() - + "! Official mappings are only available for releases 1.14.4 and newer."); } MinecraftResolverImpl.LOGGER.warn("Preparing Minecraft: Java Edition {} version {}", side, version); this.cleanAssociatedArtifacts(platform, version); @@ -207,16 +193,6 @@ CompletableFuture> provide(final Minecraf final Path extracted = this.downloader.baseDir().resolve(jarPath); side.extractJar(jar.get(), extracted, bundlerMeta); - final MappingSet scratchMappings = MappingSet.create(); - try ( - final ProGuardReader proguard = new ProGuardReader(Files.newBufferedReader(mappingsFile.get(), StandardCharsets.UTF_8)) - ) { - proguard.read(scratchMappings); - } catch (final IOException ex) { - throw new GradleException("Failed to read mappings from " + mappingsFile, ex); - } - final MappingSet mappings = scratchMappings.reverse(); - try ( final Atlas atlas = new Atlas(this.executor); final JarFile source = new JarFile(extracted) @@ -225,13 +201,6 @@ CompletableFuture> provide(final Minecraf atlas.install(ctx -> AtlasTransformers.filterEntries(side.allowedPackages())); } atlas.install(ctx -> AtlasTransformers.stripSignatures()); - final List providers = new ArrayList<>(); - providers.add(source); - atlas.install(ctx -> AtlasTransformers.remap( - mappings, - // duplicated from Atlas.run, to pass our own ASM API version - new ClassProviderInheritanceProvider(Constants.ASM_VERSION, new CascadingClassProvider(providers)) - )); atlas.run(source, outputTmp); } @@ -368,7 +337,7 @@ private CompletableFuture> provide0(final @Override public CompletableFuture> provide( - final MinecraftPlatform side, final String version, final Set modifiers + final MinecraftPlatform side, final String version, final List modifiers ) { final CompletableFuture> unmodified = this.provide0(side, version); if (modifiers.isEmpty()) { // no modifiers provided, follow the normal path @@ -413,7 +382,8 @@ public CompletableFuture> provide( try (final Atlas atlas = new Atlas(this.executor)) { for (final CompletableFuture populator : populators) { - atlas.install(populator.get()::provide); + ArtifactModifier.AtlasPopulator pop = populator.get(); + atlas.install(ctx -> pop.provide(ctx, input.get(), side, (id, classifier, extension) -> this.sharedArtifactFileName(id, version, classifier, extension))); } atlas.run(input.get().jar(), outputTmp); @@ -464,7 +434,7 @@ private void cleanAssociatedArtifacts(final MinecraftPlatform platform, final St public CompletableFuture> produceAssociatedArtifactSync( final MinecraftPlatform side, final String version, - final Set modifiers, + final List modifiers, final String id, final Set flags, final BiConsumer action diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java index 227e7db2..85761110 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java @@ -59,6 +59,7 @@ import java.util.Collections; import java.util.EnumSet; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -129,7 +130,7 @@ public void execute() { final CompletableFuture> resultFuture; try { final MinecraftProviderService minecraftProvider = this.getMinecraftProvider().get(); - final Set modifiers = + final List modifiers = ((MinecraftExtensionImpl) this.getProject().getExtensions().getByType(MinecraftExtension.class)).modifiers(); minecraftProvider.primeResolver(this.getProject(), modifiers); From 433e225aff8ced81bf46c485a457c2f4c117c4c7 Mon Sep 17 00:00:00 2001 From: Joe Date: Sun, 3 Oct 2021 17:07:31 +0100 Subject: [PATCH 02/15] Fix --- .../repository/modifier/MappingsModifier.java | 36 +------- .../modifier/OfficialMappingsModifier.java | 83 ++++++------------- .../repository/MinecraftResolverImpl.java | 41 ++++++++- 3 files changed, 70 insertions(+), 90 deletions(-) diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java index a96c6ee4..c0832979 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java @@ -1,27 +1,16 @@ package org.spongepowered.gradle.vanilla.internal.repository.modifier; -import org.cadixdev.atlas.AtlasTransformerContext; -import org.cadixdev.atlas.jar.JarFile; -import org.cadixdev.atlas.util.CascadingClassProvider; -import org.cadixdev.bombe.asm.analysis.ClassProviderInheritanceProvider; -import org.cadixdev.bombe.asm.jar.ClassProvider; -import org.cadixdev.bombe.jar.JarEntryTransformer; import org.cadixdev.lorenz.MappingSet; import org.checkerframework.checker.nullness.qual.Nullable; import org.gradle.api.provider.ListProperty; -import org.spongepowered.gradle.vanilla.internal.Constants; import org.spongepowered.gradle.vanilla.internal.repository.mappings.MappingsBuilderImpl; import org.spongepowered.gradle.vanilla.internal.resolver.AsyncUtils; import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; import org.spongepowered.gradle.vanilla.repository.MappingsReader; -import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; import org.spongepowered.gradle.vanilla.resolver.HashAlgorithm; -import java.io.IOException; -import java.io.UncheckedIOException; import java.security.MessageDigest; -import java.util.ArrayList; import java.util.concurrent.CompletableFuture; public class MappingsModifier implements ArtifactModifier { @@ -53,28 +42,9 @@ public String stateKey() { @Override public CompletableFuture providePopulator(MinecraftResolver.Context context) { - return AsyncUtils.failableFuture(() -> new AtlasPopulator() { - private JarFile jarFile; - - @Override - public JarEntryTransformer provide(AtlasTransformerContext atlasContext, MinecraftResolver.MinecraftEnvironment result, MinecraftPlatform side, SharedArtifactSupplier sharedArtifactProvider) { - MappingSet mappings = mappingsBuilder.create(readers.get()); - try { - jarFile = new JarFile(result.jar()); - } catch (IOException e) { - throw new UncheckedIOException("Could not read result jar file", e); - } - ArrayList providers = new ArrayList<>(); - providers.add(jarFile); - return AtlasTransformers.remap(mappings, new ClassProviderInheritanceProvider(Constants.ASM_VERSION, new CascadingClassProvider(providers))); - } - - @Override - public void close() throws IOException { - if (jarFile != null) { - jarFile.close(); - } - } + return AsyncUtils.failableFuture(() -> (atlasContext, result, side, sharedArtifactProvider) -> { + MappingSet mappings = mappingsBuilder.create(readers.get()); + return AtlasTransformers.remap(mappings, atlasContext.inheritanceProvider()); }, context.executor()); } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java index f726457c..3ba488dd 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java @@ -1,25 +1,15 @@ package org.spongepowered.gradle.vanilla.internal.repository.modifier; -import org.cadixdev.atlas.AtlasTransformerContext; -import org.cadixdev.atlas.jar.JarFile; -import org.cadixdev.atlas.util.CascadingClassProvider; -import org.cadixdev.bombe.asm.analysis.ClassProviderInheritanceProvider; -import org.cadixdev.bombe.asm.jar.ClassProvider; -import org.cadixdev.bombe.jar.JarEntryTransformer; import org.cadixdev.lorenz.MappingSet; import org.cadixdev.lorenz.io.proguard.ProGuardReader; -import org.spongepowered.gradle.vanilla.internal.Constants; import org.spongepowered.gradle.vanilla.internal.model.Download; import org.spongepowered.gradle.vanilla.internal.resolver.AsyncUtils; import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; -import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; import org.spongepowered.gradle.vanilla.resolver.HashAlgorithm; import java.io.IOException; -import java.io.UncheckedIOException; import java.nio.file.Files; -import java.util.ArrayList; import java.util.Arrays; import java.util.Locale; import java.util.concurrent.CompletableFuture; @@ -40,54 +30,35 @@ public String stateKey() { @Override public CompletableFuture providePopulator(MinecraftResolver.Context context) { - return AsyncUtils.failableFuture(() -> new AtlasPopulator() { - private JarFile jarFile; + return AsyncUtils.failableFuture(() -> (atlasContext, result, platform, sharedArtifactProvider) -> { + @SuppressWarnings("unchecked") + CompletableFuture[] mappingsFutures = platform.activeSides().stream().map(side -> { + Download mappingsDownload = result.metadata().requireDownload(side.mappingsArtifact()); + return context.downloader().downloadAndValidate( + mappingsDownload.url(), + sharedArtifactProvider.supply(side.name().toLowerCase(Locale.ROOT) + "_m-obf", "mappings", "txt"), + HashAlgorithm.SHA1, + mappingsDownload.sha1() + ).thenApplyAsync(downloadResult -> { + if (!downloadResult.isPresent()) { + throw new IllegalArgumentException("No mappings were available for Minecraft " + result.metadata().id() + "side " + side.name() + + "! Official mappings are only available for releases 1.14.4 and newer."); + } + MappingSet mappings = MappingSet.create(); + try (ProGuardReader reader = new ProGuardReader(Files.newBufferedReader(downloadResult.get()))) { + reader.read(mappings); + } catch (IOException e) { + throw new CompletionException(e); + } + return mappings.reverse(); // proguard mappings are backwards + }, context.executor()); + }).toArray(CompletableFuture[]::new); + CompletableFuture mappingFuture = CompletableFuture.allOf(mappingsFutures) + .thenApplyAsync($ -> Arrays.stream(mappingsFutures).map(CompletableFuture::join).reduce(MappingSet::merge).orElseGet(MappingSet::create)); - @Override - public JarEntryTransformer provide(AtlasTransformerContext atlasContext, MinecraftResolver.MinecraftEnvironment result, MinecraftPlatform platform, SharedArtifactSupplier sharedArtifactProvider) { - @SuppressWarnings("unchecked") - CompletableFuture[] mappingsFutures = platform.activeSides().stream().map(side -> { - Download mappingsDownload = result.metadata().requireDownload(side.mappingsArtifact()); - return context.downloader().downloadAndValidate( - mappingsDownload.url(), - sharedArtifactProvider.supply(side.name().toLowerCase(Locale.ROOT) + "_m-obf", "mappings", "txt"), - HashAlgorithm.SHA1, - mappingsDownload.sha1() - ).thenApplyAsync(downloadResult -> { - if (!downloadResult.isPresent()) { - throw new IllegalArgumentException("No mappings were available for Minecraft " + result.metadata().id() + "side " + side.name() - + "! Official mappings are only available for releases 1.14.4 and newer."); - } - MappingSet mappings = MappingSet.create(); - try (ProGuardReader reader = new ProGuardReader(Files.newBufferedReader(downloadResult.get()))) { - reader.read(mappings); - } catch (IOException e) { - throw new CompletionException(e); - } - return mappings; - }, context.executor()); - }).toArray(CompletableFuture[]::new); - CompletableFuture mappingFuture = CompletableFuture.allOf(mappingsFutures) - .thenApplyAsync($ -> Arrays.stream(mappingsFutures).map(CompletableFuture::join).reduce(MappingSet::merge).orElseGet(MappingSet::create)); - - MappingSet mappings = mappingFuture.join(); - try { - jarFile = new JarFile(result.jar()); - } catch (IOException e) { - throw new UncheckedIOException("Could not read result jar file", e); - } - ArrayList providers = new ArrayList<>(); - providers.add(jarFile); - return AtlasTransformers.remap(mappings, new ClassProviderInheritanceProvider(Constants.ASM_VERSION, new CascadingClassProvider(providers))); - } - - @Override - public void close() throws IOException { - if (jarFile != null) { - jarFile.close(); - } - } + MappingSet mappings = mappingFuture.join(); + return AtlasTransformers.remap(mappings, atlasContext.inheritanceProvider()); }, context.executor()); } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java index fa8bb0f2..71b4c7db 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java @@ -25,11 +25,16 @@ package org.spongepowered.gradle.vanilla.repository; import org.cadixdev.atlas.Atlas; +import org.cadixdev.atlas.AtlasTransformerContext; import org.cadixdev.atlas.jar.JarFile; +import org.cadixdev.bombe.analysis.InheritanceProvider; +import org.cadixdev.bombe.asm.analysis.ClassProviderInheritanceProvider; +import org.cadixdev.bombe.asm.jar.ClassProvider; import org.checkerframework.checker.nullness.qual.Nullable; import org.immutables.value.Value; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.spongepowered.gradle.vanilla.internal.Constants; import org.spongepowered.gradle.vanilla.internal.bundler.BundlerMetadata; import org.spongepowered.gradle.vanilla.internal.model.Download; import org.spongepowered.gradle.vanilla.internal.model.GroupArtifactVersion; @@ -50,6 +55,8 @@ import java.io.IOException; import java.io.UncheckedIOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -383,7 +390,7 @@ public CompletableFuture> provide( try (final Atlas atlas = new Atlas(this.executor)) { for (final CompletableFuture populator : populators) { ArtifactModifier.AtlasPopulator pop = populator.get(); - atlas.install(ctx -> pop.provide(ctx, input.get(), side, (id, classifier, extension) -> this.sharedArtifactFileName(id, version, classifier, extension))); + atlas.install(ctx -> pop.provide(withAsmApi(ctx, Constants.ASM_VERSION), input.get(), side, (id, classifier, extension) -> this.sharedArtifactFileName(id, version, classifier, extension))); } atlas.run(input.get().jar(), outputTmp); @@ -410,6 +417,38 @@ public CompletableFuture> provide( )); } + private static final Field CPIP_CLASS_PROVIDER_FIELD; + private static final Constructor ATC_CONSTRUCTOR; + static { + try { + CPIP_CLASS_PROVIDER_FIELD = ClassProviderInheritanceProvider.class.getDeclaredField("provider"); + CPIP_CLASS_PROVIDER_FIELD.setAccessible(true); + ATC_CONSTRUCTOR = AtlasTransformerContext.class.getDeclaredConstructor(InheritanceProvider.class); + ATC_CONSTRUCTOR.setAccessible(true); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + // Hack to set the ASM api version of the atlas inheritance provider. + // TODO: better solution, e.g. forking or using a different library? + private static ClassProvider getClassProvider(ClassProviderInheritanceProvider inheritanceProvider) { + try { + return (ClassProvider) CPIP_CLASS_PROVIDER_FIELD.get(inheritanceProvider); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + private static AtlasTransformerContext withAsmApi(AtlasTransformerContext context, int asmApi) { + InheritanceProvider inheritanceProvider = new ClassProviderInheritanceProvider(asmApi, getClassProvider((ClassProviderInheritanceProvider) context.inheritanceProvider())); + try { + return ATC_CONSTRUCTOR.newInstance(inheritanceProvider); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + private void cleanAssociatedArtifacts(final MinecraftPlatform platform, final String version) throws IOException { final Path baseArtifact = this.sharedArtifactPath(platform.artifactId(), version, null, "jar"); int errorCount = 0; From fd553c0e85b336646eaa9d70138f2fa56f4ece55 Mon Sep 17 00:00:00 2001 From: Joe Date: Mon, 4 Oct 2021 00:05:03 +0100 Subject: [PATCH 03/15] Massive refactor, allow for tiny mappings --- gradle.properties | 1 + subprojects/gradle-plugin/build.gradle.kts | 8 +- .../gradle/vanilla/MinecraftExtension.java | 29 +- .../internal/MinecraftExtensionImpl.java | 91 +++-- .../mappings/MappingsBuilderImpl.java | 132 ------- .../mappings/OfficialMappingsEntry.java | 98 +++++ ...Reader.java => ProGuardMappingFormat.java} | 15 +- .../mappings/TinyMappingFormat.java | 27 ++ .../repository/modifier/MappingsModifier.java | 29 +- .../modifier/OfficialMappingsModifier.java | 69 ---- .../vanilla/repository/MappingsBuilder.java | 5 - .../vanilla/repository/MappingsReader.java | 11 - .../mappings/DelegatingMappingsEntry.java | 47 +++ .../repository/mappings/MappingFormat.java | 32 ++ .../mappings/MappingsContainer.java | 356 ++++++++++++++++++ .../repository/mappings/MappingsEntry.java | 204 ++++++++++ .../mappings/TinyMappingsEntry.java | 36 ++ .../repository/mappings/MappingsExtensions.kt | 2 + 18 files changed, 905 insertions(+), 287 deletions(-) delete mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/MappingsBuilderImpl.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java rename subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/{ProGuardMappingsReader.java => ProGuardMappingFormat.java} (57%) create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java delete mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java delete mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsBuilder.java delete mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsReader.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/DelegatingMappingsEntry.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingFormat.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsContainer.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/TinyMappingsEntry.java create mode 100644 subprojects/gradle-plugin/src/main/kotlin/org/spongepowered/gradle/vanilla/repository/mappings/MappingsExtensions.kt diff --git a/gradle.properties b/gradle.properties index ae8b25ed..7584e303 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,3 +11,4 @@ junitVersion=5.7.2 mergeToolVersion=1.1.4 org.gradle.parallel=true +kotlin.stdlib.default.dependency=false diff --git a/subprojects/gradle-plugin/build.gradle.kts b/subprojects/gradle-plugin/build.gradle.kts index 8b29fa0f..5483283d 100644 --- a/subprojects/gradle-plugin/build.gradle.kts +++ b/subprojects/gradle-plugin/build.gradle.kts @@ -6,6 +6,7 @@ plugins { id("com.gradle.plugin-publish") id("net.kyori.indra.publishing.gradle-plugin") id("org.jetbrains.gradle.plugin.idea-ext") + kotlin("jvm") version "1.5.31" } val commonDeps by configurations.creating { @@ -16,9 +17,6 @@ val jarMerge by sourceSets.creating { val jarDecompile by sourceSets.creating { configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } } -val jarRemap by sourceSets.creating { - configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } -} val accessWiden by sourceSets.creating { configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } } @@ -53,6 +51,9 @@ dependencies { } implementation("org.cadixdev:lorenz-io-proguard:0.5.7") + compileOnly("net.fabricmc:lorenz-tiny:4.0.2") { + isTransitive = false + } compileOnlyApi("org.checkerframework:checker-qual:3.15.0") annotationProcessor("org.immutables:value:2.8.8") @@ -126,7 +127,6 @@ tasks { jar { from(jarMerge.output) from(jarDecompile.output) - from(jarRemap.output) from(accessWiden.output) from(shadow.output) } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java index 28501ca5..1e31dbcf 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java @@ -26,14 +26,17 @@ import groovy.lang.Closure; import groovy.lang.DelegatesTo; +import org.checkerframework.checker.nullness.qual.NonNull; import org.gradle.api.Action; +import org.gradle.api.NamedDomainObjectSet; +import org.gradle.api.PolymorphicDomainObjectContainer; import org.gradle.api.Project; -import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; -import org.spongepowered.gradle.vanilla.repository.MappingsBuilder; -import org.spongepowered.gradle.vanilla.repository.MappingsReader; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; import org.spongepowered.gradle.vanilla.repository.MinecraftRepositoryExtension; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsContainer; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; import org.spongepowered.gradle.vanilla.runs.RunConfigurationContainer; /** @@ -116,19 +119,25 @@ public interface MinecraftExtension extends MinecraftRepositoryExtension { */ void accessWideners(Object... file); - Property useOfficialMappings(); + PolymorphicDomainObjectContainer> getMappingFormats(); - void useOfficialMappings(boolean useOfficialMappings); + void mappingFormats(Action>> configure); - ListProperty mappingsReaders(); + void mappingFormats(@DelegatesTo(value = NamedDomainObjectSet.class, strategy = Closure.DELEGATE_FIRST) Closure>> configureClosure); - void mappingsReader(MappingsReader... readers); + MappingsContainer getMappings(); - MappingsBuilder mappings(); + void mappings(Action configure); - void mappings(Action configure); + void mappings(@DelegatesTo(value = MappingsContainer.class, strategy = Closure.DELEGATE_FIRST) Closure configureClosure); - void mappings(Closure configureClosure); + Property minecraftMappings(); + + void minecraftMappings(MappingsEntry mappings); + + void minecraftMappings(String mappings); + + void noMinecraftMappings(); /** * Get run configurations configured for this project. diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java index 2ef2a163..b916e0cc 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java @@ -26,26 +26,29 @@ import groovy.lang.Closure; import groovy.lang.DelegatesTo; +import org.checkerframework.checker.nullness.qual.NonNull; import org.gradle.api.Action; import org.gradle.api.GradleException; +import org.gradle.api.NamedDomainObjectSet; +import org.gradle.api.PolymorphicDomainObjectContainer; import org.gradle.api.Project; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.invocation.Gradle; import org.gradle.api.model.ObjectFactory; -import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; import org.gradle.util.ConfigureUtil; import org.spongepowered.gradle.vanilla.MinecraftExtension; import org.spongepowered.gradle.vanilla.internal.model.VersionClassifier; import org.spongepowered.gradle.vanilla.internal.model.VersionDescriptor; -import org.spongepowered.gradle.vanilla.internal.repository.mappings.MappingsBuilderImpl; -import org.spongepowered.gradle.vanilla.internal.repository.mappings.ProGuardMappingsReader; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.OfficialMappingsEntry; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.ProGuardMappingFormat; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.TinyMappingFormat; import org.spongepowered.gradle.vanilla.internal.repository.modifier.MappingsModifier; -import org.spongepowered.gradle.vanilla.internal.repository.modifier.OfficialMappingsModifier; -import org.spongepowered.gradle.vanilla.repository.MappingsBuilder; -import org.spongepowered.gradle.vanilla.repository.MappingsReader; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsContainer; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; import org.spongepowered.gradle.vanilla.internal.repository.MinecraftProviderService; import org.spongepowered.gradle.vanilla.internal.repository.MinecraftRepositoryPlugin; @@ -73,8 +76,10 @@ public class MinecraftExtensionImpl implements MinecraftExtension { private final Property version; private final Property platform; private final Property injectRepositories; - private final Property useOfficialMappings; - private final ListProperty mappingsReaders; + private final PolymorphicDomainObjectContainer> mappingFormats; + private final MappingsContainer mappings; + private final Property minecraftMappings; + private final Property noMinecraftMappings; private final DirectoryProperty sharedCache; private final DirectoryProperty projectCache; private final ConfigurableFileCollection accessWideners; @@ -85,26 +90,28 @@ public class MinecraftExtensionImpl implements MinecraftExtension { // Internals private final Project project; - private final MappingsBuilderImpl mappingsBuilder; private final RunConfigurationContainer runConfigurations; private volatile List lazyModifiers; + @SuppressWarnings("unchecked") @Inject public MinecraftExtensionImpl(final Gradle gradle, final ObjectFactory factory, final Project project, final Provider providerService) { this.project = project; this.providerService = providerService; - this.mappingsBuilder = new MappingsBuilderImpl(project); this.version = factory.property(String.class); this.platform = factory.property(MinecraftPlatform.class).convention(MinecraftPlatform.JOINED); this.injectRepositories = factory.property(Boolean.class).convention(project.provider(() -> !gradle.getPlugins().hasPlugin(MinecraftRepositoryPlugin.class))); // only inject if we aren't already in Settings - this.useOfficialMappings = factory.property(Boolean.class).convention(project.provider(mappingsBuilder::isEmpty)); - this.mappingsReaders = factory.listProperty(MappingsReader.class).convention(project.provider(() -> { - List readers = new ArrayList<>(); - readers.add(new ProGuardMappingsReader()); - return readers; - })); + this.mappingFormats = factory.polymorphicDomainObjectContainer((Class>) (Class) MappingFormat.class); + this.mappings = new MappingsContainer(project, this); + this.minecraftMappings = factory.property(String.class).convention(OfficialMappingsEntry.NAME); + this.noMinecraftMappings = factory.property(Boolean.class).convention(false); this.accessWideners = factory.fileCollection(); + this.mappingFormats.add(new ProGuardMappingFormat()); + this.mappingFormats.add(new TinyMappingFormat()); + this.mappings.add(new OfficialMappingsEntry(project, this)); + + this.assetsDirectory = factory.directoryProperty(); this.sharedCache = factory.directoryProperty().convention(providerService.flatMap(it -> it.getParameters().getSharedCache())); this.sharedCache.disallowChanges(); @@ -245,51 +252,61 @@ public ConfigurableFileCollection accessWideners() { } @Override - public Property useOfficialMappings() { - return useOfficialMappings; + public PolymorphicDomainObjectContainer> getMappingFormats() { + return mappingFormats; + } + + @Override + public void mappingFormats(Action>> configure) { + configure.execute(mappingFormats); + } + + @Override + public void mappingFormats(@DelegatesTo(value = NamedDomainObjectSet.class, strategy = Closure.DELEGATE_FIRST) Closure>> configureClosure) { + ConfigureUtil.configure(configureClosure, mappingFormats); } @Override - public void useOfficialMappings(boolean useOfficialMappings) { - this.useOfficialMappings.set(useOfficialMappings); + public MappingsContainer getMappings() { + return mappings; } @Override - public ListProperty mappingsReaders() { - return this.mappingsReaders; + public void mappings(Action configure) { + configure.execute(mappings); } @Override - public void mappingsReader(MappingsReader... readers) { - this.mappingsReaders.addAll(readers); + public void mappings(@DelegatesTo(value = MappingsContainer.class, strategy = Closure.DELEGATE_FIRST) Closure configureClosure) { + ConfigureUtil.configure(configureClosure, mappings); } @Override - public MappingsBuilderImpl mappings() { - return mappingsBuilder; + public Property minecraftMappings() { + return minecraftMappings; } @Override - public void mappings(Action configure) { - configure.execute(mappingsBuilder); + public void minecraftMappings(MappingsEntry mappings) { + minecraftMappings(mappings.getName()); } @Override - public void mappings(Closure configureClosure) { - configureClosure.setDelegate(mappingsBuilder); - configureClosure.call(); + public void minecraftMappings(String mappings) { + this.minecraftMappings.set(mappings); + } + + @Override + public void noMinecraftMappings() { + this.noMinecraftMappings.set(true); } public synchronized List modifiers() { if (this.lazyModifiers == null) { final List modifiers = new ArrayList<>(); - if (useOfficialMappings.get()) { - modifiers.add(new OfficialMappingsModifier()); - } - - if (!mappingsBuilder.isEmpty()) { - modifiers.add(new MappingsModifier(mappingsBuilder, mappingsReaders)); + if (!noMinecraftMappings.get()) { + modifiers.add(new MappingsModifier(mappings.getByName(minecraftMappings.get()))); } this.accessWideners.disallowChanges(); diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/MappingsBuilderImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/MappingsBuilderImpl.java deleted file mode 100644 index a8402c75..00000000 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/MappingsBuilderImpl.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.spongepowered.gradle.vanilla.internal.repository.mappings; - -import groovy.lang.GroovyObjectSupport; -import groovy.lang.MissingMethodException; -import org.cadixdev.lorenz.MappingSet; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.gradle.api.Project; -import org.gradle.api.artifacts.Dependency; -import org.gradle.api.artifacts.DependencyArtifact; -import org.gradle.api.artifacts.FileCollectionDependency; -import org.gradle.api.artifacts.ModuleDependency; -import org.spongepowered.gradle.vanilla.repository.MappingsBuilder; -import org.spongepowered.gradle.vanilla.repository.MappingsReader; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.Set; - -public class MappingsBuilderImpl extends GroovyObjectSupport implements MappingsBuilder { - private final Project project; - private final List layers = new ArrayList<>(); - - public MappingsBuilderImpl(final Project project) { - this.project = project; - } - - @Override - public void add(@NonNull final String formatName, @NonNull final Object dependencyNotation) { - final String configName = "mappingsLayer" + layers.size(); - project.getConfigurations().register(configName, config -> { - config.setVisible(false); - config.setCanBeConsumed(false); - config.setCanBeResolved(true); - }); - Dependency dependency = project.getDependencies().add(configName, dependencyNotation); - layers.add(new Layer(formatName, configName, dependency)); - } - - public boolean isEmpty() { - return layers.isEmpty(); - } - - public @Nullable MappingSet create(List readers) { - return layers.stream().map(layer -> layer.resolve(project, readers)).reduce(MappingSet::merge).orElse(null); - } - - public void computeStateKey(MessageDigest digest) { - for (Layer layer : layers) { - layer.computeStateKey(digest); - } - } - - @Override - public Object invokeMethod(String name, Object arg) { - try { - return super.invokeMethod(name, arg); - } catch (MissingMethodException e) { - final Object[] args = (Object[]) arg; - if (args.length == 1) { - add(name, args[0]); - return null; - } else { - throw e; - } - } - } - - private static class Layer { - private final String format; - private final String config; - private final Dependency dependency; - - Layer(String format, String config, Dependency dependency) { - this.format = format; - this.config = config; - this.dependency = dependency; - } - - MappingSet resolve(final Project project, final List readers) { - Set files = project.getConfigurations().getByName(config).resolve(); - if (files.size() != 1) { - throw new IllegalStateException("Mappings configuration didn't resolve to exactly one file"); - } - for (MappingsReader reader : readers) { - if (reader.getName().equals(format)) { - try { - return reader.read(files.iterator().next().toPath()); - } catch (IOException e) { - throw new UncheckedIOException("Failed to read mappings file", e); - } - } - } - throw new IllegalStateException("Could not find a mappings reader for format \"" + format + "\". Maybe there is a Gradle plugin missing."); - } - - void computeStateKey(MessageDigest digest) { - // we can't resolve the dependency at this point, try some heuristics - - if (dependency instanceof ModuleDependency) { - for (DependencyArtifact artifact : ((ModuleDependency) dependency).getArtifacts()) { - digest.update(artifact.getUrl().getBytes(StandardCharsets.UTF_8)); - } - } else if (dependency instanceof FileCollectionDependency) { - for (File file : ((FileCollectionDependency) dependency).getFiles()) { - try (final InputStream is = new FileInputStream(file)) { - final byte[] buf = new byte[4096]; - int read; - while ((read = is.read(buf)) != -1) { - digest.update(buf, 0, read); - } - } catch (final IOException ex) { - // ignore, will show up when we try to actually read the mappings - } - } - } else { - // the best we can do - byte[] bytes = new byte[32]; - new Random().nextBytes(bytes); - digest.update(bytes); - } - } - } -} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java new file mode 100644 index 00000000..a932d163 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java @@ -0,0 +1,98 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.cadixdev.lorenz.io.proguard.ProGuardReader; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.gradle.api.Project; +import org.spongepowered.gradle.vanilla.MinecraftExtension; +import org.spongepowered.gradle.vanilla.internal.model.Download; +import org.spongepowered.gradle.vanilla.internal.repository.modifier.ArtifactModifier; +import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; +import org.spongepowered.gradle.vanilla.resolver.HashAlgorithm; + +import java.io.IOException; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.Locale; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +public class OfficialMappingsEntry extends MappingsEntry { + public static final String NAME = "official"; + private boolean hasInitialized = false; + + public OfficialMappingsEntry(Project project, MinecraftExtension extension) { + super(project, extension, NAME); + format(ProGuardMappingFormat.NAME); + hasInitialized = true; + } + + @Override + public void format(@NonNull String format) { + if (hasInitialized) { + throw new IllegalStateException("Cannot modify the format of \"" + NAME + "\""); + } else { + super.format(format); + } + } + + @Override + public void dependency(@Nullable Object dependencyNotation) { + throw new IllegalStateException("Cannot modify the dependency of \"" + NAME + "\""); + } + + @Override + public void parent(@Nullable String parent) { + throw new IllegalStateException("Cannot modify the parent of \"" + NAME + "\""); + } + + @Override + public void inverse(boolean isInverse) { + throw new IllegalStateException("Cannot invert \"" + NAME + "\""); + } + + @Override + protected @NonNull MappingSet doResolve( + MinecraftResolver.@NonNull Context context, + MinecraftResolver.@NonNull MinecraftEnvironment environment, + @NonNull MinecraftPlatform platform, + ArtifactModifier.@NonNull SharedArtifactSupplier sharedArtifactSupplier, + @NonNull Set alreadySeen) { + @SuppressWarnings("unchecked") + CompletableFuture[] mappingsFutures = platform.activeSides().stream().map(side -> { + Download mappingsDownload = environment.metadata().requireDownload(side.mappingsArtifact()); + return context.downloader().downloadAndValidate( + mappingsDownload.url(), + sharedArtifactSupplier.supply(side.name().toLowerCase(Locale.ROOT) + "_m-obf", "mappings", "txt"), + HashAlgorithm.SHA1, + mappingsDownload.sha1() + ).thenApplyAsync(downloadResult -> { + if (!downloadResult.isPresent()) { + throw new IllegalArgumentException("No mappings were available for Minecraft " + environment.metadata().id() + "side " + side.name() + + "! Official mappings are only available for releases 1.14.4 and newer."); + } + MappingSet mappings = MappingSet.create(); + try (ProGuardReader reader = new ProGuardReader(Files.newBufferedReader(downloadResult.get()))) { + reader.read(mappings); + } catch (IOException e) { + throw new CompletionException(e); + } + return mappings.reverse(); // proguard mappings are backwards + }, context.executor()); + }).toArray(CompletableFuture[]::new); + CompletableFuture mappingFuture = CompletableFuture.allOf(mappingsFutures) + .thenApplyAsync($ -> Arrays.stream(mappingsFutures).map(CompletableFuture::join).reduce(MappingSet::merge).orElseGet(MappingSet::create)); + + + return mappingFuture.join(); + } + + @Override + public @NonNull String computeStateKey() { + return ""; + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingsReader.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingFormat.java similarity index 57% rename from subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingsReader.java rename to subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingFormat.java index 25edf88a..3dcec10b 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingsReader.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingFormat.java @@ -3,20 +3,27 @@ import org.cadixdev.lorenz.MappingSet; import org.cadixdev.lorenz.io.proguard.ProGuardReader; import org.checkerframework.checker.nullness.qual.NonNull; -import org.spongepowered.gradle.vanilla.repository.MappingsReader; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -public class ProGuardMappingsReader implements MappingsReader { +public class ProGuardMappingFormat extends MappingFormat<@NonNull MappingsEntry> { + public static final String NAME = "proguard"; + + public ProGuardMappingFormat() { + super(MappingsEntry.class); + } + @Override public @NonNull String getName() { - return "proguard"; + return NAME; } @Override - public @NonNull MappingSet read(final @NonNull Path file) throws IOException { + public @NonNull MappingSet read(final @NonNull Path file, final @NonNull MappingsEntry entry) throws IOException { final MappingSet scratchMappings = MappingSet.create(); try (ProGuardReader proguard = new ProGuardReader(Files.newBufferedReader(file))) { proguard.read(scratchMappings); diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java new file mode 100644 index 00000000..ebf961dd --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java @@ -0,0 +1,27 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; +import org.spongepowered.gradle.vanilla.repository.mappings.TinyMappingsEntry; + +import java.io.IOException; +import java.nio.file.Path; + +public class TinyMappingFormat extends MappingFormat<@NonNull TinyMappingsEntry> { + public TinyMappingFormat() { + super(TinyMappingsEntry.class); + } + + @Override + public @NonNull String getName() { + return "tiny"; + } + + @Override + public @NonNull MappingSet read(@NonNull Path file, @NonNull TinyMappingsEntry entry) throws IOException { + MappingSet mappings = MappingSet.create(); + net.fabricmc.lorenztiny.TinyMappingFormat.DETECT.read(mappings, file, entry.from().get(), entry.to().get()); + return mappings; + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java index c0832979..350b7f06 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java @@ -2,27 +2,23 @@ import org.cadixdev.lorenz.MappingSet; import org.checkerframework.checker.nullness.qual.Nullable; -import org.gradle.api.provider.ListProperty; -import org.spongepowered.gradle.vanilla.internal.repository.mappings.MappingsBuilderImpl; import org.spongepowered.gradle.vanilla.internal.resolver.AsyncUtils; import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; -import org.spongepowered.gradle.vanilla.repository.MappingsReader; import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; -import org.spongepowered.gradle.vanilla.resolver.HashAlgorithm; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; -import java.security.MessageDigest; +import java.io.IOException; +import java.io.UncheckedIOException; import java.util.concurrent.CompletableFuture; public class MappingsModifier implements ArtifactModifier { - private static final String KEY = "cm"; // custom mapped + private static final String KEY = "map"; // custom mapped - private final MappingsBuilderImpl mappingsBuilder; - private final ListProperty readers; + private final MappingsEntry mappings; private @Nullable String stateKey; - public MappingsModifier(final MappingsBuilderImpl mappingsBuilder, ListProperty readers) { - this.mappingsBuilder = mappingsBuilder; - this.readers = readers; + public MappingsModifier(final MappingsEntry mappings) { + this.mappings = mappings; } @Override @@ -33,9 +29,7 @@ public String key() { @Override public String stateKey() { if (stateKey == null) { - final MessageDigest digest = HashAlgorithm.SHA1.digest(); - mappingsBuilder.computeStateKey(digest); - return this.stateKey = HashAlgorithm.toHexString(digest.digest()); + return this.stateKey = mappings.computeStateKey(); } return stateKey; } @@ -43,7 +37,12 @@ public String stateKey() { @Override public CompletableFuture providePopulator(MinecraftResolver.Context context) { return AsyncUtils.failableFuture(() -> (atlasContext, result, side, sharedArtifactProvider) -> { - MappingSet mappings = mappingsBuilder.create(readers.get()); + final MappingSet mappings; + try { + mappings = this.mappings.resolve(context, result, side, sharedArtifactProvider); + } catch (IOException e) { + throw new UncheckedIOException("An exception occurred while trying to read mappings", e); + } return AtlasTransformers.remap(mappings, atlasContext.inheritanceProvider()); }, context.executor()); } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java deleted file mode 100644 index 3ba488dd..00000000 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/OfficialMappingsModifier.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.spongepowered.gradle.vanilla.internal.repository.modifier; - -import org.cadixdev.lorenz.MappingSet; -import org.cadixdev.lorenz.io.proguard.ProGuardReader; -import org.spongepowered.gradle.vanilla.internal.model.Download; -import org.spongepowered.gradle.vanilla.internal.resolver.AsyncUtils; -import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; -import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; -import org.spongepowered.gradle.vanilla.resolver.HashAlgorithm; - -import java.io.IOException; -import java.nio.file.Files; -import java.util.Arrays; -import java.util.Locale; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; - -public class OfficialMappingsModifier implements ArtifactModifier { - private static final String KEY = "map"; - - @Override - public String key() { - return KEY; - } - - @Override - public String stateKey() { - return ""; - } - - @Override - public CompletableFuture providePopulator(MinecraftResolver.Context context) { - return AsyncUtils.failableFuture(() -> (atlasContext, result, platform, sharedArtifactProvider) -> { - @SuppressWarnings("unchecked") - CompletableFuture[] mappingsFutures = platform.activeSides().stream().map(side -> { - Download mappingsDownload = result.metadata().requireDownload(side.mappingsArtifact()); - return context.downloader().downloadAndValidate( - mappingsDownload.url(), - sharedArtifactProvider.supply(side.name().toLowerCase(Locale.ROOT) + "_m-obf", "mappings", "txt"), - HashAlgorithm.SHA1, - mappingsDownload.sha1() - ).thenApplyAsync(downloadResult -> { - if (!downloadResult.isPresent()) { - throw new IllegalArgumentException("No mappings were available for Minecraft " + result.metadata().id() + "side " + side.name() - + "! Official mappings are only available for releases 1.14.4 and newer."); - } - MappingSet mappings = MappingSet.create(); - try (ProGuardReader reader = new ProGuardReader(Files.newBufferedReader(downloadResult.get()))) { - reader.read(mappings); - } catch (IOException e) { - throw new CompletionException(e); - } - return mappings.reverse(); // proguard mappings are backwards - }, context.executor()); - }).toArray(CompletableFuture[]::new); - CompletableFuture mappingFuture = CompletableFuture.allOf(mappingsFutures) - .thenApplyAsync($ -> Arrays.stream(mappingsFutures).map(CompletableFuture::join).reduce(MappingSet::merge).orElseGet(MappingSet::create)); - - - MappingSet mappings = mappingFuture.join(); - return AtlasTransformers.remap(mappings, atlasContext.inheritanceProvider()); - }, context.executor()); - } - - @Override - public boolean requiresLocalStorage() { - return false; - } -} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsBuilder.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsBuilder.java deleted file mode 100644 index 255f3487..00000000 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsBuilder.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.spongepowered.gradle.vanilla.repository; - -public interface MappingsBuilder { - void add(String formatName, Object dependencyNotation); -} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsReader.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsReader.java deleted file mode 100644 index d38de43b..00000000 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MappingsReader.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.spongepowered.gradle.vanilla.repository; - -import org.cadixdev.lorenz.MappingSet; - -import java.io.IOException; -import java.nio.file.Path; - -public interface MappingsReader { - String getName(); - MappingSet read(final Path file) throws IOException; -} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/DelegatingMappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/DelegatingMappingsEntry.java new file mode 100644 index 00000000..a0c1c289 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/DelegatingMappingsEntry.java @@ -0,0 +1,47 @@ +package org.spongepowered.gradle.vanilla.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.gradle.api.NamedDomainObjectProvider; +import org.gradle.api.Project; +import org.spongepowered.gradle.vanilla.MinecraftExtension; +import org.spongepowered.gradle.vanilla.internal.repository.modifier.ArtifactModifier; +import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; + +import java.io.IOException; +import java.util.Set; + +public class DelegatingMappingsEntry extends MappingsEntry { + private @Nullable NamedDomainObjectProvider delegateTo; + + public DelegatingMappingsEntry(Project project, MinecraftExtension extension, String name) { + super(project, extension, name); + } + + public @Nullable NamedDomainObjectProvider delegateTo() { + return delegateTo; + } + public void delegateTo(MappingsEntry delegateTo) { + delegateTo(extension.getMappings().named(delegateTo.getName())); + } + public void delegateTo(NamedDomainObjectProvider delegateTo) { + this.delegateTo = delegateTo; + } + public void delegateTo(String delegateTo) { + delegateTo(extension.getMappings().named(delegateTo)); + } + + @Override + protected MappingSet doResolve( + MinecraftResolver.Context context, + MinecraftResolver.MinecraftEnvironment environment, + MinecraftPlatform platform, + ArtifactModifier.SharedArtifactSupplier sharedArtifactSupplier, + Set alreadySeen) throws IOException { + if (delegateTo == null) { + throw new IllegalStateException("\"" + getName() + "\" delegateTo has not been initialized"); + } + return extension.getMappings().getByName(delegateTo.getName()).resolve(context, environment, platform, sharedArtifactSupplier, alreadySeen); + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingFormat.java new file mode 100644 index 00000000..d0656b99 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingFormat.java @@ -0,0 +1,32 @@ +package org.spongepowered.gradle.vanilla.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.gradle.api.Named; + +import java.io.IOException; +import java.nio.file.Path; + +public abstract class MappingFormat implements Named { + private final Class entryType; + + protected MappingFormat(Class entryType) { + this.entryType = entryType; + } + + public Class entryType() { + return entryType; + } + + public abstract MappingSet read(final Path file, final T entry) throws IOException; + + @Override + public int hashCode() { + return getName().hashCode(); + } + + @Override + public boolean equals(Object other) { + return other instanceof MappingFormat && ((MappingFormat<@NonNull ?>) other).getName().equals(getName()); + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsContainer.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsContainer.java new file mode 100644 index 00000000..9bd96525 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsContainer.java @@ -0,0 +1,356 @@ +package org.spongepowered.gradle.vanilla.repository.mappings; + +import groovy.lang.Closure; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.gradle.api.Action; +import org.gradle.api.DomainObjectCollection; +import org.gradle.api.InvalidUserDataException; +import org.gradle.api.NamedDomainObjectCollectionSchema; +import org.gradle.api.NamedDomainObjectContainer; +import org.gradle.api.NamedDomainObjectProvider; +import org.gradle.api.NamedDomainObjectSet; +import org.gradle.api.Namer; +import org.gradle.api.PolymorphicDomainObjectContainer; +import org.gradle.api.Project; +import org.gradle.api.Rule; +import org.gradle.api.UnknownDomainObjectException; +import org.gradle.api.internal.NamedDomainObjectContainerConfigureDelegate; +import org.gradle.api.provider.Provider; +import org.gradle.api.specs.Spec; +import org.gradle.util.ConfigureUtil; +import org.spongepowered.gradle.vanilla.MinecraftExtension; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; + +public class MappingsContainer implements PolymorphicDomainObjectContainer { + private final Project project; + private final MinecraftExtension extension; + private final PolymorphicDomainObjectContainer delegate; + + public MappingsContainer(Project project, MinecraftExtension extension) { + this.project = project; + this.extension = extension; + delegate = project.getObjects().polymorphicDomainObjectContainer(MappingsEntry.class); + } + + // -- Delegating to actual implementation -- // + + @Override + public U create(String name, Class type) throws InvalidUserDataException { + return delegate.create(name, type); + } + + @Override + public U maybeCreate(String name, Class type) throws InvalidUserDataException { + return delegate.maybeCreate(name, type); + } + + @Override + public U create(String name, Class type, Action configuration) throws InvalidUserDataException { + return delegate.create(name, type, configuration); + } + + @Override + public NamedDomainObjectContainer containerWithType(Class type) { + return delegate.containerWithType(type); + } + + @Override + public NamedDomainObjectProvider register(String name, Class type, Action configurationAction) throws InvalidUserDataException { + return delegate.register(name, type, configurationAction); + } + + @Override + public NamedDomainObjectProvider register(String name, Class type) throws InvalidUserDataException { + return delegate.register(name, type); + } + + @Override + public MappingsEntry create(final String name) throws InvalidUserDataException { + return this.delegate.create(name); + } + + @Override + public MappingsEntry maybeCreate(final String name) { + return this.delegate.maybeCreate(name); + } + + @Override + @SuppressWarnings("rawtypes") + public MappingsEntry create(final String name, final Closure configureClosure) throws InvalidUserDataException { + return this.delegate.create(name, configureClosure); + } + + @Override + public MappingsEntry create(final String name, final Action configureAction) + throws InvalidUserDataException { + return this.delegate.create(name, configureAction); + } + + @Override + @SuppressWarnings("rawtypes") + public NamedDomainObjectContainer configure(final Closure configureClosure) { + // TODO: This uses internal API, see if there's a more 'public' way to do this + return ConfigureUtil.configureSelf(configureClosure, this, new NamedDomainObjectContainerConfigureDelegate(configureClosure, this)); + } + + @Override + public NamedDomainObjectProvider register(final String name, final Action configurationAction) + throws InvalidUserDataException { + return this.delegate.register(name, configurationAction); + } + + @Override + public NamedDomainObjectProvider register(final String name) throws InvalidUserDataException { + return this.delegate.register(name); + } + + @Override + public int size() { + return this.delegate.size(); + } + + @Override + public boolean isEmpty() { + return this.delegate.isEmpty(); + } + + @Override + public boolean contains(final Object o) { + return this.delegate.contains(o); + } + + @Override + public Iterator iterator() { + return this.delegate.iterator(); + } + + @Override + public Object[] toArray() { + return this.delegate.toArray(); + } + + @Override public T[] toArray(final T[] a) { + return this.delegate.toArray(a); + } + + @Override + public boolean add(final MappingsEntry e) { + return this.delegate.add(e); + } + + @Override + public boolean remove(final Object o) { + return this.delegate.remove(o); + } + + @Override + public boolean containsAll(final Collection c) { + return this.delegate.containsAll(c); + } + + @Override + public boolean addAll(final Collection c) { + return this.delegate.addAll(c); + } + + @Override + public boolean removeAll(final Collection c) { + return this.delegate.removeAll(c); + } + + @Override + public boolean retainAll(final Collection c) { + return this.delegate.retainAll(c); + } + + @Override + public void clear() { + this.delegate.clear(); + } + + @Override + public Namer getNamer() { + return this.delegate.getNamer(); + } + + @Override + public SortedMap getAsMap() { + return this.delegate.getAsMap(); + } + + @Override + public SortedSet getNames() { + return this.delegate.getNames(); + } + + @Nullable + @Override + public MappingsEntry findByName(final String name) { + return this.delegate.findByName(name); + } + + @Override + public MappingsEntry getByName(final String name) throws UnknownDomainObjectException { + return this.delegate.getByName(name); + } + + @Override + @SuppressWarnings("rawtypes") + public MappingsEntry getByName(final String name, final Closure configureClosure) throws UnknownDomainObjectException { + return this.delegate.getByName(name, configureClosure); + } + + @Override + public MappingsEntry getByName(final String name, final Action configureAction) throws UnknownDomainObjectException { + return this.delegate.getByName(name, configureAction); + } + + @Override + public MappingsEntry getAt(final String name) throws UnknownDomainObjectException { + return this.delegate.getAt(name); + } + + @Override + public Rule addRule(final Rule rule) { + return this.delegate.addRule(rule); + } + + @Override + @SuppressWarnings("rawtypes") + public Rule addRule(final String description, final Closure ruleAction) { + return this.delegate.addRule(description, ruleAction); + } + + @Override + public Rule addRule(final String description, final Action ruleAction) { + return this.delegate.addRule(description, ruleAction); + } + + @Override + public List getRules() { + return this.delegate.getRules(); + } + + @Override + public void addLater(final Provider provider) { + this.delegate.addLater(provider); + } + + @Override + public void addAllLater( + final Provider> provider) { + this.delegate.addAllLater(provider); + } + + @Override + public NamedDomainObjectSet withType(final Class type) { + return this.delegate.withType(type); + } + + @Override + public DomainObjectCollection withType(final Class type, final Action configureAction) { + return this.delegate.withType(type, configureAction); + } + + @Override + @SuppressWarnings("rawtypes") + public DomainObjectCollection withType(final Class type, final Closure configureClosure) { + return this.delegate.withType(type, configureClosure); + } + + @Override + public NamedDomainObjectSet matching(final Spec spec) { + return this.delegate.matching(spec); + } + + @Override + @SuppressWarnings("rawtypes") + public NamedDomainObjectSet matching(final Closure spec) { + return this.delegate.matching(spec); + } + + @Override + public Action whenObjectAdded(final Action action) { + return this.delegate.whenObjectAdded(action); + } + + @Override + @SuppressWarnings("rawtypes") + public void whenObjectAdded(final Closure action) { + this.delegate.whenObjectAdded(action); + } + + @Override + public Action whenObjectRemoved(final Action action) { + return this.delegate.whenObjectRemoved(action); + } + + @Override + @SuppressWarnings("rawtypes") + public void whenObjectRemoved(final Closure action) { + this.delegate.whenObjectRemoved(action); + } + + @Override + public void all(final Action action) { + this.delegate.all(action); + } + + @Override + @SuppressWarnings("rawtypes") + public void all(final Closure action) { + this.delegate.all(action); + } + + @Override + public void configureEach(final Action action) { + this.delegate.configureEach(action); + } + + @Override + public NamedDomainObjectProvider named(final String name) throws UnknownDomainObjectException { + return this.delegate.named(name); + } + + @Override + public NamedDomainObjectProvider named( + final String name, + final Action configurationAction + ) throws UnknownDomainObjectException { + return this.delegate.named(name, configurationAction); + } + + @Override + public NamedDomainObjectProvider named( + final String name, + final Class type + ) throws UnknownDomainObjectException { + return this.delegate.named(name, type); + } + + @Override + public NamedDomainObjectProvider named( + final String name, + final Class type, + final Action configurationAction + ) throws UnknownDomainObjectException { + return this.delegate.named(name, type, configurationAction); + } + + @Override + public NamedDomainObjectCollectionSchema getCollectionSchema() { + return this.delegate.getCollectionSchema(); + } + + @Override + @SuppressWarnings("rawtypes") + public Set findAll(final Closure spec) { + return this.delegate.findAll(spec); + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java new file mode 100644 index 00000000..8f49b135 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java @@ -0,0 +1,204 @@ +package org.spongepowered.gradle.vanilla.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.gradle.api.Named; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.artifacts.DependencyArtifact; +import org.gradle.api.artifacts.FileCollectionDependency; +import org.gradle.api.artifacts.ModuleDependency; +import org.gradle.api.provider.Property; +import org.spongepowered.gradle.vanilla.MinecraftExtension; +import org.spongepowered.gradle.vanilla.internal.repository.modifier.ArtifactModifier; +import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; +import org.spongepowered.gradle.vanilla.resolver.HashAlgorithm; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.security.MessageDigest; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; + +public class MappingsEntry implements Named { + protected final Project project; + protected final MinecraftExtension extension; + private final String name; + private final Property format; + private final String configurationName; + private @Nullable Object dependency; + private @Nullable Dependency dependencyObj; + private final Property parent; + private final Property inverse; + + public MappingsEntry(Project project, MinecraftExtension extension, String name) { + this.project = project; + this.extension = extension; + this.name = name; + this.format = project.getObjects().property(String.class); + this.configurationName = name + "Mappings"; + this.parent = project.getObjects().property(String.class); + this.inverse = project.getObjects().property(Boolean.class).convention(false); + } + + @Override + public String getName() { + return name; + } + + public @Nullable Property format() { + return format; + } + public void format(MappingFormat<@NonNull ?> format) { + format(format.getName()); + } + public void format(String format) { + this.format.set(format); + } + + public @Nullable Object dependency() { + return dependency; + } + public void dependency(Object dependencyNotation) { + if (this.dependency != null) { + throw new IllegalStateException("MappingsEntry.dependency(Object) called twice"); + } + project.getConfigurations().register(configurationName, config -> { + config.setVisible(false); + config.setCanBeConsumed(false); + config.setCanBeResolved(true); + }); + this.dependencyObj = project.getDependencies().add(configurationName, dependencyNotation); + this.dependency = dependencyNotation; + } + + public Property<@Nullable String> parent() { + return parent; + } + public void parent(MappingsEntry parent) { + parent(parent.getName()); + } + public void parent(String parent) { + this.parent.set(parent); + } + + public Property isInverse() { + return inverse; + } + public void invert() { + inverse(true); + } + public void inverse(boolean isInverse) { + inverse.set(isInverse); + } + + public int hashCode() { + return name.hashCode(); + } + + public boolean equals(Object other) { + return other instanceof MappingsEntry && ((MappingsEntry) other).name.equals(this.name); + } + + public final MappingSet resolve( + MinecraftResolver.Context context, + MinecraftResolver.MinecraftEnvironment environment, + MinecraftPlatform platform, + ArtifactModifier.SharedArtifactSupplier sharedArtifactSupplier + ) throws IOException { + return resolve(context, environment, platform, sharedArtifactSupplier, new HashSet<>()); + } + + final MappingSet resolve( + MinecraftResolver.Context context, + MinecraftResolver.MinecraftEnvironment environment, + MinecraftPlatform platform, + ArtifactModifier.SharedArtifactSupplier sharedArtifactSupplier, + Set alreadySeen + ) throws IOException { + if (!alreadySeen.add(getName())) { + throw new IllegalStateException("Recursive mapping dependencies for \"" + getName() + "\""); + } + MappingSet resolved = doResolve(context, environment, platform, sharedArtifactSupplier, alreadySeen); + if (this.inverse.get()) { + resolved = resolved.reverse(); + } + if (parent.getOrNull() != null) { + resolved = extension.getMappings().getByName(parent.get()).resolve(context, environment, platform, sharedArtifactSupplier, alreadySeen).merge(resolved); + } + return resolved; + } + + protected MappingSet doResolve( + MinecraftResolver.Context context, + MinecraftResolver.MinecraftEnvironment environment, + MinecraftPlatform platform, + ArtifactModifier.SharedArtifactSupplier sharedArtifactSupplier, + Set alreadySeen) throws IOException { + if (dependency == null) { + throw new IllegalStateException("Mappings entry \"" + getName() + "\" of format \"" + format.get() + "\" must have a dependency"); + } + @SuppressWarnings("unchecked") + MappingFormat mappingFormat = (MappingFormat) extension.getMappingFormats().getByName(format.get()); + if (!mappingFormat.entryType().isInstance(this)) { + throw new IllegalStateException("Mappings entry \"" + getName() + "\" of type \"" + getClass().getName() + "\" is not compatible with mapping format \"" + format.get() + "\""); + } + Set resolvedFiles = project.getConfigurations().getByName(configurationName).resolve(); + if (resolvedFiles.size() != 1) { + throw new IllegalStateException("Mappings entry \"" + getName() + "\" did not resolve to exactly 1 file"); + } + Path resolvedFile = resolvedFiles.iterator().next().toPath(); + return mappingFormat.read(resolvedFile, mappingFormat.entryType().cast(this)); + } + + public String computeStateKey() { + final MessageDigest digest = HashAlgorithm.SHA1.digest(); + computeHash(digest); + return HashAlgorithm.toHexString(digest.digest()); + } + + protected void computeHash(MessageDigest digest) { + digest.update((byte) 0); + digest.update(getName().getBytes(StandardCharsets.UTF_8)); + digest.update((byte) 1); + digest.update(format.get().getBytes(StandardCharsets.UTF_8)); + if (dependencyObj != null) { + digest.update((byte) 2); + if (dependencyObj instanceof ModuleDependency) { + for (DependencyArtifact artifact : ((ModuleDependency) dependencyObj).getArtifacts()) { + digest.update(artifact.getUrl().getBytes(StandardCharsets.UTF_8)); + } + } else if (dependencyObj instanceof FileCollectionDependency) { + for (File file : ((FileCollectionDependency) dependencyObj).getFiles()) { + try (final InputStream is = new FileInputStream(file)) { + final byte[] buf = new byte[4096]; + int read; + while ((read = is.read(buf)) != -1) { + digest.update(buf, 0, read); + } + } catch (final IOException ex) { + // ignore, will show up when we try to actually read the mappings + } + } + } else { + byte[] bytes = new byte[32]; + new Random().nextBytes(bytes); + digest.update(bytes); + } + } + if (inverse.get()) { + digest.update((byte) 3); + } + if (parent.getOrNull() != null) { + digest.update((byte) 4); + extension.getMappings().getByName(parent.get()).computeHash(digest); + } + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/TinyMappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/TinyMappingsEntry.java new file mode 100644 index 00000000..733e7fdc --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/TinyMappingsEntry.java @@ -0,0 +1,36 @@ +package org.spongepowered.gradle.vanilla.repository.mappings; + +import org.gradle.api.Project; +import org.gradle.api.provider.Property; +import org.spongepowered.gradle.vanilla.MinecraftExtension; + +public class TinyMappingsEntry extends MappingsEntry { + private final Property from; + private final Property to; + + public TinyMappingsEntry( + Project project, + MinecraftExtension extension, + String name + ) { + super(project, extension, name); + this.from = project.getObjects().property(String.class); + this.to = project.getObjects().property(String.class); + } + + public Property from() { + return from; + } + + public void from(String from) { + this.from.set(from); + } + + public Property to() { + return to; + } + + public void to(String to) { + this.to.set(to); + } +} diff --git a/subprojects/gradle-plugin/src/main/kotlin/org/spongepowered/gradle/vanilla/repository/mappings/MappingsExtensions.kt b/subprojects/gradle-plugin/src/main/kotlin/org/spongepowered/gradle/vanilla/repository/mappings/MappingsExtensions.kt new file mode 100644 index 00000000..ab39223f --- /dev/null +++ b/subprojects/gradle-plugin/src/main/kotlin/org/spongepowered/gradle/vanilla/repository/mappings/MappingsExtensions.kt @@ -0,0 +1,2 @@ +package org.spongepowered.gradle.vanilla.repository.mappings + From b42e0fa7c2c408c936855185c860cc36962c10a2 Mon Sep 17 00:00:00 2001 From: Joe Date: Mon, 4 Oct 2021 01:32:50 +0100 Subject: [PATCH 04/15] Some fixes --- .../repository/mappings/TinyMappingFormat.java | 17 +++++++++++++++++ .../repository/MinecraftResolverImpl.java | 3 ++- .../repository/mappings/MappingsContainer.java | 6 +++++- .../repository/mappings/MappingsEntry.java | 9 ++++++--- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java index ebf961dd..960c6de4 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java @@ -6,7 +6,10 @@ import org.spongepowered.gradle.vanilla.repository.mappings.TinyMappingsEntry; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; public class TinyMappingFormat extends MappingFormat<@NonNull TinyMappingsEntry> { public TinyMappingFormat() { @@ -20,8 +23,22 @@ public TinyMappingFormat() { @Override public @NonNull MappingSet read(@NonNull Path file, @NonNull TinyMappingsEntry entry) throws IOException { + boolean isTempFile = false; + if (file.getFileName().endsWith(".jar")) { + try (ZipFile zip = new ZipFile(file.toFile())) { + ZipEntry zipEntry = zip.getEntry("mappings/mappings.tiny"); + if (zipEntry != null) { + file = Files.createTempFile(null, null); + Files.copy(zip.getInputStream(zipEntry), file); + isTempFile = true; + } + } + } MappingSet mappings = MappingSet.create(); net.fabricmc.lorenztiny.TinyMappingFormat.DETECT.read(mappings, file, entry.from().get(), entry.to().get()); + if (isTempFile) { + Files.delete(file); + } return mappings; } } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java index 71b4c7db..ef2b47a8 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java @@ -413,7 +413,8 @@ public CompletableFuture> provide( } } } - } + }, + executor )); } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsContainer.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsContainer.java index 9bd96525..8d724ed2 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsContainer.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsContainer.java @@ -4,6 +4,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.gradle.api.Action; import org.gradle.api.DomainObjectCollection; +import org.gradle.api.ExtensiblePolymorphicDomainObjectContainer; import org.gradle.api.InvalidUserDataException; import org.gradle.api.NamedDomainObjectCollectionSchema; import org.gradle.api.NamedDomainObjectContainer; @@ -35,7 +36,10 @@ public class MappingsContainer implements PolymorphicDomainObjectContainer delegate = project.getObjects().polymorphicDomainObjectContainer(MappingsEntry.class); + delegate.registerFactory(MappingsEntry.class, name -> new MappingsEntry(this.project, this.extension, name)); + delegate.registerFactory(TinyMappingsEntry.class, name -> new TinyMappingsEntry(this.project, this.extension, name)); + this.delegate = delegate; } // -- Delegating to actual implementation -- // diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java index 8f49b135..96e70c48 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java @@ -6,7 +6,6 @@ import org.gradle.api.Named; import org.gradle.api.Project; import org.gradle.api.artifacts.Dependency; -import org.gradle.api.artifacts.DependencyArtifact; import org.gradle.api.artifacts.FileCollectionDependency; import org.gradle.api.artifacts.ModuleDependency; import org.gradle.api.provider.Property; @@ -172,8 +171,12 @@ protected void computeHash(MessageDigest digest) { if (dependencyObj != null) { digest.update((byte) 2); if (dependencyObj instanceof ModuleDependency) { - for (DependencyArtifact artifact : ((ModuleDependency) dependencyObj).getArtifacts()) { - digest.update(artifact.getUrl().getBytes(StandardCharsets.UTF_8)); + if (dependencyObj.getGroup() != null) { + digest.update(dependencyObj.getGroup().getBytes(StandardCharsets.UTF_8)); + } + digest.update((":" + dependencyObj.getName()).getBytes(StandardCharsets.UTF_8)); + if (dependencyObj.getVersion() != null) { + digest.update((":" + dependencyObj.getVersion()).getBytes(StandardCharsets.UTF_8)); } } else if (dependencyObj instanceof FileCollectionDependency) { for (File file : ((FileCollectionDependency) dependencyObj).getFiles()) { From 7c1358d6f194c0af737df0f1d60a30fb288bd51b Mon Sep 17 00:00:00 2001 From: zml Date: Sun, 3 Oct 2021 22:06:11 -0700 Subject: [PATCH 05/15] wip: add in a sync executor to pass tasks back to the gradle thread in a less brittle way starts on fixing #39 --- .../internal/bundler/BundleElement.java | 1 - .../internal/bundler/BundlerMetadata.java | 4 +- ...taMetadataSupplierAndArtifactProducer.java | 7 ++- .../repository/MinecraftRepositoryPlugin.java | 4 +- .../transformer/AtlasTransformers.java | 1 - .../vanilla/repository/MinecraftResolver.java | 40 ++++++++++--- .../repository/MinecraftResolverImpl.java | 58 +++++++++++++++++-- .../vanilla/repository/MinecraftSide.java | 1 - .../gradle/vanilla/task/DecompileJarTask.java | 15 ++--- .../gradle/vanilla/task/GenEclipseRuns.java | 2 - 10 files changed, 104 insertions(+), 29 deletions(-) diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/bundler/BundleElement.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/bundler/BundleElement.java index fd086892..3540a90d 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/bundler/BundleElement.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/bundler/BundleElement.java @@ -25,7 +25,6 @@ package org.spongepowered.gradle.vanilla.internal.bundler; import org.immutables.value.Value; -import org.spongepowered.gradle.vanilla.internal.model.GroupArtifactVersion; /** * A single entry in a bundle. diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/bundler/BundlerMetadata.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/bundler/BundlerMetadata.java index 8e82d34a..3cfc2571 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/bundler/BundlerMetadata.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/bundler/BundlerMetadata.java @@ -59,10 +59,12 @@ public abstract class BundlerMetadata { /** * Attempt to read bundler metadata from a jar. * - *

If the jar is not a Minecraft bundler jar, an empty {@link Optional} will be returned.

+ *

If the jar is not a Minecraft bundler jar, an empty {@link Optional} will + * be returned.

* * @param jar the jar to read * @return parsed metadata + * @throws IOException if an error occurs while trying to read from the jar */ public static Optional read(final Path jar) throws IOException { try (final JarFile file = new JarFile(jar)) { diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/LauncherMetaMetadataSupplierAndArtifactProducer.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/LauncherMetaMetadataSupplierAndArtifactProducer.java index 2eff7ce9..5f23fc57 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/LauncherMetaMetadataSupplierAndArtifactProducer.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/LauncherMetaMetadataSupplierAndArtifactProducer.java @@ -38,6 +38,7 @@ import org.spongepowered.gradle.vanilla.resolver.ResolutionResult; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import javax.inject.Inject; @@ -74,8 +75,10 @@ public void execute(final ComponentMetadataSupplierDetails details) { final MinecraftResolver resolver = providerService.resolver(); // Request the appropriate jar, block until it's provided // TODO: maybe validate that the state keys of the provided modifiers actually match the artifact ID? - final ResolutionResult - resolution = resolver.provide(platform.get(), version, providerService.peekModifiers()).get(); + final CompletableFuture> resolutionFuture = resolver + .provide(platform.get(), version, providerService.peekModifiers()); + + final ResolutionResult resolution = resolver.processSyncTasksUntilComplete(resolutionFuture); if (!resolution.isPresent()) { return; } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java index 2d82ac4a..f2af3a71 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java @@ -42,8 +42,8 @@ import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.provider.Provider; import org.gradle.build.event.BuildEventsListenerRegistry; -import org.spongepowered.gradle.vanilla.internal.Constants; import org.spongepowered.gradle.vanilla.MinecraftExtension; +import org.spongepowered.gradle.vanilla.internal.Constants; import org.spongepowered.gradle.vanilla.internal.MinecraftExtensionImpl; import org.spongepowered.gradle.vanilla.internal.model.VersionClassifier; import org.spongepowered.gradle.vanilla.internal.repository.modifier.ArtifactModifier; @@ -184,7 +184,7 @@ private void configureResolutionStrategy( // If we do have a version, try to resolve that fixed version if (version != null) { try { - resolver.provide(platform.get(), version, providerService.peekModifiers()).get(); + resolver.processSyncTasksUntilComplete(resolver.provide(platform.get(), version, providerService.peekModifiers())); } catch (final InterruptedException ex) { Thread.currentThread().interrupt(); } catch (final ExecutionException ex) { diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/transformer/AtlasTransformers.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/transformer/AtlasTransformers.java index 5693dfdc..9ee5ee6a 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/transformer/AtlasTransformers.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/transformer/AtlasTransformers.java @@ -28,7 +28,6 @@ import org.cadixdev.bombe.asm.jar.JarEntryRemappingTransformer; import org.cadixdev.bombe.jar.JarEntryTransformer; import org.cadixdev.lorenz.MappingSet; -import org.cadixdev.lorenz.asm.LorenzRemapper; import org.spongepowered.gradle.vanilla.internal.asm.EnhancedClassRemapper; import org.spongepowered.gradle.vanilla.internal.asm.EnhancedRemapper; import org.spongepowered.gradle.vanilla.internal.asm.LocalVariableNamingClassVisitor; diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolver.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolver.java index b872824d..3a9f4f3c 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolver.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolver.java @@ -27,16 +27,17 @@ import org.spongepowered.gradle.vanilla.internal.model.GroupArtifactVersion; import org.spongepowered.gradle.vanilla.internal.model.VersionDescriptor; import org.spongepowered.gradle.vanilla.internal.model.VersionManifestRepository; -import org.spongepowered.gradle.vanilla.resolver.Downloader; import org.spongepowered.gradle.vanilla.internal.repository.ResolvableTool; import org.spongepowered.gradle.vanilla.internal.repository.modifier.ArtifactModifier; import org.spongepowered.gradle.vanilla.internal.repository.modifier.AssociatedResolutionFlags; +import org.spongepowered.gradle.vanilla.resolver.Downloader; import org.spongepowered.gradle.vanilla.resolver.ResolutionResult; import java.net.URLClassLoader; import java.nio.file.Path; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.function.BiConsumer; import java.util.function.Supplier; @@ -96,7 +97,21 @@ public interface MinecraftResolver { * environment and a target path * @return a future returning the result of resolving a jar path */ - CompletableFuture> produceAssociatedArtifactSync(final MinecraftPlatform side, final String version, final Set modifiers, final String id, final Set flags, final BiConsumer action); + CompletableFuture> produceAssociatedArtifactSync( + final MinecraftPlatform side, final String version, final Set modifiers, final String id, + final Set flags, final BiConsumer action + ); + + /** + * Block on the completion of a provided future, processing "sync" tasks while + * that occurs. + * + * @param the return value type + * @param future the future to await + * @return the result of the future + * @throws ExecutionException if the task execution fails + */ + T processSyncTasksUntilComplete(CompletableFuture future) throws ExecutionException, InterruptedException; interface MinecraftEnvironment { @@ -162,13 +177,22 @@ interface Context { Executor executor(); /** - * Return a child classloader with a tool and its dependencies on the - * classpath, as well as the VanillaGradle jar. + * An executor for performing main-thread synchronous operations, like some + * dependency resolution. + * + * @return the synchronous executor + */ + Executor syncExecutor(); + + /** + * Return a child classloader with a tool and its dependencies on the classpath, + * as well as the VanillaGradle jar. * - *

This is a very fragile arrangement but it allows some dependencies - * to be overridden at runtime. Classes from Gradle, VanillaGradle's - * dependencies, and the JDK can be safely shared, but VanillaGradle - * classes CAN NOT.

+ *

This is a very fragile arrangement but it allows some dependencies to be + * overridden at runtime. Classes from Gradle, VanillaGradle's dependencies, and + * the JDK can be safely shared, but VanillaGradle classes CAN NOT.

+ * + *

This must be run on the {@link #syncExecutor()}.

* * @param tool the tool to resolve * @return a class loader with the tool on the classpath diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java index 2acc322f..ba372172 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java @@ -42,17 +42,17 @@ import org.spongepowered.gradle.vanilla.internal.model.GroupArtifactVersion; import org.spongepowered.gradle.vanilla.internal.model.VersionDescriptor; import org.spongepowered.gradle.vanilla.internal.model.VersionManifestRepository; -import org.spongepowered.gradle.vanilla.internal.util.FunctionalUtils; -import org.spongepowered.gradle.vanilla.resolver.Downloader; -import org.spongepowered.gradle.vanilla.resolver.HashAlgorithm; import org.spongepowered.gradle.vanilla.internal.repository.IvyModuleWriter; import org.spongepowered.gradle.vanilla.internal.repository.ResolvableTool; import org.spongepowered.gradle.vanilla.internal.repository.modifier.ArtifactModifier; import org.spongepowered.gradle.vanilla.internal.repository.modifier.AssociatedResolutionFlags; -import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; import org.spongepowered.gradle.vanilla.internal.resolver.AsyncUtils; import org.spongepowered.gradle.vanilla.internal.resolver.FileUtils; +import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; +import org.spongepowered.gradle.vanilla.internal.util.FunctionalUtils; import org.spongepowered.gradle.vanilla.internal.util.SelfPreferringClassLoader; +import org.spongepowered.gradle.vanilla.resolver.Downloader; +import org.spongepowered.gradle.vanilla.resolver.HashAlgorithm; import org.spongepowered.gradle.vanilla.resolver.ResolutionResult; import java.io.IOException; @@ -71,6 +71,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ConcurrentHashMap; @@ -78,6 +79,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; +import java.util.concurrent.SynchronousQueue; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Supplier; @@ -95,6 +97,8 @@ public class MinecraftResolverImpl implements MinecraftResolver, MinecraftResolv private final ConcurrentMap>> artifacts = new ConcurrentHashMap<>(); private final ConcurrentMap>> associatedArtifacts = new ConcurrentHashMap<>(); private final boolean forceRefresh; + private final BlockingQueue syncTasks = new SynchronousQueue<>(); + private final Executor syncExecutor = run -> this.syncTasks.add(run); public MinecraftResolverImpl( final VersionManifestRepository manifests, @@ -127,6 +131,11 @@ public Executor executor() { return this.executor; } + @Override + public Executor syncExecutor() { + return this.syncExecutor; + } + @Override public Supplier classLoaderWithTool(final ResolvableTool tool) { final @Nullable Function toolResolver = this.toolResolver; @@ -520,6 +529,32 @@ public CompletableFuture> produceAssociatedArtifactSync( return ourResult; } + @Override + public T processSyncTasksUntilComplete(CompletableFuture future) throws InterruptedException, ExecutionException { + future.handle((res, err) -> { + this.syncTasks.add(new CompleteEvaluation(future)); + return res; + }); + + Runnable action; + for (;;) { + action = this.syncTasks.take(); + + // todo: rethrow exceptions with an ExecutionException + if (action instanceof CompleteEvaluation && ((CompleteEvaluation) action).completed == future) { + break; + } + + try { + action.run(); + } catch (final Exception ex) { + MinecraftResolverImpl.LOGGER.error("Failed to execute synchronous task {} while resolving {}", action, future, ex); + } + } + + return future.get(); + } + private String sharedArtifactFileName( final String artifactId, final String version, @@ -668,4 +703,19 @@ public VersionDescriptor.Full metadata() { } + static final class CompleteEvaluation implements Runnable { + + final CompletableFuture completed; + + CompleteEvaluation(final CompletableFuture completed) { + this.completed = completed; + } + + @Override + public void run() { + // no-op + } + + } + } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftSide.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftSide.java index b43ff0fc..d6ba6856 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftSide.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftSide.java @@ -26,7 +26,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.gradle.vanilla.internal.Constants; -import org.spongepowered.gradle.vanilla.internal.bundler.BundleElement; import org.spongepowered.gradle.vanilla.internal.bundler.BundlerMetadata; import org.spongepowered.gradle.vanilla.internal.model.DownloadClassifier; import org.spongepowered.gradle.vanilla.internal.model.GroupArtifactVersion; diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java index 227e7db2..3afa0787 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java @@ -43,15 +43,15 @@ import org.gradle.internal.component.external.model.ModuleComponentArtifactIdentifier; import org.gradle.jvm.toolchain.JavaLauncher; import org.gradle.workers.WorkerExecutor; -import org.spongepowered.gradle.vanilla.internal.Constants; import org.spongepowered.gradle.vanilla.MinecraftExtension; +import org.spongepowered.gradle.vanilla.internal.Constants; import org.spongepowered.gradle.vanilla.internal.MinecraftExtensionImpl; -import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; import org.spongepowered.gradle.vanilla.internal.repository.MinecraftProviderService; -import org.spongepowered.gradle.vanilla.resolver.ResolutionResult; import org.spongepowered.gradle.vanilla.internal.repository.modifier.ArtifactModifier; import org.spongepowered.gradle.vanilla.internal.repository.modifier.AssociatedResolutionFlags; import org.spongepowered.gradle.vanilla.internal.worker.JarDecompileWorker; +import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; +import org.spongepowered.gradle.vanilla.resolver.ResolutionResult; import java.io.File; import java.lang.management.ManagementFactory; @@ -185,12 +185,9 @@ public void execute() { this.getWorkerExecutor().await(); } ); - } finally { - DecompileJarTask.DECOMPILE_LOCK.unlock(); - } try { - final ResolutionResult result = resultFuture.get(); + final ResolutionResult result = minecraftProvider.resolver().processSyncTasksUntilComplete(resultFuture); this.setDidWork(!result.upToDate()); } catch (final ExecutionException ex) { throw new GradleException("Failed to decompile " + this.getMinecraftVersion().get(), ex.getCause()); @@ -198,6 +195,10 @@ public void execute() { Thread.currentThread().interrupt(); throw new GradleException("Interrupted"); } + + } finally { + DecompileJarTask.DECOMPILE_LOCK.unlock(); + } } } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/GenEclipseRuns.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/GenEclipseRuns.java index 3aa8b8cc..a5a4aae7 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/GenEclipseRuns.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/GenEclipseRuns.java @@ -25,7 +25,6 @@ package org.spongepowered.gradle.vanilla.task; import org.gradle.api.DefaultTask; -import org.gradle.api.InvalidUserDataException; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.provider.Property; import org.gradle.api.provider.SetProperty; @@ -37,7 +36,6 @@ import org.spongepowered.gradle.vanilla.internal.runs.EclipseRunConfigurationWriter; import org.spongepowered.gradle.vanilla.runs.RunConfiguration; -import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; From 52a783a7b49419562209c74e28ef68feaec62201 Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 5 Oct 2021 01:05:48 +0100 Subject: [PATCH 06/15] Working tiny mappings reader --- gradle.properties | 3 ++ subprojects/gradle-plugin/build.gradle.kts | 24 +++++++++--- .../gradle/vanilla/internal/Constants.java | 3 ++ .../repository/MinecraftRepositoryPlugin.java | 10 ++++- .../internal/repository/ResolvableTool.java | 37 ++++++++++++++++--- .../mappings/ProGuardMappingFormat.java | 4 +- .../mappings/TinyMappingFormat.java | 31 +++++++++++++--- .../repository/mappings/MappingFormat.java | 3 +- .../repository/mappings/MappingsEntry.java | 7 +++- .../vanilla/internal/BuildVersions.java | 4 +- .../repository/mappings/TinyReaderImpl.java | 13 +++++++ 11 files changed, 116 insertions(+), 23 deletions(-) create mode 100644 subprojects/gradle-plugin/src/remapTiny/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyReaderImpl.java diff --git a/gradle.properties b/gradle.properties index 7584e303..72d6a561 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,6 +9,9 @@ checkerVersion=3.15.0 forgeFlowerVersion=1.5.498.12 junitVersion=5.7.2 mergeToolVersion=1.1.4 +lorenzVersion=0.5.7 +lorenzTinyVersion=4.0.2 +mappingIoVersion=0.2.1 org.gradle.parallel=true kotlin.stdlib.default.dependency=false diff --git a/subprojects/gradle-plugin/build.gradle.kts b/subprojects/gradle-plugin/build.gradle.kts index 5483283d..baae3bbf 100644 --- a/subprojects/gradle-plugin/build.gradle.kts +++ b/subprojects/gradle-plugin/build.gradle.kts @@ -20,6 +20,9 @@ val jarDecompile by sourceSets.creating { val accessWiden by sourceSets.creating { configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } } +val remapTiny by sourceSets.creating { + configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } +} val shadow by sourceSets.creating { configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } } @@ -33,6 +36,9 @@ val asmVersion: String by project val forgeFlowerVersion: String by project val junitVersion: String by project val mergeToolVersion: String by project +val lorenzVersion: String by project +val lorenzTinyVersion: String by project +val mappingIoVersion: String by project dependencies { // All source sets commonDeps(gradleApi()) @@ -45,15 +51,12 @@ dependencies { // Just main implementation("com.google.code.gson:gson:2.8.7") - implementation("org.cadixdev:lorenz:0.5.7") - implementation("org.cadixdev:lorenz-asm:0.5.7") { + implementation("org.cadixdev:lorenz:$lorenzVersion") + implementation("org.cadixdev:lorenz-asm:$lorenzVersion") { exclude("org.ow2.asm") // Use our own ASM } implementation("org.cadixdev:lorenz-io-proguard:0.5.7") - compileOnly("net.fabricmc:lorenz-tiny:4.0.2") { - isTransitive = false - } compileOnlyApi("org.checkerframework:checker-qual:3.15.0") annotationProcessor("org.immutables:value:2.8.8") @@ -82,6 +85,12 @@ dependencies { } implementation(accessWiden.output) + "remapTinyCompileOnly"("org.cadixdev:lorenz:$lorenzVersion") + "remapTinyCompileOnly"("net.fabricmc:lorenz-tiny:$lorenzTinyVersion") { + isTransitive = false + } + implementation(remapTiny.output) + "shadowCompileOnly"("com.github.jengelman.gradle.plugins:shadow:6.1.0") implementation(shadow.output) @@ -101,7 +110,9 @@ tasks { "asmVersion" to asmVersion, "forgeFlowerVersion" to forgeFlowerVersion, "mergeToolVersion" to mergeToolVersion, - "accessWidenerVersion" to accessWidenerVersion + "accessWidenerVersion" to accessWidenerVersion, + "lorenzTinyVersion" to lorenzTinyVersion, + "mappingIoVersion" to mappingIoVersion ) inputs.properties(properties) @@ -128,6 +139,7 @@ tasks { from(jarMerge.output) from(jarDecompile.output) from(accessWiden.output) + from(remapTiny.output) from(shadow.output) } } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/Constants.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/Constants.java index 82a9c246..acfc6ff3 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/Constants.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/Constants.java @@ -103,6 +103,8 @@ public static final class WorkerDependencies { public static final String MERGE_TOOL = "net.minecraftforge:mergetool:" + BuildVersions.MERGE_TOOL; public static final String ACCESS_WIDENER = "net.fabricmc:access-widener:" + BuildVersions.ACCESS_WIDENER; public static final String FORGE_FLOWER = "net.minecraftforge:forgeflower:" + BuildVersions.FORGEFLOWER; + public static final String LORENZ_TINY = "net.fabricmc:lorenz-tiny:" + BuildVersions.LORENZ_TINY_VERSION; + public static final String MAPPING_IO = "net.fabricmc:mapping-io:" + BuildVersions.MAPPING_IO_VERSION; public static final String FORCED_ASM = BuildVersions.ASM; public static final String ASM_UTIL = "org.ow2.asm:asm-util:" + WorkerDependencies.FORCED_ASM; @@ -135,6 +137,7 @@ public static final class Configurations { public static final String MINECRAFT_NATIVES = "minecraftNatives"; public static final String MERGETOOL = "mergetool"; public static final String ACCESS_WIDENER = "accessWidener"; + public static final String REMAP_TINY = "remapTiny"; public static final String FORGE_FLOWER = "forgeFlower"; public static final String CLASS_DUMP = "classDump"; diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java index f2af3a71..5697384f 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java @@ -30,6 +30,8 @@ import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.Task; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.artifacts.ModuleDependency; import org.gradle.api.artifacts.ModuleVersionSelector; import org.gradle.api.artifacts.ResolutionStrategy; import org.gradle.api.artifacts.ResolvableDependencies; @@ -122,7 +124,13 @@ private void applyToProject(final Project project) { for (final ResolvableTool tool : ResolvableTool.values()) { project.getConfigurations().register(tool.id(), config -> { config.defaultDependencies(deps -> { - deps.add(project.getDependencies().create(tool.notation())); + for (ResolvableTool.Dependency dependency : tool.dependencies()) { + Dependency dep = project.getDependencies().create(dependency.notation()); + if (!dependency.isTransitive() && dep instanceof ModuleDependency) { + ((ModuleDependency) dep).setTransitive(false); + } + deps.add(dep); + } }); ConfigurationUtils.markAsJavaRuntime(project.getObjects(), config); }); diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java index 6f74414a..148a87bc 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java @@ -26,27 +26,52 @@ import org.spongepowered.gradle.vanilla.internal.Constants; +import java.util.Arrays; + /** * Tools used for specific operations in the Minecraft preparation pipeline. */ public enum ResolvableTool { JAR_MERGE(Constants.Configurations.MERGETOOL, Constants.WorkerDependencies.MERGE_TOOL), - ACCESS_WIDENER(Constants.Configurations.ACCESS_WIDENER, Constants.WorkerDependencies.ACCESS_WIDENER) + ACCESS_WIDENER(Constants.Configurations.ACCESS_WIDENER, Constants.WorkerDependencies.ACCESS_WIDENER), + REMAP_TINY(Constants.Configurations.REMAP_TINY, new Dependency(Constants.WorkerDependencies.LORENZ_TINY, false), new Dependency(Constants.WorkerDependencies.MAPPING_IO, true)), ; private final String id; - private final String notation; + private final Dependency[] dependencies; + + ResolvableTool(final String id, final String... notations) { + this(id, Arrays.stream(notations).map(notation -> new Dependency(notation, true)).toArray(Dependency[]::new)); + } - ResolvableTool(final String id, final String notation) { + ResolvableTool(final String id, final Dependency... dependencies) { this.id = id; - this.notation = notation; + this.dependencies = dependencies; } public String id() { return this.id; } - public String notation() { - return this.notation; + public Dependency[] dependencies() { + return this.dependencies; + } + + public static class Dependency { + private final String notation; + private final boolean isTransitive; + + public Dependency(final String notation, final boolean isTransitive) { + this.notation = notation; + this.isTransitive = isTransitive; + } + + public String notation() { + return notation; + } + + public boolean isTransitive() { + return isTransitive; + } } } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingFormat.java index 3dcec10b..156e516d 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingFormat.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ProGuardMappingFormat.java @@ -3,6 +3,7 @@ import org.cadixdev.lorenz.MappingSet; import org.cadixdev.lorenz.io.proguard.ProGuardReader; import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; @@ -23,7 +24,8 @@ public ProGuardMappingFormat() { } @Override - public @NonNull MappingSet read(final @NonNull Path file, final @NonNull MappingsEntry entry) throws IOException { + public @NonNull MappingSet read(final @NonNull Path file, final @NonNull MappingsEntry entry, + MinecraftResolver.Context context) throws IOException { final MappingSet scratchMappings = MappingSet.create(); try (ProGuardReader proguard = new ProGuardReader(Files.newBufferedReader(file))) { proguard.read(scratchMappings); diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java index 960c6de4..d93db900 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyMappingFormat.java @@ -2,12 +2,18 @@ import org.cadixdev.lorenz.MappingSet; import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.gradle.vanilla.internal.repository.ResolvableTool; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; import org.spongepowered.gradle.vanilla.repository.mappings.TinyMappingsEntry; import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URLClassLoader; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.concurrent.CompletableFuture; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -22,20 +28,35 @@ public TinyMappingFormat() { } @Override - public @NonNull MappingSet read(@NonNull Path file, @NonNull TinyMappingsEntry entry) throws IOException { + public @NonNull MappingSet read( + @NonNull Path file, + @NonNull TinyMappingsEntry entry, + MinecraftResolver.@NonNull Context context + ) throws IOException { boolean isTempFile = false; - if (file.getFileName().endsWith(".jar")) { + if (file.toString().endsWith(".jar")) { try (ZipFile zip = new ZipFile(file.toFile())) { ZipEntry zipEntry = zip.getEntry("mappings/mappings.tiny"); if (zipEntry != null) { - file = Files.createTempFile(null, null); - Files.copy(zip.getInputStream(zipEntry), file); + file = Files.createTempFile(file.getFileName().toString(), "mappings"); + Files.copy(zip.getInputStream(zipEntry), file, StandardCopyOption.REPLACE_EXISTING); isTempFile = true; } } } MappingSet mappings = MappingSet.create(); - net.fabricmc.lorenztiny.TinyMappingFormat.DETECT.read(mappings, file, entry.from().get(), entry.to().get()); + URLClassLoader classLoader = CompletableFuture.supplyAsync(() -> context.classLoaderWithTool(ResolvableTool.REMAP_TINY).get(), context.syncExecutor()).join(); + try { + Class readerClass = Class.forName( + "org.spongepowered.gradle.vanilla.internal.repository.mappings.TinyReaderImpl", + true, + classLoader + ); + Method readMethod = readerClass.getMethod("read", MappingSet.class, Path.class, String.class, String.class); + readMethod.invoke(null, mappings, file, entry.from().get(), entry.to().get()); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } if (isTempFile) { Files.delete(file); } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingFormat.java index d0656b99..ea9ee024 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingFormat.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingFormat.java @@ -3,6 +3,7 @@ import org.cadixdev.lorenz.MappingSet; import org.checkerframework.checker.nullness.qual.NonNull; import org.gradle.api.Named; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; import java.io.IOException; import java.nio.file.Path; @@ -18,7 +19,7 @@ public Class entryType() { return entryType; } - public abstract MappingSet read(final Path file, final T entry) throws IOException; + public abstract MappingSet read(final Path file, final T entry, MinecraftResolver.Context context) throws IOException; @Override public int hashCode() { diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java index 96e70c48..5016e11c 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java @@ -5,6 +5,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.gradle.api.Named; import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.FileCollectionDependency; import org.gradle.api.artifacts.ModuleDependency; @@ -25,6 +26,7 @@ import java.util.HashSet; import java.util.Random; import java.util.Set; +import java.util.concurrent.CompletableFuture; public class MappingsEntry implements Named { protected final Project project; @@ -149,12 +151,13 @@ protected MappingSet doResolve( if (!mappingFormat.entryType().isInstance(this)) { throw new IllegalStateException("Mappings entry \"" + getName() + "\" of type \"" + getClass().getName() + "\" is not compatible with mapping format \"" + format.get() + "\""); } - Set resolvedFiles = project.getConfigurations().getByName(configurationName).resolve(); + Configuration configuration = project.getConfigurations().getByName(configurationName); + Set resolvedFiles = CompletableFuture.supplyAsync(configuration::resolve, context.syncExecutor()).join(); if (resolvedFiles.size() != 1) { throw new IllegalStateException("Mappings entry \"" + getName() + "\" did not resolve to exactly 1 file"); } Path resolvedFile = resolvedFiles.iterator().next().toPath(); - return mappingFormat.read(resolvedFile, mappingFormat.entryType().cast(this)); + return mappingFormat.read(resolvedFile, mappingFormat.entryType().cast(this), context); } public String computeStateKey() { diff --git a/subprojects/gradle-plugin/src/main/templates/org/spongepowered/gradle/vanilla/internal/BuildVersions.java b/subprojects/gradle-plugin/src/main/templates/org/spongepowered/gradle/vanilla/internal/BuildVersions.java index 3b6172a9..4cef0abf 100644 --- a/subprojects/gradle-plugin/src/main/templates/org/spongepowered/gradle/vanilla/internal/BuildVersions.java +++ b/subprojects/gradle-plugin/src/main/templates/org/spongepowered/gradle/vanilla/internal/BuildVersions.java @@ -36,5 +36,7 @@ private BuildVersions() { public static final String FORGEFLOWER = "${forgeFlowerVersion}"; public static final String MERGE_TOOL = "${mergeToolVersion}"; public static final String ACCESS_WIDENER = "${accessWidenerVersion}"; + public static final String LORENZ_TINY_VERSION = "${lorenzTinyVersion}"; + public static final String MAPPING_IO_VERSION = "${mappingIoVersion}"; -} \ No newline at end of file +} diff --git a/subprojects/gradle-plugin/src/remapTiny/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyReaderImpl.java b/subprojects/gradle-plugin/src/remapTiny/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyReaderImpl.java new file mode 100644 index 00000000..0b6e07d4 --- /dev/null +++ b/subprojects/gradle-plugin/src/remapTiny/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TinyReaderImpl.java @@ -0,0 +1,13 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import net.fabricmc.lorenztiny.TinyMappingFormat; +import org.cadixdev.lorenz.MappingSet; + +import java.io.IOException; +import java.nio.file.Path; + +public class TinyReaderImpl { + public static void read(MappingSet mappings, Path file, String from, String to) throws IOException { + TinyMappingFormat.DETECT.read(mappings, file, from, to); + } +} From 4bab920b36af09c4b65ef0c86b5eac08c98bcb9b Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 5 Oct 2021 15:27:07 +0100 Subject: [PATCH 07/15] Parchment mappings format --- gradle.properties | 2 + subprojects/gradle-plugin/build.gradle.kts | 24 ++++++- .../gradle/vanilla/internal/Constants.java | 7 +- .../internal/MinecraftExtensionImpl.java | 2 + .../repository/MinecraftProviderService.java | 26 ++++++- .../internal/repository/ResolvableTool.java | 47 +++++++++++-- .../mappings/ParchmentMappingFormat.java | 65 +++++++++++++++++ .../vanilla/internal/BuildVersions.java | 5 +- .../mappings/ParchmentReaderImpl.java | 70 +++++++++++++++++++ 9 files changed, 236 insertions(+), 12 deletions(-) create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ParchmentMappingFormat.java create mode 100644 subprojects/gradle-plugin/src/remapParchment/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ParchmentReaderImpl.java diff --git a/gradle.properties b/gradle.properties index 72d6a561..1404826b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,7 @@ url=https://www.spongepowered.org organization=SpongePowered projectUrl=https://www.spongepowered.org +gsonVersion=2.8.7 accessWidenerVersion=1.0.2 asmVersion=9.2 checkerVersion=3.15.0 @@ -12,6 +13,7 @@ mergeToolVersion=1.1.4 lorenzVersion=0.5.7 lorenzTinyVersion=4.0.2 mappingIoVersion=0.2.1 +featherVersion=0.6.5.3-dev-SNAPSHOT org.gradle.parallel=true kotlin.stdlib.default.dependency=false diff --git a/subprojects/gradle-plugin/build.gradle.kts b/subprojects/gradle-plugin/build.gradle.kts index baae3bbf..49b5ece2 100644 --- a/subprojects/gradle-plugin/build.gradle.kts +++ b/subprojects/gradle-plugin/build.gradle.kts @@ -23,6 +23,9 @@ val accessWiden by sourceSets.creating { val remapTiny by sourceSets.creating { configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } } +val remapParchment by sourceSets.creating { + configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } +} val shadow by sourceSets.creating { configurations.named(this.implementationConfigurationName) { extendsFrom(commonDeps) } } @@ -31,6 +34,7 @@ configurations { api { extendsFrom(commonDeps) } } +val gsonVersion: String by project val accessWidenerVersion: String by project val asmVersion: String by project val forgeFlowerVersion: String by project @@ -39,6 +43,14 @@ val mergeToolVersion: String by project val lorenzVersion: String by project val lorenzTinyVersion: String by project val mappingIoVersion: String by project +val featherVersion: String by project + +repositories { + maven("https://maven.parchmentmc.org/") { + name = "ParchmentMC" + } +} + dependencies { // All source sets commonDeps(gradleApi()) @@ -50,7 +62,7 @@ dependencies { } // Just main - implementation("com.google.code.gson:gson:2.8.7") + implementation("com.google.code.gson:gson:$gsonVersion") implementation("org.cadixdev:lorenz:$lorenzVersion") implementation("org.cadixdev:lorenz-asm:$lorenzVersion") { exclude("org.ow2.asm") // Use our own ASM @@ -91,6 +103,12 @@ dependencies { } implementation(remapTiny.output) + "remapParchmentCompileOnly"("org.cadixdev:lorenz:$lorenzVersion") + "remapParchmentCompileOnly"("com.google.code.gson:gson:$gsonVersion") + "remapParchmentCompileOnly"("org.parchmentmc:feather:$featherVersion") + "remapParchmentCompileOnly"("org.parchmentmc.feather:io-gson:$featherVersion") + implementation(remapParchment.output) + "shadowCompileOnly"("com.github.jengelman.gradle.plugins:shadow:6.1.0") implementation(shadow.output) @@ -112,7 +130,8 @@ tasks { "mergeToolVersion" to mergeToolVersion, "accessWidenerVersion" to accessWidenerVersion, "lorenzTinyVersion" to lorenzTinyVersion, - "mappingIoVersion" to mappingIoVersion + "mappingIoVersion" to mappingIoVersion, + "featherVersion" to featherVersion ) inputs.properties(properties) @@ -140,6 +159,7 @@ tasks { from(jarDecompile.output) from(accessWiden.output) from(remapTiny.output) + from(remapParchment.output) from(shadow.output) } } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/Constants.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/Constants.java index acfc6ff3..267789ca 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/Constants.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/Constants.java @@ -103,8 +103,10 @@ public static final class WorkerDependencies { public static final String MERGE_TOOL = "net.minecraftforge:mergetool:" + BuildVersions.MERGE_TOOL; public static final String ACCESS_WIDENER = "net.fabricmc:access-widener:" + BuildVersions.ACCESS_WIDENER; public static final String FORGE_FLOWER = "net.minecraftforge:forgeflower:" + BuildVersions.FORGEFLOWER; - public static final String LORENZ_TINY = "net.fabricmc:lorenz-tiny:" + BuildVersions.LORENZ_TINY_VERSION; - public static final String MAPPING_IO = "net.fabricmc:mapping-io:" + BuildVersions.MAPPING_IO_VERSION; + public static final String LORENZ_TINY = "net.fabricmc:lorenz-tiny:" + BuildVersions.LORENZ_TINY; + public static final String MAPPING_IO = "net.fabricmc:mapping-io:" + BuildVersions.MAPPING_IO; + public static final String FEATHER = "org.parchmentmc:feather:" + BuildVersions.FEATHER; + public static final String FEATHER_IO_GSON = "org.parchmentmc.feather:io-gson:" + BuildVersions.FEATHER; public static final String FORCED_ASM = BuildVersions.ASM; public static final String ASM_UTIL = "org.ow2.asm:asm-util:" + WorkerDependencies.FORCED_ASM; @@ -138,6 +140,7 @@ public static final class Configurations { public static final String MERGETOOL = "mergetool"; public static final String ACCESS_WIDENER = "accessWidener"; public static final String REMAP_TINY = "remapTiny"; + public static final String REMAP_PARCHMENT = "remapParchment"; public static final String FORGE_FLOWER = "forgeFlower"; public static final String CLASS_DUMP = "classDump"; diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java index b916e0cc..5c4c4b89 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java @@ -43,6 +43,7 @@ import org.spongepowered.gradle.vanilla.internal.model.VersionClassifier; import org.spongepowered.gradle.vanilla.internal.model.VersionDescriptor; import org.spongepowered.gradle.vanilla.internal.repository.mappings.OfficialMappingsEntry; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.ParchmentMappingFormat; import org.spongepowered.gradle.vanilla.internal.repository.mappings.ProGuardMappingFormat; import org.spongepowered.gradle.vanilla.internal.repository.mappings.TinyMappingFormat; import org.spongepowered.gradle.vanilla.internal.repository.modifier.MappingsModifier; @@ -109,6 +110,7 @@ public MinecraftExtensionImpl(final Gradle gradle, final ObjectFactory factory, this.mappingFormats.add(new ProGuardMappingFormat()); this.mappingFormats.add(new TinyMappingFormat()); + this.mappingFormats.add(new ParchmentMappingFormat()); this.mappings.add(new OfficialMappingsEntry(project, this)); diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftProviderService.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftProviderService.java index 90629a62..dcac9a9d 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftProviderService.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftProviderService.java @@ -29,6 +29,7 @@ import org.gradle.api.GradleException; import org.gradle.api.Project; import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.artifacts.ResolveException; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.provider.Property; import org.gradle.api.services.BuildService; @@ -45,14 +46,19 @@ import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; import org.spongepowered.gradle.vanilla.repository.MinecraftResolverImpl; +import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Path; +import java.util.Arrays; import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; public abstract class MinecraftProviderService implements BuildService, @@ -99,6 +105,7 @@ public void onFinish(final FinishEvent finishEvent) { */ public void primeResolver(final Project project, final List modifiers) { final ResolverState state = this.activeState.get(); + state.logger = project.getLogger(); state.configurationSource = project.getConfigurations(); state.modifiers = modifiers; } @@ -169,7 +176,23 @@ private URL[] resolveTool(final ResolvableTool tool) { if (configurations == null) { throw new IllegalArgumentException("Tried to perform a configuration resolution outside of a project-managed context!"); } - return configurations.getByName(tool.id()).resolve().stream() + Set resolvedFiles; + try { + resolvedFiles = configurations.getByName(tool.id()).resolve(); + } catch (ResolveException e) { + String repoHelpStr = Arrays.stream(tool.dependencies()) + .map(ResolvableTool.Dependency::repo) + .filter(Objects::nonNull) + .distinct() + .map(ResolvableTool.Repository::url) + .collect(Collectors.joining(", ")); + if (!repoHelpStr.isEmpty()) { + String helpStr = String.format("Help: this tool requires the following repositories to be declared in the repositories {} block: %s", repoHelpStr); + throw new ResolvableTool.MissingToolException(helpStr, e); + } + throw new ResolvableTool.MissingToolException(e.toString(), e); + } + return resolvedFiles.stream() .map(file -> { try { return file.toURI().toURL(); @@ -221,6 +244,7 @@ public void close() throws IOException { static final class ResolverState { + org.gradle.api.logging.@MonotonicNonNull Logger logger; @MonotonicNonNull ConfigurationContainer configurationSource; @Nullable List modifiers; diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java index 148a87bc..c31c0c01 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java @@ -24,6 +24,7 @@ */ package org.spongepowered.gradle.vanilla.internal.repository; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.gradle.vanilla.internal.Constants; import java.util.Arrays; @@ -34,14 +35,15 @@ public enum ResolvableTool { JAR_MERGE(Constants.Configurations.MERGETOOL, Constants.WorkerDependencies.MERGE_TOOL), ACCESS_WIDENER(Constants.Configurations.ACCESS_WIDENER, Constants.WorkerDependencies.ACCESS_WIDENER), - REMAP_TINY(Constants.Configurations.REMAP_TINY, new Dependency(Constants.WorkerDependencies.LORENZ_TINY, false), new Dependency(Constants.WorkerDependencies.MAPPING_IO, true)), + REMAP_TINY(Constants.Configurations.REMAP_TINY, new Dependency(Constants.WorkerDependencies.LORENZ_TINY).setNonTransitive(), new Dependency(Constants.WorkerDependencies.MAPPING_IO)), + REMAP_PARCHMENT(Constants.Configurations.REMAP_PARCHMENT, new Dependency(Constants.WorkerDependencies.FEATHER).setRepo(Repository.PARCHMENT), new Dependency(Constants.WorkerDependencies.FEATHER_IO_GSON).setRepo(Repository.PARCHMENT)), ; private final String id; private final Dependency[] dependencies; ResolvableTool(final String id, final String... notations) { - this(id, Arrays.stream(notations).map(notation -> new Dependency(notation, true)).toArray(Dependency[]::new)); + this(id, Arrays.stream(notations).map(Dependency::new).toArray(Dependency[]::new)); } ResolvableTool(final String id, final Dependency... dependencies) { @@ -57,21 +59,56 @@ public Dependency[] dependencies() { return this.dependencies; } + public enum Repository { + PARCHMENT("https://maven.parchmentmc.org/"), + ; + + private final String url; + + Repository(String url) { + this.url = url; + } + + public String url() { + return url; + } + } + public static class Dependency { private final String notation; - private final boolean isTransitive; + private @Nullable Repository repo = null; + private boolean isTransitive = true; - public Dependency(final String notation, final boolean isTransitive) { + public Dependency(final String notation) { this.notation = notation; - this.isTransitive = isTransitive; + } + + public Dependency setNonTransitive() { + this.isTransitive = false; + return this; + } + + public Dependency setRepo(Repository repo) { + this.repo = repo; + return this; } public String notation() { return notation; } + public Repository repo() { + return repo; + } + public boolean isTransitive() { return isTransitive; } } + + public static class MissingToolException extends RuntimeException { + public MissingToolException(String message, Throwable cause) { + super(message, cause); + } + } } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ParchmentMappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ParchmentMappingFormat.java new file mode 100644 index 00000000..adb41451 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ParchmentMappingFormat.java @@ -0,0 +1,65 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.gradle.vanilla.internal.repository.ResolvableTool; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.concurrent.CompletableFuture; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class ParchmentMappingFormat extends MappingFormat<@NonNull MappingsEntry> { + public ParchmentMappingFormat() { + super(MappingsEntry.class); + } + + @Override + public @NonNull String getName() { + return "parchment"; + } + + @Override + public @NonNull MappingSet read( + @NonNull Path file, + @NonNull MappingsEntry entry, + MinecraftResolver.@NonNull Context context + ) throws IOException { + boolean isTempFile = false; + if (file.toString().endsWith(".zip")) { + try (ZipFile zip = new ZipFile(file.toFile())) { + ZipEntry zipEntry = zip.getEntry("parchment.json"); + if (zipEntry != null) { + file = Files.createTempFile(file.getFileName().toString(), "mappings"); + Files.copy(zip.getInputStream(zipEntry), file, StandardCopyOption.REPLACE_EXISTING); + isTempFile = true; + } + } + } + MappingSet mappings = MappingSet.create(); + URLClassLoader classLoader = CompletableFuture.supplyAsync(() -> context.classLoaderWithTool(ResolvableTool.REMAP_PARCHMENT).get(), context.syncExecutor()).join(); + try { + Class readerClass = Class.forName( + "org.spongepowered.gradle.vanilla.internal.repository.mappings.ParchmentReaderImpl", + true, + classLoader + ); + Method readMethod = readerClass.getMethod("read", MappingSet.class, Path.class); + readMethod.invoke(null, mappings, file); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + if (isTempFile) { + Files.delete(file); + } + return mappings; + } +} diff --git a/subprojects/gradle-plugin/src/main/templates/org/spongepowered/gradle/vanilla/internal/BuildVersions.java b/subprojects/gradle-plugin/src/main/templates/org/spongepowered/gradle/vanilla/internal/BuildVersions.java index 4cef0abf..a4ea2bbc 100644 --- a/subprojects/gradle-plugin/src/main/templates/org/spongepowered/gradle/vanilla/internal/BuildVersions.java +++ b/subprojects/gradle-plugin/src/main/templates/org/spongepowered/gradle/vanilla/internal/BuildVersions.java @@ -36,7 +36,8 @@ private BuildVersions() { public static final String FORGEFLOWER = "${forgeFlowerVersion}"; public static final String MERGE_TOOL = "${mergeToolVersion}"; public static final String ACCESS_WIDENER = "${accessWidenerVersion}"; - public static final String LORENZ_TINY_VERSION = "${lorenzTinyVersion}"; - public static final String MAPPING_IO_VERSION = "${mappingIoVersion}"; + public static final String LORENZ_TINY = "${lorenzTinyVersion}"; + public static final String MAPPING_IO = "${mappingIoVersion}"; + public static final String FEATHER = "${featherVersion}"; } diff --git a/subprojects/gradle-plugin/src/remapParchment/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ParchmentReaderImpl.java b/subprojects/gradle-plugin/src/remapParchment/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ParchmentReaderImpl.java new file mode 100644 index 00000000..49140300 --- /dev/null +++ b/subprojects/gradle-plugin/src/remapParchment/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ParchmentReaderImpl.java @@ -0,0 +1,70 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.cadixdev.lorenz.MappingSet; +import org.cadixdev.lorenz.model.ClassMapping; +import org.cadixdev.lorenz.model.ExtensionKey; +import org.cadixdev.lorenz.model.FieldMapping; +import org.cadixdev.lorenz.model.MethodMapping; +import org.cadixdev.lorenz.model.MethodParameterMapping; +import org.parchmentmc.feather.io.gson.MDCGsonAdapterFactory; +import org.parchmentmc.feather.io.gson.OffsetDateTimeAdapter; +import org.parchmentmc.feather.io.gson.SimpleVersionAdapter; +import org.parchmentmc.feather.io.gson.metadata.MetadataAdapterFactory; +import org.parchmentmc.feather.mapping.MappingDataContainer; +import org.parchmentmc.feather.mapping.VersionedMappingDataContainer; +import org.parchmentmc.feather.util.SimpleVersion; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.OffsetDateTime; +import java.util.Collections; +import java.util.List; + +public class ParchmentReaderImpl { + @SuppressWarnings("unchecked") + private static final ExtensionKey> JAVADOC_EXTENSION = new ExtensionKey<>((Class>) (Class) List.class, "javadoc"); + private static final Gson GSON = new GsonBuilder() + // Required for `MappingDataContainer` and inner data classes + .registerTypeAdapterFactory(new MDCGsonAdapterFactory()) + // Required for `MappingDataContainer`s and `SourceMetadata` + .registerTypeAdapter(SimpleVersion.class, new SimpleVersionAdapter()) + // Required for the metadata classes (`SourceMetadata`, `MethodReference`, etc.) and `Named` + .registerTypeAdapterFactory(new MetadataAdapterFactory()) + // Required for parsing manifests: `LauncherManifest`, `VersionManifest`, and their inner data classes + .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeAdapter()) + .create(); + + public static void read(MappingSet output, Path file) throws IOException { + final MappingDataContainer parchmentData; + try (BufferedReader reader = Files.newBufferedReader(file)) { + parchmentData = GSON.fromJson(reader, VersionedMappingDataContainer.class); + } + for (final MappingDataContainer.ClassData parchmentClassMapping : parchmentData.getClasses()) { + final ClassMapping classMapping = output.getOrCreateClassMapping(parchmentClassMapping.getName()); + classMapping.set(JAVADOC_EXTENSION, parchmentClassMapping.getJavadoc()); + + for (final MappingDataContainer.FieldData field : parchmentClassMapping.getFields()) { + final FieldMapping fieldMapping = classMapping.getOrCreateFieldMapping(field.getName(), field.getDescriptor()); + fieldMapping.set(JAVADOC_EXTENSION, field.getJavadoc()); + } + + for (final MappingDataContainer.MethodData method : parchmentClassMapping.getMethods()) { + final MethodMapping methodMapping = classMapping.getOrCreateMethodMapping(method.getName(), method.getDescriptor()); + methodMapping.set(JAVADOC_EXTENSION, method.getJavadoc()); + for (final MappingDataContainer.ParameterData parameter : method.getParameters()) { + final MethodParameterMapping parameterMapping = methodMapping.getOrCreateParameterMapping(parameter.getIndex()); + if (parameter.getName() != null) { + parameterMapping.setDeobfuscatedName(parameter.getName()); + } + if (parameter.getJavadoc() != null) { + parameterMapping.set(JAVADOC_EXTENSION, Collections.singletonList(parameter.getJavadoc())); + } + } + } + } + } +} From a92d2d4097b14816db64cc4c16f720fdfa7b4976 Mon Sep 17 00:00:00 2001 From: Joe Date: Fri, 8 Oct 2021 17:15:20 +0100 Subject: [PATCH 08/15] Remove parchment repo, sponge now mirrors it --- subprojects/gradle-plugin/build.gradle.kts | 6 ------ .../gradle/vanilla/internal/repository/ResolvableTool.java | 3 +-- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/subprojects/gradle-plugin/build.gradle.kts b/subprojects/gradle-plugin/build.gradle.kts index 49b5ece2..2e189d00 100644 --- a/subprojects/gradle-plugin/build.gradle.kts +++ b/subprojects/gradle-plugin/build.gradle.kts @@ -45,12 +45,6 @@ val lorenzTinyVersion: String by project val mappingIoVersion: String by project val featherVersion: String by project -repositories { - maven("https://maven.parchmentmc.org/") { - name = "ParchmentMC" - } -} - dependencies { // All source sets commonDeps(gradleApi()) diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java index c31c0c01..cdef19c9 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/ResolvableTool.java @@ -36,7 +36,7 @@ public enum ResolvableTool { JAR_MERGE(Constants.Configurations.MERGETOOL, Constants.WorkerDependencies.MERGE_TOOL), ACCESS_WIDENER(Constants.Configurations.ACCESS_WIDENER, Constants.WorkerDependencies.ACCESS_WIDENER), REMAP_TINY(Constants.Configurations.REMAP_TINY, new Dependency(Constants.WorkerDependencies.LORENZ_TINY).setNonTransitive(), new Dependency(Constants.WorkerDependencies.MAPPING_IO)), - REMAP_PARCHMENT(Constants.Configurations.REMAP_PARCHMENT, new Dependency(Constants.WorkerDependencies.FEATHER).setRepo(Repository.PARCHMENT), new Dependency(Constants.WorkerDependencies.FEATHER_IO_GSON).setRepo(Repository.PARCHMENT)), + REMAP_PARCHMENT(Constants.Configurations.REMAP_PARCHMENT, Constants.WorkerDependencies.FEATHER, Constants.WorkerDependencies.FEATHER_IO_GSON), ; private final String id; @@ -60,7 +60,6 @@ public Dependency[] dependencies() { } public enum Repository { - PARCHMENT("https://maven.parchmentmc.org/"), ; private final String url; From 460537571da70e5078bd0c5706191633c6f126bb Mon Sep 17 00:00:00 2001 From: Joe Date: Fri, 8 Oct 2021 17:49:12 +0100 Subject: [PATCH 09/15] Add support for srg, tsrg, csrg and xsrg, add builtin obf mappings --- .../gradle/vanilla/MinecraftExtension.java | 2 - .../internal/MinecraftExtensionImpl.java | 19 +++++---- .../mappings/CSrgMappingFormat.java | 30 ++++++++++++++ .../mappings/ImmutableMappingsEntry.java | 41 +++++++++++++++++++ .../repository/mappings/ObfMappingsEntry.java | 31 ++++++++++++++ .../mappings/OfficialMappingsEntry.java | 32 +-------------- .../repository/mappings/SrgMappingFormat.java | 30 ++++++++++++++ .../mappings/TSrgMappingFormat.java | 30 ++++++++++++++ .../mappings/XSrgMappingFormat.java | 30 ++++++++++++++ 9 files changed, 205 insertions(+), 40 deletions(-) create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/CSrgMappingFormat.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ImmutableMappingsEntry.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ObfMappingsEntry.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/SrgMappingFormat.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TSrgMappingFormat.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/XSrgMappingFormat.java diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java index 1e31dbcf..b6b4ae50 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/MinecraftExtension.java @@ -137,8 +137,6 @@ public interface MinecraftExtension extends MinecraftRepositoryExtension { void minecraftMappings(String mappings); - void noMinecraftMappings(); - /** * Get run configurations configured for this project. * diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java index 5c4c4b89..90ae80be 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java @@ -42,10 +42,15 @@ import org.spongepowered.gradle.vanilla.MinecraftExtension; import org.spongepowered.gradle.vanilla.internal.model.VersionClassifier; import org.spongepowered.gradle.vanilla.internal.model.VersionDescriptor; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.CSrgMappingFormat; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.ObfMappingsEntry; import org.spongepowered.gradle.vanilla.internal.repository.mappings.OfficialMappingsEntry; import org.spongepowered.gradle.vanilla.internal.repository.mappings.ParchmentMappingFormat; import org.spongepowered.gradle.vanilla.internal.repository.mappings.ProGuardMappingFormat; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.SrgMappingFormat; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.TSrgMappingFormat; import org.spongepowered.gradle.vanilla.internal.repository.mappings.TinyMappingFormat; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.XSrgMappingFormat; import org.spongepowered.gradle.vanilla.internal.repository.modifier.MappingsModifier; import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; import org.spongepowered.gradle.vanilla.repository.mappings.MappingsContainer; @@ -80,7 +85,6 @@ public class MinecraftExtensionImpl implements MinecraftExtension { private final PolymorphicDomainObjectContainer> mappingFormats; private final MappingsContainer mappings; private final Property minecraftMappings; - private final Property noMinecraftMappings; private final DirectoryProperty sharedCache; private final DirectoryProperty projectCache; private final ConfigurableFileCollection accessWideners; @@ -105,12 +109,16 @@ public MinecraftExtensionImpl(final Gradle gradle, final ObjectFactory factory, this.mappingFormats = factory.polymorphicDomainObjectContainer((Class>) (Class) MappingFormat.class); this.mappings = new MappingsContainer(project, this); this.minecraftMappings = factory.property(String.class).convention(OfficialMappingsEntry.NAME); - this.noMinecraftMappings = factory.property(Boolean.class).convention(false); this.accessWideners = factory.fileCollection(); this.mappingFormats.add(new ProGuardMappingFormat()); this.mappingFormats.add(new TinyMappingFormat()); this.mappingFormats.add(new ParchmentMappingFormat()); + this.mappingFormats.add(new SrgMappingFormat()); + this.mappingFormats.add(new TSrgMappingFormat()); + this.mappingFormats.add(new CSrgMappingFormat()); + this.mappingFormats.add(new XSrgMappingFormat()); + this.mappings.add(new ObfMappingsEntry(project, this)); this.mappings.add(new OfficialMappingsEntry(project, this)); @@ -298,16 +306,11 @@ public void minecraftMappings(String mappings) { this.minecraftMappings.set(mappings); } - @Override - public void noMinecraftMappings() { - this.noMinecraftMappings.set(true); - } - public synchronized List modifiers() { if (this.lazyModifiers == null) { final List modifiers = new ArrayList<>(); - if (!noMinecraftMappings.get()) { + if (!minecraftMappings.get().equals(ObfMappingsEntry.NAME)) { modifiers.add(new MappingsModifier(mappings.getByName(minecraftMappings.get()))); } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/CSrgMappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/CSrgMappingFormat.java new file mode 100644 index 00000000..8621ecd4 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/CSrgMappingFormat.java @@ -0,0 +1,30 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; + +import java.io.IOException; +import java.nio.file.Path; + +public class CSrgMappingFormat extends MappingFormat<@NonNull MappingsEntry> { + public CSrgMappingFormat() { + super(MappingsEntry.class); + } + + @Override + public @NonNull String getName() { + return "csrg"; + } + + @Override + public @NonNull MappingSet read( + @NonNull Path file, + @NonNull MappingsEntry entry, + MinecraftResolver.@NonNull Context context + ) throws IOException { + return new org.cadixdev.lorenz.io.srg.csrg.CSrgMappingFormat().read(file); + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ImmutableMappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ImmutableMappingsEntry.java new file mode 100644 index 00000000..715b8c53 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ImmutableMappingsEntry.java @@ -0,0 +1,41 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.gradle.api.Project; +import org.spongepowered.gradle.vanilla.MinecraftExtension; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; + +public abstract class ImmutableMappingsEntry extends MappingsEntry { + private boolean hasInitialized = false; + + public ImmutableMappingsEntry(Project project, MinecraftExtension extension, String name, String format) { + super(project, extension, name); + format(format); + hasInitialized = true; + } + + @Override + public void format(@NonNull String format) { + if (hasInitialized) { + throw new IllegalStateException("Cannot modify the format of \"" + getName() + "\""); + } else { + super.format(format); + } + } + + @Override + public void dependency(@Nullable Object dependencyNotation) { + throw new IllegalStateException("Cannot modify the dependency of \"" + getName() + "\""); + } + + @Override + public void parent(@Nullable String parent) { + throw new IllegalStateException("Cannot modify the parent of \"" + getName() + "\""); + } + + @Override + public void inverse(boolean isInverse) { + throw new IllegalStateException("Cannot invert \"" + getName() + "\""); + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ObfMappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ObfMappingsEntry.java new file mode 100644 index 00000000..aa2d02bf --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ObfMappingsEntry.java @@ -0,0 +1,31 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.gradle.api.Project; +import org.spongepowered.gradle.vanilla.MinecraftExtension; +import org.spongepowered.gradle.vanilla.internal.repository.modifier.ArtifactModifier; +import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; + +import java.util.Set; + +public class ObfMappingsEntry extends ImmutableMappingsEntry { + public static final String NAME = "obf"; + + public ObfMappingsEntry(Project project, MinecraftExtension extension) { + super(project, extension, NAME, ProGuardMappingFormat.NAME); + } + + @Override + protected @NonNull MappingSet doResolve( + MinecraftResolver.@NonNull Context context, + MinecraftResolver.@NonNull MinecraftEnvironment environment, + @NonNull MinecraftPlatform platform, + ArtifactModifier.@NonNull SharedArtifactSupplier sharedArtifactSupplier, + @NonNull Set alreadySeen + ) { + return MappingSet.create(); + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java index a932d163..b6d8532d 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java @@ -3,7 +3,6 @@ import org.cadixdev.lorenz.MappingSet; import org.cadixdev.lorenz.io.proguard.ProGuardReader; import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; import org.gradle.api.Project; import org.spongepowered.gradle.vanilla.MinecraftExtension; import org.spongepowered.gradle.vanilla.internal.model.Download; @@ -21,38 +20,11 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; -public class OfficialMappingsEntry extends MappingsEntry { +public class OfficialMappingsEntry extends ImmutableMappingsEntry { public static final String NAME = "official"; - private boolean hasInitialized = false; public OfficialMappingsEntry(Project project, MinecraftExtension extension) { - super(project, extension, NAME); - format(ProGuardMappingFormat.NAME); - hasInitialized = true; - } - - @Override - public void format(@NonNull String format) { - if (hasInitialized) { - throw new IllegalStateException("Cannot modify the format of \"" + NAME + "\""); - } else { - super.format(format); - } - } - - @Override - public void dependency(@Nullable Object dependencyNotation) { - throw new IllegalStateException("Cannot modify the dependency of \"" + NAME + "\""); - } - - @Override - public void parent(@Nullable String parent) { - throw new IllegalStateException("Cannot modify the parent of \"" + NAME + "\""); - } - - @Override - public void inverse(boolean isInverse) { - throw new IllegalStateException("Cannot invert \"" + NAME + "\""); + super(project, extension, NAME, ProGuardMappingFormat.NAME); } @Override diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/SrgMappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/SrgMappingFormat.java new file mode 100644 index 00000000..0ced40af --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/SrgMappingFormat.java @@ -0,0 +1,30 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; + +import java.io.IOException; +import java.nio.file.Path; + +public class SrgMappingFormat extends MappingFormat<@NonNull MappingsEntry> { + public SrgMappingFormat() { + super(MappingsEntry.class); + } + + @Override + public @NonNull String getName() { + return "srg"; + } + + @Override + public @NonNull MappingSet read( + @NonNull Path file, + @NonNull MappingsEntry entry, + MinecraftResolver.@NonNull Context context + ) throws IOException { + return new org.cadixdev.lorenz.io.srg.SrgMappingFormat().read(file); + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TSrgMappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TSrgMappingFormat.java new file mode 100644 index 00000000..10de6300 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/TSrgMappingFormat.java @@ -0,0 +1,30 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; + +import java.io.IOException; +import java.nio.file.Path; + +public class TSrgMappingFormat extends MappingFormat<@NonNull MappingsEntry> { + public TSrgMappingFormat() { + super(MappingsEntry.class); + } + + @Override + public @NonNull String getName() { + return "tsrg"; + } + + @Override + public @NonNull MappingSet read( + @NonNull Path file, + @NonNull MappingsEntry entry, + MinecraftResolver.@NonNull Context context + ) throws IOException { + return new org.cadixdev.lorenz.io.srg.tsrg.TSrgMappingFormat().read(file); + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/XSrgMappingFormat.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/XSrgMappingFormat.java new file mode 100644 index 00000000..86853399 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/XSrgMappingFormat.java @@ -0,0 +1,30 @@ +package org.spongepowered.gradle.vanilla.internal.repository.mappings; + +import org.cadixdev.lorenz.MappingSet; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingFormat; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; + +import java.io.IOException; +import java.nio.file.Path; + +public class XSrgMappingFormat extends MappingFormat<@NonNull MappingsEntry> { + public XSrgMappingFormat() { + super(MappingsEntry.class); + } + + @Override + public @NonNull String getName() { + return "xsrg"; + } + + @Override + public @NonNull MappingSet read( + @NonNull Path file, + @NonNull MappingsEntry entry, + MinecraftResolver.@NonNull Context context + ) throws IOException { + return new org.cadixdev.lorenz.io.srg.xsrg.XSrgMappingFormat().read(file); + } +} From ddcbe80102401131664bd7b1531c3314d9f7d2c5 Mon Sep 17 00:00:00 2001 From: Joe Date: Fri, 8 Oct 2021 20:39:57 +0100 Subject: [PATCH 10/15] Detached configuration, caching --- subprojects/gradle-plugin/build.gradle.kts | 6 ++ .../internal/MinecraftExtensionImpl.java | 2 +- .../repository/mappings/ObfMappingsEntry.java | 5 ++ .../mappings/OfficialMappingsEntry.java | 4 +- .../repository/modifier/MappingsModifier.java | 18 +++-- .../repository/mappings/MappingsEntry.java | 79 +++++++++++++------ 6 files changed, 81 insertions(+), 33 deletions(-) diff --git a/subprojects/gradle-plugin/build.gradle.kts b/subprojects/gradle-plugin/build.gradle.kts index 2e189d00..49b5ece2 100644 --- a/subprojects/gradle-plugin/build.gradle.kts +++ b/subprojects/gradle-plugin/build.gradle.kts @@ -45,6 +45,12 @@ val lorenzTinyVersion: String by project val mappingIoVersion: String by project val featherVersion: String by project +repositories { + maven("https://maven.parchmentmc.org/") { + name = "ParchmentMC" + } +} + dependencies { // All source sets commonDeps(gradleApi()) diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java index 90ae80be..fa247fc2 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/MinecraftExtensionImpl.java @@ -311,7 +311,7 @@ public synchronized List modifiers() { final List modifiers = new ArrayList<>(); if (!minecraftMappings.get().equals(ObfMappingsEntry.NAME)) { - modifiers.add(new MappingsModifier(mappings.getByName(minecraftMappings.get()))); + modifiers.add(new MappingsModifier(mappings, ObfMappingsEntry.NAME, minecraftMappings.get())); } this.accessWideners.disallowChanges(); diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ObfMappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ObfMappingsEntry.java index aa2d02bf..6f11fe22 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ObfMappingsEntry.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/ObfMappingsEntry.java @@ -18,6 +18,11 @@ public ObfMappingsEntry(Project project, MinecraftExtension extension) { super(project, extension, NAME, ProGuardMappingFormat.NAME); } + @Override + public @NonNull String computeStateKey(boolean isFrom) { + return isFrom ? "" : super.computeStateKey(false); + } + @Override protected @NonNull MappingSet doResolve( MinecraftResolver.@NonNull Context context, diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java index b6d8532d..2f9082ed 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/mappings/OfficialMappingsEntry.java @@ -64,7 +64,7 @@ public OfficialMappingsEntry(Project project, MinecraftExtension extension) { } @Override - public @NonNull String computeStateKey() { - return ""; + public @NonNull String computeStateKey(boolean isFrom) { + return isFrom ? super.computeStateKey(true) : ""; } } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java index 350b7f06..05097f13 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/modifier/MappingsModifier.java @@ -5,7 +5,7 @@ import org.spongepowered.gradle.vanilla.internal.resolver.AsyncUtils; import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; -import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsContainer; import java.io.IOException; import java.io.UncheckedIOException; @@ -14,11 +14,15 @@ public class MappingsModifier implements ArtifactModifier { private static final String KEY = "map"; // custom mapped - private final MappingsEntry mappings; + private final MappingsContainer mappings; + private final String from; + private final String to; private @Nullable String stateKey; - public MappingsModifier(final MappingsEntry mappings) { + public MappingsModifier(final MappingsContainer mappings, final String from, final String to) { this.mappings = mappings; + this.from = from; + this.to = to; } @Override @@ -29,7 +33,11 @@ public String key() { @Override public String stateKey() { if (stateKey == null) { - return this.stateKey = mappings.computeStateKey(); + this.stateKey = mappings.getByName(from).computeStateKey(true); + if (!this.stateKey.isEmpty()) { + this.stateKey += "-"; + } + this.stateKey += mappings.getByName(to).computeStateKey(false); } return stateKey; } @@ -39,7 +47,7 @@ public CompletableFuture providePopulator(MinecraftResolver.Cont return AsyncUtils.failableFuture(() -> (atlasContext, result, side, sharedArtifactProvider) -> { final MappingSet mappings; try { - mappings = this.mappings.resolve(context, result, side, sharedArtifactProvider); + mappings = this.mappings.getByName(to).convertFrom(from, context, result, side, sharedArtifactProvider); } catch (IOException e) { throw new UncheckedIOException("An exception occurred while trying to read mappings", e); } diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java index 5016e11c..cd8eae29 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/mappings/MappingsEntry.java @@ -11,6 +11,7 @@ import org.gradle.api.artifacts.ModuleDependency; import org.gradle.api.provider.Property; import org.spongepowered.gradle.vanilla.MinecraftExtension; +import org.spongepowered.gradle.vanilla.internal.repository.mappings.ObfMappingsEntry; import org.spongepowered.gradle.vanilla.internal.repository.modifier.ArtifactModifier; import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform; import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; @@ -20,31 +21,33 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.ref.SoftReference; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.security.MessageDigest; import java.util.HashSet; +import java.util.Map; import java.util.Random; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; public class MappingsEntry implements Named { protected final Project project; protected final MinecraftExtension extension; private final String name; private final Property format; - private final String configurationName; - private @Nullable Object dependency; - private @Nullable Dependency dependencyObj; + private @Nullable Configuration configuration; + private @Nullable Dependency dependency; private final Property parent; private final Property inverse; + private final Map> convertFromCache = new ConcurrentHashMap<>(); public MappingsEntry(Project project, MinecraftExtension extension, String name) { this.project = project; this.extension = extension; this.name = name; this.format = project.getObjects().property(String.class); - this.configurationName = name + "Mappings"; this.parent = project.getObjects().property(String.class); this.inverse = project.getObjects().property(Boolean.class).convention(false); } @@ -71,13 +74,8 @@ public void dependency(Object dependencyNotation) { if (this.dependency != null) { throw new IllegalStateException("MappingsEntry.dependency(Object) called twice"); } - project.getConfigurations().register(configurationName, config -> { - config.setVisible(false); - config.setCanBeConsumed(false); - config.setCanBeResolved(true); - }); - this.dependencyObj = project.getDependencies().add(configurationName, dependencyNotation); - this.dependency = dependencyNotation; + this.dependency = project.getDependencies().create(dependencyNotation); + this.configuration = project.getConfigurations().detachedConfiguration(this.dependency); } public Property<@Nullable String> parent() { @@ -100,15 +98,46 @@ public void inverse(boolean isInverse) { inverse.set(isInverse); } + @Override public int hashCode() { return name.hashCode(); } + @Override public boolean equals(Object other) { return other instanceof MappingsEntry && ((MappingsEntry) other).name.equals(this.name); } - public final MappingSet resolve( + public final MappingSet convertFrom( + String otherMappingsName, + MinecraftResolver.Context context, + MinecraftResolver.MinecraftEnvironment environment, + MinecraftPlatform platform, + ArtifactModifier.SharedArtifactSupplier sharedArtifactSupplier + ) throws IOException { + SoftReference ref = convertFromCache.get(otherMappingsName); + if (ref != null) { + @Nullable MappingSet entry = ref.get(); + if (entry != null) { + return entry; + } + } + + MappingSet resolved; + if (otherMappingsName.equals(getName())) { + resolved = MappingSet.create(); + } else if (otherMappingsName.equals(ObfMappingsEntry.NAME)) { + resolved = resolve(context, environment, platform, sharedArtifactSupplier); + } else { + MappingsEntry otherMappings = extension.getMappings().getByName(otherMappingsName); + resolved = otherMappings.resolve(context, environment, platform, sharedArtifactSupplier) + .reverse().merge(resolve(context, environment, platform, sharedArtifactSupplier)); + } + convertFromCache.put(otherMappingsName, new SoftReference<>(resolved)); + return resolved; + } + + private MappingSet resolve( MinecraftResolver.Context context, MinecraftResolver.MinecraftEnvironment environment, MinecraftPlatform platform, @@ -143,16 +172,16 @@ protected MappingSet doResolve( MinecraftPlatform platform, ArtifactModifier.SharedArtifactSupplier sharedArtifactSupplier, Set alreadySeen) throws IOException { - if (dependency == null) { + if (this.dependency == null) { throw new IllegalStateException("Mappings entry \"" + getName() + "\" of format \"" + format.get() + "\" must have a dependency"); } + assert this.configuration != null; @SuppressWarnings("unchecked") MappingFormat mappingFormat = (MappingFormat) extension.getMappingFormats().getByName(format.get()); if (!mappingFormat.entryType().isInstance(this)) { throw new IllegalStateException("Mappings entry \"" + getName() + "\" of type \"" + getClass().getName() + "\" is not compatible with mapping format \"" + format.get() + "\""); } - Configuration configuration = project.getConfigurations().getByName(configurationName); - Set resolvedFiles = CompletableFuture.supplyAsync(configuration::resolve, context.syncExecutor()).join(); + Set resolvedFiles = CompletableFuture.supplyAsync(this.configuration::resolve, context.syncExecutor()).join(); if (resolvedFiles.size() != 1) { throw new IllegalStateException("Mappings entry \"" + getName() + "\" did not resolve to exactly 1 file"); } @@ -160,7 +189,7 @@ protected MappingSet doResolve( return mappingFormat.read(resolvedFile, mappingFormat.entryType().cast(this), context); } - public String computeStateKey() { + public String computeStateKey(boolean isFrom) { final MessageDigest digest = HashAlgorithm.SHA1.digest(); computeHash(digest); return HashAlgorithm.toHexString(digest.digest()); @@ -171,18 +200,18 @@ protected void computeHash(MessageDigest digest) { digest.update(getName().getBytes(StandardCharsets.UTF_8)); digest.update((byte) 1); digest.update(format.get().getBytes(StandardCharsets.UTF_8)); - if (dependencyObj != null) { + if (dependency != null) { digest.update((byte) 2); - if (dependencyObj instanceof ModuleDependency) { - if (dependencyObj.getGroup() != null) { - digest.update(dependencyObj.getGroup().getBytes(StandardCharsets.UTF_8)); + if (dependency instanceof ModuleDependency) { + if (dependency.getGroup() != null) { + digest.update(dependency.getGroup().getBytes(StandardCharsets.UTF_8)); } - digest.update((":" + dependencyObj.getName()).getBytes(StandardCharsets.UTF_8)); - if (dependencyObj.getVersion() != null) { - digest.update((":" + dependencyObj.getVersion()).getBytes(StandardCharsets.UTF_8)); + digest.update((":" + dependency.getName()).getBytes(StandardCharsets.UTF_8)); + if (dependency.getVersion() != null) { + digest.update((":" + dependency.getVersion()).getBytes(StandardCharsets.UTF_8)); } - } else if (dependencyObj instanceof FileCollectionDependency) { - for (File file : ((FileCollectionDependency) dependencyObj).getFiles()) { + } else if (dependency instanceof FileCollectionDependency) { + for (File file : ((FileCollectionDependency) dependency).getFiles()) { try (final InputStream is = new FileInputStream(file)) { final byte[] buf = new byte[4096]; int read; From 2bb3fa918a5157e4b8fe58b3d2e5fc2699f24667 Mon Sep 17 00:00:00 2001 From: Joe Date: Sat, 9 Oct 2021 17:26:20 +0100 Subject: [PATCH 11/15] Remap jar task --- subprojects/gradle-plugin/build.gradle.kts | 6 - .../task/JarEntryTransformerProvider.java | 9 + .../vanilla/internal/task/RemapFilter.java | 69 ++++++++ .../repository/MinecraftResolverImpl.java | 6 +- .../gradle/vanilla/task/RemapJar.java | 159 ++++++++++++++++++ 5 files changed, 242 insertions(+), 7 deletions(-) create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/JarEntryTransformerProvider.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/RemapFilter.java create mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/RemapJar.java diff --git a/subprojects/gradle-plugin/build.gradle.kts b/subprojects/gradle-plugin/build.gradle.kts index 49b5ece2..2e189d00 100644 --- a/subprojects/gradle-plugin/build.gradle.kts +++ b/subprojects/gradle-plugin/build.gradle.kts @@ -45,12 +45,6 @@ val lorenzTinyVersion: String by project val mappingIoVersion: String by project val featherVersion: String by project -repositories { - maven("https://maven.parchmentmc.org/") { - name = "ParchmentMC" - } -} - dependencies { // All source sets commonDeps(gradleApi()) diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/JarEntryTransformerProvider.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/JarEntryTransformerProvider.java new file mode 100644 index 00000000..7c031062 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/JarEntryTransformerProvider.java @@ -0,0 +1,9 @@ +package org.spongepowered.gradle.vanilla.internal.task; + +import org.cadixdev.bombe.jar.JarEntryTransformer; + +import java.io.IOException; + +public interface JarEntryTransformerProvider { + JarEntryTransformer getJarEntryTransformer() throws IOException; +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/RemapFilter.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/RemapFilter.java new file mode 100644 index 00000000..74242631 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/RemapFilter.java @@ -0,0 +1,69 @@ +package org.spongepowered.gradle.vanilla.internal.task; + +import org.apache.tools.ant.filters.BaseFilterReader; +import org.apache.tools.ant.util.ReaderInputStream; +import org.cadixdev.bombe.jar.JarClassEntry; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.gradle.api.Project; +import org.gradle.api.file.CopySpec; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.util.Collections; + +public class RemapFilter extends BaseFilterReader { + private @MonotonicNonNull JarEntryTransformerProvider remapper; + private @MonotonicNonNull Reader delegate; + + public RemapFilter(Reader in) { + super(in); + } + + public JarEntryTransformerProvider getRemapper() { + return remapper; + } + + public void setRemapper(JarEntryTransformerProvider remapper) { + this.remapper = remapper; + } + + public static CopySpec createCopySpec(Project project, JarEntryTransformerProvider remapper) { + return project.copySpec(spec -> { + spec.include("**/*.class"); + spec.setFilteringCharset("ISO-8859-1"); + spec.filter(Collections.singletonMap("remapper", remapper), RemapFilter.class); + }); + } + + private void initialize() throws IOException { + InputStream in = new ReaderInputStream(this.in, StandardCharsets.ISO_8859_1); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[8192]; + int n; + while ((n = in.read(buffer)) != -1) { + baos.write(buffer, 0, n); + } + byte[] bytes = baos.toByteArray(); + + JarClassEntry transformed = remapper.getJarEntryTransformer().transform(new JarClassEntry("Foo.class", 0, bytes)); + if (transformed == null) { + delegate = this.in; + } else { + delegate = new InputStreamReader(new ByteArrayInputStream(transformed.getContents()), StandardCharsets.ISO_8859_1); + } + } + + @Override + public int read() throws IOException { + if (!getInitialized()) { + initialize(); + setInitialized(true); + } + return delegate.read(); + } +} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java index cb3e3931..bab0a78d 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java @@ -399,7 +399,7 @@ public CompletableFuture> provide( try (final Atlas atlas = new Atlas(this.executor)) { for (final CompletableFuture populator : populators) { ArtifactModifier.AtlasPopulator pop = populator.get(); - atlas.install(ctx -> pop.provide(withAsmApi(ctx, Constants.ASM_VERSION), input.get(), side, (id, classifier, extension) -> this.sharedArtifactFileName(id, version, classifier, extension))); + atlas.install(ctx -> pop.provide(withAsmApi(ctx, Constants.ASM_VERSION), input.get(), side, sharedArtifactSupplier(version))); } atlas.run(input.get().jar(), outputTmp); @@ -427,6 +427,10 @@ public CompletableFuture> provide( )); } + public ArtifactModifier.SharedArtifactSupplier sharedArtifactSupplier(String version) { + return (id, classifier, extension) -> this.sharedArtifactFileName(id, version, classifier, extension); + } + private static final Field CPIP_CLASS_PROVIDER_FIELD; private static final Constructor ATC_CONSTRUCTOR; static { diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/RemapJar.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/RemapJar.java new file mode 100644 index 00000000..70e5e6f5 --- /dev/null +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/RemapJar.java @@ -0,0 +1,159 @@ +package org.spongepowered.gradle.vanilla.task; + +import org.cadixdev.atlas.jar.JarFile; +import org.cadixdev.atlas.util.CascadingClassProvider; +import org.cadixdev.bombe.asm.analysis.ClassProviderInheritanceProvider; +import org.cadixdev.bombe.asm.jar.ClassProvider; +import org.cadixdev.bombe.jar.JarEntryTransformer; +import org.cadixdev.lorenz.MappingSet; +import org.gradle.api.GradleException; +import org.gradle.api.Project; +import org.gradle.api.file.FileCollection; +import org.gradle.api.file.FileTree; +import org.gradle.api.model.ObjectFactory; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Classpath; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Internal; +import org.gradle.jvm.tasks.Jar; +import org.spongepowered.gradle.vanilla.MinecraftExtension; +import org.spongepowered.gradle.vanilla.internal.Constants; +import org.spongepowered.gradle.vanilla.internal.MinecraftExtensionImpl; +import org.spongepowered.gradle.vanilla.internal.repository.MinecraftProviderService; +import org.spongepowered.gradle.vanilla.internal.task.JarEntryTransformerProvider; +import org.spongepowered.gradle.vanilla.internal.task.RemapFilter; +import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; +import org.spongepowered.gradle.vanilla.repository.MinecraftResolverImpl; +import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; +import org.spongepowered.gradle.vanilla.resolver.ResolutionResult; + +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +public abstract class RemapJar extends Jar implements JarEntryTransformerProvider { + private final Property fromMappings; + private final Property toMappings; + private FileCollection classpath; + private JarEntryTransformer cachedTransformer; + + public RemapJar() { + final Project project = getProject(); + final ObjectFactory objects = project.getObjects(); + + fromMappings = objects.property(String.class).convention(project.provider(() -> { + final MinecraftExtension extension = project.getExtensions().findByType(MinecraftExtension.class); + Objects.requireNonNull(extension, "Could not find minecraft extension in project"); + return extension.minecraftMappings().get(); + })); + toMappings = objects.property(String.class); + + with(RemapFilter.createCopySpec(project, this)); + } + + @Input + public Property getFromMappings() { + return fromMappings; + } + + public void fromMappings(MappingsEntry mappings) { + fromMappings(mappings.getName()); + } + + public void fromMappings(String mappings) { + fromMappings.set(mappings); + } + + public void toMappings(MappingsEntry mappings) { + toMappings(mappings.getName()); + } + + public void toMappings(String mappings) { + toMappings.set(mappings); + } + + @Input + public Property getToMappings() { + return toMappings; + } + + @Classpath + public FileCollection getClasspath() { + return classpath; + } + + public void setClasspath(FileCollection classpath) { + this.classpath = classpath; + } + + @Internal + public abstract Property getMinecraftProvider(); + + @Override + public synchronized JarEntryTransformer getJarEntryTransformer() throws IOException { + if (cachedTransformer != null) { + return cachedTransformer; + } + Project project = getProject(); + MinecraftExtensionImpl extension = (MinecraftExtensionImpl) project.getExtensions().findByType(MinecraftExtension.class); + Objects.requireNonNull(extension, "Could not find minecraft extension in project"); + MinecraftProviderService minecraftProvider = getMinecraftProvider().get(); + minecraftProvider.primeResolver(project, extension.modifiers()); + MinecraftResolverImpl resolver = (MinecraftResolverImpl) minecraftProvider.resolver(); + String minecraftVersion = extension.version().get(); + CompletableFuture> envFuture = + resolver.provide(extension.platform().get(), minecraftVersion, extension.modifiers()); + try { + resolver.processSyncTasksUntilComplete(envFuture); + } catch (final ExecutionException ex) { + throw new GradleException("Failed to remap", ex.getCause()); + } catch (final InterruptedException ex) { + Thread.currentThread().interrupt(); + throw new GradleException("Interrupted"); + } + ResolutionResult envResult = envFuture.join(); + if (!envResult.isPresent()) { + throw new IllegalStateException("Could not find Minecraft environment"); + } + + List allFiles = new ArrayList<>(); + getMainSpec().walk(res -> allFiles.add(res.getAllSource())); + FileCollection actualClasspath = project.files(classpath, allFiles); + MappingSet mappings = extension.getMappings().getByName(toMappings.get()).convertFrom( + fromMappings.get(), + resolver, + envResult.get(), + extension.platform().get(), + resolver.sharedArtifactSupplier(minecraftVersion) + ); + List classProviders = new ArrayList<>(); + for (File file : actualClasspath) { + if (file.getName().endsWith(".jar")) { + classProviders.add(new JarFile(file.toPath())); + } + } + classProviders.add(name -> { + Set files = actualClasspath.getAsFileTree().matching(tree -> tree.include(name + ".class")).getFiles(); + if (files.size() != 1) { + return null; + } + try { + return Files.readAllBytes(files.iterator().next().toPath()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + return cachedTransformer = AtlasTransformers.remap(mappings, new ClassProviderInheritanceProvider( + Constants.ASM_VERSION, + new CascadingClassProvider(classProviders)) + ); + } +} From 94d9056bbc0eebaa1a9210ea8c015ba8068bddb0 Mon Sep 17 00:00:00 2001 From: zml Date: Tue, 12 Oct 2021 21:38:34 -0700 Subject: [PATCH 12/15] Allow customizing the cache locations used with Gradle properties. --- .../repository/MinecraftRepositoryPlugin.java | 85 +++++++++++++++---- 1 file changed, 70 insertions(+), 15 deletions(-) diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java index f2af3a71..a71ca8a0 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/repository/MinecraftRepositoryPlugin.java @@ -41,6 +41,7 @@ import org.gradle.api.invocation.Gradle; import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.provider.Provider; +import org.gradle.api.provider.ProviderFactory; import org.gradle.build.event.BuildEventsListenerRegistry; import org.spongepowered.gradle.vanilla.MinecraftExtension; import org.spongepowered.gradle.vanilla.internal.Constants; @@ -55,7 +56,6 @@ import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; import java.io.File; -import java.nio.file.Path; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.regex.Pattern; @@ -67,6 +67,12 @@ */ public class MinecraftRepositoryPlugin implements Plugin { + private static final String GRADLE_PROPERTY_PREFIX = "org.spongepowered.gradle.vanilla."; + + private static final String GRADLE_PROPERTY_SHARED_CACHE = MinecraftRepositoryPlugin.GRADLE_PROPERTY_PREFIX + "sharedCacheRoot"; + + private static final String GRADLE_PROPERTY_ROOT_PROJECT_CACHE = MinecraftRepositoryPlugin.GRADLE_PROPERTY_PREFIX + "projectCacheRoot"; + /** * A variant of {@link IvyArtifactRepository#MAVEN_IVY_PATTERN} that takes * into account our metadata revision number. @@ -107,8 +113,19 @@ public Provider service() { private void applyToProject(final Project project) { // Setup - final Path sharedCacheDirectory = MinecraftRepositoryPlugin.resolveCache(project.getGradle().getGradleUserHomeDir().toPath()); - final Path rootProjectCache = MinecraftRepositoryPlugin.resolveCache(project.getRootDir().toPath().resolve(".gradle")); + final ProviderFactory providers = project.getProviders(); + final Provider sharedCacheDirectory = MinecraftRepositoryPlugin.resolveCache( + project.getRootDir(), + providers, + MinecraftRepositoryPlugin.GRADLE_PROPERTY_SHARED_CACHE, + project.getGradle().getGradleUserHomeDir() + ); + final Provider rootProjectCache = MinecraftRepositoryPlugin.resolveCache( + project.getRootDir(), + providers, + MinecraftRepositoryPlugin.GRADLE_PROPERTY_ROOT_PROJECT_CACHE, + new File(project.getRootDir(), ".gradle") + ); final Provider service = this.registerService(project.getGradle(), sharedCacheDirectory, rootProjectCache); // Apply vanillagradle caches @@ -227,8 +244,19 @@ private void configureResolutionStrategy( private void applyToSettings(final Settings settings) { // Setup - final Path sharedCacheDirectory = MinecraftRepositoryPlugin.resolveCache(settings.getGradle().getGradleUserHomeDir().toPath()); - final Path rootProjectCache = MinecraftRepositoryPlugin.resolveCache(settings.getRootDir().toPath().resolve(".gradle")); + final ProviderFactory providers = settings.getProviders(); + final Provider sharedCacheDirectory = MinecraftRepositoryPlugin.resolveCache( + settings.getRootDir(), + providers, + MinecraftRepositoryPlugin.GRADLE_PROPERTY_SHARED_CACHE, + settings.getGradle().getGradleUserHomeDir() + ); + final Provider rootProjectCache = MinecraftRepositoryPlugin.resolveCache( + settings.getRootDir(), + providers, + MinecraftRepositoryPlugin.GRADLE_PROPERTY_ROOT_PROJECT_CACHE, + new File(settings.getRootDir(), ".gradle") + ); final Provider service = this.registerService(settings.getGradle(), sharedCacheDirectory, rootProjectCache); // Apply VanillaGradle caches @@ -268,29 +296,54 @@ private MinecraftRepositoryExtension registerExtension(final ExtensionAware hold return extension; } - private static Path resolveCache(final Path root) { - return root.resolve(Constants.Directories.CACHES).resolve(Constants.NAME).resolve("v" + MinecraftResolver.STORAGE_VERSION); + private static Provider resolveCache( + final File relativeTo, + final ProviderFactory providers, + final String propertyName, + final File root + ) { + return providers.gradleProperty(propertyName) + .forUseAtConfigurationTime() + .map(dirName -> { + final File dir = new File(dirName); + if (dir.isAbsolute()) { + return dir; + } else { + return new File(relativeTo, dirName); + } + }) + .orElse(new File(new File(root, Constants.Directories.CACHES), Constants.NAME)) + .map(loc -> new File(loc, "v" + MinecraftResolver.STORAGE_VERSION)); } - private void createRepositories(final RepositoryHandler repositories, final Provider service, final Path sharedCache, final Path rootProjectCache) { + private void createRepositories( + final RepositoryHandler repositories, + final Provider service, + final Provider sharedCache, + final Provider rootProjectCache + ) { // Global cache (for standard artifacts) repositories.ivy(MinecraftRepositoryPlugin.repositoryConfiguration( "VanillaGradle Global Cache", - sharedCache.resolve(Constants.Directories.JARS), + sharedCache.map(f -> new File(f, Constants.Directories.JARS)), service )); // Root-project cache (for project-specific transformations, such as access wideners, potentially other things repositories.ivy(MinecraftRepositoryPlugin.repositoryConfiguration( "VanillaGradle Project Cache", - rootProjectCache.resolve(Constants.Directories.JARS), + rootProjectCache.map(f -> new File(f, Constants.Directories.JARS)), service )); } - private static Action repositoryConfiguration(final String name, final Path root, final Provider service) { + private static Action repositoryConfiguration( + final String name, + final Provider root, + final Provider service + ) { return ivy -> { ivy.setName(name); - ivy.setUrl(root.toUri()); + ivy.setUrl(root.get().toURI()); ivy.patternLayout(layout -> { layout.artifact(IvyArtifactRepository.MAVEN_ARTIFACT_PATTERN); layout.ivy(MinecraftRepositoryPlugin.IVY_METADATA_PATTERN); @@ -320,11 +373,13 @@ private void registerComponentMetadataRules(final ComponentMetadataHandler handl } } - private Provider registerService(final Gradle gradle, final Path sharedCacheDir, final Path rootProjectCacheDir) { + private Provider registerService( + final Gradle gradle, final Provider sharedCacheDir, final Provider rootProjectCacheDir + ) { final Provider service = this.service = gradle.getSharedServices().registerIfAbsent("vanillaGradleMinecraft", MinecraftProviderService.class, params -> { final MinecraftProviderService.Parameters options = params.getParameters(); - options.getSharedCache().set(sharedCacheDir.toFile()); - options.getRootProjectCache().set(rootProjectCacheDir.toFile()); + options.getSharedCache().fileProvider(sharedCacheDir); + options.getRootProjectCache().fileProvider(rootProjectCacheDir); options.getOfflineMode().set(gradle.getStartParameter().isOffline()); options.getRefreshDependencies().set(gradle.getStartParameter().isRefreshDependencies()); }); From 65b51ff56ded11a0523c92e36bc1ff656f577352 Mon Sep 17 00:00:00 2001 From: zml Date: Tue, 12 Oct 2021 21:57:03 -0700 Subject: [PATCH 13/15] Fix one of the causes of locking up --- .../repository/MinecraftResolverImpl.java | 22 ++++++++++++----- .../gradle/vanilla/task/DecompileJarTask.java | 24 +++++++++---------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java index ba372172..c827946c 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java @@ -531,18 +531,28 @@ public CompletableFuture> produceAssociatedArtifactSync( @Override public T processSyncTasksUntilComplete(CompletableFuture future) throws InterruptedException, ExecutionException { - future.handle((res, err) -> { - this.syncTasks.add(new CompleteEvaluation(future)); - return res; - }); + future.handleAsync( + ( + res, + err + ) -> { + this.syncTasks.add(new CompleteEvaluation(future)); + return res; + }, + this.executor + ); Runnable action; for (;;) { action = this.syncTasks.take(); // todo: rethrow exceptions with an ExecutionException - if (action instanceof CompleteEvaluation && ((CompleteEvaluation) action).completed == future) { - break; + if (action instanceof CompleteEvaluation) { + if (((CompleteEvaluation) action).completed == future) { + break; + } else { + this.syncTasks.add(action); + } } try { diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java index 3afa0787..0932c7d7 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/DecompileJarTask.java @@ -186,19 +186,19 @@ public void execute() { } ); - try { - final ResolutionResult result = minecraftProvider.resolver().processSyncTasksUntilComplete(resultFuture); - this.setDidWork(!result.upToDate()); - } catch (final ExecutionException ex) { - throw new GradleException("Failed to decompile " + this.getMinecraftVersion().get(), ex.getCause()); - } catch (final InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new GradleException("Interrupted"); - } + try { + final ResolutionResult result = minecraftProvider.resolver().processSyncTasksUntilComplete(resultFuture); + this.setDidWork(!result.upToDate()); + } catch (final ExecutionException ex) { + throw new GradleException("Failed to decompile " + this.getMinecraftVersion().get(), ex.getCause()); + } catch (final InterruptedException ex) { + Thread.currentThread().interrupt(); + throw new GradleException("Interrupted"); + } - } finally { - DecompileJarTask.DECOMPILE_LOCK.unlock(); - } + } finally { + DecompileJarTask.DECOMPILE_LOCK.unlock(); + } } } From 4c31919a22ce6e7634ab32800be648b14ceb3daa Mon Sep 17 00:00:00 2001 From: zml Date: Tue, 12 Oct 2021 22:04:25 -0700 Subject: [PATCH 14/15] Terrible dumb temp fix for being able to decompile produceAssociatedArtifactSync needs to go at some point anyways. --- .../gradle/vanilla/repository/MinecraftResolverImpl.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java index c827946c..30f81962 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java @@ -489,7 +489,13 @@ public CompletableFuture> produceAssociatedArtifactSync( // there's nothing yet, it's our time to resolve final ResolutionResult envResult; try { - envResult = this.provide(side, version, modifiers).get(); + envResult = this.processSyncTasksUntilComplete( + this.provide( + side, + version, + modifiers + ) + ); } catch (final ExecutionException ex) { ourResult.completeExceptionally(ex.getCause()); return ourResult; From c25bfacd4d7d2a7c354065bfd7cac7d251eaf412 Mon Sep 17 00:00:00 2001 From: Joe Date: Fri, 15 Oct 2021 13:34:22 +0100 Subject: [PATCH 15/15] Revert "Remap jar task" This reverts commit 2bb3fa918a5157e4b8fe58b3d2e5fc2699f24667. --- .../task/JarEntryTransformerProvider.java | 9 - .../vanilla/internal/task/RemapFilter.java | 69 -------- .../repository/MinecraftResolverImpl.java | 6 +- .../gradle/vanilla/task/RemapJar.java | 159 ------------------ 4 files changed, 1 insertion(+), 242 deletions(-) delete mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/JarEntryTransformerProvider.java delete mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/RemapFilter.java delete mode 100644 subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/RemapJar.java diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/JarEntryTransformerProvider.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/JarEntryTransformerProvider.java deleted file mode 100644 index 7c031062..00000000 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/JarEntryTransformerProvider.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.spongepowered.gradle.vanilla.internal.task; - -import org.cadixdev.bombe.jar.JarEntryTransformer; - -import java.io.IOException; - -public interface JarEntryTransformerProvider { - JarEntryTransformer getJarEntryTransformer() throws IOException; -} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/RemapFilter.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/RemapFilter.java deleted file mode 100644 index 74242631..00000000 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/internal/task/RemapFilter.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.spongepowered.gradle.vanilla.internal.task; - -import org.apache.tools.ant.filters.BaseFilterReader; -import org.apache.tools.ant.util.ReaderInputStream; -import org.cadixdev.bombe.jar.JarClassEntry; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -import org.gradle.api.Project; -import org.gradle.api.file.CopySpec; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.Collections; - -public class RemapFilter extends BaseFilterReader { - private @MonotonicNonNull JarEntryTransformerProvider remapper; - private @MonotonicNonNull Reader delegate; - - public RemapFilter(Reader in) { - super(in); - } - - public JarEntryTransformerProvider getRemapper() { - return remapper; - } - - public void setRemapper(JarEntryTransformerProvider remapper) { - this.remapper = remapper; - } - - public static CopySpec createCopySpec(Project project, JarEntryTransformerProvider remapper) { - return project.copySpec(spec -> { - spec.include("**/*.class"); - spec.setFilteringCharset("ISO-8859-1"); - spec.filter(Collections.singletonMap("remapper", remapper), RemapFilter.class); - }); - } - - private void initialize() throws IOException { - InputStream in = new ReaderInputStream(this.in, StandardCharsets.ISO_8859_1); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[8192]; - int n; - while ((n = in.read(buffer)) != -1) { - baos.write(buffer, 0, n); - } - byte[] bytes = baos.toByteArray(); - - JarClassEntry transformed = remapper.getJarEntryTransformer().transform(new JarClassEntry("Foo.class", 0, bytes)); - if (transformed == null) { - delegate = this.in; - } else { - delegate = new InputStreamReader(new ByteArrayInputStream(transformed.getContents()), StandardCharsets.ISO_8859_1); - } - } - - @Override - public int read() throws IOException { - if (!getInitialized()) { - initialize(); - setInitialized(true); - } - return delegate.read(); - } -} diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java index 222a517d..a24cbe89 100644 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java +++ b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java @@ -399,7 +399,7 @@ public CompletableFuture> provide( try (final Atlas atlas = new Atlas(this.executor)) { for (final CompletableFuture populator : populators) { ArtifactModifier.AtlasPopulator pop = populator.get(); - atlas.install(ctx -> pop.provide(withAsmApi(ctx, Constants.ASM_VERSION), input.get(), side, sharedArtifactSupplier(version))); + atlas.install(ctx -> pop.provide(withAsmApi(ctx, Constants.ASM_VERSION), input.get(), side, (id, classifier, extension) -> this.sharedArtifactFileName(id, version, classifier, extension))); } atlas.run(input.get().jar(), outputTmp); @@ -427,10 +427,6 @@ public CompletableFuture> provide( )); } - public ArtifactModifier.SharedArtifactSupplier sharedArtifactSupplier(String version) { - return (id, classifier, extension) -> this.sharedArtifactFileName(id, version, classifier, extension); - } - private static final Field CPIP_CLASS_PROVIDER_FIELD; private static final Constructor ATC_CONSTRUCTOR; static { diff --git a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/RemapJar.java b/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/RemapJar.java deleted file mode 100644 index 70e5e6f5..00000000 --- a/subprojects/gradle-plugin/src/main/java/org/spongepowered/gradle/vanilla/task/RemapJar.java +++ /dev/null @@ -1,159 +0,0 @@ -package org.spongepowered.gradle.vanilla.task; - -import org.cadixdev.atlas.jar.JarFile; -import org.cadixdev.atlas.util.CascadingClassProvider; -import org.cadixdev.bombe.asm.analysis.ClassProviderInheritanceProvider; -import org.cadixdev.bombe.asm.jar.ClassProvider; -import org.cadixdev.bombe.jar.JarEntryTransformer; -import org.cadixdev.lorenz.MappingSet; -import org.gradle.api.GradleException; -import org.gradle.api.Project; -import org.gradle.api.file.FileCollection; -import org.gradle.api.file.FileTree; -import org.gradle.api.model.ObjectFactory; -import org.gradle.api.provider.Property; -import org.gradle.api.tasks.Classpath; -import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.Internal; -import org.gradle.jvm.tasks.Jar; -import org.spongepowered.gradle.vanilla.MinecraftExtension; -import org.spongepowered.gradle.vanilla.internal.Constants; -import org.spongepowered.gradle.vanilla.internal.MinecraftExtensionImpl; -import org.spongepowered.gradle.vanilla.internal.repository.MinecraftProviderService; -import org.spongepowered.gradle.vanilla.internal.task.JarEntryTransformerProvider; -import org.spongepowered.gradle.vanilla.internal.task.RemapFilter; -import org.spongepowered.gradle.vanilla.internal.transformer.AtlasTransformers; -import org.spongepowered.gradle.vanilla.repository.MinecraftResolver; -import org.spongepowered.gradle.vanilla.repository.MinecraftResolverImpl; -import org.spongepowered.gradle.vanilla.repository.mappings.MappingsEntry; -import org.spongepowered.gradle.vanilla.resolver.ResolutionResult; - -import java.io.File; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -public abstract class RemapJar extends Jar implements JarEntryTransformerProvider { - private final Property fromMappings; - private final Property toMappings; - private FileCollection classpath; - private JarEntryTransformer cachedTransformer; - - public RemapJar() { - final Project project = getProject(); - final ObjectFactory objects = project.getObjects(); - - fromMappings = objects.property(String.class).convention(project.provider(() -> { - final MinecraftExtension extension = project.getExtensions().findByType(MinecraftExtension.class); - Objects.requireNonNull(extension, "Could not find minecraft extension in project"); - return extension.minecraftMappings().get(); - })); - toMappings = objects.property(String.class); - - with(RemapFilter.createCopySpec(project, this)); - } - - @Input - public Property getFromMappings() { - return fromMappings; - } - - public void fromMappings(MappingsEntry mappings) { - fromMappings(mappings.getName()); - } - - public void fromMappings(String mappings) { - fromMappings.set(mappings); - } - - public void toMappings(MappingsEntry mappings) { - toMappings(mappings.getName()); - } - - public void toMappings(String mappings) { - toMappings.set(mappings); - } - - @Input - public Property getToMappings() { - return toMappings; - } - - @Classpath - public FileCollection getClasspath() { - return classpath; - } - - public void setClasspath(FileCollection classpath) { - this.classpath = classpath; - } - - @Internal - public abstract Property getMinecraftProvider(); - - @Override - public synchronized JarEntryTransformer getJarEntryTransformer() throws IOException { - if (cachedTransformer != null) { - return cachedTransformer; - } - Project project = getProject(); - MinecraftExtensionImpl extension = (MinecraftExtensionImpl) project.getExtensions().findByType(MinecraftExtension.class); - Objects.requireNonNull(extension, "Could not find minecraft extension in project"); - MinecraftProviderService minecraftProvider = getMinecraftProvider().get(); - minecraftProvider.primeResolver(project, extension.modifiers()); - MinecraftResolverImpl resolver = (MinecraftResolverImpl) minecraftProvider.resolver(); - String minecraftVersion = extension.version().get(); - CompletableFuture> envFuture = - resolver.provide(extension.platform().get(), minecraftVersion, extension.modifiers()); - try { - resolver.processSyncTasksUntilComplete(envFuture); - } catch (final ExecutionException ex) { - throw new GradleException("Failed to remap", ex.getCause()); - } catch (final InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new GradleException("Interrupted"); - } - ResolutionResult envResult = envFuture.join(); - if (!envResult.isPresent()) { - throw new IllegalStateException("Could not find Minecraft environment"); - } - - List allFiles = new ArrayList<>(); - getMainSpec().walk(res -> allFiles.add(res.getAllSource())); - FileCollection actualClasspath = project.files(classpath, allFiles); - MappingSet mappings = extension.getMappings().getByName(toMappings.get()).convertFrom( - fromMappings.get(), - resolver, - envResult.get(), - extension.platform().get(), - resolver.sharedArtifactSupplier(minecraftVersion) - ); - List classProviders = new ArrayList<>(); - for (File file : actualClasspath) { - if (file.getName().endsWith(".jar")) { - classProviders.add(new JarFile(file.toPath())); - } - } - classProviders.add(name -> { - Set files = actualClasspath.getAsFileTree().matching(tree -> tree.include(name + ".class")).getFiles(); - if (files.size() != 1) { - return null; - } - try { - return Files.readAllBytes(files.iterator().next().toPath()); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }); - return cachedTransformer = AtlasTransformers.remap(mappings, new ClassProviderInheritanceProvider( - Constants.ASM_VERSION, - new CascadingClassProvider(classProviders)) - ); - } -}