1use crate::core::{Artifact, ArtifactKind, ArtifactMetadata, MarkerKind, ProjectKind, ProjectMarker};
4use crate::error::Result;
5use crate::plugins::Plugin;
6use std::path::Path;
7
8pub struct MavenPlugin;
10
11impl Plugin for MavenPlugin {
12 fn id(&self) -> &'static str {
13 "maven"
14 }
15
16 fn name(&self) -> &'static str {
17 "Java (Maven)"
18 }
19
20 fn supported_kinds(&self) -> &[ProjectKind] {
21 &[ProjectKind::JavaMaven]
22 }
23
24 fn markers(&self) -> Vec<ProjectMarker> {
25 vec![ProjectMarker {
26 indicator: MarkerKind::File("pom.xml"),
27 kind: ProjectKind::JavaMaven,
28 priority: 60,
29 }]
30 }
31
32 fn detect(&self, path: &Path) -> Option<ProjectKind> {
33 if path.join("pom.xml").is_file() {
34 Some(ProjectKind::JavaMaven)
35 } else {
36 None
37 }
38 }
39
40 fn find_artifacts(&self, project_root: &Path) -> Result<Vec<Artifact>> {
41 let mut artifacts = Vec::new();
42
43 let target = project_root.join("target");
45 if target.exists() {
46 artifacts.push(Artifact {
47 path: target,
48 kind: ArtifactKind::BuildOutput,
49 size: 0,
50 file_count: 0,
51 age: None,
52 metadata: ArtifactMetadata {
53 restorable: true,
54 restore_command: Some("mvn compile".into()),
55 lockfile: Some(project_root.join("pom.xml")),
56 restore_time_estimate: Some(60),
57 ..Default::default()
58 },
59 });
60 }
61
62 Ok(artifacts)
63 }
64
65 fn cleanable_dirs(&self) -> &[&'static str] {
66 &["target"]
67 }
68
69 fn priority(&self) -> u8 {
70 60
71 }
72}
73
74pub struct GradlePlugin;
76
77impl Plugin for GradlePlugin {
78 fn id(&self) -> &'static str {
79 "gradle"
80 }
81
82 fn name(&self) -> &'static str {
83 "Java (Gradle)"
84 }
85
86 fn supported_kinds(&self) -> &[ProjectKind] {
87 &[ProjectKind::JavaGradle]
88 }
89
90 fn markers(&self) -> Vec<ProjectMarker> {
91 vec![
92 ProjectMarker {
93 indicator: MarkerKind::File("build.gradle"),
94 kind: ProjectKind::JavaGradle,
95 priority: 60,
96 },
97 ProjectMarker {
98 indicator: MarkerKind::File("build.gradle.kts"),
99 kind: ProjectKind::JavaGradle,
100 priority: 60,
101 },
102 ProjectMarker {
103 indicator: MarkerKind::File("settings.gradle"),
104 kind: ProjectKind::JavaGradle,
105 priority: 55,
106 },
107 ProjectMarker {
108 indicator: MarkerKind::File("settings.gradle.kts"),
109 kind: ProjectKind::JavaGradle,
110 priority: 55,
111 },
112 ]
113 }
114
115 fn detect(&self, path: &Path) -> Option<ProjectKind> {
116 if path.join("build.gradle").is_file()
117 || path.join("build.gradle.kts").is_file()
118 || path.join("settings.gradle").is_file()
119 || path.join("settings.gradle.kts").is_file()
120 {
121 Some(ProjectKind::JavaGradle)
122 } else {
123 None
124 }
125 }
126
127 fn find_artifacts(&self, project_root: &Path) -> Result<Vec<Artifact>> {
128 let mut artifacts = Vec::new();
129
130 let build = project_root.join("build");
132 if build.exists() {
133 artifacts.push(Artifact {
134 path: build,
135 kind: ArtifactKind::BuildOutput,
136 size: 0,
137 file_count: 0,
138 age: None,
139 metadata: ArtifactMetadata {
140 restorable: true,
141 restore_command: Some("./gradlew build".into()),
142 ..Default::default()
143 },
144 });
145 }
146
147 let gradle_cache = project_root.join(".gradle");
149 if gradle_cache.exists() {
150 artifacts.push(Artifact {
151 path: gradle_cache,
152 kind: ArtifactKind::Cache,
153 size: 0,
154 file_count: 0,
155 age: None,
156 metadata: ArtifactMetadata::default(),
157 });
158 }
159
160 let out = project_root.join("out");
162 if out.exists() {
163 artifacts.push(Artifact {
164 path: out,
165 kind: ArtifactKind::BuildOutput,
166 size: 0,
167 file_count: 0,
168 age: None,
169 metadata: ArtifactMetadata::restorable("./gradlew build"),
170 });
171 }
172
173 Ok(artifacts)
174 }
175
176 fn cleanable_dirs(&self) -> &[&'static str] {
177 &["build", ".gradle", "out"]
178 }
179
180 fn priority(&self) -> u8 {
181 60
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188 use tempfile::TempDir;
189
190 #[test]
191 fn test_detect_maven() {
192 let temp = TempDir::new().unwrap();
193 std::fs::write(
194 temp.path().join("pom.xml"),
195 r#"<project></project>"#,
196 )
197 .unwrap();
198
199 let plugin = MavenPlugin;
200 assert_eq!(plugin.detect(temp.path()), Some(ProjectKind::JavaMaven));
201 }
202
203 #[test]
204 fn test_detect_gradle() {
205 let temp = TempDir::new().unwrap();
206 std::fs::write(temp.path().join("build.gradle"), "").unwrap();
207
208 let plugin = GradlePlugin;
209 assert_eq!(plugin.detect(temp.path()), Some(ProjectKind::JavaGradle));
210 }
211
212 #[test]
213 fn test_detect_gradle_kts() {
214 let temp = TempDir::new().unwrap();
215 std::fs::write(temp.path().join("build.gradle.kts"), "").unwrap();
216
217 let plugin = GradlePlugin;
218 assert_eq!(plugin.detect(temp.path()), Some(ProjectKind::JavaGradle));
219 }
220
221 #[test]
222 fn test_find_gradle_artifacts() {
223 let temp = TempDir::new().unwrap();
224 std::fs::write(temp.path().join("build.gradle"), "").unwrap();
225 std::fs::create_dir(temp.path().join("build")).unwrap();
226 std::fs::create_dir(temp.path().join(".gradle")).unwrap();
227
228 let plugin = GradlePlugin;
229 let artifacts = plugin.find_artifacts(temp.path()).unwrap();
230
231 assert_eq!(artifacts.len(), 2);
232 }
233}