Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove dependency on github.com/spf13/viper #593

Closed
wants to merge 1 commit into from
Closed
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
106 changes: 51 additions & 55 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,50 +22,51 @@ import (
"github.com/Masterminds/sprig"
"github.com/pelletier/go-toml"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/twpayne/chezmoi/internal/chezmoi"
"github.com/twpayne/chezmoi/internal/configparser"
vfs "github.com/twpayne/go-vfs"
xdg "github.com/twpayne/go-xdg/v3"
bolt "go.etcd.io/bbolt"
yaml "gopkg.in/yaml.v2"
)

type sourceVCSConfig struct {
Command string
AutoCommit bool
AutoPush bool
Init interface{}
Pull interface{}
Command string `json:"command" toml:"command" yaml:"command"`
AutoCommit bool `json:"autoCommit" toml:"autoCommit" yaml:"autoCommit"`
AutoPush bool `json:"autoPush" toml:"autoPush" yaml:"autoPush"`
Init interface{} `json:"init" toml:"init" yaml:"init"`
Pull interface{} `json:"pull" toml:"pull" yaml:"pull"`
}

// A Config represents a configuration.
type Config struct {
configFile string
configFileName string
configFile *os.File
err error
fs vfs.FS
mutator chezmoi.Mutator
SourceDir string
DestDir string
Umask permValue
DryRun bool
Follow bool
Remove bool
Verbose bool
Color string
Debug bool
GPG chezmoi.GPG
GPGRecipient string
SourceVCS sourceVCSConfig
Merge mergeConfig
Bitwarden bitwardenCmdConfig
GenericSecret genericSecretCmdConfig
Gopass gopassCmdConfig
KeePassXC keePassXCCmdConfig
Lastpass lastpassCmdConfig
Onepassword onepasswordCmdConfig
Vault vaultCmdConfig
Pass passCmdConfig
Data map[string]interface{}
SourceDir string `json:"sourceDir" toml:"sourceDir" yaml:"sourceDir"`
DestDir string `json:"destDir" toml:"destDir" yaml:"destDir"`
Umask permValue `json:"umask" toml:"umask" yaml:"umask"`
DryRun bool `json:"dryRun" toml:"dryRun" yaml:"dryRun"`
Follow bool `json:"follow" toml:"follow" yaml:"follow"`
Remove bool `json:"remove" toml:"remove" yaml:"remove"`
Verbose bool `json:"verbose" toml:"verbose" yaml:"verbose"`
Color string `json:"color" toml:"color" yaml:"color"`
Debug bool `json:"debug" toml:"debug" yaml:"debug"`
GPG chezmoi.GPG `json:"gpg" toml:"gpg" yaml:"gpg"`
GPGRecipient string `json:"gpgRecipient" toml:"gpgRecipient" yaml:"gpgRecipient"`
SourceVCS sourceVCSConfig `json:"sourceVCS" toml:"sourceVCS" yaml:"sourceVCS"`
Merge mergeConfig `json:"merge" toml:"merge" yaml:"merge"`
Bitwarden bitwardenCmdConfig `json:"bitwarden" toml:"bitwarden" yaml:"bitwarden"`
GenericSecret genericSecretCmdConfig `json:"genericSecret" toml:"genericSecret" yaml:"genericSecret"`
Gopass gopassCmdConfig `json:"gopass" toml:"gopass" yaml:"gopass"`
KeePassXC keePassXCCmdConfig `json:"keePassXC" toml:"keePassXC" yaml:"keePassXC"`
Lastpass lastpassCmdConfig `json:"lastpass" toml:"lastpass" yaml:"lastpass"`
Onepassword onepasswordCmdConfig `json:"onepassword" toml:"onepassword" yaml:"onepassword"`
Vault vaultCmdConfig `json:"vault" toml:"vault" yaml:"vault"`
Pass passCmdConfig `json:"pass" toml:"pass" yaml:"pass"`
Data map[string]interface{} `json:"data" toml:"data" yaml:"data"`
colored bool
maxDiffDataSize int
templateFuncs template.FuncMap
Expand Down Expand Up @@ -277,6 +278,13 @@ func (c *Config) ensureSourceDirectory() error {
}
}

func (c *Config) getConfigFileName() string {
if c.configFile != nil {
return c.configFile.Name()
}
return c.getDefaultConfigFileName(c.bds)
}

func (c *Config) getData() (map[string]interface{}, error) {
defaultData, err := c.getDefaultData()
if err != nil {
Expand All @@ -291,6 +299,17 @@ func (c *Config) getData() (map[string]interface{}, error) {
return data, nil
}

func (c *Config) getDefaultConfigFileName(bds *xdg.BaseDirectorySpecification) string {
for _, configDir := range bds.ConfigDirs {
configFileName, _ := configparser.FindConfig(c.fs, filepath.Join(configDir, "chezmoi", "chezmoi"))
if configFileName != "" {
return configFileName
}
}
// Fallback to XDG Base Directory Specification default.
return filepath.Join(bds.ConfigHome, "chezmoi", "chezmoi.toml")
}

func (c *Config) getDefaultData() (map[string]interface{}, error) {
data := map[string]interface{}{
"arch": runtime.GOARCH,
Expand Down Expand Up @@ -381,7 +400,7 @@ func (c *Config) getEntries(ts *chezmoi.TargetState, args []string) ([]chezmoi.E
}

func (c *Config) getPersistentState(options *bolt.Options) (chezmoi.PersistentState, error) {
persistentStateFile := c.getPersistentStateFile()
persistentStateFile := c.getPersistentStateFileName()
if c.DryRun {
if options == nil {
options = &bolt.Options{}
Expand All @@ -391,17 +410,8 @@ func (c *Config) getPersistentState(options *bolt.Options) (chezmoi.PersistentSt
return chezmoi.NewBoltPersistentState(c.fs, persistentStateFile, options)
}

func (c *Config) getPersistentStateFile() string {
if c.configFile != "" {
return filepath.Join(filepath.Dir(c.configFile), "chezmoistate.boltdb")
}
for _, configDir := range c.bds.ConfigDirs {
persistentStateFile := filepath.Join(configDir, "chezmoi", "chezmoistate.boltdb")
if _, err := os.Stat(persistentStateFile); err == nil {
return persistentStateFile
}
}
return filepath.Join(filepath.Dir(getDefaultConfigFile(c.bds)), "chezmoistate.boltdb")
func (c *Config) getPersistentStateFileName() string {
return filepath.Join(filepath.Dir(c.getConfigFileName()), "chezmoistate.boltdb")
}

func (c *Config) getTargetState(populateOptions *chezmoi.PopulateOptions) (*chezmoi.TargetState, error) {
Expand Down Expand Up @@ -514,20 +524,6 @@ func getAsset(name string) ([]byte, error) {
return ioutil.ReadAll(r)
}

func getDefaultConfigFile(bds *xdg.BaseDirectorySpecification) string {
// Search XDG Base Directory Specification config directories first.
for _, configDir := range bds.ConfigDirs {
for _, extension := range viper.SupportedExts {
configFilePath := filepath.Join(configDir, "chezmoi", "chezmoi."+extension)
if _, err := os.Stat(configFilePath); err == nil {
return configFilePath
}
}
}
// Fallback to XDG Base Directory Specification default.
return filepath.Join(bds.ConfigHome, "chezmoi", "chezmoi.toml")
}

func getDefaultSourceDir(bds *xdg.BaseDirectorySpecification) string {
// Check for XDG Base Directory Specification data directories first.
for _, dataDir := range bds.DataDirs {
Expand Down
2 changes: 1 addition & 1 deletion cmd/doctor.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (c *Config) runDoctorCmd(cmd *cobra.Command, args []string) error {
},
&doctorFileCheck{
name: "configuration file",
path: c.configFile,
path: c.getConfigFileName(),
},
&doctorBinaryCheck{
name: "shell",
Expand Down
24 changes: 12 additions & 12 deletions cmd/editconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package cmd

import (
"fmt"
"os"
"path/filepath"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/twpayne/chezmoi/internal/configparser"
vfs "github.com/twpayne/go-vfs"
vfsafero "github.com/twpayne/go-vfsafero"
)

var editConfigCommand = &cobra.Command{
Expand All @@ -24,24 +24,24 @@ func init() {
}

func (c *Config) runEditConfigCmd(cmd *cobra.Command, args []string) error {
if err := vfs.MkdirAll(c.mutator, filepath.Dir(c.configFile), 0777); err != nil {
configFileName := c.getConfigFileName()
if err := vfs.MkdirAll(c.mutator, filepath.Dir(configFileName), 0777); err != nil {
return err
}

if err := c.runEditor(c.configFile); err != nil {
if err := c.runEditor(configFileName); err != nil {
return err
}

// Warn the user of any errors reading the config file.
v := viper.New()
v.SetFs(vfsafero.NewAferoFS(c.fs))
v.SetConfigFile(c.configFile)
err := v.ReadInConfig()
if err == nil {
err = v.Unmarshal(&Config{})
}
configFile, err := os.Open(configFileName)
if err != nil {
c.warn(fmt.Sprintf("%s: %v", c.configFile, err))
c.warn(fmt.Sprintf("%s: %v", configFileName, err))
return nil
}
defer configFile.Close()
if err := configparser.ParseConfig(configFile, &Config{}); err != nil {
c.warn(fmt.Sprintf("%s: %v", configFileName, err))
}

return nil
Expand Down
23 changes: 12 additions & 11 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
"text/template"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/twpayne/chezmoi/internal/chezmoi"
"github.com/twpayne/chezmoi/internal/configparser"
vfs "github.com/twpayne/go-vfs"
)

Expand Down Expand Up @@ -110,7 +110,7 @@ func (c *Config) runInitCmd(cmd *cobra.Command, args []string) error {
}

func (c *Config) createConfigFile() error {
filename, ext, data, err := c.findConfigTemplate()
filename, data, err := c.findConfigTemplate()
if err != nil {
return err
}
Expand Down Expand Up @@ -152,25 +152,26 @@ func (c *Config) createConfigFile() error {
return err
}

viper.SetConfigType(ext)
if err := viper.ReadConfig(contents); err != nil {
configFile, err := os.Open(configPath)
if err != nil {
return err
}
return viper.Unmarshal(c)
defer configFile.Close()
return configparser.ParseConfig(configFile, c)
}

func (c *Config) findConfigTemplate() (string, string, string, error) {
for _, ext := range viper.SupportedExts {
contents, err := c.fs.ReadFile(filepath.Join(c.SourceDir, ".chezmoi."+ext+chezmoi.TemplateSuffix))
func (c *Config) findConfigTemplate() (string, string, error) {
for _, ext := range configparser.Extensions() {
contents, err := c.fs.ReadFile(filepath.Join(c.SourceDir, ".chezmoi"+ext+chezmoi.TemplateSuffix))
switch {
case os.IsNotExist(err):
continue
case err != nil:
return "", "", "", err
return "", "", err
}
return "chezmoi." + ext, ext, string(contents), nil
return "chezmoi" + ext, string(contents), nil
}
return "", "", "", nil
return "", "", nil
}

func (c *Config) promptString(field string) string {
Expand Down
4 changes: 2 additions & 2 deletions cmd/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ var mergeCmd = &cobra.Command{
}

type mergeConfig struct {
Command string
Args []string
Command string `json:"command" toml:"command" yaml:"command"`
Args []string `json:"args" toml:"args" yaml:"args"`
}

func init() {
Expand Down
15 changes: 6 additions & 9 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/twpayne/chezmoi/internal/chezmoi"
"github.com/twpayne/chezmoi/internal/configparser"
vfs "github.com/twpayne/go-vfs"
xdg "github.com/twpayne/go-xdg/v3"
"golang.org/x/crypto/ssh/terminal"
Expand Down Expand Up @@ -64,7 +65,7 @@ func init() {

persistentFlags := rootCmd.PersistentFlags()

persistentFlags.StringVarP(&config.configFile, "config", "c", getDefaultConfigFile(config.bds), "config file")
persistentFlags.StringVarP(&config.configFileName, "config", "c", config.getDefaultConfigFileName(config.bds), "config file")

persistentFlags.BoolVarP(&config.DryRun, "dry-run", "n", false, "dry run")
panicOnError(viper.BindPFlag("dry-run", persistentFlags.Lookup("dry-run")))
Expand All @@ -91,19 +92,15 @@ func init() {
panicOnError(viper.BindPFlag("debug", persistentFlags.Lookup("debug")))

cobra.OnInitialize(func() {
_, err := os.Stat(config.configFile)
config.configFile, config.err = config.fs.Open(config.configFileName)
switch {
case err == nil:
viper.SetConfigFile(config.configFile)
config.err = viper.ReadInConfig()
if config.err == nil {
config.err = viper.Unmarshal(&config)
}
case config.err == nil:
config.err = configparser.ParseConfig(config.configFile, &config)
if config.err == nil {
config.err = config.validateData()
}
if config.err != nil {
config.warn(fmt.Sprintf("%s: %v", config.configFile, config.err))
config.warn(fmt.Sprintf("%s: %v", config.configFileName, config.err))
}
case os.IsNotExist(err):
default:
Expand Down
2 changes: 1 addition & 1 deletion cmd/secretbitwarden.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var bitwardenCmd = &cobra.Command{
}

type bitwardenCmdConfig struct {
Command string
Command string `json:"command" toml:"command" yaml:"command"`
}

var bitwardenCache = make(map[string]interface{})
Expand Down
2 changes: 1 addition & 1 deletion cmd/secretgeneric.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ var genericSecretCmd = &cobra.Command{
}

type genericSecretCmdConfig struct {
Command string
Command string `json:"command" toml:"command" yaml:"command"`
}

var (
Expand Down
2 changes: 1 addition & 1 deletion cmd/secretgopass.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var gopassCmd = &cobra.Command{
}

type gopassCmdConfig struct {
Command string
Command string `json:"command" toml:"command" yaml:"command"`
}

var gopassCache = make(map[string]string)
Expand Down
6 changes: 3 additions & 3 deletions cmd/secretkeepassxc.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ var keePassXCCmd = &cobra.Command{
}

type keePassXCCmdConfig struct {
Command string
Database string
Args []string
Command string `json:"command" toml:"command" yaml:"command"`
Database string `json:"database" toml:"database" yaml:"database"`
Args []string `json:"args" toml:"args" yaml:"args"`
}

type keePassXCAttributeCacheKey struct {
Expand Down
2 changes: 1 addition & 1 deletion cmd/secretlastpass.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var (
)

type lastpassCmdConfig struct {
Command string
Command string `json:"command" toml:"command" yaml:"command"`
versionCheckOnce sync.Once
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/secretonepassword.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var onepasswordCmd = &cobra.Command{
}

type onepasswordCmdConfig struct {
Command string
Command string `json:"command" toml:"command" yaml:"command"`
}

var (
Expand Down
2 changes: 1 addition & 1 deletion cmd/secretpass.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var passCmd = &cobra.Command{
}

type passCmdConfig struct {
Command string
Command string `json:"command" toml:"command" yaml:"command"`
}

var passCache = make(map[string]string)
Expand Down
Loading