Skip to content

Commit

Permalink
feat: add go.sum and go.work to Go detection
Browse files Browse the repository at this point in the history
  • Loading branch information
BoscoDomingo committed Jan 3, 2025
1 parent b1694b5 commit a6cfe14
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 18 deletions.
49 changes: 37 additions & 12 deletions src/segments/golang.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package segments

import (
"github.com/jandedobbeleer/oh-my-posh/src/properties"
"regexp"

"github.com/jandedobbeleer/oh-my-posh/src/properties"
"golang.org/x/mod/modfile"
)

Expand All @@ -11,15 +12,16 @@ type Golang struct {
}

const (
ParseModFile properties.Property = "parse_mod_file"
ParseModFile properties.Property = "parse_mod_file"
ParseGoWorkFile properties.Property = "parse_go_work_file"
)

func (g *Golang) Template() string {
return languageTemplate
}

func (g *Golang) Enabled() bool {
g.extensions = []string{"*.go", "go.mod"}
g.extensions = []string{"*.go", "go.mod", "go.sum", "go.work"}
g.commands = []*cmd{
{
regex: `(?P<version>((?P<major>[0-9]+).(?P<minor>[0-9]+)(.(?P<patch>[0-9]+))?))`,
Expand All @@ -36,21 +38,44 @@ func (g *Golang) Enabled() bool {
return g.language.Enabled()
}

// getVersion returns the version of the Go language
// It first checks if the go.mod file is present and if it is, it parses the file to get the version
// If the go.mod file is not present, it checks if the go.work file is present and if it is, it parses the file to get the version
// If neither file is present, it returns an empty string
func (g *Golang) getVersion() (string, error) {
if !g.props.GetBool(ParseModFile, false) {
if !g.props.GetBool(ParseModFile, false) && !g.props.GetBool(ParseGoWorkFile, false) {
return "", nil
}

gomod, err := g.language.env.HasParentFilePath("go.mod", false)
if err != nil {
return "", nil
if g.props.GetBool(ParseModFile, false) {
gomod, err := g.language.env.HasParentFilePath("go.mod", false)
if err != nil {
return "", nil
}

contents := g.language.env.FileContent(gomod.Path)
file, err := modfile.Parse(gomod.Path, []byte(contents), nil)
if err != nil {
return "", err
}

if file.Go.Version != "" {
return file.Go.Version, nil
}
}

contents := g.language.env.FileContent(gomod.Path)
file, err := modfile.Parse(gomod.Path, []byte(contents), nil)
if err != nil {
return "", err
if g.props.GetBool(ParseGoWorkFile, false) {
goWork, err := g.language.env.HasParentFilePath("go.work", false)
if err != nil {
return "", err
}

contents := g.language.env.FileContent(goWork.Path)
goVersionRegex := regexp.MustCompile(`go (\d(\.\d{1,2})?(\.\d{1,2})?)`)
if version := goVersionRegex.FindStringSubmatch(contents); version != nil {
return version[1], nil
}
}

return file.Go.Version, nil
return "", nil
}
60 changes: 54 additions & 6 deletions src/segments/golang_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ import (

func TestGolang(t *testing.T) {
cases := []struct {
Case string
ExpectedString string
Version string
ParseModFile bool
HasModFileInParentDir bool
InvalidModfile bool
Case string
ExpectedString string
Version string
ParseModFile bool
HasModFileInParentDir bool
InvalidModfile bool
ParseGoWorkFile bool
HasGoWorkFileInParentDir bool
InvalidGoWorkFile bool
}{
{Case: "Go 1.15", ExpectedString: "1.15.8", Version: "go version go1.15.8 darwin/amd64"},
{Case: "Go 1.16", ExpectedString: "1.16", Version: "go version go1.16 darwin/amd64"},
Expand All @@ -31,6 +34,30 @@ func TestGolang(t *testing.T) {
ExpectedString: "1.16",
Version: "go version go1.16 darwin/amd64",
},
{Case: "go.work file", ParseGoWorkFile: true, HasGoWorkFileInParentDir: true, ExpectedString: "1.21"},
{
Case: "invalid go.work file fallback",
ParseGoWorkFile: true,
HasGoWorkFileInParentDir: true,
InvalidGoWorkFile: true,
ExpectedString: "1.16",
Version: "go version go1.16 darwin/amd64",
},
{
Case: "go.work file with go.mod file uses go.mod's version",
ParseModFile: true,
HasModFileInParentDir: true,
ParseGoWorkFile: true,
HasGoWorkFileInParentDir: true,
ExpectedString: "1.22.3",
},
{
Case: "missing both go.mod and go.work file fallback",
ParseModFile: true,
ParseGoWorkFile: true,
ExpectedString: "1.16",
Version: "go version go1.16 darwin/amd64",
},
}
for _, tc := range cases {
params := &mockedLanguageParams{
Expand Down Expand Up @@ -61,6 +88,27 @@ func TestGolang(t *testing.T) {
}
env.On("FileContent", fileInfo.Path).Return(content)
}
if tc.ParseGoWorkFile {
props[ParseGoWorkFile] = tc.ParseGoWorkFile
fileInfo := &runtime.FileInfo{
Path: "../test/go.work",
ParentFolder: "./",
IsDir: false,
}
var err error
if !tc.HasGoWorkFileInParentDir {
err = errors.New("no match")
}
env.On("HasParentFilePath", "go.work", false).Return(fileInfo, err)
var content string
if tc.InvalidGoWorkFile {
content = "invalid go.work file"
} else {
tmp, _ := os.ReadFile(fileInfo.Path)
content = string(tmp)
}
env.On("FileContent", fileInfo.Path).Return(content)
}
g := &Golang{}
g.Init(props, env)
assert.True(t, g.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
Expand Down
6 changes: 6 additions & 0 deletions themes/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,12 @@
"description": "Parse go.mod file instead of calling out to go to improve performance.",
"default": false
},
"parse_go_work_file": {
"type": "boolean",
"title": "Parse go.work file",
"description": "Parse go.work file instead of calling out to go to improve performance.",
"default": false
},
"extensions": {
"type": "array",
"title": "Extensions",
Expand Down
1 change: 1 addition & 0 deletions website/docs/segments/languages/golang.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import Config from "@site/src/components/Config.js";
| `display_mode` | `string` | `context` | <ul><li>`always`: the segment is always displayed</li><li>`files`: the segment is only displayed when file `extensions` listed are present</li><li>`context`: displays the segment when the environment or files is active</li></ul> |
| `version_url_template` | `string` | | a go [text/template][go-text-template] [template][templates] that creates the URL of the version info / release notes |
| `parse_mod_file` | `boolean` | `false` | parse the go.mod file instead of calling `go version` |
| `parse_go_work_file` | `boolean` | `false` | parse the go.work file instead of calling `go version` |
| `extensions` | `[]string` | `*.go, go.mod` | allows to override the default list of file extensions to validate |
| `folders` | `[]string` | | allows to override the list of folder names to validate |

Expand Down

0 comments on commit a6cfe14

Please sign in to comment.