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>
98 lines
2.7 KiB
Rust
98 lines
2.7 KiB
Rust
use chrono::DateTime;
|
|
use thiserror::Error;
|
|
|
|
use crate::gitlab::types::GitLabIssue;
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum TransformError {
|
|
#[error("Failed to parse timestamp '{0}': {1}")]
|
|
TimestampParse(String, String),
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct IssueRow {
|
|
pub gitlab_id: i64,
|
|
pub iid: i64,
|
|
pub project_id: i64,
|
|
pub title: String,
|
|
pub description: Option<String>,
|
|
pub state: String,
|
|
pub author_username: String,
|
|
pub created_at: i64,
|
|
pub updated_at: i64,
|
|
pub web_url: String,
|
|
pub due_date: Option<String>,
|
|
pub milestone_title: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct MilestoneRow {
|
|
pub gitlab_id: i64,
|
|
pub project_id: i64,
|
|
pub iid: i64,
|
|
pub title: String,
|
|
pub description: Option<String>,
|
|
pub state: Option<String>,
|
|
pub due_date: Option<String>,
|
|
pub web_url: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct IssueWithMetadata {
|
|
pub issue: IssueRow,
|
|
pub label_names: Vec<String>,
|
|
pub assignee_usernames: Vec<String>,
|
|
pub milestone: Option<MilestoneRow>,
|
|
}
|
|
|
|
fn parse_timestamp(ts: &str) -> Result<i64, TransformError> {
|
|
DateTime::parse_from_rfc3339(ts)
|
|
.map(|dt| dt.timestamp_millis())
|
|
.map_err(|e| TransformError::TimestampParse(ts.to_string(), e.to_string()))
|
|
}
|
|
|
|
pub fn transform_issue(issue: &GitLabIssue) -> Result<IssueWithMetadata, TransformError> {
|
|
let created_at = parse_timestamp(&issue.created_at)?;
|
|
let updated_at = parse_timestamp(&issue.updated_at)?;
|
|
|
|
let assignee_usernames: Vec<String> =
|
|
issue.assignees.iter().map(|a| a.username.clone()).collect();
|
|
|
|
let milestone_title = issue.milestone.as_ref().map(|m| m.title.clone());
|
|
|
|
let milestone = issue.milestone.as_ref().map(|m| MilestoneRow {
|
|
gitlab_id: m.id,
|
|
project_id: m.project_id.unwrap_or(issue.project_id),
|
|
iid: m.iid,
|
|
title: m.title.clone(),
|
|
description: m.description.clone(),
|
|
state: m.state.clone(),
|
|
due_date: m.due_date.clone(),
|
|
web_url: m.web_url.clone(),
|
|
});
|
|
|
|
Ok(IssueWithMetadata {
|
|
issue: IssueRow {
|
|
gitlab_id: issue.id,
|
|
iid: issue.iid,
|
|
project_id: issue.project_id,
|
|
title: issue.title.clone(),
|
|
description: issue.description.clone(),
|
|
state: issue.state.clone(),
|
|
author_username: issue.author.username.clone(),
|
|
created_at,
|
|
updated_at,
|
|
web_url: issue.web_url.clone(),
|
|
due_date: issue.due_date.clone(),
|
|
milestone_title,
|
|
},
|
|
label_names: issue.labels.clone(),
|
|
assignee_usernames,
|
|
milestone,
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "issue_tests.rs"]
|
|
mod tests;
|