Skip to content

Commit 0f26318

Browse files
committed
Add additional options to x setup
1 parent 6f5451e commit 0f26318

File tree

4 files changed

+122
-30
lines changed

4 files changed

+122
-30
lines changed

src/bootstrap/builder.rs

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

src/bootstrap/config.rs

-3
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,6 @@ pub struct Config {
233233
pub rust_info: channel::GitInfo,
234234

235235
pub paths: Vec<PathBuf>,
236-
/// Arguments appearing after `--` to be forwarded to tools,
237-
/// e.g. `--fix-broken` or test arguments.
238-
pub free_args: Vec<String>,
239236
}
240237

241238
#[derive(Default, Deserialize)]

src/bootstrap/flags.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub enum Warnings {
3030
/// Parsed version of command line flags using [`clap::Parser`]
3131
#[clap(
3232
override_usage = "x.py <subcommand> [options] [<paths>...]",
33-
disable_help_subcommand(true),
33+
// disable_help_subcommand(true),
3434
about = "",
3535
next_line_help(false)
3636
)]
@@ -371,17 +371,28 @@ pub enum Subcommand {
371371
#[arg(long, allow_hyphen_values(true))]
372372
args: Vec<String>,
373373
},
374-
/// Create a config.toml (making it easier to use `x.py` itself)
374+
/// Set up the environment for development
375375
#[clap(long_about = format!(
376376
"\n
377-
x.py setup creates a `config.toml` which changes the defaults for x.py itself.
377+
x.py setup creates a `config.toml` which changes the defaults for x.py itself,
378+
as well as setting up a git pre-push hook, VS Code config and toolchain link.
378379
Arguments:
379380
This subcommand accepts a 'profile' to use for builds. For example:
380-
./x.py setup library
381+
./x.py setup library
381382
The profile is optional and you will be prompted interactively if it is not given.
382383
The following profiles are available:
383-
{}", Profile::all_for_help(" ").trim_end()))]
384-
Setup { profile: Option<PathBuf> },
384+
{}
385+
386+
To only set up the git hook, VS Code config or toolchain link, you may use
387+
./x.py setup hook
388+
./x.py setup vscode
389+
./x.py setup link", Profile::all_for_help(" ").trim_end()))]
390+
Setup {
391+
/// Either the profile for `config.toml` or another setup action/
392+
/// May be omitted to set up interactively
393+
#[arg(value_name = "<PROFILE>|hook|vscode|link")]
394+
profile: Option<PathBuf>,
395+
},
385396
}
386397

387398
impl Subcommand {

src/bootstrap/setup.rs

+104-20
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`.
@@ -40,7 +41,7 @@ impl Profile {
4041
pub fn all() -> impl Iterator<Item = Self> {
4142
use Profile::*;
4243
// N.B. these are ordered by how they are displayed, not alphabetically
43-
[Library, Compiler, Codegen, Tools, User].iter().copied()
44+
[Library, Compiler, Codegen, Tools, User, None].iter().copied()
4445
}
4546

4647
pub fn purpose(&self) -> String {
@@ -51,6 +52,7 @@ impl Profile {
5152
Codegen => "Contribute to the compiler, and also modify LLVM or codegen",
5253
Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)",
5354
User => "Install Rust from source",
55+
None => "Do not modify `config.toml`"
5456
}
5557
.to_string()
5658
}
@@ -70,6 +72,7 @@ impl Profile {
7072
Profile::Library => "library",
7173
Profile::Tools => "tools",
7274
Profile::User => "user",
75+
Profile::None => "none",
7376
}
7477
}
7578
}
@@ -86,6 +89,7 @@ impl FromStr for Profile {
8689
"tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => {
8790
Ok(Profile::Tools)
8891
}
92+
"none" => Ok(Profile::None),
8993
_ => Err(format!("unknown profile: '{}'", s)),
9094
}
9195
}
@@ -143,17 +147,8 @@ impl Step for Profile {
143147
}
144148

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

169-
if !config.dry_run() {
170-
t!(install_git_hook_maybe(&config));
171-
t!(create_vscode_settings_maybe(&config));
172-
}
173-
174-
println!();
175-
176-
println!("To get started, try one of the following commands:");
164+
println!("\nTo get started, try one of the following commands:");
177165
for cmd in suggestions {
178166
println!("- `x.py {}`", cmd);
179167
}
@@ -189,6 +177,9 @@ pub fn setup(config: &Config, profile: Profile) {
189177
}
190178

191179
fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
180+
if profile == Profile::None {
181+
return;
182+
}
192183
if path.exists() {
193184
eprintln!();
194185
eprintln!(
@@ -216,6 +207,41 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
216207
println!("`x.py` will now use the configuration at {}", include_path.display());
217208
}
218209

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

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

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

0 commit comments

Comments
 (0)