Added foundational modules for core functionalities:

- Introduced `walk.rs` as a parallel directory walker for search operations.
- Implemented basic index handling in `commands/index.rs`.
- Created `utils/config.rs` for configuration management with placeholders for future enhancements.
This commit is contained in:
elipeter 2025-06-16 16:46:22 +02:00
commit ab5558f537
16 changed files with 2187 additions and 0 deletions

37
src/commands/clean.rs Normal file
View file

@ -0,0 +1,37 @@
use std::{env, fs};
use crate::utils::get_project_info;
pub fn handle(
project: Option<String>,
all: bool,
config_dir: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
if all {
println!("Cleaning all indexes...");
if config_dir.exists() {
fs::remove_dir_all(config_dir)?;
fs::create_dir_all(config_dir)?;
}
println!("All indexes cleaned.");
} else if let Some(proj_name) = project {
let db_path = config_dir.join(format!("{}.sqlite", proj_name));
if db_path.exists() {
fs::remove_file(&db_path)?;
println!("Cleaned index for: {}", proj_name);
} else {
println!("No index found for: {}", proj_name);
}
} else {
let current_dir = env::current_dir()?;
let (project_name, db_path) = get_project_info(&current_dir, config_dir)?;
if db_path.exists() {
fs::remove_file(&db_path)?;
println!("Cleaned index for: {}", project_name);
} else {
println!("No index found for current project: {}", project_name);
}
}
Ok(())
}

48
src/commands/index.rs Normal file
View file

@ -0,0 +1,48 @@
use std::fs;
use crate::cli::IndexAction;
use crate::utils::project::get_project_info;
pub fn handle(
action: IndexAction,
database_dir: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
match action {
IndexAction::Build { path, force } => {
let build_path = std::path::Path::new(&path).canonicalize()?;
let (project_name, db_path) = get_project_info(&build_path, database_dir)?;
if force || !db_path.exists() {
println!("Building index for: {}", project_name);
build_index(&build_path, &db_path)?;
println!("Index built: {}", db_path.display());
} else {
println!("Index already exists. Use --force to rebuild.");
}
}
IndexAction::Status { path } => {
let status_path = std::path::Path::new(&path).canonicalize()?;
let (project_name, db_path) = get_project_info(&status_path, database_dir)?;
println!("Project: {}", project_name);
println!("Index path: {}", db_path.display());
println!("Index exists: {}", db_path.exists());
if db_path.exists() {
let metadata = fs::metadata(&db_path)?;
println!("Index size: {} bytes", metadata.len());
println!("Last modified: {:?}", metadata.modified()?);
}
}
}
Ok(())
}
pub fn build_index(
_project_path: &std::path::Path,
db_path: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
// TODO: Implement actual index building
fs::File::create(db_path)?;
println!("Index building logic goes here...");
Ok(())
}

35
src/commands/list.rs Normal file
View file

@ -0,0 +1,35 @@
use std::fs;
pub fn handle(
verbose: bool,
database_dir: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error>> {
println!("Indexed projects:");
if database_dir.exists() {
for entry in fs::read_dir(database_dir)? {
let entry = entry?;
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("sqlite") {
let project_name = path
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("unknown");
println!(" {}", project_name);
if verbose {
let metadata = fs::metadata(&path)?;
println!(" Path: {}", path.display());
println!(" Size: {} bytes", metadata.len());
println!(" Modified: {:?}", metadata.modified()?);
}
}
}
} else {
println!(" No indexed projects found.");
}
Ok(())
}

29
src/commands/mod.rs Normal file
View file

@ -0,0 +1,29 @@
pub mod scan;
pub mod index;
pub mod list;
pub mod clean;
use crate::cli::Commands;
use std::path::Path;
use crate::utils::config::Config;
pub fn handle_command(
command: Commands,
database_dir: &Path,
config: &Config
) -> Result<(), Box<dyn std::error::Error>> {
match command {
Commands::Scan { path, no_index, rebuild_index, format, high_only } => {
scan::handle(&path, no_index, rebuild_index, format, high_only, database_dir, config)
}
Commands::Index { action } => {
index::handle(action, database_dir)
}
Commands::List { verbose } => {
list::handle(verbose, database_dir)
}
Commands::Clean { project, all } => {
clean::handle(project, all, database_dir)
}
}
}

53
src/commands/scan.rs Normal file
View file

@ -0,0 +1,53 @@
use crate::cli::OutputFormat;
use crate::utils::project::get_project_info;
use std::path::Path;
use crate::utils::config::Config;
pub fn handle(
path: &str,
no_index: bool,
rebuild_index: bool,
format: OutputFormat,
high_only: bool,
database_dir: &Path,
config: &Config,
) -> Result<(), Box<dyn std::error::Error>> {
let scan_path = Path::new(path).canonicalize()?;
let (project_name, db_path) = get_project_info(&scan_path, database_dir)?;
tracing::info!("Config: {:?}", config);
tracing::info!("Scanning project: {}", project_name);
tracing::info!("Scan path: {}", scan_path.display());
if no_index {
tracing::info!("Scanning without index...");
scan_filesystem(&scan_path)?;
} else {
if rebuild_index || !db_path.exists() {
tracing::info!("Building/updating index...");
crate::commands::index::build_index(&scan_path, &db_path)?;
}
tracing::info!("Using index: {}", db_path.display());
scan_with_index(&db_path)?;
}
tracing::info!("Output format: {:?}", format);
if high_only {
tracing::info!("Filtering: High severity only");
}
Ok(())
}
fn scan_filesystem(path: &Path) -> Result<(), Box<dyn std::error::Error>> {
// TODO: Implement direct filesystem scanning
tracing::info!("Direct filesystem scan of: {}", path.display());
Ok(())
}
fn scan_with_index(db_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
// TODO: Implement index-based scanning
tracing::info!("Index-based scan using: {}", db_path.display());
Ok(())
}