Skip to main content

carch_core/
version.rs

1use crate::error::{CarchError, Result};
2use serde::Deserialize;
3
4#[derive(Deserialize)]
5struct Release {
6    tag_name: String,
7}
8
9/// Raw Cargo.toml version, no `v` prefix.
10#[must_use]
11pub fn current_version() -> &'static str {
12    env!("CARGO_PKG_VERSION")
13}
14
15/// Version string with `v` prefix.
16#[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}