From 9926a79503c9bd6454c076f2b60cd577f6061e4d Mon Sep 17 00:00:00 2001
From: Kai Reinhard <K.Reinhard@micromata.de>
Date: Sat, 19 Feb 2022 07:29:58 +0000
Subject: [PATCH] Using Borg version 1.1.17 as default. Version is now configurable via web client and json file.

---
 borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/ServerConfiguration.kt    |    4 +
 borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java       |   61 +++++++++------
 borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx                   |   26 ++++--
 borgbutler-core/src/main/kotlin/de/micromata/borgbutler/config/Configuration.kt            |    7 +
 borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgConfig.java             |   50 ++++++------
 borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfo.kt        |    8 +-
 borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgConfigTest.java         |   20 +++++
 borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgInstallationTest.java   |   17 ++++
 borgbutler-core/src/test/resources/log4j.properties                                        |    1 
 borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationInfo.kt |    4 
 /dev/null                                                                                  |   20 -----
 borgbutler-server/src/test/kotlin/de/micromata/borgbutler/server/user/UserFilterTest.kt    |    1 
 borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationRest.kt |   10 +-
 borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfoRest.kt    |   10 +-
 14 files changed, 137 insertions(+), 102 deletions(-)

diff --git a/borgbutler-core/src/main/kotlin/de/micromata/borgbutler/config/Configuration.kt b/borgbutler-core/src/main/kotlin/de/micromata/borgbutler/config/Configuration.kt
index e375483..f45429c 100644
--- a/borgbutler-core/src/main/kotlin/de/micromata/borgbutler/config/Configuration.kt
+++ b/borgbutler-core/src/main/kotlin/de/micromata/borgbutler/config/Configuration.kt
@@ -30,8 +30,6 @@
     /**
      * The borg version to install from github (optional).
      */
-    // @JsonIgnore needed by client: ConfigurationserverTab.jsx fails otherwise (conflicting borgVersion fields).
-    @JsonIgnore
     var borgVersion: String? = null
 
     /**
@@ -101,6 +99,7 @@
 
     fun copyFrom(other: Configuration) {
         borgCommand = other.borgCommand
+        borgVersion = other.borgVersion
         maxArchiveContentCacheCapacityMb = other.maxArchiveContentCacheCapacityMb
         showDemoRepos = other.showDemoRepos
     }
@@ -123,6 +122,10 @@
         return this
     }
 
+    override fun toString(): String {
+        return "borgCommand=[$borgCommand], borgVersion=[$borgVersion], workingDir=[$workingDir], maxArchiveContentCacheCapacityMb=[$maxArchiveContentCacheCapacityMb], showDemoRepos=[$showDemoRepos]"
+    }
+
     companion object {
         /**
          * Default dir name for restoring archives.
diff --git a/borgbutler-core/src/test/resources/log4j.properties b/borgbutler-core/src/test/resources/log4j.properties
index 7a86484..6321d9e 100644
--- a/borgbutler-core/src/test/resources/log4j.properties
+++ b/borgbutler-core/src/test/resources/log4j.properties
@@ -1,5 +1,4 @@
 log4j.rootLogger=info, stdout
-log4j.logger.de.micromata.paypal=debug
 
 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgVersion.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgConfig.java
similarity index 76%
rename from borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgVersion.java
rename to borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgConfig.java
index 0f4c91f..194da8a 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgVersion.java
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgConfig.java
@@ -2,12 +2,8 @@
 
 import org.apache.commons.lang3.StringUtils;
 
-public class BorgVersion {
-    public static final String BORG_DEFAULT_DOWNLOAD_VERSION = "1.1.16";
-
-    private static final String BORG_VERSION = BORG_DEFAULT_DOWNLOAD_VERSION;
-
-    private String binariesDownloadVersion = BORG_DEFAULT_DOWNLOAD_VERSION;
+public class BorgConfig {
+    public static final String BORG_DEFAULT_DOWNLOAD_VERSION = "1.1.17";
 
     private String[][] borgBinaries = {
             {"freebsd64", "FreeBSD 64"},
@@ -18,7 +14,7 @@
     private String minimumRequiredBorgVersion = "1.1.8";
 
     public String getBinariesDownloadUrl() {
-        return "https://github.com/borgbackup/borg/releases/download/" + binariesDownloadVersion + "/";
+        return "https://github.com/borgbackup/borg/releases/download/" + version + "/";
     }
 
     /**
@@ -28,10 +24,10 @@
     private String borgBinary;
 
     private boolean versionOK = false;
-    private String version;
+    private String version = BORG_DEFAULT_DOWNLOAD_VERSION;
     private String statusMessage;
 
-    public BorgVersion copyFrom(BorgVersion other) {
+    public BorgConfig copyFrom(BorgConfig other) {
         this.borgBinary = other.borgBinary;
         this.versionOK = other.versionOK;
         this.version = other.version;
@@ -39,18 +35,6 @@
         return this;
     }
 
-    public String getBinariesDownloadVersion() {
-        return this.binariesDownloadVersion;
-    }
-
-    public void setBinariesDownloadVersion(String binariesDownloadVersion) {
-        if (StringUtils.isNotBlank(binariesDownloadVersion)) {
-            this.binariesDownloadVersion = binariesDownloadVersion;
-        } else {
-            this.binariesDownloadVersion = BORG_DEFAULT_DOWNLOAD_VERSION;
-        }
-    }
-
     public String[][] getBorgBinaries() {
         return this.borgBinaries;
     }
@@ -78,22 +62,26 @@
         return this.statusMessage;
     }
 
-    BorgVersion setBorgBinary(String borgBinary) {
+    BorgConfig setBorgBinary(String borgBinary) {
         this.borgBinary = borgBinary;
         return this;
     }
 
-    BorgVersion setVersionOK(boolean versionOK) {
+    BorgConfig setVersionOK(boolean versionOK) {
         this.versionOK = versionOK;
         return this;
     }
 
-    BorgVersion setVersion(String version) {
-        this.version = version;
+    BorgConfig setVersion(String version) {
+        if (StringUtils.isNotBlank(version)) {
+            this.version = version;
+        } else {
+            this.version = BORG_DEFAULT_DOWNLOAD_VERSION;
+        }
         return this;
     }
 
-    BorgVersion setStatusMessage(String statusMessage) {
+    BorgConfig setStatusMessage(String statusMessage) {
         this.statusMessage = statusMessage;
         return this;
     }
@@ -125,4 +113,14 @@
         }
         return version.split("\\.");
     }
+
+    @Override
+    public String toString() {
+        return "BorgConfig{" +
+                ", borgBinary='" + borgBinary + '\'' +
+                ", versionOK=" + versionOK +
+                ", version='" + version + '\'' +
+                ", statusMessage='" + statusMessage + '\'' +
+                '}';
+    }
 }
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java
index de65328..4516747 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java
@@ -26,7 +26,7 @@
         return instance;
     }
 
-    private BorgVersion borgVersion = new BorgVersion();
+    private BorgConfig borgConfig = new BorgConfig();
 
     public void initialize() {
         Configuration configuration = ConfigurationHandler.getConfiguration();
@@ -35,10 +35,10 @@
                 return;
             }
         }
-        borgVersion.setBinariesDownloadVersion(configuration.getBorgVersion());
+        borgConfig.setVersion(configuration.getBorgVersion());
         initialize(getBinary(RunningMode.getOSType()));
-        if (!borgVersion.isVersionOK()) {
-            log.warn("No working borg version found. Please configure a borg version with minimal version '" + borgVersion.getMinimumRequiredBorgVersion() + "'.");
+        if (!borgConfig.isVersionOK()) {
+            log.warn("No working borg version found. Please configure a borg version with minimal version '" + borgConfig.getMinimumRequiredBorgVersion() + "'.");
         }
     }
 
@@ -46,13 +46,19 @@
      * Configures a new borg configuration if modifications was done.
      *
      * @param newConfiguration The new configuration with the (new) borg command to use (executable).
-     * @param borgBinary       The id of the borg binary (Mac OS X, Linux 64, manual etc.)
+     * @param newBorgConfig     The new config, including the id of the borg binary (Mac OS X, Linux 64, manual etc.) and version.
      */
-    public void configure(ServerConfiguration newConfiguration, String borgBinary) {
+    public void configure(ServerConfiguration newConfiguration, BorgConfig newBorgConfig) {
         ServerConfiguration configuration = ServerConfiguration.get();
-        boolean borgBinaryChanged = !StringUtils.equals(borgVersion.getBorgBinary(), borgBinary);
-        borgVersion.setBorgBinary(borgBinary); // Update borg binary (if changed).
-        boolean manualBorgCommand = "manual".equals(borgBinary);
+        String oldBorgBinary = borgConfig.getBorgBinary();
+        String oldVersion = borgConfig.getVersion();
+        String newBorgBinary = newBorgConfig.getBorgBinary();
+        String newVersion = newConfiguration.getBorgVersion();
+        boolean borgBinaryChanged = !StringUtils.equals(oldBorgBinary, newBorgBinary) ||
+                !StringUtils.equals(oldVersion, newVersion);
+        borgConfig.setBorgBinary(newBorgBinary); // Update borg binary (if changed).
+        borgConfig.setVersion(newVersion);
+        boolean manualBorgCommand = "manual".equals( newBorgConfig.getBorgBinary());
         if (manualBorgCommand) {
             boolean borgCommandChanged = !StringUtils.equals(newConfiguration.getBorgCommand(), configuration.getBorgCommand());
             if (borgCommandChanged) {
@@ -61,9 +67,16 @@
             }
         } else {
             if (borgBinaryChanged) {
-                initialize(getBinary(borgBinary));
+                initialize(getBinary(newBorgBinary));
             }
             newConfiguration.setBorgCommand(configuration.getBorgCommand()); // borg command of this class overwrites new configuration for mode != 'manual'.
+            newConfiguration.setBorgVersion(newVersion);
+            if (!StringUtils.equals(oldVersion, newVersion)) {
+                log.info("Version '" + oldVersion + "' -> '" + newVersion + "'.");
+            }
+            if (!StringUtils.equals(oldBorgBinary, newBorgBinary)) {
+                log.info("Binary '" + oldBorgBinary + "' -> '" + newBorgBinary + "'.");
+            }
         }
     }
 
@@ -75,7 +88,7 @@
         File file = download(binary);
         if (file != null) {
             configuration.setBorgCommand(file.getAbsolutePath());
-            borgVersion.setBorgBinary(binary[0]);
+            borgConfig.setBorgBinary(binary[0]);
         }
         return version(configuration);
     }
@@ -83,9 +96,9 @@
     private boolean version(Configuration configuration) {
         String borgCommand = configuration.getBorgCommand();
         if (StringUtils.isNotBlank(borgCommand)) {
-            for (String[] borgBinary : borgVersion.getBorgBinaries()) {
+            for (String[] borgBinary : borgConfig.getBorgBinaries()) {
                 if (borgCommand.contains(borgBinary[0])) {
-                    borgVersion.setBorgBinary(borgBinary[0]);
+                    borgConfig.setBorgBinary(borgBinary[0]);
                     break;
                 }
             }
@@ -94,22 +107,22 @@
         boolean versionOK = false;
         String msg = null;
         if (versionString != null) {
-            borgVersion.setVersion(versionString);
-            int cmp = BorgVersion.compareVersions(versionString, borgVersion.getMinimumRequiredBorgVersion());
+            borgConfig.setVersion(versionString);
+            int cmp = BorgConfig.compareVersions(versionString, borgConfig.getMinimumRequiredBorgVersion());
             if (cmp < 0) {
-                msg = "Found borg version '" + versionString + "' is less than minimum required version '" + borgVersion.getMinimumRequiredBorgVersion() + "'.";
+                msg = "Found borg version '" + versionString + "' is less than minimum required version '" + borgConfig.getMinimumRequiredBorgVersion() + "'.";
                 log.info(msg);
             } else {
                 versionOK = true;
-                msg = "Found borg '" + configuration.getBorgCommand() + "', version: " + versionString + " (equals to or newer than '" + borgVersion.getMinimumRequiredBorgVersion()
+                msg = "Found borg '" + configuration.getBorgCommand() + "', version: " + versionString + " (equals to or newer than '" + borgConfig.getMinimumRequiredBorgVersion()
                         + "', OK).";
                 log.info(msg);
             }
         } else {
             msg = "Couldn't execute borg command '" + configuration.getBorgCommand() + "'.";
         }
-        borgVersion.setVersionOK(versionOK);
-        borgVersion.setStatusMessage(msg);
+        borgConfig.setVersionOK(versionOK);
+        borgConfig.setStatusMessage(msg);
         return versionOK;
     }
 
@@ -133,7 +146,7 @@
         if (os == null) {
             return null;
         }
-        for (String[] binary : borgVersion.getBorgBinaries()) {
+        for (String[] binary : borgConfig.getBorgBinaries()) {
             if (binary[0].contains(os)) {
                 return binary;
             }
@@ -156,7 +169,7 @@
             // File already downloaded, nothing to do.
             return file;
         }
-        String url = borgVersion.getBinariesDownloadUrl() + getDownloadFilename(binary);
+        String url = borgConfig.getBinariesDownloadUrl() + getDownloadFilename(binary);
         log.info("Trying to download borg binary '" + binary[0] + "' (" + binary[1] + ") from url: " + url + "...");
         HttpClientBuilder builder = HttpClients.custom()
                 .setDefaultRequestConfig(RequestConfig.custom()
@@ -186,7 +199,7 @@
             log.info("Creating binary directory: " + dir.getAbsolutePath());
             dir.mkdirs();
         }
-        return new File(dir, getDownloadFilename(binary) + "-" + borgVersion.getBinariesDownloadVersion());
+        return new File(dir, getDownloadFilename(binary) + "-" + borgConfig.getVersion());
     }
 
     private String getDownloadFilename(String[] binary) {
@@ -196,7 +209,7 @@
     private BorgInstallation() {
     }
 
-    public BorgVersion getBorgVersion() {
-        return this.borgVersion;
+    public BorgConfig getBorgConfig() {
+        return this.borgConfig;
     }
 }
diff --git a/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/ServerConfiguration.kt b/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/ServerConfiguration.kt
index fb59362..683a2b1 100644
--- a/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/ServerConfiguration.kt
+++ b/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/ServerConfiguration.kt
@@ -20,6 +20,10 @@
         webDevelopmentMode = other.webDevelopmentMode
     }
 
+    override fun toString(): String {
+        return "${super.toString()}, port=[$port], webDevelopmentMode=[$webDevelopmentMode]"
+    }
+
     companion object {
         val supportedLanguages = arrayOf("en", "de")
         const val WEBSERVER_PORT_DEFAULT = 9042
diff --git a/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationInfo.kt b/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationInfo.kt
index a5e0b8f..8075e37 100644
--- a/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationInfo.kt
+++ b/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationInfo.kt
@@ -1,9 +1,9 @@
 package de.micromata.borgbutler.server.rest
 
-import de.micromata.borgbutler.server.BorgVersion
+import de.micromata.borgbutler.server.BorgConfig
 import de.micromata.borgbutler.server.ServerConfiguration
 
 class ConfigurationInfo(
     var serverConfiguration: ServerConfiguration? = null,
-    var borgVersion: BorgVersion? = null
+    var borgConfig: BorgConfig? = null
 )
diff --git a/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationRest.kt b/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationRest.kt
index 29dba18..1fff9bf 100644
--- a/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationRest.kt
+++ b/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/ConfigurationRest.kt
@@ -2,13 +2,11 @@
 
 import de.micromata.borgbutler.cache.ButlerCache
 import de.micromata.borgbutler.config.ConfigurationHandler
-import de.micromata.borgbutler.json.JsonUtils
 import de.micromata.borgbutler.server.BorgInstallation
 import de.micromata.borgbutler.server.ServerConfiguration
 import de.micromata.borgbutler.server.user.UserData
 import de.micromata.borgbutler.server.user.UserManager
 import mu.KotlinLogging
-import org.apache.commons.lang3.StringUtils
 import org.springframework.web.bind.annotation.*
 
 private val log = KotlinLogging.logger {}
@@ -21,19 +19,19 @@
     fun getConfig(): ConfigurationInfo {
         val configurationInfo = ConfigurationInfo()
         configurationInfo.serverConfiguration = ServerConfiguration.get()
-        configurationInfo.borgVersion = BorgInstallation.getInstance().borgVersion
+        configurationInfo.borgConfig = BorgInstallation.getInstance().borgConfig
         return configurationInfo
     }
 
     @PostMapping("config")
     fun setConfig(@RequestBody configurationInfo: ConfigurationInfo) {
-        val configurationHandler = ConfigurationHandler.getInstance()
-        BorgInstallation.getInstance()
-            .configure(configurationInfo.serverConfiguration, configurationInfo.borgVersion?.borgBinary)
+        log.info("server-config: ${configurationInfo.serverConfiguration}, borg-binary: ${configurationInfo.borgConfig?.borgBinary}")
+        BorgInstallation.getInstance().configure(configurationInfo.serverConfiguration, configurationInfo.borgConfig)
         val configuration: ServerConfiguration = ServerConfiguration.get()
         configurationInfo.serverConfiguration?.let {
             configuration.copyFrom(it)
         }
+        val configurationHandler = ConfigurationHandler.getInstance()
         configurationHandler.save()
     }
 
diff --git a/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfo.kt b/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfo.kt
index 3b8e904..38393df 100644
--- a/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfo.kt
+++ b/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfo.kt
@@ -1,7 +1,7 @@
 package de.micromata.borgbutler.server.rest
 
 import de.micromata.borgbutler.BorgQueueStatistics
-import de.micromata.borgbutler.server.BorgVersion
+import de.micromata.borgbutler.server.BorgConfig
 
 /**
  * Statistics of all the job queues, especially the number of total queued and running jobs.
@@ -13,7 +13,7 @@
         private set
     var configurationOK = false
         private set
-    var borgVersion: BorgVersion? = null
+    var borgConfig: BorgConfig? = null
         private set
 
     fun setQueueStatistics(queueStatistics: BorgQueueStatistics?): SystemInfo {
@@ -26,8 +26,8 @@
         return this
     }
 
-    fun setBorgVersion(borgVersion: BorgVersion?): SystemInfo {
-        this.borgVersion = borgVersion
+    fun setBorgConfig(borgConfig: BorgConfig?): SystemInfo {
+        this.borgConfig = borgConfig
         return this
     }
 }
diff --git a/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfoRest.kt b/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfoRest.kt
index 90a79f1..a35ec07 100644
--- a/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfoRest.kt
+++ b/borgbutler-server/src/main/kotlin/de/micromata/borgbutler/server/rest/SystemInfoRest.kt
@@ -16,11 +16,11 @@
      */
     @GetMapping("info")
     fun statistics(): SystemInfo {
-        val borgVersion = BorgInstallation.getInstance().borgVersion
-        val systemInfonfo = SystemInfo()
+        val borgConfig = BorgInstallation.getInstance().borgConfig
+        val systemInfo = SystemInfo()
             .setQueueStatistics(BorgQueueExecutor.getInstance().statistics)
-            .setConfigurationOK(borgVersion.isVersionOK)
-            .setBorgVersion(borgVersion)
-        return systemInfonfo
+            .setConfigurationOK(borgConfig.isVersionOK)
+            .setBorgConfig(borgConfig)
+        return systemInfo
     }
 }
diff --git a/borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgConfigTest.java b/borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgConfigTest.java
new file mode 100644
index 0000000..69839c4
--- /dev/null
+++ b/borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgConfigTest.java
@@ -0,0 +1,20 @@
+package de.micromata.borgbutler.server;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class BorgConfigTest {
+
+    @Test
+    void versionCompareTest() {
+        Assertions.assertThrows(IllegalArgumentException.class, () -> {
+            BorgConfig.compareVersions(null, "");
+        });
+        Assertions.assertThrows(IllegalArgumentException.class, () -> {
+            BorgConfig.compareVersions("", "");
+        });
+        Assertions.assertEquals(-1, BorgConfig.compareVersions("1.1.8", "1.1.16"));
+        Assertions.assertEquals(0, BorgConfig.compareVersions("1.1.8", "1.1.8"));
+        Assertions.assertEquals(1, BorgConfig.compareVersions("1.1.16", "1.1.8"));
+    }
+}
diff --git a/borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgInstallationTest.java b/borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgInstallationTest.java
index dc97e98..c74408f 100644
--- a/borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgInstallationTest.java
+++ b/borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgInstallationTest.java
@@ -21,9 +21,24 @@
         borgInstallation.initialize();
     }
 
+
+    @Test
+    void configureTest() {
+        ConfigurationHandler.setConfigClazz(ServerConfiguration.class);
+        BorgInstallation borgInstallation = BorgInstallation.getInstance();
+        borgInstallation.initialize();
+        BorgConfig borgConfig = new BorgConfig();
+        borgConfig.setVersion("1.1.15");
+        borgConfig.setBorgBinary("freebsd64");
+        ServerConfiguration serverConfig = ServerConfiguration.get();
+        borgInstallation.configure(serverConfig, borgConfig);
+        String expected = "freebsd64-1.1.15";
+        assertTrue(serverConfig.getBorgCommand().endsWith(expected), "String '" + serverConfig.getBorgCommand() + "' should end with '" + expected + "'.");
+    }
+
     @Test
     void downloadTest() {
-        String version = new BorgVersion().getBinariesDownloadVersion();
+        String version = new BorgConfig().getVersion();
         checkDownload(RunningMode.OSType.LINUX, "borg-linux64-" + version);
         checkDownload(RunningMode.OSType.MAC_OS, "borg-macosx64-" + version);
         checkDownload(RunningMode.OSType.FREEBSD, "borg-freebsd64-" + version);
diff --git a/borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgVersionTest.java b/borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgVersionTest.java
deleted file mode 100644
index 0d233c7..0000000
--- a/borgbutler-server/src/test/java/de/micromata/borgbutler/server/BorgVersionTest.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.micromata.borgbutler.server;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-public class BorgVersionTest {
-
-    @Test
-    void versionCompareTest() {
-        Assertions.assertThrows(IllegalArgumentException.class, () -> {
-            BorgVersion.compareVersions(null, "");
-        });
-        Assertions.assertThrows(IllegalArgumentException.class, () -> {
-            BorgVersion.compareVersions("", "");
-        });
-        Assertions.assertEquals(-1, BorgVersion.compareVersions("1.1.8", "1.1.16"));
-        Assertions.assertEquals(0, BorgVersion.compareVersions("1.1.8", "1.1.8"));
-        Assertions.assertEquals(1, BorgVersion.compareVersions("1.1.16", "1.1.8"));
-    }
-}
diff --git a/borgbutler-server/src/test/kotlin/de/micromata/borgbutler/server/user/UserFilterTest.kt b/borgbutler-server/src/test/kotlin/de/micromata/borgbutler/server/user/UserFilterTest.kt
index bebfccf..d10e667 100644
--- a/borgbutler-server/src/test/kotlin/de/micromata/borgbutler/server/user/UserFilterTest.kt
+++ b/borgbutler-server/src/test/kotlin/de/micromata/borgbutler/server/user/UserFilterTest.kt
@@ -1,6 +1,5 @@
 package de.micromata.borgbutler.server.user
 
-import de.micromata.borgbutler.server.BorgVersion
 import org.junit.jupiter.api.Assertions
 import org.junit.jupiter.api.Test
 
diff --git a/borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx b/borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx
index 8fdc69b..8a53b9f 100644
--- a/borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx
+++ b/borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx
@@ -35,8 +35,8 @@
             .then((data) => {
                 this.setState({
                     loading: false,
-                    borgVersion: data.borgVersion,
-                    borgBinary: data.borgVersion.borgBinary,
+                    borgConfig: data.borgConfig,
+                    borgBinary: data.borgConfig.borgBinary,
                     ...data.serverConfiguration
                 })
             })
@@ -56,6 +56,7 @@
             loading: true,
             failed: false,
             port: 9042,
+            borgVersion: "1.1.17",
             webdevelopmentMode: false,
             showDemoRepos: true,
             maxArchiveContentCacheCapacityMb: 100,
@@ -88,9 +89,10 @@
                 maxArchiveContentCacheCapacityMb: this.state.maxArchiveContentCacheCapacityMb,
                 webDevelopmentMode: this.state.webDevelopmentMode,
                 showDemoRepos: this.state.showDemoRepos,
-                borgCommand: this.state.borgCommand
+                borgCommand: this.state.borgCommand,
+                borgVersion: this.state.borgVersion,
             },
-            borgVersion: {
+            borgConfig: {
                 borgBinary: this.state.borgBinary
             }
         };
@@ -121,12 +123,12 @@
         if (this.state.failed) {
             return <ErrorAlertGenericRestFailure handleClick={this.loadConfig}/>;
         }
-        const borgVersion = this.state.borgVersion;
+        const borgConfig = this.state.borgConfig;
         let borgInfoColor = 'success';
-        let borgInfoMessage = `Borg version '${borgVersion.version}' is OK.`;
-        if (!borgVersion.versionOK) {
+        let borgInfoMessage = `Borg version '${borgConfig.version}' is OK.`;
+        if (!borgConfig.versionOK) {
             borgInfoColor = 'danger';
-            borgInfoMessage = borgVersion.statusMessage;
+            borgInfoMessage = borgConfig.statusMessage;
         }
         return (
             <React.Fragment>
@@ -138,9 +140,9 @@
                                 value={this.state.borgBinary}
                                 name={'borgBinary'}
                                 onChange={this.handleTextChange}
-                                hint={`Choose your OS and BorgButler will download and use a ready to run borg binary from ${borgVersion.binariesDownloadUrl} or choose a manual installed version.`}
+                                hint={`Choose your OS and BorgButler will download and use a ready to run borg binary from ${borgConfig.binariesDownloadUrl} or choose a manual installed version.`}
                             >
-                                {borgVersion.borgBinaries
+                                {borgConfig.borgBinaries
                                     .map((binary, index) => <FormOption label={binary[1]} value={binary[0]}
                                                                         key={index}/>)}
                                 <FormOption label={'Manual'} value={'manual'}/>
@@ -157,6 +159,10 @@
                             {borgInfoMessage}
                         </Alert>
                     </FormGroup>
+                    <FormLabelInputField label={'Borg version'} fieldLength={2}
+                                         name={'borgVersion'} value={this.state.borgVersion}
+                                         onChange={this.handleTextChange}
+                                         placeholder="Enter borg version (e. g. 1.1.17)"/>
                     <FormLabelInputField label={'Port'} fieldLength={2} type="number" min={0} max={65535}
                                          step={1}
                                          name={'port'} value={this.state.port}

--
Gitblit v1.10.0