Skip to content

Commit

Permalink
Support for machine wide installs: fallback-settings file
Browse files Browse the repository at this point in the history
This provides a way for snaps, distro packages and other such installs
to set the default-toolchain for users that have not gone through the
rustup-init one-time set of questions.

/etc/rustup/settings.toml can more now just provide a default toolchain
for users of rustup on the machine. More keys will be supported as
needed. No equivalent file is defined for Windows OS machines at this
time.
  • Loading branch information
rbtcollins committed Mar 5, 2020
1 parent 6de2f76 commit f6315b4
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 4 deletions.
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ remove_dir_all = "0.5.1"
same-file = "1"
scopeguard = "1"
semver = "0.9"
serde = { version = "1.0", features = ["derive"] }
sha2 = "0.8"
strsim = "0.9.1"
tar = "0.4.26"
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ And it runs on all platforms Rust supports, including Windows.
* [Working with custom toolchains](#working-with-custom-toolchains-and-local-builds)
* [Working with network proxies](#working-with-network-proxies)
* [Examples](#examples)
* [Configuration files](#configuration-files)
* [Environment variables](#environment-variables)
* [Other installation methods](#other-installation-methods)
* [Security](#security)
Expand Down Expand Up @@ -639,6 +640,17 @@ Command | Description
`rustup toolchain help` | Show the `help` page for a subcommand (like `toolchain`)
`rustup man cargo` | \(*Unix only*\) View the man page for a given command (like `cargo`)

## Configuration files

Rustup has a settings file in [TOML](https://github.com/toml-lang/toml) format
at `${RUSTUP_HOME}/settings.toml`. The schema for this file is not part of the
public interface for rustup - the rustup CLI should be used to query and set
settings.

On Unix operating systems a fallback settings file is consulted for some
settings. This fallback file is located at `/etc/rustup/settings.toml` and
currently can define only `default_toolchain`.

## Environment variables


Expand Down
25 changes: 21 additions & 4 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use pgp::{Deserializable, SignedPublicKey};

use crate::dist::{dist, temp};
use crate::errors::*;
use crate::fallback_settings::FallbackSettings;
use crate::notifications::*;
use crate::settings::{Settings, SettingsFile, DEFAULT_METADATA_VERSION};
use crate::toolchain::{Toolchain, UpdateStatus};
Expand Down Expand Up @@ -108,10 +109,13 @@ impl Display for PgpPublicKey {
}
}

pub const UNIX_FALLBACK_SETTINGS: &str = "/etc/rustup/settings.toml";

pub struct Cfg {
pub profile_override: Option<dist::Profile>,
pub rustup_dir: PathBuf,
pub settings_file: SettingsFile,
pub fallback_settings: Option<FallbackSettings>,
pub toolchains_dir: PathBuf,
pub update_hash_dir: PathBuf,
pub download_dir: PathBuf,
Expand All @@ -133,6 +137,13 @@ impl Cfg {

let settings_file = SettingsFile::new(rustup_dir.join("settings.toml"));

// Centralised file for multi-user systems to provide admin/distributor set initial values.
let fallback_settings = if cfg!(not(windows)) {
FallbackSettings::new(PathBuf::from(UNIX_FALLBACK_SETTINGS))?
} else {
None
};

let toolchains_dir = rustup_dir.join("toolchains");
let update_hash_dir = rustup_dir.join("update-hashes");
let download_dir = rustup_dir.join("downloads");
Expand Down Expand Up @@ -191,6 +202,7 @@ impl Cfg {
profile_override: None,
rustup_dir,
settings_file,
fallback_settings,
toolchains_dir,
update_hash_dir,
download_dir,
Expand Down Expand Up @@ -365,9 +377,7 @@ impl Cfg {
}

pub fn find_default(&self) -> Result<Option<Toolchain<'_>>> {
let opt_name = self
.settings_file
.with(|s| Ok(s.default_toolchain.clone()))?;
let opt_name = self.get_default()?;

if let Some(name) = opt_name {
let toolchain = self
Expand Down Expand Up @@ -509,7 +519,14 @@ impl Cfg {
}

pub fn get_default(&self) -> Result<Option<String>> {
self.settings_file.with(|s| Ok(s.default_toolchain.clone()))
let user_opt = self.settings_file.with(|s| Ok(s.default_toolchain.clone()));
if let Some(fallback_settings) = &self.fallback_settings {
match user_opt {
Err(_) | Ok(None) => return Ok(fallback_settings.default_toolchain.clone()),
_ => {}
};
};
user_opt
}

pub fn list_toolchains(&self) -> Result<Vec<String>> {
Expand Down
3 changes: 3 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,9 @@ error_chain! {
display("component {} was automatically added because it is required for toolchain '{}'",
c, t)
}
ParsingFallbackSettings(e: toml::de::Error) {
description("error parsing settings")
}
ParsingSettings(e: toml::de::Error) {
description("error parsing settings")
}
Expand Down
41 changes: 41 additions & 0 deletions src/fallback_settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::errors::*;
use crate::utils::utils;
use serde::Deserialize;
use std::error::Error;
use std::io;
use std::path::Path;

#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct FallbackSettings {
pub default_toolchain: Option<String>,
}

impl Default for FallbackSettings {
fn default() -> Self {
Self {
default_toolchain: None,
}
}
}

impl FallbackSettings {
pub fn new<P: AsRef<Path>>(path: P) -> Result<Option<Self>> {
// Users cannot fix issues with missing/unreadable/invalid centralised files, but logging isn't setup early so
// we can't simply trap all errors and log diagnostics. Ideally we would, and then separate these into different
// sorts of issues, logging messages about errors that should be fixed. Instead we trap some conservative errors
// that hopefully won't lead to too many tickets.
match utils::read_file("fallback settings", path.as_ref()) {
Err(e @ Error(ErrorKind::ReadingFile { .. }, _)) => {
let io_err = e.source().unwrap().downcast_ref::<io::Error>().unwrap();
match io_err.kind() {
io::ErrorKind::NotFound | io::ErrorKind::PermissionDenied => Ok(None),
_ => Err(e.into()),
}
}
Err(e) => Err(e),
Ok(file_contents) => Ok(Some(
toml::from_str(&file_contents).map_err(ErrorKind::ParsingFallbackSettings)?,
)),
}
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub mod diskio;
pub mod dist;
pub mod env_var;
pub mod errors;
pub mod fallback_settings;
mod install;
mod notifications;
pub mod settings;
Expand Down

0 comments on commit f6315b4

Please sign in to comment.