mirror of
https://github.com/packwiz/packwiz-installer.git
synced 2025-04-19 21:16:30 +02:00
Start rewrite of downloading system, THIS IS SCARY HELP
This commit is contained in:
parent
bd95bc15ad
commit
320e56e74e
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
|
@ -1,5 +1,126 @@
|
||||
package link.infra.packwiz.installer;
|
||||
|
||||
class DownloadTask {
|
||||
import link.infra.packwiz.installer.metadata.IndexFile;
|
||||
import link.infra.packwiz.installer.metadata.ManifestFile;
|
||||
import link.infra.packwiz.installer.metadata.hash.Hash;
|
||||
import link.infra.packwiz.installer.metadata.hash.HashUtils;
|
||||
import link.infra.packwiz.installer.ui.IOptionDetails;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class DownloadTask implements IOptionDetails {
|
||||
final IndexFile.File metadata;
|
||||
private Exception failure = null;
|
||||
private boolean complete = false;
|
||||
private boolean invalidated = false;
|
||||
private boolean optionValue = true;
|
||||
// If file is new or isOptional changed to true, the option needs to be presented again
|
||||
private boolean newOptional = true;
|
||||
|
||||
public DownloadTask(IndexFile.File metadata) {
|
||||
this.metadata = metadata;
|
||||
if (this.metadata.linkedFile != null) {
|
||||
if (this.metadata.linkedFile.option != null) {
|
||||
// Set option to it's default value
|
||||
optionValue = this.metadata.linkedFile.option.defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setDefaultHashFormat(String format) {
|
||||
if (failure != null || complete) return;
|
||||
if (metadata.hashFormat == null || metadata.hashFormat.length() == 0) {
|
||||
metadata.hashFormat = format;
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
invalidated = true;
|
||||
complete = false;
|
||||
}
|
||||
|
||||
public void updateFromCache(ManifestFile.File cachedFile) {
|
||||
if (failure != null || complete) return;
|
||||
if (cachedFile == null) return;
|
||||
|
||||
if (!invalidated) {
|
||||
Hash currHash = null;
|
||||
try {
|
||||
currHash = HashUtils.getHash(metadata.hashFormat, metadata.hash);
|
||||
} catch (Exception e) {
|
||||
failure = e;
|
||||
return;
|
||||
}
|
||||
if (currHash != null && currHash.equals(cachedFile.hash)) {
|
||||
// Already up to date
|
||||
complete = true;
|
||||
}
|
||||
}
|
||||
if (cachedFile.isOptional) {
|
||||
// Set option to the cached value
|
||||
optionValue = cachedFile.optionValue;
|
||||
if (isOptional()) {
|
||||
// isOptional didn't change
|
||||
newOptional = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadMetadata(IndexFile parentIndexFile, URI indexUri) {
|
||||
if (failure != null || complete) return;
|
||||
try {
|
||||
metadata.downloadMeta(parentIndexFile, indexUri);
|
||||
} catch (Exception e) {
|
||||
failure = e;
|
||||
}
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return failure;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
if (metadata.linkedFile != null) {
|
||||
return metadata.linkedFile.isOptional();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isNewOptional() {
|
||||
return isOptional() && this.newOptional;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return metadata.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getOptionValue() {
|
||||
return this.optionValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOptionDescription() {
|
||||
if (metadata.linkedFile != null) {
|
||||
return metadata.linkedFile.option.description;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setOptionValue(boolean value) {
|
||||
// TODO: if this is false, ensure the file is deleted in the actual download stage
|
||||
this.optionValue = value;
|
||||
}
|
||||
|
||||
public static List<DownloadTask> createTasksFromIndex(IndexFile index) {
|
||||
ArrayList<DownloadTask> tasks = new ArrayList<>();
|
||||
for (IndexFile.File file : index.files) {
|
||||
tasks.add(new DownloadTask(file));
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -13,6 +13,7 @@ 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.IOptionDetails;
|
||||
import link.infra.packwiz.installer.ui.IUserInterface;
|
||||
import link.infra.packwiz.installer.ui.InstallProgress;
|
||||
import okio.Buffer;
|
||||
@ -133,16 +134,27 @@ public class UpdateManager {
|
||||
|
||||
ui.submitProgress(new InstallProgress("Checking local files..."));
|
||||
|
||||
// Invalidation checking must be done here, as it must happen before pack/index hashes are checked
|
||||
List<URI> invalidatedUris = new ArrayList<>();
|
||||
if (manifest.cachedFiles != null) {
|
||||
for (Map.Entry<URI, ManifestFile.File> entry : manifest.cachedFiles.entrySet()) {
|
||||
if (entry.getValue().cachedLocation != null) {
|
||||
if (!Files.exists(Paths.get(opts.packFolder, entry.getValue().cachedLocation))) {
|
||||
URI fileUri = entry.getKey();
|
||||
System.out.println("File " + fileUri.toString() + " invalidated, marked for redownloading");
|
||||
invalidatedUris.add(fileUri);
|
||||
boolean invalid = false;
|
||||
// if isn't optional, or is optional but optionValue == true
|
||||
if (!entry.getValue().isOptional || entry.getValue().optionValue) {
|
||||
if (entry.getValue().cachedLocation != null) {
|
||||
if (!Files.exists(Paths.get(opts.packFolder, entry.getValue().cachedLocation))) {
|
||||
invalid = true;
|
||||
}
|
||||
} else {
|
||||
// if cachedLocation == null, should probably be installed!!
|
||||
invalid = true;
|
||||
}
|
||||
}
|
||||
if (invalid) {
|
||||
URI fileUri = entry.getKey();
|
||||
System.out.println("File " + fileUri.toString() + " invalidated, marked for redownloading");
|
||||
invalidatedUris.add(fileUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,6 +167,7 @@ public class UpdateManager {
|
||||
System.out.println("Modpack name: " + pf.name);
|
||||
|
||||
try {
|
||||
// This is badly written, I'll probably heavily refactor it at some point
|
||||
processIndex(HandlerManager.getNewLoc(opts.downloadURI, pf.index.file),
|
||||
HashUtils.getHash(pf.index.hashFormat, pf.index.hash), pf.index.hashFormat, manifest, invalidatedUris);
|
||||
} catch (Exception e1) {
|
||||
@ -216,60 +229,57 @@ public class UpdateManager {
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<URI, ManifestFile.File> entry = it.next();
|
||||
if (entry.getValue().cachedLocation != null) {
|
||||
if (indexFile.files.stream().noneMatch(f -> f.file.equals(entry.getKey()))) {
|
||||
// File has been removed from the index
|
||||
boolean alreadyDeleted = false;
|
||||
// Delete if option value has been set to false
|
||||
if (entry.getValue().isOptional && !entry.getValue().optionValue) {
|
||||
try {
|
||||
Files.deleteIfExists(Paths.get(opts.packFolder, entry.getValue().cachedLocation));
|
||||
} catch (IOException e) {
|
||||
// TODO: should this be shown to the user in some way?
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Set to null, as it doesn't exist anymore
|
||||
entry.getValue().cachedLocation = null;
|
||||
alreadyDeleted = true;
|
||||
}
|
||||
if (indexFile.files.stream().noneMatch(f -> f.file.equals(entry.getKey()))) {
|
||||
// File has been removed from the index
|
||||
if (!alreadyDeleted) {
|
||||
try {
|
||||
Files.deleteIfExists(Paths.get(opts.packFolder, entry.getValue().cachedLocation));
|
||||
} catch (IOException e) {
|
||||
// TODO: should this be shown to the user in some way?
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
ui.submitProgress(new InstallProgress("Comparing new files..."));
|
||||
|
||||
// TODO: progress bar
|
||||
ConcurrentLinkedQueue<Exception> exceptionQueue = new ConcurrentLinkedQueue<>();
|
||||
List<IndexFile.File> newFiles = indexFile.files.stream().peek(f -> {
|
||||
if (f.hashFormat == null || f.hashFormat.length() == 0) {
|
||||
f.hashFormat = indexFile.hashFormat;
|
||||
// TODO: progress bar, parallelify
|
||||
List<DownloadTask> tasks = DownloadTask.createTasksFromIndex(indexFile);
|
||||
tasks.forEach(f -> f.setDefaultHashFormat(indexFile.hashFormat));
|
||||
tasks.forEach(f -> {
|
||||
// TODO: should linkedfile be checked as well? should a getter be used?
|
||||
if (invalidatedUris.contains(f.metadata.file)) {
|
||||
f.invalidate();
|
||||
} else {
|
||||
f.updateFromCache(manifest.cachedFiles.get(f.metadata.file));
|
||||
}
|
||||
}).filter(f -> {
|
||||
if (invalidatedUris.contains(f.file)) {
|
||||
return true;
|
||||
}
|
||||
ManifestFile.File cachedFile = manifest.cachedFiles.get(f.file);
|
||||
Hash newHash;
|
||||
try {
|
||||
newHash = HashUtils.getHash(f.hashFormat, f.hash);
|
||||
} catch (Exception e) {
|
||||
exceptionQueue.add(e);
|
||||
return false;
|
||||
}
|
||||
return cachedFile == null || !newHash.equals(cachedFile.hash);
|
||||
}).parallel().peek(f -> {
|
||||
try {
|
||||
f.downloadMeta(indexFile, indexUri);
|
||||
} catch (Exception e) {
|
||||
exceptionQueue.add(e);
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
for (Exception e : exceptionQueue) {
|
||||
// TODO: collect all exceptions, present in one dialog
|
||||
ui.handleException(e);
|
||||
}
|
||||
|
||||
// TODO: present options
|
||||
// TODO: all options should be presented, not just new files!!!!!!!
|
||||
// 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 ->
|
||||
"option: " + (f.linkedFile.option.description == null ? "null" : f.linkedFile.option.description)
|
||||
).forEachOrdered(desc -> {
|
||||
System.out.println(desc);
|
||||
});
|
||||
tasks.forEach(f -> f.downloadMetadata(indexFile, indexUri));
|
||||
|
||||
// TODO: collect all exceptions, present in one dialog
|
||||
// TODO: quit if there are exceptions or just remove failed tasks before presenting options
|
||||
List<DownloadTask> failedTasks = tasks.stream().filter(t -> t.getException() != null).collect(Collectors.toList());
|
||||
|
||||
// If options changed, present all options again
|
||||
if (tasks.stream().filter(DownloadTask::isNewOptional).count() > 0) {
|
||||
List<IOptionDetails> opts = tasks.stream().filter(DownloadTask::isOptional).collect(Collectors.toList());
|
||||
// TODO: present options
|
||||
}
|
||||
|
||||
// TODO: different thread pool type?
|
||||
ExecutorService threadPool = Executors.newFixedThreadPool(10);
|
||||
|
@ -0,0 +1,8 @@
|
||||
package link.infra.packwiz.installer.ui;
|
||||
|
||||
public interface IOptionDetails {
|
||||
String getName();
|
||||
boolean getOptionValue();
|
||||
String getOptionDescription();
|
||||
void setOptionValue(boolean value);
|
||||
}
|
@ -1,23 +1,27 @@
|
||||
package link.infra.packwiz.installer.ui;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IUserInterface {
|
||||
|
||||
public void show();
|
||||
void show();
|
||||
|
||||
public void handleException(Exception e);
|
||||
void handleException(Exception e);
|
||||
|
||||
/**
|
||||
* This might not exit straight away, return after calling this!
|
||||
*/
|
||||
public default void handleExceptionAndExit(Exception e) {
|
||||
default void handleExceptionAndExit(Exception e) {
|
||||
handleException(e);
|
||||
System.exit(1);
|
||||
};
|
||||
}
|
||||
|
||||
public default void setTitle(String title) {};
|
||||
default void setTitle(String title) {}
|
||||
|
||||
public void submitProgress(InstallProgress progress);
|
||||
void submitProgress(InstallProgress progress);
|
||||
|
||||
public void executeManager(Runnable task);
|
||||
void executeManager(Runnable task);
|
||||
|
||||
void showOptions(List<IOptionDetails> option);
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user