Skip to main content

relay_knowledge/application/code_repository/update/
mod.rs

1//! Coordinates one durable, commit-to-commit repository update request.
2
3use crate::{
4    api::{
5        ApiError, CodeRepositoryIndexStartResponse, CodeRepositoryUpdateRequest, RequestContext,
6    },
7    application::RelayKnowledgeService,
8    domain::{
9        CodeIndexMode, CodeIndexRequest, CodeRepositorySelector, FreshnessPolicy,
10        clean_git_commit_from_snapshot_identity,
11    },
12};
13
14impl RelayKnowledgeService {
15    /// Resolves optional moving refs and submits one durable incremental index task.
16    pub async fn start_code_repository_update(
17        &self,
18        request: CodeRepositoryUpdateRequest,
19        context: RequestContext,
20    ) -> Result<CodeRepositoryIndexStartResponse, ApiError> {
21        let head_ref = request.head_ref.unwrap_or_else(|| "HEAD".to_owned());
22        let selector = CodeRepositorySelector::new(
23            request.repository,
24            head_ref.clone(),
25            Vec::new(),
26            Vec::new(),
27        )
28        .map_err(|error| ApiError::invalid_argument(error.to_string()))?;
29        let status = self
30            .code_repository_status(selector.clone(), context.clone())
31            .await?
32            .status;
33        let base_ref = resolve_update_base(
34            request.base_ref,
35            status.last_indexed_commit.as_deref(),
36            &status.alias,
37        )
38        .map_err(ApiError::invalid_argument)?;
39        let mode = CodeIndexMode::incremental(base_ref, head_ref)
40            .map_err(|error| ApiError::invalid_argument(error.to_string()))?;
41
42        self.start_code_repository_index(
43            CodeIndexRequest {
44                repository: selector,
45                mode,
46                workspace_detection: Default::default(),
47                freshness_policy: FreshnessPolicy::WaitUntilFresh,
48                reuse_historical: false,
49            },
50            context,
51        )
52        .await
53    }
54}
55
56fn resolve_update_base(
57    explicit_base: Option<String>,
58    last_indexed_commit: Option<&str>,
59    alias: &str,
60) -> Result<String, String> {
61    if let Some(explicit_base) = explicit_base {
62        return Ok(explicit_base);
63    }
64    last_indexed_commit
65        .and_then(clean_git_commit_from_snapshot_identity)
66        .map(str::to_owned)
67        .ok_or_else(|| {
68            format!(
69                "code repository '{alias}' has no completed clean Git snapshot; run repo index --ref HEAD before repo update, or pass an explicit --base for a filesystem snapshot"
70            )
71        })
72}
73
74#[cfg(test)]
75#[path = "mod_tests.rs"]
76mod tests;