use crate::error::{KopiError, Result};
use crate::models::package::PackageType;
use crate::version::format_version_minimal;
use crate::version::parser::ParsedVersionRequest;
use log::debug;
use std::fs;
use std::io::Write;
use std::path::PathBuf;
pub fn write_version_file(path: &PathBuf, version_request: &ParsedVersionRequest) -> Result<()> {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).map_err(|e| {
KopiError::SystemError(format!(
"Failed to create directory {}: {}",
parent.display(),
e
))
})?;
}
let version = version_request.version.as_ref().unwrap();
let version_str = format_version_minimal(version);
let mut parts = Vec::new();
if let Some(package_type) = &version_request.package_type
&& *package_type == PackageType::Jre
{
parts.push("jre".to_string());
}
if let Some(dist) = &version_request.distribution {
parts.push(dist.id().to_string());
}
parts.push(version_str);
let version_string = parts.join("@");
let temp_path = path.with_extension("tmp");
{
let mut file = fs::File::create(&temp_path).map_err(|e| {
KopiError::SystemError(format!("Failed to create {}: {}", temp_path.display(), e))
})?;
file.write_all(version_string.as_bytes()).map_err(|e| {
KopiError::SystemError(format!("Failed to write to {}: {}", temp_path.display(), e))
})?;
file.flush().map_err(|e| {
KopiError::SystemError(format!("Failed to flush {}: {}", temp_path.display(), e))
})?;
}
fs::rename(&temp_path, path).map_err(|e| {
KopiError::SystemError(format!(
"Failed to rename {} to {}: {}",
temp_path.display(),
path.display(),
e
))
})?;
debug!("Wrote version file: {path:?}");
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::models::distribution::Distribution;
use crate::version::Version;
use tempfile::TempDir;
#[test]
fn test_write_version_file() {
let temp_dir = TempDir::new().unwrap();
let version_file = temp_dir.path().join("version");
let version_request = ParsedVersionRequest {
distribution: Some(Distribution::Temurin),
version: Some(Version::new(21, 0, 0)),
package_type: Some(PackageType::Jdk),
latest: false,
};
write_version_file(&version_file, &version_request).unwrap();
let content = fs::read_to_string(&version_file).unwrap();
assert_eq!(content, "temurin@21");
let version_request2 = ParsedVersionRequest {
distribution: None,
version: Some(Version::new(17, 0, 0)),
package_type: Some(PackageType::Jdk),
latest: false,
};
write_version_file(&version_file, &version_request2).unwrap();
let content2 = fs::read_to_string(&version_file).unwrap();
assert_eq!(content2, "17"); }
#[test]
fn test_write_version_file_with_full_version() {
let temp_dir = TempDir::new().unwrap();
let version_file = temp_dir.path().join("version");
let version_request = ParsedVersionRequest {
distribution: Some(Distribution::Corretto),
version: Some(Version::new(11, 0, 21)),
package_type: Some(PackageType::Jdk),
latest: false,
};
write_version_file(&version_file, &version_request).unwrap();
let content = fs::read_to_string(&version_file).unwrap();
assert_eq!(content, "corretto@11.0.21");
}
#[test]
fn test_write_version_file_creates_parent_dir() {
let temp_dir = TempDir::new().unwrap();
let nested_path = temp_dir.path().join("subdir").join("version");
let version_request = ParsedVersionRequest {
distribution: None,
version: Some(Version::new(21, 0, 0)),
package_type: Some(PackageType::Jdk),
latest: false,
};
write_version_file(&nested_path, &version_request).unwrap();
assert!(nested_path.exists());
let content = fs::read_to_string(&nested_path).unwrap();
assert_eq!(content, "21");
}
#[test]
fn test_write_version_file_with_jre() {
let temp_dir = TempDir::new().unwrap();
let version_file = temp_dir.path().join("version");
let version_request = ParsedVersionRequest {
distribution: Some(Distribution::Temurin),
version: Some(Version::new(21, 0, 0)),
package_type: Some(PackageType::Jre),
latest: false,
};
write_version_file(&version_file, &version_request).unwrap();
let content = fs::read_to_string(&version_file).unwrap();
assert_eq!(content, "jre@temurin@21");
let version_request2 = ParsedVersionRequest {
distribution: None,
version: Some(Version::new(17, 0, 0)),
package_type: Some(PackageType::Jre),
latest: false,
};
write_version_file(&version_file, &version_request2).unwrap();
let content2 = fs::read_to_string(&version_file).unwrap();
assert_eq!(content2, "jre@17");
}
}