true
if an update is available, false
otherwise. Always true
for SNAPSHOT versions.
+ */
+ static boolean isUpdateAvailable(String updateVersion, String installedVersion) {
+ if (installedVersion.contains("SNAPSHOT")) {
+ return true; // SNAPSHOT versions are always considered to be outdated.
+ } else {
+ return SemVerComparator.INSTANCE.compare(updateVersion, installedVersion) > 0;
+ }
+ }
+
+ /**
+ * Checks whether an update is available.
+ * @param currentVersion The full version string of the currently installed application, e.g. "1.2.3-beta4".
+ * @return true
if an update is available, false
otherwise.
+ * @throws UpdateFailedException If the availability of an update could not be determined
+ */
+ @Blocking
+ boolean isUpdateAvailable(String currentVersion) throws UpdateFailedException;
+
+ /**
+ * Performs as much as possible to prepare the update. This may include downloading the update, checking signatures, etc.
+ * @return a new {@link UpdateProcess} that can be used to monitor the progress of the update preparation. The task will complete when the preparation is done.
+ * @throws UpdateFailedException If no update process can be started, e.g. due to network or I/O issues.
+ */
+ UpdateProcess prepareUpdate() throws UpdateFailedException;
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/cryptomator/integrations/update/UpdateProcess.java b/src/main/java/org/cryptomator/integrations/update/UpdateProcess.java
new file mode 100644
index 0000000..1b5811a
--- /dev/null
+++ b/src/main/java/org/cryptomator/integrations/update/UpdateProcess.java
@@ -0,0 +1,54 @@
+package org.cryptomator.integrations.update;
+
+import org.jetbrains.annotations.ApiStatus;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+@ApiStatus.Experimental
+public interface UpdateProcess {
+
+ /**
+ * A thread-safe method to check the progress of the update preparation.
+ * @return a value between 0.0 and 1.0 indicating the progress of the update preparation or -1.0 indicating indeterminate progress.
+ */
+ double preparationProgress();
+
+ /**
+ * Cancels the update process and cleans up any resources that were used during the preparation.
+ */
+ void cancel();
+
+ /**
+ * Blocks the current thread until the update preparation is complete or an error occurs.
+ * + * If the preparation is already complete, this method returns immediately. + * + * @throws InterruptedException if the current thread is interrupted while waiting. + */ + void await() throws InterruptedException; + + /** + * Blocks the current thread until the update preparation is complete or an error occurs, or until the specified timeout expires. + *
+ * If the preparation is already complete, this method returns immediately. + * + * @param timeout the maximum time to wait + * @param unit the time unit of the {@code timeout} argument + * @return true if the update is prepared + */ + boolean await(long timeout, TimeUnit unit) throws InterruptedException; + + /** + * Once the update preparation is complete, this method can be called to launch the external update process. + *
+ * This method shall be called after making sure that the application is ready to be restarted, e.g. after locking all vaults.
+ *
+ * @return a {@link ProcessHandle} that represents the external update process.
+ * @throws IllegalStateException if the update preparation is not complete or if the update process cannot be launched.
+ * @throws IOException if the update preparation failed or starting the update process failed
+ */
+ ProcessHandle applyUpdate() throws IllegalStateException, IOException;
+
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/cryptomator/integrations/update/SemVerComparatorTest.java b/src/test/java/org/cryptomator/integrations/update/SemVerComparatorTest.java
new file mode 100644
index 0000000..ac080d8
--- /dev/null
+++ b/src/test/java/org/cryptomator/integrations/update/SemVerComparatorTest.java
@@ -0,0 +1,79 @@
+package org.cryptomator.integrations.update;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.util.Comparator;
+
+public class SemVerComparatorTest {
+
+ private final Comparator