198 lines
6.3 KiB
Rust
198 lines
6.3 KiB
Rust
#![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<std::io::Error> for WhereError {
|
|
fn from(err: std::io::Error) -> Self {
|
|
WhereError::Io(err)
|
|
}
|
|
}
|
|
|
|
impl From<std::string::FromUtf8Error> 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<dyn std::error::Error>> {
|
|
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<dyn PackageManager>],
|
|
_depth: Option<usize>,
|
|
package_filter: Option<String>,
|
|
_source_filter: Option<String>
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
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<dyn PackageManager>],
|
|
name: &str
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
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<dyn PackageManager>],
|
|
_source_filter: Option<String>
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
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<dyn PackageManager>],
|
|
path: &str
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
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<dyn PackageManager>],
|
|
_name: Option<String>,
|
|
package: Option<String>,
|
|
_size: Option<String>
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
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<dyn PackageManager>],
|
|
_force: bool
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("Scan functionality not yet implemented");
|
|
Ok(())
|
|
} |