github.com/ForceCLI/config@v0.0.0-20230217143549-9149d42a3c99/config.go (about)

     1  // Cross-platform configuration manager
     2  package config
     3  
     4  import (
     5  	"fmt"
     6  	"github.com/mitchellh/go-homedir"
     7  	"io/ioutil"
     8  	"os"
     9  	"path"
    10  	"path/filepath"
    11  	"sort"
    12  )
    13  
    14  type Config struct {
    15  	Base    string
    16  	Entries map[string]ConfigEntry
    17  }
    18  
    19  type ConfigEntry struct {
    20  	Key   string
    21  	Value string
    22  }
    23  
    24  // Create a new Config manager
    25  func NewConfig(base string) (config *Config) {
    26  	config = &Config{}
    27  	config.Base = base
    28  	config.Entries = make(map[string]ConfigEntry)
    29  	return
    30  }
    31  
    32  // List keys for a given config
    33  func (c *Config) List(name string) (keys []string, err error) {
    34  	configDir, err := c.configDirectory()
    35  	if err != nil {
    36  		return
    37  	}
    38  	dir := path.Join(configDir, name)
    39  	files, err := ioutil.ReadDir(dir)
    40  	if err != nil {
    41  		return
    42  	}
    43  	for _, file := range files {
    44  		keys = append(keys, file.Name())
    45  	}
    46  	sort.Strings(keys)
    47  	return
    48  }
    49  
    50  // Save a key/value pair for a config
    51  func (c *Config) Save(name, key, value string) (err error) {
    52  	return c.SaveGlobal(name, key, value)
    53  }
    54  
    55  func (c *Config) SaveGlobal(name, key, value string) (err error) {
    56  	dir, err := c.configDirectory()
    57  	if err != nil {
    58  		return
    59  	}
    60  	filename := path.Join(dir, name, key)
    61  	err = c.writeFile(filename, value)
    62  	return
    63  }
    64  
    65  func (c *Config) SaveLocal(name, key, value string) (err error) {
    66  	dir, err := c.localConfigDirectory()
    67  	if err != nil {
    68  		return
    69  	}
    70  	filename := path.Join(dir, name, key)
    71  	err = c.writeFile(filename, value)
    72  	return
    73  }
    74  
    75  // Load a value for a config key
    76  func (c *Config) Load(name, key string) (body string, err error) {
    77  	return c.LoadGlobal(name, key)
    78  }
    79  
    80  func (c *Config) LoadGlobal(name, key string) (body string, err error) {
    81  	dir, err := c.configDirectory()
    82  	if err != nil {
    83  		return
    84  	}
    85  	filename := path.Join(dir, name, key)
    86  	body, err = c.readFile(filename)
    87  	return
    88  }
    89  
    90  // Load value from local config directory if it exists; otherwise from global
    91  // config directory
    92  func (c *Config) LoadLocalOrGlobal(name, key string) (body string, err error) {
    93  	dir, err := c.localConfigDirectory()
    94  	if err != nil {
    95  		return
    96  	}
    97  	filename := path.Join(dir, name, key)
    98  	body, err = c.readFile(filename)
    99  	if err != nil {
   100  		return c.LoadGlobal(name, key)
   101  	}
   102  	return
   103  }
   104  
   105  // Delete a config key/value pair
   106  func (c *Config) Delete(name, key string) (err error) {
   107  	return c.DeleteGlobal(name, key)
   108  }
   109  
   110  func (c *Config) DeleteGlobal(name, key string) (err error) {
   111  	dir, err := c.configDirectory()
   112  	if err != nil {
   113  		return
   114  	}
   115  	filename := path.Join(dir, name, key)
   116  	err = os.Remove(filename)
   117  	return
   118  }
   119  
   120  // Delete a config key/value pair
   121  func (c *Config) DeleteLocalOrGlobal(name, key string) (err error) {
   122  	dir, err := c.localConfigDirectory()
   123  	if err != nil {
   124  		return
   125  	}
   126  	filename := path.Join(dir, name, key)
   127  	err = os.Remove(filename)
   128  	if err != nil {
   129  		return c.DeleteGlobal(name, key)
   130  	}
   131  	return
   132  }
   133  
   134  func (c *Config) configDirectory() (configDir string, err error) {
   135  	home, err := c.homeDirectory()
   136  	if err != nil {
   137  		return
   138  	}
   139  	configDir = path.Join(home, fmt.Sprintf(".%s", c.Base))
   140  	return
   141  }
   142  
   143  func (c *Config) localConfigDirectory() (configDir string, err error) {
   144  	cwd, err := os.Getwd()
   145  	if err != nil {
   146  		return
   147  	}
   148  	configDir = path.Join(cwd, fmt.Sprintf(".%s", c.Base))
   149  	return
   150  }
   151  
   152  func (c *Config) writeFile(filename, body string) (err error) {
   153  	dir := filepath.Dir(filename)
   154  	if err = os.MkdirAll(dir, 0700); err != nil {
   155  		return err
   156  	}
   157  	err = ioutil.WriteFile(filename, []byte(body), 0600)
   158  	if err != nil {
   159  		return
   160  	}
   161  	return
   162  }
   163  
   164  func (c *Config) readFile(filename string) (body string, err error) {
   165  	data, err := ioutil.ReadFile(filename)
   166  	if err != nil {
   167  		return
   168  	}
   169  	body = string(data)
   170  	return
   171  }
   172  
   173  func (c *Config) homeDirectory() (string, error) {
   174  	return homedir.Dir()
   175  }