Skip to content

Commit 1afee99

Browse files
committed
rustup check: set exit status based on available updates
This helps with interfaces above rustup, for example prompting a user to update, but only if updates are actually available. If any updates are available, exits 0, otherwise exits 1. This allows "natural" shell commands like 'if rustup check; then <update>'. It also mirrors existing exit codes for update, where rustup exits 1 if updates are not permitted by the distribution or because of errors.
1 parent c8a69f7 commit 1afee99

File tree

3 files changed

+50
-33
lines changed

3 files changed

+50
-33
lines changed

src/cli/rustup_mode.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::{
1919
common::{self, PackageUpdate, update_console_filter},
2020
errors::CLIError,
2121
help::*,
22-
self_update::{self, SelfUpdateMode, check_rustup_update},
22+
self_update::{self, RustupUpdateAvailable, SelfUpdateMode, check_rustup_update},
2323
topical_doc,
2424
},
2525
command,
@@ -790,6 +790,8 @@ async fn default_(
790790
}
791791

792792
async fn check_updates(cfg: &Cfg<'_>, opts: CheckOpts) -> Result<utils::ExitCode> {
793+
let mut update_available = false;
794+
793795
let mut t = cfg.process.stdout().terminal(cfg.process);
794796
let channels = cfg.list_channels()?;
795797

@@ -811,12 +813,14 @@ async fn check_updates(cfg: &Cfg<'_>, opts: CheckOpts) -> Result<utils::ExitCode
811813
writeln!(t.lock(), " : {cv}")?;
812814
}
813815
(Some(cv), Some(dv)) => {
816+
update_available = true;
814817
let _ = t.fg(terminalsource::Color::Yellow);
815818
write!(t.lock(), "Update available")?;
816819
let _ = t.reset();
817820
writeln!(t.lock(), " : {cv} -> {dv}")?;
818821
}
819822
(None, Some(dv)) => {
823+
update_available = true;
820824
let _ = t.fg(terminalsource::Color::Yellow);
821825
write!(t.lock(), "Update available")?;
822826
let _ = t.reset();
@@ -834,11 +838,17 @@ async fn check_updates(cfg: &Cfg<'_>, opts: CheckOpts) -> Result<utils::ExitCode
834838
&& self_update_mode == SelfUpdateMode::Enable
835839
&& !opts.no_self_update;
836840

837-
if self_update {
838-
check_rustup_update(cfg.process).await?;
841+
if self_update
842+
&& matches!(
843+
check_rustup_update(cfg.process).await?,
844+
RustupUpdateAvailable::True
845+
)
846+
{
847+
update_available = true;
839848
}
840849

841-
Ok(utils::ExitCode(0))
850+
let exit_status = if update_available { 0 } else { 1 };
851+
Ok(utils::ExitCode(exit_status))
842852
}
843853

844854
async fn update(

src/cli/self_update.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,15 @@ impl fmt::Display for SchemaVersion {
12501250
}
12511251
}
12521252

1253-
pub(crate) async fn check_rustup_update(process: &Process) -> Result<()> {
1253+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1254+
pub(crate) enum RustupUpdateAvailable {
1255+
True,
1256+
False,
1257+
}
1258+
1259+
pub(crate) async fn check_rustup_update(process: &Process) -> Result<RustupUpdateAvailable> {
1260+
let mut update_available = RustupUpdateAvailable::False;
1261+
12541262
let mut t = process.stdout().terminal(process);
12551263
// Get current rustup version
12561264
let current_version = env!("CARGO_PKG_VERSION");
@@ -1262,6 +1270,8 @@ pub(crate) async fn check_rustup_update(process: &Process) -> Result<()> {
12621270
write!(t.lock(), "rustup - ")?;
12631271

12641272
if current_version != available_version {
1273+
update_available = RustupUpdateAvailable::True;
1274+
12651275
let _ = t.fg(terminalsource::Color::Yellow);
12661276
write!(t.lock(), "Update available")?;
12671277
let _ = t.reset();
@@ -1273,7 +1283,7 @@ pub(crate) async fn check_rustup_update(process: &Process) -> Result<()> {
12731283
writeln!(t.lock(), " : {current_version}")?;
12741284
}
12751285

1276-
Ok(())
1286+
Ok(update_available)
12771287
}
12781288

12791289
#[tracing::instrument(level = "trace")]

tests/suite/cli_exact.rs

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -166,16 +166,15 @@ async fn check_updates_none() {
166166
.expect_ok(&["rustup", "toolchain", "add", "stable", "beta", "nightly"])
167167
.await;
168168
cx.config
169-
.expect_stdout_ok(
170-
&["rustup", "check"],
171-
for_host!(
172-
r"stable-{0} - Up to date : 1.1.0 (hash-stable-1.1.0)
173-
beta-{0} - Up to date : 1.2.0 (hash-beta-1.2.0)
174-
nightly-{0} - Up to date : 1.3.0 (hash-nightly-2)
175-
"
176-
),
177-
)
178-
.await;
169+
.expect(["rustup", "check"])
170+
.await
171+
.is_err()
172+
.with_stdout(snapbox::str![[r#"
173+
stable-[HOST_TRIPLE] - Up to date : 1.1.0 (hash-stable-1.1.0)
174+
beta-[HOST_TRIPLE] - Up to date : 1.2.0 (hash-beta-1.2.0)
175+
nightly-[HOST_TRIPLE] - Up to date : 1.3.0 (hash-nightly-2)
176+
177+
"#]]);
179178
}
180179

181180
#[tokio::test]
@@ -236,14 +235,13 @@ async fn check_updates_self_no_change() {
236235
.await;
237236

238237
cx.config
239-
.expect_stdout_ok(
240-
&["rustup", "check"],
241-
&format!(
242-
r"rustup - Up to date : {current_version}
238+
.expect(["rustup", "check"])
239+
.await
240+
.is_err()
241+
.with_stdout(format!(
242+
r"rustup - Up to date : {current_version}
243243
"
244-
),
245-
)
246-
.await;
244+
));
247245
}
248246

249247
#[tokio::test]
@@ -256,16 +254,15 @@ async fn check_updates_with_update() {
256254
.expect_ok(&["rustup", "toolchain", "add", "stable", "beta", "nightly"])
257255
.await;
258256
cx.config
259-
.expect_stdout_ok(
260-
&["rustup", "check"],
261-
for_host!(
262-
r"stable-{0} - Up to date : 1.0.0 (hash-stable-1.0.0)
263-
beta-{0} - Up to date : 1.1.0 (hash-beta-1.1.0)
264-
nightly-{0} - Up to date : 1.2.0 (hash-nightly-1)
265-
"
266-
),
267-
)
268-
.await;
257+
.expect(["rustup", "check"])
258+
.await
259+
.is_err()
260+
.with_stdout(snapbox::str![[r#"
261+
stable-[HOST_TRIPLE] - Up to date : 1.0.0 (hash-stable-1.0.0)
262+
beta-[HOST_TRIPLE] - Up to date : 1.1.0 (hash-beta-1.1.0)
263+
nightly-[HOST_TRIPLE] - Up to date : 1.2.0 (hash-nightly-1)
264+
265+
"#]]);
269266
}
270267

271268
let mut cx = cx.with_dist_dir(Scenario::SimpleV2);

0 commit comments

Comments
 (0)