Skip to main content

git_mover/
platform.rs

1//! This module contains the Platform trait and `PlatformType` enum.
2
3use crate::{
4    errors::GitMoverError,
5    utils::{check_ssh_access, Repo},
6};
7use serde::Deserialize;
8use std::pin::Pin;
9
10/// The Platform trait is used to interact with different git platforms.
11pub trait Platform: Sync + Send {
12    /// Check git access
13    fn check_git_access(
14        &self,
15    ) -> Pin<Box<dyn std::future::Future<Output = Result<(), GitMoverError>> + Send + '_>> {
16        let url_ssh = format!("git@{}", self.get_remote_url());
17        Box::pin(async move {
18            let (stdout, stderr) = check_ssh_access(&url_ssh).await?;
19            if stdout.contains(self.get_username()) || stderr.contains(self.get_username()) {
20                Ok(())
21            } else {
22                let stdout_str = if stdout.is_empty() {
23                    ""
24                } else {
25                    &format!("stdout={} ", stdout.trim())
26                };
27                let stderr_str = if stderr.is_empty() {
28                    ""
29                } else {
30                    &format!("stderr={} ", stderr.trim())
31                };
32                Err(GitMoverError::new(format!(
33                    "Cannot access to {url_ssh}: {stdout_str}{stderr_str}for {}",
34                    self.get_type()
35                )))
36            }
37        })
38    }
39
40    /// Create a new repository on the platform.
41    fn create_repo(
42        &self,
43        repo: Repo,
44    ) -> Pin<Box<dyn std::future::Future<Output = Result<(), GitMoverError>> + Send + '_>>;
45
46    /// Get a repository from the platform.
47    fn get_repo(
48        &self,
49        name: &str,
50    ) -> Pin<Box<dyn std::future::Future<Output = Result<Repo, GitMoverError>> + Send + '_>>;
51
52    /// Edit a repository on the platform.
53    fn edit_repo(
54        &self,
55        repo: Repo,
56    ) -> Pin<Box<dyn std::future::Future<Output = Result<(), GitMoverError>> + Send + '_>>;
57
58    /// Get all repositories from the platform.
59    fn get_all_repos(
60        &self,
61    ) -> Pin<Box<dyn std::future::Future<Output = Result<Vec<Repo>, GitMoverError>> + Send>>;
62
63    /// Delete a repository from the platform.
64    fn delete_repo(
65        &self,
66        name: &str,
67    ) -> Pin<Box<dyn std::future::Future<Output = Result<(), GitMoverError>> + Send + '_>>;
68
69    /// Get the username of the platform.
70    fn get_username(&self) -> &str;
71
72    /// Get the platform type.
73    fn get_remote_url(&self) -> String;
74
75    /// get the type of the Platform
76    fn get_type(&self) -> PlatformType;
77}
78
79/// The `PlatformType` enum is used to specify the platform type.
80#[derive(Debug, Clone, PartialEq, Deserialize)]
81pub enum PlatformType {
82    /// Gitlab platform
83    Gitlab,
84
85    /// Github platform
86    Github,
87
88    /// Codeberg platform
89    Codeberg,
90}
91
92impl std::fmt::Display for PlatformType {
93    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94        match self {
95            PlatformType::Gitlab => write!(f, "gitlab"),
96            PlatformType::Github => write!(f, "github"),
97            PlatformType::Codeberg => write!(f, "codeberg"),
98        }
99    }
100}
101
102impl From<String> for PlatformType {
103    fn from(s: String) -> Self {
104        match s.to_lowercase().as_str() {
105            "gitlab" => PlatformType::Gitlab,
106            "github" => PlatformType::Github,
107            "codeberg" => PlatformType::Codeberg,
108            _ => panic!("Invalid platform"),
109        }
110    }
111}