feat(project): cargo and poetry support

This commit is contained in:
Hadron Collider 2022-04-01 12:54:33 +03:00 committed by GitHub
parent af7db43889
commit b61ec064dd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 97 additions and 20 deletions

View file

@ -11,6 +11,8 @@ Display the current version of your project defined in the package file.
Supports: Supports:
- Node.js project (`package.json`) - Node.js project (`package.json`)
- Cargo project (`Cargo.toml`)
- Poetry project (`pyproject.toml`)
## Sample Configuration ## Sample Configuration
@ -21,7 +23,7 @@ Supports:
"powerline_symbol": "\uE0B0", "powerline_symbol": "\uE0B0",
"foreground": "#193549", "foreground": "#193549",
"background": "#ffeb3b", "background": "#ffeb3b",
"template": " {{ if .Error }}{{ .Error }}{{ else }}{{ if .Version }}\uf487 {{.Version}}{{ end }}{{ end }} " "template": " {{ if .Error }}{{ .Error }}{{ else }}{{ if .Version }}\uf487 {{.Version}}{{ end }} {{ if .Name }}{{ .Name }}{{ end }}{{ end }} "
} }
``` ```
@ -30,7 +32,7 @@ Supports:
:::note default template :::note default template
``` template ``` template
{{ if .Error }}{{ .Error }}{{ else }}{{ if .Version }}\uf487 {{.Version}}{{ end }}{{ end }} {{ if .Error }}{{ .Error }}{{ else }}{{ if .Version }}\uf487 {{.Version}}{{ end }} {{ if .Name }}{{ .Name }}{{ end }}{{ end }}
``` ```
::: :::
@ -38,5 +40,6 @@ Supports:
### Properties ### Properties
- `.Version`: `string` - The version of your project - `.Version`: `string` - The version of your project
- `.Name`: `string` - The name of your project
[templates]: /docs/config-templates [templates]: /docs/config-templates

View file

@ -40,7 +40,7 @@ require (
) )
require ( require (
github.com/BurntSushi/toml v1.0.0 // indirect github.com/BurntSushi/toml v1.0.0
github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect

View file

@ -4,18 +4,33 @@ import (
"encoding/json" "encoding/json"
"oh-my-posh/environment" "oh-my-posh/environment"
"oh-my-posh/properties" "oh-my-posh/properties"
"github.com/BurntSushi/toml"
) )
type ProjectItem struct { type ProjectItem struct {
Name string Name string
File string File string
Fetcher func(item ProjectItem) string Fetcher func(item ProjectItem) (string, string)
} }
type NodePackageJSON struct { type ProjectData struct {
Name string `json:"name"` Version string
Description string `json:"description"` Name string
Version string `json:"version"` }
// Rust Cargo package
type CargoTOML struct {
Package ProjectData
}
// Python Poetry package
type PyProjectTOML struct {
Tool PyProjectToolTOML
}
type PyProjectToolTOML struct {
Poetry ProjectData
} }
type Project struct { type Project struct {
@ -23,8 +38,9 @@ type Project struct {
env environment.Environment env environment.Environment
projects []*ProjectItem projects []*ProjectItem
Version string
Error string Error string
ProjectData
} }
func (n *Project) Enabled() bool { func (n *Project) Enabled() bool {
@ -39,7 +55,7 @@ func (n *Project) Enabled() bool {
} }
func (n *Project) Template() string { func (n *Project) Template() string {
return " {{ if .Error }}{{ .Error }}{{ else }}{{ if .Version }}\uf487 {{.Version}}{{ end }}{{ end }} " return " {{ if .Error }}{{ .Error }}{{ else }}{{ if .Version }}\uf487 {{.Version}}{{ end }} {{ if .Name }}{{ .Name }}{{ end }}{{ end }} "
} }
func (n *Project) Init(props properties.Properties, env environment.Environment) { func (n *Project) Init(props properties.Properties, env environment.Environment) {
@ -50,14 +66,25 @@ func (n *Project) Init(props properties.Properties, env environment.Environment)
{ {
Name: "node", Name: "node",
File: "package.json", File: "package.json",
Fetcher: n.getNodePackageVersion, Fetcher: n.getNodePackage,
},
{
Name: "cargo",
File: "Cargo.toml",
Fetcher: n.getCargoPackage,
},
{
Name: "poetry",
File: "pyproject.toml",
Fetcher: n.getPoetryPackage,
}, },
} }
n.Version = "" n.Version = ""
n.Name = ""
for _, item := range n.projects { for _, item := range n.projects {
if n.hasProjectFile(item) { if n.hasProjectFile(item) {
n.Version = item.Fetcher(*item) n.Version, n.Name = item.Fetcher(*item)
break break
} }
} }
@ -67,15 +94,41 @@ func (n *Project) hasProjectFile(p *ProjectItem) bool {
return n.env.HasFiles(p.File) return n.env.HasFiles(p.File)
} }
func (n *Project) getNodePackageVersion(item ProjectItem) string { func (n *Project) getNodePackage(item ProjectItem) (string, string) {
content := n.env.FileContent(item.File) content := n.env.FileContent(item.File)
var data NodePackageJSON var data ProjectData
err := json.Unmarshal([]byte(content), &data) err := json.Unmarshal([]byte(content), &data)
if err != nil { if err != nil {
n.Error = err.Error() n.Error = err.Error()
return "" return "", ""
} }
return data.Version return data.Version, data.Name
}
func (n *Project) getCargoPackage(item ProjectItem) (string, string) {
content := n.env.FileContent(item.File)
var data CargoTOML
_, err := toml.Decode(content, &data)
if err != nil {
n.Error = err.Error()
return "", ""
}
return data.Package.Version, data.Package.Name
}
func (n *Project) getPoetryPackage(item ProjectItem) (string, string) {
content := n.env.FileContent(item.File)
var data PyProjectTOML
_, err := toml.Decode(content, &data)
if err != nil {
n.Error = err.Error()
return "", ""
}
return data.Tool.Poetry.Version, data.Tool.Poetry.Name
} }

View file

@ -7,6 +7,8 @@ import (
"testing" "testing"
"github.com/alecthomas/assert" "github.com/alecthomas/assert"
testify_mock "github.com/stretchr/testify/mock"
) )
type MockData struct { type MockData struct {
@ -20,17 +22,36 @@ type MockData struct {
func getMockedPackageEnv(tc *MockData) (*mock.MockedEnvironment, properties.Map) { func getMockedPackageEnv(tc *MockData) (*mock.MockedEnvironment, properties.Map) {
env := new(mock.MockedEnvironment) env := new(mock.MockedEnvironment)
props := properties.Map{} props := properties.Map{}
env.On("HasFiles", tc.File).Return(true) env.On("HasFiles", testify_mock.Anything).Run(func(args testify_mock.Arguments) {
for _, c := range env.ExpectedCalls {
if c.Method == "HasFiles" {
c.ReturnArguments = testify_mock.Arguments{args.Get(0).(string) == tc.File}
}
}
})
env.On("FileContent", tc.File).Return(tc.PackageContents) env.On("FileContent", tc.File).Return(tc.PackageContents)
return env, props return env, props
} }
func TestPackage(t *testing.T) { func TestPackage(t *testing.T) {
cases := []*MockData{ cases := []*MockData{
{Case: "1.0.0", ExpectedString: "\uf487 1.0.0", Name: "node", File: "package.json", PackageContents: "{\"version\":\"1.0.0\"}"}, {Case: "1.0.0 node.js", ExpectedString: "\uf487 1.0.0 test", Name: "node", File: "package.json", PackageContents: "{\"version\":\"1.0.0\",\"name\":\"test\"}"},
{Case: "3.2.1", ExpectedString: "\uf487 3.2.1", Name: "node", File: "package.json", PackageContents: "{\"version\":\"3.2.1\"}"}, {Case: "3.2.1 node.js", ExpectedString: "\uf487 3.2.1 test", Name: "node", File: "package.json", PackageContents: "{\"version\":\"3.2.1\",\"name\":\"test\"}"},
{Case: "No version present", ExpectedString: "", Name: "node", File: "package.json", PackageContents: "{}"}, {Case: "1.0.0 cargo", ExpectedString: "\uf487 1.0.0 test", Name: "cargo", File: "Cargo.toml", PackageContents: "[package]\nname=\"test\"\nversion=\"1.0.0\"\n"},
{Case: "3.2.1 cargo", ExpectedString: "\uf487 3.2.1 test", Name: "cargo", File: "Cargo.toml", PackageContents: "[package]\nname=\"test\"\nversion=\"3.2.1\"\n"},
{Case: "1.0.0 poetry", ExpectedString: "\uf487 1.0.0 test", Name: "poetry", File: "pyproject.toml", PackageContents: "[tool.poetry]\nname=\"test\"\nversion=\"1.0.0\"\n"},
{Case: "3.2.1 poetry", ExpectedString: "\uf487 3.2.1 test", Name: "poetry", File: "pyproject.toml", PackageContents: "[tool.poetry]\nname=\"test\"\nversion=\"3.2.1\"\n"},
{Case: "No version present node.js", ExpectedString: "test", Name: "node", File: "package.json", PackageContents: "{\"name\":\"test\"}"},
{Case: "No version present cargo", ExpectedString: "test", Name: "cargo", File: "Cargo.toml", PackageContents: "[package]\nname=\"test\"\n"},
{Case: "No version present poetry", ExpectedString: "test", Name: "poetry", File: "pyproject.toml", PackageContents: "[tool.poetry]\nname=\"test\"\n"},
{Case: "No name present node.js", ExpectedString: "\uf487 1.0.0", Name: "node", File: "package.json", PackageContents: "{\"version\":\"1.0.0\"}"},
{Case: "No name present cargo", ExpectedString: "\uf487 1.0.0", Name: "cargo", File: "Cargo.toml", PackageContents: "[package]\nversion=\"1.0.0\"\n"},
{Case: "No name present poetry", ExpectedString: "\uf487 1.0.0", Name: "poetry", File: "pyproject.toml", PackageContents: "[tool.poetry]\nversion=\"1.0.0\"\n"},
{Case: "Empty project package node.js", ExpectedString: "", Name: "node", File: "package.json", PackageContents: "{}"},
{Case: "Empty project package cargo", ExpectedString: "", Name: "cargo", File: "Cargo.toml", PackageContents: ""},
{Case: "Empty project package poetry", ExpectedString: "", Name: "poetry", File: "pyproject.toml", PackageContents: ""},
{Case: "Invalid json", ExpectedString: "invalid character '}' looking for beginning of value", Name: "node", File: "package.json", PackageContents: "}"}, {Case: "Invalid json", ExpectedString: "invalid character '}' looking for beginning of value", Name: "node", File: "package.json", PackageContents: "}"},
{Case: "Invalid toml", ExpectedString: "toml: line 1: unexpected end of table name (table names cannot be empty)", Name: "cargo", File: "Cargo.toml", PackageContents: "["},
} }
for _, tc := range cases { for _, tc := range cases {