Skip to content

Commit

Permalink
Installation profiles (rust-lang#1673)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
nrc authored Sep 11, 2019
1 parent 039a0a8 commit ec6d1af
Show file tree
Hide file tree
Showing 30 changed files with 1,348 additions and 567 deletions.
1 change: 1 addition & 0 deletions rustup-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ OPTIONS:
--default-host <default-host> Choose a default host triple
--default-toolchain <default-toolchain> Choose a default toolchain to install
--default-toolchain none Do not install any toolchains
--profile [minimal|default|complete] Choose a profile
EOF
}

Expand Down
12 changes: 2 additions & 10 deletions src/cli/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,11 +368,7 @@ pub fn list_targets(toolchain: &Toolchain<'_>) -> Result<()> {
.target
.as_ref()
.expect("rust-std should have a target");
if component.required {
let _ = t.attr(term2::Attr::Bold);
let _ = writeln!(t, "{} (default)", target);
let _ = t.reset();
} else if component.installed {
if component.installed {
let _ = t.attr(term2::Attr::Bold);
let _ = writeln!(t, "{} (installed)", target);
let _ = t.reset();
Expand Down Expand Up @@ -406,11 +402,7 @@ pub fn list_components(toolchain: &Toolchain<'_>) -> Result<()> {
let mut t = term2::stdout();
for component in toolchain.list_components()? {
let name = component.name;
if component.required {
t.attr(term2::Attr::Bold)?;
writeln!(t, "{} (default)", name)?;
t.reset()?;
} else if component.installed {
if component.installed {
t.attr(term2::Attr::Bold)?;
writeln!(t, "{} (installed)", name)?;
t.reset()?;
Expand Down
1 change: 0 additions & 1 deletion src/cli/download_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ impl<'a> fmt::Display for Size<'a> {

#[cfg(test)]
mod tests {

#[test]
fn download_tracker_from_seconds_test() {
use crate::download_tracker::DownloadTracker;
Expand Down
46 changes: 40 additions & 6 deletions src/cli/rustup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::self_update;
use crate::term2;
use crate::term2::Terminal;
use clap::{App, AppSettings, Arg, ArgGroup, ArgMatches, Shell, SubCommand};
use rustup::dist::dist::{PartialTargetTriple, PartialToolchainDesc, TargetTriple};
use rustup::dist::dist::{PartialTargetTriple, PartialToolchainDesc, Profile, TargetTriple};
use rustup::dist::manifest::Component;
use rustup::utils::utils::{self, ExitCode};
use rustup::{command, Cfg, Toolchain};
Expand Down Expand Up @@ -44,6 +44,7 @@ pub fn main() -> Result<()> {
("show", Some(c)) => match c.subcommand() {
("active-toolchain", Some(_)) => handle_epipe(show_active_toolchain(cfg))?,
("home", Some(_)) => handle_epipe(show_rustup_home(cfg))?,
("profile", Some(_)) => handle_epipe(show_profile(cfg))?,
(_, _) => handle_epipe(show(cfg))?,
},
("install", Some(m)) => update(cfg, m)?,
Expand Down Expand Up @@ -86,6 +87,7 @@ pub fn main() -> Result<()> {
},
("set", Some(c)) => match c.subcommand() {
("default-host", Some(m)) => set_default_host_triple(&cfg, m)?,
("profile", Some(m)) => set_profile(&cfg, m)?,
(_, _) => unreachable!(),
},
("completions", Some(c)) => {
Expand Down Expand Up @@ -125,7 +127,7 @@ pub fn cli() -> App<'static, 'static> {
)
.subcommand(
SubCommand::with_name("show")
.about("Show the active and installed toolchains")
.about("Show the active and installed toolchains or profiles")
.after_help(SHOW_HELP)
.setting(AppSettings::VersionlessSubcommands)
.setting(AppSettings::DeriveDisplayOrder)
Expand All @@ -138,6 +140,7 @@ pub fn cli() -> App<'static, 'static> {
SubCommand::with_name("home")
.about("Display the computed value of RUSTUP_HOME"),
)
.subcommand(SubCommand::with_name("profile").about("Show the current profile")),
)
.subcommand(
SubCommand::with_name("install")
Expand Down Expand Up @@ -501,6 +504,16 @@ pub fn cli() -> App<'static, 'static> {
SubCommand::with_name("default-host")
.about("The triple used to identify toolchains when not specified")
.arg(Arg::with_name("host_triple").required(true)),
)
.subcommand(
SubCommand::with_name("profile")
.about("The default components installed")
.arg(
Arg::with_name("profile-name")
.required(true)
.possible_values(Profile::names())
.default_value(Profile::default_name()),
),
),
);

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

for target in &targets {
let new_component = Component::new("rust-std".to_string(), Some(TargetTriple::new(target)));
let new_component = Component::new(
"rust-std".to_string(),
Some(TargetTriple::new(target)),
false,
);
toolchain.add_component(new_component)?;
}

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

for target in m.values_of("target").expect("") {
let new_component = Component::new("rust-std".to_string(), Some(TargetTriple::new(target)));
let new_component = Component::new(
"rust-std".to_string(),
Some(TargetTriple::new(target)),
false,
);

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

for component in m.values_of("component").expect("") {
let new_component = Component::new(component.to_string(), target.clone());
let new_component = Component::new(component.to_string(), target.clone(), true);

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

for component in m.values_of("component").expect("") {
let new_component = Component::new(component.to_string(), target.clone());
let new_component = Component::new(component.to_string(), target.clone(), true);

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

fn set_profile(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
cfg.set_profile(&m.value_of("profile-name").unwrap())?;
Ok(())
}

fn show_profile(cfg: &Cfg) -> Result<()> {
match cfg.get_profile()? {
Some(p) => println!("{}", p),
None => println!("No profile set"),
}
Ok(())
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum CompletionCommand {
Rustup,
Expand Down
34 changes: 29 additions & 5 deletions src/cli/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::common::{self, Confirm};
use crate::errors::*;
use crate::markdown::md;
use crate::term2;
use rustup::dist::dist;
use rustup::dist::dist::{self, Profile};
use rustup::utils::utils;
use rustup::utils::Notification;
use rustup::{DUP_TOOLS, TOOLS};
Expand All @@ -48,6 +48,7 @@ use std::process::{self, Command};
pub struct InstallOpts {
pub default_host_triple: String,
pub default_toolchain: String,
pub profile: String,
pub no_modify_path: bool,
}

Expand Down Expand Up @@ -278,7 +279,12 @@ pub fn install(no_prompt: bool, verbose: bool, mut opts: InstallOpts) -> Result<
do_add_to_path(&get_add_path_methods())?;
}
utils::create_rustup_home()?;
maybe_install_rust(&opts.default_toolchain, &opts.default_host_triple, verbose)?;
maybe_install_rust(
&opts.default_toolchain,
&opts.profile,
&opts.default_host_triple,
verbose,
)?;

if cfg!(unix) {
let env_file = utils::cargo_home()?.join("env");
Expand Down Expand Up @@ -590,10 +596,12 @@ fn current_install_opts(opts: &InstallOpts) -> String {
- ` `default host triple: `{}`
- ` `default toolchain: `{}`
- ` `profile: `{}`
- modify PATH variable: `{}`
",
opts.default_host_triple,
opts.default_toolchain,
opts.profile,
if !opts.no_modify_path { "yes" } else { "no" }
)
}
Expand All @@ -615,6 +623,14 @@ fn customize_install(mut opts: InstallOpts) -> Result<InstallOpts> {
&opts.default_toolchain,
)?;

opts.profile = common::question_str(
&format!(
"Profile (which tools and data to install)? ({})",
Profile::names().join("/")
),
&opts.profile,
)?;

opts.no_modify_path =
!common::question_bool("Modify PATH variable? (y/n)", !opts.no_modify_path)?;

Expand Down Expand Up @@ -716,8 +732,14 @@ pub fn install_proxies() -> Result<()> {
Ok(())
}

fn maybe_install_rust(toolchain_str: &str, default_host_triple: &str, verbose: bool) -> Result<()> {
fn maybe_install_rust(
toolchain_str: &str,
profile_str: &str,
default_host_triple: &str,
verbose: bool,
) -> Result<()> {
let cfg = common::set_globals(verbose)?;
cfg.set_profile(profile_str)?;

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

// First everything except the bin directory
for dirent in fs::read_dir(&cargo_home).chain_err(|| read_dir_err)? {
let diriter = fs::read_dir(&cargo_home).chain_err(|| read_dir_err)?;
for dirent in diriter {
let dirent = dirent.chain_err(|| read_dir_err)?;
if dirent.file_name().to_str() != Some("bin") {
if dirent.path().is_dir() {
Expand All @@ -805,7 +828,8 @@ pub fn uninstall(no_prompt: bool) -> Result<()> {
.chain(DUP_TOOLS.iter())
.map(|t| format!("{}{}", t, EXE_SUFFIX));
let tools: Vec<_> = tools.chain(vec![format!("rustup{}", EXE_SUFFIX)]).collect();
for dirent in fs::read_dir(&cargo_home.join("bin")).chain_err(|| read_dir_err)? {
let diriter = fs::read_dir(&cargo_home.join("bin")).chain_err(|| read_dir_err)?;
for dirent in diriter {
let dirent = dirent.chain_err(|| read_dir_err)?;
let name = dirent.file_name();
let file_is_tool = name.to_str().map(|n| tools.iter().any(|t| *t == n));
Expand Down
12 changes: 11 additions & 1 deletion src/cli/setup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::common;
use crate::errors::*;
use crate::self_update::{self, InstallOpts};
use clap::{App, AppSettings, Arg};
use rustup::dist::dist::TargetTriple;
use rustup::dist::dist::{Profile, TargetTriple};
use std::env;

pub fn main() -> Result<()> {
Expand Down Expand Up @@ -48,6 +48,12 @@ pub fn main() -> Result<()> {
.takes_value(true)
.help("Choose a default toolchain to install"),
)
.arg(
Arg::with_name("profile")
.long("profile")
.possible_values(Profile::names())
.default_value(Profile::default_name()),
)
.arg(
Arg::with_name("no-modify-path")
.long("no-modify-path")
Expand All @@ -62,11 +68,15 @@ pub fn main() -> Result<()> {
.map(std::borrow::ToOwned::to_owned)
.unwrap_or_else(|| TargetTriple::from_host_or_build().to_string());
let default_toolchain = matches.value_of("default-toolchain").unwrap_or("stable");
let profile = matches
.value_of("profile")
.expect("Unreachable: Clap should supply a default");
let no_modify_path = matches.is_present("no-modify-path");

let opts = InstallOpts {
default_host_triple: default_host,
default_toolchain: default_toolchain.to_owned(),
profile: profile.to_owned(),
no_modify_path,
};

Expand Down
30 changes: 30 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,36 @@ impl Cfg {
Ok(())
}

pub fn set_profile(&self, profile: &str) -> Result<()> {
if !dist::Profile::names().contains(&profile) {
return Err(ErrorKind::UnknownProfile(profile.to_owned()).into());
}
self.settings_file.with_mut(|s| {
s.profile = Some(profile.to_owned());
Ok(())
})?;
(self.notify_handler)(Notification::SetProfile(profile));
Ok(())
}

// Returns a profile, if one exists in the settings file.
//
// Returns `Err` if the settings file could not be read or the profile is
// invalid. Returns `Ok(Some(...))` if there is a valid profile, and `Ok(None)`
// if there is no profile in the settings file. The last variant happens when
// a user upgrades from a version of Rustup without profiles to a version of
// Rustup with profiles.
pub fn get_profile(&self) -> Result<Option<dist::Profile>> {
self.settings_file.with(|s| {
let p = match &s.profile {
Some(p) => p,
None => return Ok(None),
};
let p = dist::Profile::from_str(p)?;
Ok(Some(p))
})
}

pub fn get_toolchain(&self, name: &str, create_parent: bool) -> Result<Toolchain<'_>> {
if create_parent {
utils::ensure_dir_exists("toolchains", &self.toolchains_dir, &|n| {
Expand Down
10 changes: 5 additions & 5 deletions src/dist/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ pub struct Config {

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

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

Ok(Self {
config_version: version,
config_version,
components,
})
}
Expand Down Expand Up @@ -55,7 +55,7 @@ impl Config {
for (i, v) in arr.into_iter().enumerate() {
if let toml::Value::Table(t) = v {
let path = format!("{}[{}]", path, i);
result.push(Component::from_toml(t, &path)?);
result.push(Component::from_toml(t, &path, false)?);
}
}

Expand Down
Loading

0 comments on commit ec6d1af

Please sign in to comment.