Skip to content

Commit 4b6010c

Browse files
authored
Rollup merge of #104952 - jyn514:setup, r=Mark-Simulacrum
Streamline the user experience for `x.py setup` ## Don't update submodules for x setup Before, the submodule handling was very jank and would update *between two interactive prompts*: ``` ; x setup Building rustbuild Finished dev [unoptimized] target(s) in 0.05s Welcome to the Rust project! What do you want to do with x.py? a) library: Contribute to the standard library Please choose one (a/b/c/d/e): a Updating submodule library/backtrace Submodule 'library/backtrace' (https://github.com/rust-lang/backtrace-rs.git) registered for path 'library/backtrace' error: you asked `x.py` to setup a new config file, but one already exists at `config.toml` Build completed unsuccessfully in 0:00:02 ``` That's not a great user experience because you need to wait a long time between prompts. It would be possible to move the submodule handling either before or after the prompt, but it seems better to just not require submodules to be checked out at all, to minimize the time spend waiting just to create a new configuration. ## Revamp the order setup executes - Create `config.toml` last. It's the most likely to error, and used to stop later steps from executing - Don't print an error message + exit if the git hook already exists; that's expected
2 parents 8ad447c + b771d90 commit 4b6010c

File tree

3 files changed

+77
-67
lines changed

3 files changed

+77
-67
lines changed

src/bootstrap/flags.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ pub enum Subcommand {
143143
args: Vec<String>,
144144
},
145145
Setup {
146-
profile: Profile,
146+
profile: Option<Profile>,
147147
},
148148
}
149149

@@ -628,14 +628,15 @@ Arguments:
628628
|path| format!("{} is not a valid UTF8 string", path.to_string_lossy())
629629
));
630630

631-
profile_string.parse().unwrap_or_else(|err| {
631+
let profile = profile_string.parse().unwrap_or_else(|err| {
632632
eprintln!("error: {}", err);
633633
eprintln!("help: the available profiles are:");
634634
eprint!("{}", Profile::all_for_help("- "));
635635
crate::detail_exit(1);
636-
})
636+
});
637+
Some(profile)
637638
} else {
638-
t!(crate::setup::interactive_path())
639+
None
639640
};
640641
Subcommand::Setup { profile }
641642
}

src/bootstrap/lib.rs

+25-19
Original file line numberDiff line numberDiff line change
@@ -542,16 +542,6 @@ impl Build {
542542
metrics: metrics::BuildMetrics::init(),
543543
};
544544

545-
build.verbose("finding compilers");
546-
cc_detect::find(&mut build);
547-
// When running `setup`, the profile is about to change, so any requirements we have now may
548-
// be different on the next invocation. Don't check for them until the next time x.py is
549-
// run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
550-
if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
551-
build.verbose("running sanity check");
552-
sanity::check(&mut build);
553-
}
554-
555545
// If local-rust is the same major.minor as the current version, then force a
556546
// local-rebuild
557547
let local_version_verbose =
@@ -567,16 +557,32 @@ impl Build {
567557
build.local_rebuild = true;
568558
}
569559

570-
// Make sure we update these before gathering metadata so we don't get an error about missing
571-
// Cargo.toml files.
572-
let rust_submodules =
573-
["src/tools/rust-installer", "src/tools/cargo", "library/backtrace", "library/stdarch"];
574-
for s in rust_submodules {
575-
build.update_submodule(Path::new(s));
576-
}
560+
build.verbose("finding compilers");
561+
cc_detect::find(&mut build);
562+
// When running `setup`, the profile is about to change, so any requirements we have now may
563+
// be different on the next invocation. Don't check for them until the next time x.py is
564+
// run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
565+
//
566+
// Similarly, for `setup` we don't actually need submodules or cargo metadata.
567+
if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
568+
build.verbose("running sanity check");
569+
sanity::check(&mut build);
577570

578-
build.verbose("learning about cargo");
579-
metadata::build(&mut build);
571+
// Make sure we update these before gathering metadata so we don't get an error about missing
572+
// Cargo.toml files.
573+
let rust_submodules = [
574+
"src/tools/rust-installer",
575+
"src/tools/cargo",
576+
"library/backtrace",
577+
"library/stdarch",
578+
];
579+
for s in rust_submodules {
580+
build.update_submodule(Path::new(s));
581+
}
582+
583+
build.verbose("learning about cargo");
584+
metadata::build(&mut build);
585+
}
580586

581587
build
582588
}

src/bootstrap/setup.rs

+47-44
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1+
use crate::Config;
12
use crate::{t, VERSION};
2-
use crate::{Config, TargetSelection};
33
use std::env::consts::EXE_SUFFIX;
44
use std::fmt::Write as _;
55
use std::fs::File;
6+
use std::io::Write;
67
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
78
use std::process::Command;
89
use std::str::FromStr;
9-
use std::{
10-
env, fmt, fs,
11-
io::{self, Write},
12-
};
10+
use std::{fmt, fs, io};
1311

1412
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1513
pub enum Profile {
@@ -81,38 +79,10 @@ impl fmt::Display for Profile {
8179
}
8280
}
8381

84-
pub fn setup(config: &Config, profile: Profile) {
85-
let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml"));
86-
87-
if path.exists() {
88-
eprintln!(
89-
"error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
90-
path.display()
91-
);
92-
eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display());
93-
eprintln!(
94-
"note: this will use the configuration in {}",
95-
profile.include_path(&config.src).display()
96-
);
97-
crate::detail_exit(1);
98-
}
99-
100-
let settings = format!(
101-
"# Includes one of the default files in src/bootstrap/defaults\n\
102-
profile = \"{}\"\n\
103-
changelog-seen = {}\n",
104-
profile, VERSION
105-
);
106-
t!(fs::write(path, settings));
107-
108-
let include_path = profile.include_path(&config.src);
109-
println!("`x.py` will now use the configuration at {}", include_path.display());
110-
111-
let build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
82+
pub fn setup(config: &Config, profile: Option<Profile>) {
83+
let profile = profile.unwrap_or_else(|| t!(interactive_path()));
11284
let stage_path =
113-
["build", build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
114-
115-
println!();
85+
["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
11686

11787
if !rustup_installed() && profile != Profile::User {
11888
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
@@ -134,8 +104,6 @@ pub fn setup(config: &Config, profile: Profile) {
134104
Profile::User => &["dist", "build"],
135105
};
136106

137-
println!();
138-
139107
t!(install_git_hook_maybe(&config));
140108

141109
println!();
@@ -150,6 +118,36 @@ pub fn setup(config: &Config, profile: Profile) {
150118
"For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
151119
);
152120
}
121+
122+
let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml"));
123+
setup_config_toml(path, profile, config);
124+
}
125+
126+
fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
127+
if path.exists() {
128+
eprintln!();
129+
eprintln!(
130+
"error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
131+
path.display()
132+
);
133+
eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display());
134+
eprintln!(
135+
"note: this will use the configuration in {}",
136+
profile.include_path(&config.src).display()
137+
);
138+
crate::detail_exit(1);
139+
}
140+
141+
let settings = format!(
142+
"# Includes one of the default files in src/bootstrap/defaults\n\
143+
profile = \"{}\"\n\
144+
changelog-seen = {}\n",
145+
profile, VERSION
146+
);
147+
t!(fs::write(path, settings));
148+
149+
let include_path = profile.include_path(&config.src);
150+
println!("`x.py` will now use the configuration at {}", include_path.display());
153151
}
154152

155153
fn rustup_installed() -> bool {
@@ -303,7 +301,18 @@ pub fn interactive_path() -> io::Result<Profile> {
303301

304302
// install a git hook to automatically run tidy --bless, if they want
305303
fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
304+
let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
305+
assert!(output.status.success(), "failed to run `git`");
306+
PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
307+
}));
308+
let dst = git.join("hooks").join("pre-push");
309+
if dst.exists() {
310+
// The git hook has already been set up, or the user already has a custom hook.
311+
return Ok(());
312+
}
313+
306314
let mut input = String::new();
315+
println!();
307316
println!(
308317
"Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
309318
If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before
@@ -329,12 +338,6 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
329338

330339
if should_install {
331340
let src = config.src.join("src").join("etc").join("pre-push.sh");
332-
let git =
333-
t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
334-
assert!(output.status.success(), "failed to run `git`");
335-
PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
336-
}));
337-
let dst = git.join("hooks").join("pre-push");
338341
match fs::hard_link(src, &dst) {
339342
Err(e) => eprintln!(
340343
"error: could not create hook {}: do you already have the git hook installed?\n{}",

0 commit comments

Comments
 (0)