skootrs_lib/service/
ecosystem.rs

1#![allow(clippy::module_name_repetitions)]
2
3use std::process::Command;
4
5use tracing::info;
6
7use skootrs_model::skootrs::{
8    EcosystemInitializeParams, GoParams, InitializedEcosystem, InitializedGo, InitializedMaven,
9    InitializedSource, MavenParams, SkootError,
10};
11
12/// The `EcosystemService` trait provides an interface for initializing and managing a project's ecosystem.
13/// An ecosystem is the language or packaging ecosystem that a project is built in, such as Maven or Go.
14pub trait EcosystemService {
15    /// Initializes a project's ecosystem. This involves setting up the project's package or build system.
16    /// For example `go mod init` for Go.
17    ///
18    /// # Errors
19    ///
20    /// Returns an error if the ecosystem can't be initialized.
21    fn initialize(
22        &self,
23        params: EcosystemInitializeParams,
24        source: InitializedSource,
25    ) -> Result<InitializedEcosystem, SkootError>;
26}
27
28/// The `LocalEcosystemService` struct provides an implementation of the `EcosystemService` trait for initializing 
29/// and managing a project's ecosystem on the local machine.
30#[derive(Debug)]
31pub struct LocalEcosystemService {}
32
33impl EcosystemService for LocalEcosystemService {
34    fn initialize(
35        &self,
36        params: EcosystemInitializeParams,
37        source: InitializedSource,
38    ) -> Result<InitializedEcosystem, SkootError> {
39        match params {
40            EcosystemInitializeParams::Maven(m) => {
41                LocalMavenEcosystemHandler::initialize(&source.path, &m)?;
42                Ok(InitializedEcosystem::Maven(InitializedMaven {
43                    group_id: m.group_id,
44                    artifact_id: m.artifact_id,
45                }))
46            }
47            EcosystemInitializeParams::Go(g) => {
48                LocalGoEcosystemHandler::initialize(&source.path, &g)?;
49                Ok(InitializedEcosystem::Go(InitializedGo {
50                    name: g.name,
51                    host: g.host,
52                }))
53            }
54        }
55    }
56}
57
58
59/// The `LocalMavenEcosystemHandler` struct represents a handler for initializing and managing a Maven 
60/// project on the local machine.
61struct LocalMavenEcosystemHandler {}
62
63impl LocalMavenEcosystemHandler {
64    /// Returns `Ok(())` if the Maven project initialization is successful,
65    /// otherwise returns an error.
66    fn initialize(path: &str, params: &MavenParams) -> Result<(), SkootError> {
67        let output = Command::new("mvn")
68            .arg("archetype:generate")
69            .arg(format!("-DgroupId={}", params.group_id))
70            .arg(format!("-DartifactId={}", params.artifact_id))
71            .arg("-DarchetypeArtifactId=maven-archetype-quickstart")
72            .arg("-DinteractiveMode=false")
73            .current_dir(path)
74            .output()?;
75        if output.status.success() {
76            info!("Initialized maven project for {}", params.artifact_id);
77            Ok(())
78        } else {
79            Err(Box::new(std::io::Error::new(
80                std::io::ErrorKind::Other,
81                "Failed to run mvn generate",
82            )))
83        }
84    }
85}
86
87/// The `LocalGoEcosystemHandler` struct represents a handler for initializing and managing a Go
88/// project on the local machine.
89struct LocalGoEcosystemHandler {}
90
91impl LocalGoEcosystemHandler {
92    /// Returns an error if the initialization of a Go module at the specified
93    /// path fails.
94    ///
95    /// # Arguments
96    ///
97    /// * `path` - The path where the Go module should be initialized.
98    fn initialize(path: &str, params: &GoParams) -> Result<(), SkootError> {
99        let output = Command::new("go")
100            .arg("mod")
101            .arg("init")
102            .arg(params.module())
103            .current_dir(path)
104            .output()?;
105        if output.status.success() {
106            info!("Initialized go module for {}", params.name);
107            Ok(())
108        } else {
109            Err(Box::new(std::io::Error::new(
110                std::io::ErrorKind::Other,
111                format!(
112                    "Failed to run go mod init: {}",
113                    String::from_utf8(output.stderr)?
114                ),
115            )))
116        }
117    }
118}
119
120#[cfg(test)]
121mod tests {
122    use super::*;
123    use tempdir::TempDir;
124
125    #[test]
126    fn test_local_maven_ecosystem_handler_initialize_success() {
127        let temp_dir = TempDir::new("test").unwrap();
128        let path = temp_dir.path().to_str().unwrap();
129        let params = MavenParams {
130            group_id: "com.example".to_string(),
131            artifact_id: "my-project".to_string(),
132        };
133
134        let result = LocalMavenEcosystemHandler::initialize(path, &params);
135
136        assert!(result.is_ok());
137    }
138
139    #[test]
140    fn test_local_maven_ecosystem_handler_initialize_failure() {
141        let temp_dir = TempDir::new("test").unwrap();
142        let path = temp_dir.path().to_str().unwrap();
143        let params = MavenParams {
144            // Invalid group ID
145            group_id: "".to_string(),
146            artifact_id: "my-project".to_string(),
147        };
148
149        let result = LocalMavenEcosystemHandler::initialize(path, &params);
150
151        assert!(result.is_err());
152    }
153
154    #[test]
155    fn test_local_go_ecosystem_handler_initialize_success() {
156        let temp_dir = TempDir::new("test").unwrap();
157        let path = temp_dir.path().to_str().unwrap();
158        let params = GoParams {
159            name: "my-project".to_string(),
160            host: "github.com".to_string(),
161        };
162
163        let result = LocalGoEcosystemHandler::initialize(path, &params);
164
165        assert!(result.is_ok());
166    }
167
168    #[test]
169    fn test_local_go_ecosystem_handler_initialize_failure() {
170        let temp_dir = TempDir::new("test").unwrap();
171        let path = temp_dir.path().to_str().unwrap();
172        let params = GoParams {
173            // Invalid project name
174            name: "".to_string(),
175            host: "github.com".to_string(),
176        };
177
178        let result = LocalGoEcosystemHandler::initialize(path, &params);
179
180        assert!(result.is_err());
181    }
182}