[wip] git-root config search concept

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
Alex Goodman 2021-11-30 16:43:41 -05:00
parent fe616acd98
commit f2aa4caf55
No known key found for this signature in database
GPG Key ID: 5CB45AE22BAB7EA7
2 changed files with 59 additions and 18 deletions

View File

@ -201,6 +201,8 @@ Configuration search paths:
- `.syft.yaml` - `.syft.yaml`
- `.syft/config.yaml` - `.syft/config.yaml`
- `<git repo root>/.syft.yaml`
- `<git repo root>/.syft/config.yaml`
- `~/.syft.yaml` - `~/.syft.yaml`
- `<XDG_CONFIG_HOME>/syft/config.yaml` - `<XDG_CONFIG_HOME>/syft/config.yaml`

View File

@ -3,7 +3,10 @@ package config
import ( import (
"errors" "errors"
"fmt" "fmt"
"os"
"os/exec"
"path" "path"
"path/filepath"
"reflect" "reflect"
"strings" "strings"
@ -206,44 +209,80 @@ func readConfig(v *viper.Viper, configPath string) error {
// 1. look for .<appname>.yaml (in the current directory) // 1. look for .<appname>.yaml (in the current directory)
v.AddConfigPath(".") v.AddConfigPath(".")
v.SetConfigName("." + internal.ApplicationName) v.SetConfigName("." + internal.ApplicationName)
if err = v.ReadInConfig(); err == nil { if exists, err := readViperConfig(v); exists || err != nil {
return nil return err
} else if !errors.As(err, &viper.ConfigFileNotFoundError{}) {
return fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err)
} }
// 2. look for .<appname>/config.yaml (in the current directory) // 2. look for .<appname>/config.yaml (in the current directory)
v.AddConfigPath("." + internal.ApplicationName) v.AddConfigPath("." + internal.ApplicationName)
v.SetConfigName("config") v.SetConfigName("config")
if err = v.ReadInConfig(); err == nil { if exists, err := readViperConfig(v); exists || err != nil {
return nil return err
} else if !errors.As(err, &viper.ConfigFileNotFoundError{}) {
return fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err)
} }
// 3. look for ~/.<appname>.yaml if root := gitRepoRoot(); root != "" {
// 3. look for <git repo root>/.<appname>.yaml, where the repo root is defined by "git rev-parse --show-toplevel"
v.AddConfigPath(root)
v.SetConfigName("." + internal.ApplicationName)
if exists, err := readViperConfig(v); exists {
if err != nil {
return err
}
return os.Chdir(root)
}
// 4. look for <git repo root>/.<appname>/config.yaml, where the repo root is defined by "git rev-parse --show-toplevel"
v.AddConfigPath(filepath.Join(root, "."+internal.ApplicationName))
v.SetConfigName("config")
if exists, err := readViperConfig(v); exists {
if err != nil {
return err
}
return os.Chdir(root)
}
}
// 5. look for ~/.<appname>.yaml
home, err := homedir.Dir() home, err := homedir.Dir()
if err == nil { if err == nil {
v.AddConfigPath(home) v.AddConfigPath(home)
v.SetConfigName("." + internal.ApplicationName) v.SetConfigName("." + internal.ApplicationName)
if err = v.ReadInConfig(); err == nil { if exists, err := readViperConfig(v); exists || err != nil {
return nil return err
} else if !errors.As(err, &viper.ConfigFileNotFoundError{}) {
return fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err)
} }
} }
// 4. look for <appname>/config.yaml in xdg locations (starting with xdg home config dir, then moving upwards) // 6. look for <appname>/config.yaml in xdg locations (starting with xdg home config dir, then moving upwards)
v.AddConfigPath(path.Join(xdg.ConfigHome, internal.ApplicationName)) v.AddConfigPath(path.Join(xdg.ConfigHome, internal.ApplicationName))
for _, dir := range xdg.ConfigDirs { for _, dir := range xdg.ConfigDirs {
v.AddConfigPath(path.Join(dir, internal.ApplicationName)) v.AddConfigPath(path.Join(dir, internal.ApplicationName))
} }
v.SetConfigName("config") v.SetConfigName("config")
if err = v.ReadInConfig(); err == nil { if exists, err := readViperConfig(v); exists || err != nil {
return nil return err
} else if !errors.As(err, &viper.ConfigFileNotFoundError{}) {
return fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err)
} }
return ErrApplicationConfigNotFound return ErrApplicationConfigNotFound
} }
func readViperConfig(v *viper.Viper) (bool, error) {
err := v.ReadInConfig()
if err == nil {
return true, nil
} else if errors.As(err, &viper.ConfigFileNotFoundError{}) {
return false, nil
}
return true, fmt.Errorf("unable to parse config=%q: %w", v.ConfigFileUsed(), err)
}
func gitRepoRoot() string {
root, err := exec.Command("git", "rev-parse", "--show-toplevel").Output()
if err != nil {
return ""
}
absRepoRoot, err := filepath.Abs(strings.TrimSpace(string(root)))
if err != nil {
return ""
}
return absRepoRoot
}