1use crate::error::{CarchError, Result};
2use serde::Deserialize;
3
4#[derive(Deserialize)]
5struct Release {
6 tag_name: String,
7}
8
9#[must_use]
11pub fn current_version() -> &'static str {
12 env!("CARGO_PKG_VERSION")
13}
14
15#[must_use]
17pub fn get_current_version() -> String {
18 format!("v{}", current_version())
19}
20
21pub fn get_latest_version() -> Result<String> {
22 let client = reqwest::blocking::Client::builder().user_agent("carch").build()?;
23 let response =
24 client.get("https://api.github.com/repos/harilvfs/carch/releases/latest").send()?;
25
26 if !response.status().is_success() {
27 return Err(CarchError::Command("Failed to fetch latest version information".to_string()));
28 }
29
30 let release: Release = response.json()?;
31 Ok(release.tag_name.trim_start_matches('v').to_string())
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37
38 #[test]
39 fn current_version_is_nonempty() {
40 assert!(!current_version().is_empty());
41 }
42
43 #[test]
44 fn current_version_is_valid_semver_shape() {
45 let v = current_version();
46 let first = v.split('.').next().unwrap_or("");
47 assert!(first.chars().all(|c| c.is_ascii_digit()), "expected digit prefix, got {v:?}");
48 }
49
50 #[test]
51 fn get_current_version_has_v_prefix() {
52 let v = get_current_version();
53 assert!(v.starts_with('v'), "expected 'v' prefix, got {v:?}");
54 assert_eq!(&v[1..], current_version());
55 }
56}