From b1fa96a571036bef597695f8e0e7b7a58d1f3296 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sat, 10 Jan 2026 06:20:32 +0800 Subject: Add platform restrictions to deployment configs - Move build_helper from crates/ to tools/ directory - Specify platform targets for shell completions and entry scripts - Bash scripts now target linux and macos - Powershell scripts target windows - Zsh plugin files target linux and macos --- .cargo/config.toml | 20 ++- Cargo.toml | 2 +- crates/build_helper/Cargo.toml | 13 -- crates/build_helper/src/bin/exporter.rs | 227 ----------------------------- deploy.ps1 | 2 +- deploy.sh | 2 +- scripts/deploy/jv_cli.ps1 | 8 +- scripts/deploy/jv_cli.sh | 8 +- tools/build_helper/Cargo.toml | 13 ++ tools/build_helper/src/bin/exporter.rs | 249 ++++++++++++++++++++++++++++++++ 10 files changed, 287 insertions(+), 257 deletions(-) delete mode 100644 crates/build_helper/Cargo.toml delete mode 100644 crates/build_helper/src/bin/exporter.rs create mode 100644 tools/build_helper/Cargo.toml create mode 100644 tools/build_helper/src/bin/exporter.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 93f2182..ca6a8cb 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -21,16 +21,19 @@ binaries = [ # Completions [copies.completion_jv_bash] from = "scripts/deploy/completions/bash/completion_jv.sh" -to = "completions/bash/completion_jv.sh" +to = "comp/jv.sh" +platform = [ "linux", "macos" ] [copies.completion_jvv_bash] from = "scripts/deploy/completions/bash/completion_jvv.sh" -to = "completions/bash/completion_jvv.sh" +to = "comp/jvv.sh" +platform = [ "linux", "macos" ] # Entries [copies.entry_bash] from = "scripts/deploy/jv_cli.sh" to = "jv_cli.sh" +platform = [ "linux", "macos" ] ################## ### Powershell ### @@ -39,16 +42,19 @@ to = "jv_cli.sh" # Completions [copies.completion_jv_powershell] from = "scripts/deploy/completions/powershell/completion_jv.ps1" -to = "completions/powershell/completion_jv.ps1" +to = "comp/jv.ps1" +platform = [ "windows" ] [copies.completion_jvv_powershell] from = "scripts/deploy/completions/powershell/completion_jvv.ps1" -to = "completions/powershell/completion_jvv.ps1" +to = "comp/jvv.ps1" +platform = [ "windows" ] # Entries [copies.entry_powershell] from = "scripts/deploy/jv_cli.ps1" to = "jv_cli.ps1" +platform = [ "windows" ] ################## ### Zsh Plugin ### @@ -56,8 +62,10 @@ to = "jv_cli.ps1" [copies.zsh_plugin] from = "scripts/deploy/zsh_support/jvcs.plugin.zsh" -to = "scripts/zsh_support/jvcs.plugin.zsh" +to = "zsh_support/jvcs.plugin.zsh" +platform = [ "linux", "macos" ] [copies.zsh_plugin_installation] from = "scripts/deploy/zsh_support/how_to_install.md" -to = "scripts/zsh_support/how_to_install.md" +to = "zsh_support/how_to_install.md" +platform = [ "linux", "macos" ] diff --git a/Cargo.toml b/Cargo.toml index 5e76958..2a0bb00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = ["JustEnoughVCS Team"] homepage = "http://jvcs.cc/" [workspace] -members = ["crates/build_helper"] +members = ["tools/build_helper"] [workspace.package] version = "0.1.0-dev" diff --git a/crates/build_helper/Cargo.toml b/crates/build_helper/Cargo.toml deleted file mode 100644 index deadd4c..0000000 --- a/crates/build_helper/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "cli_publisher" -edition = "2024" -version = "0.0.1" - -[dependencies] - -# Serialization -serde = { version = "1.0.226", features = ["derive"] } -toml = { version = "0.9.7", features = ["serde"] } - -# Colored -colored = "3.0.0" diff --git a/crates/build_helper/src/bin/exporter.rs b/crates/build_helper/src/bin/exporter.rs deleted file mode 100644 index 27c1274..0000000 --- a/crates/build_helper/src/bin/exporter.rs +++ /dev/null @@ -1,227 +0,0 @@ -use std::{collections::VecDeque, env::current_dir}; - -use colored::Colorize; - -fn main() -> Result<(), Box> { - println!(" {} `.cargo/cargo.toml`", "Reading".green().bold()); - - let start_time = std::time::Instant::now(); - - 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"); - let copy_configs = copy_configs().expect("Failed to get copy configurations"); - - // Final, export binaries to publish directory - let copied_files = export(target_dir, publish_dir, publish_binaries, copy_configs)?; - - let duration = start_time.elapsed(); - println!( - " {} publish {} {} in {:.1}s", - "Finished".green().bold(), - copied_files, - if copied_files == 1 { "file" } else { "files" }, - duration.as_secs_f32(), - ); - - Ok(()) -} - -/// Export binaries to publish directory -fn export( - target_dir: std::path::PathBuf, - publish_dir: std::path::PathBuf, - publish_binaries: Vec, - copy_configs: Vec, -) -> Result> { - let mut copied_files = 0; - - if publish_dir.exists() { - std::fs::remove_dir_all(&publish_dir)?; - } - std::fs::create_dir_all(&publish_dir)?; - - // Create bin directory for binaries - let bin_dir = publish_dir.join("bin"); - std::fs::create_dir_all(&bin_dir)?; - - // Copy binaries to bin directory - let mut queue = VecDeque::new(); - queue.push_back(target_dir); - - while let Some(current_dir) = queue.pop_front() { - let entries = match std::fs::read_dir(¤t_dir) { - Ok(entries) => entries, - Err(_) => continue, - }; - - for entry in entries.flatten() { - let path = entry.path(); - let metadata = match entry.metadata() { - Ok(metadata) => metadata, - Err(_) => continue, - }; - - if metadata.is_dir() { - queue.push_back(path); - continue; - } - - if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) - && publish_binaries.contains(&file_name.to_string()) - { - let dest_path = bin_dir.join(file_name); - - if let Some(parent) = dest_path.parent() { - std::fs::create_dir_all(parent)?; - } - - println!( - " {} `{}` ({})", - "Binary".green().bold(), - file_name, - path.display() - ); - std::fs::copy(&path, &dest_path)?; - copied_files += 1; - } - } - } - - // Copy additional files based on configuration - let current = current_dir()?; - for config in copy_configs { - let source_path = current.join(&config.from); - let dest_path = publish_dir.join(&config.to); - - if let Some(parent) = dest_path.parent() { - std::fs::create_dir_all(parent)?; - } - - if source_path.exists() { - println!( - " {} `{}` -> `{}` ({})", - "Other".green().bold(), - config.from, - config.to, - source_path.display() - ); - std::fs::copy(&source_path, &dest_path)?; - copied_files += 1; - } else { - println!( - " {} `{}` (file not found)", - "Warning".yellow().bold(), - config.from - ); - } - } - - Ok(copied_files) -} - -/// Copy configuration structure -#[derive(Debug)] -struct CopyConfig { - from: String, - to: String, -} - -/// Get a target directory from the cargo config -/// Returns the complete path relative to the current directory -fn get_target_dir(section: &str) -> Result { - let current = current_dir()?; - let config_file = current.join(".cargo").join("config.toml"); - let config_content = std::fs::read_to_string(&config_file)?; - let config: toml::Value = toml::from_str(&config_content).map_err(|e| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("Failed to parse config.toml: {}", e), - ) - })?; - let target_dir_str = config[section]["target-dir"].as_str().ok_or_else(|| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - "target-dir not found or not a string", - ) - })?; - - Ok(current.join(target_dir_str)) -} - -/// Get the binaries list from the cargo config -/// Returns a vector of binary names -fn get_array(section: &str, array_name: &str) -> Result, std::io::Error> { - let current = current_dir()?; - let config_file = current.join(".cargo").join("config.toml"); - let config_content = std::fs::read_to_string(&config_file)?; - let config: toml::Value = toml::from_str(&config_content).map_err(|e| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("Failed to parse config.toml: {}", e), - ) - })?; - - if let Some(array) = config[section][array_name].as_array() { - let arr: Vec = array - .iter() - .filter_map(|v| v.as_str().map(String::from)) - .collect(); - Ok(arr) - } else { - Ok(Vec::new()) - } -} - -/// Get the copy configurations from the cargo config -/// Returns a vector of CopyConfig structs -fn copy_configs() -> Result, std::io::Error> { - let current = current_dir()?; - let config_file = current.join(".cargo").join("config.toml"); - let config_content = std::fs::read_to_string(&config_file)?; - let config: toml::Value = toml::from_str(&config_content).map_err(|e| { - std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("Failed to parse config.toml: {}", e), - ) - })?; - - let mut copy_configs = Vec::new(); - - if let Some(copies) = config.get("copies") { - if let Some(tables) = copies.as_table() { - for (_, table) in tables { - if let Some(from) = table.get("from").and_then(|v| v.as_str()) { - let to = table.get("to").and_then(|v| v.as_str()).unwrap_or(""); - copy_configs.push(CopyConfig { - from: from.to_string(), - to: to.to_string(), - }); - } - } - } - } - - Ok(copy_configs) -} - -/// Get the target directory of the current project -/// By reading the `build.target-dir` configuration item in the `.cargo/config.toml` file -/// Returns the complete path relative to the current directory -fn current_target_dir() -> Result { - get_target_dir("build") -} - -/// Get the publish directory of the current project -/// By reading the `publish.target-dir` configuration item in the `.cargo/config.toml` file -/// Returns the complete path relative to the current directory -fn current_publish_dir() -> Result { - get_target_dir("publish") -} - -/// Get the binaries list for publishing -// By reading the `publish.binaries` configuration item in the `.cargo/config.toml` file -// Returns a vector of binary names -fn publish_binaries() -> Result, std::io::Error> { - get_array("publish", "binaries") -} diff --git a/deploy.ps1 b/deploy.ps1 index e247395..d627a1a 100644 --- a/deploy.ps1 +++ b/deploy.ps1 @@ -28,7 +28,7 @@ if ($LASTEXITCODE -ne 0) { } else { # Build succeeded # Export - if (cargo run --manifest-path crates/build_helper/Cargo.toml --bin exporter) { + if (cargo run --manifest-path tools/build_helper/Cargo.toml --bin exporter) { Copy-Item -Path templates\compile_info.rs -Destination src\data\compile_info.rs -Force ISCC /Q .\setup\windows\setup_jv_cli.iss } diff --git a/deploy.sh b/deploy.sh index a4e533f..972b494 100755 --- a/deploy.sh +++ b/deploy.sh @@ -8,7 +8,7 @@ cd "$(dirname "$0")" || exit 1 # Build if FORCE_BUILD=$(date +%s) cargo build --workspace --release; then # Export - if cargo run --manifest-path crates/build_helper/Cargo.toml --bin exporter; then + if cargo run --manifest-path tools/build_helper/Cargo.toml --bin exporter; then # Copy compile_info.rs.template to compile_info.rs after successful export cp -f templates/compile_info.rs src/data/compile_info.rs fi diff --git a/scripts/deploy/jv_cli.ps1 b/scripts/deploy/jv_cli.ps1 index 22836c7..2761137 100644 --- a/scripts/deploy/jv_cli.ps1 +++ b/scripts/deploy/jv_cli.ps1 @@ -47,11 +47,11 @@ Set-Alias jmv jmv ### COMPLETION ### ################## -if (Test-Path "$SCRIPT_DIR\completions\powershell\completion_jv.ps1") { - . "$SCRIPT_DIR\completions\powershell\completion_jv.ps1" +if (Test-Path "$SCRIPT_DIR\comp\jv.ps1") { + . "$SCRIPT_DIR\comp\jv.ps1" } -if (Test-Path "$SCRIPT_DIR\completions\powershell\completion_jvv.ps1") { - . "$SCRIPT_DIR\completions\powershell\completion_jvv.ps1" +if (Test-Path "$SCRIPT_DIR\comp\jvv.ps1") { + . "$SCRIPT_DIR\comp\jvv.ps1" } ################### diff --git a/scripts/deploy/jv_cli.sh b/scripts/deploy/jv_cli.sh index d732d95..80ff757 100644 --- a/scripts/deploy/jv_cli.sh +++ b/scripts/deploy/jv_cli.sh @@ -58,11 +58,11 @@ alias jvu='jv update' ### COMPLETION ### ################## -if [ -f "$SCRIPT_DIR/completions/bash/completion_jv.sh" ]; then - source "$SCRIPT_DIR/completions/bash/completion_jv.sh" +if [ -f "$SCRIPT_DIR/comp/jv.sh" ]; then + source "$SCRIPT_DIR/comp/jv.sh" fi -if [ -f "$SCRIPT_DIR/completions/bash/completion_jvv.sh" ]; then - source "$SCRIPT_DIR/completions/bash/completion_jvv.sh" +if [ -f "$SCRIPT_DIR/comp/jvv.sh" ]; then + source "$SCRIPT_DIR/comp/jvv.sh" fi ################## diff --git a/tools/build_helper/Cargo.toml b/tools/build_helper/Cargo.toml new file mode 100644 index 0000000..deadd4c --- /dev/null +++ b/tools/build_helper/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "cli_publisher" +edition = "2024" +version = "0.0.1" + +[dependencies] + +# Serialization +serde = { version = "1.0.226", features = ["derive"] } +toml = { version = "0.9.7", features = ["serde"] } + +# Colored +colored = "3.0.0" diff --git a/tools/build_helper/src/bin/exporter.rs b/tools/build_helper/src/bin/exporter.rs new file mode 100644 index 0000000..c8f7ba2 --- /dev/null +++ b/tools/build_helper/src/bin/exporter.rs @@ -0,0 +1,249 @@ +use std::{collections::VecDeque, env::current_dir}; + +use colored::Colorize; + +fn main() -> Result<(), Box> { + println!(" {} `.cargo/cargo.toml`", "Reading".green().bold()); + + let start_time = std::time::Instant::now(); + + 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"); + let copy_configs = copy_configs().expect("Failed to get copy configurations"); + + // Final, export binaries to publish directory + let copied_files = export(target_dir, publish_dir, publish_binaries, copy_configs)?; + + let duration = start_time.elapsed(); + println!( + " {} publish {} {} in {:.1}s", + "Finished".green().bold(), + copied_files, + if copied_files == 1 { "file" } else { "files" }, + duration.as_secs_f32(), + ); + + Ok(()) +} + +/// Export binaries to publish directory +fn export( + target_dir: std::path::PathBuf, + publish_dir: std::path::PathBuf, + publish_binaries: Vec, + copy_configs: Vec, +) -> Result> { + let mut copied_files = 0; + + if publish_dir.exists() { + std::fs::remove_dir_all(&publish_dir)?; + } + std::fs::create_dir_all(&publish_dir)?; + + // Create bin directory for binaries + let bin_dir = publish_dir.join("bin"); + std::fs::create_dir_all(&bin_dir)?; + + // Copy binaries to bin directory + let mut queue = VecDeque::new(); + queue.push_back(target_dir); + + while let Some(current_dir) = queue.pop_front() { + let entries = match std::fs::read_dir(¤t_dir) { + Ok(entries) => entries, + Err(_) => continue, + }; + + for entry in entries.flatten() { + let path = entry.path(); + let metadata = match entry.metadata() { + Ok(metadata) => metadata, + Err(_) => continue, + }; + + if metadata.is_dir() { + queue.push_back(path); + continue; + } + + if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) + && publish_binaries.contains(&file_name.to_string()) + { + let dest_path = bin_dir.join(file_name); + + if let Some(parent) = dest_path.parent() { + std::fs::create_dir_all(parent)?; + } + + println!( + " {} `{}` ({})", + "Binary".green().bold(), + file_name, + path.display() + ); + std::fs::copy(&path, &dest_path)?; + copied_files += 1; + } + } + } + + // Copy additional files based on configuration + let current = current_dir()?; + for config in copy_configs { + // Check if platforms are specified and if current platform matches + if !config.platforms.is_empty() { + let current_platform = std::env::consts::OS; + if !config.platforms.contains(¤t_platform.to_string()) { + continue; + } + } + + let source_path = current.join(&config.from); + let dest_path = publish_dir.join(&config.to); + + if let Some(parent) = dest_path.parent() { + std::fs::create_dir_all(parent)?; + } + + if source_path.exists() { + println!( + " {} `{}` -> `{}` ({})", + "Other".green().bold(), + config.from, + config.to, + source_path.display() + ); + std::fs::copy(&source_path, &dest_path)?; + copied_files += 1; + } else { + println!( + " {} `{}` (file not found)", + "Warning".yellow().bold(), + config.from + ); + } + } + + Ok(copied_files) +} + +/// Copy configuration structure +#[derive(Debug)] +struct CopyConfig { + from: String, + to: String, + platforms: Vec, +} + +/// Get a target directory from the cargo config +/// Returns the complete path relative to the current directory +fn get_target_dir(section: &str) -> Result { + let current = current_dir()?; + let config_file = current.join(".cargo").join("config.toml"); + let config_content = std::fs::read_to_string(&config_file)?; + let config: toml::Value = toml::from_str(&config_content).map_err(|e| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("Failed to parse config.toml: {}", e), + ) + })?; + let target_dir_str = config[section]["target-dir"].as_str().ok_or_else(|| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + "target-dir not found or not a string", + ) + })?; + + Ok(current.join(target_dir_str)) +} + +/// Get the binaries list from the cargo config +/// Returns a vector of binary names +fn get_array(section: &str, array_name: &str) -> Result, std::io::Error> { + let current = current_dir()?; + let config_file = current.join(".cargo").join("config.toml"); + let config_content = std::fs::read_to_string(&config_file)?; + let config: toml::Value = toml::from_str(&config_content).map_err(|e| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("Failed to parse config.toml: {}", e), + ) + })?; + + if let Some(array) = config[section][array_name].as_array() { + let arr: Vec = array + .iter() + .filter_map(|v| v.as_str().map(String::from)) + .collect(); + Ok(arr) + } else { + Ok(Vec::new()) + } +} + +/// Get the copy configurations from the cargo config +/// Returns a vector of CopyConfig structs +fn copy_configs() -> Result, std::io::Error> { + let current = current_dir()?; + let config_file = current.join(".cargo").join("config.toml"); + let config_content = std::fs::read_to_string(&config_file)?; + let config: toml::Value = toml::from_str(&config_content).map_err(|e| { + std::io::Error::new( + std::io::ErrorKind::InvalidData, + format!("Failed to parse config.toml: {}", e), + ) + })?; + + let mut copy_configs = Vec::new(); + + if let Some(copies) = config.get("copies") { + if let Some(tables) = copies.as_table() { + for (_, table) in tables { + if let Some(from) = table.get("from").and_then(|v| v.as_str()) { + let to = table.get("to").and_then(|v| v.as_str()).unwrap_or(""); + + // Parse platforms array + let mut platforms = Vec::new(); + if let Some(platforms_array) = table.get("platform").and_then(|v| v.as_array()) + { + for platform in platforms_array { + if let Some(platform_str) = platform.as_str() { + platforms.push(platform_str.to_string()); + } + } + } + + copy_configs.push(CopyConfig { + from: from.to_string(), + to: to.to_string(), + platforms, + }); + } + } + } + } + + Ok(copy_configs) +} + +/// Get the target directory of the current project +/// By reading the `build.target-dir` configuration item in the `.cargo/config.toml` file +/// Returns the complete path relative to the current directory +fn current_target_dir() -> Result { + get_target_dir("build") +} + +/// Get the publish directory of the current project +/// By reading the `publish.target-dir` configuration item in the `.cargo/config.toml` file +/// Returns the complete path relative to the current directory +fn current_publish_dir() -> Result { + get_target_dir("publish") +} + +/// Get the binaries list for publishing +// By reading the `publish.binaries` configuration item in the `.cargo/config.toml` file +// Returns a vector of binary names +fn publish_binaries() -> Result, std::io::Error> { + get_array("publish", "binaries") +} -- cgit