ferrflow 2.9.1

Universal semantic versioning for monorepos and classic repos
Documentation
use anyhow::{Context, Result};
use std::path::Path;

pub struct TxtVersionFile;

#[cfg(test)]
mod tests {
    use super::*;
    use crate::formats::VersionFile;
    use std::io::Write;
    use tempfile::NamedTempFile;

    #[test]
    fn read_version_from_txt() {
        let mut f = NamedTempFile::new().unwrap();
        writeln!(f, "1.2.3").unwrap();
        let v = TxtVersionFile.read_version(f.path()).unwrap();
        assert_eq!(v, "1.2.3");
    }

    #[test]
    fn read_version_trims_whitespace() {
        let mut f = NamedTempFile::new().unwrap();
        write!(f, "  0.4.1\n\n").unwrap();
        let v = TxtVersionFile.read_version(f.path()).unwrap();
        assert_eq!(v, "0.4.1");
    }

    #[test]
    fn read_empty_file_fails() {
        let f = NamedTempFile::new().unwrap();
        let result = TxtVersionFile.read_version(f.path());
        assert!(result.is_err());
    }

    #[test]
    fn write_version_to_txt() {
        let mut f = NamedTempFile::new().unwrap();
        writeln!(f, "1.0.0").unwrap();
        TxtVersionFile.write_version(f.path(), "2.0.0").unwrap();
        let content = std::fs::read_to_string(f.path()).unwrap();
        assert_eq!(content, "2.0.0\n");
    }
}

impl super::VersionFile for TxtVersionFile {
    fn read_version(&self, file_path: &Path) -> Result<String> {
        let content = std::fs::read_to_string(file_path)
            .with_context(|| format!("failed to read {}", file_path.display()))?;
        let version = content.trim();
        if version.is_empty() {
            anyhow::bail!("no version found in {}", file_path.display());
        }
        Ok(version.to_string())
    }

    fn write_version(&self, file_path: &Path, version: &str) -> Result<()> {
        std::fs::write(file_path, format!("{version}\n"))
            .with_context(|| format!("failed to write {}", file_path.display()))?;
        Ok(())
    }
}