Compare commits

..

3 Commits

Author SHA1 Message Date
comp500
d1647764c4 Implement preserve and alias in index 2019-06-24 17:47:17 +01:00
comp500
12bf090895 Fix hash serialisation in JSON, check index hash 2019-06-24 17:27:28 +01:00
comp500
533c7a3ed5 Gson isn't broken, I'm broken 2019-06-24 03:41:33 +01:00
11 changed files with 122 additions and 38 deletions

View File

@@ -21,6 +21,7 @@ import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName;
@@ -30,6 +31,7 @@ import link.infra.packwiz.installer.metadata.IndexFile;
import link.infra.packwiz.installer.metadata.ManifestFile;
import link.infra.packwiz.installer.metadata.PackFile;
import link.infra.packwiz.installer.metadata.hash.GeneralHashingSource;
import link.infra.packwiz.installer.metadata.hash.Hash;
import link.infra.packwiz.installer.metadata.hash.HashUtils;
import link.infra.packwiz.installer.request.HandlerManager;
import link.infra.packwiz.installer.ui.IUserInterface;
@@ -109,19 +111,17 @@ public class UpdateManager {
this.checkOptions();
ui.submitProgress(new InstallProgress("Loading manifest file..."));
Gson gson = new Gson();
ManifestFile manifest = null;
Gson gson = new GsonBuilder().registerTypeAdapter(Hash.class, new Hash.TypeHandler()).create();
ManifestFile manifest;
try {
manifest = gson.fromJson(new FileReader(Paths.get(opts.packFolder, opts.manifestFile).toString()),
ManifestFile.class);
} catch (FileNotFoundException e) { // Do nothing
} catch (FileNotFoundException e) {
manifest = new ManifestFile();
} catch (JsonSyntaxException | JsonIOException e) {
ui.handleExceptionAndExit(e);
return;
}
if (manifest == null) {
manifest = new ManifestFile();
}
ui.submitProgress(new InstallProgress("Loading pack file..."));
GeneralHashingSource packFileSource;
@@ -142,13 +142,13 @@ public class UpdateManager {
return;
}
if (packFileSource.hashIsEqual(manifest.packFileHash)) {
System.out.println("Hash already up to date!");
// WOOO it's already up to date
if (manifest.packFileHash != null && packFileSource.hashIsEqual(manifest.packFileHash)) {
System.out.println("Modpack is already up to date!");
// todo: --force?
return;
}
System.out.println(pf.name);
System.out.println("Modpack name: " + pf.name);
try {
processIndex(HandlerManager.getNewLoc(opts.downloadURI, pf.index.file),
@@ -157,10 +157,9 @@ public class UpdateManager {
ui.handleExceptionAndExit(e1);
}
// When successfully updated
// TODO: update MMC params, java args etc
manifest.packFileHash = packFileSource.getHash();
// update other hashes
// TODO: don't do this on failure?
try (Writer writer = new FileWriter(Paths.get(opts.packFolder, opts.manifestFile).toString())) {
gson.toJson(manifest, writer);
} catch (IOException e) {
@@ -174,7 +173,13 @@ public class UpdateManager {
// TODO: implement
}
protected void processIndex(URI indexUri, Object indexHash, String hashFormat, ManifestFile manifest) {
protected void processIndex(URI indexUri, Hash indexHash, String hashFormat, ManifestFile manifest) {
if (manifest.indexFileHash != null && manifest.indexFileHash.equals(indexHash)) {
System.out.println("Modpack files are already up to date!");
return;
}
manifest.indexFileHash = indexHash;
GeneralHashingSource indexFileSource;
try {
Source src = HandlerManager.getFileSource(indexUri);
@@ -194,10 +199,8 @@ public class UpdateManager {
}
if (!indexFileSource.hashIsEqual(indexHash)) {
System.out.println("Hash problems!!!!!!!");
System.out.println(indexHash);
System.out.println(indexFileSource.getHash());
// TODO: throw exception
return;
}
if (manifest.cachedFiles == null) {
@@ -213,7 +216,7 @@ public class UpdateManager {
return f;
}).filter(f -> {
ManifestFile.File cachedFile = manifest.cachedFiles.get(f.file);
Object newHash;
Hash newHash;
try {
newHash = HashUtils.getHash(f.hashFormat, f.hash);
} catch (Exception e) {
@@ -267,8 +270,15 @@ public class UpdateManager {
} catch (Exception e) {}
}
// Don't update files marked with preserve if they already exist on disk
if (f.preserve) {
if (Files.exists(Paths.get(opts.packFolder, f.getDestURI().toString()))) {
return dc;
}
}
try {
Object hash;
Hash hash;
String fileHashFormat;
if (f.linkedFile != null) {
hash = f.linkedFile.getHash();

View File

@@ -9,6 +9,7 @@ import com.google.gson.annotations.SerializedName;
import com.moandjiezana.toml.Toml;
import link.infra.packwiz.installer.metadata.hash.GeneralHashingSource;
import link.infra.packwiz.installer.metadata.hash.Hash;
import link.infra.packwiz.installer.metadata.hash.HashUtils;
import link.infra.packwiz.installer.request.HandlerManager;
import okio.Okio;
@@ -25,10 +26,8 @@ public class IndexFile {
@SerializedName("hash-format")
public String hashFormat;
public String hash;
// TODO: implement
public String alias;
public URI alias;
public boolean metafile;
// TODO: implement
public boolean preserve;
public transient ModFile linkedFile;
@@ -42,7 +41,7 @@ public class IndexFile {
if (hashFormat == null || hashFormat.length() == 0) {
hashFormat = parentIndexFile.hashFormat;
}
Object fileHash = HashUtils.getHash(hashFormat, hash);
Hash fileHash = HashUtils.getHash(hashFormat, hash);
linkedFileURI = HandlerManager.getNewLoc(indexUri, file);
Source src = HandlerManager.getFileSource(linkedFileURI);
GeneralHashingSource fileStream = HashUtils.getHasher(hashFormat).getHashingSource(src);
@@ -68,7 +67,7 @@ public class IndexFile {
}
}
public Object getHash() throws Exception {
public Hash getHash() throws Exception {
if (hash == null) {
throw new Exception("Index file doesn't have a hash");
}
@@ -95,6 +94,9 @@ public class IndexFile {
}
public URI getDestURI() {
if (alias != null) {
return alias;
}
if (metafile && linkedFile != null) {
// TODO: URIs are bad
return file.resolve(linkedFile.filename.replace(" ", "%20"));

View File

@@ -3,16 +3,18 @@ package link.infra.packwiz.installer.metadata;
import java.net.URI;
import java.util.Map;
import link.infra.packwiz.installer.metadata.hash.Hash;
public class ManifestFile {
public Object packFileHash = null;
public Object indexFileHash = null;
public Hash packFileHash = null;
public Hash indexFileHash = null;
public Map<URI, File> cachedFiles;
public static class File {
public Object hash = null;
public Hash hash = null;
public boolean isOptional = false;
public boolean optionValue = true;
public Object linkedFileHash = null;
public Hash linkedFileHash = null;
}
}

View File

@@ -7,6 +7,7 @@ import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import link.infra.packwiz.installer.UpdateManager.Options.Side;
import link.infra.packwiz.installer.metadata.hash.Hash;
import link.infra.packwiz.installer.metadata.hash.HashUtils;
import link.infra.packwiz.installer.request.HandlerManager;
import okio.Source;
@@ -50,7 +51,7 @@ public class ModFile {
return HandlerManager.getFileSource(newLoc);
}
public Object getHash() throws Exception {
public Hash getHash() throws Exception {
if (download == null) {
throw new Exception("Metadata file doesn't have download");
}

View File

@@ -9,7 +9,7 @@ public abstract class GeneralHashingSource extends ForwardingSource {
super(delegate);
}
public abstract Object getHash();
public abstract Hash getHash();
public boolean hashIsEqual(Object compareTo) {
return compareTo.equals(getHash());

View File

@@ -0,0 +1,48 @@
package link.infra.packwiz.installer.metadata.hash;
import java.lang.reflect.Type;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
public abstract class Hash {
protected abstract String getStringValue();
protected abstract String getType();
public static class TypeHandler implements JsonDeserializer<Hash>, JsonSerializer<Hash> {
@Override
public JsonElement serialize(Hash src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject out = new JsonObject();
out.add("type", new JsonPrimitive(src.getType()));
out.add("value", new JsonPrimitive(src.getStringValue()));
return out;
}
@Override
public Hash deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
JsonObject obj = json.getAsJsonObject();
String type, value;
try {
type = obj.get("type").getAsString();
value = obj.get("value").getAsString();
} catch (NullPointerException e) {
throw new JsonParseException("Invalid hash JSON data");
}
try {
return HashUtils.getHash(type, value);
} catch (Exception e) {
throw new JsonParseException("Failed to create hash object", e);
}
}
}
}

View File

@@ -18,7 +18,7 @@ public class HashUtils {
return hasher;
}
public static Object getHash(String type, String value) throws Exception {
public static Hash getHash(String type, String value) throws Exception {
if (hashTypeConversion.containsKey(type)) {
return hashTypeConversion.get(type).getHash(value);
}

View File

@@ -21,7 +21,7 @@ public class HashingSourceHasher implements IHasher {
}
@Override
public Object getHash() {
public Hash getHash() {
if (value == null) {
value = new HashingSourceHash(delegateHashing.hash().hex());
}
@@ -33,7 +33,7 @@ public class HashingSourceHasher implements IHasher {
// this some funky inner class stuff
// each of these classes is specific to the instance of the HasherHashingSource
// therefore HashingSourceHashes from different parent instances will be not instanceof each other
private class HashingSourceHash {
private class HashingSourceHash extends Hash {
String value;
private HashingSourceHash(String value) {
this.value = value;
@@ -56,6 +56,16 @@ public class HashingSourceHasher implements IHasher {
public String toString() {
return type + ": " + value;
}
@Override
protected String getStringValue() {
return value;
}
@Override
protected String getType() {
return type;
}
}
@Override
@@ -69,7 +79,7 @@ public class HashingSourceHasher implements IHasher {
}
@Override
public Object getHash(String value) {
public Hash getHash(String value) {
return new HashingSourceHash(value);
}

View File

@@ -4,5 +4,5 @@ import okio.Source;
public interface IHasher {
public GeneralHashingSource getHashingSource(Source delegate);
public Object getHash(String value);
public Hash getHash(String value);
}

View File

@@ -28,7 +28,7 @@ public class Murmur2Hasher implements IHasher {
}
@Override
public Object getHash() {
public Hash getHash() {
if (value == null) {
byte[] data = computeNormalizedArray(internalBuffer.readByteArray());
value = new Murmur2Hash(Murmur2Lib.hash32(data, data.length, 1));
@@ -54,7 +54,7 @@ public class Murmur2Hasher implements IHasher {
}
private class Murmur2Hash {
private class Murmur2Hash extends Hash {
int value;
private Murmur2Hash(String value) {
// Parsing as long then casting to int converts values gt int max value but lt uint max value
@@ -79,6 +79,16 @@ public class Murmur2Hasher implements IHasher {
public String toString() {
return "murmur2: " + value;
}
@Override
protected String getStringValue() {
return Integer.toString(value);
}
@Override
protected String getType() {
return "murmur2";
}
}
@Override
@@ -87,7 +97,7 @@ public class Murmur2Hasher implements IHasher {
}
@Override
public Object getHash(String value) {
public Hash getHash(String value) {
return new Murmur2Hash(value);
}

View File

@@ -27,6 +27,7 @@ public class CLIHandler implements IUserInterface {
@Override
public void executeManager(Runnable task) {
task.run();
System.out.println("Finished successfully!");
}
}