origin_mcp/
version_check.rs1use semver::Version;
2
3#[derive(Debug, PartialEq)]
4pub enum VersionStatus {
5 Compatible,
6 McpOutdated { mcp: Version, daemon: Version },
7}
8
9pub fn compare(mcp_version: &str, daemon_version: &str) -> VersionStatus {
14 let mcp = match Version::parse(mcp_version) {
17 Ok(v) => v,
18 Err(_) => return VersionStatus::Compatible,
19 };
20 let daemon = match Version::parse(daemon_version) {
21 Ok(v) => v,
22 Err(_) => return VersionStatus::Compatible,
23 };
24 if daemon.major > mcp.major || (daemon.major == mcp.major && daemon.minor > mcp.minor) {
25 VersionStatus::McpOutdated { mcp, daemon }
26 } else {
27 VersionStatus::Compatible
28 }
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34
35 #[test]
36 fn equal_versions_compatible() {
37 assert_eq!(compare("0.1.2", "0.1.2"), VersionStatus::Compatible);
38 }
39
40 #[test]
41 fn mcp_ahead_compatible() {
42 assert_eq!(compare("0.2.0", "0.1.5"), VersionStatus::Compatible);
43 }
44
45 #[test]
46 fn daemon_minor_ahead_outdated() {
47 assert!(matches!(
48 compare("0.1.2", "0.2.0"),
49 VersionStatus::McpOutdated { .. }
50 ));
51 }
52
53 #[test]
54 fn daemon_major_ahead_outdated() {
55 assert!(matches!(
56 compare("0.1.2", "1.0.0"),
57 VersionStatus::McpOutdated { .. }
58 ));
59 }
60
61 #[test]
62 fn patch_drift_compatible() {
63 assert_eq!(compare("0.1.2", "0.1.5"), VersionStatus::Compatible);
64 }
65
66 #[test]
67 fn unparseable_daemon_version_compatible() {
68 assert_eq!(compare("0.1.2", "garbage"), VersionStatus::Compatible);
69 }
70
71 #[test]
72 fn build_metadata_ignored_in_ordering() {
73 assert_eq!(compare("0.1.2", "0.1.2+abc"), VersionStatus::Compatible);
75 }
76
77 #[test]
78 fn prerelease_daemon_same_minor_compatible() {
79 assert_eq!(compare("0.2.0", "0.2.0-beta.1"), VersionStatus::Compatible);
83 }
84}