1use crate::core::{Artifact, ArtifactKind, ArtifactMetadata, MarkerKind, ProjectKind, ProjectMarker};
4use crate::error::Result;
5use crate::plugins::Plugin;
6use std::path::Path;
7
8pub struct GoPlugin;
10
11impl Plugin for GoPlugin {
12 fn id(&self) -> &'static str {
13 "go"
14 }
15
16 fn name(&self) -> &'static str {
17 "Go"
18 }
19
20 fn supported_kinds(&self) -> &[ProjectKind] {
21 &[ProjectKind::Go]
22 }
23
24 fn markers(&self) -> Vec<ProjectMarker> {
25 vec![
26 ProjectMarker {
27 indicator: MarkerKind::File("go.mod"),
28 kind: ProjectKind::Go,
29 priority: 60,
30 },
31 ProjectMarker {
32 indicator: MarkerKind::File("go.sum"),
33 kind: ProjectKind::Go,
34 priority: 55,
35 },
36 ]
37 }
38
39 fn detect(&self, path: &Path) -> Option<ProjectKind> {
40 if path.join("go.mod").is_file() {
41 Some(ProjectKind::Go)
42 } else {
43 None
44 }
45 }
46
47 fn find_artifacts(&self, project_root: &Path) -> Result<Vec<Artifact>> {
48 let mut artifacts = Vec::new();
49
50 let vendor = project_root.join("vendor");
52 if vendor.exists() {
53 artifacts.push(Artifact {
54 path: vendor,
55 kind: ArtifactKind::Dependencies,
56 size: 0,
57 file_count: 0,
58 age: None,
59 metadata: ArtifactMetadata {
60 restorable: true,
61 restore_command: Some("go mod vendor".into()),
62 lockfile: Some(project_root.join("go.sum")),
63 ..Default::default()
64 },
65 });
66 }
67
68 let bin = project_root.join("bin");
70 if bin.exists() {
71 artifacts.push(Artifact {
72 path: bin,
73 kind: ArtifactKind::BuildOutput,
74 size: 0,
75 file_count: 0,
76 age: None,
77 metadata: ArtifactMetadata::restorable("go build"),
78 });
79 }
80
81 let dist = project_root.join("dist");
83 if dist.exists() {
84 artifacts.push(Artifact {
85 path: dist,
86 kind: ArtifactKind::BuildOutput,
87 size: 0,
88 file_count: 0,
89 age: None,
90 metadata: ArtifactMetadata::restorable("go build"),
91 });
92 }
93
94 Ok(artifacts)
95 }
96
97 fn cleanable_dirs(&self) -> &[&'static str] {
98 &["vendor"]
99 }
100
101 fn priority(&self) -> u8 {
102 55
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109 use tempfile::TempDir;
110
111 #[test]
112 fn test_detect_go() {
113 let temp = TempDir::new().unwrap();
114 std::fs::write(
115 temp.path().join("go.mod"),
116 "module example.com/test\n\ngo 1.21\n",
117 )
118 .unwrap();
119
120 let plugin = GoPlugin;
121 assert_eq!(plugin.detect(temp.path()), Some(ProjectKind::Go));
122 }
123
124 #[test]
125 fn test_find_artifacts() {
126 let temp = TempDir::new().unwrap();
127 std::fs::write(temp.path().join("go.mod"), "module test").unwrap();
128 std::fs::create_dir(temp.path().join("vendor")).unwrap();
129
130 let plugin = GoPlugin;
131 let artifacts = plugin.find_artifacts(temp.path()).unwrap();
132
133 assert_eq!(artifacts.len(), 1);
134 assert_eq!(artifacts[0].name(), "vendor");
135 }
136}