Skip to main content

interprex_test/
code_hosting.rs

1use async_trait::async_trait;
2use interprex::{
3    AppliedSourceRequirements, AppliedSourceRequirementsProvider, CodeHostingProvider, CommitRange,
4    ProviderError, Repository, RepositoryFacts, RepositorySettings, Result,
5    SourceCodeConfigurationProvider,
6};
7use secrecy::SecretString;
8
9use crate::state::{FakeProvider, missing};
10
11#[async_trait]
12impl CodeHostingProvider for FakeProvider {
13    async fn repository(&self, repository: &Repository) -> Result<RepositoryFacts> {
14        self.state
15            .read()
16            .await
17            .repositories
18            .get(repository)
19            .map(|(facts, _)| facts.clone())
20            .ok_or_else(|| missing(repository.to_string()))
21    }
22
23    async fn settings(&self, repository: &Repository) -> Result<RepositorySettings> {
24        self.state
25            .read()
26            .await
27            .repositories
28            .get(repository)
29            .map(|(_, settings)| settings.clone())
30            .ok_or_else(|| missing(repository.to_string()))
31    }
32
33    async fn apply_settings(
34        &self,
35        repository: &Repository,
36        settings: &RepositorySettings,
37    ) -> Result<RepositorySettings> {
38        let mut state = self.state.write().await;
39        let (_, current) = state
40            .repositories
41            .get_mut(repository)
42            .ok_or_else(|| missing(repository.to_string()))?;
43        *current = settings.clone();
44        Ok(settings.clone())
45    }
46
47    async fn put_secret(
48        &self,
49        repository: &Repository,
50        name: &str,
51        _value: SecretString,
52    ) -> Result<()> {
53        self.state
54            .write()
55            .await
56            .secret_names
57            .entry(repository.clone())
58            .or_default()
59            .push(name.to_owned());
60        Ok(())
61    }
62}
63
64#[async_trait]
65impl SourceCodeConfigurationProvider for FakeProvider {
66    type Ruleset = serde_json::Value;
67
68    async fn read_rulesets(&self, _repository: &Repository) -> Result<Vec<Self::Ruleset>> {
69        Err(unsupported("read source rulesets"))
70    }
71
72    async fn apply_ruleset(
73        &self,
74        _repository: &Repository,
75        _ruleset: &Self::Ruleset,
76    ) -> Result<Self::Ruleset> {
77        Err(unsupported("apply source ruleset"))
78    }
79}
80
81#[async_trait]
82impl AppliedSourceRequirementsProvider for FakeProvider {
83    async fn applied_requirements(
84        &self,
85        repository: &Repository,
86        target_branch: &str,
87        commit_range: &CommitRange,
88    ) -> Result<AppliedSourceRequirements> {
89        for (value, field) in [
90            (target_branch, "target branch"),
91            (&commit_range.base_sha, "base sha"),
92            (&commit_range.head_sha, "head sha"),
93        ] {
94            if value.is_empty() {
95                return Err(ProviderError::InvalidInput {
96                    provider: "fake",
97                    fact: format!("{field} must not be empty"),
98                });
99            }
100        }
101        let key = (
102            repository.clone(),
103            target_branch.to_owned(),
104            commit_range.base_sha.clone(),
105            commit_range.head_sha.clone(),
106        );
107        let state = self.state.read().await;
108        if let Some(error) = state.applied_requirement_errors.get(&key) {
109            return Err(error.clone());
110        }
111        state
112            .applied_requirements
113            .get(&key)
114            .cloned()
115            .ok_or_else(|| ProviderError::NotFound {
116                entity: format!(
117                    "applied requirements for {repository}:{target_branch} at {}..{}",
118                    commit_range.base_sha, commit_range.head_sha
119                ),
120            })
121    }
122}
123
124fn unsupported(operation: &'static str) -> ProviderError {
125    ProviderError::Unsupported {
126        provider: "fake",
127        operation,
128    }
129}