baritone/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java

207 lines
7.8 KiB
Java
Raw Normal View History

/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
2018-10-13 02:21:16 +00:00
package baritone.gradle.task;
import baritone.gradle.util.Determinizer;
import org.apache.commons.io.IOUtils;
2019-03-15 23:11:14 +00:00
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.TaskAction;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
2019-03-15 23:11:14 +00:00
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
/**
* @author Brady
* @since 10/11/2018
*/
2018-10-13 02:21:16 +00:00
public class ProguardTask extends BaritoneGradleTask {
@Input
private String url;
@Input
private String extract;
@TaskAction
2018-10-13 19:28:20 +00:00
protected void exec() throws Exception {
2018-10-13 02:21:16 +00:00
super.verifyArtifacts();
// "Haha brady why don't you make separate tasks"
processArtifact();
downloadProguard();
extractProguard();
generateConfigs();
if (getProject().hasProperty("baritone.forge_build")) {
proguardApi(this.artifactForgeApiPath.toString());
} else {
proguardApi(this.artifactApiPath.toString());
proguardStandalone(this.artifactStandalonePath.toString());
}
cleanup();
}
private void processArtifact() throws Exception {
if (Files.exists(this.artifactUnoptimizedPath)) {
Files.delete(this.artifactUnoptimizedPath);
}
2019-03-15 23:11:14 +00:00
Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString());
}
private void downloadProguard() throws Exception {
Path proguardZip = getTemporaryFile(PROGUARD_ZIP);
if (!Files.exists(proguardZip)) {
write(new URL(this.url).openStream(), proguardZip);
}
}
private void extractProguard() throws Exception {
Path proguardJar = getTemporaryFile(PROGUARD_JAR);
if (!Files.exists(proguardJar)) {
ZipFile zipFile = new ZipFile(getTemporaryFile(PROGUARD_ZIP).toFile());
ZipEntry zipJarEntry = zipFile.getEntry(this.extract);
write(zipFile.getInputStream(zipJarEntry), proguardJar);
zipFile.close();
}
}
private void generateConfigs() throws Exception {
Files.copy(getRelativeFile(PROGUARD_CONFIG_TEMPLATE), getTemporaryFile(PROGUARD_CONFIG_DEST), REPLACE_EXISTING);
// Setup the template that will be used to derive the API and Standalone configs
List<String> template = Files.readAllLines(getTemporaryFile(PROGUARD_CONFIG_DEST));
template.add(0, "-injars " + this.artifactPath.toString());
template.add(1, "-outjars " + this.getTemporaryFile(PROGUARD_EXPORT_PATH));
// Acquire the RT jar using "java -verbose". This doesn't work on Java 9+
Process p = new ProcessBuilder("java", "-verbose").start();
String out = IOUtils.toString(p.getInputStream(), "UTF-8").split("\n")[0].split("Opened ")[1].replace("]", "");
template.add(2, "-libraryjars '" + out + "'");
{
final Stream<File> libraries;
{
// Discover all of the libraries that we will need to acquire from gradle
final Stream<File> dependencies = acquireDependencies()
// remove MCP mapped jar
.filter(f -> !f.toString().endsWith("-recomp.jar"))
// go from the extra to the original downloaded client
.map(f -> f.toString().endsWith("client-extra.jar") ? new File(f.getParentFile(), "client.jar") : f);
if (getProject().hasProperty("baritone.forge_build")) {
libraries = dependencies
.map(f -> f.toString().endsWith("client.jar") ? getSrgMcJar() : f);
} else {
libraries = dependencies;
}
2019-03-15 23:11:14 +00:00
}
libraries.forEach(f -> {
template.add(2, "-libraryjars '" + f + "'");
});
}
2019-03-15 23:11:14 +00:00
// API config doesn't require any changes from the changes that we made to the template
Files.write(getTemporaryFile(PROGUARD_API_CONFIG), template);
// For the Standalone config, don't keep the API package
List<String> standalone = new ArrayList<>(template);
standalone.removeIf(s -> s.contains("# this is the keep api"));
Files.write(getTemporaryFile(PROGUARD_STANDALONE_CONFIG), standalone);
}
private File getSrgMcJar() {
return getProject().getTasks().findByName("copyMcJar").getOutputs().getFiles().getSingleFile();
}
2019-03-15 23:11:14 +00:00
private Stream<File> acquireDependencies() {
return getProject().getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().findByName("launch").getRuntimeClasspath().getFiles()
.stream()
.filter(File::isFile);
//.peek(f -> System.out.println("xd: " + f));
}
private void proguardApi(String artifact) throws Exception {
runProguard(getTemporaryFile(PROGUARD_API_CONFIG));
Determinizer.determinize(this.proguardOut.toString(), artifact);
}
private void proguardStandalone(String artifact) throws Exception {
runProguard(getTemporaryFile(PROGUARD_STANDALONE_CONFIG));
Determinizer.determinize(this.proguardOut.toString(), artifact);
}
private void cleanup() {
try {
Files.delete(this.proguardOut);
} catch (IOException ignored) {}
}
public void setUrl(String url) {
this.url = url;
}
public void setExtract(String extract) {
this.extract = extract;
}
private void runProguard(Path config) throws Exception {
// Delete the existing proguard output file. Proguard probably handles this already, but why not do it ourselves
if (Files.exists(this.proguardOut)) {
Files.delete(this.proguardOut);
}
Path proguardJar = getTemporaryFile(PROGUARD_JAR);
Process p = new ProcessBuilder("java", "-jar", proguardJar.toString(), "@" + config.toString())
2018-10-13 02:21:16 +00:00
.directory(getTemporaryFile("").toFile()) // Set the working directory to the temporary folder]
.start();
2018-10-13 02:21:16 +00:00
// We can't do output inherit process I/O with gradle for some reason and have it work, so we have to do this
2019-02-04 03:27:28 +00:00
this.printOutputLog(p.getInputStream(), System.out);
this.printOutputLog(p.getErrorStream(), System.err);
2018-10-13 02:21:16 +00:00
// Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception
2018-10-13 04:19:11 +00:00
int exitCode = p.waitFor();
if (exitCode != 0) {
2018-10-27 21:41:25 +00:00
throw new IllegalStateException("Proguard exited with code " + exitCode);
}
}
2019-02-04 03:27:28 +00:00
private void printOutputLog(InputStream stream, PrintStream outerr) {
2018-10-13 02:21:16 +00:00
new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
String line;
while ((line = reader.readLine()) != null) {
2019-02-04 03:27:28 +00:00
outerr.println(line);
2018-10-13 02:21:16 +00:00
}
2018-12-01 18:45:58 +00:00
} catch (Exception e) {
2018-10-13 02:21:16 +00:00
e.printStackTrace();
}
}).start();
}
}