Skip to main content

quanttide_devops/contract/
source.rs

1//! 来源配置:版本号来源的枚举与自动检测。
2
3use serde::{Deserialize, Serialize};
4use std::path::Path;
5
6// ── Sources(事实源维度)──────────────────────────────────────────────
7
8/// 事实源配置。
9#[derive(Debug, Clone, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case")]
11pub struct Source {
12    #[serde(default)]
13    pub version: VersionSource,
14}
15
16impl Default for Source {
17    fn default() -> Self {
18        Self {
19            version: VersionSource {
20                source_type: SourceType::Auto,
21                path: None,
22            },
23        }
24    }
25}
26
27/// 版本号来源配置。
28#[derive(Debug, Clone, Serialize, Deserialize)]
29#[serde(rename_all = "snake_case")]
30pub struct VersionSource {
31    /// YAML key 为 `type`(Rust 保留字,故字段命名避开)。
32    #[serde(default, rename = "type")]
33    pub source_type: SourceType,
34    #[serde(default)]
35    pub path: Option<String>,
36}
37
38impl Default for VersionSource {
39    fn default() -> Self {
40        Self {
41            source_type: SourceType::Auto,
42            path: None,
43        }
44    }
45}
46
47/// 版本号读取来源。
48#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
49#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
50#[serde(rename_all = "snake_case")]
51pub enum SourceType {
52    Cargo,
53    Pyproject,
54    /// 不从配置文件读版本,只从 git tag 读。
55    TagOnly,
56    Pubspec,
57    #[serde(rename = "package.json")]
58    PackageJson,
59    /// 自动检测。
60    #[default]
61    Auto,
62}
63
64impl SourceType {
65    /// 根据目录下的文件自动检测版本源类型。
66    pub fn detect(dir: &Path) -> Self {
67        if dir.join("Cargo.toml").exists() {
68            Self::Cargo
69        } else if dir.join("pyproject.toml").exists() {
70            Self::Pyproject
71        } else if dir.join("pubspec.yaml").exists() {
72            Self::Pubspec
73        } else if dir.join("package.json").exists() {
74            Self::PackageJson
75        } else {
76            Self::TagOnly
77        }
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn test_source_default() {
87        let s = Source::default();
88        assert_eq!(s.version.source_type, SourceType::Auto);
89        assert_eq!(s.version.path, None);
90    }
91
92    #[test]
93    fn test_version_source_default() {
94        let vs = VersionSource::default();
95        assert_eq!(vs.source_type, SourceType::Auto);
96        assert_eq!(vs.path, None);
97    }
98}