Use jar processor ids to fix #432 (#444)

* Use jar processor ids to fix #432

* Use full hash string of jar processor ids
dev/0.11
Juuxel 2021-07-23 23:51:34 +03:00 committed by GitHub
parent 606046e719
commit 08a797c53b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 0 deletions

View File

@ -69,6 +69,11 @@ public class AccessWidenerJarProcessor implements JarProcessor {
this.project = project; this.project = project;
} }
@Override
public String getId() {
return "loom:access_widener";
}
@Override @Override
public void setup() { public void setup() {
LoomGradleExtension loomGradleExtension = LoomGradleExtension.get(project); LoomGradleExtension loomGradleExtension = LoomGradleExtension.get(project);

View File

@ -27,6 +27,18 @@ package net.fabricmc.loom.configuration.processors;
import java.io.File; import java.io.File;
public interface JarProcessor { public interface JarProcessor {
/**
* Returns a unique ID for this jar processor, containing all configuration details.
*
* <p>If the jar processor implementation class supports creating multiple jar processors with different effects,
* the needed configuration should also be included in this ID. Example: {@code path.to.MyJarProcessor#someOption}.
*
* @return the ID of this jar processor
*/
default String getId() {
return getClass().getName();
}
void setup(); void setup();
/** /**

View File

@ -25,9 +25,27 @@
package net.fabricmc.loom.configuration.processors; package net.fabricmc.loom.configuration.processors;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import com.google.common.hash.Hashing;
import com.google.common.io.CharSource;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.transform.StreamZipEntryTransformer;
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
public class JarProcessorManager { public class JarProcessorManager {
private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
private static final String JAR_PROCESSOR_HASH_ATTRIBUTE = "Loom-Jar-Processor-Hash";
private final List<JarProcessor> jarProcessors; private final List<JarProcessor> jarProcessors;
public JarProcessorManager(List<JarProcessor> jarProcessors) { public JarProcessorManager(List<JarProcessor> jarProcessors) {
@ -47,13 +65,56 @@ public class JarProcessorManager {
return true; return true;
} }
String jarProcessorHash = getJarProcessorHash();
try (JarFile jar = new JarFile(file)) {
Attributes attributes = jar.getManifest().getMainAttributes();
if (!jarProcessorHash.equals(attributes.getValue(JAR_PROCESSOR_HASH_ATTRIBUTE))) {
return true;
}
} catch (IOException e) {
throw new UncheckedIOException("Could not check jar manifest of " + file, e);
}
return jarProcessors.stream().anyMatch(jarProcessor -> jarProcessor.isInvalid(file)); return jarProcessors.stream().anyMatch(jarProcessor -> jarProcessor.isInvalid(file));
} }
private String getJarProcessorHash() {
String jarProcessorIds = jarProcessors.stream()
.map(JarProcessor::getId)
.sorted()
.collect(Collectors.joining(";"));
try {
return CharSource.wrap(jarProcessorIds)
.asByteSource(StandardCharsets.UTF_8)
.hash(Hashing.sha256())
.toString();
} catch (IOException e) {
throw new UncheckedIOException("Could not hash jar processor IDs", e);
}
}
public void process(File file) { public void process(File file) {
for (JarProcessor jarProcessor : jarProcessors) { for (JarProcessor jarProcessor : jarProcessors) {
jarProcessor.process(file); jarProcessor.process(file);
} }
boolean manifestTransformed = ZipUtil.transformEntries(file, new ZipEntryTransformerEntry[] {
new ZipEntryTransformerEntry(MANIFEST_PATH, new StreamZipEntryTransformer() {
@Override
protected void transform(ZipEntry zipEntry, InputStream in, OutputStream out) throws IOException {
Manifest manifest = new Manifest(in);
manifest.getMainAttributes().putValue(JAR_PROCESSOR_HASH_ATTRIBUTE, getJarProcessorHash());
manifest.write(out);
}
})
});
if (!manifestTransformed) {
throw new RuntimeException("Could not add data to jar manifest in " + file);
}
} }
public <T extends JarProcessor> T getByType(Class<T> tClass) { public <T extends JarProcessor> T getByType(Class<T> tClass) {