carto/src/main.rs

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(())
}