Refactor project and index handling

- Standardized formatting across key functions in `project.rs`.
- Updated `index::handle` and `build_index` to incorporate the `config` parameter.
- Improved index-building logic to include project details and enhanced issue tracking.
- Replaced variable names like `files` with `paths` for clarity in `scan.rs`.
This commit is contained in:
elipeter 2025-06-17 17:42:41 +02:00
parent 0eecf886f2
commit ead64c0bd3
4 changed files with 66 additions and 36 deletions

View file

@ -1,10 +1,15 @@
use std::fs;
use crate::cli::IndexAction;
use crate::database::index::{Indexer, IssueRow};
use crate::patterns::Severity;
use crate::utils::Config;
use crate::utils::project::get_project_info;
use crate::walk::spawn_senders;
pub fn handle(
action: IndexAction,
database_dir: &std::path::Path,
config: &Config,
) -> Result<(), Box<dyn std::error::Error>> {
match action {
IndexAction::Build { path, force } => {
@ -12,8 +17,7 @@ pub fn handle(
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)?;
build_index(&project_name, &build_path, &db_path, config)?;
println!("Index built: {}", db_path.display());
} else {
println!("Index already exists. Use --force to rebuild.");
@ -38,10 +42,35 @@ pub fn handle(
}
pub fn build_index(
_project_path: &std::path::Path,
project_name: &str,
project_path: &std::path::Path,
db_path: &std::path::Path,
config: &Config,
) -> Result<(), Box<dyn std::error::Error>> {
// TODO: Implement actual index building
tracing::debug!("Building index for: {}", project_name);
fs::File::create(db_path)?;
let mut indexer = Indexer::new(&project_name, &db_path)?;
let rx = spawn_senders(project_path, config);
for path in rx.iter().flatten() {
let issues = crate::commands::scan::run_rules_on_file(&path, config)?;
let file_id = indexer.upsert_file(&path)?;
let issue_rows: Vec<IssueRow> = issues
.iter()
.map(|d| IssueRow {
rule_id: d.id.as_ref(),
severity: match d.severity {
Severity::High => "HIGH",
Severity::Medium => "MEDIUM",
Severity::Low => "LOW",
},
line: d.line as i64,
col: d.col as i64,
})
.collect();
indexer.replace_issues(file_id, issue_rows)?;
}
Ok(())
}

View file

@ -17,7 +17,7 @@ pub fn handle_command(
scan::handle(&path, no_index, rebuild_index, format, high_only, database_dir, config)
}
Commands::Index { action } => {
index::handle(action, database_dir)
index::handle(action, database_dir, config)
}
Commands::List { verbose } => {
list::handle(verbose, database_dir)

View file

@ -40,7 +40,8 @@ pub fn handle(
diags = scan_filesystem(&scan_path, config)?;
} else {
if rebuild_index || !db_path.exists() {
crate::commands::index::build_index(&scan_path, &db_path)?;
tracing::debug!("Scanning filesystem index filesystem");
crate::commands::index::build_index(&project_name,&scan_path, &db_path, config)?;
}
diags = scan_with_index(&project_name, &db_path, config, &mut indexer)?;
}
@ -90,12 +91,12 @@ fn scan_with_index(
cfg: &Config,
indexer: &mut Indexer,
) -> Result<Vec<Diag>, Box<dyn std::error::Error>> {
let files = indexer.get_files(project).unwrap_or_default();
let paths = indexer.get_files(project).unwrap_or_default();
let mut issues: Vec<Diag> = Vec::new();
for file in files {
if indexer.should_scan(&file)? {
let mut diags = run_rules_on_file(&file, cfg)?;
let file_id = indexer.upsert_file(&file)?;
for path in paths {
if indexer.should_scan(&path)? {
let mut diags = run_rules_on_file(&path, cfg)?;
let file_id = indexer.upsert_file(&path)?;
let issue_rows: Vec<IssueRow> = diags
.iter()
@ -115,7 +116,7 @@ fn scan_with_index(
issues.append(&mut diags);
continue;
}
issues.append(&mut indexer.get_issues_from_file(&file)?);
issues.append(&mut indexer.get_issues_from_file(&path)?);
}
Ok(issues)
}
@ -123,7 +124,7 @@ fn scan_with_index(
// --------------------------------------------------------------------------------------------
// Treesitterbased rule runner returns a Vec<Diag>
// --------------------------------------------------------------------------------------------
fn run_rules_on_file(
pub(crate) fn run_rules_on_file(
path: &Path,
cfg: &Config,
) -> Result<Vec<Diag>, Box<dyn std::error::Error>> {

View file

@ -3,29 +3,29 @@ use std::path::{Path, PathBuf};
pub fn get_project_info(
project_path: &Path,
config_dir: &Path,
) -> Result<(String, PathBuf), Box<dyn std::error::Error>> {
let project_name = project_path
.file_name()
.and_then(|name| name.to_str())
.ok_or("Unable to determine project name")?;
let db_name = sanitize_project_name(project_name);
let db_path = config_dir.join(format!("{}.sqlite", db_name));
Ok((project_name.to_string(), db_path))
) -> Result<(String, PathBuf), Box<dyn std::error::Error>> {
let project_name = project_path
.file_name()
.and_then(|name| name.to_str())
.ok_or("Unable to determine project name")?;
let db_name = sanitize_project_name(project_name);
let db_path = config_dir.join(format!("{}.sqlite", db_name));
Ok((project_name.to_string(), db_path))
}
pub fn sanitize_project_name(name: &str) -> String {
name.to_lowercase()
.chars()
.map(|c| match c {
' ' | '\t' | '\n' | '\r' => '_',
c if c.is_alphanumeric() || c == '_' || c == '-' => c,
_ => '_'
})
.collect::<String>()
.split('_')
.filter(|s| !s.is_empty())
.collect::<Vec<_>>()
.join("_")
pub fn sanitize_project_name(name: &str) -> String {
name.to_lowercase()
.chars()
.map(|c| match c {
' ' | '\t' | '\n' | '\r' => '_',
c if c.is_alphanumeric() || c == '_' || c == '-' => c,
_ => '_'
})
.collect::<String>()
.split('_')
.filter(|s| !s.is_empty())
.collect::<Vec<_>>()
.join("_")
}