knife_util/path.rs
1//! 路径工具模块
2//!
3//! 提供工作目录检测和路径处理功能
4
5use crate::error::AppError;
6use std::env;
7use std::path::PathBuf;
8
9/// 获取工作目录路径
10///
11/// 根据环境自动判断工作目录:
12/// - 开发环境:使用 `workspace` 目录(测试时使用 `workspace/test`)
13/// - 生产环境:使用可执行文件所在目录
14///
15/// # 示例
16/// ```rust
17/// use knife_util::get_work_dir;
18///
19/// fn main() -> Result<(), knife_util::AppError> {
20/// let work_dir = get_work_dir()?;
21/// println!("工作目录: {:?}", work_dir);
22/// Ok(())
23/// }
24/// ```
25pub fn get_work_dir() -> Result<PathBuf, AppError> {
26 if is_dev_mode() {
27 // 在开发环境中,使用Cargo清单目录
28 if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
29 let manifest_path = PathBuf::from(manifest_dir);
30
31 // 验证路径是否存在且为目录
32 if manifest_path.exists() && manifest_path.is_dir() {
33 let workspace_path = if cfg!(test) {
34 manifest_path.join("workspace").join("test")
35 } else {
36 manifest_path.join("workspace")
37 };
38 return Ok(workspace_path);
39 }
40 }
41 }
42
43 // 在生产环境中,尝试获取可执行文件路径
44 if let Ok(exe_path) = env::current_exe()
45 && let Some(parent) = exe_path.parent()
46 {
47 // 检查可执行文件是否在bin或sbin目录中,如果是则使用上级目录
48 if let Some(parent_name) = parent.file_name()
49 && (parent_name == "bin" || parent_name == "sbin")
50 && let Some(grandparent) = parent.parent()
51 {
52 return Ok(grandparent.to_path_buf());
53 }
54 // 否则使用可执行文件所在路径
55 return Ok(parent.to_path_buf());
56 }
57
58 Err(AppError::new("GET_WORK_DIR_ERROR", "无法获取工作目录"))
59}
60
61/// 检查是否为开发模式
62///
63/// 通过检查CARGO_MANIFEST_DIR环境变量判断
64///
65/// # 示例
66/// ```rust
67/// use knife_util::is_dev_mode;
68///
69/// if is_dev_mode() {
70/// println!("当前在开发模式中");
71/// } else {
72/// println!("当前在生产模式中");
73/// }
74/// ```
75pub fn is_dev_mode() -> bool {
76 env::var("CARGO_MANIFEST_DIR").is_ok()
77}
78
79/// 构建工作路径
80///
81/// 基于工作目录构建指定路径
82///
83/// # 示例
84/// ```rust
85/// use knife_util::build_work_path;
86///
87/// fn main() -> Result<(), knife_util::AppError> {
88/// let config_path = build_work_path("config/app.toml")?;
89/// println!("配置文件路径: {:?}", config_path);
90/// Ok(())
91/// }
92/// ```
93pub fn build_work_path(path: &str) -> Result<PathBuf, AppError> {
94 let work_dir = get_work_dir()?;
95 Ok(work_dir.join(path))
96}