#![allow(dead_code)] #![allow(unused_imports)] pub mod package_managers; pub mod cli; use std::path::PathBuf; use package_managers::{detect_available_managers, PackageManager, PackageSource}; use cli::{Cli, Commands}; use clap::Parser; // Define the types that your modules need #[derive(Debug, Clone)] pub struct PackageInfo { pub name: String, pub version: String, pub source: PackageSource, pub install_time: u64, pub size: u64, } #[derive(Debug)] pub enum WhereError { Io(std::io::Error), Utf8(std::string::FromUtf8Error), CommandFailed(String), PackageNotFound(String), ManagerNotAvailable(String), InvalidDatabase, } // Implement From traits for error conversion impl From for WhereError { fn from(err: std::io::Error) -> Self { WhereError::Io(err) } } impl From for WhereError { fn from(err: std::string::FromUtf8Error) -> Self { WhereError::Utf8(err) } } impl std::fmt::Display for WhereError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { WhereError::Io(e) => write!(f, "IO error: {}", e), WhereError::Utf8(e) => write!(f, "UTF-8 error: {}", e), WhereError::CommandFailed(s) => write!(f, "Command failed: {}", s), WhereError::PackageNotFound(s) => write!(f, "Package not found: {}", s), WhereError::ManagerNotAvailable(s) => write!(f, "Manager not available: {}", s), WhereError::InvalidDatabase => write!(f, "Invalid database format"), } } } impl std::error::Error for WhereError {} fn main() -> Result<(), Box> { let cli = Cli::parse(); let managers = detect_available_managers(); match cli.command { Commands::Tree { depth, package, source } => { handle_tree_command(&managers, depth, package, source)?; } Commands::Package { name } => { handle_package_command(&managers, &name)?; } Commands::Packages { source } => { handle_packages_command(&managers, source)?; } Commands::File { path } => { handle_file_command(&managers, &path)?; } Commands::Find { name, package, size } => { handle_find_command(&managers, name, package, size)?; } Commands::Scan { force } => { handle_scan_command(&managers, force)?; } } Ok(()) } fn handle_tree_command( managers: &[Box], _depth: Option, package_filter: Option, _source_filter: Option ) -> Result<(), Box> { if let Some(dnf) = managers.iter().find(|m| m.name() == "dnf") { if let Some(package_name) = package_filter { // Show tree for specific package cli::tree::print_package_tree(dnf.as_ref(), &package_name)?; } else { // Show tree for first few packages as demo println!("Package file trees (first 5 packages):"); let packages = dnf.get_installed_packages()?; for package in packages.iter().take(5) { cli::tree::print_package_tree(dnf.as_ref(), &package.name)?; println!(); // Empty line between packages } } } else { println!("No DNF package manager found"); } Ok(()) } fn handle_package_command( managers: &[Box], name: &str ) -> Result<(), Box> { if let Some(dnf) = managers.iter().find(|m| m.name() == "dnf") { match dnf.get_package_info(name) { Ok(Some(info)) => { println!("Package: {}", info.name); println!("Version: {}", info.version); println!("Source: {}", info.source.name()); println!("Install time: {}", info.install_time); println!("Size: {} bytes", info.size); // Show file tree for this package println!("\nFiles:"); cli::tree::print_package_tree(dnf.as_ref(), name)?; } Ok(None) => println!("Package '{}' not found", name), Err(e) => println!("Error: {}", e), } } Ok(()) } fn handle_packages_command( managers: &[Box], _source_filter: Option ) -> Result<(), Box> { if let Some(dnf) = managers.iter().find(|m| m.name() == "dnf") { let packages = dnf.get_installed_packages()?; println!("Installed packages ({} total):", packages.len()); for package in packages.iter() { println!(" {} {} ({})", package.name, package.version, package.source.name()); } } Ok(()) } fn handle_file_command( managers: &[Box], path: &str ) -> Result<(), Box> { if let Some(dnf) = managers.iter().find(|m| m.name() == "dnf") { match dnf.get_file_owner(std::path::Path::new(path)) { Ok(Some(owner)) => println!("{} is owned by package: {}", path, owner), Ok(None) => println!("{} is not owned by any package", path), Err(e) => println!("Error checking {}: {}", path, e), } } Ok(()) } fn handle_find_command( managers: &[Box], _name: Option, package: Option, _size: Option ) -> Result<(), Box> { if let Some(package_name) = package { if let Some(dnf) = managers.iter().find(|m| m.name() == "dnf") { match dnf.get_package_files(&package_name) { Ok(files) => { println!("Files in package '{}':", package_name); for file in files { println!(" {}", file.display()); } } Err(e) => println!("Error: {}", e), } } } else { println!("Find command needs more specific criteria"); } Ok(()) } fn handle_scan_command( _managers: &[Box], _force: bool ) -> Result<(), Box> { println!("Scan functionality not yet implemented"); Ok(()) }