Skip to content
Open
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
4 changes: 2 additions & 2 deletions src/cli/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ fn show_channel_updates(
Ok((pkg, banner, width, color, version, previous_version))
});

let mut t = cfg.process.stdout().terminal(cfg.process);
let mut t = cfg.process.stdout();

let data: Vec<_> = data.collect::<Result<_>>()?;
let max_width = data
Expand Down Expand Up @@ -307,7 +307,7 @@ pub(super) fn list_items(
quiet: bool,
process: &Process,
) -> Result<utils::ExitCode> {
let mut t = process.stdout().terminal(process);
let mut t = process.stdout();
for (name, installed) in items {
if installed && !installed_only && !quiet {
t.attr(terminalsource::Attr::Bold)?;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ where
Ok(s) if s.eq_ignore_ascii_case("never") => false,
// `RUSTUP_TERM_COLOR` is prioritized over `NO_COLOR`.
_ if process.var("NO_COLOR").is_ok() => false,
_ => process.stderr().is_a_tty(process),
_ => process.stderr().is_a_tty(),
};
let maybe_rustup_log_directives = process.var("RUSTUP_LOG");
let process = process.clone();
Expand Down
12 changes: 6 additions & 6 deletions src/cli/rustup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ async fn default_(
}

async fn check_updates(cfg: &Cfg<'_>, opts: CheckOpts) -> Result<utils::ExitCode> {
let t = cfg.process.stdout().terminal(cfg.process);
let t = cfg.process.stdout();
let use_colors = matches!(t.color_choice(), ColorChoice::Auto | ColorChoice::Always);
let mut update_available = false;
let channels = cfg.list_channels()?;
Expand Down Expand Up @@ -890,7 +890,7 @@ async fn check_updates(cfg: &Cfg<'_>, opts: CheckOpts) -> Result<utils::ExitCode
.await
};

let t = cfg.process.stdout().terminal(cfg.process);
let t = cfg.process.stdout();
for result in channels {
let (update_a, message) = result?;
if update_a {
Expand Down Expand Up @@ -1072,7 +1072,7 @@ async fn show(cfg: &Cfg<'_>, verbose: bool) -> Result<utils::ExitCode> {

// Print host triple
{
let mut t = cfg.process.stdout().terminal(cfg.process);
let mut t = cfg.process.stdout();
t.attr(terminalsource::Attr::Bold)?;
write!(t.lock(), "Default host: ")?;
t.reset()?;
Expand All @@ -1081,7 +1081,7 @@ async fn show(cfg: &Cfg<'_>, verbose: bool) -> Result<utils::ExitCode> {

// Print rustup home directory
{
let mut t = cfg.process.stdout().terminal(cfg.process);
let mut t = cfg.process.stdout();
t.attr(terminalsource::Attr::Bold)?;
write!(t.lock(), "rustup home: ")?;
t.reset()?;
Expand Down Expand Up @@ -1121,7 +1121,7 @@ async fn show(cfg: &Cfg<'_>, verbose: bool) -> Result<utils::ExitCode> {

// show installed toolchains
{
let mut t = cfg.process.stdout().terminal(cfg.process);
let mut t = cfg.process.stdout();

print_header::<Error>(&mut t, "installed toolchains")?;

Expand Down Expand Up @@ -1157,7 +1157,7 @@ async fn show(cfg: &Cfg<'_>, verbose: bool) -> Result<utils::ExitCode> {

// show active toolchain
{
let mut t = cfg.process.stdout().terminal(cfg.process);
let mut t = cfg.process.stdout();

writeln!(t.lock())?;

Expand Down
6 changes: 3 additions & 3 deletions src/cli/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ pub(crate) async fn install(
exit_code &= unix::do_anti_sudo_check(no_prompt, process)?;
}

let mut term = process.stdout().terminal(process);
let mut term = process.stdout();

#[cfg(windows)]
windows::maybe_install_msvc(&mut term, no_prompt, quiet, &opts, process).await?;
Expand Down Expand Up @@ -991,7 +991,7 @@ pub(crate) fn uninstall(no_prompt: bool, process: &Process) -> Result<utils::Exi
pre_uninstall_msg!(),
cargo_home = canonical_cargo_home(process)?
);
md(&mut process.stdout().terminal(process), msg);
md(&mut process.stdout(), msg);
if !common::confirm("\nContinue? (y/N)", false, process)? {
info!("aborting uninstallation");
return Ok(utils::ExitCode(0));
Expand Down Expand Up @@ -1347,7 +1347,7 @@ impl fmt::Display for SchemaVersion {

/// Returns whether an update was available
pub(crate) async fn check_rustup_update(process: &Process) -> anyhow::Result<bool> {
let mut t = process.stdout().terminal(process);
let mut t = process.stdout();
// Get current rustup version
let current_version = env!("CARGO_PKG_VERSION");

Expand Down
1 change: 1 addition & 0 deletions src/cli/setup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub async fn main(
} = match RustupInit::try_parse() {
Ok(args) => args,
Err(e) if [ErrorKind::DisplayHelp, ErrorKind::DisplayVersion].contains(&e.kind()) => {
use std::io::Write as _;
write!(process.stdout().lock(), "{e}")?;
return Ok(utils::ExitCode(0));
}
Expand Down
1 change: 1 addition & 0 deletions src/dist/component/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ fn unpack_without_first_dir<R: Read>(
None => {
// Tar has item before containing directory
// Complain about this so we can see if these exist.
use std::io::Write as _;
writeln!(
cx.process.stderr().lock(),
"Unexpected: missing parent '{}' for '{}'",
Expand Down
20 changes: 13 additions & 7 deletions src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,25 @@ impl Process {
}
}

pub(crate) fn stdout(&self) -> Box<dyn filesource::Writer> {
pub(crate) fn stdout(&self) -> terminalsource::ColorableTerminal {
match self {
Process::OsProcess(_) => Box::new(io::stdout()),
Process::OsProcess(_) => terminalsource::ColorableTerminal::stdout(self),
#[cfg(feature = "test")]
Process::TestProcess(p) => Box::new(filesource::TestWriter(p.stdout.clone())),
Process::TestProcess(p) => terminalsource::ColorableTerminal::test(
filesource::TestWriter(p.stdout.clone()),
self,
),
}
}

pub(crate) fn stderr(&self) -> Box<dyn filesource::Writer> {
pub(crate) fn stderr(&self) -> terminalsource::ColorableTerminal {
match self {
Process::OsProcess(_) => Box::new(io::stderr()),
Process::OsProcess(_) => terminalsource::ColorableTerminal::stderr(self),
#[cfg(feature = "test")]
Process::TestProcess(p) => Box::new(filesource::TestWriter(p.stderr.clone())),
Process::TestProcess(p) => terminalsource::ColorableTerminal::test(
filesource::TestWriter(p.stderr.clone()),
self,
),
}
}

Expand All @@ -178,7 +184,7 @@ impl Process {
#[cfg(feature = "test")]
Process::TestProcess(_) => return ProgressDrawTarget::hidden(),
}
let t = self.stdout().terminal(self);
let t = self.stdout();
match self.var("RUSTUP_TERM_PROGRESS_WHEN") {
Ok(s) if s.eq_ignore_ascii_case("always") => ProgressDrawTarget::term_like(Box::new(t)),
Ok(s) if s.eq_ignore_ascii_case("never") => ProgressDrawTarget::hidden(),
Expand Down
85 changes: 2 additions & 83 deletions src/process/filesource.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use std::io::{self, BufRead, Read, Write};

use super::terminalsource::{ColorableTerminal, StreamSelector};
use crate::process::Process;
use std::io::{self, BufRead, Read};

/// Stand-in for std::io::Stdin
pub trait Stdin {
Expand All @@ -21,75 +18,13 @@ impl Stdin for io::Stdin {
}
}

// -------------- stdout -------------------------------

/// This is a stand-in for [`std::io::StdoutLock`] and [`std::io::StderrLock`].
pub trait WriterLock: Write {}

/// This is a stand-in for [`std::io::Stdout`] or [`std::io::Stderr`].
/// TODO: remove Sync.
pub trait Writer: Write + Send + Sync {
/// This is a stand-in for [`std::io::Stdout::lock`] or [`std::io::Stderr::lock`].
fn lock(&self) -> Box<dyn WriterLock + '_>;

/// Query whether a TTY is present. Used in download_tracker - we may want
/// to remove this entirely with a better progress bar system (in favour of
/// filtering in the Terminal layer?)
fn is_a_tty(&self, process: &Process) -> bool;

/// Construct a terminal on this writer.
fn terminal(&self, process: &Process) -> ColorableTerminal;
}

// ----------------- OS support for writers -----------------

impl WriterLock for io::StdoutLock<'_> {}

impl Writer for io::Stdout {
fn is_a_tty(&self, process: &Process) -> bool {
match process {
crate::process::Process::OsProcess(p) => p.stdout_is_a_tty,
#[cfg(feature = "test")]
crate::process::Process::TestProcess(_) => unreachable!(),
}
}

fn lock(&self) -> Box<dyn WriterLock + '_> {
Box::new(io::Stdout::lock(self))
}

fn terminal(&self, process: &Process) -> ColorableTerminal {
ColorableTerminal::new(StreamSelector::Stdout, process)
}
}

impl WriterLock for io::StderrLock<'_> {}

impl Writer for io::Stderr {
fn is_a_tty(&self, process: &Process) -> bool {
match process {
crate::process::Process::OsProcess(p) => p.stderr_is_a_tty,
#[cfg(feature = "test")]
crate::process::Process::TestProcess(_) => unreachable!(),
}
}

fn lock(&self) -> Box<dyn WriterLock + '_> {
Box::new(io::Stderr::lock(self))
}

fn terminal(&self, process: &Process) -> ColorableTerminal {
ColorableTerminal::new(StreamSelector::Stderr, process)
}
}

#[cfg(feature = "test")]
pub(crate) use self::test_support::*;

#[cfg(feature = "test")]
mod test_support {
use std::{
io::Cursor,
io::{Cursor, Write},
sync::{Arc, Mutex, MutexGuard},
};

Expand Down Expand Up @@ -136,8 +71,6 @@ mod test_support {
inner: MutexGuard<'a, Vec<u8>>,
}

impl WriterLock for TestWriterLock<'_> {}

impl Write for TestWriterLock<'_> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.write(buf)
Expand All @@ -164,20 +97,6 @@ mod test_support {
}
}

impl Writer for TestWriter {
fn is_a_tty(&self, _: &Process) -> bool {
false
}

fn lock(&self) -> Box<dyn WriterLock + '_> {
Box::new(self.lock())
}

fn terminal(&self, process: &Process) -> ColorableTerminal {
ColorableTerminal::new(StreamSelector::TestWriter(self.clone()), process)
}
}

impl Write for TestWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.lock().write(buf)
Expand Down
15 changes: 14 additions & 1 deletion src/process/terminalsource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,25 @@ impl TerminalInnerLocked {
}

impl ColorableTerminal {
pub(super) fn stdout(process: &Process) -> Self {
Self::new(StreamSelector::Stdout, process)
}

pub(super) fn stderr(process: &Process) -> Self {
Self::new(StreamSelector::Stderr, process)
}

#[cfg(feature = "test")]
pub(super) fn test(writer: TestWriter, process: &Process) -> Self {
Self::new(StreamSelector::TestWriter(writer), process)
}

/// A terminal that supports colorisation of a stream.
/// If `RUSTUP_TERM_COLOR` is set to `always`, or if the stream is a tty and
/// `RUSTUP_TERM_COLOR` either unset or set to `auto`,
/// then color commands will be sent to the stream.
/// Otherwise color commands are discarded.
pub(super) fn new(stream: StreamSelector, process: &Process) -> Self {
fn new(stream: StreamSelector, process: &Process) -> Self {
let is_a_tty = stream.is_a_tty(process);
let choice = match process.var("RUSTUP_TERM_COLOR") {
Ok(s) if s.eq_ignore_ascii_case("always") => ColorChoice::Always,
Expand Down
Loading