Skip to content

Commit f4d9c53

Browse files
committed
Add --stub flag to create stubbed jar files useful for public repos and CI builds.
Add bulk operations for net.minecraft artifacts. Add support for generating official named artifacts for versions that dont have MCPConfig data.
1 parent 550de64 commit f4d9c53

File tree

14 files changed

+530
-93
lines changed

14 files changed

+530
-93
lines changed

src/main/java/net/minecraftforge/mcmaven/cli/MCPDataTask.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
import net.minecraftforge.mcmaven.impl.cache.Cache;
1414
import net.minecraftforge.mcmaven.impl.mappings.Mappings;
1515
import net.minecraftforge.mcmaven.impl.mappings.ParchmentMappings;
16+
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCP;
1617
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCPConfigRepo;
18+
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MinecraftTasks;
1719
import net.minecraftforge.mcmaven.impl.util.Artifact;
1820
import net.minecraftforge.srgutils.IMappingFile;
1921
import net.minecraftforge.srgutils.IRenamer;
@@ -101,7 +103,7 @@ private static int runI(String[] args) throws Exception {
101103

102104
var artifact =
103105
options.has(artifactO) ? Artifact.from(options.valueOf(artifactO)) :
104-
options.has(versionO) ? Artifact.from("de.oceanlabs.mcp", "mcp_config", options.valueOf(versionO), null, "zip") :
106+
options.has(versionO) ? MCP.artifact(options.valueOf(versionO)) :
105107
null;
106108

107109
if (artifact == null) {
@@ -159,8 +161,8 @@ else if (options.has(parchmentO))
159161

160162
if (mcp.getConfig().official) {
161163
var mc = mcp.getMinecraftTasks();
162-
var client = mc.versionFile("client_mappings", "txt");
163-
var server = mc.versionFile("server_mappings", "txt");
164+
var client = mc.versionFile(MinecraftTasks.Files.CLIENT_MAPPINGS);
165+
var server = mc.versionFile(MinecraftTasks.Files.SERVER_MAPPINGS);
164166

165167
var obf2OffClient = IMappingFile.load(client.execute());
166168
var obf2OffServer = IMappingFile.load(server.execute());

src/main/java/net/minecraftforge/mcmaven/cli/MCPTask.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@
66

77
import java.io.File;
88
import java.io.IOException;
9-
import java.nio.file.Files;
10-
119
import joptsimple.OptionParser;
1210
import net.minecraftforge.mcmaven.impl.MinecraftMaven;
1311
import net.minecraftforge.mcmaven.impl.cache.Cache;
1412
import net.minecraftforge.mcmaven.impl.data.MCPSetupFiles;
1513
import net.minecraftforge.mcmaven.impl.mappings.Mappings;
1614
import net.minecraftforge.mcmaven.impl.mappings.ParchmentMappings;
1715
import net.minecraftforge.mcmaven.impl.repo.forge.Patcher;
16+
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCP;
1817
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCPConfigRepo;
1918
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCPTaskFactory;
2019
import net.minecraftforge.mcmaven.impl.tasks.RenameTask;
@@ -116,7 +115,7 @@ public static void run(String[] args) throws Exception {
116115

117116
var artifact =
118117
options.has(artifactO) ? Artifact.from(options.valueOf(artifactO)) :
119-
options.has(versionO) ? Artifact.from("de.oceanlabs.mcp", "mcp_config", options.valueOf(versionO), null, "zip") :
118+
options.has(versionO) ? MCP.artifact(options.valueOf(versionO)) :
120119
null;
121120

122121
var pipeline = options.valueOf(pipelineO);

src/main/java/net/minecraftforge/mcmaven/cli/MavenTask.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ static void run(String[] args) throws Exception {
9191
var disableGradleO = parser.accepts("disable-gradle",
9292
"Disabels the gradle module file, and writes all mappings to the main artifact files.");
9393

94+
var stubO = parser.accepts("stub",
95+
"Runs any generated jar through a stub tool, deleteing data files and stubing all class files. The resulting jar can be compiled against but is non-functional.");
96+
9497
var shorthandOptions = new HashMap<String, OptionSpecBuilder>();
9598
var artifacts = Map.of(
9699
"forge", Constants.FORGE_ARTIFACT,
@@ -162,7 +165,7 @@ static void run(String[] args) throws Exception {
162165
}
163166

164167
var mcmaven = new MinecraftMaven(output, options.has(dependenciesOnlyO), cache, jdkCache, mappings,
165-
foreignRepositories, options.has(globalAuxiliaryVariantsO), options.has(disableGradleO));
168+
foreignRepositories, options.has(globalAuxiliaryVariantsO), options.has(disableGradleO), options.has(stubO));
166169
mcmaven.run(artifact);
167170
}
168171
}

src/main/java/net/minecraftforge/mcmaven/impl/MinecraftMaven.java

Lines changed: 159 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,18 @@
88
import net.minecraftforge.mcmaven.impl.data.GradleModule;
99
import net.minecraftforge.mcmaven.impl.mappings.Mappings;
1010
import net.minecraftforge.mcmaven.impl.repo.Repo;
11+
import net.minecraftforge.mcmaven.impl.repo.Repo.PendingArtifact;
1112
import net.minecraftforge.mcmaven.impl.repo.forge.FGVersion;
1213
import net.minecraftforge.mcmaven.impl.repo.forge.ForgeRepo;
14+
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCP;
1315
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCPConfigRepo;
16+
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MinecraftTasks;
1417
import net.minecraftforge.mcmaven.impl.util.Artifact;
1518
import net.minecraftforge.mcmaven.impl.util.ComparableVersion;
1619
import net.minecraftforge.mcmaven.impl.util.Constants;
1720
import net.minecraftforge.mcmaven.impl.util.POMBuilder;
18-
import net.minecraftforge.mcmaven.impl.util.Util;
21+
import net.minecraftforge.mcmaven.impl.util.ProcessUtils;
22+
import net.minecraftforge.srgutils.MinecraftVersion;
1923
import net.minecraftforge.util.data.json.JsonData;
2024
import net.minecraftforge.util.file.FileUtils;
2125
import net.minecraftforge.util.hash.HashStore;
@@ -30,10 +34,12 @@
3034
import java.nio.charset.StandardCharsets;
3135
import java.util.ArrayList;
3236
import java.util.Arrays;
37+
import java.util.Collections;
3338
import java.util.HashMap;
3439
import java.util.HashSet;
3540
import java.util.List;
3641
import java.util.Map;
42+
import java.util.Set;
3743

3844
import javax.xml.parsers.DocumentBuilderFactory;
3945
import javax.xml.parsers.ParserConfigurationException;
@@ -57,13 +63,17 @@ public record MinecraftMaven(
5763
Mappings mappings,
5864
Map<String, String> foreignRepositories,
5965
boolean globalAuxiliaryVariants,
60-
boolean disableGradle
66+
boolean disableGradle,
67+
boolean stubJars,
68+
Set<String> mcpConfigVersions
6169
) {
62-
private static final ComparableVersion MIN_SUPPORTED_FORGE = new ComparableVersion("1.14.4"); // Only 1.14.4+ has official mappings, we can support more when we add more mappings
70+
// Only 1.14.4+ has official mappings, we can support more when we add more mappings
71+
private static final MinecraftVersion MIN_OFFICIAL_MAPPINGS = MinecraftVersion.from("1.14.4");
72+
private static final ComparableVersion MIN_SUPPORTED_FORGE = new ComparableVersion("1.14.4");
6373

6474
public MinecraftMaven(File output, boolean dependenciesOnly, File cacheRoot, File jdkCacheRoot, Mappings mappings,
65-
Map<String, String> foreignRepositories, boolean globalAuxiliaryVariants, boolean disableGradle) {
66-
this(output, dependenciesOnly, new Cache(cacheRoot, jdkCacheRoot, foreignRepositories), mappings, foreignRepositories, globalAuxiliaryVariants, disableGradle);
75+
Map<String, String> foreignRepositories, boolean globalAuxiliaryVariants, boolean disableGradle, boolean stubJars) {
76+
this(output, dependenciesOnly, new Cache(cacheRoot, jdkCacheRoot, foreignRepositories), mappings, foreignRepositories, globalAuxiliaryVariants, disableGradle, stubJars, new HashSet<>());
6777
}
6878

6979
public MinecraftMaven {
@@ -78,6 +88,7 @@ public MinecraftMaven(File output, boolean dependenciesOnly, File cacheRoot, Fil
7888
LOGGER.info(" Foreign Repos: [" + String.join(", ", foreignRepositories.values()) + ']');
7989
LOGGER.info(" GradleVariantHack: " + globalAuxiliaryVariants);
8090
LOGGER.info(" Disable Gradle: " + disableGradle);
91+
LOGGER.info(" Stub Jars: " + stubJars);
8192
LOGGER.info();
8293
}
8394

@@ -86,49 +97,118 @@ public void run(Artifact artifact) {
8697
var version = artifact.getVersion();
8798
LOGGER.info("Processing Minecraft dependency: %s:%s".formatted(module, version));
8899
var mcprepo = new MCPConfigRepo(this.cache, dependenciesOnly);
89-
90100
if (Constants.FORGE_GROUP.equals(artifact.getGroup()) && Constants.FORGE_NAME.equals(artifact.getName())) {
91-
if (dependenciesOnly)
92-
throw new IllegalArgumentException("ForgeRepo doesn't currently support dependenciesOnly");
93-
94101
var repo = new ForgeRepo(this.cache, mcprepo);
95-
if (artifact.getVersion() == null)
96-
throw new IllegalArgumentException("No version specified for Forge");
97-
98-
if ("all".equals(version)) {
99-
var versions = this.cache.maven().getVersions(artifact);
100-
var mappingCache = new HashMap<String, Mappings>();
101-
for (var ver : versions.reversed()) {
102-
var cver = new ComparableVersion(ver);
103-
if (cver.compareTo(MIN_SUPPORTED_FORGE) < 0)
104-
continue;
102+
createForge(artifact, mcprepo, repo);
103+
} else if (Constants.MC_GROUP.equals(artifact.getGroup())) {
104+
createMinecraft(artifact, mcprepo);
105+
} else {
106+
throw new IllegalArgumentException("Artifact '%s' is currently Unsupported. Will add later".formatted(module));
107+
}
108+
}
109+
110+
protected void createForge(Artifact artifact, MCPConfigRepo mcprepo, ForgeRepo repo) {
111+
if (dependenciesOnly)
112+
throw new IllegalArgumentException("ForgeRepo doesn't currently support dependenciesOnly");
113+
114+
var version = artifact.getVersion();
115+
if (version == null)
116+
throw new IllegalArgumentException("No version specified for Forge");
117+
118+
if ("all".equals(version)) {
119+
var versions = this.cache.maven().getVersions(artifact);
120+
var mappingCache = new HashMap<String, Mappings>();
121+
for (var ver : versions.reversed()) {
122+
var cver = new ComparableVersion(ver);
123+
if (cver.compareTo(MIN_SUPPORTED_FORGE) < 0)
124+
continue;
125+
126+
var fg = FGVersion.fromForge(ver);
127+
if (fg == null || fg.ordinal() < FGVersion.v3.ordinal()) // Unsupported
128+
continue;
129+
130+
var mappings = mappingCache.computeIfAbsent(forgeToMcVersion(ver), this.mappings::withMCVersion);
131+
var art = artifact.withVersion(ver);
132+
var artifacts = repo.process(art, mappings);
133+
finalize(art, mappings, artifacts);
134+
}
135+
} else {
136+
var mappings = this.mappings.withMCVersion(forgeToMcVersion(version));
137+
var artifacts = repo.process(artifact, mappings);
138+
finalize(artifact, mappings, artifacts);
139+
}
140+
}
105141

106-
var fg = FGVersion.fromForge(ver);
107-
if (fg == null || fg.ordinal() < FGVersion.v3.ordinal()) // Unsupported
142+
protected void createMinecraft(Artifact artifact, MCPConfigRepo mcprepo) {
143+
if (artifact.getVersion() == null)
144+
throw new IllegalArgumentException("No version specified for MCPConfig");
145+
146+
var version = artifact.getVersion();
147+
if (version == null)
148+
throw new IllegalArgumentException("No version specified for Forge");
149+
150+
if ("all".equals(version)) {
151+
var manifestFile = mcprepo.getLauncherManifestTask().execute();
152+
var manifest = JsonData.launcherManifest(manifestFile);
153+
for (var ver : manifest.versions) {
154+
155+
try {
156+
var cver = MinecraftVersion.from(ver.id);
157+
if (cver.compareTo(MIN_OFFICIAL_MAPPINGS) < 0)
108158
continue;
159+
} catch (IllegalArgumentException e) {
160+
// Invalid/unknown version, so skip.
161+
continue;
162+
}
109163

110-
var mappings = mappingCache.computeIfAbsent(forgeToMcVersion(ver), this.mappings()::withMCVersion);
111-
var art = artifact.withVersion(ver);
112-
var artifacts = repo.process(art, mappings);
113-
finalize(art, mappings, artifacts);
164+
var versioned = artifact.withVersion(ver.id);
165+
// If there is no MCPConfig, then we just produce a official named jar
166+
List<PendingArtifact> artifacts = null;
167+
if (hasMcp(mcprepo, ver.id))
168+
artifacts = mcprepo.process(versioned, mappings.withMCVersion(ver.id));
169+
else if (mappings.channel().equals("official") && hasOfficialMappings(mcprepo, ver.id))
170+
artifacts = mcprepo.processWithoutMcp(versioned, mappings.withMCVersion(ver.id));
171+
else {
172+
LOGGER.info("Skipping " + versioned + " no mcp config");
173+
continue;
114174
}
115-
} else {
116-
var mappings = this.mappings().withMCVersion(forgeToMcVersion(version));
117-
var artifacts = repo.process(artifact, mappings);
118175
finalize(artifact, mappings, artifacts);
119176
}
120-
} else if (Constants.MC_GROUP.equals(artifact.getGroup())) {
121-
if (artifact.getVersion() == null)
122-
throw new IllegalArgumentException("No version specified for MCPConfig");
177+
} else {
178+
var mcVersion = mcpToMcVersion(version);
179+
var mappings = this.mappings.withMCVersion(mcVersion);
180+
181+
List<PendingArtifact> artifacts = null;
182+
if (hasMcp(mcprepo, version))
183+
artifacts = mcprepo.process(artifact, mappings);
184+
else if (mappings.channel().equals("official") && hasOfficialMappings(mcprepo, mcVersion))
185+
artifacts = mcprepo.processWithoutMcp(artifact, mappings);
186+
else
187+
throw new IllegalStateException("Can not process " + artifact + " as it does not have a MCPConfig ror official mappings");
123188

124-
var mappings = this.mappings().withMCVersion(mcpToMcVersion(version));
125-
var artifacts = mcprepo.process(artifact, mappings);
126189
finalize(artifact, mappings, artifacts);
127-
} else {
128-
throw new IllegalArgumentException("Artifact '%s' is currently Unsupported. Will add later".formatted(module));
129190
}
130191
}
131192

193+
// This is ugly, but there really isn't a good way to check if a file exists. DownlodUtils could probably use a 'exists' that HEAD's and returns false non 404
194+
private boolean hasMcp(MCPConfigRepo repo, String version) {
195+
if (this.mcpConfigVersions.isEmpty()) {
196+
var versions = repo.getCache().maven().getVersions(MCP.artifact("1.21.11"));
197+
this.mcpConfigVersions.addAll(versions);
198+
}
199+
return this.mcpConfigVersions.contains(version);
200+
}
201+
202+
// No official mappings, we can't do anything
203+
private static boolean hasOfficialMappings(MCPConfigRepo repo, String version) {
204+
var tasks = repo.getMCTasks(version);
205+
var versionF = tasks.versionJson.execute();
206+
var json = JsonData.minecraftVersion(versionF);
207+
208+
return json.getDownload(MinecraftTasks.Files.CLIENT_MAPPINGS.key) != null ||
209+
json.getDownload(MinecraftTasks.Files.SERVER_MAPPINGS.key) != null;
210+
}
211+
132212
private static String forgeToMcVersion(String version) {
133213
// Save for a few april-fools versions, Minecraft doesn't use _ in their version names.
134214
// So when Forge needs to reference a version of Minecraft that uses - in the name, it replaces
@@ -151,7 +231,7 @@ public static String mcpToMcVersion(String version) {
151231
return version.substring(0, idx);
152232
}
153233

154-
private void finalize(Artifact module, Mappings mappings, List<Repo.PendingArtifact> artifacts) {
234+
protected void finalize(Artifact module, Mappings mappings, List<Repo.PendingArtifact> artifacts) {
155235
var variants = new HashSet<Artifact>();
156236
for (var pending : artifacts) {
157237
if (pending == null)
@@ -161,6 +241,13 @@ private void finalize(Artifact module, Mappings mappings, List<Repo.PendingArtif
161241
// Simplest case would be different mapping channels.
162242
// I haven't added an opt-in for making artifacts that use mappings, so just assume any artifact with variants
163243
var artifact = pending.artifact();
244+
245+
if (stubJars && "jar".equals(artifact.getExtension())) {
246+
// No sources allowed in stub repos
247+
if ("sources".equals(artifact.getClassifier()))
248+
continue;
249+
}
250+
164251
String suffix = null;
165252
if (!disableGradle && pending.variants() != null && !mappings.isPrimary()) {
166253
// If we are not the primary mapping, but we haven't generated the primary mapping yet, do so.
@@ -214,6 +301,11 @@ private void finalize(Artifact module, Mappings mappings, List<Repo.PendingArtif
214301
}
215302

216303
private void updateFile(File target, File source, Artifact artifact) {
304+
if (stubJars && "jar".equals(artifact.getExtension())) {
305+
writeStub(target, source, artifact);
306+
return;
307+
}
308+
217309
var cache = HashStore.fromFile(target)
218310
.add("source", source);
219311

@@ -228,7 +320,6 @@ private void updateFile(File target, File source, Artifact artifact) {
228320
}
229321

230322
if (write) {
231-
// TODO: [MCMavenizer] Add --api argument to turn class artifacts to api-only targets for a public repo
232323
try {
233324
if (disableGradle && isPom) {
234325
makeNonGradlePom(source, target);
@@ -243,6 +334,37 @@ private void updateFile(File target, File source, Artifact artifact) {
243334
}
244335
}
245336

337+
private void writeStub(File target, File source, Artifact artifact) {
338+
var tool = this.cache.maven().download(Constants.STUBIFY);
339+
var cache = HashStore.fromFile(target)
340+
.add("tool", tool)
341+
.add("source", source);
342+
343+
if (target.exists() && cache.isSame())
344+
return;
345+
346+
File jdk;
347+
try {
348+
jdk = this.cache.jdks().get(Constants.STUBIFY_JAVA_VERSION);
349+
} catch (Exception e) {
350+
throw new IllegalStateException("Failed to find JDK for version " + Constants.STUBIFY_JAVA_VERSION, e);
351+
}
352+
353+
var log = new File(source.getAbsolutePath() + ".stubify.log");
354+
var ret = ProcessUtils.runJar(jdk, source.getParentFile(), log, tool, Collections.emptyList(),
355+
List.of("--input", source.getAbsolutePath(), "--output", target.getAbsolutePath())
356+
);
357+
if (ret.exitCode != 0)
358+
throw new IllegalStateException("Failed to stubify jar file (exit code " + ret.exitCode + "), See log: " + log.getAbsolutePath());
359+
360+
try {
361+
cache.save();
362+
HashUtils.updateHash(target);
363+
} catch (Throwable t) {
364+
throw new RuntimeException("Failed to generate artifact: %s".formatted(artifact), t);
365+
}
366+
}
367+
246368
private void updateVariants(Artifact artifact) {
247369
var root = new File(this.output, artifact.getFolder());
248370
var inputs = new ArrayList<File>();

src/main/java/net/minecraftforge/mcmaven/impl/mappings/Mappings.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import net.minecraftforge.mcmaven.impl.Mavenizer;
1717
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCPSide;
18+
import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MinecraftTasks;
1819
import net.minecraftforge.mcmaven.impl.util.Artifact;
1920
import net.minecraftforge.mcmaven.impl.util.Constants;
2021
import net.minecraftforge.mcmaven.impl.util.ProcessUtils;
@@ -141,8 +142,8 @@ public Task getCsvZip(MCPSide side) {
141142

142143
var mc = side.getMCP().getMinecraftTasks();
143144
var srg = side.getTasks().getMappings();
144-
var client = mc.versionFile("client_mappings", "txt");
145-
var server = mc.versionFile("server_mappings", "txt");
145+
var client = mc.versionFile(MinecraftTasks.Files.CLIENT_MAPPINGS);
146+
var server = mc.versionFile(MinecraftTasks.Files.SERVER_MAPPINGS);
146147
ret = Task.named("srg2names[" + this + ']',
147148
Task.deps(srg, client, server),
148149
() -> getMappings(side, srg, client, server)

0 commit comments

Comments
 (0)