insta_cmd/
cargo.rs

1use std::env;
2use std::path::PathBuf;
3use std::process::Command;
4
5use serde::Deserialize;
6
7#[derive(Deserialize)]
8struct MetaData {
9    target_directory: PathBuf,
10}
11
12fn add_profile_dir(mut target_dir: PathBuf) -> PathBuf {
13    if cfg!(debug_assertions) {
14        target_dir.push("debug");
15    } else {
16        target_dir.push("release");
17    }
18    target_dir
19}
20
21fn primary_target_dir() -> PathBuf {
22    // the target dir is explicitly set and exists
23    if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") {
24        let target_dir = add_profile_dir(PathBuf::from(target_dir));
25        if target_dir.is_dir() {
26            return target_dir;
27        };
28    }
29
30    // try to guess it from the current exe
31    env::current_exe()
32        .ok()
33        .map(|mut path| {
34            path.pop();
35            if path.ends_with("deps") || path.ends_with("examples") {
36                path.pop();
37            }
38            path
39        })
40        .unwrap()
41}
42
43fn cargo_inferred_target_dir() -> PathBuf {
44    let metadata = Command::new(env::var("CARGO").ok().unwrap_or_else(|| "cargo".into()))
45        .arg("metadata")
46        .output()
47        .unwrap();
48    let meta: MetaData = serde_json::from_slice(&metadata.stdout).unwrap();
49    add_profile_dir(meta.target_directory)
50}
51
52fn find_exe(name: &str) -> PathBuf {
53    let mut first = primary_target_dir();
54    first.push(name);
55    if first.is_file() {
56        return first;
57    }
58
59    let mut alt = cargo_inferred_target_dir();
60    alt.push(name);
61    if alt.is_file() {
62        return alt;
63    }
64    panic!("Cannot determine path to executable '{}'", name);
65}
66
67/// Helper function to return the path to an executable that cargo is building.
68pub fn get_cargo_bin(name: &str) -> PathBuf {
69    let env_var = format!("CARGO_BIN_EXE_{}", name);
70    env::var_os(env_var)
71        .map(|p| p.into())
72        .unwrap_or_else(|| find_exe(&format!("{}{}", name, env::consts::EXE_SUFFIX)))
73}
74
75/// Helper function to return the path to an example that cargo is building.
76pub fn get_cargo_example(name: &str) -> PathBuf {
77    find_exe(&format!("examples/{}{}", name, env::consts::EXE_SUFFIX))
78}