Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide better documentation and help messages for x.py setup #77879

Merged
merged 5 commits into from
Oct 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/bootstrap/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ Subcommands:
dist Build distribution artifacts
install Install distribution artifacts
run, r Run tools contained in this repository
setup Create a config.toml (making it easier to use `x.py` itself)

To learn more about a subcommand, run `./x.py <subcommand> -h`",
);
Expand Down Expand Up @@ -472,15 +473,21 @@ Arguments:
);
}
"setup" => {
subcommand_help.push_str(
subcommand_help.push_str(&format!(
"\n
x.py setup creates a `config.toml` which changes the defaults for x.py itself.

Arguments:
This subcommand accepts a 'profile' to use for builds. For example:

./x.py setup library

The profile is optional and you will be prompted interactively if it is not given.",
);
The profile is optional and you will be prompted interactively if it is not given.
The following profiles are available:

{}",
Profile::all_for_help(" ").trim_end()
));
}
_ => {}
};
Expand Down Expand Up @@ -551,9 +558,7 @@ Arguments:
profile_string.parse().unwrap_or_else(|err| {
eprintln!("error: {}", err);
eprintln!("help: the available profiles are:");
for choice in Profile::all() {
eprintln!("- {}", choice);
}
eprint!("{}", Profile::all_for_help("- "));
std::process::exit(1);
})
} else {
Expand Down
70 changes: 55 additions & 15 deletions src/bootstrap/setup.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{t, VERSION};
use std::fmt::Write as _;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::{
Expand All @@ -20,7 +21,28 @@ impl Profile {
}

pub fn all() -> impl Iterator<Item = Self> {
[Profile::Compiler, Profile::Codegen, Profile::Library, Profile::User].iter().copied()
use Profile::*;
// N.B. these are ordered by how they are displayed, not alphabetically
[Library, Compiler, Codegen, User].iter().copied()
}

pub fn purpose(&self) -> String {
use Profile::*;
match self {
Library => "Contribute to the standard library",
Compiler => "Contribute to the compiler or rustdoc",
Codegen => "Contribute to the compiler, and also modify LLVM or codegen",
User => "Install Rust from source",
}
.to_string()
}

pub fn all_for_help(indent: &str) -> String {
let mut out = String::new();
for choice in Profile::all() {
writeln!(&mut out, "{}{}: {}", indent, choice, choice.purpose()).unwrap();
}
out
}
}

Expand All @@ -29,10 +51,10 @@ impl FromStr for Profile {

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"a" | "lib" | "library" => Ok(Profile::Library),
"b" | "compiler" | "rustdoc" => Ok(Profile::Compiler),
"c" | "llvm" | "codegen" => Ok(Profile::Codegen),
"d" | "maintainer" | "user" => Ok(Profile::User),
"lib" | "library" => Ok(Profile::Library),
"compiler" | "rustdoc" => Ok(Profile::Compiler),
"llvm" | "codegen" => Ok(Profile::Codegen),
"maintainer" | "user" => Ok(Profile::User),
_ => Err(format!("unknown profile: '{}'", s)),
}
}
Expand Down Expand Up @@ -104,19 +126,37 @@ pub fn setup(src_path: &Path, profile: Profile) {

// Used to get the path for `Subcommand::Setup`
pub fn interactive_path() -> io::Result<Profile> {
let mut input = String::new();
println!(
"Welcome to the Rust project! What do you want to do with x.py?
a) Contribute to the standard library
b) Contribute to the compiler or rustdoc
c) Contribute to the compiler, and also modify LLVM or codegen
d) Install Rust from source"
);
fn abbrev_all() -> impl Iterator<Item = (String, Profile)> {
jyn514 marked this conversation as resolved.
Show resolved Hide resolved
('a'..).map(|c| c.to_string()).zip(Profile::all())
}

fn parse_with_abbrev(input: &str) -> Result<Profile, String> {
let input = input.trim().to_lowercase();
for (letter, profile) in abbrev_all() {
if input == letter {
return Ok(profile);
}
}
input.parse()
}

println!("Welcome to the Rust project! What do you want to do with x.py?");
for (letter, profile) in abbrev_all() {
println!("{}) {}: {}", letter, profile, profile.purpose());
}
let template = loop {
print!("Please choose one (a/b/c/d): ");
print!(
"Please choose one ({}): ",
abbrev_all().map(|(l, _)| l).collect::<Vec<_>>().join("/")
);
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
jyn514 marked this conversation as resolved.
Show resolved Hide resolved
break match input.trim().to_lowercase().parse() {
if input == "" {
eprintln!("EOF on stdin, when expecting answer to question. Giving up.");
std::process::exit(1);
}
break match parse_with_abbrev(&input) {
Ok(profile) => profile,
Err(err) => {
println!("error: {}", err);
Expand Down