1use std::io::Write;
2use std::fs::OpenOptions;
3use chrono::Local;
4use std::path::PathBuf;
5use std::process::Command;
6use std::thread;
7use std::time::Duration;
8
9pub fn write_logfile(message: &str) {
10 let now = Local::now();
11 let timestamp = now.format("%Y-%m-%d %H:%M:%S").to_string();
12 let date = now.format("%Y-%m-%d").to_string();
13
14 let log_entry = format!("[{}] {}\n", timestamp, message);
15
16 let log_dir = PathBuf::from("/opt/builder/log");
17 let log_file = log_dir.join(format!("{}.log", date));
18
19 match OpenOptions::new()
20 .create(true)
21 .append(true)
22 .open(&log_file)
23 {
24 Ok(mut file) => {
25 match file.write_all(log_entry.as_bytes()) {
26 Ok(_) => {}
27 Err(e) => {
28 eprintln!("ERROR: could not write to log file: {:?}: {}", log_file, e);
29 std::process::exit(1);
30 }
31 }
32 }
33 Err(e) => {
34 eprintln!("ERROR: could not open log file: {:?}: {}", log_file, e);
35 std::process::exit(1);
36 }
37 }
38}
39
40pub fn log(message: &str) {
41 println!("{}", message);
42 write_logfile(message);
43}
44
45pub fn halt(message: &str) -> ! {
46 let error_message = &format!("ERROR: {}", message);
47 eprintln!("{}", error_message);
48 write_logfile(error_message);
49 std::process::exit(1)
50}
51
52pub fn perform( description: &str, mut check: Command, mut operation: Command ){
53 match check.output() {
54 Ok(output) => {
55 if output.status.success() {
56 log(&format!("{} was already done, skipping.", description));
57 return
58 }
59 },
60 Err(e) => {
61 halt(&format!("Check command '{}' failed: {}", check.cmdline(), e));
62 }
63 }
64
65 match operation.output() {
66 Ok(output) => {
67 if output.status.success() {
68 log(&format!("{} succeeded.", description));
69 } else {
70 let stdout = String::from_utf8_lossy(&output.stdout);
71 let stderr = String::from_utf8_lossy(&output.stderr);
72 halt(&format!("Command '{}' failed:\nSTDOUT: {}\nSTDERR: {}", operation.cmdline(), stdout, stderr));
73 }
74 },
75 Err(e) => {
76 halt(&format!("Command '{}' failed: {}", operation.cmdline(), e));
77 }
78 }
79
80}
81
82
83trait CommandExt {
84 fn cmdline(&self) -> String;
85}
86
87impl CommandExt for Command {
88 fn cmdline(&self) -> String {
89 format!("{} {}",
90 self.get_program().to_str().unwrap_or(""),
91 self.get_args().map(|s| s.to_str().unwrap_or("")).collect::<Vec<_>>().join(" ")
92 )
93 }
94}
95
96
97pub fn wait(mut command: Command, sleep: u64) {
98 loop {
99 match command.output() {
100 Ok(output) => {
101 if output.status.success() {
102 return;
103 } else {
104 thread::sleep(Duration::from_secs(sleep));
105 }
106 },
107 Err(e) => {
108 halt(&format!("Command '{}' failed: {}", command.cmdline(), e));
109 }
110 }
111 }
112}