Skip to main content

relay_knowledge/domain/code/repository/
registration.rs

1use serde::{Deserialize, Serialize};
2
3use super::super::{
4    CodeWorkspaceDetectionConfig, DomainError, FreshnessPolicy, error::required_text,
5};
6use super::validation::{checked_u32, normalize_filter_list};
7
8/// Inclusive byte or line range for repository code index rows.
9#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10pub struct RepositoryCodeRange {
11    pub start: u32,
12    pub end: u32,
13}
14
15impl RepositoryCodeRange {
16    /// Creates an ordered range using one-based lines or zero-based bytes.
17    pub fn new(field: &'static str, start: usize, end: usize) -> Result<Self, DomainError> {
18        if end < start {
19            return Err(DomainError::invalid(
20                field,
21                "end must be greater than or equal to start",
22            ));
23        }
24
25        Ok(Self {
26            start: checked_u32(field, start)?,
27            end: checked_u32(field, end)?,
28        })
29    }
30}
31
32/// Code repository identity persisted after registration.
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
34pub struct CodeRepositoryRegistration {
35    pub repository_id: String,
36    pub alias: String,
37    pub root_path: String,
38    pub path_filters: Vec<String>,
39    pub language_filters: Vec<String>,
40}
41
42impl CodeRepositoryRegistration {
43    /// Validates a repository registration before storage persists it.
44    pub fn new(
45        repository_id: impl Into<String>,
46        alias: impl Into<String>,
47        root_path: impl Into<String>,
48        path_filters: Vec<String>,
49        language_filters: Vec<String>,
50    ) -> Result<Self, DomainError> {
51        Ok(Self {
52            repository_id: required_text("repository_id", repository_id)?,
53            alias: required_text("alias", alias)?,
54            root_path: required_text("root_path", root_path)?,
55            path_filters: normalize_filter_list("path_filter", path_filters)?,
56            language_filters: normalize_filter_list("language_filter", language_filters)?,
57        })
58    }
59}
60
61/// Repository selector accepted by code index and retrieval APIs.
62#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
63pub struct CodeRepositorySelector {
64    pub repository: String,
65    pub ref_selector: String,
66    pub path_filters: Vec<String>,
67    pub language_filters: Vec<String>,
68}
69
70impl CodeRepositorySelector {
71    /// Validates a code repository selector with an explicit ref.
72    pub fn new(
73        repository: impl Into<String>,
74        ref_selector: impl Into<String>,
75        path_filters: Vec<String>,
76        language_filters: Vec<String>,
77    ) -> Result<Self, DomainError> {
78        Ok(Self {
79            repository: required_text("repository", repository)?,
80            ref_selector: required_text("ref_selector", ref_selector)?,
81            path_filters: normalize_filter_list("path_filter", path_filters)?,
82            language_filters: normalize_filter_list("language_filter", language_filters)?,
83        })
84    }
85}
86
87/// Code index mode tied to Git snapshots or diffs.
88#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
89#[serde(rename_all = "snake_case")]
90pub enum CodeIndexMode {
91    Full,
92    Incremental { base_ref: String, head_ref: String },
93    WorktreeOverlay,
94}
95
96impl CodeIndexMode {
97    /// Validates incremental refs and preserves the mode contract.
98    pub fn incremental(
99        base_ref: impl Into<String>,
100        head_ref: impl Into<String>,
101    ) -> Result<Self, DomainError> {
102        Ok(Self::Incremental {
103            base_ref: required_text("base_ref", base_ref)?,
104            head_ref: required_text("head_ref", head_ref)?,
105        })
106    }
107}
108
109#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
110pub struct CodeIndexRequest {
111    pub repository: CodeRepositorySelector,
112    pub mode: CodeIndexMode,
113    #[serde(default)]
114    pub workspace_detection: CodeWorkspaceDetectionConfig,
115    pub freshness_policy: FreshnessPolicy,
116}
117
118#[cfg(test)]
119#[path = "registration_tests.rs"]
120mod tests;