From 17ec663e150e81da1d0edddf0fbdd7d1e6b26b49 Mon Sep 17 00:00:00 2001
From: timvisee <tim@visee.me>
Date: Mon, 15 Nov 2021 16:32:13 +0100
Subject: [PATCH] Show warning if config version is outdated or invalid

---
 Cargo.lock    |  7 +++++++
 Cargo.toml    |  1 +
 src/config.rs | 39 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/Cargo.lock b/Cargo.lock
index 106f7b8..da6762a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -634,6 +634,7 @@ dependencies = [
  "thiserror",
  "tokio",
  "toml",
+ "version-compare",
  "winapi",
 ]
 
@@ -1264,6 +1265,12 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "version-compare"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
+
 [[package]]
 name = "version_check"
 version = "0.9.3"
diff --git a/Cargo.toml b/Cargo.toml
index b7f60d9..0faab6f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,6 +39,7 @@ shlex = "1.1"
 thiserror = "1.0"
 tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "io-util", "net", "macros", "time", "process", "signal", "sync"] }
 toml = "0.5"
+version-compare = "0.1"
 
 # Feature: rcon
 rust_rcon = { package = "rcon", version = "0.5", optional = true }
diff --git a/src/config.rs b/src/config.rs
index 2627b7c..ddee2be 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -5,6 +5,7 @@ use std::path::{Path, PathBuf};
 
 use clap::ArgMatches;
 use serde::Deserialize;
+use version_compare::Cmp;
 
 use crate::proto;
 use crate::util::error::{quit_error, quit_error_msg, ErrorHintsBuilder};
@@ -12,6 +13,9 @@ use crate::util::error::{quit_error, quit_error_msg, ErrorHintsBuilder};
 /// Default configuration file location.
 pub const CONFIG_FILE: &str = "lazymc.toml";
 
+/// Configuration version user should be using, or warning will be shown.
+const CONFIG_VERSION: &str = "0.2.0";
+
 /// Load config from file, based on CLI arguments.
 ///
 /// Quits with an error message on failure.
@@ -96,13 +100,32 @@ pub struct Config {
     /// Advanced configuration.
     #[serde(default)]
     pub advanced: Advanced,
+
+    /// Config configuration.
+    #[serde(default)]
+    pub config: ConfigConfig,
 }
 
 impl Config {
     /// Load configuration from file.
     pub fn load<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> {
         let data = fs::read(path)?;
-        let config = toml::from_slice(&data)?;
+        let config: Config = toml::from_slice(&data)?;
+
+        // Show warning if config version is problematic
+        match &config.config.version {
+            None => warn!(target: "lazymc::config", "Config version unknown, it may be outdated"),
+            Some(version) => match version_compare::compare_to(version, CONFIG_VERSION, Cmp::Ge) {
+                Ok(false) => {
+                    warn!(target: "lazymc::config", "Config is for older lazymc version, you may need to update it")
+                }
+                Err(_) => {
+                    warn!(target: "lazymc::config", "Config version is invalid, you may need to update it")
+                }
+                Ok(true) => {}
+            },
+        }
+
         Ok(config)
     }
 }
@@ -341,6 +364,20 @@ impl Default for Advanced {
     }
 }
 
+/// Config configuration.
+#[derive(Debug, Deserialize)]
+#[serde(default)]
+pub struct ConfigConfig {
+    /// Configuration for lazymc version.
+    pub version: Option<String>,
+}
+
+impl Default for ConfigConfig {
+    fn default() -> Self {
+        Self { version: None }
+    }
+}
+
 fn option_pathbuf_dot() -> Option<PathBuf> {
     Some(".".into())
 }