Move inline #[cfg(test)] mod tests { ... } blocks from 22 source files
into dedicated _tests.rs companion files, wired via:
#[cfg(test)]
#[path = "module_tests.rs"]
mod tests;
This keeps implementation-focused source files leaner and more scannable
while preserving full access to private items through `use super::*;`.
Modules extracted:
core: db, note_parser, payloads, project, references, sync_run,
timeline_collect, timeline_expand, timeline_seed
cli: list (55 tests), who (75 tests)
documents: extractor (43 tests), regenerator
embedding: change_detector, chunking
gitlab: graphql (wiremock async tests), transformers/issue
ingestion: dirty_tracker, discussions, issues, mr_diffs
Also adds conflicts_with("explain_score") to the --detail flag in the
who command to prevent mutually exclusive flags from being combined.
All 629 unit tests pass. No behavior changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
127 lines
3.6 KiB
Rust
127 lines
3.6 KiB
Rust
use rusqlite::{Connection, OptionalExtension};
|
|
use tracing::info;
|
|
|
|
use super::error::Result;
|
|
use super::time::now_ms;
|
|
|
|
pub fn extract_refs_from_state_events(conn: &Connection, project_id: i64) -> Result<usize> {
|
|
let changes = conn.execute(
|
|
"INSERT OR IGNORE INTO entity_references (
|
|
project_id,
|
|
source_entity_type, source_entity_id,
|
|
target_entity_type, target_entity_id,
|
|
reference_type, source_method, created_at
|
|
)
|
|
SELECT
|
|
rse.project_id,
|
|
'merge_request',
|
|
mr.id,
|
|
'issue',
|
|
rse.issue_id,
|
|
'closes',
|
|
'api',
|
|
rse.created_at
|
|
FROM resource_state_events rse
|
|
JOIN merge_requests mr
|
|
ON mr.project_id = rse.project_id
|
|
AND mr.iid = rse.source_merge_request_iid
|
|
WHERE rse.source_merge_request_iid IS NOT NULL
|
|
AND rse.issue_id IS NOT NULL
|
|
AND rse.project_id = ?1",
|
|
rusqlite::params![project_id],
|
|
)?;
|
|
|
|
if changes > 0 {
|
|
info!(
|
|
project_id,
|
|
references_inserted = changes,
|
|
"Extracted cross-references from state events"
|
|
);
|
|
}
|
|
|
|
Ok(changes)
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct EntityReference<'a> {
|
|
pub project_id: i64,
|
|
pub source_entity_type: &'a str,
|
|
pub source_entity_id: i64,
|
|
pub target_entity_type: &'a str,
|
|
pub target_entity_id: Option<i64>,
|
|
pub target_project_path: Option<&'a str>,
|
|
pub target_entity_iid: Option<i64>,
|
|
pub reference_type: &'a str,
|
|
pub source_method: &'a str,
|
|
}
|
|
|
|
pub fn insert_entity_reference(conn: &Connection, ref_: &EntityReference<'_>) -> Result<bool> {
|
|
let now = now_ms();
|
|
let changes = conn.execute(
|
|
"INSERT OR IGNORE INTO entity_references \
|
|
(project_id, source_entity_type, source_entity_id, \
|
|
target_entity_type, target_entity_id, target_project_path, target_entity_iid, \
|
|
reference_type, source_method, created_at) \
|
|
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)",
|
|
rusqlite::params![
|
|
ref_.project_id,
|
|
ref_.source_entity_type,
|
|
ref_.source_entity_id,
|
|
ref_.target_entity_type,
|
|
ref_.target_entity_id,
|
|
ref_.target_project_path,
|
|
ref_.target_entity_iid,
|
|
ref_.reference_type,
|
|
ref_.source_method,
|
|
now,
|
|
],
|
|
)?;
|
|
|
|
Ok(changes > 0)
|
|
}
|
|
|
|
pub fn resolve_issue_local_id(
|
|
conn: &Connection,
|
|
project_id: i64,
|
|
issue_iid: i64,
|
|
) -> Result<Option<i64>> {
|
|
let mut stmt =
|
|
conn.prepare_cached("SELECT id FROM issues WHERE project_id = ?1 AND iid = ?2")?;
|
|
|
|
let result = stmt
|
|
.query_row(rusqlite::params![project_id, issue_iid], |row| row.get(0))
|
|
.optional()?;
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
pub fn resolve_project_path(conn: &Connection, gitlab_project_id: i64) -> Result<Option<String>> {
|
|
let mut stmt = conn
|
|
.prepare_cached("SELECT path_with_namespace FROM projects WHERE gitlab_project_id = ?1")?;
|
|
|
|
let result = stmt
|
|
.query_row(rusqlite::params![gitlab_project_id], |row| row.get(0))
|
|
.optional()?;
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
pub fn count_references_for_source(
|
|
conn: &Connection,
|
|
source_entity_type: &str,
|
|
source_entity_id: i64,
|
|
) -> Result<usize> {
|
|
let count: i64 = conn.query_row(
|
|
"SELECT COUNT(*) FROM entity_references \
|
|
WHERE source_entity_type = ?1 AND source_entity_id = ?2",
|
|
rusqlite::params![source_entity_type, source_entity_id],
|
|
|row| row.get(0),
|
|
)?;
|
|
|
|
Ok(count as usize)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "references_tests.rs"]
|
|
mod tests;
|