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

Split x setup sub-actions to CLI arguments #107848

Merged
merged 1 commit into from
Feb 26, 2023
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
2 changes: 1 addition & 1 deletion src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ impl<'a> Builder<'a> {
run::CollectLicenseMetadata,
run::GenerateCopyright,
),
Kind::Setup => describe!(setup::Profile),
Kind::Setup => describe!(setup::Profile, setup::Hook, setup::Link, setup::Vscode),
Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
// special-cased in Build::build()
Kind::Format => vec![],
Expand Down
13 changes: 10 additions & 3 deletions src/bootstrap/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,8 @@ Arguments:
Kind::Setup => {
subcommand_help.push_str(&format!(
"\n
x.py setup creates a `config.toml` which changes the defaults for x.py itself.
x.py setup creates a `config.toml` which changes the defaults for x.py itself,
as well as setting up a git pre-push hook, VS code config and toolchain link.

Arguments:
This subcommand accepts a 'profile' to use for builds. For example:
Expand All @@ -552,7 +553,13 @@ Arguments:
The profile is optional and you will be prompted interactively if it is not given.
The following profiles are available:

{}",
{}

To only set up the git hook, VS code or toolchain link, you may use
./x.py setup hook
./x.py setup vscode
./x.py setup link
",
Profile::all_for_help(" ").trim_end()
));
}
Expand Down Expand Up @@ -625,7 +632,7 @@ Arguments:
}
Kind::Setup => {
let profile = if paths.len() > 1 {
eprintln!("\nerror: At most one profile can be passed to setup\n");
eprintln!("\nerror: At most one option can be passed to setup\n");
usage(1, &opts, verbose, &subcommand_help)
} else if let Some(path) = paths.pop() {
let profile_string = t!(path.into_os_string().into_string().map_err(
Expand Down
120 changes: 103 additions & 17 deletions src/bootstrap/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub enum Profile {
Library,
Tools,
User,
None,
}

/// A list of historical hashes of `src/etc/vscode_settings.json`.
Expand All @@ -40,7 +41,7 @@ impl Profile {
pub fn all() -> impl Iterator<Item = Self> {
use Profile::*;
// N.B. these are ordered by how they are displayed, not alphabetically
[Library, Compiler, Codegen, Tools, User].iter().copied()
[Library, Compiler, Codegen, Tools, User, None].iter().copied()
}

pub fn purpose(&self) -> String {
Expand All @@ -51,6 +52,7 @@ impl Profile {
Codegen => "Contribute to the compiler, and also modify LLVM or codegen",
Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)",
User => "Install Rust from source",
None => "Do not modify `config.toml`"
}
.to_string()
}
Expand All @@ -70,6 +72,7 @@ impl Profile {
Profile::Library => "library",
Profile::Tools => "tools",
Profile::User => "user",
Profile::None => "none",
}
}
}
Expand All @@ -86,6 +89,7 @@ impl FromStr for Profile {
"tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => {
Ok(Profile::Tools)
}
"none" => Ok(Profile::None),
_ => Err(format!("unknown profile: '{}'", s)),
}
}
Expand Down Expand Up @@ -143,17 +147,8 @@ impl Step for Profile {
}

pub fn setup(config: &Config, profile: Profile) {
let stage_path =
["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());

if !rustup_installed() && profile != Profile::User {
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
} else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
attempt_toolchain_link(&stage_path[..]);
}

let suggestions = match profile {
Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
let suggestions: &[&str] = match profile {
Profile::Codegen | Profile::Compiler | Profile::None => &["check", "build", "test"],
Profile::Tools => &[
"check",
"build",
Expand All @@ -166,11 +161,6 @@ pub fn setup(config: &Config, profile: Profile) {
Profile::User => &["dist", "build"],
};

if !config.dry_run() {
t!(install_git_hook_maybe(&config));
t!(create_vscode_settings_maybe(&config));
}

println!();

println!("To get started, try one of the following commands:");
Expand All @@ -189,6 +179,9 @@ pub fn setup(config: &Config, profile: Profile) {
}

fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
if profile == Profile::None {
return;
}
if path.exists() {
eprintln!();
eprintln!(
Expand Down Expand Up @@ -216,6 +209,41 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
println!("`x.py` will now use the configuration at {}", include_path.display());
}

/// Creates a toolchain link for stage1 using `rustup`
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct Link;
impl Step for Link {
type Output = ();
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.alias("link")
}
fn make_run(run: RunConfig<'_>) {
if run.builder.config.dry_run() {
return;
}
if let [cmd] = &run.paths[..] {
if cmd.assert_single_path().path.as_path().as_os_str() == "link" {
run.builder.ensure(Link);
}
}
}
fn run(self, builder: &Builder<'_>) -> Self::Output {
let config = &builder.config;
if config.dry_run() {
return;
}
let stage_path =
["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());

if !rustup_installed() {
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
} else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
attempt_toolchain_link(&stage_path[..]);
}
}
}

fn rustup_installed() -> bool {
Command::new("rustup")
.arg("--version")
Expand Down Expand Up @@ -393,6 +421,35 @@ fn prompt_user(prompt: &str) -> io::Result<Option<PromptResult>> {
}
}

/// Installs `src/etc/pre-push.sh` as a Git hook
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct Hook;

impl Step for Hook {
type Output = ();
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.alias("hook")
}
fn make_run(run: RunConfig<'_>) {
if run.builder.config.dry_run() {
return;
}
if let [cmd] = &run.paths[..] {
if cmd.assert_single_path().path.as_path().as_os_str() == "hook" {
run.builder.ensure(Hook);
}
}
}
fn run(self, builder: &Builder<'_>) -> Self::Output {
let config = &builder.config;
if config.dry_run() {
return;
}
t!(install_git_hook_maybe(&config));
}
}

// install a git hook to automatically run tidy, if they want
fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
Expand Down Expand Up @@ -431,6 +488,35 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
Ok(())
}

/// Sets up or displays `src/etc/vscode_settings.json`
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct Vscode;

impl Step for Vscode {
type Output = ();
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.alias("vscode")
}
fn make_run(run: RunConfig<'_>) {
if run.builder.config.dry_run() {
return;
}
if let [cmd] = &run.paths[..] {
if cmd.assert_single_path().path.as_path().as_os_str() == "vscode" {
run.builder.ensure(Vscode);
}
}
}
fn run(self, builder: &Builder<'_>) -> Self::Output {
let config = &builder.config;
if config.dry_run() {
return;
}
t!(create_vscode_settings_maybe(&config));
}
}

/// Create a `.vscode/settings.json` file for rustc development, or just print it
fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> {
let (current_hash, historical_hashes) = SETTINGS_HASHES.split_last().unwrap();
Expand Down