Add file mappings layer (#590)
* Support passing FileSpecs around for the FileSpec notation * Add file mappings layer * Add better tests for file mappings * Remove unnecessary param in setup closure call * Fix test code style * Add ZipUtils.isZip * Automatically detect whether the file is a zip * Rename LayeredMappingSpecBuilder.fileMappings -> mappings * Add test for file mappings in layered mappings, fix inconsistent hashCode being * Resolve reviewsdev/0.11
parent
287e6cefb9
commit
5dda747cee
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016-2021 FabricMC
|
||||
* Copyright (c) 2016-2022 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -26,6 +26,8 @@ package net.fabricmc.loom.api.mappings.layered;
|
|||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The standard namespaces used by loom.
|
||||
*/
|
||||
|
@ -49,6 +51,21 @@ public enum MappingsNamespace {
|
|||
*/
|
||||
NAMED;
|
||||
|
||||
/**
|
||||
* Gets a {@code MappingsNamespace} from a namespace string.
|
||||
*
|
||||
* @param namespace the name of the namespace as a lowercase string
|
||||
* @return the {@code MappingsNamespace}, or null if not found
|
||||
*/
|
||||
public static @Nullable MappingsNamespace of(String namespace) {
|
||||
return switch (namespace) {
|
||||
case "official" -> OFFICIAL;
|
||||
case "intermediary" -> INTERMEDIARY;
|
||||
case "named" -> NAMED;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021-2022 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.api.mappings.layered.spec;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
|
||||
/**
|
||||
* A builder for a file mappings layer.
|
||||
* This layer type supports any mapping type that mapping-io can read.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public interface FileMappingsSpecBuilder {
|
||||
/**
|
||||
* Sets the mapping path inside a zip or jar.
|
||||
* This will have no effect if the file of this mapping spec
|
||||
* is not a zip.
|
||||
*
|
||||
* <p>Path components within the path should be separated with {@code /}.
|
||||
*
|
||||
* <p>The default mapping path is {@code mappings/mappings.tiny}, matching regular mapping dependency jars
|
||||
* such as Yarn's.
|
||||
*
|
||||
* @param mappingPath the mapping path, or null if a bare file
|
||||
* @return this builder
|
||||
*/
|
||||
FileMappingsSpecBuilder mappingPath(String mappingPath);
|
||||
|
||||
/**
|
||||
* Sets the fallback namespaces. They will be used
|
||||
* if the mapping format itself doesn't provide namespaces with names
|
||||
* (e.g. Enigma mappings).
|
||||
*
|
||||
* <p>The default fallback namespaces are {@code intermediary} as the source namespace
|
||||
* and {@code named} as the target namespace as in Yarn.
|
||||
*
|
||||
* @param sourceNamespace the fallback source namespace
|
||||
* @param targetNamespace the fallback target namespace
|
||||
* @return this builder
|
||||
*/
|
||||
FileMappingsSpecBuilder fallbackNamespaces(String sourceNamespace, String targetNamespace);
|
||||
|
||||
/**
|
||||
* Marks that the file contains Enigma mappings.
|
||||
* Because they are stored in a directory, the format cannot be auto-detected.
|
||||
*
|
||||
* @return this builder
|
||||
*/
|
||||
FileMappingsSpecBuilder enigmaMappings();
|
||||
|
||||
/**
|
||||
* Sets the merge namespace of this mappings spec.
|
||||
*
|
||||
* <p>The merge namespace is the namespace that is used to match up this layer's
|
||||
* names to the rest of the mappings. For example, Yarn mappings should be merged through
|
||||
* the intermediary names.
|
||||
*
|
||||
* <p>The default merge namespace is {@link MappingsNamespace#INTERMEDIARY}.
|
||||
*
|
||||
* @param namespace the new merge namespace
|
||||
* @return this builder
|
||||
*/
|
||||
FileMappingsSpecBuilder mergeNamespace(MappingsNamespace namespace);
|
||||
|
||||
/**
|
||||
* Sets the merge namespace of this mappings spec.
|
||||
*
|
||||
* <p>The merge namespace is the namespace that is used to match up this layer's
|
||||
* names to the rest of the mappings. For example, Yarn mappings should be merged through
|
||||
* the intermediary names.
|
||||
*
|
||||
* <p>The default merge namespace is {@code intermediary}.
|
||||
*
|
||||
* @param namespace the new merge namespace
|
||||
* @return this builder
|
||||
*/
|
||||
FileMappingsSpecBuilder mergeNamespace(String namespace);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
* Copyright (c) 2021-2022 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -50,9 +50,10 @@ public interface FileSpec {
|
|||
* <p>The parameter will be evaluated like this:
|
||||
* <ul>
|
||||
* <li>{@link File}, {@link Path} and {@link FileSystemLocation} will be resolved as local files</li>
|
||||
* <li>{@link Provider} (including {@link org.gradle.api.provider.Property} will recursively be resolved as its current value</li>
|
||||
* <li>{@link Provider} (including {@link org.gradle.api.provider.Property}) will recursively be resolved as its current value</li>
|
||||
* <li>{@link CharSequence} (including {@link String} and {@link groovy.lang.GString}) will be resolved as Maven dependencies</li>
|
||||
* <li>{@link Dependency} will be resolved as any dependency</li>
|
||||
* <li>{@code FileSpec} will just return the spec itself</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param o the file notation
|
||||
|
@ -73,6 +74,8 @@ public interface FileSpec {
|
|||
return createFromFile(p);
|
||||
} else if (o instanceof FileSystemLocation l) {
|
||||
return createFromFile(l);
|
||||
} else if (o instanceof FileSpec s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Cannot create FileSpec from object of type:" + o.getClass().getCanonicalName());
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
* Copyright (c) 2021-2022 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -77,4 +77,40 @@ public interface LayeredMappingSpecBuilder {
|
|||
*/
|
||||
@ApiStatus.Experimental
|
||||
LayeredMappingSpecBuilder signatureFix(Object object);
|
||||
|
||||
/**
|
||||
* Add a layer that uses a mappings file or directory.
|
||||
*
|
||||
* @param file the file notation for a {@link FileSpec}
|
||||
* @return this builder
|
||||
* @see FileMappingsSpecBuilder
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
default LayeredMappingSpecBuilder mappings(Object file) {
|
||||
return mappings(file, builder -> { });
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure and add a layer that uses a mappings file or directory.
|
||||
*
|
||||
* @param file the file notation for a {@link FileSpec}
|
||||
* @param closure the configuration action
|
||||
* @return this builder
|
||||
* @see FileMappingsSpecBuilder
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
default LayeredMappingSpecBuilder mappings(Object file, @DelegatesTo(value = FileMappingsSpecBuilder.class, strategy = Closure.DELEGATE_FIRST) Closure<?> closure) {
|
||||
return mappings(file, new ClosureAction<>(closure));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure and add a layer that uses a mappings file or directory.
|
||||
*
|
||||
* @param file the file notation for a {@link FileSpec}
|
||||
* @param action the configuration action
|
||||
* @return this builder
|
||||
* @see FileMappingsSpecBuilder
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
LayeredMappingSpecBuilder mappings(Object file, Action<? super FileMappingsSpecBuilder> action);
|
||||
}
|
||||
|
|
|
@ -30,12 +30,14 @@ import java.util.List;
|
|||
|
||||
import org.gradle.api.Action;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileMappingsSpecBuilder;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.MojangMappingsSpecBuilder;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.ParchmentMappingsSpecBuilder;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.extras.signatures.SignatureFixesSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.file.FileMappingsSpecBuilderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.mojmap.MojangMappingsSpecBuilderImpl;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.parchment.ParchmentMappingsSpecBuilderImpl;
|
||||
|
@ -68,6 +70,13 @@ public class LayeredMappingSpecBuilderImpl implements LayeredMappingSpecBuilder
|
|||
return addLayer(new SignatureFixesSpec(FileSpec.create(object)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayeredMappingSpecBuilder mappings(Object file, Action<? super FileMappingsSpecBuilder> action) {
|
||||
FileMappingsSpecBuilderImpl builder = FileMappingsSpecBuilderImpl.builder(FileSpec.create(file));
|
||||
action.execute(builder);
|
||||
return addLayer(builder.build());
|
||||
}
|
||||
|
||||
public LayeredMappingSpec build() {
|
||||
List<MappingsSpec<?>> builtLayers = new LinkedList<>();
|
||||
// Intermediary is always the base layer
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.file;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingLayer;
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingLayer;
|
||||
import net.fabricmc.loom.util.FileSystemUtil;
|
||||
import net.fabricmc.loom.util.ZipUtils;
|
||||
import net.fabricmc.mappingio.MappingReader;
|
||||
import net.fabricmc.mappingio.MappingUtil;
|
||||
import net.fabricmc.mappingio.MappingVisitor;
|
||||
import net.fabricmc.mappingio.adapter.MappingNsRenamer;
|
||||
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch;
|
||||
import net.fabricmc.mappingio.format.MappingFormat;
|
||||
|
||||
public record FileMappingsLayer(
|
||||
Path path, String mappingPath,
|
||||
String fallbackSourceNamespace, String fallbackTargetNamespace,
|
||||
boolean enigma, // Enigma cannot be automatically detected since it's stored in a directory.
|
||||
String mergeNamespace
|
||||
) implements MappingLayer {
|
||||
@Override
|
||||
public void visit(MappingVisitor mappingVisitor) throws IOException {
|
||||
// Bare file
|
||||
if (!ZipUtils.isZip(path)) {
|
||||
visit(path, mappingVisitor);
|
||||
} else {
|
||||
try (FileSystemUtil.Delegate fileSystem = FileSystemUtil.getJarFileSystem(path)) {
|
||||
visit(fileSystem.get().getPath(mappingPath), mappingVisitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void visit(Path path, MappingVisitor mappingVisitor) throws IOException {
|
||||
MappingSourceNsSwitch nsSwitch = new MappingSourceNsSwitch(mappingVisitor, mergeNamespace.toString());
|
||||
|
||||
// Replace the default fallback namespaces with
|
||||
// our fallback namespaces if potentially needed.
|
||||
Map<String, String> fallbackNamespaceReplacements = Map.of(
|
||||
MappingUtil.NS_SOURCE_FALLBACK, fallbackSourceNamespace,
|
||||
MappingUtil.NS_TARGET_FALLBACK, fallbackTargetNamespace
|
||||
);
|
||||
MappingNsRenamer renamer = new MappingNsRenamer(nsSwitch, fallbackNamespaceReplacements);
|
||||
|
||||
MappingReader.read(path, enigma ? MappingFormat.ENIGMA : null, renamer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingsNamespace getSourceNamespace() {
|
||||
return MappingsNamespace.of(mergeNamespace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends MappingLayer>> dependsOn() {
|
||||
return List.of(IntermediaryMappingLayer.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.file;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingContext;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileSpec;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.MappingsSpec;
|
||||
|
||||
public record FileMappingsSpec(
|
||||
FileSpec fileSpec, String mappingPath,
|
||||
String fallbackSourceNamespace, String fallbackTargetNamespace,
|
||||
boolean enigma,
|
||||
String mergeNamespace
|
||||
) implements MappingsSpec<FileMappingsLayer> {
|
||||
@Override
|
||||
public FileMappingsLayer createLayer(MappingContext context) {
|
||||
return new FileMappingsLayer(fileSpec.get(context), mappingPath, fallbackSourceNamespace, fallbackTargetNamespace, enigma, mergeNamespace);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.configuration.providers.mappings.file;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileMappingsSpecBuilder;
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileSpec;
|
||||
|
||||
public class FileMappingsSpecBuilderImpl implements FileMappingsSpecBuilder {
|
||||
/**
|
||||
* The mapping path of regular mapping dependencies.
|
||||
*/
|
||||
private static final String DEFAULT_MAPPING_PATH = "mappings/mappings.tiny";
|
||||
|
||||
private final FileSpec fileSpec;
|
||||
private String mappingPath = DEFAULT_MAPPING_PATH;
|
||||
private String fallbackSourceNamespace = MappingsNamespace.INTERMEDIARY.toString();
|
||||
private String fallbackTargetNamespace = MappingsNamespace.NAMED.toString();
|
||||
private boolean enigma = false;
|
||||
private String mergeNamespace = MappingsNamespace.INTERMEDIARY.toString();
|
||||
|
||||
private FileMappingsSpecBuilderImpl(FileSpec fileSpec) {
|
||||
this.fileSpec = fileSpec;
|
||||
}
|
||||
|
||||
public static FileMappingsSpecBuilderImpl builder(FileSpec fileSpec) {
|
||||
return new FileMappingsSpecBuilderImpl(fileSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileMappingsSpecBuilderImpl mappingPath(String mappingPath) {
|
||||
this.mappingPath = Objects.requireNonNull(mappingPath, "mapping path cannot be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileMappingsSpecBuilderImpl fallbackNamespaces(String sourceNamespace, String targetNamespace) {
|
||||
fallbackSourceNamespace = Objects.requireNonNull(sourceNamespace, "fallback source namespace cannot be null");
|
||||
fallbackTargetNamespace = Objects.requireNonNull(targetNamespace, "fallback target namespace cannot be null");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileMappingsSpecBuilderImpl enigmaMappings() {
|
||||
enigma = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileMappingsSpecBuilderImpl mergeNamespace(MappingsNamespace namespace) {
|
||||
mergeNamespace = Objects.requireNonNull(namespace, "merge namespace cannot be null").toString();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileMappingsSpecBuilderImpl mergeNamespace(String namespace) {
|
||||
Objects.requireNonNull(namespace, "merge namespace cannot be null");
|
||||
|
||||
if (MappingsNamespace.of(namespace) == null) {
|
||||
throw new IllegalArgumentException("Namespace '" + namespace + "' is unsupported! It must be either 'official', 'intermediary' or 'named'.");
|
||||
}
|
||||
|
||||
mergeNamespace = namespace;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileMappingsSpec build() {
|
||||
return new FileMappingsSpec(fileSpec, mappingPath, fallbackSourceNamespace, fallbackTargetNamespace, enigma, mergeNamespace);
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
package net.fabricmc.loom.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UncheckedIOException;
|
||||
|
@ -47,6 +48,22 @@ import org.jetbrains.annotations.Nullable;
|
|||
import net.fabricmc.loom.LoomGradlePlugin;
|
||||
|
||||
public class ZipUtils {
|
||||
public static boolean isZip(Path zip) throws IOException {
|
||||
if (Files.notExists(zip)) {
|
||||
throw new NoSuchFileException("Cannot check if '" + zip + "' is a zip because it doesn't exist!");
|
||||
}
|
||||
|
||||
if (Files.isRegularFile(zip)) {
|
||||
try (DataInputStream in = new DataInputStream(Files.newInputStream(zip))) {
|
||||
int header = in.readInt();
|
||||
// See https://en.wikipedia.org/wiki/List_of_file_signatures
|
||||
return header == 0x504B0304 || header == 0x504B0506 || header == 0x504B0708;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean contains(Path zip, String path) {
|
||||
try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(zip, false)) {
|
||||
Path fsPath = fs.get().getPath(path);
|
||||
|
|
|
@ -121,4 +121,32 @@ class ZipUtilsTest extends Specification {
|
|||
outputFile.exists()
|
||||
outputFile.text == "This is a test of unpacking all"
|
||||
}
|
||||
|
||||
def "is zip"() {
|
||||
setup:
|
||||
// Create zip
|
||||
def dir = Files.createTempDirectory("loom-zip-test")
|
||||
def zip = Files.createTempFile("loom-zip-test", ".zip")
|
||||
def fileInside = dir.resolve("text.txt")
|
||||
Files.writeString(fileInside, "hello world")
|
||||
ZipUtils.pack(dir, zip)
|
||||
|
||||
when:
|
||||
def result = ZipUtils.isZip(zip)
|
||||
|
||||
then:
|
||||
result
|
||||
}
|
||||
|
||||
def "is not zip"() {
|
||||
setup:
|
||||
def textFile = Files.createTempFile("loom-zip-test", ".txt")
|
||||
Files.writeString(textFile, "hello world")
|
||||
|
||||
when:
|
||||
def result = ZipUtils.isZip(textFile)
|
||||
|
||||
then:
|
||||
!result
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2022 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.fabricmc.loom.test.unit.layeredmappings
|
||||
|
||||
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace
|
||||
import net.fabricmc.loom.api.mappings.layered.spec.FileSpec
|
||||
import net.fabricmc.loom.configuration.providers.mappings.file.FileMappingsSpecBuilderImpl
|
||||
import net.fabricmc.loom.configuration.providers.mappings.intermediary.IntermediaryMappingsSpec
|
||||
import net.fabricmc.loom.util.DownloadUtil
|
||||
import net.fabricmc.loom.util.ZipUtils
|
||||
import spock.lang.Unroll
|
||||
|
||||
import java.nio.file.Path
|
||||
import java.util.function.Consumer
|
||||
|
||||
class FileMappingLayerTest extends LayeredMappingsSpecification {
|
||||
@Unroll
|
||||
def "read Yarn mappings from #setupType.displayName"() {
|
||||
setup:
|
||||
intermediaryUrl = INTERMEDIARY_1_17_URL
|
||||
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17
|
||||
setupType.setup.delegate = this
|
||||
def mappingFile = setupType.setup.call()
|
||||
when:
|
||||
def builder = FileMappingsSpecBuilderImpl.builder(FileSpec.create(mappingFile))
|
||||
setupType.mappingsSpec.accept(builder)
|
||||
def mappings = getLayeredMappings(
|
||||
new IntermediaryMappingsSpec(),
|
||||
builder.build()
|
||||
)
|
||||
then:
|
||||
mappings.srcNamespace == "named"
|
||||
mappings.dstNamespaces == ["intermediary", "official"]
|
||||
mappings.classes.size() == 6111
|
||||
mappings.classes[0].srcName == "net/minecraft/block/FenceBlock"
|
||||
mappings.classes[0].getDstName(0) == "net/minecraft/class_2354"
|
||||
mappings.classes[0].fields[0].srcName == "cullingShapes"
|
||||
mappings.classes[0].fields[0].getDstName(0) == "field_11066"
|
||||
mappings.classes[0].methods[0].srcName == "canConnectToFence"
|
||||
mappings.classes[0].methods[0].getDstName(0) == "method_26375"
|
||||
mappings.classes[0].methods[0].args[0].srcName == "state"
|
||||
where:
|
||||
setupType << YarnSetupType.values()
|
||||
}
|
||||
|
||||
// Also tests the custom fallback namespace and source namespace functionality
|
||||
def "read Mojang mappings from proguard"() {
|
||||
setup:
|
||||
intermediaryUrl = INTERMEDIARY_1_17_URL
|
||||
mockMinecraftProvider.getVersionInfo() >> VERSION_META_1_17
|
||||
def mappingsDownload = VERSION_META_1_17.download('client_mappings')
|
||||
def mappingsFile = new File(tempDir, 'mappings.txt')
|
||||
DownloadUtil.downloadIfChanged(new URL(mappingsDownload.url()), mappingsFile, mappingContext.logger)
|
||||
when:
|
||||
def mappings = getLayeredMappings(
|
||||
new IntermediaryMappingsSpec(),
|
||||
FileMappingsSpecBuilderImpl.builder(FileSpec.create(mappingsFile))
|
||||
.fallbackNamespaces('named', 'official')
|
||||
.mergeNamespace(MappingsNamespace.OFFICIAL)
|
||||
.build()
|
||||
)
|
||||
def tiny = getTiny(mappings)
|
||||
then:
|
||||
mappings.srcNamespace == "named"
|
||||
mappings.dstNamespaces == ["intermediary", "official"]
|
||||
mappings.classes.size() == 6113
|
||||
mappings.classes[0].srcName.hashCode() == 1869546970 // MojMap name, just check the hash
|
||||
mappings.classes[0].getDstName(0) == "net/minecraft/class_2354"
|
||||
mappings.classes[0].methods[0].args.size() == 0 // No Args
|
||||
tiny.contains('this$0')
|
||||
}
|
||||
|
||||
enum YarnSetupType {
|
||||
TINY_JAR('tiny jar', { downloadFile(YARN_1_17_URL, "yarn.jar") }, { }),
|
||||
BARE_TINY('bare tiny file', {
|
||||
def yarnJar = downloadFile(YARN_1_17_URL, "yarn.jar")
|
||||
def yarnTiny = new File(tempDir, "yarn.tiny")
|
||||
yarnTiny.bytes = ZipUtils.unpack(yarnJar.toPath(), "mappings/mappings.tiny")
|
||||
yarnTiny
|
||||
}, { }),
|
||||
ENIGMA_ZIP('enigma zip', {
|
||||
// Recent Yarn data is not published as Enigma zips, so this zip is just a copy
|
||||
// of Yarn's repo at a60a3189
|
||||
Path.of("src/test/resources/mappings/yarn-1.17.zip")
|
||||
}, {
|
||||
it.mappingPath("mappings").enigmaMappings()
|
||||
}),
|
||||
;
|
||||
|
||||
final String displayName
|
||||
final Closure<?> setup
|
||||
final Consumer<FileMappingsSpecBuilderImpl> mappingsSpec
|
||||
|
||||
YarnSetupType(String displayName, Closure<?> setup, Consumer<FileMappingsSpecBuilderImpl> mappingsSpec) {
|
||||
this.displayName = displayName
|
||||
this.setup = setup
|
||||
this.mappingsSpec = mappingsSpec
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
package net.fabricmc.loom.test.unit.layeredmappings
|
||||
|
||||
import net.fabricmc.loom.configuration.providers.mappings.file.FileMappingsSpec
|
||||
import net.fabricmc.loom.configuration.providers.mappings.utils.MavenFileSpec
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec
|
||||
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilderImpl
|
||||
|
@ -106,6 +107,20 @@ class LayeredMappingSpecBuilderTest extends Specification {
|
|||
parchment.removePrefix() == false
|
||||
}
|
||||
|
||||
def "yarn through file mappings"() {
|
||||
when:
|
||||
def spec = layered {
|
||||
mappings("net.fabricmc:yarn:1.18.1+build.1:v2")
|
||||
}
|
||||
def layers = spec.layers()
|
||||
then:
|
||||
spec.version == "layered+hash.1284206205"
|
||||
layers.size() == 2
|
||||
layers[0].class == IntermediaryMappingsSpec
|
||||
layers[1].class == FileMappingsSpec
|
||||
((layers[1] as FileMappingsSpec).fileSpec() as MavenFileSpec).dependencyNotation() == "net.fabricmc:yarn:1.18.1+build.1:v2"
|
||||
}
|
||||
|
||||
LayeredMappingSpec layered(@DelegatesTo(LayeredMappingSpecBuilderImpl) Closure cl) {
|
||||
LayeredMappingSpecBuilderImpl builder = new LayeredMappingSpecBuilderImpl()
|
||||
new ClosureAction(cl).execute(builder)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 FabricMC
|
||||
* Copyright (c) 2021-2022 FabricMC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -44,4 +44,5 @@ interface LayeredMappingsTestConstants {
|
|||
|
||||
public static final String PARCHMENT_NOTATION = "org.parchmentmc.data:parchment-1.16.5:20210608-SNAPSHOT@zip"
|
||||
public static final String PARCHMENT_URL = "https://maven.parchmentmc.net/org/parchmentmc/data/parchment-1.16.5/20210608-SNAPSHOT/parchment-1.16.5-20210608-SNAPSHOT.zip"
|
||||
public static final String YARN_1_17_URL = "https://maven.fabricmc.net/net/fabricmc/yarn/1.17%2Bbuild.13/yarn-1.17%2Bbuild.13-v2.jar"
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue