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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
//! Run `x.py` from any subdirectory of a rust compiler checkout.
//!
//! We prefer `exec`, to avoid adding an extra process in the process tree.
//! However, since `exec` isn't available on Windows, we indirect through
//! `exec_or_status`, which will call `exec` on unix and `status` on Windows.
//!
//! We use `python`, `python3`, or `python2` as the python interpreter to run
//! `x.py`, in that order of preference.
use std::{
env::{self, consts::EXE_EXTENSION},
io,
process::{self, Command, ExitStatus},
};
const PYTHON: &str = "python";
const PYTHON2: &str = "python2";
const PYTHON3: &str = "python3";
fn python() -> &'static str {
let val = match env::var_os("PATH") {
Some(val) => val,
None => return PYTHON,
};
let mut python2 = false;
let mut python3 = false;
for dir in env::split_paths(&val) {
// `python` should always take precedence over python2 / python3 if it exists
if dir.join(PYTHON).with_extension(EXE_EXTENSION).exists() {
return PYTHON;
}
python2 |= dir.join(PYTHON2).with_extension(EXE_EXTENSION).exists();
python3 |= dir.join(PYTHON3).with_extension(EXE_EXTENSION).exists();
}
// try 3 before 2
if python3 {
PYTHON3
} else if python2 {
PYTHON2
} else {
// Python was not found on path, so exit
eprintln!("Unable to find python in your PATH. Please check it is installed.");
process::exit(1);
}
}
#[cfg(unix)]
fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
use std::os::unix::process::CommandExt;
Err(command.exec())
}
#[cfg(not(unix))]
fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
command.status()
}
fn main() {
let current = match env::current_dir() {
Ok(dir) => dir,
Err(err) => {
eprintln!("Failed to get current directory: {err}");
process::exit(1);
}
};
for dir in current.ancestors() {
let candidate = dir.join("x.py");
if candidate.exists() {
let mut python = Command::new(python());
python.arg(&candidate).args(env::args().skip(1)).current_dir(dir);
let result = exec_or_status(&mut python);
match result {
Err(error) => {
eprintln!("Failed to invoke `{}`: {}", candidate.display(), error);
}
Ok(status) => {
process::exit(status.code().unwrap_or(1));
}
}
}
}
eprintln!(
"x.py not found. Please run inside of a checkout of `https://github.com/rust-lang/rust`."
);
process::exit(1);
}
|