Skip to content

Commit 3905517

Browse files
Rollup merge of #107848 - clubby789:x-setup-options, r=Mark-Simulacrum
Split `x setup` sub-actions to CLI arguments Closes #107846 This adds a new `none` profile option which simply skips the `config.toml` step. It also adds `hook` and `vscode` subcommands, for installing the pre-push hook and getting `settings.json` respectively.
2 parents 1a599d7 + ee5404c commit 3905517

File tree

3 files changed

+114
-21
lines changed

3 files changed

+114
-21
lines changed

src/bootstrap/builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ impl<'a> Builder<'a> {
792792
run::CollectLicenseMetadata,
793793
run::GenerateCopyright,
794794
),
795-
Kind::Setup => describe!(setup::Profile),
795+
Kind::Setup => describe!(setup::Profile, setup::Hook, setup::Link, setup::Vscode),
796796
Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
797797
// special-cased in Build::build()
798798
Kind::Format => vec![],

src/bootstrap/flags.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,8 @@ Arguments:
554554
Kind::Setup => {
555555
subcommand_help.push_str(&format!(
556556
"\n
557-
x.py setup creates a `config.toml` which changes the defaults for x.py itself.
557+
x.py setup creates a `config.toml` which changes the defaults for x.py itself,
558+
as well as setting up a git pre-push hook, VS code config and toolchain link.
558559
559560
Arguments:
560561
This subcommand accepts a 'profile' to use for builds. For example:
@@ -564,7 +565,13 @@ Arguments:
564565
The profile is optional and you will be prompted interactively if it is not given.
565566
The following profiles are available:
566567
567-
{}",
568+
{}
569+
570+
To only set up the git hook, VS code or toolchain link, you may use
571+
./x.py setup hook
572+
./x.py setup vscode
573+
./x.py setup link
574+
",
568575
Profile::all_for_help(" ").trim_end()
569576
));
570577
}
@@ -638,7 +645,7 @@ Arguments:
638645
}
639646
Kind::Setup => {
640647
let profile = if paths.len() > 1 {
641-
eprintln!("\nerror: At most one profile can be passed to setup\n");
648+
eprintln!("\nerror: At most one option can be passed to setup\n");
642649
usage(1, &opts, verbose, &subcommand_help)
643650
} else if let Some(path) = paths.pop() {
644651
let profile_string = t!(path.into_os_string().into_string().map_err(

src/bootstrap/setup.rs

+103-17
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub enum Profile {
2121
Library,
2222
Tools,
2323
User,
24+
None,
2425
}
2526

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

4748
pub fn purpose(&self) -> String {
@@ -52,6 +53,7 @@ impl Profile {
5253
Codegen => "Contribute to the compiler, and also modify LLVM or codegen",
5354
Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)",
5455
User => "Install Rust from source",
56+
None => "Do not modify `config.toml`"
5557
}
5658
.to_string()
5759
}
@@ -71,6 +73,7 @@ impl Profile {
7173
Profile::Library => "library",
7274
Profile::Tools => "tools",
7375
Profile::User => "user",
76+
Profile::None => "none",
7477
}
7578
}
7679
}
@@ -87,6 +90,7 @@ impl FromStr for Profile {
8790
"tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => {
8891
Ok(Profile::Tools)
8992
}
93+
"none" => Ok(Profile::None),
9094
_ => Err(format!("unknown profile: '{}'", s)),
9195
}
9296
}
@@ -144,17 +148,8 @@ impl Step for Profile {
144148
}
145149

146150
pub fn setup(config: &Config, profile: Profile) {
147-
let stage_path =
148-
["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
149-
150-
if !rustup_installed() && profile != Profile::User {
151-
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
152-
} else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
153-
attempt_toolchain_link(&stage_path[..]);
154-
}
155-
156-
let suggestions = match profile {
157-
Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
151+
let suggestions: &[&str] = match profile {
152+
Profile::Codegen | Profile::Compiler | Profile::None => &["check", "build", "test"],
158153
Profile::Tools => &[
159154
"check",
160155
"build",
@@ -167,11 +162,6 @@ pub fn setup(config: &Config, profile: Profile) {
167162
Profile::User => &["dist", "build"],
168163
};
169164

170-
if !config.dry_run() {
171-
t!(install_git_hook_maybe(&config));
172-
t!(create_vscode_settings_maybe(&config));
173-
}
174-
175165
println!();
176166

177167
println!("To get started, try one of the following commands:");
@@ -190,6 +180,9 @@ pub fn setup(config: &Config, profile: Profile) {
190180
}
191181

192182
fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
183+
if profile == Profile::None {
184+
return;
185+
}
193186
if path.exists() {
194187
eprintln!();
195188
eprintln!(
@@ -217,6 +210,41 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
217210
println!("`x.py` will now use the configuration at {}", include_path.display());
218211
}
219212

213+
/// Creates a toolchain link for stage1 using `rustup`
214+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
215+
pub struct Link;
216+
impl Step for Link {
217+
type Output = ();
218+
const DEFAULT: bool = true;
219+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
220+
run.alias("link")
221+
}
222+
fn make_run(run: RunConfig<'_>) {
223+
if run.builder.config.dry_run() {
224+
return;
225+
}
226+
if let [cmd] = &run.paths[..] {
227+
if cmd.assert_single_path().path.as_path().as_os_str() == "link" {
228+
run.builder.ensure(Link);
229+
}
230+
}
231+
}
232+
fn run(self, builder: &Builder<'_>) -> Self::Output {
233+
let config = &builder.config;
234+
if config.dry_run() {
235+
return;
236+
}
237+
let stage_path =
238+
["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
239+
240+
if !rustup_installed() {
241+
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
242+
} else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
243+
attempt_toolchain_link(&stage_path[..]);
244+
}
245+
}
246+
}
247+
220248
fn rustup_installed() -> bool {
221249
Command::new("rustup")
222250
.arg("--version")
@@ -394,6 +422,35 @@ fn prompt_user(prompt: &str) -> io::Result<Option<PromptResult>> {
394422
}
395423
}
396424

425+
/// Installs `src/etc/pre-push.sh` as a Git hook
426+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
427+
pub struct Hook;
428+
429+
impl Step for Hook {
430+
type Output = ();
431+
const DEFAULT: bool = true;
432+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
433+
run.alias("hook")
434+
}
435+
fn make_run(run: RunConfig<'_>) {
436+
if run.builder.config.dry_run() {
437+
return;
438+
}
439+
if let [cmd] = &run.paths[..] {
440+
if cmd.assert_single_path().path.as_path().as_os_str() == "hook" {
441+
run.builder.ensure(Hook);
442+
}
443+
}
444+
}
445+
fn run(self, builder: &Builder<'_>) -> Self::Output {
446+
let config = &builder.config;
447+
if config.dry_run() {
448+
return;
449+
}
450+
t!(install_git_hook_maybe(&config));
451+
}
452+
}
453+
397454
// install a git hook to automatically run tidy, if they want
398455
fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
399456
let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
@@ -432,6 +489,35 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
432489
Ok(())
433490
}
434491

492+
/// Sets up or displays `src/etc/vscode_settings.json`
493+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
494+
pub struct Vscode;
495+
496+
impl Step for Vscode {
497+
type Output = ();
498+
const DEFAULT: bool = true;
499+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
500+
run.alias("vscode")
501+
}
502+
fn make_run(run: RunConfig<'_>) {
503+
if run.builder.config.dry_run() {
504+
return;
505+
}
506+
if let [cmd] = &run.paths[..] {
507+
if cmd.assert_single_path().path.as_path().as_os_str() == "vscode" {
508+
run.builder.ensure(Vscode);
509+
}
510+
}
511+
}
512+
fn run(self, builder: &Builder<'_>) -> Self::Output {
513+
let config = &builder.config;
514+
if config.dry_run() {
515+
return;
516+
}
517+
t!(create_vscode_settings_maybe(&config));
518+
}
519+
}
520+
435521
/// Create a `.vscode/settings.json` file for rustc development, or just print it
436522
fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> {
437523
let (current_hash, historical_hashes) = SETTINGS_HASHES.split_last().unwrap();

0 commit comments

Comments
 (0)