summaryrefslogtreecommitdiff
path: root/xtask/src/main.rs
blob: 8bf25ae43b8944dc44873c9000dc945779b89017 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use std::process::Command;

fn main()
{
    let mut args = std::env::args();

    let Some(task) = args.nth(1) else {
        println!("Error: No task is specified");
        return;
    };

    if task == "execute" {
        let Some(program) = args.next() else {
            println!("Error: No program is specified");
            return;
        };

        if let Err(err) = Command::new(program)
            .args(args)
            .remove_envs(
                // When a binary crate is run with 'cargo run', cargo sets environment
                // variables with information about the crate, package & cargo manifest.
                // These environment variables are unwanted when the program run here
                // is cargo so they are removed.
                //
                // If cargo is the program run here and the environment variables are
                // kept, cargo does not overwrite them, which can cause unnecessary
                // rebuilds of dependencies
                std::env::vars()
                    .map(|(key, _)| key)
                    .filter(|key| key.starts_with("CARGO_") && key != "CARGO_HOME"),
            )
            .status()
        {
            println!("Error: Failed to execute command: {err}");
        }
    } else {
        println!("Error: Unknown task '{task}'");
    }
}

trait CommandExt
{
    fn remove_envs(&mut self, keys: impl IntoIterator<Item = String>) -> &mut Self;
}

impl CommandExt for Command
{
    fn remove_envs(&mut self, keys: impl IntoIterator<Item = String>) -> &mut Self
    {
        for env_key in keys {
            self.env_remove(env_key);
        }

        self
    }
}