diff --git a/CHANGELOG.md b/CHANGELOG.md index 0795aa5..b761315 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 暂无。 +## [0.6.1] - 2026-08-18 + +### 🔧 其他变更 +- 依赖瘦身:移除未使用的直接依赖 `config`、`handlebars`、`shell-words`、`walkdir`、`console`、`lazy_static`、`atty`,crate 总数由 341 降至 296,release 二进制体积由 7.38 MB 降至 7.00 MB(-5.2%) +- `lazy_static!` 宏替换为标准库 `LazyLock`;`atty` 替换为标准库 `std::io::IsTerminal` +- `tokio` 特性由 `full` 精简为 `macros` + `rt-multi-thread` +- `regex` 关闭默认 unicode 特性(保留 `std` + `perf`),行为变化:`\s`/`\d`/`\w` 字符类仅匹配 ASCII,对提交信息、版本号、邮箱、GPG Key ID 校验无实质影响 + ## [0.6.0] - 2026-08-17 ### ✨ 新功能 diff --git a/Cargo.toml b/Cargo.toml index ec9d4b4..1e711f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "quicommit" -version = "0.6.0" +version = "0.6.1" edition = "2024" authors = ["Sidney Zhang "] description = "A powerful Git assistant tool with AI-powered commit/tag/changelog generation" @@ -19,11 +19,9 @@ path = "src/main.rs" clap = { version = "4.5", features = ["derive", "env", "wrap_help"] } clap_complete = "4.5" dialoguer = "0.11" -console = "0.15" indicatif = "0.17" # Configuration management -config = "0.14" serde = { version = "1.0", features = ["derive"] } toml = "0.8" dirs = "5.0" @@ -32,7 +30,7 @@ dirs = "5.0" git2 = "0.20.3" which = "6.0" -tokio = { version = "1.35", features = ["full", "macros", "rt-multi-thread"] } +tokio = { version = "1.35", features = ["macros", "rt-multi-thread"] } # Error handling thiserror = "1.0" @@ -44,20 +42,16 @@ tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } # Utilities chrono = { version = "0.4", features = ["serde"] } -regex = "1.10" +regex = { version = "1.10", default-features = false, features = ["std", "perf"] } roxmltree = "0.20" -lazy_static = "1.4" colored = "2.1" -handlebars = "5.1" semver = "1.0" -walkdir = "2.4" tempfile = "3.9" sha2 = "0.10" hex = "0.4" textwrap = "0.16" futures-util = "0.3" serde_json = "1.0" -atty = "0.2" # Encryption for sensitive data (SSH keys, GPG, etc.) aes-gcm = "0.10" @@ -71,8 +65,6 @@ keyring = { version = "3.6.3", features = ["apple-native", "windows-native", "sy # Interactive editor edit = "0.1" -# Shell completion generation -shell-words = "1.1" # LLM integration (rig-core only: HTTP backend + rustls; no agent/derive) rig-core = { version = "0.41", default-features = false, features = ["reqwest", "rustls"] } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 6e14760..301456a 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -62,7 +62,7 @@ pub fn password_input(prompt: &str) -> Result { /// Check if running in a terminal pub fn is_terminal() -> bool { - atty::is(atty::Stream::Stdout) + std::io::IsTerminal::is_terminal(&io::stdout()) } /// Format duration in human-readable format diff --git a/src/utils/validators.rs b/src/utils/validators.rs index 821143f..0428cb3 100644 --- a/src/utils/validators.rs +++ b/src/utils/validators.rs @@ -1,6 +1,6 @@ use anyhow::{Result, bail}; -use lazy_static::lazy_static; use regex::Regex; +use std::sync::LazyLock; /// Conventional commit types pub const CONVENTIONAL_TYPES: &[&str] = &[ @@ -37,32 +37,33 @@ pub const COMMITLINT_TYPES: &[&str] = &[ "security", // Security-related changes ]; -lazy_static! { - /// Regex for conventional commit format - static ref CONVENTIONAL_COMMIT_REGEX: Regex = Regex::new( - r"^(?Pfeat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\((?P[^)]+)\))?(?P!)?: (?P.+)$" - ).unwrap(); +/// Regex for conventional commit format +static CONVENTIONAL_COMMIT_REGEX: LazyLock = LazyLock::new(|| { + Regex::new( + r"^(?Pfeat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\((?P[^)]+)\))?(?P!)?: (?P.+)$", + ) + .unwrap() +}); - /// Regex for scope validation - static ref SCOPE_REGEX: Regex = Regex::new( - r"^[a-z0-9-]+$" - ).unwrap(); +/// Regex for scope validation +static SCOPE_REGEX: LazyLock = LazyLock::new(|| Regex::new(r"^[a-z0-9-]+$").unwrap()); - /// Regex for version tag validation (semver) - static ref SEMVER_REGEX: Regex = Regex::new( - r"^v?(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" - ).unwrap(); +/// Regex for version tag validation (semver) +static SEMVER_REGEX: LazyLock = LazyLock::new(|| { + Regex::new( + r"^v?(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", + ) + .unwrap() +}); - /// Regex for email validation - static ref EMAIL_REGEX: Regex = Regex::new( - r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" - ).unwrap(); +/// Regex for email validation +static EMAIL_REGEX: LazyLock = LazyLock::new(|| { + Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap() +}); - /// Regex for GPG key ID validation - static ref GPG_KEY_ID_REGEX: Regex = Regex::new( - r"^[A-F0-9]{16,40}$" - ).unwrap(); -} +/// Regex for GPG key ID validation +static GPG_KEY_ID_REGEX: LazyLock = + LazyLock::new(|| Regex::new(r"^[A-F0-9]{16,40}$").unwrap()); /// Validate conventional commit message pub fn validate_conventional_commit(message: &str) -> Result<()> {