cargo_test_support/
tools.rs
1use crate::{basic_manifest, paths, project, Project};
4use std::path::{Path, PathBuf};
5use std::sync::Mutex;
6use std::sync::OnceLock;
7
8static ECHO_WRAPPER: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();
9static ECHO: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();
10static CLIPPY_DRIVER: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();
11
12pub fn echo_wrapper() -> PathBuf {
16 let mut lock = ECHO_WRAPPER
17 .get_or_init(|| Default::default())
18 .lock()
19 .unwrap();
20 if let Some(path) = &*lock {
21 return path.clone();
22 }
23 let p = project()
24 .at(paths::global_root().join("rustc-echo-wrapper"))
25 .file("Cargo.toml", &basic_manifest("rustc-echo-wrapper", "1.0.0"))
26 .file(
27 "src/main.rs",
28 r#"
29 use std::fs::read_to_string;
30 use std::path::PathBuf;
31 fn main() {
32 // Handle args from `@path` argfile for rustc
33 let args = std::env::args()
34 .flat_map(|p| if let Some(p) = p.strip_prefix("@") {
35 read_to_string(p).unwrap().lines().map(String::from).collect()
36 } else {
37 vec![p]
38 })
39 .collect::<Vec<_>>();
40 eprintln!("WRAPPER CALLED: {}", args[1..].join(" "));
41 let status = std::process::Command::new(&args[1])
42 .args(&args[2..]).status().unwrap();
43 std::process::exit(status.code().unwrap_or(1));
44 }
45 "#,
46 )
47 .build();
48 p.cargo("build").run();
49 let path = p.bin("rustc-echo-wrapper");
50 *lock = Some(path.clone());
51 path
52}
53
54pub fn echo() -> PathBuf {
58 let mut lock = ECHO.get_or_init(|| Default::default()).lock().unwrap();
59 if let Some(path) = &*lock {
60 return path.clone();
61 }
62 if let Ok(path) = cargo_util::paths::resolve_executable(Path::new("echo")) {
63 *lock = Some(path.clone());
64 return path;
65 }
66 let p = project()
68 .at(paths::global_root().join("basic-echo"))
69 .file("Cargo.toml", &basic_manifest("basic-echo", "1.0.0"))
70 .file(
71 "src/main.rs",
72 r#"
73 fn main() {
74 let mut s = String::new();
75 let mut it = std::env::args().skip(1).peekable();
76 while let Some(n) = it.next() {
77 s.push_str(&n);
78 if it.peek().is_some() {
79 s.push(' ');
80 }
81 }
82 println!("{}", s);
83 }
84 "#,
85 )
86 .build();
87 p.cargo("build").run();
88 let path = p.bin("basic-echo");
89 *lock = Some(path.clone());
90 path
91}
92
93pub fn echo_subcommand() -> Project {
95 let p = project()
96 .at("cargo-echo")
97 .file("Cargo.toml", &basic_manifest("cargo-echo", "0.0.1"))
98 .file(
99 "src/main.rs",
100 r#"
101 fn main() {
102 let args: Vec<_> = ::std::env::args().skip(1).collect();
103 println!("{}", args.join(" "));
104 }
105 "#,
106 )
107 .build();
108 p.cargo("build").run();
109 p
110}
111
112pub fn wrapped_clippy_driver() -> PathBuf {
114 let mut lock = CLIPPY_DRIVER
115 .get_or_init(|| Default::default())
116 .lock()
117 .unwrap();
118 if let Some(path) = &*lock {
119 return path.clone();
120 }
121 let clippy_driver = project()
122 .at(paths::global_root().join("clippy-driver"))
123 .file("Cargo.toml", &basic_manifest("clippy-driver", "0.0.1"))
124 .file(
125 "src/main.rs",
126 r#"
127 fn main() {
128 let mut args = std::env::args_os();
129 let _me = args.next().unwrap();
130 let rustc = args.next().unwrap();
131 let status = std::process::Command::new(rustc).args(args).status().unwrap();
132 std::process::exit(status.code().unwrap_or(1));
133 }
134 "#,
135 )
136 .build();
137 clippy_driver.cargo("build").run();
138 let path = clippy_driver.bin("clippy-driver");
139 *lock = Some(path.clone());
140 path
141}