Skip to main content

cargo_prepost/
lib.rs

1pub mod cargo_utils;
2pub mod prepost_utils;
3
4use cargo_metadata::MetadataCommand;
5use std::env;
6use std::path::{Path, PathBuf};
7
8pub fn get_target_dir(path: Option<PathBuf>) -> PathBuf {
9    let path = path.unwrap_or(env::current_dir().expect("Failed to get current dir"));
10    let cargo = search_original_cargo();
11    let target_dir = match MetadataCommand::new()
12        .current_dir(&path)
13        .cargo_path(&cargo)
14        .exec()
15    {
16        Ok(v) => v.target_directory.into_std_path_buf(),
17        Err(e) => {
18            log::warn!("Failed to get cargo metadata: {e}; use default values");
19            // TODO: Windows support
20            std::fs::canonicalize("./target").unwrap_or(PathBuf::from("./target"))
21        }
22    };
23    let target_dir = target_dir.join("prepost");
24    if let Err(e) = std::fs::create_dir_all(&target_dir) {
25        log::error!("Failed to create target directory: {e}");
26        std::process::exit(1);
27    }
28    target_dir
29}
30
31pub fn prepost_home_path() -> PathBuf {
32    match env::home_dir() {
33        Some(v) => v.join(".cargo-prepost"),
34        None => {
35            log::error!("Failed to get home directory");
36            std::process::exit(1);
37        }
38    }
39}
40
41pub fn create_alias(path: impl AsRef<Path>) {
42    let current_exe = match env::current_exe() {
43        Ok(v) => v,
44        Err(e) => {
45            log::error!("Failed to get current executable path: {e}");
46            std::process::exit(1);
47        }
48    };
49
50    let dir = path.as_ref().parent().unwrap();
51    if let Err(e) = std::fs::create_dir_all(dir) {
52        log::error!("Failed to create directory: {e}");
53        std::process::exit(1);
54    }
55    if let Err(e) = std::os::unix::fs::symlink(current_exe, &path) {
56        log::error!("Failed to create cargo symlink: {e}");
57        std::process::exit(1);
58    }
59}
60
61pub fn search_original_cargo() -> PathBuf {
62    let path = match env::var("PATH") {
63        Ok(v) => v,
64        _ => {
65            log::error!("Failed to get PATH");
66            std::process::exit(1);
67        }
68    };
69    let paths = env::split_paths(&path);
70    let mut cargo = None;
71    for path in paths {
72        let path = path.join("cargo");
73        if path.is_file()
74            && env::current_exe().expect("Failed to fetch current executable path") != path
75        {
76            log::info!("Find default cargo: {}", path.display());
77            cargo = Some(path);
78            break;
79        }
80    }
81    match cargo {
82        Some(v) => v,
83        None => {
84            log::error!("Failed to find default cargo");
85            std::process::exit(1);
86        }
87    }
88}
89
90#[cfg(test)]
91mod test {
92    use super::*;
93
94    #[test]
95    fn test_search_original_cargo() {
96        assert!(search_original_cargo().is_file());
97    }
98
99    #[test]
100    fn test_target_dir() {
101        let target = get_target_dir(None);
102        let current = env::current_dir().unwrap();
103        assert_eq!(target, current.join("target").join("prepost"));
104    }
105}