Skip to content

Commit ec6d1af

Browse files
authored
Installation profiles (#1673)
* Add profile argument to rustup install * Address some warnings Signed-off-by: Nick Cameron <[email protected]> * Review changes Signed-off-by: Nick Cameron <[email protected]>
1 parent 039a0a8 commit ec6d1af

30 files changed

+1348
-567
lines changed

rustup-init.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ OPTIONS:
2929
--default-host <default-host> Choose a default host triple
3030
--default-toolchain <default-toolchain> Choose a default toolchain to install
3131
--default-toolchain none Do not install any toolchains
32+
--profile [minimal|default|complete] Choose a profile
3233
EOF
3334
}
3435

src/cli/common.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,7 @@ pub fn list_targets(toolchain: &Toolchain<'_>) -> Result<()> {
368368
.target
369369
.as_ref()
370370
.expect("rust-std should have a target");
371-
if component.required {
372-
let _ = t.attr(term2::Attr::Bold);
373-
let _ = writeln!(t, "{} (default)", target);
374-
let _ = t.reset();
375-
} else if component.installed {
371+
if component.installed {
376372
let _ = t.attr(term2::Attr::Bold);
377373
let _ = writeln!(t, "{} (installed)", target);
378374
let _ = t.reset();
@@ -406,11 +402,7 @@ pub fn list_components(toolchain: &Toolchain<'_>) -> Result<()> {
406402
let mut t = term2::stdout();
407403
for component in toolchain.list_components()? {
408404
let name = component.name;
409-
if component.required {
410-
t.attr(term2::Attr::Bold)?;
411-
writeln!(t, "{} (default)", name)?;
412-
t.reset()?;
413-
} else if component.installed {
405+
if component.installed {
414406
t.attr(term2::Attr::Bold)?;
415407
writeln!(t, "{} (installed)", name)?;
416408
t.reset()?;

src/cli/download_tracker.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,6 @@ impl<'a> fmt::Display for Size<'a> {
251251

252252
#[cfg(test)]
253253
mod tests {
254-
255254
#[test]
256255
fn download_tracker_from_seconds_test() {
257256
use crate::download_tracker::DownloadTracker;

src/cli/rustup_mode.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::self_update;
55
use crate::term2;
66
use crate::term2::Terminal;
77
use clap::{App, AppSettings, Arg, ArgGroup, ArgMatches, Shell, SubCommand};
8-
use rustup::dist::dist::{PartialTargetTriple, PartialToolchainDesc, TargetTriple};
8+
use rustup::dist::dist::{PartialTargetTriple, PartialToolchainDesc, Profile, TargetTriple};
99
use rustup::dist::manifest::Component;
1010
use rustup::utils::utils::{self, ExitCode};
1111
use rustup::{command, Cfg, Toolchain};
@@ -44,6 +44,7 @@ pub fn main() -> Result<()> {
4444
("show", Some(c)) => match c.subcommand() {
4545
("active-toolchain", Some(_)) => handle_epipe(show_active_toolchain(cfg))?,
4646
("home", Some(_)) => handle_epipe(show_rustup_home(cfg))?,
47+
("profile", Some(_)) => handle_epipe(show_profile(cfg))?,
4748
(_, _) => handle_epipe(show(cfg))?,
4849
},
4950
("install", Some(m)) => update(cfg, m)?,
@@ -86,6 +87,7 @@ pub fn main() -> Result<()> {
8687
},
8788
("set", Some(c)) => match c.subcommand() {
8889
("default-host", Some(m)) => set_default_host_triple(&cfg, m)?,
90+
("profile", Some(m)) => set_profile(&cfg, m)?,
8991
(_, _) => unreachable!(),
9092
},
9193
("completions", Some(c)) => {
@@ -125,7 +127,7 @@ pub fn cli() -> App<'static, 'static> {
125127
)
126128
.subcommand(
127129
SubCommand::with_name("show")
128-
.about("Show the active and installed toolchains")
130+
.about("Show the active and installed toolchains or profiles")
129131
.after_help(SHOW_HELP)
130132
.setting(AppSettings::VersionlessSubcommands)
131133
.setting(AppSettings::DeriveDisplayOrder)
@@ -138,6 +140,7 @@ pub fn cli() -> App<'static, 'static> {
138140
SubCommand::with_name("home")
139141
.about("Display the computed value of RUSTUP_HOME"),
140142
)
143+
.subcommand(SubCommand::with_name("profile").about("Show the current profile")),
141144
)
142145
.subcommand(
143146
SubCommand::with_name("install")
@@ -501,6 +504,16 @@ pub fn cli() -> App<'static, 'static> {
501504
SubCommand::with_name("default-host")
502505
.about("The triple used to identify toolchains when not specified")
503506
.arg(Arg::with_name("host_triple").required(true)),
507+
)
508+
.subcommand(
509+
SubCommand::with_name("profile")
510+
.about("The default components installed")
511+
.arg(
512+
Arg::with_name("profile-name")
513+
.required(true)
514+
.possible_values(Profile::names())
515+
.default_value(Profile::default_name()),
516+
),
504517
),
505518
);
506519

@@ -919,7 +932,11 @@ fn target_add(cfg: &Cfg, m: &ArgMatches<'_>) -> Result<()> {
919932
}
920933

921934
for target in &targets {
922-
let new_component = Component::new("rust-std".to_string(), Some(TargetTriple::new(target)));
935+
let new_component = Component::new(
936+
"rust-std".to_string(),
937+
Some(TargetTriple::new(target)),
938+
false,
939+
);
923940
toolchain.add_component(new_component)?;
924941
}
925942

@@ -930,7 +947,11 @@ fn target_remove(cfg: &Cfg, m: &ArgMatches<'_>) -> Result<()> {
930947
let toolchain = explicit_or_dir_toolchain(cfg, m)?;
931948

932949
for target in m.values_of("target").expect("") {
933-
let new_component = Component::new("rust-std".to_string(), Some(TargetTriple::new(target)));
950+
let new_component = Component::new(
951+
"rust-std".to_string(),
952+
Some(TargetTriple::new(target)),
953+
false,
954+
);
934955

935956
toolchain.remove_component(new_component)?;
936957
}
@@ -959,7 +980,7 @@ fn component_add(cfg: &Cfg, m: &ArgMatches<'_>) -> Result<()> {
959980
});
960981

961982
for component in m.values_of("component").expect("") {
962-
let new_component = Component::new(component.to_string(), target.clone());
983+
let new_component = Component::new(component.to_string(), target.clone(), true);
963984

964985
toolchain.add_component(new_component)?;
965986
}
@@ -978,7 +999,7 @@ fn component_remove(cfg: &Cfg, m: &ArgMatches<'_>) -> Result<()> {
978999
});
9791000

9801001
for component in m.values_of("component").expect("") {
981-
let new_component = Component::new(component.to_string(), target.clone());
1002+
let new_component = Component::new(component.to_string(), target.clone(), true);
9821003

9831004
toolchain.remove_component(new_component)?;
9841005
}
@@ -1159,6 +1180,19 @@ fn set_default_host_triple(cfg: &Cfg, m: &ArgMatches<'_>) -> Result<()> {
11591180
Ok(())
11601181
}
11611182

1183+
fn set_profile(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
1184+
cfg.set_profile(&m.value_of("profile-name").unwrap())?;
1185+
Ok(())
1186+
}
1187+
1188+
fn show_profile(cfg: &Cfg) -> Result<()> {
1189+
match cfg.get_profile()? {
1190+
Some(p) => println!("{}", p),
1191+
None => println!("No profile set"),
1192+
}
1193+
Ok(())
1194+
}
1195+
11621196
#[derive(Copy, Clone, Debug, PartialEq)]
11631197
pub enum CompletionCommand {
11641198
Rustup,

src/cli/self_update.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use crate::common::{self, Confirm};
3434
use crate::errors::*;
3535
use crate::markdown::md;
3636
use crate::term2;
37-
use rustup::dist::dist;
37+
use rustup::dist::dist::{self, Profile};
3838
use rustup::utils::utils;
3939
use rustup::utils::Notification;
4040
use rustup::{DUP_TOOLS, TOOLS};
@@ -48,6 +48,7 @@ use std::process::{self, Command};
4848
pub struct InstallOpts {
4949
pub default_host_triple: String,
5050
pub default_toolchain: String,
51+
pub profile: String,
5152
pub no_modify_path: bool,
5253
}
5354

@@ -278,7 +279,12 @@ pub fn install(no_prompt: bool, verbose: bool, mut opts: InstallOpts) -> Result<
278279
do_add_to_path(&get_add_path_methods())?;
279280
}
280281
utils::create_rustup_home()?;
281-
maybe_install_rust(&opts.default_toolchain, &opts.default_host_triple, verbose)?;
282+
maybe_install_rust(
283+
&opts.default_toolchain,
284+
&opts.profile,
285+
&opts.default_host_triple,
286+
verbose,
287+
)?;
282288

283289
if cfg!(unix) {
284290
let env_file = utils::cargo_home()?.join("env");
@@ -590,10 +596,12 @@ fn current_install_opts(opts: &InstallOpts) -> String {
590596
591597
- ` `default host triple: `{}`
592598
- ` `default toolchain: `{}`
599+
- ` `profile: `{}`
593600
- modify PATH variable: `{}`
594601
",
595602
opts.default_host_triple,
596603
opts.default_toolchain,
604+
opts.profile,
597605
if !opts.no_modify_path { "yes" } else { "no" }
598606
)
599607
}
@@ -615,6 +623,14 @@ fn customize_install(mut opts: InstallOpts) -> Result<InstallOpts> {
615623
&opts.default_toolchain,
616624
)?;
617625

626+
opts.profile = common::question_str(
627+
&format!(
628+
"Profile (which tools and data to install)? ({})",
629+
Profile::names().join("/")
630+
),
631+
&opts.profile,
632+
)?;
633+
618634
opts.no_modify_path =
619635
!common::question_bool("Modify PATH variable? (y/n)", !opts.no_modify_path)?;
620636

@@ -716,8 +732,14 @@ pub fn install_proxies() -> Result<()> {
716732
Ok(())
717733
}
718734

719-
fn maybe_install_rust(toolchain_str: &str, default_host_triple: &str, verbose: bool) -> Result<()> {
735+
fn maybe_install_rust(
736+
toolchain_str: &str,
737+
profile_str: &str,
738+
default_host_triple: &str,
739+
verbose: bool,
740+
) -> Result<()> {
720741
let cfg = common::set_globals(verbose)?;
742+
cfg.set_profile(profile_str)?;
721743

722744
// If there is already an install, then `toolchain_str` may not be
723745
// a toolchain the user actually wants. Don't do anything. FIXME:
@@ -787,7 +809,8 @@ pub fn uninstall(no_prompt: bool) -> Result<()> {
787809
// Delete everything in CARGO_HOME *except* the rustup bin
788810

789811
// First everything except the bin directory
790-
for dirent in fs::read_dir(&cargo_home).chain_err(|| read_dir_err)? {
812+
let diriter = fs::read_dir(&cargo_home).chain_err(|| read_dir_err)?;
813+
for dirent in diriter {
791814
let dirent = dirent.chain_err(|| read_dir_err)?;
792815
if dirent.file_name().to_str() != Some("bin") {
793816
if dirent.path().is_dir() {
@@ -805,7 +828,8 @@ pub fn uninstall(no_prompt: bool) -> Result<()> {
805828
.chain(DUP_TOOLS.iter())
806829
.map(|t| format!("{}{}", t, EXE_SUFFIX));
807830
let tools: Vec<_> = tools.chain(vec![format!("rustup{}", EXE_SUFFIX)]).collect();
808-
for dirent in fs::read_dir(&cargo_home.join("bin")).chain_err(|| read_dir_err)? {
831+
let diriter = fs::read_dir(&cargo_home.join("bin")).chain_err(|| read_dir_err)?;
832+
for dirent in diriter {
809833
let dirent = dirent.chain_err(|| read_dir_err)?;
810834
let name = dirent.file_name();
811835
let file_is_tool = name.to_str().map(|n| tools.iter().any(|t| *t == n));

src/cli/setup_mode.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::common;
22
use crate::errors::*;
33
use crate::self_update::{self, InstallOpts};
44
use clap::{App, AppSettings, Arg};
5-
use rustup::dist::dist::TargetTriple;
5+
use rustup::dist::dist::{Profile, TargetTriple};
66
use std::env;
77

88
pub fn main() -> Result<()> {
@@ -48,6 +48,12 @@ pub fn main() -> Result<()> {
4848
.takes_value(true)
4949
.help("Choose a default toolchain to install"),
5050
)
51+
.arg(
52+
Arg::with_name("profile")
53+
.long("profile")
54+
.possible_values(Profile::names())
55+
.default_value(Profile::default_name()),
56+
)
5157
.arg(
5258
Arg::with_name("no-modify-path")
5359
.long("no-modify-path")
@@ -62,11 +68,15 @@ pub fn main() -> Result<()> {
6268
.map(std::borrow::ToOwned::to_owned)
6369
.unwrap_or_else(|| TargetTriple::from_host_or_build().to_string());
6470
let default_toolchain = matches.value_of("default-toolchain").unwrap_or("stable");
71+
let profile = matches
72+
.value_of("profile")
73+
.expect("Unreachable: Clap should supply a default");
6574
let no_modify_path = matches.is_present("no-modify-path");
6675

6776
let opts = InstallOpts {
6877
default_host_triple: default_host,
6978
default_toolchain: default_toolchain.to_owned(),
79+
profile: profile.to_owned(),
7080
no_modify_path,
7181
};
7282

src/config.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,36 @@ impl Cfg {
125125
Ok(())
126126
}
127127

128+
pub fn set_profile(&self, profile: &str) -> Result<()> {
129+
if !dist::Profile::names().contains(&profile) {
130+
return Err(ErrorKind::UnknownProfile(profile.to_owned()).into());
131+
}
132+
self.settings_file.with_mut(|s| {
133+
s.profile = Some(profile.to_owned());
134+
Ok(())
135+
})?;
136+
(self.notify_handler)(Notification::SetProfile(profile));
137+
Ok(())
138+
}
139+
140+
// Returns a profile, if one exists in the settings file.
141+
//
142+
// Returns `Err` if the settings file could not be read or the profile is
143+
// invalid. Returns `Ok(Some(...))` if there is a valid profile, and `Ok(None)`
144+
// if there is no profile in the settings file. The last variant happens when
145+
// a user upgrades from a version of Rustup without profiles to a version of
146+
// Rustup with profiles.
147+
pub fn get_profile(&self) -> Result<Option<dist::Profile>> {
148+
self.settings_file.with(|s| {
149+
let p = match &s.profile {
150+
Some(p) => p,
151+
None => return Ok(None),
152+
};
153+
let p = dist::Profile::from_str(p)?;
154+
Ok(Some(p))
155+
})
156+
}
157+
128158
pub fn get_toolchain(&self, name: &str, create_parent: bool) -> Result<Toolchain<'_>> {
129159
if create_parent {
130160
utils::ensure_dir_exists("toolchains", &self.toolchains_dir, &|n| {

src/dist/config.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@ pub struct Config {
1313

1414
impl Config {
1515
pub fn from_toml(mut table: toml::value::Table, path: &str) -> Result<Self> {
16-
let version = get_string(&mut table, "config_version", path)?;
17-
if !SUPPORTED_CONFIG_VERSIONS.contains(&&*version) {
18-
return Err(ErrorKind::UnsupportedVersion(version).into());
16+
let config_version = get_string(&mut table, "config_version", path)?;
17+
if !SUPPORTED_CONFIG_VERSIONS.contains(&&*config_version) {
18+
return Err(ErrorKind::UnsupportedVersion(config_version).into());
1919
}
2020

2121
let components = get_array(&mut table, "components", path)?;
2222
let components =
2323
Self::toml_to_components(components, &format!("{}{}.", path, "components"))?;
2424

2525
Ok(Self {
26-
config_version: version,
26+
config_version,
2727
components,
2828
})
2929
}
@@ -55,7 +55,7 @@ impl Config {
5555
for (i, v) in arr.into_iter().enumerate() {
5656
if let toml::Value::Table(t) = v {
5757
let path = format!("{}[{}]", path, i);
58-
result.push(Component::from_toml(t, &path)?);
58+
result.push(Component::from_toml(t, &path, false)?);
5959
}
6060
}
6161

0 commit comments

Comments
 (0)