1use std::process::Command;
2
3use anyhow::{ensure, Context};
4
5use crate::config::Config;
6
7pub fn build_submission(config: &Config) -> anyhow::Result<()> {
9 let cmd_args = &config.command.build.submission;
10
11 let Some(program) = cmd_args.first() else {
13 return Ok(());
14 };
15
16 let process_handle = Command::new(program)
17 .args(&cmd_args[1..])
18 .spawn()
19 .with_context(|| {
20 format!(
21 "
22Failed to start the child process that builds the submission code.
23List of arguments: {:?}
24",
25 cmd_args
26 )
27 })?;
28
29 let output = process_handle
30 .wait_with_output()
31 .with_context(|| "Failed to building the submission code.")?;
32
33 ensure!(
34 output.status.success(),
35 BuildCommandError {
36 cmd_args: config.command.build.submission.clone(),
37 output
38 }
39 );
40
41 Ok(())
42}
43
44pub fn build_tester(config: &Config) -> anyhow::Result<()> {
46 let cmd_args = &config.command.build.tester;
47
48 let Some(program) = cmd_args.first() else {
50 return Ok(());
51 };
52
53 let process_handle = Command::new(program)
54 .args(&cmd_args[1..])
55 .spawn()
56 .with_context(|| {
57 format!(
58 "
59Failed to start the child process that builds the local tester.
60List of arguments: {:?}
61",
62 cmd_args
63 )
64 })?;
65
66 let output = process_handle
67 .wait_with_output()
68 .with_context(|| "Failed to build the local tester.")?;
69
70 ensure!(
71 output.status.success(),
72 BuildCommandError {
73 cmd_args: config.command.build.tester.clone(),
74 output
75 }
76 );
77
78 Ok(())
79}
80
81#[derive(Debug)]
82pub struct BuildCommandError {
83 pub cmd_args: Vec<String>,
84 pub output: std::process::Output,
85}
86
87impl std::fmt::Display for BuildCommandError {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 let stdout = String::from_utf8(self.output.stdout.clone()).unwrap();
90 let stderr = String::from_utf8(self.output.stderr.clone()).unwrap();
91
92 write!(
93 f,
94 "
95Failed to execute command.
96
97Exit code: {}
98
99Command line arguments: {:?},
100
101------------------------------- Standard Output --------------------------------
102{}
103--------------------------------------------------------------------------------
104
105---------------------------- Standard Error Output -----------------------------
106{}
107--------------------------------------------------------------------------------
108",
109 self.output.status, self.cmd_args, stdout, stderr,
110 )
111 }
112}
113
114impl std::error::Error for BuildCommandError {}