Skip to content

Commit

Permalink
feat: add YAML config support (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
ayakovlenko authored Jun 30, 2021
1 parent 24e12fb commit 5402098
Show file tree
Hide file tree
Showing 12 changed files with 181 additions and 35 deletions.
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ _zit_ chooses a git identity based on:
2. repository owner
3. repository name

… as defined in the configuration file:
… as defined in the configuration file.

2 types of configuration files are supported:

**Jsonnet**

```jsonnet
local User(name, email) = { name: name, email: email };
Expand All @@ -36,6 +40,31 @@ local user = {
}
```

**YAML**

```yaml
users:
work: &work_user
name: John Doe
email: john.doe@corp.com
personal:
github_user: &personal_github_user
name: JD42
email: JD42@users.noreply.github.com
gitlab_user: &personal_gitlab_user
name: JD42
email: 786972-JD42@users.noreply.gitlab.com

hosts:
github.com:
default: *personal_github_user
overrides:
- owner: corp
user: *work_user
gitlab.com:
default: *personal_gitlab_user
```
## Setup
There are 2 ways to set up a configuration file:
Expand All @@ -45,6 +74,8 @@ There are 2 ways to set up a configuration file:

```bash
export ZIT_CONFIG=~/.zit-config.jsonnet
# or
export ZIT_CONFIG=~/.zit-config.yaml
```

If the environment variable is set up, it will be chosen over the config at the
Expand Down
37 changes: 21 additions & 16 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,6 @@ func (err *ErrConfigNotFound) Error() string {
// HostMap TODO
type HostMap map[string]Config

// Get TODO
func (hm *HostMap) Get(host string) (*Config, error) {
conf, ok := (*hm)[host]
if !ok {
return nil, fmt.Errorf("cannot find config for host %q", host)
}

return &conf, nil
}

// Config TODO
type Config struct {
Default *User `json:"default"`
Expand All @@ -49,19 +39,19 @@ type Config struct {

// User TODO
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Name string `json:"name" yaml:"name"`
Email string `json:"email" yaml:"email"`
}

// Override TODO
type Override struct {
Owner string `json:"owner"`
Repo string `json:"repo,omitempty"`
User User `json:"user"`
Owner string `json:"owner" yaml:"owner"`
Repo string `json:"repo,omitempty" yaml:"repo"`
User User `json:"user" yaml:"user"`
}

// ReadHostMap TODO
func ReadHostMap(filename string, r io.Reader) (*HostMap, error) {
func readHostMap(filename string, r io.Reader) (*HostMap, error) {
buf := new(bytes.Buffer)
buf.ReadFrom(r)
confStr := buf.String()
Expand Down Expand Up @@ -114,3 +104,18 @@ func LocateConfFile() (string, error) {

return confPath, nil
}

// ---

func toV2(hostMap *HostMap) *ConfigV2 {
configV2 := ConfigV2{
Hosts: map[string]HostV2{},
}
for host, hostConfig := range *hostMap {
configV2.Hosts[host] = HostV2{
Default: hostConfig.Default,
Overrides: hostConfig.Overrides,
}
}
return &configV2
}
22 changes: 22 additions & 0 deletions config/config_v2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package config

import "fmt"

type ConfigV2 struct {
Hosts map[string]HostV2 `yaml:"hosts"`
}

type HostV2 struct {
Default *User `yaml:"default"`
Overrides []Override `yaml:"overrides"`
}

// Get TODO
func (c *ConfigV2) Get(host string) (*HostV2, error) {
hostConf, ok := (*&c.Hosts)[host]
if !ok {
return nil, fmt.Errorf("cannot find config for host %q", host)
}

return &hostConf, nil
}
38 changes: 38 additions & 0 deletions config/load.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package config

import (
"bytes"
"fmt"
"os"
"strings"
)

func Load(filename string) (*ConfigV2, error) {
isYaml := strings.HasSuffix(filename, ".yaml")
isJsonnet := strings.HasSuffix(filename, ".jsonnet")

if !isYaml && !isJsonnet {
return nil, fmt.Errorf("unsupported config format")
}

r, err := os.Open(filename)
if err != nil {
return nil, err
}

if isYaml {
buf := new(bytes.Buffer)
buf.ReadFrom(r)
confStr := buf.String()
return parseYaml(confStr)
} else if isJsonnet {
hostMap, err := readHostMap(filename, r)
if err != nil {
return nil, err
}
configV2 := toV2(hostMap)
return configV2, nil
} else {
return nil, fmt.Errorf("something went horribly wrong")
}
}
13 changes: 13 additions & 0 deletions config/yaml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package config

import (
"gopkg.in/yaml.v2"
)

func parseYaml(s string) (*ConfigV2, error) {
var config ConfigV2
if err := yaml.Unmarshal([]byte(s), &config); err != nil {
return nil, err
}
return &config, nil
}
38 changes: 38 additions & 0 deletions config/yaml_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package config

import (
"testing"
)

func TestParseYaml(t *testing.T) {

// TODO: improve this test
t.Run("test YAML config parsing", func(t *testing.T) {
s := `users:
work: &work_user
name: John Doe
email: john.doe@corp.com
personal:
github_user: &personal_github_user
name: JD42
email: JD42@users.noreply.github.com
gitlab_user: &personal_gitlab_user
name: JD42
email: 786972-JD42@users.noreply.gitlab.com
hosts:
github.com:
default: *personal_github_user
overrides:
- owner: corp
user: *work_user
gitlab.com:
default: *personal_gitlab_user`

_, err := parseYaml(s)
if err != nil {
t.Errorf("%+v", err)
}
})
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ require (
github.com/google/go-jsonnet v0.17.0
github.com/spf13/cobra v1.1.3
github.com/whilp/git-urls v1.0.0
gopkg.in/yaml.v2 v2.4.0
)
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
14 changes: 7 additions & 7 deletions identity/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import (
"zit/git"
)

func findBestMatch(conf config.Config, repo git.RepoInfo) (user *config.User) {
func findBestMatch(conf config.HostV2, repo git.RepoInfo) (user *config.User) {
if conf.Default != nil {
user = &config.User{
conf.Default.Name,
conf.Default.Email,
Name: conf.Default.Name,
Email: conf.Default.Email,
}
}

Expand All @@ -18,8 +18,8 @@ func findBestMatch(conf config.Config, repo git.RepoInfo) (user *config.User) {
if override.Repo != "" {
if override.Owner == repo.Owner && override.Repo == repo.Name {
user = &config.User{
override.User.Name,
override.User.Email,
Name: override.User.Name,
Email: override.User.Email,
}
break
} else {
Expand All @@ -29,8 +29,8 @@ func findBestMatch(conf config.Config, repo git.RepoInfo) (user *config.User) {

if override.Owner == repo.Owner {
user = &config.User{
override.User.Name,
override.User.Email,
Name: override.User.Name,
Email: override.User.Email,
}
break
}
Expand Down
8 changes: 4 additions & 4 deletions identity/identity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestFindBestMatch(t *testing.T) {
}

t.Run("match default user", func(t *testing.T) {
conf := config.Config{
conf := config.HostV2{
Default: &defaultUser,
Overrides: []config.Override{
{
Expand All @@ -56,7 +56,7 @@ func TestFindBestMatch(t *testing.T) {
})

t.Run("match owner override", func(t *testing.T) {
conf := config.Config{
conf := config.HostV2{
Default: &defaultUser,
Overrides: []config.Override{
{
Expand All @@ -82,7 +82,7 @@ func TestFindBestMatch(t *testing.T) {
})

t.Run("match repo override", func(t *testing.T) {
conf := config.Config{
conf := config.HostV2{
Default: &defaultUser,
Overrides: []config.Override{
{
Expand All @@ -108,7 +108,7 @@ func TestFindBestMatch(t *testing.T) {
})

t.Run("match repo and owner override", func(t *testing.T) {
conf := config.Config{
conf := config.HostV2{
Default: &defaultUser,
Overrides: []config.Override{
{
Expand Down
9 changes: 3 additions & 6 deletions identity/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ var SetCmd = &cobra.Command{
confPath, err := config.LocateConfFile()
cli.PrintlnExit(err)

confFile, err := os.Open(confPath)
cli.PrintlnExit(err)

hostMap, err := config.ReadHostMap(confPath, confFile)
conf, err := config.Load(confPath)
cli.PrintlnExit(err)

host, err := git.RemoteURL("origin")
Expand All @@ -47,10 +44,10 @@ defined in the configuration file:
repo, err := git.ExtractRepoInfo(host)
cli.PrintlnExit(err)

conf, err := hostMap.Get((*repo).Host)
hostConf, err := conf.Get((*repo).Host)
cli.PrintlnExit(err)

cred := findBestMatch(*conf, *repo)
cred := findBestMatch(*hostConf, *repo)
if cred == nil {
cli.PrintlnExit(fmt.Errorf("cannot find a match for host %q", (*repo).Host))
}
Expand Down
2 changes: 1 addition & 1 deletion version/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2.2.0+1
v2.3.0

0 comments on commit 5402098

Please sign in to comment.