-
Notifications
You must be signed in to change notification settings - Fork 12.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a tool to run
x.py
from any subdirectory
This adds a binary called `x` in `src/tools/x`. All it does is check the current directory and its ancestors for a file called `x.py`, and if it finds one, runs it. By installing x, you can easily `x.py` from any subdirectory. It can be installed globally with `cargo install --path src/tools/x`
- Loading branch information
Showing
6 changed files
with
114 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# This file is automatically @generated by Cargo. | ||
# It is not intended for manual editing. | ||
[[package]] | ||
name = "x" | ||
version = "0.1.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[package] | ||
name = "x" | ||
version = "0.1.0" | ||
description = "Run x.py slightly more conveniently" | ||
authors = ["Casey Rodarmor <casey@rodarmor.com>"] | ||
edition = "2018" | ||
publish = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# x | ||
|
||
`x` invokes `x.py` from any subdirectory. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
//! 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, 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) { | ||
if dir.join(PYTHON).exists() { | ||
return PYTHON; | ||
} | ||
|
||
python2 |= dir.join(PYTHON2).exists(); | ||
python3 |= dir.join(PYTHON3).exists(); | ||
} | ||
|
||
if python3 { | ||
PYTHON3 | ||
} else if python2 { | ||
PYTHON2 | ||
} else { | ||
PYTHON | ||
} | ||
} | ||
|
||
#[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); | ||
} |
5fc22f1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why the name is
x.py
? thanks!5fc22f1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure! I think perhaps it was just a short letter that wasn't taken by another command, but I wasn't around when it was added, so I can't say for sure.
5fc22f1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@casey got it, thank you for your reply!