zeck 2.1.0

A Rust library for compressing and decompressing data using the Zeckendorf representation algorithm
Documentation
use std::fs;
use std::path::Path;
use std::process::Command;

fn maybe_get_git_commit_sha() -> Option<String> {
    let output = Command::new("git")
        .args(&["rev-parse", "HEAD"])
        .output()
        .ok()?;

    if !output.status.success() {
        return None;
    }

    String::from_utf8(output.stdout)
        .ok()
        .map(|s| s.trim().to_string())
}

fn is_workspace_dirty() -> bool {
    let output = Command::new("git")
        .args(&["status", "--porcelain"])
        .output()
        .ok();

    let Some(output) = output else {
        return false;
    };

    !output.stdout.is_empty()
}

fn maybe_parse_vcs_info_sha() -> Option<String> {
    let contents = fs::read_to_string(".cargo_vcs_info.json").ok()?;

    // Parse the JSON manually to extract the SHA
    // Format: {"git": {"sha1": "...", "dirty": true/false}, "path_in_vcs": ""}
    const SHA1_KEY: &str = "\"sha1\": \"";
    let sha_start = contents.find(SHA1_KEY)?;
    let sha_start = sha_start + SHA1_KEY.len();

    let sha_end = contents[sha_start..].find('"')?;
    let sha = contents[sha_start..sha_start + sha_end].trim().to_string();

    if sha.is_empty() {
        return None;
    }

    Some(sha)
}

fn get_git_commit_sha_with_fallback() -> String {
    // Try to get git commit SHA from git first (for local development)
    if let Some(mut git_commit) = maybe_get_git_commit_sha() {
        // We're in a git repo, use current commit
        // FIXME: this will show dirty if this was cargo installed from GitHub source code repository.
        if is_workspace_dirty() {
            git_commit.push_str("-dirty");
        }
        return git_commit;
    }

    // Not in a git repo (e.g., installed from crates.io), try to read from .cargo_vcs_info.json
    // This file is automatically generated by Cargo during packaging
    maybe_parse_vcs_info_sha().unwrap_or_default()
}

fn generate_version_string(git_commit_sha: &str) -> String {
    if git_commit_sha.is_empty() {
        env!("CARGO_PKG_VERSION").to_string()
    } else {
        format!("{} ({})", env!("CARGO_PKG_VERSION"), git_commit_sha)
    }
}

fn write_ephemeral_version_string_file(version_string: &str) {
    let out_dir = std::env::var("OUT_DIR").unwrap();
    let version_file = Path::new(&out_dir).join("version_string.rs");
    let content = format!("pub const VERSION_STRING: &str = {:?};", version_string);
    fs::write(&version_file, content).unwrap();
}

fn main() {
    let git_commit_sha = get_git_commit_sha_with_fallback();
    let version_string = generate_version_string(&git_commit_sha);
    write_ephemeral_version_string_file(&version_string);
}