Merge pull request #438 from yushijinhun/force-update
移除「更新一次 HMCL,电脑上所有 HMCL 都得到更新」的功能
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.upgrade;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.jar.JarOutputStream;
|
||||||
|
import java.util.jar.Pack200;
|
||||||
|
|
||||||
|
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||||
|
import org.jackhuang.hmcl.util.NetworkUtils;
|
||||||
|
import org.tukaani.xz.XZInputStream;
|
||||||
|
|
||||||
|
class HMCLDownloadTask extends FileDownloadTask {
|
||||||
|
|
||||||
|
private RemoteVersion.Type archiveFormat;
|
||||||
|
|
||||||
|
public HMCLDownloadTask(RemoteVersion version, Path target) {
|
||||||
|
super(NetworkUtils.toURL(version.getUrl()), target.toFile(), version.getIntegrityCheck());
|
||||||
|
archiveFormat = version.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws Exception {
|
||||||
|
super.execute();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Path target = getFile().toPath();
|
||||||
|
|
||||||
|
switch (archiveFormat) {
|
||||||
|
case JAR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PACK_XZ:
|
||||||
|
byte[] raw = Files.readAllBytes(target);
|
||||||
|
try (InputStream in = new XZInputStream(new ByteArrayInputStream(raw));
|
||||||
|
JarOutputStream out = new JarOutputStream(Files.newOutputStream(target))) {
|
||||||
|
Pack200.newUnpacker().unpack(in, out);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown format: " + archiveFormat);
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
getFile().delete();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ import java.util.zip.ZipFile;
|
|||||||
|
|
||||||
import org.jackhuang.hmcl.util.DigestUtils;
|
import org.jackhuang.hmcl.util.DigestUtils;
|
||||||
import org.jackhuang.hmcl.util.IOUtils;
|
import org.jackhuang.hmcl.util.IOUtils;
|
||||||
|
import org.jackhuang.hmcl.util.JarUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that checks the integrity of HMCL.
|
* A class that checks the integrity of HMCL.
|
||||||
@@ -123,8 +124,7 @@ public final class IntegrityChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void verifySelf() throws IOException {
|
private static void verifySelf() throws IOException {
|
||||||
Path self = LocalVersion.current().orElseThrow(() -> new IOException("Failed to find myself"))
|
Path self = JarUtils.thisJar().orElseThrow(() -> new IOException("Failed to find current HMCL location"));
|
||||||
.getLocation();
|
|
||||||
requireVerifiedJar(self);
|
requireVerifiedJar(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
/*
|
|
||||||
* Hello Minecraft! Launcher.
|
|
||||||
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
||||||
*/
|
|
||||||
package org.jackhuang.hmcl.upgrade;
|
|
||||||
|
|
||||||
import org.jackhuang.hmcl.Launcher;
|
|
||||||
import org.jackhuang.hmcl.task.FileDownloadTask;
|
|
||||||
import org.jackhuang.hmcl.util.Constants;
|
|
||||||
import org.jackhuang.hmcl.util.FileUtils;
|
|
||||||
import org.jackhuang.hmcl.util.JarUtils;
|
|
||||||
import org.tukaani.xz.XZInputStream;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.jar.JarOutputStream;
|
|
||||||
import java.util.jar.Pack200;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Logging.LOG;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class used to manage the local HMCL repository.
|
|
||||||
*
|
|
||||||
* @author yushijinhun
|
|
||||||
*/
|
|
||||||
final class LocalRepository {
|
|
||||||
private LocalRepository() {}
|
|
||||||
|
|
||||||
private static Path localStorage = Launcher.HMCL_DIRECTORY.toPath().resolve("hmcl.jar");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current stored executable in local repository.
|
|
||||||
*/
|
|
||||||
public static Optional<LocalVersion> getStored() {
|
|
||||||
if (!Files.isRegularFile(localStorage)) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
return Optional.of(localStorage)
|
|
||||||
.flatMap(JarUtils::getImplementationVersion)
|
|
||||||
.map(version -> new LocalVersion(version, localStorage));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void writeToStorage(Path source, boolean checkHeaders) throws IOException {
|
|
||||||
IntegrityChecker.requireVerifiedJar(source);
|
|
||||||
Files.createDirectories(localStorage.getParent());
|
|
||||||
if (checkHeaders) {
|
|
||||||
ExecutableHeaderHelper.copyWithoutHeader(source, localStorage);
|
|
||||||
} else {
|
|
||||||
Files.copy(source, localStorage, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a task that downloads the given version to local repository.
|
|
||||||
*/
|
|
||||||
public static FileDownloadTask downloadFromRemote(RemoteVersion version) throws IOException {
|
|
||||||
Path downloaded = Files.createTempFile("hmcl-update-", null);
|
|
||||||
return new FileDownloadTask(new URL(version.getUrl()), downloaded.toFile(), version.getIntegrityCheck()) {
|
|
||||||
@Override
|
|
||||||
public void execute() throws Exception {
|
|
||||||
super.execute();
|
|
||||||
|
|
||||||
try {
|
|
||||||
switch (version.getType()) {
|
|
||||||
case JAR:
|
|
||||||
writeToStorage(downloaded, false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PACK_XZ:
|
|
||||||
Path unpacked = Files.createTempFile("hmcl-update-unpack-", null);
|
|
||||||
try {
|
|
||||||
try (InputStream in = new XZInputStream(Files.newInputStream(downloaded));
|
|
||||||
JarOutputStream out = new JarOutputStream(Files.newOutputStream(unpacked))) {
|
|
||||||
Pack200.newUnpacker().unpack(in, out);
|
|
||||||
}
|
|
||||||
writeToStorage(unpacked, false);
|
|
||||||
} finally {
|
|
||||||
Files.deleteIfExists(unpacked);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unknown type: " + version.getType());
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
Files.deleteIfExists(downloaded);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies the current HMCL executable to local repository.
|
|
||||||
*/
|
|
||||||
public static void downloadFromCurrent() {
|
|
||||||
Optional<LocalVersion> current = LocalVersion.current();
|
|
||||||
if (current.isPresent()) {
|
|
||||||
Path currentPath = current.get().getLocation();
|
|
||||||
if (!Files.isRegularFile(currentPath)) {
|
|
||||||
LOG.warning("Failed to download " + current.get() + ", it isn't a file");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isSameAsLocalStorage(currentPath)) {
|
|
||||||
LOG.warning("Trying to download from self, ignored");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG.info("Downloading " + current.get());
|
|
||||||
try {
|
|
||||||
writeToStorage(current.get().getLocation(), true);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.log(Level.WARNING, "Failed to download " + current.get(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the executable stored in local repository to the given location.
|
|
||||||
*/
|
|
||||||
public static void applyTo(Path target) throws IOException {
|
|
||||||
if (isSameAsLocalStorage(target)) {
|
|
||||||
throw new IOException("Cannot apply update to self");
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.info("Applying update to " + target);
|
|
||||||
IntegrityChecker.requireVerifiedJar(localStorage);
|
|
||||||
ExecutableHeaderHelper.copyWithHeader(localStorage, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isSameAsLocalStorage(Path path) {
|
|
||||||
return path.toAbsolutePath().equals(localStorage.toAbsolutePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Hello Minecraft! Launcher.
|
|
||||||
* Copyright (C) 2018 huangyuhui <huanghongxun2008@126.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
||||||
*/
|
|
||||||
package org.jackhuang.hmcl.upgrade;
|
|
||||||
|
|
||||||
import org.jackhuang.hmcl.Metadata;
|
|
||||||
import org.jackhuang.hmcl.util.JarUtils;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
class LocalVersion {
|
|
||||||
|
|
||||||
public static Optional<LocalVersion> current() {
|
|
||||||
return JarUtils.thisJar().map(path -> new LocalVersion(Metadata.VERSION, path));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String version;
|
|
||||||
private Path location;
|
|
||||||
|
|
||||||
public LocalVersion(String version, Path location) {
|
|
||||||
this.version = version;
|
|
||||||
this.location = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVersion() {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path getLocation() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "[" + version + " at " + location + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,11 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.upgrade;
|
package org.jackhuang.hmcl.upgrade;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.checkFxUserThread;
|
import static org.jackhuang.hmcl.ui.FXUtils.checkFxUserThread;
|
||||||
import static org.jackhuang.hmcl.util.IntVersionNumber.isIntVersionNumber;
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.thread;
|
import static org.jackhuang.hmcl.util.Lang.thread;
|
||||||
import static org.jackhuang.hmcl.util.Logging.LOG;
|
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||||
import static org.jackhuang.hmcl.util.VersionNumber.asVersion;
|
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -30,6 +29,7 @@ import java.nio.file.Path;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@@ -45,9 +45,12 @@ import org.jackhuang.hmcl.task.TaskExecutor;
|
|||||||
import org.jackhuang.hmcl.ui.Controllers;
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
|
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
|
||||||
import org.jackhuang.hmcl.ui.construct.MessageBox;
|
import org.jackhuang.hmcl.ui.construct.MessageBox;
|
||||||
|
import org.jackhuang.hmcl.util.JarUtils;
|
||||||
import org.jackhuang.hmcl.util.JavaVersion;
|
import org.jackhuang.hmcl.util.JavaVersion;
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
|
|
||||||
@@ -58,9 +61,7 @@ public final class UpdateHandler {
|
|||||||
* @return whether to exit
|
* @return whether to exit
|
||||||
*/
|
*/
|
||||||
public static boolean processArguments(String[] args) {
|
public static boolean processArguments(String[] args) {
|
||||||
if (!isIntVersionNumber(Metadata.VERSION)) {
|
breakForceUpdateFeature();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNestedApplication()) {
|
if (isNestedApplication()) {
|
||||||
// updated from old versions
|
// updated from old versions
|
||||||
@@ -88,33 +89,69 @@ public final class UpdateHandler {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<LocalVersion> local = LocalRepository.getStored();
|
return false;
|
||||||
if (local.isPresent()) {
|
}
|
||||||
int difference = asVersion(local.get().getVersion()).compareTo(asVersion(Metadata.VERSION));
|
|
||||||
|
|
||||||
if (difference < 0) {
|
public static void updateFrom(RemoteVersion version) {
|
||||||
LocalRepository.downloadFromCurrent();
|
checkFxUserThread();
|
||||||
|
|
||||||
} else if (difference > 0) {
|
Path downloaded;
|
||||||
Optional<LocalVersion> current = LocalVersion.current();
|
try {
|
||||||
if (current.isPresent() && IntegrityChecker.isSelfVerified()) {
|
downloaded = Files.createTempFile("hmcl-update-", ".jar");
|
||||||
try {
|
} catch (IOException e) {
|
||||||
requestUpdate(local.get().getLocation(), current.get().getLocation());
|
LOG.log(Level.WARNING, "Failed to create temp file", e);
|
||||||
} catch (IOException e) {
|
return;
|
||||||
LOG.log(Level.WARNING, "Failed to update from local repository", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
LocalRepository.downloadFromCurrent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
Task task = new HMCLDownloadTask(version, downloaded);
|
||||||
|
|
||||||
|
TaskExecutor executor = task.executor();
|
||||||
|
Region dialog = Controllers.taskDialog(executor, i18n("message.downloading"), "", null);
|
||||||
|
thread(() -> {
|
||||||
|
boolean success = executor.test();
|
||||||
|
Platform.runLater(() -> dialog.fireEvent(new DialogCloseEvent()));
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
try {
|
||||||
|
if (!IntegrityChecker.isSelfVerified()) {
|
||||||
|
throw new IOException("Current JAR is not verified");
|
||||||
|
}
|
||||||
|
|
||||||
|
requestUpdate(downloaded, getCurrentLocation());
|
||||||
|
System.exit(0);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.log(Level.WARNING, "Failed to update to " + version, e);
|
||||||
|
Platform.runLater(() -> Controllers.dialog(StringUtils.getStackTrace(e), i18n("update.failed"), MessageBox.ERROR_MESSAGE));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Throwable e = task.getLastException();
|
||||||
|
LOG.log(Level.WARNING, "Failed to update to " + version, e);
|
||||||
|
Platform.runLater(() -> Controllers.dialog(e.toString(), i18n("update.failed"), MessageBox.ERROR_MESSAGE));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyUpdate(Path target) throws IOException {
|
||||||
|
LOG.info("Applying update to " + target);
|
||||||
|
|
||||||
|
Path self = getCurrentLocation();
|
||||||
|
IntegrityChecker.requireVerifiedJar(self);
|
||||||
|
ExecutableHeaderHelper.copyWithHeader(self, target);
|
||||||
|
|
||||||
|
Optional<Path> newFilename = tryRename(target, Metadata.VERSION);
|
||||||
|
if (newFilename.isPresent()) {
|
||||||
|
LOG.info("Move " + target + " to " + newFilename.get());
|
||||||
|
try {
|
||||||
|
Files.move(target, newFilename.get());
|
||||||
|
target = newFilename.get();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.log(Level.WARNING, "Failed to move target", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startJava(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void requestUpdate(Path updateTo, Path self) throws IOException {
|
private static void requestUpdate(Path updateTo, Path self) throws IOException {
|
||||||
@@ -122,28 +159,6 @@ public final class UpdateHandler {
|
|||||||
startJava(updateTo, "--apply-to", self.toString());
|
startJava(updateTo, "--apply-to", self.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyUpdate(Path target) throws IOException {
|
|
||||||
LocalRepository.applyTo(target);
|
|
||||||
|
|
||||||
Optional<String> newVersion = LocalRepository.getStored().map(LocalVersion::getVersion);
|
|
||||||
if (newVersion.isPresent()) {
|
|
||||||
Optional<Path> newFilename = tryRename(target, newVersion.get());
|
|
||||||
if (newFilename.isPresent()) {
|
|
||||||
LOG.info("Move " + target + " to " + newFilename.get());
|
|
||||||
try {
|
|
||||||
Files.move(target, newFilename.get());
|
|
||||||
target = newFilename.get();
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.log(Level.WARNING, "Failed to move target", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG.warning("Failed to find local repository");
|
|
||||||
}
|
|
||||||
|
|
||||||
startJava(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void startJava(Path jar, String... appArgs) throws IOException {
|
private static void startJava(Path jar, String... appArgs) throws IOException {
|
||||||
List<String> commandline = new ArrayList<>();
|
List<String> commandline = new ArrayList<>();
|
||||||
commandline.add(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath());
|
commandline.add(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath());
|
||||||
@@ -159,49 +174,6 @@ public final class UpdateHandler {
|
|||||||
.start();
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateFrom(RemoteVersion version) {
|
|
||||||
checkFxUserThread();
|
|
||||||
|
|
||||||
Task task;
|
|
||||||
try {
|
|
||||||
task = LocalRepository.downloadFromRemote(version);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.log(Level.WARNING, "Failed to create upgrade download task", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TaskExecutor executor = task.executor();
|
|
||||||
Region dialog = Controllers.taskDialog(executor, i18n("message.downloading"), "", null);
|
|
||||||
thread(() -> {
|
|
||||||
boolean success = executor.test();
|
|
||||||
Platform.runLater(() -> dialog.fireEvent(new DialogCloseEvent()));
|
|
||||||
if (success) {
|
|
||||||
try {
|
|
||||||
Optional<LocalVersion> current = LocalVersion.current();
|
|
||||||
Optional<LocalVersion> stored = LocalRepository.getStored();
|
|
||||||
if (!current.isPresent()) {
|
|
||||||
throw new IOException("Failed to find current HMCL location");
|
|
||||||
}
|
|
||||||
if (!stored.isPresent()) {
|
|
||||||
throw new IOException("Failed to find local repository, this shouldn't happen");
|
|
||||||
}
|
|
||||||
if (!IntegrityChecker.isSelfVerified()) {
|
|
||||||
throw new IOException("Current JAR is not verified");
|
|
||||||
}
|
|
||||||
requestUpdate(stored.get().getLocation(), current.get().getLocation());
|
|
||||||
System.exit(0);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.log(Level.WARNING, "Failed to update to " + version, e);
|
|
||||||
Platform.runLater(() -> Controllers.dialog(StringUtils.getStackTrace(e), i18n("update.failed"), MessageBox.ERROR_MESSAGE));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Throwable e = task.getLastException();
|
|
||||||
LOG.log(Level.WARNING, "Failed to update to " + version, e);
|
|
||||||
Platform.runLater(() -> Controllers.dialog(e.toString(), i18n("update.failed"), MessageBox.ERROR_MESSAGE));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Optional<Path> tryRename(Path path, String newVersion) {
|
private static Optional<Path> tryRename(Path path, String newVersion) {
|
||||||
String filename = path.getFileName().toString();
|
String filename = path.getFileName().toString();
|
||||||
Matcher matcher = Pattern.compile("^(?<prefix>[hH][mM][cC][lL][.-])(?<version>\\d+(?:\\.\\d+)*)(?<suffix>\\.[^.]+)$").matcher(filename);
|
Matcher matcher = Pattern.compile("^(?<prefix>[hH][mM][cC][lL][.-])(?<version>\\d+(?:\\.\\d+)*)(?<suffix>\\.[^.]+)$").matcher(filename);
|
||||||
@@ -214,6 +186,10 @@ public final class UpdateHandler {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Path getCurrentLocation() throws IOException {
|
||||||
|
return JarUtils.thisJar().orElseThrow(() -> new IOException("Failed to find current HMCL location"));
|
||||||
|
}
|
||||||
|
|
||||||
// ==== support for old versions ===
|
// ==== support for old versions ===
|
||||||
private static void performMigration() throws IOException {
|
private static void performMigration() throws IOException {
|
||||||
LOG.info("Migrating from old versions");
|
LOG.info("Migrating from old versions");
|
||||||
@@ -221,17 +197,7 @@ public final class UpdateHandler {
|
|||||||
Path location = getParentApplicationLocation()
|
Path location = getParentApplicationLocation()
|
||||||
.orElseThrow(() -> new IOException("Failed to get parent application location"));
|
.orElseThrow(() -> new IOException("Failed to get parent application location"));
|
||||||
|
|
||||||
Optional<LocalVersion> local = LocalRepository.getStored();
|
requestUpdate(getCurrentLocation(), location);
|
||||||
if (!local.isPresent() ||
|
|
||||||
asVersion(local.get().getVersion()).compareTo(asVersion(Metadata.VERSION)) < 0) {
|
|
||||||
LocalRepository.downloadFromCurrent();
|
|
||||||
}
|
|
||||||
local = LocalRepository.getStored();
|
|
||||||
if (!local.isPresent()) {
|
|
||||||
throw new IOException("Failed to find local repository");
|
|
||||||
}
|
|
||||||
|
|
||||||
requestUpdate(local.get().getLocation(), location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -265,7 +231,7 @@ public final class UpdateHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isFirstLaunchAfterUpgrade() {
|
private static boolean isFirstLaunchAfterUpgrade() {
|
||||||
Optional<Path> currentPath = LocalVersion.current().map(LocalVersion::getLocation);
|
Optional<Path> currentPath = JarUtils.thisJar();
|
||||||
if (currentPath.isPresent()) {
|
if (currentPath.isPresent()) {
|
||||||
Path updated = Launcher.HMCL_DIRECTORY.toPath().resolve("HMCL-" + Metadata.VERSION + ".jar");
|
Path updated = Launcher.HMCL_DIRECTORY.toPath().resolve("HMCL-" + Metadata.VERSION + ".jar");
|
||||||
if (currentPath.get().toAbsolutePath().equals(updated.toAbsolutePath())) {
|
if (currentPath.get().toAbsolutePath().equals(updated.toAbsolutePath())) {
|
||||||
@@ -274,5 +240,21 @@ public final class UpdateHandler {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void breakForceUpdateFeature() {
|
||||||
|
try {
|
||||||
|
Path hmclVersionJson = Launcher.HMCL_DIRECTORY.toPath().resolve("hmclver.json");
|
||||||
|
if (Files.isRegularFile(hmclVersionJson)) {
|
||||||
|
Map<?, ?> content = new Gson().fromJson(new String(Files.readAllBytes(hmclVersionJson), UTF_8), Map.class);
|
||||||
|
Object ver = content.get("ver");
|
||||||
|
if (ver instanceof String && ((String) ver).startsWith("3.")) {
|
||||||
|
Files.delete(hmclVersionJson);
|
||||||
|
LOG.info("Successfully broke the force update feature");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.log(Level.WARNING, "Failed to break the force update feature", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
// ====
|
// ====
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ update.checking=Checking for updates
|
|||||||
update.failed=Failed to perform upgrade
|
update.failed=Failed to perform upgrade
|
||||||
update.found=Update Available!
|
update.found=Update Available!
|
||||||
update.newest_version=Latest version: %s
|
update.newest_version=Latest version: %s
|
||||||
update.note=Development version contains more functionality and bug fixes as well as more possible bugs. And this will affect all HMCL installations in your computer.
|
update.note=Development version contains more functionality and bug fixes as well as more possible bugs.
|
||||||
update.latest=This is latest Version.
|
update.latest=This is latest Version.
|
||||||
update.no_browser=Cannot open any browser. The link has been copied to the clipboard. Paste it to a browser address bar to update.
|
update.no_browser=Cannot open any browser. The link has been copied to the clipboard. Paste it to a browser address bar to update.
|
||||||
update.tooltip=Update
|
update.tooltip=Update
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ update.checking=正在檢查更新
|
|||||||
update.failed=更新失敗
|
update.failed=更新失敗
|
||||||
update.found=發現到更新
|
update.found=發現到更新
|
||||||
update.newest_version=最新版本為:%s
|
update.newest_version=最新版本為:%s
|
||||||
update.note=開發版包含更多的功能以及錯誤修復,但也可能會包含其他的問題。選擇更新到開發版,將會把你電腦的所有 HMCL 更新至開發版
|
update.note=開發版包含更多的功能以及錯誤修復,但也可能會包含其他的問題。
|
||||||
update.latest=目前版本為最新版本
|
update.latest=目前版本為最新版本
|
||||||
update.no_browser=無法打開瀏覽器,網址已經複製到剪貼簿了,您可以手動複製網址打開頁面
|
update.no_browser=無法打開瀏覽器,網址已經複製到剪貼簿了,您可以手動複製網址打開頁面
|
||||||
update.tooltip=更新
|
update.tooltip=更新
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ update.checking=正在检查更新
|
|||||||
update.failed=更新失败
|
update.failed=更新失败
|
||||||
update.found=发现更新
|
update.found=发现更新
|
||||||
update.newest_version=最新版本为:%s
|
update.newest_version=最新版本为:%s
|
||||||
update.note=开发版包含更多的功能以及错误修复,但也可能会包含其他的问题。选择更新到开发版导致你电脑中所有的 HMCL 更新至开发版
|
update.note=开发版包含更多的功能以及错误修复,但也可能会包含其他的问题。
|
||||||
update.latest=当前版本为最新版本
|
update.latest=当前版本为最新版本
|
||||||
update.no_browser=无法打开浏览器,网址已经复制到剪贴板了,您可以手动粘贴网址打开页面
|
update.no_browser=无法打开浏览器,网址已经复制到剪贴板了,您可以手动粘贴网址打开页面
|
||||||
update.tooltip=更新
|
update.tooltip=更新
|
||||||
|
|||||||
Reference in New Issue
Block a user