Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/autodetect/autodetect.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func detectors(path string) []detector.Detector {
return []detector.Detector{
&detector.PythonDetector{Root: path},
&detector.PoetryDetector{Root: path},
&detector.GoDetector{Root: path},
}
}

Expand Down
53 changes: 53 additions & 0 deletions pkg/autodetect/detector/go.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package detector

import (
"context"
"os"
"path/filepath"
"regexp"
)

type GoDetector struct {
Root string
}

var _ Detector = &GoDetector{}

func (d *GoDetector) Relevance(path string) (float64, error) {
goModPath := filepath.Join(d.Root, "go.mod")
_, err := os.Stat(goModPath)
if err == nil {
return 1.0, nil
}
if os.IsNotExist(err) {
return 0, nil
}
return 0, err
}

func (d *GoDetector) Packages(ctx context.Context) ([]string, error) {
goModPath := filepath.Join(d.Root, "go.mod")
goModContent, err := os.ReadFile(goModPath)
if err != nil {
return nil, err
}

// Parse the Go version from go.mod
goVersion := parseGoVersion(string(goModContent))
if goVersion != "" {
return []string{"go@" + goVersion}, nil
}
return []string{"go@latest"}, nil
}

func parseGoVersion(goModContent string) string {
// Use a regular expression to find the Go version directive
re := regexp.MustCompile(`(?m)^go\s+(\d+\.\d+(\.\d+)?)`)
match := re.FindStringSubmatch(goModContent)

if len(match) >= 2 {
return match[1]
}

return ""
}
103 changes: 103 additions & 0 deletions pkg/autodetect/detector/go_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package detector

import (
"context"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
)

func TestGoDetectorRelevance(t *testing.T) {
tempDir := t.TempDir()
detector := &GoDetector{Root: tempDir}

t.Run("No go.mod file", func(t *testing.T) {
relevance, err := detector.Relevance(tempDir)
assert.NoError(t, err)
assert.Equal(t, 0.0, relevance)
})

t.Run("With go.mod file", func(t *testing.T) {
err := os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte("module example.com"), 0o644)
assert.NoError(t, err)

relevance, err := detector.Relevance(tempDir)
assert.NoError(t, err)
assert.Equal(t, 1.0, relevance)
})
}

func TestGoDetectorPackages(t *testing.T) {
tempDir := t.TempDir()
detector := &GoDetector{Root: tempDir}

t.Run("No go.mod file", func(t *testing.T) {
packages, err := detector.Packages(context.Background())
assert.Error(t, err)
assert.Nil(t, packages)
})

t.Run("With go.mod file and no version", func(t *testing.T) {
err := os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte("module example.com"), 0o644)
assert.NoError(t, err)

packages, err := detector.Packages(context.Background())
assert.NoError(t, err)
assert.Equal(t, []string{"go@latest"}, packages)
})

t.Run("With go.mod file and specific version", func(t *testing.T) {
goModContent := `
module example.com

go 1.18
`
err := os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte(goModContent), 0o644)
assert.NoError(t, err)

packages, err := detector.Packages(context.Background())
assert.NoError(t, err)
assert.Equal(t, []string{"[email protected]"}, packages)
})
}

func TestParseGoVersion(t *testing.T) {
testCases := []struct {
name string
content string
expected string
}{
{
name: "No version",
content: "module example.com",
expected: "",
},
{
name: "With version",
content: `
module example.com

go 1.18
`,
expected: "1.18",
},
{
name: "With patch version",
content: `
module example.com

go 1.18.3
`,
expected: "1.18.3",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
version := parseGoVersion(tc.content)
assert.Equal(t, tc.expected, version)
})
}
}
Loading