From f4287de7958c895cc6c07f7b5a1be831298d266b Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Sat, 28 Feb 2026 23:08:26 +0300 Subject: [PATCH] treewide: remove dead code Also deletes some dead_code annotations from functions that are *actually used*. Signed-off-by: NotAShelf Change-Id: Ic815cacc93c464078ead1674e7523d8b6a6a6964 --- src/cli/commands/status.rs | 16 ++------ src/ui_utils.rs | 49 +++++++++++++----------- src/utils/hash.rs | 77 -------------------------------------- 3 files changed, 30 insertions(+), 112 deletions(-) diff --git a/src/cli/commands/status.rs b/src/cli/commands/status.rs index 6b50ed6..1e157a8 100644 --- a/src/cli/commands/status.rs +++ b/src/cli/commands/status.rs @@ -13,6 +13,7 @@ use crate::{ pub async fn execute( parallel: bool, + skip_prompts: bool, lockfile_path: &Path, config_path: &Path, ) -> Result<()> { @@ -77,15 +78,15 @@ pub async fn execute( // Prompt to update if there are updates available if !updates.is_empty() { println!(); - if crate::ui_utils::prompt_yes_no("Update now?", false)? { + if crate::ui_utils::prompt_yes_no("Update now?", false, skip_prompts)? { // Call update command programmatically (update all projects) let update_args = crate::cli::UpdateArgs { inputs: vec![], all: true, - yes: true, // Auto-yes for status command }; crate::cli::commands::update::execute( update_args, + true, // Auto-yes for status command lockfile_path, config_path, ) @@ -380,17 +381,6 @@ fn display_update_results(updates: &[ProjectUpdate]) { ); } -#[allow(dead_code)] -fn get_project_display_name(project: &Project) -> String { - project - .name - .values() - .next() - .or_else(|| project.slug.values().next()) - .cloned() - .unwrap_or_else(|| "Unknown".to_string()) -} - fn get_api_key(platform: &str) -> Option { match platform { "modrinth" => std::env::var("MODRINTH_TOKEN").ok(), diff --git a/src/ui_utils.rs b/src/ui_utils.rs index 62589b5..f293256 100644 --- a/src/ui_utils.rs +++ b/src/ui_utils.rs @@ -2,7 +2,7 @@ use std::io; -use dialoguer::{Confirm, Input, MultiSelect, Select, theme::ColorfulTheme}; +use dialoguer::{Confirm, Input, Select, theme::ColorfulTheme}; /// Creates a terminal hyperlink using OSC 8 escape sequence /// Format: \x1b]8;;\x1b\\\x1b]8;;\x1b\\ @@ -12,7 +12,16 @@ pub fn hyperlink(url: &str, text: &str) -> String { /// Prompts user with a yes/no question /// Returns true for yes, false for no -pub fn prompt_yes_no(question: &str, default: bool) -> io::Result { +/// If `skip_prompts` is true, returns the default value without prompting +pub fn prompt_yes_no( + question: &str, + default: bool, + skip_prompts: bool, +) -> io::Result { + if skip_prompts { + return Ok(default); + } + Confirm::with_theme(&ColorfulTheme::default()) .with_prompt(question) .default(default) @@ -22,7 +31,6 @@ pub fn prompt_yes_no(question: &str, default: bool) -> io::Result { /// Prompts user to select from a list of options /// Returns the index of the selected option -#[allow(dead_code)] pub fn prompt_select(question: &str, options: &[&str]) -> io::Result { Select::with_theme(&ColorfulTheme::default()) .with_prompt(question) @@ -32,28 +40,12 @@ pub fn prompt_select(question: &str, options: &[&str]) -> io::Result { .map_err(io::Error::other) } -/// Prompts user to select multiple items from a list -/// Returns the indices of the selected options -#[allow(dead_code)] -pub fn prompt_multi_select( - question: &str, - options: &[&str], -) -> io::Result> { - MultiSelect::with_theme(&ColorfulTheme::default()) - .with_prompt(question) - .items(options) - .interact() - .map_err(io::Error::other) -} - /// Creates a formatted project URL for Modrinth -#[allow(dead_code)] pub fn modrinth_project_url(slug: &str) -> String { format!("https://modrinth.com/mod/{slug}") } /// Creates a formatted project URL for `CurseForge` -#[allow(dead_code)] pub fn curseforge_project_url(project_id: &str) -> String { format!("https://www.curseforge.com/minecraft/mc-mods/{project_id}") } @@ -118,16 +110,22 @@ pub fn suggest_similar<'a>( /// Prompt user if they meant a similar project name. /// Returns `Some(suggested_name)` if user confirms, None otherwise. +/// If `skip_prompts` is true, automatically accepts the first suggestion. pub fn prompt_typo_suggestion( input: &str, candidates: &[String], + skip_prompts: bool, ) -> io::Result> { // Use a max distance based on input length for reasonable suggestions let max_distance = (input.len() / 2).clamp(2, 4); let suggestions = suggest_similar(input, candidates, max_distance); if let Some(first_suggestion) = suggestions.first() - && prompt_yes_no(&format!("Did you mean '{first_suggestion}'?"), true)? + && prompt_yes_no( + &format!("Did you mean '{first_suggestion}'?"), + true, + skip_prompts, + )? { return Ok(Some((*first_suggestion).to_string())); } @@ -164,7 +162,14 @@ pub fn prompt_input_optional(prompt: &str) -> io::Result> { /// Prompt for `CurseForge` API key when authentication fails. /// Returns the API key if provided, None if cancelled. -pub fn prompt_curseforge_api_key() -> io::Result> { +/// If `skip_prompts` is true, returns None immediately. +pub fn prompt_curseforge_api_key( + skip_prompts: bool, +) -> io::Result> { + if skip_prompts { + return Ok(None); + } + use dialoguer::Password; println!(); @@ -172,7 +177,7 @@ pub fn prompt_curseforge_api_key() -> io::Result> { println!("Get your API key from: https://console.curseforge.com/"); println!(); - if !prompt_yes_no("Would you like to enter your API key now?", true)? { + if !prompt_yes_no("Would you like to enter your API key now?", true, false)? { return Ok(None); } diff --git a/src/utils/hash.rs b/src/utils/hash.rs index 88abdde..d440b0e 100644 --- a/src/utils/hash.rs +++ b/src/utils/hash.rs @@ -10,58 +10,6 @@ use sha2::{Sha256, Sha512}; use crate::error::{PakkerError, Result}; -/// Compute Murmur2 hash (32-bit) for `CurseForge` fingerprinting -#[allow(dead_code)] -pub fn compute_murmur2_hash(data: &[u8]) -> u32 { - murmur2_hash(data, 1) -} - -/// Murmur2 hash implementation -#[allow(dead_code)] -fn murmur2_hash(data: &[u8], seed: u32) -> u32 { - const M: u32 = 0x5BD1E995; - const R: i32 = 24; - - let mut h: u32 = seed ^ (data.len() as u32); - let mut chunks = data.chunks_exact(4); - - for chunk in chunks.by_ref() { - let mut k = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]); - k = k.wrapping_mul(M); - k ^= k >> R; - k = k.wrapping_mul(M); - - h = h.wrapping_mul(M); - h ^= k; - } - - let remainder = chunks.remainder(); - match remainder.len() { - 3 => { - h ^= u32::from(remainder[2]) << 16; - h ^= u32::from(remainder[1]) << 8; - h ^= u32::from(remainder[0]); - h = h.wrapping_mul(M); - }, - 2 => { - h ^= u32::from(remainder[1]) << 8; - h ^= u32::from(remainder[0]); - h = h.wrapping_mul(M); - }, - 1 => { - h ^= u32::from(remainder[0]); - h = h.wrapping_mul(M); - }, - _ => {}, - } - - h ^= h >> 13; - h = h.wrapping_mul(M); - h ^= h >> 15; - - h -} - /// Compute SHA1 hash of a file pub fn compute_sha1>(path: P) -> Result { let file = File::open(path)?; @@ -167,31 +115,6 @@ pub fn verify_hash>( mod tests { use super::*; - #[test] - fn test_murmur2_hash_deterministic() { - let data = b"hello world"; - let hash1 = compute_murmur2_hash(data); - let hash2 = compute_murmur2_hash(data); - assert_eq!(hash1, hash2, "Murmur2 hash must be deterministic"); - } - - #[test] - fn test_murmur2_hash_empty() { - let data = b""; - let hash = compute_murmur2_hash(data); - assert_ne!(hash, 0, "Empty data should produce a non-zero hash"); - } - - #[test] - fn test_murmur2_hash_different_inputs() { - let hash1 = compute_murmur2_hash(b"hello"); - let hash2 = compute_murmur2_hash(b"world"); - assert_ne!( - hash1, hash2, - "Different inputs should produce different hashes" - ); - } - #[test] fn test_sha256_bytes_deterministic() { let data = b"test data";