Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 0 additions & 64 deletions src/cli/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
use std::cell::RefCell;
use std::fmt::Display;
use std::fs;
#[cfg(not(windows))]
use std::io::ErrorKind;
use std::io::{BufRead, Write};
use std::path::{Path, PathBuf};
use std::sync::{Arc, LazyLock, Mutex};
Expand All @@ -15,7 +13,6 @@ use git_testament::{git_testament, render_testament};
use tracing::{debug, error, info, trace, warn};
use tracing_subscriber::{EnvFilter, Registry, reload::Handle};

use super::self_update;
use crate::{
cli::download_tracker::DownloadTracker,
config::Cfg,
Expand Down Expand Up @@ -303,67 +300,6 @@ pub(crate) async fn update_all_channels(
Ok(exit_code)
}

#[derive(Clone, Copy, Debug)]
pub(crate) enum SelfUpdatePermission {
HardFail,
#[cfg(not(windows))]
Skip,
Permit,
}

#[cfg(windows)]
pub(crate) fn self_update_permitted(_explicit: bool) -> Result<SelfUpdatePermission> {
Ok(SelfUpdatePermission::Permit)
}

#[cfg(not(windows))]
pub(crate) fn self_update_permitted(explicit: bool) -> Result<SelfUpdatePermission> {
// Detect if rustup is not meant to self-update
let current_exe = env::current_exe()?;
let current_exe_dir = current_exe.parent().expect("Rustup isn't in a directory‽");
if let Err(e) = tempfile::Builder::new()
.prefix("updtest")
.tempdir_in(current_exe_dir)
{
match e.kind() {
ErrorKind::PermissionDenied => {
trace!("Skipping self-update because we cannot write to the rustup dir");
if explicit {
return Ok(SelfUpdatePermission::HardFail);
} else {
return Ok(SelfUpdatePermission::Skip);
}
}
_ => return Err(e.into()),
}
}
Ok(SelfUpdatePermission::Permit)
}

/// Performs all of a self-update: check policy, download, apply and exit.
pub(crate) async fn self_update(process: &Process) -> Result<utils::ExitCode> {
match self_update_permitted(false)? {
SelfUpdatePermission::HardFail => {
error!("Unable to self-update. STOP");
return Ok(utils::ExitCode(1));
}
#[cfg(not(windows))]
SelfUpdatePermission::Skip => return Ok(utils::ExitCode(0)),
SelfUpdatePermission::Permit => {}
}

let setup_path = self_update::prepare_update(process).await?;

if let Some(setup_path) = &setup_path {
return self_update::run_update(setup_path);
} else {
// Try again in case we emitted "tool `{}` is already installed" last time.
self_update::install_proxies(process)?;
}

Ok(utils::ExitCode(0))
}

/// Print a list of items (targets or components) to stdout.
///
/// `items` represents the list of items, with the name and a boolean
Expand Down
4 changes: 2 additions & 2 deletions src/cli/rustup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -996,7 +996,7 @@ async fn update(
}
}
if self_update {
exit_code &= common::self_update(cfg.process).await?;
exit_code &= self_update::self_update(cfg.process).await?;
}
} else if ensure_active_toolchain {
let (toolchain, reason) = cfg.ensure_active_toolchain(force_non_host, true).await?;
Expand All @@ -1005,7 +1005,7 @@ async fn update(
} else {
exit_code &= common::update_all_channels(cfg, opts.force).await?;
if self_update {
exit_code &= common::self_update(cfg.process).await?;
exit_code &= self_update::self_update(cfg.process).await?;
}

info!("cleaning up downloads & tmp directories");
Expand Down
70 changes: 66 additions & 4 deletions src/cli/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@

use std::borrow::Cow;
use std::env::{self, consts::EXE_SUFFIX};
use std::fmt;
use std::fs;
#[cfg(not(windows))]
use std::io;
use std::io::Write;
use std::path::{Component, MAIN_SEPARATOR, Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use std::{fmt, fs};

use anyhow::{Context, Result, anyhow};
use cfg_if::cfg_if;
Expand Down Expand Up @@ -1071,6 +1072,67 @@ pub(crate) fn uninstall(no_prompt: bool, process: &Process) -> Result<utils::Exi
Ok(utils::ExitCode(0))
}

#[derive(Clone, Copy, Debug)]
pub(crate) enum SelfUpdatePermission {
HardFail,
#[cfg(not(windows))]
Skip,
Permit,
}

#[cfg(windows)]
pub(crate) fn self_update_permitted(_explicit: bool) -> Result<SelfUpdatePermission> {
Ok(SelfUpdatePermission::Permit)
}

#[cfg(not(windows))]
pub(crate) fn self_update_permitted(explicit: bool) -> Result<SelfUpdatePermission> {
// Detect if rustup is not meant to self-update
let current_exe = env::current_exe()?;
let current_exe_dir = current_exe.parent().expect("Rustup isn't in a directory‽");
if let Err(e) = tempfile::Builder::new()
.prefix("updtest")
.tempdir_in(current_exe_dir)
{
match e.kind() {
io::ErrorKind::PermissionDenied => {
trace!("Skipping self-update because we cannot write to the rustup dir");
if explicit {
return Ok(SelfUpdatePermission::HardFail);
} else {
return Ok(SelfUpdatePermission::Skip);
}
}
_ => return Err(e.into()),
}
}
Ok(SelfUpdatePermission::Permit)
}

/// Performs all of a self-update: check policy, download, apply and exit.
pub(crate) async fn self_update(process: &Process) -> Result<utils::ExitCode> {
match self_update_permitted(false)? {
SelfUpdatePermission::HardFail => {
error!("Unable to self-update. STOP");
return Ok(utils::ExitCode(1));
}
#[cfg(not(windows))]
SelfUpdatePermission::Skip => return Ok(utils::ExitCode(0)),
SelfUpdatePermission::Permit => {}
}

let setup_path = prepare_update(process).await?;

if let Some(setup_path) = &setup_path {
return run_update(setup_path);
} else {
// Try again in case we emitted "tool `{}` is already installed" last time.
install_proxies(process)?;
}

Ok(utils::ExitCode(0))
}

/// Self update downloads rustup-init to `CARGO_HOME`/bin/rustup-init
/// and runs it.
///
Expand All @@ -1089,11 +1151,11 @@ pub(crate) fn uninstall(no_prompt: bool, process: &Process) -> Result<utils::Exi
pub(crate) async fn update(cfg: &Cfg<'_>) -> Result<utils::ExitCode> {
common::warn_if_host_is_emulated(cfg.process);

use common::SelfUpdatePermission::*;
use SelfUpdatePermission::*;
let update_permitted = if cfg!(feature = "no-self-update") {
HardFail
} else {
common::self_update_permitted(true)?
self_update_permitted(true)?
};
match update_permitted {
HardFail => {
Expand Down
Loading