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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use std::process::Command;

use color_eyre::Result;

use crate::runner::IntoCommand;
use crate::Binaries;

pub struct Make {
    target: String,
    directory: Option<String>,
    variables: Vec<(String, String)>,
}

impl IntoCommand for &mut Make {
    fn into_command(self, _binaries: &Binaries) -> Result<Command> {
        // We're forced away from the full builder syntax because we need to return the owned
        // Command, not the &mut Command that the builder methods return.
        let mut command = Command::new("make");
        command.arg(&self.target);

        if let Some(directory) = &self.directory {
            command.args(["-C", directory]);
        }

        for (name, value) in &self.variables {
            command.arg(format!("{name}={value}"));
        }

        Ok(command)
    }
}

pub fn make(target: impl Into<String>) -> Make {
    Make {
        target: target.into().to_string(),
        directory: None,
        variables: vec![],
    }
}

impl Make {
    pub fn directory(&mut self, directory: impl Into<String>) -> &mut Self {
        self.directory = Some(directory.into());
        self
    }

    pub fn variable(&mut self, name: impl Into<String>, value: impl Into<String>) -> &mut Self {
        self.variables.push((name.into(), value.into()));
        self
    }
}

pub struct Gdb {
    binary: String,
    args: Vec<String>,
}

impl IntoCommand for &mut Gdb {
    fn into_command(self, binaries: &Binaries) -> Result<Command> {
        // We're forced away from the full builder syntax because we need to return the owned
        // Command, not the &mut Command that the builder methods return.
        let mut command = Command::new(&binaries.gdb);
        command.args(&self.args).arg(&self.binary);

        Ok(command)
    }
}

pub fn gdb(binary: impl Into<String>) -> Gdb {
    Gdb {
        binary: binary.into(),
        args: vec![],
    }
}

impl Gdb {
    pub fn arg(&mut self, arg: impl Into<String>) -> &mut Self {
        self.args.push(arg.into());
        self
    }
}