Skip to main content

client_core/utils/
archive.rs

1//! 压缩归档文件辅助函数
2//!
3//! 使用 `infer` 库通过魔数(magic number)检测文件格式
4
5use anyhow::Result;
6use std::path::Path;
7
8/// 压缩包格式
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum ArchiveFormat {
11    Zip,
12    TarGz,
13}
14
15impl ArchiveFormat {
16    /// 文件扩展名
17    pub fn extension(&self) -> &str {
18        match self {
19            Self::Zip => ".zip",
20            Self::TarGz => ".tar.gz",
21        }
22    }
23
24    /// 从 infer 的 Type 转换
25    fn from_infer_kind(kind: &infer::Type) -> Option<Self> {
26        match kind.extension() {
27            "zip" => Some(ArchiveFormat::Zip),
28            "gz" | "tgz" => Some(ArchiveFormat::TarGz),
29            _ => None,
30        }
31    }
32}
33
34/// 使用 infer 库通过魔数检测格式
35pub fn detect_format_by_magic(path: &Path) -> Result<ArchiveFormat> {
36    let kind =
37        infer::get_from_path(path)?.ok_or_else(|| anyhow::anyhow!("Unable to detect file format"))?;
38
39    ArchiveFormat::from_infer_kind(&kind)
40        .ok_or_else(|| anyhow::anyhow!("Unsupported file format: {}", kind.mime_type()))
41}
42
43/// 生成 Docker 服务包文件名
44pub fn generate_docker_filename(arch: &str, format: ArchiveFormat) -> String {
45    format!("docker-{}{}", arch, format.extension())
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn test_generate_filename() {
54        assert_eq!(
55            generate_docker_filename("aarch64", ArchiveFormat::TarGz),
56            "docker-aarch64.tar.gz"
57        );
58        assert_eq!(
59            generate_docker_filename("x86_64", ArchiveFormat::Zip),
60            "docker-x86_64.zip"
61        );
62    }
63
64    #[test]
65    fn test_archive_format_extension() {
66        assert_eq!(ArchiveFormat::Zip.extension(), ".zip");
67        assert_eq!(ArchiveFormat::TarGz.extension(), ".tar.gz");
68    }
69}