github.com/knoebber/dotfile@v1.0.6/local/config.go (about)

     1  package local
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/knoebber/usererror"
    10  	"github.com/pkg/errors"
    11  )
    12  
    13  // Config contains local user settings for dotfile.
    14  type Config struct {
    15  	Remote   string `json:"remote"`
    16  	Username string `json:"username"`
    17  	Token    string `json:"token"`
    18  }
    19  
    20  func (c *Config) String() string {
    21  	return fmt.Sprintf("remote: %q\nusername: %q\ntoken: %q",
    22  		c.Remote,
    23  		c.Username,
    24  		c.Token,
    25  	)
    26  }
    27  
    28  func createDefaultConfig(path string) ([]byte, error) {
    29  	var newCfg Config
    30  
    31  	bytes, err := json.MarshalIndent(newCfg, "", jsonIndent)
    32  	if err != nil {
    33  		return nil, errors.Wrap(err, "marshalling new user config file")
    34  	}
    35  
    36  	if err = os.WriteFile(path, bytes, 0644); err != nil {
    37  		return nil, errors.Wrap(err, "saving new user config file")
    38  	}
    39  
    40  	return bytes, nil
    41  }
    42  
    43  func configBytes(path string) ([]byte, error) {
    44  	if !exists(path) {
    45  		return createDefaultConfig(path)
    46  	}
    47  
    48  	bytes, err := os.ReadFile(path)
    49  	if err != nil {
    50  		return nil, errors.Wrap(err, "reading config bytes")
    51  	}
    52  
    53  	return bytes, nil
    54  }
    55  
    56  // DefaultConfigPath returns the default config file.
    57  func DefaultConfigPath() (string, error) {
    58  	configDir, err := os.UserConfigDir()
    59  	if err != nil {
    60  		return "", err
    61  	}
    62  	dotfileDir := filepath.Join(configDir, "dotfile")
    63  	if !exists(dotfileDir) {
    64  		if err := os.MkdirAll(dotfileDir, 0755); err != nil {
    65  			return "", err
    66  		}
    67  	}
    68  
    69  	return filepath.Join(dotfileDir, "dotfile.json"), nil
    70  }
    71  
    72  // ReadConfig reads the user's config.
    73  // Creates a default file when it doesn't yet exist.
    74  func ReadConfig(path string) (*Config, error) {
    75  	cfg := new(Config)
    76  
    77  	bytes, err := configBytes(path)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  
    82  	if err = json.Unmarshal(bytes, cfg); err != nil {
    83  		return nil, errors.Wrap(err, "unmarshalling config")
    84  	}
    85  
    86  	return cfg, nil
    87  }
    88  
    89  // SetConfig sets a value in the dotfile config json file.
    90  func SetConfig(path, key, value string) error {
    91  	cfg := make(map[string]*string)
    92  
    93  	bytes, err := configBytes(path)
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	if err = json.Unmarshal(bytes, &cfg); err != nil {
    99  		return errors.Wrapf(err, "unmarshaling user config to map")
   100  	}
   101  
   102  	if _, ok := cfg[key]; !ok {
   103  		return usererror.Format("%q is not a valid config key", key)
   104  	}
   105  
   106  	cfg[key] = &value
   107  
   108  	bytes, err = json.MarshalIndent(cfg, "", jsonIndent)
   109  	if err != nil {
   110  		return errors.Wrap(err, "marshalling updated config map")
   111  	}
   112  
   113  	if err = os.WriteFile(path, bytes, 0644); err != nil {
   114  		return errors.Wrap(err, "saving updated config file")
   115  	}
   116  
   117  	return nil
   118  }