diff options
| author | 魏曹先生 <1992414357@qq.com> | 2025-11-04 14:29:34 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2025-11-04 14:29:34 +0800 |
| commit | 5991905ae9fb519a3a43c599c5515ba39c04e5fb (patch) | |
| tree | 3d9dcb37a30c9a17070c30c7964afec32a09435b | |
| parent | 57320aa7832d88c8e60fa0423df31cf71361ff58 (diff) | |
Add compile-time version and build information
- Add build script to generate compile_info.rs with build metadata -
Include version, build date, target platform, and toolchain info - Add
version command to both jv and jvv binaries - Update help documentation
with version information - Ignore generated compile_info.rs in git
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | build.rs | 97 | ||||
| -rw-r--r-- | crates/build_helper/src/bin/exporter.rs | 80 | ||||
| -rw-r--r-- | locales/help_docs/en.yml | 24 | ||||
| -rw-r--r-- | locales/help_docs/zh-CN.yml | 22 | ||||
| -rw-r--r-- | src/bin/jv.rs | 39 | ||||
| -rw-r--r-- | src/bin/jvv.rs | 36 | ||||
| -rw-r--r-- | src/data.rs | 2 | ||||
| -rw-r--r-- | src/data/compile_info.rs.template | 20 | ||||
| -rw-r--r-- | src/lib.rs | 3 |
12 files changed, 293 insertions, 38 deletions
@@ -16,3 +16,6 @@ # Target directory /target/ + +# Compile info +/src/data/compile_info.rs @@ -865,6 +865,7 @@ dependencies = [ "regex", "rust-i18n", "tokio", + "toml 0.9.8", ] [[package]] @@ -27,6 +27,10 @@ lto = "fat" panic = "abort" strip = "symbols" +[build-dependencies] +chrono = "0.4" +toml = "0.9" + [dependencies] # Just Enough VCS just_enough_vcs = { path = "../VersionControl", features = ["all"] } diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..7c9aac2 --- /dev/null +++ b/build.rs @@ -0,0 +1,97 @@ +use std::env; +use std::path::PathBuf; + +const COMPILE_INFO_RS: &str = "./src/data/compile_info.rs"; +const COMPILE_INFO_RS_TEMPLATE: &str = "./src/data/compile_info.rs.template"; + +fn main() { + println!("cargo:rerun-if-changed={}", COMPILE_INFO_RS_TEMPLATE); + + let repo_root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + + if let Err(e) = generate_compile_info(&repo_root) { + eprintln!("Failed to generate compile info: {}", e); + std::process::exit(1); + } +} + +/// Generate compile info +fn generate_compile_info(repo_root: &PathBuf) -> Result<(), Box<dyn std::error::Error>> { + // Read the template code + let template_code = std::fs::read_to_string(repo_root.join(COMPILE_INFO_RS_TEMPLATE))?; + + let date = chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string(); + let target = env::var("TARGET").unwrap_or_else(|_| "unknown".to_string()); + let platform = get_platform(&target); + let toolchain = get_toolchain(); + let version = get_version(); + + let generated_code = template_code + .replace("{date}", &date) + .replace("{target}", &target) + .replace("{platform}", &platform) + .replace("{toolchain}", &toolchain) + .replace("{version}", &version); + + // Write the generated code + let compile_info_path = repo_root.join(COMPILE_INFO_RS); + std::fs::write(compile_info_path, generated_code)?; + + Ok(()) +} + +fn get_platform(target: &str) -> String { + if target.contains("windows") { + "Windows".to_string() + } else if target.contains("linux") { + "Linux".to_string() + } else if target.contains("darwin") || target.contains("macos") { + "macOS".to_string() + } else if target.contains("android") { + "Android".to_string() + } else if target.contains("ios") { + "iOS".to_string() + } else { + "Unknown".to_string() + } +} + +fn get_toolchain() -> String { + let rustc_version = std::process::Command::new("rustc") + .arg("--version") + .output() + .ok() + .and_then(|output| String::from_utf8(output.stdout).ok()) + .unwrap_or_else(|| "unknown".to_string()) + .trim() + .to_string(); + + let channel = if rustc_version.contains("nightly") { + "nightly" + } else if rustc_version.contains("beta") { + "beta" + } else { + "stable" + }; + + format!("{} ({})", rustc_version, channel) +} + +fn get_version() -> String { + let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let manifest_path = PathBuf::from(manifest_dir).join("Cargo.toml"); + + if let Ok(contents) = std::fs::read_to_string(&manifest_path) { + if let Ok(manifest) = contents.parse::<toml::Value>() { + if let Some(package) = manifest.get("package") { + if let Some(version) = package.get("version") { + if let Some(version_str) = version.as_str() { + return version_str.to_string(); + } + } + } + } + } + + "0.1.0".to_string() +} diff --git a/crates/build_helper/src/bin/exporter.rs b/crates/build_helper/src/bin/exporter.rs index edc7e9c..4a35de5 100644 --- a/crates/build_helper/src/bin/exporter.rs +++ b/crates/build_helper/src/bin/exporter.rs @@ -6,12 +6,34 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { println!(" {} `.cargo/cargo.toml`", "Reading".green().bold()); let start_time = std::time::Instant::now(); - let mut copied_files = 0; let target_dir = current_target_dir().expect("Failed to get target directory"); let publish_dir = current_publish_dir().expect("Failed to get publish directory"); let publish_binaries = publish_binaries().expect("Failed to get publish binaries"); + // Final, export binaries to publish directory + let copied_files = export(target_dir, publish_dir, publish_binaries)?; + + let duration = start_time.elapsed(); + println!(); + println!( + "Done (in {:.1}s) Publish {} {}", + duration.as_secs_f32(), + copied_files, + if copied_files == 1 { "file" } else { "files" } + ); + + Ok(()) +} + +/// Export binaries to publish directory +fn export( + target_dir: std::path::PathBuf, + publish_dir: std::path::PathBuf, + publish_binaries: Vec<String>, +) -> Result<usize, Box<dyn std::error::Error>> { + let mut copied_files = 0; + if publish_dir.exists() { std::fs::remove_dir_all(&publish_dir)?; } @@ -39,42 +61,34 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { } if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) - && publish_binaries.contains(&file_name.to_string()) { - let parent_dir_name = path - .parent() - .and_then(|p| p.file_name()) - .and_then(|n| n.to_str()) - .unwrap_or(""); - - let dest_path = publish_dir.join(parent_dir_name).join(file_name); - - if let Some(parent) = dest_path.parent() { - std::fs::create_dir_all(parent)?; - } - - println!( - " {} `{}/{}` ({})", - "Copy".green().bold(), - parent_dir_name, - file_name, - path.display() - ); - std::fs::copy(&path, &dest_path)?; - copied_files += 1; + && publish_binaries.contains(&file_name.to_string()) + { + let parent_dir_name = path + .parent() + .and_then(|p| p.file_name()) + .and_then(|n| n.to_str()) + .unwrap_or(""); + + let dest_path = publish_dir.join(parent_dir_name).join(file_name); + + if let Some(parent) = dest_path.parent() { + std::fs::create_dir_all(parent)?; } + + println!( + " {} `{}/{}` ({})", + "Copy".green().bold(), + parent_dir_name, + file_name, + path.display() + ); + std::fs::copy(&path, &dest_path)?; + copied_files += 1; + } } } - let duration = start_time.elapsed(); - println!(); - println!( - "Done (in {:.1}s) Publish {} {}", - duration.as_secs_f32(), - copied_files, - if copied_files == 1 { "file" } else { "files" } - ); - - Ok(()) + Ok(copied_files) } /// Get a target directory from the cargo config diff --git a/locales/help_docs/en.yml b/locales/help_docs/en.yml index 435ad21..62c1f56 100644 --- a/locales/help_docs/en.yml +++ b/locales/help_docs/en.yml @@ -3,6 +3,17 @@ common: Confirm to perform the above operation? (Y/n): jvv: + version: + header: | + JustEnoughVCS Upstream Vault Manager + VERSION - %{version} + + compile_info: | + Compile Info + Compile Date - %{build_time} + Target - %{build_target} + Platform - %{build_platform} - %{build_toolchain} + help: | **JustEnoughVCS Upstream Vault Commands** This program directly creates, manages, and runs JustEnoughVCS upstream vaults. @@ -135,8 +146,19 @@ jvv: listen_done: Server shutdown! jv: + version: + header: | + JustEnoughVCS + VERSION - %{version} + + compile_info: | + Compile Info + Compile Date - %{build_time} + Target - %{build_target} + Platform - %{build_platform} - %{build_toolchain} + help: | - **JustEnoughVCS Local Workspace Commands** + **JustEnoughVCS** This program connects to upstream vaults to synchronize and commit changes to local workspace files for collaborative work. **ALIASES**: diff --git a/locales/help_docs/zh-CN.yml b/locales/help_docs/zh-CN.yml index 7fa8a43..ba89cb8 100644 --- a/locales/help_docs/zh-CN.yml +++ b/locales/help_docs/zh-CN.yml @@ -3,6 +3,17 @@ common: 是否执行上述操作?(Y/n): jvv: + version: + header: | + JustEnoughVCS 上游库管理工具 + 当前版本:%{version} + + compile_info: | + 编译信息: + 时间:%{build_time} + 目标:%{build_target} + 平台:%{build_platform} - %{build_toolchain} + help: | **JustEnoughVCS 上游库命令** 该程序直接创建、管理、运行 JustEnoughVCS 的上游库 @@ -129,6 +140,17 @@ jvv: listen_done: 服务端运行结束! jv: + version: + header: | + JustEnoughVCS 本地工作区命令 + 当前版本:%{version} + + compile_info: | + 编译信息: + 时间:%{build_time} + 目标:%{build_target} + 平台:%{build_platform} - %{build_toolchain} + help: | **JustEnoughVCS 本地工作区命令** 该程序将连接至上游库,用以同步、提交本地工作区文件的变化,以供协同创作 diff --git a/src/bin/jv.rs b/src/bin/jv.rs index b7eb105..8ccd843 100644 --- a/src/bin/jv.rs +++ b/src/bin/jv.rs @@ -30,8 +30,11 @@ use just_enough_vcs::{ utils::tcp_connection::error::TcpTargetError, vcs::{actions::local_actions::proc_set_upstream_vault_action, registry::client_registry}, }; -use just_enough_vcs_cli::utils::{ - input::confirm_hint_or, lang_selector::current_locales, md_colored::md, socket_addr_helper, +use just_enough_vcs_cli::{ + data::compile_info::CompileInfo, + utils::{ + input::confirm_hint_or, lang_selector::current_locales, md_colored::md, socket_addr_helper, + }, }; use rust_i18n::{set_locale, t}; use tokio::{fs, net::TcpSocket}; @@ -54,6 +57,11 @@ struct JustEnoughVcsWorkspace { #[derive(Subcommand, Debug)] enum JustEnoughVcsWorkspaceCommand { + /// Version information + #[command(alias = "--version", alias = "-v")] + Version(VersionArgs), + + /// Display help information #[command(alias = "--help", alias = "-h")] Help, @@ -130,6 +138,12 @@ enum JustEnoughVcsWorkspaceCommand { Sheets, } +#[derive(Parser, Debug)] +struct VersionArgs { + #[arg(short = 'C', long = "compile-info")] + compile_info: bool, +} + #[derive(Subcommand, Debug)] enum AccountManage { /// Show help information @@ -407,6 +421,27 @@ async fn main() { }; match parser.command { + JustEnoughVcsWorkspaceCommand::Version(version_args) => { + let compile_info = CompileInfo::default(); + println!( + "{}", + md(t!("jv.version.header", version = compile_info.cli_version)) + ); + + if version_args.compile_info { + println!( + "\n{}", + md(t!( + "jv.version.compile_info", + build_time = compile_info.date, + build_target = compile_info.target, + build_platform = compile_info.platform, + build_toolchain = compile_info.toolchain + )) + ); + } + } + JustEnoughVcsWorkspaceCommand::Help => { println!("{}", md(t!("jv.help"))); } diff --git a/src/bin/jvv.rs b/src/bin/jvv.rs index 8480029..8dc9c88 100644 --- a/src/bin/jvv.rs +++ b/src/bin/jvv.rs @@ -16,8 +16,9 @@ use just_enough_vcs::{ }, }, }; -use just_enough_vcs_cli::utils::{ - build_env_logger::build_env_logger, lang_selector::current_locales, md_colored::md, +use just_enough_vcs_cli::{ + data::compile_info::CompileInfo, + utils::{build_env_logger::build_env_logger, lang_selector::current_locales, md_colored::md}, }; use log::{error, info}; use rust_i18n::{set_locale, t}; @@ -40,6 +41,10 @@ struct JustEnoughVcsVault { #[derive(Subcommand, Debug)] enum JustEnoughVcsVaultCommand { + /// Version information + #[command(alias = "--version", alias = "-v")] + Version(VersionArgs), + /// Get vault info in the current directory #[command(alias = "-H")] Here(HereArgs), @@ -65,6 +70,12 @@ enum JustEnoughVcsVaultCommand { ServiceListen(ListenArgs), } +#[derive(Parser, Debug)] +struct VersionArgs { + #[arg(short = 'C', long = "compile-info")] + compile_info: bool, +} + #[derive(Subcommand, Debug)] enum MemberManage { /// Register a member to the vault @@ -178,6 +189,27 @@ async fn main() { }; match parser.command { + JustEnoughVcsVaultCommand::Version(version_args) => { + let compile_info = CompileInfo::default(); + println!( + "{}", + md(t!("jvv.version.header", version = compile_info.cli_version)) + ); + + if version_args.compile_info { + println!( + "\n{}", + md(t!( + "jvv.version.compile_info", + build_time = compile_info.date, + build_target = compile_info.target, + build_platform = compile_info.platform, + build_toolchain = compile_info.toolchain + )) + ); + } + } + JustEnoughVcsVaultCommand::Here(here_args) => { if here_args.help { println!("{}", md(t!("jvv.here"))); diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 0000000..036fd98 --- /dev/null +++ b/src/data.rs @@ -0,0 +1,2 @@ +#[allow(dead_code)] +pub mod compile_info; diff --git a/src/data/compile_info.rs.template b/src/data/compile_info.rs.template new file mode 100644 index 0000000..7720d2b --- /dev/null +++ b/src/data/compile_info.rs.template @@ -0,0 +1,20 @@ +pub struct CompileInfo { + pub date: String, + pub target: String, + pub platform: String, + pub toolchain: String, + + pub cli_version: String, +} + +impl Default for CompileInfo { + fn default() -> Self { + Self { + date: "{date}".to_string(), + target: "{target}".to_string(), + platform: "{platform}".to_string(), + toolchain: "{toolchain}".to_string(), + cli_version: "{version}".to_string(), + } + } +} @@ -1,2 +1,5 @@ /// Utils pub mod utils; + +/// Data +pub mod data; |
