* Use jar processor ids to fix #432 * Use full hash string of jar processor idsdev/0.11
parent
606046e719
commit
08a797c53b
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue