Skip to content

Commit 2547b4e

Browse files
authored
Merge pull request #12 from rust-lang/unstable-api-new-features
Add new features to `unstable-api` tool.
2 parents 929f596 + e696a60 commit 2547b4e

File tree

3 files changed

+69
-22
lines changed

3 files changed

+69
-22
lines changed

tools/unstable-api/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ version = "0.3"
1919

2020
[dependencies.anyhow]
2121
version = "1"
22+
23+
[target.'cfg(unix)'.dependencies]
24+
nix = "0.20"

tools/unstable-api/README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This tool will dump the public API for an unstable feature.
77
From this directory, run something like:
88

99
```shell
10-
cargo run --release -- --feature $feature --repo-root $path_to_rust | rustfmt
10+
cargo run --release -- --feature $feature --repo-root $path_to_rust
1111
```
1212

1313
where `$feature` is the name of the unstable feature and `$path_to_rust` is the path to a local clone of `rust-lang/rust`. You'll probably need to run `x.py` first to make sure submodules are cloned.
@@ -16,9 +16,16 @@ You can also install it as a Cargo tool and use it that way:
1616

1717
```shell
1818
cargo install --path .
19-
cargo unstable-api --feature $feature --repo-root $path_to_rust | rustfmt
19+
cd $path_to_rust
20+
cargo unstable-api --feature $feature
2021
```
2122

23+
You can leave out the `--repo-root` option when running it inside the `rust-lang/rust` repository.
24+
25+
## Output formatting
26+
27+
On Unix, the output is automatically formatted with `rustfmt` and highlighted with `bat`, if you have those tools installed.
28+
2229
## Limitations
2330

2431
APIs that are generated by macros won't be picked up. This tool just parses the source code so it can be run without needing to build the standard library itself.

tools/unstable-api/src/main.rs

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{env, path::PathBuf};
22

3-
use anyhow::Error;
3+
use anyhow::{Context, Error};
44
use structopt::StructOpt;
55

66
mod util;
@@ -14,33 +14,26 @@ mod visit;
1414
struct Opt {
1515
/// Repository root of `rust-lang/rust`.
1616
#[structopt(long, parse(from_os_str))]
17-
repo_root: PathBuf,
17+
repo_root: Option<PathBuf>,
1818
#[structopt(long)]
1919
feature: String,
2020
}
2121

2222
fn main() -> Result<(), Error> {
2323
let opt = Opt::from_iter(env::args().filter(|arg| arg != "unstable-api"));
2424

25+
let repo_root = match opt.repo_root {
26+
Some(p) => p,
27+
None => find_repo_root()?,
28+
};
29+
30+
#[cfg(unix)]
31+
setup_output_formatting();
32+
2533
let libs = vec![
26-
{
27-
let mut lib_core = opt.repo_root.clone();
28-
lib_core.push("library");
29-
lib_core.push("core");
30-
lib_core
31-
},
32-
{
33-
let mut lib_alloc = opt.repo_root.clone();
34-
lib_alloc.push("library");
35-
lib_alloc.push("alloc");
36-
lib_alloc
37-
},
38-
{
39-
let mut lib_std = opt.repo_root.clone();
40-
lib_std.push("library");
41-
lib_std.push("std");
42-
lib_std
43-
},
34+
repo_root.clone().join("library/core"),
35+
repo_root.clone().join("library/alloc"),
36+
repo_root.clone().join("library/std"),
4437
];
4538

4639
for crate_root in libs {
@@ -49,3 +42,47 @@ fn main() -> Result<(), Error> {
4942

5043
Ok(())
5144
}
45+
46+
fn find_repo_root() -> Result<PathBuf, Error> {
47+
let path = std::process::Command::new("cargo")
48+
.arg("locate-project")
49+
.arg("--workspace")
50+
.arg("--message-format=plain")
51+
.output()
52+
.context("unable to find repository root")?
53+
.stdout;
54+
let mut path = PathBuf::from(String::from_utf8(path)?);
55+
path.pop();
56+
Ok(path)
57+
}
58+
59+
#[cfg(unix)]
60+
fn setup_output_formatting() {
61+
use nix::unistd::{isatty, dup2};
62+
use std::os::unix::io::AsRawFd;
63+
use std::process::{Command, Stdio};
64+
65+
if isatty(1) == Ok(true) {
66+
// Pipe the output through `bat` for nice formatting and paging, if available.
67+
if let Ok(mut bat) = Command::new("bat")
68+
.arg("--language=rust")
69+
.arg("--plain") // Disable line numbers for easy copy-pasting.
70+
.stdin(Stdio::piped())
71+
.stdout(Stdio::inherit())
72+
.spawn()
73+
{
74+
// Replace our stdout by the pipe into `bat`.
75+
dup2(bat.stdin.take().unwrap().as_raw_fd(), 1).unwrap();
76+
}
77+
}
78+
79+
// Pipe the output through `rustfmt`, if available.
80+
if let Ok(mut rustfmt) = Command::new("rustfmt")
81+
.stdin(Stdio::piped())
82+
.stdout(Stdio::inherit()) // This pipes into `bat` if it was executed above.
83+
.spawn()
84+
{
85+
// Replace our stdout by the pipe into `rustfmt`.
86+
dup2(rustfmt.stdin.take().unwrap().as_raw_fd(), 1).unwrap();
87+
}
88+
}

0 commit comments

Comments
 (0)