mirror of
https://github.com/packwiz/packwiz-installer.git
synced 2025-04-19 21:16:30 +02:00
Thanks IntelliJ. ThintelliJ.
This commit is contained in:
parent
794b817eff
commit
bd95bc15ad
2
.idea/.gitignore
generated
vendored
Normal file
2
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/workspace.xml
|
18
.idea/gradle.xml
generated
Normal file
18
.idea/gradle.xml
generated
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="GradleSettings">
|
||||||
|
<option name="linkedExternalProjectsSettings">
|
||||||
|
<GradleProjectSettings>
|
||||||
|
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="gradleJvm" value="11" />
|
||||||
|
<option name="modules">
|
||||||
|
<set>
|
||||||
|
<option value="$PROJECT_DIR$" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
<option name="useQualifiedModuleNames" value="true" />
|
||||||
|
</GradleProjectSettings>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
5
.idea/misc.xml
generated
Normal file
5
.idea/misc.xml
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK" />
|
||||||
|
</project>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -0,0 +1,5 @@
|
|||||||
|
package link.infra.packwiz.installer;
|
||||||
|
|
||||||
|
class DownloadTask {
|
||||||
|
|
||||||
|
}
|
@ -1,22 +1,14 @@
|
|||||||
package link.infra.packwiz.installer;
|
package link.infra.packwiz.installer;
|
||||||
|
|
||||||
import java.awt.EventQueue;
|
|
||||||
import java.awt.GraphicsEnvironment;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
|
|
||||||
import javax.swing.JOptionPane;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
|
||||||
import org.apache.commons.cli.DefaultParser;
|
|
||||||
import org.apache.commons.cli.Options;
|
|
||||||
import org.apache.commons.cli.ParseException;
|
|
||||||
|
|
||||||
import link.infra.packwiz.installer.ui.CLIHandler;
|
import link.infra.packwiz.installer.ui.CLIHandler;
|
||||||
import link.infra.packwiz.installer.ui.IUserInterface;
|
import link.infra.packwiz.installer.ui.IUserInterface;
|
||||||
import link.infra.packwiz.installer.ui.InstallWindow;
|
import link.infra.packwiz.installer.ui.InstallWindow;
|
||||||
|
import org.apache.commons.cli.*;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
@ -28,13 +20,11 @@ public class Main {
|
|||||||
this.startup(args);
|
this.startup(args);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
EventQueue.invokeLater(new Runnable() {
|
EventQueue.invokeLater(() -> {
|
||||||
public void run() {
|
JOptionPane.showMessageDialog(null,
|
||||||
JOptionPane.showMessageDialog(null,
|
"A fatal error occurred: \n" + e.getClass().getCanonicalName() + ": " + e.getMessage(),
|
||||||
"A fatal error occurred: \n" + e.getClass().getCanonicalName() + ": " + e.getMessage(),
|
"packwiz-installer", JOptionPane.ERROR_MESSAGE);
|
||||||
"packwiz-installer", JOptionPane.ERROR_MESSAGE);
|
System.exit(1);
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
// In case the eventqueue is broken, exit after 1 minute
|
// In case the eventqueue is broken, exit after 1 minute
|
||||||
try {
|
try {
|
||||||
@ -127,14 +117,12 @@ public class Main {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// TODO: better error message?
|
// TODO: better error message?
|
||||||
ui.handleExceptionAndExit(e);
|
ui.handleExceptionAndExit(e);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// TODO: better error message?
|
// TODO: better error message?
|
||||||
ui.handleExceptionAndExit(e);
|
ui.handleExceptionAndExit(e);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package link.infra.packwiz.installer;
|
package link.infra.packwiz.installer;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import javax.swing.JOptionPane;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
|
|
||||||
public class RequiresBootstrap {
|
public class RequiresBootstrap {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
@ -15,10 +13,10 @@ public class RequiresBootstrap {
|
|||||||
if (Arrays.stream(args).map(str -> {
|
if (Arrays.stream(args).map(str -> {
|
||||||
if (str == null) return "";
|
if (str == null) return "";
|
||||||
if (str.startsWith("--")) {
|
if (str.startsWith("--")) {
|
||||||
return str.substring(2, str.length());
|
return str.substring(2);
|
||||||
}
|
}
|
||||||
if (str.startsWith("-")) {
|
if (str.startsWith("-")) {
|
||||||
return str.substring(1, str.length());
|
return str.substring(1);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}).anyMatch(str -> str.equals("g") || str.equals("no-gui"))) {
|
}).anyMatch(str -> str.equals("g") || str.equals("no-gui"))) {
|
||||||
|
@ -1,36 +1,11 @@
|
|||||||
package link.infra.packwiz.installer;
|
package link.infra.packwiz.installer;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.CompletionService;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.ExecutorCompletionService;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonIOException;
|
import com.google.gson.JsonIOException;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.moandjiezana.toml.Toml;
|
import com.moandjiezana.toml.Toml;
|
||||||
|
|
||||||
import link.infra.packwiz.installer.metadata.IndexFile;
|
import link.infra.packwiz.installer.metadata.IndexFile;
|
||||||
import link.infra.packwiz.installer.metadata.ManifestFile;
|
import link.infra.packwiz.installer.metadata.ManifestFile;
|
||||||
import link.infra.packwiz.installer.metadata.PackFile;
|
import link.infra.packwiz.installer.metadata.PackFile;
|
||||||
@ -44,6 +19,16 @@ import okio.Buffer;
|
|||||||
import okio.Okio;
|
import okio.Okio;
|
||||||
import okio.Source;
|
import okio.Source;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class UpdateManager {
|
public class UpdateManager {
|
||||||
|
|
||||||
public final Options opts;
|
public final Options opts;
|
||||||
@ -84,8 +69,8 @@ public class UpdateManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this.depSides != null) {
|
if (this.depSides != null) {
|
||||||
for (int i = 0; i < this.depSides.length; i++) {
|
for (Side depSide : this.depSides) {
|
||||||
if (this.depSides[i].equals(tSide)) {
|
if (depSide.equals(tSide)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +81,7 @@ public class UpdateManager {
|
|||||||
public static Side from(String name) {
|
public static Side from(String name) {
|
||||||
String lowerName = name.toLowerCase();
|
String lowerName = name.toLowerCase();
|
||||||
for (Side side : Side.values()) {
|
for (Side side : Side.values()) {
|
||||||
if (side.sideName == lowerName) {
|
if (side.sideName.equals(lowerName)) {
|
||||||
return side;
|
return side;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,9 +135,7 @@ public class UpdateManager {
|
|||||||
|
|
||||||
List<URI> invalidatedUris = new ArrayList<>();
|
List<URI> invalidatedUris = new ArrayList<>();
|
||||||
if (manifest.cachedFiles != null) {
|
if (manifest.cachedFiles != null) {
|
||||||
Iterator<Map.Entry<URI, ManifestFile.File>> it = manifest.cachedFiles.entrySet().iterator();
|
for (Map.Entry<URI, ManifestFile.File> entry : manifest.cachedFiles.entrySet()) {
|
||||||
while (it.hasNext()) {
|
|
||||||
Map.Entry<URI, ManifestFile.File> entry = it.next();
|
|
||||||
if (entry.getValue().cachedLocation != null) {
|
if (entry.getValue().cachedLocation != null) {
|
||||||
if (!Files.exists(Paths.get(opts.packFolder, entry.getValue().cachedLocation))) {
|
if (!Files.exists(Paths.get(opts.packFolder, entry.getValue().cachedLocation))) {
|
||||||
URI fileUri = entry.getKey();
|
URI fileUri = entry.getKey();
|
||||||
@ -225,7 +208,7 @@ public class UpdateManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (manifest.cachedFiles == null) {
|
if (manifest.cachedFiles == null) {
|
||||||
manifest.cachedFiles = new HashMap<URI, ManifestFile.File>();
|
manifest.cachedFiles = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.submitProgress(new InstallProgress("Checking local files..."));
|
ui.submitProgress(new InstallProgress("Checking local files..."));
|
||||||
@ -233,7 +216,7 @@ public class UpdateManager {
|
|||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Map.Entry<URI, ManifestFile.File> entry = it.next();
|
Map.Entry<URI, ManifestFile.File> entry = it.next();
|
||||||
if (entry.getValue().cachedLocation != null) {
|
if (entry.getValue().cachedLocation != null) {
|
||||||
if (!indexFile.files.stream().anyMatch(f -> f.file.equals(entry.getKey()))) {
|
if (indexFile.files.stream().noneMatch(f -> f.file.equals(entry.getKey()))) {
|
||||||
// File has been removed from the index
|
// File has been removed from the index
|
||||||
try {
|
try {
|
||||||
Files.deleteIfExists(Paths.get(opts.packFolder, entry.getValue().cachedLocation));
|
Files.deleteIfExists(Paths.get(opts.packFolder, entry.getValue().cachedLocation));
|
||||||
@ -248,12 +231,11 @@ public class UpdateManager {
|
|||||||
ui.submitProgress(new InstallProgress("Comparing new files..."));
|
ui.submitProgress(new InstallProgress("Comparing new files..."));
|
||||||
|
|
||||||
// TODO: progress bar
|
// TODO: progress bar
|
||||||
ConcurrentLinkedQueue<Exception> exceptionQueue = new ConcurrentLinkedQueue<Exception>();
|
ConcurrentLinkedQueue<Exception> exceptionQueue = new ConcurrentLinkedQueue<>();
|
||||||
List<IndexFile.File> newFiles = indexFile.files.stream().map(f -> {
|
List<IndexFile.File> newFiles = indexFile.files.stream().peek(f -> {
|
||||||
if (f.hashFormat == null || f.hashFormat.length() == 0) {
|
if (f.hashFormat == null || f.hashFormat.length() == 0) {
|
||||||
f.hashFormat = indexFile.hashFormat;
|
f.hashFormat = indexFile.hashFormat;
|
||||||
}
|
}
|
||||||
return f;
|
|
||||||
}).filter(f -> {
|
}).filter(f -> {
|
||||||
if (invalidatedUris.contains(f.file)) {
|
if (invalidatedUris.contains(f.file)) {
|
||||||
return true;
|
return true;
|
||||||
@ -267,13 +249,12 @@ public class UpdateManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return cachedFile == null || !newHash.equals(cachedFile.hash);
|
return cachedFile == null || !newHash.equals(cachedFile.hash);
|
||||||
}).parallel().map(f -> {
|
}).parallel().peek(f -> {
|
||||||
try {
|
try {
|
||||||
f.downloadMeta(indexFile, indexUri);
|
f.downloadMeta(indexFile, indexUri);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
exceptionQueue.add(e);
|
exceptionQueue.add(e);
|
||||||
}
|
}
|
||||||
return f;
|
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
for (Exception e : exceptionQueue) {
|
for (Exception e : exceptionQueue) {
|
||||||
@ -284,81 +265,78 @@ public class UpdateManager {
|
|||||||
// TODO: present options
|
// TODO: present options
|
||||||
// TODO: all options should be presented, not just new files!!!!!!!
|
// TODO: all options should be presented, not just new files!!!!!!!
|
||||||
// and options should be readded to newFiles after option -> true
|
// and options should be readded to newFiles after option -> true
|
||||||
newFiles.stream().filter(f -> f.linkedFile != null).filter(f -> f.linkedFile.option != null).map(f -> {
|
newFiles.stream().filter(f -> f.linkedFile != null).filter(f -> f.linkedFile.option != null).map(f ->
|
||||||
return "option: " + (f.linkedFile.option.description == null ? "null" : f.linkedFile.option.description);
|
"option: " + (f.linkedFile.option.description == null ? "null" : f.linkedFile.option.description)
|
||||||
}).forEachOrdered(desc -> {
|
).forEachOrdered(desc -> {
|
||||||
System.out.println(desc);
|
System.out.println(desc);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: different thread pool type?
|
// TODO: different thread pool type?
|
||||||
ExecutorService threadPool = Executors.newFixedThreadPool(10);
|
ExecutorService threadPool = Executors.newFixedThreadPool(10);
|
||||||
CompletionService<DownloadCompletion> completionService = new ExecutorCompletionService<DownloadCompletion>(
|
CompletionService<DownloadCompletion> completionService = new ExecutorCompletionService<>(threadPool);
|
||||||
threadPool);
|
|
||||||
|
|
||||||
for (IndexFile.File f : newFiles) {
|
for (IndexFile.File f : newFiles) {
|
||||||
ManifestFile.File cachedFile = manifest.cachedFiles.get(f.file);
|
ManifestFile.File cachedFile = manifest.cachedFiles.get(f.file);
|
||||||
completionService.submit(new Callable<DownloadCompletion>() {
|
completionService.submit(() -> {
|
||||||
public DownloadCompletion call() {
|
DownloadCompletion dc = new DownloadCompletion();
|
||||||
DownloadCompletion dc = new DownloadCompletion();
|
dc.file = f;
|
||||||
dc.file = f;
|
|
||||||
|
|
||||||
if (cachedFile != null && cachedFile.linkedFileHash != null && f.linkedFile != null) {
|
if (cachedFile != null && cachedFile.linkedFileHash != null && f.linkedFile != null) {
|
||||||
try {
|
try {
|
||||||
if (cachedFile.linkedFileHash.equals(f.linkedFile.getHash())) {
|
if (cachedFile.linkedFileHash.equals(f.linkedFile.getHash())) {
|
||||||
// Do nothing, the file didn't change
|
// Do nothing, the file didn't change
|
||||||
// TODO: but if the hash of the metafile changed, what did change?????
|
// TODO: but if the hash of the metafile changed, what did change?????
|
||||||
// should this be checked somehow??
|
// should this be checked somehow??
|
||||||
return dc;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Path destPath = Paths.get(opts.packFolder, f.getDestURI().toString());
|
|
||||||
|
|
||||||
// Don't update files marked with preserve if they already exist on disk
|
|
||||||
if (f.preserve) {
|
|
||||||
if (Files.exists(destPath)) {
|
|
||||||
return dc;
|
return dc;
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
Path destPath = Paths.get(opts.packFolder, f.getDestURI().toString());
|
||||||
Hash hash;
|
|
||||||
String fileHashFormat;
|
|
||||||
if (f.linkedFile != null) {
|
|
||||||
hash = f.linkedFile.getHash();
|
|
||||||
fileHashFormat = f.linkedFile.download.hashFormat;
|
|
||||||
} else {
|
|
||||||
hash = f.getHash();
|
|
||||||
fileHashFormat = f.hashFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
Source src = f.getSource(indexUri);
|
// Don't update files marked with preserve if they already exist on disk
|
||||||
GeneralHashingSource fileSource = HashUtils.getHasher(fileHashFormat).getHashingSource(src);
|
if (f.preserve) {
|
||||||
Buffer data = new Buffer();
|
if (Files.exists(destPath)) {
|
||||||
Okio.buffer(fileSource).readAll(data);
|
|
||||||
|
|
||||||
if (fileSource.hashIsEqual(hash)) {
|
|
||||||
Files.createDirectories(destPath.getParent());
|
|
||||||
Files.copy(data.inputStream(), destPath, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
} else {
|
|
||||||
System.out.println("Invalid hash for " + f.getDestURI().toString());
|
|
||||||
System.out.println("Calculated: " + fileSource.getHash());
|
|
||||||
System.out.println("Expected: " + hash);
|
|
||||||
dc.err = new Exception("Hash invalid!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cachedFile != null && !destPath.equals(Paths.get(opts.packFolder, cachedFile.cachedLocation))) {
|
|
||||||
// Delete old file if location changes
|
|
||||||
Files.delete(Paths.get(opts.packFolder, cachedFile.cachedLocation));
|
|
||||||
}
|
|
||||||
|
|
||||||
return dc;
|
|
||||||
} catch (Exception e) {
|
|
||||||
dc.err = e;
|
|
||||||
return dc;
|
return dc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Hash hash;
|
||||||
|
String fileHashFormat;
|
||||||
|
if (f.linkedFile != null) {
|
||||||
|
hash = f.linkedFile.getHash();
|
||||||
|
fileHashFormat = f.linkedFile.download.hashFormat;
|
||||||
|
} else {
|
||||||
|
hash = f.getHash();
|
||||||
|
fileHashFormat = f.hashFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
Source src = f.getSource(indexUri);
|
||||||
|
GeneralHashingSource fileSource = HashUtils.getHasher(fileHashFormat).getHashingSource(src);
|
||||||
|
Buffer data = new Buffer();
|
||||||
|
Okio.buffer(fileSource).readAll(data);
|
||||||
|
|
||||||
|
if (fileSource.hashIsEqual(hash)) {
|
||||||
|
Files.createDirectories(destPath.getParent());
|
||||||
|
Files.copy(data.inputStream(), destPath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
} else {
|
||||||
|
System.out.println("Invalid hash for " + f.getDestURI().toString());
|
||||||
|
System.out.println("Calculated: " + fileSource.getHash());
|
||||||
|
System.out.println("Expected: " + hash);
|
||||||
|
dc.err = new Exception("Hash invalid!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedFile != null && !destPath.equals(Paths.get(opts.packFolder, cachedFile.cachedLocation))) {
|
||||||
|
// Delete old file if location changes
|
||||||
|
Files.delete(Paths.get(opts.packFolder, cachedFile.cachedLocation));
|
||||||
|
}
|
||||||
|
|
||||||
|
return dc;
|
||||||
|
} catch (Exception e) {
|
||||||
|
dc.err = e;
|
||||||
|
return dc;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
package link.infra.packwiz.installer.metadata;
|
package link.infra.packwiz.installer.metadata;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.gson.annotations.JsonAdapter;
|
import com.google.gson.annotations.JsonAdapter;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.moandjiezana.toml.Toml;
|
import com.moandjiezana.toml.Toml;
|
||||||
|
|
||||||
import link.infra.packwiz.installer.metadata.hash.GeneralHashingSource;
|
import link.infra.packwiz.installer.metadata.hash.GeneralHashingSource;
|
||||||
import link.infra.packwiz.installer.metadata.hash.Hash;
|
import link.infra.packwiz.installer.metadata.hash.Hash;
|
||||||
import link.infra.packwiz.installer.metadata.hash.HashUtils;
|
import link.infra.packwiz.installer.metadata.hash.HashUtils;
|
||||||
@ -15,6 +10,10 @@ import link.infra.packwiz.installer.request.HandlerManager;
|
|||||||
import okio.Okio;
|
import okio.Okio;
|
||||||
import okio.Source;
|
import okio.Source;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class IndexFile {
|
public class IndexFile {
|
||||||
@SerializedName("hash-format")
|
@SerializedName("hash-format")
|
||||||
public String hashFormat;
|
public String hashFormat;
|
||||||
@ -69,6 +68,7 @@ public class IndexFile {
|
|||||||
|
|
||||||
public Hash getHash() throws Exception {
|
public Hash getHash() throws Exception {
|
||||||
if (hash == null) {
|
if (hash == null) {
|
||||||
|
// TODO: should these be more specific exceptions (e.g. IndexFileException?!)
|
||||||
throw new Exception("Index file doesn't have a hash");
|
throw new Exception("Index file doesn't have a hash");
|
||||||
}
|
}
|
||||||
if (hashFormat == null) {
|
if (hashFormat == null) {
|
||||||
@ -90,7 +90,8 @@ public class IndexFile {
|
|||||||
if (file != null) {
|
if (file != null) {
|
||||||
return Paths.get(file.getPath()).getFileName().toString();
|
return Paths.get(file.getPath()).getFileName().toString();
|
||||||
}
|
}
|
||||||
return file.getPath();
|
// TODO: throw some kind of exception?
|
||||||
|
return "Invalid file";
|
||||||
}
|
}
|
||||||
|
|
||||||
public URI getDestURI() {
|
public URI getDestURI() {
|
||||||
|
@ -48,7 +48,7 @@ public class HashingSourceHasher implements IHasher {
|
|||||||
if (value != null) {
|
if (value != null) {
|
||||||
return value.equals(objHash.value);
|
return value.equals(objHash.value);
|
||||||
} else {
|
} else {
|
||||||
return objHash.value == null ? true : false;
|
return objHash.value == null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package link.infra.packwiz.installer.metadata.hash;
|
package link.infra.packwiz.installer.metadata.hash;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import okio.Buffer;
|
import okio.Buffer;
|
||||||
import okio.Source;
|
import okio.Source;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class Murmur2Hasher implements IHasher {
|
public class Murmur2Hasher implements IHasher {
|
||||||
private class Murmur2GeneralHashingSource extends GeneralHashingSource {
|
private class Murmur2GeneralHashingSource extends GeneralHashingSource {
|
||||||
Murmur2Hash value;
|
Murmur2Hash value;
|
||||||
@ -40,8 +40,7 @@ public class Murmur2Hasher implements IHasher {
|
|||||||
private byte[] computeNormalizedArray(byte[] input) {
|
private byte[] computeNormalizedArray(byte[] input) {
|
||||||
byte[] output = new byte[input.length];
|
byte[] output = new byte[input.length];
|
||||||
int num = 0;
|
int num = 0;
|
||||||
for (int i = 0; i < input.length; i++) {
|
for (byte b : input) {
|
||||||
byte b = input[i];
|
|
||||||
if (!(b == 9 || b == 10 || b == 13 || b == 32)) {
|
if (!(b == 9 || b == 10 || b == 13 || b == 32)) {
|
||||||
output[num] = b;
|
output[num] = b;
|
||||||
num++;
|
num++;
|
||||||
@ -54,7 +53,7 @@ public class Murmur2Hasher implements IHasher {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Murmur2Hash extends Hash {
|
private static class Murmur2Hash extends Hash {
|
||||||
int value;
|
int value;
|
||||||
private Murmur2Hash(String value) {
|
private Murmur2Hash(String value) {
|
||||||
// Parsing as long then casting to int converts values gt int max value but lt uint max value
|
// Parsing as long then casting to int converts values gt int max value but lt uint max value
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
package link.infra.packwiz.installer.request;
|
package link.infra.packwiz.installer.request;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import okio.Source;
|
import okio.Source;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IRequestHandler handles requests for locations specified in modpack metadata.
|
* IRequestHandler handles requests for locations specified in modpack metadata.
|
||||||
*/
|
*/
|
||||||
public interface IRequestHandler {
|
public interface IRequestHandler {
|
||||||
|
|
||||||
public boolean matchesHandler(URI loc);
|
boolean matchesHandler(URI loc);
|
||||||
|
|
||||||
public default URI getNewLoc(URI loc) {
|
default URI getNewLoc(URI loc) {
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,6 +22,6 @@ public interface IRequestHandler {
|
|||||||
* @return The Source containing the data of the file
|
* @return The Source containing the data of the file
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public Source getFileSource(URI loc) throws Exception;
|
Source getFileSource(URI loc) throws Exception;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,17 @@ public class RequestHandlerGithub extends RequestHandlerZip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: is caching really needed, if HTTPURLConnection follows redirects correctly?
|
// TODO: is caching really needed, if HTTPURLConnection follows redirects correctly?
|
||||||
private Map<String, URI> zipUriMap = new HashMap<String, URI>();
|
private Map<String, URI> zipUriMap = new HashMap<>();
|
||||||
final ReentrantReadWriteLock zipUriLock = new ReentrantReadWriteLock();
|
private final ReentrantReadWriteLock zipUriLock = new ReentrantReadWriteLock();
|
||||||
private static Pattern repoMatcherPattern = Pattern.compile("/([\\w.-]+/[\\w.-]+).*");
|
private static Pattern repoMatcherPattern = Pattern.compile("/([\\w.-]+/[\\w.-]+).*");
|
||||||
|
|
||||||
private String getRepoName(URI loc) {
|
private String getRepoName(URI loc) {
|
||||||
Matcher matcher = repoMatcherPattern.matcher(loc.getPath());
|
Matcher matcher = repoMatcherPattern.matcher(loc.getPath());
|
||||||
matcher.matches();
|
if (matcher.matches()) {
|
||||||
return matcher.group(1);
|
return matcher.group(1);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -57,8 +60,11 @@ public class RequestHandlerGithub extends RequestHandlerZip {
|
|||||||
|
|
||||||
private String getBranch(URI loc) {
|
private String getBranch(URI loc) {
|
||||||
Matcher matcher = branchMatcherPattern.matcher(loc.getPath());
|
Matcher matcher = branchMatcherPattern.matcher(loc.getPath());
|
||||||
matcher.matches();
|
if (matcher.matches()) {
|
||||||
return matcher.group(1);
|
return matcher.group(1);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package link.infra.packwiz.installer.request.handlers;
|
package link.infra.packwiz.installer.request.handlers;
|
||||||
|
|
||||||
|
import okio.Buffer;
|
||||||
|
import okio.BufferedSource;
|
||||||
|
import okio.Okio;
|
||||||
|
import okio.Source;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
@ -11,14 +16,9 @@ import java.util.function.Predicate;
|
|||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
import okio.Buffer;
|
|
||||||
import okio.BufferedSource;
|
|
||||||
import okio.Okio;
|
|
||||||
import okio.Source;
|
|
||||||
|
|
||||||
public abstract class RequestHandlerZip extends RequestHandlerHTTP {
|
public abstract class RequestHandlerZip extends RequestHandlerHTTP {
|
||||||
|
|
||||||
protected final boolean modeHasFolder;
|
private final boolean modeHasFolder;
|
||||||
|
|
||||||
public RequestHandlerZip(boolean modeHasFolder) {
|
public RequestHandlerZip(boolean modeHasFolder) {
|
||||||
this.modeHasFolder = modeHasFolder;
|
this.modeHasFolder = modeHasFolder;
|
||||||
@ -35,14 +35,14 @@ public abstract class RequestHandlerZip extends RequestHandlerHTTP {
|
|||||||
private class ZipReader {
|
private class ZipReader {
|
||||||
|
|
||||||
private final ZipInputStream zis;
|
private final ZipInputStream zis;
|
||||||
private final Map<URI, Buffer> readFiles = new HashMap<URI, Buffer>();
|
private final Map<URI, Buffer> readFiles = new HashMap<>();
|
||||||
// Write lock implies access to ZipInputStream - only 1 thread must read at a time!
|
// Write lock implies access to ZipInputStream - only 1 thread must read at a time!
|
||||||
final ReentrantLock filesLock = new ReentrantLock();
|
final ReentrantLock filesLock = new ReentrantLock();
|
||||||
private ZipEntry entry;
|
private ZipEntry entry;
|
||||||
|
|
||||||
private final BufferedSource zipSource;
|
private final BufferedSource zipSource;
|
||||||
|
|
||||||
public ZipReader(Source zip) {
|
ZipReader(Source zip) {
|
||||||
zis = new ZipInputStream(Okio.buffer(zip).inputStream());
|
zis = new ZipInputStream(Okio.buffer(zip).inputStream());
|
||||||
zipSource = Okio.buffer(Okio.source(zis));
|
zipSource = Okio.buffer(Okio.source(zis));
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ public abstract class RequestHandlerZip extends RequestHandlerHTTP {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Source getFileSource(URI loc) throws Exception {
|
Source getFileSource(URI loc) throws Exception {
|
||||||
filesLock.lock();
|
filesLock.lock();
|
||||||
// Assume files are only read once, allow GC by removing
|
// Assume files are only read once, allow GC by removing
|
||||||
Buffer file = readFiles.remove(loc);
|
Buffer file = readFiles.remove(loc);
|
||||||
@ -82,13 +82,10 @@ public abstract class RequestHandlerZip extends RequestHandlerHTTP {
|
|||||||
|
|
||||||
file = findFile(loc);
|
file = findFile(loc);
|
||||||
filesLock.unlock();
|
filesLock.unlock();
|
||||||
if (file != null) {
|
return file;
|
||||||
return file;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public URI findInZip(Predicate<URI> matches) throws Exception {
|
URI findInZip(Predicate<URI> matches) throws Exception {
|
||||||
filesLock.lock();
|
filesLock.lock();
|
||||||
for (URI file : readFiles.keySet()) {
|
for (URI file : readFiles.keySet()) {
|
||||||
if (matches.test(file)) {
|
if (matches.test(file)) {
|
||||||
@ -115,8 +112,8 @@ public abstract class RequestHandlerZip extends RequestHandlerHTTP {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<URI, ZipReader> cache = new HashMap<URI, ZipReader>();
|
private final Map<URI, ZipReader> cache = new HashMap<>();
|
||||||
final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock();
|
private final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock();
|
||||||
|
|
||||||
protected abstract URI getZipUri(URI loc) throws Exception;
|
protected abstract URI getZipUri(URI loc) throws Exception;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user