Skip to content

Commit e4e81c9

Browse files
authored
Better version comparison (#157)
* fix: don't tell people to upgrade to old versions * feat: warn people when they're ahead of latest release * test: MVP tests for version comparison
1 parent 45e9c41 commit e4e81c9

3 files changed

Lines changed: 55 additions & 3 deletions

File tree

crates/tower-cmd/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,10 @@ impl App {
8585
if let Some(latest) = Self::check_latest_version().await {
8686
let current = tower_version::current_version();
8787

88-
if current != latest {
89-
output::write_update_message(&latest, &current);
88+
if tower_version::is_older_version(current, &latest) {
89+
output::write_update_available_message(&latest, current);
90+
} else if tower_version::is_newer_version(current, &latest) {
91+
output::write_dev_version_message(current, &latest);
9092
}
9193
}
9294

crates/tower-cmd/src/output.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ pub fn spinner(msg: &str) -> Spinner {
501501
Spinner::new(msg.into())
502502
}
503503

504-
pub fn write_update_message(latest: &str, current: &str) {
504+
pub fn write_update_available_message(latest: &str, current: &str) {
505505
let line = format!(
506506
"{}\n{}\n",
507507
format!(
@@ -517,6 +517,20 @@ pub fn write_update_message(latest: &str, current: &str) {
517517
io::stderr().write_all(line.as_bytes()).unwrap();
518518
}
519519

520+
pub fn write_dev_version_message(current: &str, latest: &str) {
521+
let line = format!(
522+
"{}\n",
523+
format!(
524+
"Running dev version {} (latest published: {})",
525+
current, latest
526+
)
527+
.dimmed()
528+
);
529+
530+
use std::io::{self, Write};
531+
io::stderr().write_all(line.as_bytes()).unwrap();
532+
}
533+
520534
/// newline just outputs a newline. This is useful when you have a very specific formatting you
521535
/// want to maintain and you don't want to use println!.
522536
pub fn newline() {

crates/tower-version/src/lib.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,39 @@ pub async fn check_latest_version() -> Result<Option<String>> {
4242
}
4343
Ok(None)
4444
}
45+
46+
fn parse_version(v: &str) -> Option<(u32, u32, u32)> {
47+
let parts: Vec<_> = v.split('.').filter_map(|p| p.parse::<u32>().ok()).collect();
48+
(parts.len() == 3).then(|| (parts[0], parts[1], parts[2]))
49+
}
50+
51+
pub fn is_older_version(current: &str, latest: &str) -> bool {
52+
matches!((parse_version(current), parse_version(latest)), (Some(c), Some(l)) if c < l)
53+
}
54+
55+
pub fn is_newer_version(current: &str, latest: &str) -> bool {
56+
matches!((parse_version(current), parse_version(latest)), (Some(c), Some(l)) if c > l)
57+
}
58+
59+
#[cfg(test)]
60+
mod tests {
61+
use super::*;
62+
63+
#[test]
64+
fn test_current_version_equal() {
65+
assert!(!is_older_version("0.3.39", "0.3.39"));
66+
assert!(!is_newer_version("0.3.39", "0.3.39"));
67+
}
68+
69+
#[test]
70+
fn test_older_version() {
71+
assert!(is_older_version("0.3.38", "0.3.39"));
72+
assert!(!is_newer_version("0.3.38", "0.3.39"));
73+
}
74+
75+
#[test]
76+
fn test_newer_version() {
77+
assert!(!is_older_version("0.3.40", "0.3.39"));
78+
assert!(is_newer_version("0.3.40", "0.3.39"));
79+
}
80+
}

0 commit comments

Comments
 (0)