1 /// Generating build depfiles from parsed bindings.
2 use std::{collections::BTreeSet, path::PathBuf};
3 
4 #[derive(Clone, Debug)]
5 pub(crate) struct DepfileSpec {
6     pub output_module: String,
7     pub depfile_path: PathBuf,
8 }
9 
10 impl DepfileSpec {
write(&self, deps: &BTreeSet<Box<str>>) -> std::io::Result<()>11     pub fn write(&self, deps: &BTreeSet<Box<str>>) -> std::io::Result<()> {
12         std::fs::write(&self.depfile_path, self.to_string(deps))
13     }
14 
to_string(&self, deps: &BTreeSet<Box<str>>) -> String15     fn to_string(&self, deps: &BTreeSet<Box<str>>) -> String {
16         // Transforms a string by escaping spaces and backslashes.
17         let escape = |s: &str| s.replace('\\', "\\\\").replace(' ', "\\ ");
18 
19         let mut buf = format!("{}:", escape(&self.output_module));
20         for file in deps {
21             buf = format!("{} {}", buf, escape(file));
22         }
23         buf
24     }
25 }
26 
27 #[cfg(test)]
28 mod tests {
29     use super::*;
30 
31     #[test]
32     fn escaping_depfile() {
33         let spec = DepfileSpec {
34             output_module: "Mod Name".to_owned(),
35             depfile_path: PathBuf::new(),
36         };
37 
38         let deps: BTreeSet<_> = vec![
39             r"/absolute/path".into(),
40             r"C:\win\absolute\path".into(),
41             r"../relative/path".into(),
42             r"..\win\relative\path".into(),
43             r"../path/with spaces/in/it".into(),
44             r"..\win\path\with spaces\in\it".into(),
45             r"path\with/mixed\separators".into(),
46         ]
47         .into_iter()
48         .collect();
49         assert_eq!(
50             spec.to_string(&deps),
51             "Mod\\ Name: \
52             ../path/with\\ spaces/in/it \
53             ../relative/path \
54             ..\\\\win\\\\path\\\\with\\ spaces\\\\in\\\\it \
55             ..\\\\win\\\\relative\\\\path \
56             /absolute/path \
57             C:\\\\win\\\\absolute\\\\path \
58             path\\\\with/mixed\\\\separators"
59         );
60     }
61 }
62