From 42759102fc398c3299580840b162cb7c43669b7d Mon Sep 17 00:00:00 2001 From: Stephan Boyer Date: Fri, 16 May 2025 21:55:33 -0700 Subject: [PATCH] Update Rust to v1.87.0 --- .github/workflows/ci.yml | 12 +++--- Cargo.lock | 1 - Cargo.toml | 3 +- src/cache.rs | 6 +-- src/config.rs | 2 +- src/docker.rs | 4 +- src/format.rs | 4 +- src/main.rs | 13 +++--- src/runner.rs | 8 ++-- src/schedule.rs | 2 +- src/spinner.rs | 92 ++++++++++++++++++++-------------------- src/tar.rs | 6 +-- src/toastfile.rs | 18 +++++--- toast.yml | 12 +++--- 14 files changed, 93 insertions(+), 90 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6672492..af3abc6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,8 +83,8 @@ jobs: # https://github.com/rust-lang/rustup/issues/2441 # # for more information. - rustup toolchain install 1.85.0 --no-self-update # [ref:rust_1.85.0] - rustup default 1.85.0 # [ref:rust_1.85.0] + rustup toolchain install 1.87.0 --no-self-update # [ref:rust_1.87.0] + rustup default 1.87.0 # [ref:rust_1.87.0] # Add the targets. rustup target add x86_64-pc-windows-msvc @@ -124,8 +124,8 @@ jobs: set -euxo pipefail # Install the appropriate version of Rust. - rustup toolchain install 1.85.0 # [ref:rust_1.85.0] - rustup default 1.85.0 # [ref:rust_1.85.0] + rustup toolchain install 1.87.0 # [ref:rust_1.87.0] + rustup default 1.87.0 # [ref:rust_1.87.0] # Add the targets. rustup target add x86_64-apple-darwin @@ -200,8 +200,8 @@ jobs: set -euxo pipefail # Install the appropriate version of Rust. - rustup toolchain install 1.85.0 # [ref:rust_1.85.0] - rustup default 1.85.0 # [ref:rust_1.85.0] + rustup toolchain install 1.87.0 # [ref:rust_1.87.0] + rustup default 1.87.0 # [ref:rust_1.87.0] # Fetch the program version. VERSION="$(cargo pkgid | cut -d# -f2 | cut -d: -f2)" diff --git a/Cargo.lock b/Cargo.lock index d84200f..f06d4b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -647,7 +647,6 @@ dependencies = [ "env_logger", "hex", "indicatif", - "lazy_static", "log", "scopeguard", "serde", diff --git a/Cargo.toml b/Cargo.toml index 34bf9e5..669429b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "toast" version = "0.47.7" authors = ["Stephan Boyer "] -edition = "2021" +edition = "2024" description = "Containerize your development and continuous integration environments." license = "MIT" documentation = "https://github.com/stepchowfun/toast" @@ -24,7 +24,6 @@ dirs = "3" env_logger = "0.8" hex = "0.4" indicatif = "0.16" -lazy_static = "1.4" log = "0.4" scopeguard = "1" serde_yaml = "0.8" diff --git a/src/cache.rs b/src/cache.rs index e4fff1c..fd2884b 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -2,7 +2,7 @@ use { crate::{ failure, failure::Failure, - toastfile::{command, location, user, Task, Toastfile}, + toastfile::{Task, Toastfile, command, location, user}, }, sha2::{Digest, Sha256}, std::{ @@ -159,8 +159,8 @@ pub fn image_name( mod tests { use { crate::{ - cache::{combine, hash_read, image_name, CryptoHash}, - toastfile::{Task, Toastfile, DEFAULT_LOCATION, DEFAULT_USER}, + cache::{CryptoHash, combine, hash_read, image_name}, + toastfile::{DEFAULT_LOCATION, DEFAULT_USER, Task, Toastfile}, }, std::{collections::HashMap, path::Path}, typed_path::UnixPath, diff --git a/src/config.rs b/src/config.rs index 8a5935e..538886b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -62,7 +62,7 @@ pub fn parse(config: &str) -> Result { #[cfg(test)] mod tests { - use crate::config::{parse, Config, DOCKER_CLI_DEFAULT, EMPTY_CONFIG}; + use crate::config::{Config, DOCKER_CLI_DEFAULT, EMPTY_CONFIG, parse}; #[test] fn parse_empty() { diff --git a/src/docker.rs b/src/docker.rs index 53fe78a..f9be4be 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -3,15 +3,15 @@ use { std::{ collections::HashMap, env::current_dir, - fs::{copy, create_dir_all, rename, symlink_metadata, Metadata}, + fs::{Metadata, copy, create_dir_all, rename, symlink_metadata}, io, io::Read, path::Path, process::{ChildStdin, Command, Stdio}, string::ToString, sync::{ - atomic::{AtomicBool, Ordering}, Arc, + atomic::{AtomicBool, Ordering}, }, }, tempfile::tempdir, diff --git a/src/format.rs b/src/format.rs index 4cdcfab..bd5747b 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,4 +1,4 @@ -use colored::{control::SHOULD_COLORIZE, ColoredString, Colorize}; +use colored::{ColoredString, Colorize, control::SHOULD_COLORIZE}; // This trait has a function for formatting "code-like" text, such as a file path. The reason it's // implemented as a trait and not just a function is so we can use it with method syntax, as in @@ -46,7 +46,7 @@ pub fn series(items: &[String]) -> String { #[cfg(test)] mod tests { - use crate::format::{number, series, CodeStr}; + use crate::format::{CodeStr, number, series}; #[test] fn code_str_display() { diff --git a/src/main.rs b/src/main.rs index b5ea9aa..d12c736 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use { crate::{failure::Failure, format::CodeStr}, atty::Stream, clap::{App, AppSettings, Arg}, - env_logger::{fmt::Color, Builder}, + env_logger::{Builder, fmt::Color}, log::{Level, LevelFilter}, std::{ collections::{HashMap, HashSet}, @@ -22,24 +22,21 @@ use { env, env::current_dir, fs, - io::{stdout, Write}, + io::{Write, stdout}, mem::drop, path::Path, path::PathBuf, process::exit, str::FromStr, sync::{ - atomic::{AtomicBool, Ordering}, Arc, Mutex, + atomic::{AtomicBool, Ordering}, }, }, - toastfile::{default_task_mount_readonly, location, user, DEFAULT_USER}, + toastfile::{DEFAULT_USER, default_task_mount_readonly, location, user}, typed_path::UnixPath, }; -#[macro_use] -extern crate lazy_static; - #[macro_use] extern crate log; @@ -723,7 +720,7 @@ fn entry() -> Result<(), Failure> { // There was an error not caused by a regular task failure. Quit now. return result; } - }; + } // Drop the user into a shell if requested. if settings.spawn_shell { diff --git a/src/runner.rs b/src/runner.rs index eed2071..79f076c 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -3,15 +3,15 @@ use { cache, docker, failure, failure::Failure, tar, - toastfile::{command, location, user, Task, Toastfile}, + toastfile::{Task, Toastfile, command, location, user}, }, std::{ collections::{HashMap, HashSet}, io::{Seek, SeekFrom}, path::PathBuf, sync::{ - atomic::{AtomicBool, Ordering}, Arc, Mutex, + atomic::{AtomicBool, Ordering}, }, }, tempfile::tempfile, @@ -72,7 +72,7 @@ pub fn run( return ( Err(failure::system("Unable to create temporary file.")(e)), Some(context), - ) + ); } }; @@ -96,7 +96,7 @@ pub fn run( Err(failure::system("Unable to seek temporary file.")(e)), Some(context), ); - }; + } // Compute the name of the image that this task produces. let image = cache::image_name( diff --git a/src/schedule.rs b/src/schedule.rs index cb80741..785351a 100644 --- a/src/schedule.rs +++ b/src/schedule.rs @@ -81,7 +81,7 @@ mod tests { use { crate::{ schedule::compute, - toastfile::{Task, Toastfile, DEFAULT_LOCATION, DEFAULT_USER}, + toastfile::{DEFAULT_LOCATION, DEFAULT_USER, Task, Toastfile}, }, std::collections::HashMap, typed_path::UnixPath, diff --git a/src/spinner.rs b/src/spinner.rs index 468f8c8..034643f 100644 --- a/src/spinner.rs +++ b/src/spinner.rs @@ -1,12 +1,12 @@ use { atty::Stream, - crossbeam::channel::{bounded, Sender}, + crossbeam::channel::{Sender, bounded}, indicatif::{ProgressBar, ProgressStyle}, scopeguard::guard, std::{ sync::{ - atomic::{AtomicBool, Ordering}, Arc, + atomic::{AtomicBool, Ordering}, }, thread, thread::sleep, @@ -18,57 +18,59 @@ use { pub fn spin(message: &str) -> impl Drop { // Start a thread for our spinner-as-a-service. This thread will only be created once and will // live for the duration of the whole program. - lazy_static! { - static ref SPINNER_SERVICE: Sender<(String, Arc, Sender<()>)> = { - // Create a channel for requests to start spinning. - let (request_sender, request_receiver) = - bounded::<(String, Arc, Sender<()>)>(0); + #[allow(clippy::type_complexity)] + static SPINNER_SERVICE: std::sync::LazyLock, Sender<()>)>> = + std::sync::LazyLock::new(|| { + // Create a channel for requests to start spinning. + let (request_sender, request_receiver) = + bounded::<(String, Arc, Sender<()>)>(0); - // Start a thread to handle spinner requests. - thread::spawn(move || loop { - // Wait for a request. The `unwrap` is safe since we never hang up the channel. - let (message, spinning, response_sender) = - request_receiver.recv().unwrap(); + // Start a thread to handle spinner requests. + thread::spawn(move || { + loop { + // Wait for a request. The `unwrap` is safe since we never hang up the channel. + let (message, spinning, response_sender) = request_receiver.recv().unwrap(); - // If STDERR is not a TTY, the spinner will be hidden. In that case, just print - // the message to STDERR. - if !atty::is(Stream::Stderr) { - info!("{}", message); - } + // If STDERR is not a TTY, the spinner will be hidden. In that case, just print + // the message to STDERR. + if !atty::is(Stream::Stderr) { + info!("{}", message); + } - // Create the spinner! - let spinner = ProgressBar::new(1); - spinner.set_style(ProgressStyle::default_spinner()); - spinner.set_message(message.clone()); + // Create the spinner! + let spinner = ProgressBar::new(1); + spinner.set_style(ProgressStyle::default_spinner()); + spinner.set_message(message.clone()); - // Animate the spinner for as long as necessary. - let now = Instant::now(); - while spinning.load(Ordering::SeqCst) { - // Render the next frame of the spinner. - spinner.tick(); + // Animate the spinner for as long as necessary. + let now = Instant::now(); + while spinning.load(Ordering::SeqCst) { + // Render the next frame of the spinner. + spinner.tick(); - // For the first 100ms, we animate on a shorter time interval so we can stop faster if - // the work finishes instantly. If the work takes longer than that, we slow the - // animation down out of courtesy for the CPU. - if now.elapsed() < Duration::from_millis(100) { - sleep(Duration::from_millis(16)); - } else { - sleep(Duration::from_millis(100)); - } - } + // For the first 100ms, we animate on a shorter time interval so we can + // stop faster if the work finishes instantly. If the work takes longer + // than that, we slow the animation down out of courtesy for the CPU. + if now.elapsed() < Duration::from_millis(100) { + sleep(Duration::from_millis(16)); + } else { + sleep(Duration::from_millis(100)); + } + } - // Clean up the spinner. - spinner.finish_and_clear(); + // Clean up the spinner. + spinner.finish_and_clear(); - // Inform the caller that the spinner has been cleaned up. The `unwrap` is safe since we - // never hang up the channel. - response_sender.send(()).unwrap(); - }); + // Inform the caller that the spinner has been cleaned up. The `unwrap` is safe + // since we never hang up the channel. + response_sender.send(()).unwrap(); + } + }); - // The sender half of the request channel is the API for this spinner service. Return it. - request_sender - }; - } + // The sender half of the request channel is the API for this spinner service. Return + // it. + request_sender + }); // Create a channel for waiting on the spinner. let (response_sender, response_receiver) = bounded::<()>(0); diff --git a/src/tar.rs b/src/tar.rs index f8ab45c..a60a252 100644 --- a/src/tar.rs +++ b/src/tar.rs @@ -2,12 +2,12 @@ use { crate::{cache, cache::CryptoHash, failure, failure::Failure, format::CodeStr, spinner::spin}, std::{ collections::HashSet, - fs::{read_link, symlink_metadata, File, Metadata}, - io::{empty, Read, Seek, SeekFrom, Write}, + fs::{File, Metadata, read_link, symlink_metadata}, + io::{Read, Seek, SeekFrom, Write, empty}, path::Path, sync::{ - atomic::{AtomicBool, Ordering}, Arc, + atomic::{AtomicBool, Ordering}, }, }, tar::{Builder, EntryType, Header}, diff --git a/src/toastfile.rs b/src/toastfile.rs index 90a32fb..a0e1b59 100644 --- a/src/toastfile.rs +++ b/src/toastfile.rs @@ -1,6 +1,6 @@ use { crate::{failure::Failure, format, format::CodeStr}, - serde::{de::Error, Deserialize, Deserializer}, + serde::{Deserialize, Deserializer, de::Error}, std::{ collections::{HashMap, HashSet}, env, @@ -641,8 +641,8 @@ fn check_task(name: &str, task: &Task) -> Result<(), Failure> { mod tests { use { crate::toastfile::{ - check_dependencies, check_task, command, environment, location, parse, user, - MappingPath, Task, Toastfile, DEFAULT_LOCATION, DEFAULT_USER, + DEFAULT_LOCATION, DEFAULT_USER, MappingPath, Task, Toastfile, check_dependencies, + check_task, command, environment, location, parse, user, }, std::{collections::HashMap, env, path::Path}, typed_path::UnixPath, @@ -1750,7 +1750,9 @@ tasks: let mut expected = HashMap::new(); expected.insert("foo1".to_owned(), "baz".to_owned()); - env::set_var("foo1", "baz"); + unsafe { + env::set_var("foo1", "baz"); + } assert_eq!(env::var("foo1"), Ok("baz".to_owned())); assert_eq!(environment(&task), Ok(expected)); } @@ -1784,7 +1786,9 @@ tasks: let mut expected = HashMap::new(); expected.insert("foo2".to_owned(), "bar".to_owned()); - env::remove_var("foo2"); + unsafe { + env::remove_var("foo2"); + } assert!(env::var("foo2").is_err()); assert_eq!(environment(&task), Ok(expected)); } @@ -1815,7 +1819,9 @@ tasks: extra_docker_arguments: vec![], }; - env::remove_var("foo3"); + unsafe { + env::remove_var("foo3"); + } assert!(env::var("foo3").is_err()); let result = environment(&task); assert!(result.is_err()); diff --git a/toast.yml b/toast.yml index 593367c..ba7454d 100644 --- a/toast.yml +++ b/toast.yml @@ -17,11 +17,11 @@ command_prefix: | cargo-offline () { cargo --frozen --offline "$@"; } # Use this wrapper for formatting code or checking that code is formatted. We use a nightly Rust - # version for the `trailing_comma` formatting option [tag:rust_fmt_nightly_2025-02-21]. The + # version for the `trailing_comma` formatting option [tag:rust_fmt_nightly_2025-05-17]. The # nightly version was chosen as the latest available release with all components present # according to this page: # https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu.html - cargo-fmt () { cargo +nightly-2025-02-21 --frozen --offline fmt --all -- "$@"; } + cargo-fmt () { cargo +nightly-2025-05-17 --frozen --offline fmt --all -- "$@"; } # Make Bash log commands. set -x @@ -92,18 +92,18 @@ tasks: - install_packages - create_user command: | - # Install stable Rust [tag:rust_1.85.0]. + # Install stable Rust [tag:rust_1.87.0]. curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \ -y \ - --default-toolchain 1.85.0 \ + --default-toolchain 1.87.0 \ --profile minimal \ --component clippy # Add Rust tools to `$PATH`. . "$HOME/.cargo/env" - # Install nightly Rust [ref:rust_fmt_nightly_2025-02-21]. - rustup toolchain install nightly-2025-02-21 --profile minimal --component rustfmt + # Install nightly Rust [ref:rust_fmt_nightly_2025-05-17]. + rustup toolchain install nightly-2025-05-17 --profile minimal --component rustfmt install_tools: description: Install the tools needed to build and validate the program.