From dc018128473687bd93b50556e13e1381280fa54c Mon Sep 17 00:00:00 2001 From: Valentin Haudiquet Date: Sat, 3 Oct 2026 01:24:54 +0200 Subject: [PATCH 1/9] deps: drop the unused cmd_lib dependency No cmd_lib!/run_cmd!/run_fun! invocation remains anywhere in the tree; the crate shells out through std::process::Command exclusively. --- Cargo.lock | 46 ---------------------------------------------- Cargo.toml | 1 - 2 files changed, 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c3515a..26bbe34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -233,30 +233,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" -[[package]] -name = "cmd_lib" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc93f60133215cad2ef47e47db5a386c78874a2630c2c2be68f0f543b3ce0c2c" -dependencies = [ - "cmd_lib_macros", - "env_logger", - "faccess", - "log", - "os_pipe", -] - -[[package]] -name = "cmd_lib_macros" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd39b5c2657c1a0064aa5d73636dac4a217edeeb6c5f8a5f52c123a758462ece" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "colorchoice" version = "1.0.5" @@ -538,17 +514,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "faccess" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ae66425802d6a903e268ae1a08b8c38ba143520f227a205edf4e9c7e3e26d5" -dependencies = [ - "bitflags 1.3.2", - "libc", - "winapi", -] - [[package]] name = "fastrand" version = "2.5.0" @@ -1488,16 +1453,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "os_pipe" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - [[package]] name = "parking_lot" version = "0.12.5" @@ -1546,7 +1501,6 @@ dependencies = [ "bzip2-rs", "chrono", "clap", - "cmd_lib", "crossterm", "csv", "directories", diff --git a/Cargo.toml b/Cargo.toml index b596e8b..211b33a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ readme = "README.md" [dependencies] clap = { version = "4.5.51", features = ["cargo"] } -cmd_lib = "2.0.0" crossterm = "0.28" flate2 = "1.1.5" serde = { version = "1.0.228", features = ["derive"] } From 239bcb28dfc32b481240dd2f0b64f1abc80cb00a Mon Sep 17 00:00:00 2001 From: Valentin Haudiquet Date: Sat, 3 Oct 2026 01:28:00 +0200 Subject: [PATCH 2/9] data,apt/release,distro_info,new: replace lazy_static with LazyLock Unify the lazily-initialized statics on std::sync::LazyLock, which the newer code already uses: the embed_data! macro expands to a plain static now, which also removes the visibility-forwarding workaround the lazy_static! matcher forced on it (the @expand arm wrapping vis in parentheses), and the 'static ref' spelling is kept at the call sites. distro_info's HTTP client, the apt keyring cache and the new-template registry follow the same pattern. --- src/apt/release.rs | 11 +++++------ src/data.rs | 37 +++++++++++++------------------------ src/distro_info.rs | 20 ++++++++++---------- src/new/templates/mod.rs | 17 ++++++++--------- 4 files changed, 36 insertions(+), 49 deletions(-) diff --git a/src/apt/release.rs b/src/apt/release.rs index 412c695..0a98702 100644 --- a/src/apt/release.rs +++ b/src/apt/release.rs @@ -45,7 +45,6 @@ //! keyserver responses are armored) are dearmored in-process, so no `gpg` //! binary is needed. -use lazy_static::lazy_static; use log::{debug, warn}; use serde::Deserialize; use std::collections::HashMap; @@ -53,6 +52,7 @@ use std::error::Error; use std::fmt; use std::path::Path; use std::path::PathBuf; +use std::sync::LazyLock; use std::sync::Mutex; use std::sync::PoisonError; @@ -793,11 +793,10 @@ async fn fetch_optional(url: &str) -> Option> { None } -lazy_static! { - /// Downloaded keyrings, keyed by URL: keyrings are small but would - /// otherwise be re-downloaded once per series/pocket lookup - static ref KEYRING_CACHE: Mutex>> = Mutex::new(HashMap::new()); -} +/// Downloaded keyrings, keyed by URL: keyrings are small but would +/// otherwise be re-downloaded once per series/pocket lookup +static KEYRING_CACHE: LazyLock>>> = + LazyLock::new(|| Mutex::new(HashMap::new())); /// Read the keyring cache, ignoring poisoning (the map is only corrupted on /// panics, in which case a fresh map is just as good) diff --git a/src/data.rs b/src/data.rs index e750ec7..970b66c 100644 --- a/src/data.rs +++ b/src/data.rs @@ -13,7 +13,7 @@ //! data/quirks.yml) through the [`embed_data!`] macro below, so data //! and its accessors stay together and a diff touching one domain cannot //! half-touch another. The macro embeds the file at compile time and -//! parses it once into a `lazy_static` on first use; since the data ships +//! parses it once into a [`LazyLock`] on first use; since the data ships //! inside the binary, a parse failure is a build-time bug that cannot be //! recovered from at runtime, and the macro panics on it. //! @@ -30,8 +30,9 @@ /// the invoking source file (`"../data/distro_info.yml"` from /// `src/distro_info.rs`, `"../../data/host_keys.yml"` from /// `src/put/ssh.rs`, ...), and expands to the house `include_str!` → -/// `lazy_static` → parse pattern — only the embed+parse boilerplate is -/// generated. +/// parse-on-first-use pattern — only the embed+parse boilerplate is +/// generated. The `static ref` spelling is kept from the macro's +/// `lazy_static!` ancestry; it expands to a plain `LazyLock` static. /// /// ```ignore /// embed_data! { @@ -39,31 +40,19 @@ /// } /// ``` macro_rules! embed_data { - // Internal arm: the visibility arrives wrapped in parentheses (empty for - // private statics) because `lazy_static!` only re-matches literal - // `pub`/`pub(...)` token sequences, not an opaque forwarded `vis`. - (@expand ($($vis:tt)*) static ref $name:ident : $ty:ty = $path:literal) => { - lazy_static::lazy_static! { - // The YAML is include_str!'d at compile time and statically - // valid; if it ever failed to parse it would be a build-time bug - // that cannot be recovered from at runtime, so panicking here is - // acceptable. - $($vis)* static ref $name: $ty = serde_yaml::from_str(include_str!($path)) + ($vis:vis static ref $name:ident : $ty:ty = $path:literal) => { + // The YAML is include_str!'d at compile time and statically + // valid; if it ever failed to parse it would be a build-time bug + // that cannot be recovered from at runtime, so panicking here is + // acceptable. + $vis static $name: ::std::sync::LazyLock<$ty> = ::std::sync::LazyLock::new(|| { + serde_yaml::from_str(include_str!($path)) .expect(concat!( "built-in ", $path, " data is statically valid and must parse" - )); - } - }; - (static ref $name:ident : $ty:ty = $path:literal) => { - $crate::data::embed_data!(@expand () static ref $name : $ty = $path); - }; - (pub static ref $name:ident : $ty:ty = $path:literal) => { - $crate::data::embed_data!(@expand (pub) static ref $name : $ty = $path); - }; - (pub ($($vis:tt)+) static ref $name:ident : $ty:ty = $path:literal) => { - $crate::data::embed_data!(@expand (pub ($($vis)+)) static ref $name : $ty = $path); + )) + }); }; } diff --git a/src/distro_info.rs b/src/distro_info.rs index 9e7fb6c..45505af 100644 --- a/src/distro_info.rs +++ b/src/distro_info.rs @@ -1,10 +1,10 @@ use crate::data::embed_data; use chrono::NaiveDate; -use lazy_static::lazy_static; use serde::Deserialize; use std::collections::HashMap; use std::error::Error; use std::path::Path; +use std::sync::LazyLock; use std::time::Duration; #[derive(Debug, Clone)] @@ -104,20 +104,20 @@ embed_data! { static ref DATA: Data = "../data/distro_info.yml" } -lazy_static! { - // Shared HTTP client used for all outgoing plain requests: timeouts keep - // a hanging remote (connect or transfer) from stalling pkh indefinitely. - // The short pool idle timeout and TCP keepalive avoid reusing keep-alive - // connections that the remote closed in the meantime, which surfaces as - // spurious 'error sending request' failures on busy mirrors/CDNs. - static ref HTTP_CLIENT: reqwest::Client = reqwest::Client::builder() +// Shared HTTP client used for all outgoing plain requests: timeouts keep +// a hanging remote (connect or transfer) from stalling pkh indefinitely. +// The short pool idle timeout and TCP keepalive avoid reusing keep-alive +// connections that the remote closed in the meantime, which surfaces as +// spurious 'error sending request' failures on busy mirrors/CDNs. +static HTTP_CLIENT: LazyLock = LazyLock::new(|| { + reqwest::Client::builder() .connect_timeout(Duration::from_secs(10)) .timeout(Duration::from_secs(30)) .pool_idle_timeout(Duration::from_secs(10)) .tcp_keepalive(Duration::from_secs(30)) .build() - .expect("building the shared HTTP client with static options cannot fail"); -} + .expect("building the shared HTTP client with static options cannot fail") +}); /// Shared HTTP client with a connect timeout (10s) and a total request /// timeout (30s), to be used for all outgoing plain HTTP(S) requests diff --git a/src/new/templates/mod.rs b/src/new/templates/mod.rs index 9e2bdde..9576183 100644 --- a/src/new/templates/mod.rs +++ b/src/new/templates/mod.rs @@ -52,6 +52,7 @@ pub mod rust; pub mod shell; use std::path::{Path, PathBuf}; +use std::sync::LazyLock; use serde::Deserialize; @@ -478,15 +479,13 @@ static TEMPLATE_SOURCES: &[TemplateSources] = &[ }, ]; -lazy_static::lazy_static! { - /// The parsed registry: manifest data plus resolved hooks, in the - /// order of [`TEMPLATE_SOURCES`] (wizard menu = detection priority). - static ref REGISTRY: Vec