refactor: bump msrv to remove once-cell, improve logger test & handle clippy warnings (#6315)

* refactor: replace `once_cell`-crate with stdlib

* test(logger): make log cleanup-test cross-platform

* chore: handle clippy warnings

* build(deps): update dependency dprint/dprint-plugin-toml to v0.6.3

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
David Knaack 2024-10-17 16:03:22 +02:00 committed by GitHub
parent 22c6c5201d
commit a5631a17dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 97 additions and 94 deletions

View File

@ -28,6 +28,6 @@
"https://github.com/dprint/dprint-plugin-typescript/releases/download/0.93.0/plugin.wasm",
"https://github.com/dprint/dprint-plugin-json/releases/download/0.19.3/plugin.wasm",
"https://github.com/dprint/dprint-plugin-markdown/releases/download/0.17.8/plugin.wasm",
"https://github.com/dprint/dprint-plugin-toml/releases/download/0.6.2/plugin.wasm"
"https://github.com/dprint/dprint-plugin-toml/releases/download/0.6.3/plugin.wasm"
]
}

1
Cargo.lock generated
View File

@ -2762,7 +2762,6 @@ dependencies = [
"nix",
"notify-rust",
"nu-ansi-term",
"once_cell",
"open",
"os_info",
"path-slash",

View File

@ -23,7 +23,7 @@ license = "ISC"
readme = "README.md"
repository = "https://github.com/starship/starship"
# Note: MSRV is only intended as a hint, and only the latest version is officially supported in starship.
rust-version = "1.76"
rust-version = "1.80"
description = """
The minimal, blazing-fast, and infinitely customizable prompt for any shell! 🌌
"""
@ -56,7 +56,6 @@ log = { version = "0.4.22", features = ["std"] }
# see: https://github.com/NixOS/nixpkgs/issues/160876
notify-rust = { version = "4.11.3", optional = true }
nu-ansi-term = "0.50.1"
once_cell = "1.20.2"
open = "5.3.0"
# update os module config and tests when upgrading os_info
os_info = "3.8.2"

View File

@ -4,8 +4,6 @@ version = 2
# A list of advisory IDs to ignore. Note that ignored advisories will still
# output a note when they are encountered.
ignore = [
# { id = "RUSTSEC-0000-0000", reason = "" },
]

View File

@ -12,7 +12,6 @@ use gix::{
sec::{self as git_sec, trust::DefaultForLevel},
state as git_state, Repository, ThreadSafeRepository,
};
use once_cell::sync::OnceCell;
#[cfg(test)]
use std::collections::HashMap;
use std::collections::HashSet;
@ -25,6 +24,7 @@ use std::num::ParseIntError;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::string::String;
use std::sync::OnceLock;
use std::time::{Duration, Instant};
use terminal_size::terminal_size;
@ -44,13 +44,13 @@ pub struct Context<'a> {
pub logical_dir: PathBuf,
/// A struct containing directory contents in a lookup-optimized format.
dir_contents: OnceCell<DirContents>,
dir_contents: OnceLock<Result<DirContents, std::io::Error>>,
/// Properties to provide to modules.
pub properties: Properties,
/// Private field to store Git information for modules who need it
repo: OnceCell<Repo>,
repo: OnceLock<Result<Repo, Box<gix::discover::Error>>>,
/// The shell the user is assumed to be running
pub shell: Shell,
@ -166,8 +166,8 @@ impl<'a> Context<'a> {
properties,
current_dir,
logical_dir,
dir_contents: OnceCell::new(),
repo: OnceCell::new(),
dir_contents: OnceLock::new(),
repo: OnceLock::new(),
shell,
target,
width,
@ -286,9 +286,9 @@ impl<'a> Context<'a> {
}
/// Will lazily get repo root and branch when a module requests it.
pub fn get_repo(&self) -> Result<&Repo, Box<gix::discover::Error>> {
pub fn get_repo(&self) -> Result<&Repo, &gix::discover::Error> {
self.repo
.get_or_try_init(|| -> Result<Repo, Box<gix::discover::Error>> {
.get_or_init(|| -> Result<Repo, Box<gix::discover::Error>> {
// custom open options
let mut git_open_opts_map =
git_sec::trust::Mapping::<gix::open::Options>::default();
@ -359,10 +359,13 @@ impl<'a> Context<'a> {
kind: repository.kind(),
})
})
.as_ref()
.map_err(std::convert::AsRef::as_ref)
}
pub fn dir_contents(&self) -> Result<&DirContents, std::io::Error> {
self.dir_contents.get_or_try_init(|| {
pub fn dir_contents(&self) -> Result<&DirContents, &std::io::Error> {
self.dir_contents
.get_or_init(|| {
let timeout = self.root_config.scan_timeout;
DirContents::from_path_with_timeout(
&self.current_dir,
@ -370,6 +373,7 @@ impl<'a> Context<'a> {
self.root_config.follow_symlinks,
)
})
.as_ref()
}
fn get_shell() -> Shell {

View File

@ -303,10 +303,6 @@ impl<'a> StringFormatter<'a> {
),
)),
FormatElement::TextGroup(textgroup) => {
let textgroup = TextGroup {
format: textgroup.format,
style: textgroup.style,
};
parse_textgroup(textgroup, variables, style_variables, context)
}
FormatElement::Variable(name) => variables

View File

@ -1,8 +1,8 @@
use super::string_formatter::StringFormatterError;
use super::StringFormatter;
use crate::segment;
use once_cell::sync::Lazy;
use std::ops::Deref;
use std::sync::LazyLock;
use versions::Versioning;
pub struct VersionFormatter<'a> {
@ -30,7 +30,7 @@ impl<'a> VersionFormatter<'a> {
/// Formats a version structure into a readable string
pub fn format(self, version: &'a str) -> Result<String, StringFormatterError> {
let parsed = Lazy::new(|| Versioning::new(version));
let parsed = LazyLock::new(|| Versioning::new(version));
let formatted = self
.formatter
.map(|variable| match variable {

View File

@ -1,7 +1,7 @@
use crate::utils;
use log::{Level, LevelFilter, Metadata, Record};
use nu_ansi_term::Color;
use once_cell::sync::OnceCell;
use std::sync::OnceLock;
use std::{
cmp,
collections::HashSet,
@ -13,7 +13,7 @@ use std::{
};
pub struct StarshipLogger {
log_file: OnceCell<Mutex<File>>,
log_file: OnceLock<Result<Mutex<File>, std::io::Error>>,
log_file_path: PathBuf,
log_file_content: RwLock<HashSet<String>>,
log_level: Level,
@ -101,7 +101,7 @@ impl Default for StarshipLogger {
.map(std::string::ToString::to_string)
.collect(),
),
log_file: OnceCell::new(),
log_file: OnceLock::new(),
log_file_path: session_log_file,
log_level: env::var("STARSHIP_LOG")
.map(|level| match level.to_ascii_lowercase().as_str() {
@ -174,7 +174,7 @@ impl log::Log for StarshipLogger {
// Write warning messages to the log file
// If log level is error, only write error messages to the log file
if record.level() <= cmp::min(Level::Warn, self.log_level) {
let log_file = match self.log_file.get_or_try_init(|| {
let log_file = match self.log_file.get_or_init(|| {
OpenOptions::new()
.create(true)
.append(true)
@ -224,7 +224,7 @@ impl log::Log for StarshipLogger {
}
fn flush(&self) {
if let Some(m) = self.log_file.get() {
if let Some(Ok(m)) = self.log_file.get() {
let result = match m.lock() {
Ok(mut file) => file.flush(),
Err(err) => return eprintln!("Log file writer mutex was poisoned: {err:?}"),
@ -246,7 +246,9 @@ mod test {
use super::*;
use crate::utils::read_file;
use log::Log;
use std::fs::{File, FileTimes};
use std::io;
use std::time::SystemTime;
#[test]
fn test_log_to_file() -> io::Result<()> {
@ -353,11 +355,7 @@ mod test {
}
#[test]
#[cfg(unix)]
fn test_cleanup() -> io::Result<()> {
use nix::sys::{stat::utimes, time::TimeVal};
use std::fs::File;
let log_dir = tempfile::tempdir()?;
// Should not be deleted
@ -379,6 +377,10 @@ mod test {
}
fs::create_dir(&directory)?;
let times = FileTimes::new()
.set_accessed(SystemTime::UNIX_EPOCH)
.set_modified(SystemTime::UNIX_EPOCH);
// Set all files except the new file to be older than 24 hours
for file in &[
&non_matching_file,
@ -386,10 +388,19 @@ mod test {
&old_file,
&directory,
] {
utimes(file.as_path(), &TimeVal::new(0, 0), &TimeVal::new(0, 0))?;
if let Ok(f) = File::open(file) {
f.sync_all()?;
let Ok(f) = File::open(file) else {
panic!("Unable to open file {file:?}!")
};
match f.set_times(times) {
Err(err) if err.kind() == io::ErrorKind::PermissionDenied => {
// Ignore permission errors (e.g. on Windows)
eprintln!("Unable to set file times for {file:?}: {err:?}");
return Ok(());
}
other => other,
}?;
f.sync_all()?;
}
cleanup_log_files(log_dir.path());

View File

@ -4,7 +4,7 @@ use std::str::FromStr;
use chrono::DateTime;
use ini::Ini;
use once_cell::unsync::OnceCell;
use std::cell::OnceCell;
use super::{Context, Module, ModuleConfig};

View File

@ -4,10 +4,10 @@ use crate::configs::c::CConfig;
use crate::formatter::StringFormatter;
use crate::formatter::VersionFormatter;
use once_cell::sync::Lazy;
use semver::Version;
use std::borrow::Cow;
use std::ops::Deref;
use std::sync::LazyLock;
/// Creates a module with the current C compiler and version
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
@ -25,7 +25,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
}
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
let c_compiler_info = Lazy::new(|| context.exec_cmds_return_first(config.commands));
let c_compiler_info = LazyLock::new(|| context.exec_cmds_return_first(config.commands));
formatter
.map_meta(|var, _| match var {

View File

@ -254,7 +254,7 @@ fn get_pinned_sdk_version(json: &str) -> Option<String> {
}
}
fn get_local_dotnet_files(context: &Context) -> Result<Vec<DotNetFile>, std::io::Error> {
fn get_local_dotnet_files<'a>(context: &'a Context) -> Result<Vec<DotNetFile>, &'a std::io::Error> {
Ok(context
.dir_contents()?
.files()

View File

@ -4,8 +4,8 @@ use crate::configs::elixir::ElixirConfig;
use crate::formatter::StringFormatter;
use crate::formatter::VersionFormatter;
use once_cell::sync::Lazy;
use std::ops::Deref;
use std::sync::LazyLock;
/// Create a module with the current Elixir version
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
@ -23,7 +23,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
return None;
}
let versions = Lazy::new(|| get_elixir_version(context));
let versions = LazyLock::new(|| get_elixir_version(context));
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter

View File

@ -1,8 +1,8 @@
use ini::Ini;
use once_cell::sync::{Lazy, OnceCell};
use std::borrow::Cow;
use std::path::Path;
use std::path::PathBuf;
use std::sync::{LazyLock, OnceLock};
use super::{Context, Module, ModuleConfig};
@ -15,7 +15,7 @@ type Account<'a> = (&'a str, Option<&'a str>);
struct GcloudContext {
config_name: String,
config_path: PathBuf,
config: OnceCell<Option<Ini>>,
config: OnceLock<Option<Ini>>,
}
impl<'a> GcloudContext {
@ -94,7 +94,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
return None;
}
let gcloud_context = GcloudContext::new(&config_name, &config_path);
let account: Lazy<Option<Account<'_>>, _> = Lazy::new(|| gcloud_context.get_account());
let account: LazyLock<Option<Account<'_>>, _> = LazyLock::new(|| gcloud_context.get_account());
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter

View File

@ -1,5 +1,5 @@
use once_cell::sync::OnceCell;
use regex::Regex;
use std::sync::OnceLock;
use super::{Context, Module, ModuleConfig};
@ -135,8 +135,8 @@ struct GitStatusInfo<'a> {
context: &'a Context<'a>,
repo: &'a context::Repo,
config: GitStatusConfig<'a>,
repo_status: OnceCell<Option<RepoStatus>>,
stashed_count: OnceCell<Option<usize>>,
repo_status: OnceLock<Option<RepoStatus>>,
stashed_count: OnceLock<Option<usize>>,
}
impl<'a> GitStatusInfo<'a> {
@ -149,8 +149,8 @@ impl<'a> GitStatusInfo<'a> {
context,
repo,
config,
repo_status: OnceCell::new(),
stashed_count: OnceCell::new(),
repo_status: OnceLock::new(),
stashed_count: OnceLock::new(),
}
}

View File

@ -4,11 +4,11 @@ use crate::configs::go::GoConfig;
use crate::formatter::StringFormatter;
use crate::formatter::VersionFormatter;
use once_cell::sync::Lazy;
use regex::Regex;
use semver::Version;
use semver::VersionReq;
use std::ops::Deref;
use std::sync::LazyLock;
/// Creates a module with the current Go version
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
@ -26,8 +26,8 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
}
let golang_version =
Lazy::new(|| parse_go_version(&context.exec_cmd("go", &["version"])?.stdout));
let mod_version = Lazy::new(|| get_go_mod_version(context));
LazyLock::new(|| parse_go_version(&context.exec_cmd("go", &["version"])?.stdout));
let mod_version = LazyLock::new(|| get_go_mod_version(context));
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter

View File

@ -270,10 +270,7 @@ mod tests {
toml_config["hostname"]["aliases"]
.as_table_mut()
.unwrap()
.insert(
hostname.clone(),
toml::Value::String("homeworld".to_string()),
);
.insert(hostname, toml::Value::String("homeworld".to_string()));
let actual = ModuleRenderer::new("hostname")
.config(toml_config)
.collect();

View File

@ -3,8 +3,7 @@ use super::{Context, Module, ModuleConfig};
use crate::configs::mojo::MojoConfig;
use crate::formatter::StringFormatter;
use once_cell::sync::Lazy;
use std::ops::Deref;
use std::sync::LazyLock;
/// Creates a module with the current Mojo version
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
@ -22,7 +21,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
return None;
}
let version_hash = Lazy::new(|| get_mojo_version(context));
let version_hash = LazyLock::new(|| get_mojo_version(context));
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter
@ -35,11 +34,11 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
_ => None,
})
.map(|variable| match variable {
"version" => match version_hash.deref() {
"version" => match &*version_hash {
Some((version, _)) => Some(Ok(version)),
_ => None,
},
"hash" => match version_hash.deref() {
"hash" => match &*version_hash {
Some((_, Some(hash))) => Some(Ok(hash)),
_ => None,
},

View File

@ -3,12 +3,12 @@ use super::{Context, Module, ModuleConfig};
use crate::configs::nodejs::NodejsConfig;
use crate::formatter::{StringFormatter, VersionFormatter};
use once_cell::sync::Lazy;
use regex::Regex;
use semver::Version;
use semver::VersionReq;
use serde_json as json;
use std::ops::Deref;
use std::sync::LazyLock;
/// Creates a module with the current Node.js version
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
@ -30,12 +30,12 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
return None;
}
let nodejs_version = Lazy::new(|| {
let nodejs_version = LazyLock::new(|| {
context
.exec_cmd("node", &["--version"])
.map(|cmd| cmd.stdout)
});
let engines_version = Lazy::new(|| get_engines_version(context));
let engines_version = LazyLock::new(|| get_engines_version(context));
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter

View File

@ -1,7 +1,7 @@
use super::{Context, Module, ModuleConfig};
use once_cell::sync::Lazy;
use std::ops::Deref;
use std::path::Path;
use std::sync::LazyLock;
use crate::configs::ocaml::OCamlConfig;
use crate::formatter::StringFormatter;
@ -29,7 +29,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
return None;
}
let opam_switch: Lazy<Option<OpamSwitch>, _> = Lazy::new(|| get_opam_switch(context));
let opam_switch: LazyLock<Option<OpamSwitch>, _> = LazyLock::new(|| get_opam_switch(context));
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter

View File

@ -3,8 +3,8 @@ use super::{Context, Module, ModuleConfig};
use crate::configs::raku::RakuConfig;
use crate::formatter::StringFormatter;
use crate::formatter::VersionFormatter;
use once_cell::sync::Lazy;
use std::ops::Deref;
use std::sync::LazyLock;
/// Creates a module with the current raku version
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
@ -21,7 +21,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
return None;
}
let versions = Lazy::new(|| get_raku_version(context));
let versions = LazyLock::new(|| get_raku_version(context));
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter

View File

@ -12,7 +12,7 @@ use crate::formatter::{StringFormatter, VersionFormatter};
use crate::utils::create_command;
use home::rustup_home;
use once_cell::sync::OnceCell;
use std::sync::OnceLock;
use guess_host_triple::guess_host_triple;
@ -22,23 +22,23 @@ type ToolchainString = String;
/// A struct to cache the output of any commands that need to be run.
struct RustToolingEnvironmentInfo {
/// Rustup settings parsed from $HOME/.rustup/settings.toml
rustup_settings: OnceCell<RustupSettings>,
rustup_settings: OnceLock<RustupSettings>,
/// Rustc toolchain overrides as contained in the environment or files
env_toolchain_override: OnceCell<Option<String>>,
env_toolchain_override: OnceLock<Option<String>>,
/// The output of `rustup rustc --version` with a fixed toolchain
rustup_rustc_output: OnceCell<RustupRunRustcVersionOutcome>,
rustup_rustc_output: OnceLock<RustupRunRustcVersionOutcome>,
/// The output of running rustc -vV. Only called if rustup rustc fails or
/// is unavailable.
rustc_verbose_output: OnceCell<Option<(VersionString, ToolchainString)>>,
rustc_verbose_output: OnceLock<Option<(VersionString, ToolchainString)>>,
}
impl RustToolingEnvironmentInfo {
fn new() -> Self {
Self {
rustup_settings: OnceCell::new(),
env_toolchain_override: OnceCell::new(),
rustup_rustc_output: OnceCell::new(),
rustc_verbose_output: OnceCell::new(),
rustup_settings: OnceLock::new(),
env_toolchain_override: OnceLock::new(),
rustup_rustc_output: OnceLock::new(),
rustc_verbose_output: OnceLock::new(),
}
}
@ -500,9 +500,9 @@ impl RustupSettings {
#[cfg(test)]
mod tests {
use crate::context::{Shell, Target};
use once_cell::sync::Lazy;
use std::io;
use std::process::{ExitStatus, Output};
use std::sync::LazyLock;
use super::*;
@ -648,7 +648,7 @@ version = "12"
#[cfg(windows)]
use std::os::windows::process::ExitStatusExt as _;
static RUSTC_VERSION: Lazy<Output> = Lazy::new(|| Output {
static RUSTC_VERSION: LazyLock<Output> = LazyLock::new(|| Output {
status: ExitStatus::from_raw(0),
stdout: b"rustc 1.34.0\n"[..].to_owned(),
stderr: vec![],
@ -658,7 +658,7 @@ version = "12"
RustupRunRustcVersionOutcome::RustcVersion("rustc 1.34.0\n".to_owned()),
);
static TOOLCHAIN_NAME: Lazy<Output> = Lazy::new(|| Output {
static TOOLCHAIN_NAME: LazyLock<Output> = LazyLock::new(|| Output {
status: ExitStatus::from_raw(1),
stdout: vec![],
stderr: b"error: toolchain 'channel-triple' is not installed\n"[..].to_owned(),
@ -668,7 +668,7 @@ version = "12"
RustupRunRustcVersionOutcome::ToolchainNotInstalled("channel-triple".to_owned()),
);
static INVALID_STDOUT: Lazy<Output> = Lazy::new(|| Output {
static INVALID_STDOUT: LazyLock<Output> = LazyLock::new(|| Output {
status: ExitStatus::from_raw(0),
stdout: b"\xc3\x28"[..].to_owned(),
stderr: vec![],
@ -678,7 +678,7 @@ version = "12"
RustupRunRustcVersionOutcome::Err,
);
static INVALID_STDERR: Lazy<Output> = Lazy::new(|| Output {
static INVALID_STDERR: LazyLock<Output> = LazyLock::new(|| Output {
status: ExitStatus::from_raw(1),
stdout: vec![],
stderr: b"\xc3\x28"[..].to_owned(),
@ -688,7 +688,7 @@ version = "12"
RustupRunRustcVersionOutcome::Err,
);
static UNEXPECTED_FORMAT_OF_ERROR: Lazy<Output> = Lazy::new(|| Output {
static UNEXPECTED_FORMAT_OF_ERROR: LazyLock<Output> = LazyLock::new(|| Output {
status: ExitStatus::from_raw(1),
stdout: vec![],
stderr: b"error:"[..].to_owned(),

View File

@ -5,18 +5,18 @@ use crate::{
utils::{create_command, CommandOutput},
};
use log::{Level, LevelFilter};
use once_cell::sync::Lazy;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use std::sync::LazyLock;
use std::sync::Once;
use tempfile::TempDir;
static FIXTURE_DIR: Lazy<PathBuf> =
Lazy::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/test/fixtures/"));
static FIXTURE_DIR: LazyLock<PathBuf> =
LazyLock::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/test/fixtures/"));
static GIT_FIXTURE: Lazy<PathBuf> = Lazy::new(|| FIXTURE_DIR.join("git-repo.bundle"));
static HG_FIXTURE: Lazy<PathBuf> = Lazy::new(|| FIXTURE_DIR.join("hg-repo.bundle"));
static GIT_FIXTURE: LazyLock<PathBuf> = LazyLock::new(|| FIXTURE_DIR.join("git-repo.bundle"));
static HG_FIXTURE: LazyLock<PathBuf> = LazyLock::new(|| FIXTURE_DIR.join("hg-repo.bundle"));
static LOGGER: Once = Once::new();