knife_util/
path.rs

1//! # 智能路径管理模块
2//!
3//! 提供智能的工作目录检测和路径处理功能,支持开发和生产环境的自动切换。
4//!
5//! ## 核心功能
6//! - **环境感知**: 自动检测开发/生产环境
7//! - **智能路径**: 根据环境选择合适的工作目录
8//! - **路径构建**: 基于工作目录构建项目路径
9//!
10//! ## 环境检测逻辑
11//! - **开发环境**: 存在 `CARGO_MANIFEST_DIR` 环境变量
12//! - **生产环境**: 基于可执行文件位置推断工作目录
13
14use crate::error::AppError;
15use std::env;
16use std::path::PathBuf;
17
18/// 获取工作目录路径
19///
20/// 根据运行环境自动选择合适的工作目录:
21///
22/// ## 开发环境
23/// - 使用 `CARGO_MANIFEST_DIR/workspace` 目录
24/// - 测试时使用 `CARGO_MANIFEST_DIR/workspace/test` 目录
25///
26/// ## 生产环境
27/// - 基于可执行文件位置推断工作目录
28/// - 如果在 `bin/` 或 `sbin/` 目录中,使用父目录作为工作目录
29/// - 否则使用可执行文件所在目录
30///
31/// # 示例
32/// ```rust
33/// use knife_util::{get_work_dir, AppError};
34///
35/// fn main() -> Result<(), AppError> {
36///     let work_dir = get_work_dir()?;
37///     println!("工作目录: {:?}", work_dir);
38///     Ok(())
39/// }
40/// ```
41pub fn get_work_dir() -> Result<PathBuf, AppError> {
42    // 开发环境:使用 Cargo 项目目录
43    if is_dev_mode()
44        && let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR")
45    {
46        let manifest_path = PathBuf::from(manifest_dir);
47        if manifest_path.exists() && manifest_path.is_dir() {
48            let workspace_path = if cfg!(test) {
49                manifest_path.join("work").join("test")
50            } else {
51                manifest_path.join("work")
52            };
53            return Ok(workspace_path);
54        }
55    }
56
57    // 生产环境:基于可执行文件位置推断
58    if let Ok(exe_path) = env::current_exe()
59        && let Some(parent) = exe_path.parent()
60    {
61        // 检查是否在 bin 或 sbin 目录中
62        if let Some(parent_name) = parent.file_name()
63            && (parent_name == "bin" || parent_name == "sbin")
64            && let Some(grandparent) = parent.parent()
65        {
66            return Ok(grandparent.to_path_buf());
67        }
68        return Ok(parent.to_path_buf());
69    }
70
71    Err(AppError::new("GET_WORK_DIR_ERROR", "无法获取工作目录"))
72}
73
74/// 检查是否为开发模式
75///
76/// 通过检查 `CARGO_MANIFEST_DIR` 环境变量来判断是否在开发环境中运行。
77///
78/// # 返回值
79/// - `true`: 开发环境(存在 Cargo 项目)
80/// - `false`: 生产环境
81pub fn is_dev_mode() -> bool {
82    env::var("CARGO_MANIFEST_DIR").is_ok()
83}
84
85/// 构建工作路径
86///
87/// 基于工作目录构建完整的项目路径。
88///
89/// # 参数
90/// - `path`: 相对于工作目录的路径字符串
91///
92/// # 示例
93/// ```rust
94/// use knife_util::{build_work_path, AppError};
95///
96/// fn main() -> Result<(), AppError> {
97///     let config_path = build_work_path("config/app.toml")?;
98///     println!("配置文件路径: {:?}", config_path);
99///     Ok(())
100/// }
101/// ```
102pub fn build_work_path(path: &str) -> Result<PathBuf, AppError> {
103    let work_dir = get_work_dir()?;
104    Ok(work_dir.join(path))
105}