Skip to content

Commit 14fa9f4

Browse files
committed
Preserve libraries order to improve reproducibility
1 parent d02734f commit 14fa9f4

File tree

8 files changed

+88
-81
lines changed

8 files changed

+88
-81
lines changed

src/main/java/org/spongepowered/gradle/vanilla/internal/bundler/BundlerMetadata.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,11 @@
3131
import java.io.InputStreamReader;
3232
import java.nio.charset.StandardCharsets;
3333
import java.nio.file.Path;
34+
import java.util.List;
3435
import java.util.Optional;
35-
import java.util.Set;
3636
import java.util.jar.JarEntry;
3737
import java.util.jar.JarFile;
3838
import java.util.jar.Manifest;
39-
import java.util.stream.Collectors;
4039
import java.util.stream.Stream;
4140

4241
/**
@@ -47,7 +46,7 @@
4746
* @param server A bundle element describing the server itself.
4847
* @param mainClass The main class to execute.
4948
*/
50-
public record BundlerMetadata(FormatVersion version, Set<BundleElement> libraries, BundleElement server, @Nullable String mainClass) {
49+
public record BundlerMetadata(FormatVersion version, List<BundleElement> libraries, BundleElement server, @Nullable String mainClass) {
5150

5251
private static final String MAIN_CLASS = "META-INF/main-class";
5352

@@ -99,9 +98,9 @@ public static Optional<BundlerMetadata> read(final JarFile file) throws IOExcept
9998
}
10099

101100
// libraries list
102-
final Set<BundleElement> libraries;
101+
final List<BundleElement> libraries;
103102
try (final Stream<BundleElement> elements = BundlerMetadata.readIndex(file, "libraries")) {
104-
libraries = elements.collect(Collectors.toUnmodifiableSet());
103+
libraries = elements.toList();
105104
}
106105

107106
// main class

src/main/java/org/spongepowered/gradle/vanilla/internal/repository/IvyModuleWriter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@
3838
import java.nio.file.Path;
3939
import java.util.Collection;
4040
import java.util.Collections;
41-
import java.util.HashSet;
41+
import java.util.LinkedHashSet;
4242
import java.util.Objects;
43+
import java.util.SequencedSet;
4344
import java.util.Set;
4445

4546
import javax.xml.XMLConstants;
@@ -69,7 +70,7 @@ public final class IvyModuleWriter implements AutoCloseable {
6970
private final boolean managedOutput;
7071
private final Writer output;
7172
private final XMLStreamWriter writer;
72-
private final Set<GroupArtifactVersion> dependencies = new HashSet<>();
73+
private final SequencedSet<GroupArtifactVersion> dependencies = new LinkedHashSet<>();
7374
private @Nullable String artifactId;
7475

7576
public IvyModuleWriter(final Writer output) throws XMLStreamException {

src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolver.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
import java.net.URLClassLoader;
3737
import java.nio.file.Path;
38+
import java.util.SequencedSet;
3839
import java.util.Set;
3940
import java.util.concurrent.CompletableFuture;
4041
import java.util.concurrent.ExecutionException;
@@ -143,7 +144,7 @@ interface MinecraftEnvironment {
143144
*
144145
* @return the dependencies
145146
*/
146-
Set<GroupArtifactVersion> dependencies();
147+
SequencedSet<GroupArtifactVersion> dependencies();
147148

148149
/**
149150
* The Mojang-provided metadata for a certain Minecraft environment.

src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftResolverImpl.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@
5858
import java.nio.file.Path;
5959
import java.util.Arrays;
6060
import java.util.Collections;
61-
import java.util.HashSet;
61+
import java.util.LinkedHashSet;
62+
import java.util.SequencedSet;
6263
import java.util.Set;
6364
import java.util.concurrent.BlockingQueue;
6465
import java.util.concurrent.CompletableFuture;
@@ -172,7 +173,7 @@ CompletableFuture<ResolutionResult<MinecraftEnvironment>> provide(final Minecraf
172173
} else {
173174
MinecraftResolverImpl.LOGGER.info("No bundler metadata found in jar {}", jar.get());
174175
}
175-
final Supplier<Set<GroupArtifactVersion>> dependencies = () -> side.dependencies(descriptor, bundlerMeta);
176+
final Supplier<SequencedSet<GroupArtifactVersion>> dependencies = () -> side.dependencies(descriptor, bundlerMeta);
176177
if (!this.forceRefresh && jar.upToDate() && outputExists) {
177178
// Our inputs are up-to-date, and the output exists, so we can assume (for now) that the output is up-to-date
178179
// Check meta here too, before returning
@@ -226,7 +227,7 @@ CompletableFuture<ResolutionResult<MinecraftEnvironment>> provideJoined(
226227
}
227228
final VersionDescriptor.Full descriptor = potentialDescriptor.get();
228229
final boolean outputExists = Files.isRegularFile(outputJar);
229-
final Supplier<Set<GroupArtifactVersion>> dependencies = () -> MinecraftResolverImpl.mergedDependencies(client.get(), server.get());
230+
final Supplier<SequencedSet<GroupArtifactVersion>> dependencies = () -> MinecraftResolverImpl.mergedDependencies(client.get(), server.get());
230231
if (!this.forceRefresh && client.upToDate() && server.upToDate() && outputExists) {
231232
// We're up-to-date, give meta a poke and then return without re-executing the jar merge
232233
this.writeMetaIfNecessary(
@@ -256,11 +257,11 @@ CompletableFuture<ResolutionResult<MinecraftEnvironment>> provideJoined(
256257
});
257258
}
258259

259-
private static Set<GroupArtifactVersion> mergedDependencies(final MinecraftEnvironment client, final MinecraftEnvironment server) {
260-
final Set<GroupArtifactVersion> deps = new HashSet<>();
260+
private static SequencedSet<GroupArtifactVersion> mergedDependencies(final MinecraftEnvironment client, final MinecraftEnvironment server) {
261+
final SequencedSet<GroupArtifactVersion> deps = new LinkedHashSet<>();
261262
deps.addAll(client.dependencies());
262263
deps.addAll(server.dependencies());
263-
return Collections.unmodifiableSet(deps);
264+
return Collections.unmodifiableSequencedSet(deps);
264265
}
265266

266267
/**
@@ -576,7 +577,7 @@ private String artifactFileName(
576577
private void writeMetaIfNecessary(
577578
final MinecraftPlatform platform,
578579
final ResolutionResult<VersionDescriptor.Full> version,
579-
final Supplier<Set<GroupArtifactVersion>> dependencies,
580+
final Supplier<SequencedSet<GroupArtifactVersion>> dependencies,
580581
final Path baseDir
581582
) throws IOException, XMLStreamException {
582583
this.writeMetaIfNecessary(
@@ -592,7 +593,7 @@ private void writeMetaIfNecessary(
592593
final MinecraftPlatform platform,
593594
final String artifactIdOverride,
594595
final ResolutionResult<VersionDescriptor.Full> version,
595-
final Supplier<Set<GroupArtifactVersion>> dependencies,
596+
final Supplier<SequencedSet<GroupArtifactVersion>> dependencies,
596597
final Path baseDir
597598
) throws IOException, XMLStreamException {
598599
if (!version.isPresent()) {
@@ -624,10 +625,10 @@ static final class MinecraftEnvironmentImpl implements MinecraftEnvironment {
624625

625626
private final String decoratedArtifactId;
626627
private final Path jar;
627-
private final Supplier<Set<GroupArtifactVersion>> dependencies;
628+
private final Supplier<SequencedSet<GroupArtifactVersion>> dependencies;
628629
private final VersionDescriptor.Full metadata;
629630

630-
MinecraftEnvironmentImpl(final String decoratedArtifactId, final Path jar, final Supplier<Set<GroupArtifactVersion>> dependencies, final VersionDescriptor.Full metadata) {
631+
MinecraftEnvironmentImpl(final String decoratedArtifactId, final Path jar, final Supplier<SequencedSet<GroupArtifactVersion>> dependencies, final VersionDescriptor.Full metadata) {
631632
this.decoratedArtifactId = decoratedArtifactId;
632633
this.jar = jar;
633634
this.dependencies = FunctionalUtils.memoizeSupplier(dependencies);
@@ -645,7 +646,7 @@ public Path jar() {
645646
}
646647

647648
@Override
648-
public Set<GroupArtifactVersion> dependencies() {
649+
public SequencedSet<GroupArtifactVersion> dependencies() {
649650
return this.dependencies.get();
650651
}
651652

src/main/java/org/spongepowered/gradle/vanilla/repository/MinecraftSide.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
import java.nio.file.Path;
3939
import java.nio.file.StandardCopyOption;
4040
import java.util.Collections;
41-
import java.util.HashSet;
41+
import java.util.LinkedHashSet;
42+
import java.util.SequencedSet;
4243
import java.util.Set;
4344
import java.util.function.Predicate;
4445
import java.util.jar.JarEntry;
@@ -48,7 +49,7 @@
4849
public enum MinecraftSide {
4950
CLIENT(DownloadClassifier.CLIENT) {
5051
@Override
51-
public Set<GroupArtifactVersion> dependencies(
52+
public SequencedSet<GroupArtifactVersion> dependencies(
5253
final VersionDescriptor.Full descriptor,
5354
final @Nullable BundlerMetadata bundleMetadata
5455
) {
@@ -58,7 +59,7 @@ public Set<GroupArtifactVersion> dependencies(
5859
},
5960
SERVER(DownloadClassifier.SERVER) {
6061
@Override
61-
public Set<GroupArtifactVersion> dependencies(
62+
public SequencedSet<GroupArtifactVersion> dependencies(
6263
final VersionDescriptor.Full descriptor,
6364
final @Nullable BundlerMetadata metadata
6465
) {
@@ -73,9 +74,9 @@ public Set<GroupArtifactVersion> dependencies(
7374
);
7475
} else {
7576
// 21w39+
76-
return Collections.unmodifiableSet(metadata.libraries().stream()
77+
return Collections.unmodifiableSequencedSet(metadata.libraries().stream()
7778
.map(el -> GroupArtifactVersion.parse(el.id()))
78-
.collect(Collectors.toSet()));
79+
.collect(Collectors.<GroupArtifactVersion, SequencedSet<GroupArtifactVersion>>toCollection(LinkedHashSet::new)));
7980
}
8081
}
8182

@@ -107,7 +108,7 @@ public final DownloadClassifier executableArtifact() {
107108
return this.executableArtifact;
108109
}
109110

110-
public abstract Set<GroupArtifactVersion> dependencies(
111+
public abstract SequencedSet<GroupArtifactVersion> dependencies(
111112
final VersionDescriptor.Full descriptor,
112113
final @Nullable BundlerMetadata bundleMetadata
113114
);
@@ -141,18 +142,18 @@ public Set<String> allowedPackages() {
141142
return Collections.emptySet();
142143
}
143144

144-
private static Set<GroupArtifactVersion> manifestLibraries(
145+
private static SequencedSet<GroupArtifactVersion> manifestLibraries(
145146
final VersionDescriptor.Full manifest,
146147
final RuleContext rules,
147148
final Predicate<Library> filter
148149
) {
149-
final Set<GroupArtifactVersion> ret = new HashSet<>();
150+
final SequencedSet<GroupArtifactVersion> ret = new LinkedHashSet<>();
150151
for (final Library library : manifest.libraries()) {
151152
if (library.rules().test(rules) && filter.test(library)) {
152153
ret.add(library.name());
153154
}
154155
}
155-
return Collections.unmodifiableSet(ret);
156+
return Collections.unmodifiableSequencedSet(ret);
156157
}
157158

158159
}

src/test/java/org/spongepowered/gradle/vanilla/repository/IvyModuleWriterTest.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@
4545
import java.util.Collections;
4646
import java.util.LinkedHashSet;
4747
import java.util.List;
48-
import java.util.Set;
48+
import java.util.SequencedSet;
4949
import java.util.function.Predicate;
5050
import java.util.regex.Pattern;
51-
import java.util.stream.Collectors;
5251

5352
import javax.xml.stream.XMLStreamException;
5453

@@ -79,7 +78,7 @@ void testWriteVersionWithoutJavaVersion() throws IOException, XMLStreamException
7978

8079
Assertions.assertLinesMatch(
8180
IvyModuleWriterTest.readLinesFromResource("expected-ivy-1.16.5.xml"),
82-
IvyModuleWriterTest.NEWLINE.splitAsStream(writer.getBuffer()).collect(Collectors.toList())
81+
IvyModuleWriterTest.NEWLINE.splitAsStream(writer.getBuffer()).toList()
8382
);
8483
}
8584

@@ -94,20 +93,25 @@ void testWriteVersionWithJavaVersion() throws IOException, XMLStreamException {
9493
.dependencies(IvyModuleWriterTest.manifestLibraries(version, IvyModuleWriterTest.TEST_CONTEXT, lib -> !lib.isNatives()))
9594
.write(version, MinecraftPlatform.JOINED);
9695
}
96+
97+
Assertions.assertLinesMatch(
98+
IvyModuleWriterTest.readLinesFromResource("expected-ivy-21w15a.xml"),
99+
IvyModuleWriterTest.NEWLINE.splitAsStream(writer.getBuffer()).toList()
100+
);
97101
}
98102

99-
private static Set<GroupArtifactVersion> manifestLibraries(
103+
private static SequencedSet<GroupArtifactVersion> manifestLibraries(
100104
final VersionDescriptor.Full manifest,
101105
final RuleContext rules,
102106
final Predicate<Library> filter
103107
) {
104-
final Set<GroupArtifactVersion> ret = new LinkedHashSet<>();
108+
final SequencedSet<GroupArtifactVersion> ret = new LinkedHashSet<>();
105109
for (final Library library : manifest.libraries()) {
106110
if (library.rules().test(rules) && filter.test(library)) {
107111
ret.add(library.name());
108112
}
109113
}
110-
return Collections.unmodifiableSet(ret);
114+
return Collections.unmodifiableSequencedSet(ret);
111115
}
112116

113117
private static List<String> readLinesFromResource(final String resource) throws IOException {

src/test/resources/org/spongepowered/gradle/vanilla/repository/expected-ivy-1.16.5.xml

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,38 @@
77
</vanillagradle:mojangStatus>
88
</info>
99
<dependencies>
10+
<dependency org="com.mojang" name="patchy" rev="1.1" transitive="false"/>
1011
<dependency org="oshi-project" name="oshi-core" rev="1.1" transitive="false"/>
11-
<dependency org="net.java.jinput" name="jinput" rev="2.0.5" transitive="false"/>
12-
<dependency org="org.apache.logging.log4j" name="log4j-api" rev="2.8.1" transitive="false"/>
13-
<dependency org="com.mojang" name="text2speech" rev="1.11.3" transitive="false"/>
1412
<dependency org="net.java.dev.jna" name="jna" rev="4.4.0" transitive="false"/>
15-
<dependency org="org.lwjgl" name="lwjgl-tinyfd" rev="3.2.2" transitive="false"/>
16-
<dependency org="io.netty" name="netty-all" rev="4.1.25.Final" transitive="false"/>
13+
<dependency org="net.java.dev.jna" name="platform" rev="3.4.0" transitive="false"/>
1714
<dependency org="com.ibm.icu" name="icu4j" rev="66.1" transitive="false"/>
18-
<dependency org="org.lwjgl" name="lwjgl-glfw" rev="3.2.2" transitive="false"/>
19-
<dependency org="org.lwjgl" name="lwjgl" rev="3.2.2" transitive="false"/>
20-
<dependency org="org.apache.logging.log4j" name="log4j-core" rev="2.8.1" transitive="false"/>
21-
<dependency org="com.mojang" name="brigadier" rev="1.0.17" transitive="false"/>
22-
<dependency org="org.apache.httpcomponents" name="httpcore" rev="4.3.2" transitive="false"/>
23-
<dependency org="org.apache.commons" name="commons-lang3" rev="3.5" transitive="false"/>
24-
<dependency org="org.apache.httpcomponents" name="httpclient" rev="4.3.3" transitive="false"/>
25-
<dependency org="commons-codec" name="commons-codec" rev="1.10" transitive="false"/>
15+
<dependency org="com.mojang" name="javabridge" rev="1.0.22" transitive="false"/>
2616
<dependency org="net.sf.jopt-simple" name="jopt-simple" rev="5.0.3" transitive="false"/>
27-
<dependency org="net.java.dev.jna" name="platform" rev="3.4.0" transitive="false"/>
28-
<dependency org="it.unimi.dsi" name="fastutil" rev="8.2.1" transitive="false"/>
29-
<dependency org="com.google.code.gson" name="gson" rev="2.8.0" transitive="false"/>
17+
<dependency org="io.netty" name="netty-all" rev="4.1.25.Final" transitive="false"/>
18+
<dependency org="com.google.guava" name="guava" rev="21.0" transitive="false"/>
19+
<dependency org="org.apache.commons" name="commons-lang3" rev="3.5" transitive="false"/>
3020
<dependency org="commons-io" name="commons-io" rev="2.5" transitive="false"/>
21+
<dependency org="commons-codec" name="commons-codec" rev="1.10" transitive="false"/>
22+
<dependency org="net.java.jinput" name="jinput" rev="2.0.5" transitive="false"/>
23+
<dependency org="net.java.jutils" name="jutils" rev="1.0.0" transitive="false"/>
24+
<dependency org="com.mojang" name="brigadier" rev="1.0.17" transitive="false"/>
3125
<dependency org="com.mojang" name="datafixerupper" rev="4.0.26" transitive="false"/>
32-
<dependency org="org.lwjgl" name="lwjgl-jemalloc" rev="3.2.2" transitive="false"/>
33-
<dependency org="com.google.guava" name="guava" rev="21.0" transitive="false"/>
26+
<dependency org="com.google.code.gson" name="gson" rev="2.8.0" transitive="false"/>
3427
<dependency org="com.mojang" name="authlib" rev="2.1.28" transitive="false"/>
35-
<dependency org="com.mojang" name="patchy" rev="1.1" transitive="false"/>
36-
<dependency org="org.lwjgl" name="lwjgl-openal" rev="3.2.2" transitive="false"/>
37-
<dependency org="net.java.jutils" name="jutils" rev="1.0.0" transitive="false"/>
38-
<dependency org="com.mojang" name="javabridge" rev="1.0.22" transitive="false"/>
39-
<dependency org="org.lwjgl" name="lwjgl-stb" rev="3.2.2" transitive="false"/>
4028
<dependency org="org.apache.commons" name="commons-compress" rev="1.8.1" transitive="false"/>
29+
<dependency org="org.apache.httpcomponents" name="httpclient" rev="4.3.3" transitive="false"/>
4130
<dependency org="commons-logging" name="commons-logging" rev="1.1.3" transitive="false"/>
31+
<dependency org="org.apache.httpcomponents" name="httpcore" rev="4.3.2" transitive="false"/>
32+
<dependency org="it.unimi.dsi" name="fastutil" rev="8.2.1" transitive="false"/>
33+
<dependency org="org.apache.logging.log4j" name="log4j-api" rev="2.8.1" transitive="false"/>
34+
<dependency org="org.apache.logging.log4j" name="log4j-core" rev="2.8.1" transitive="false"/>
35+
<dependency org="org.lwjgl" name="lwjgl" rev="3.2.2" transitive="false"/>
36+
<dependency org="org.lwjgl" name="lwjgl-jemalloc" rev="3.2.2" transitive="false"/>
37+
<dependency org="org.lwjgl" name="lwjgl-openal" rev="3.2.2" transitive="false"/>
4238
<dependency org="org.lwjgl" name="lwjgl-opengl" rev="3.2.2" transitive="false"/>
39+
<dependency org="org.lwjgl" name="lwjgl-glfw" rev="3.2.2" transitive="false"/>
40+
<dependency org="org.lwjgl" name="lwjgl-stb" rev="3.2.2" transitive="false"/>
41+
<dependency org="org.lwjgl" name="lwjgl-tinyfd" rev="3.2.2" transitive="false"/>
42+
<dependency org="com.mojang" name="text2speech" rev="1.11.3" transitive="false"/>
4343
</dependencies>
4444
</ivy-module>

0 commit comments

Comments
 (0)