Browse Source

Added default_account and Find function

Blallo 3 years ago
parent
commit
5fb994bd68
7 changed files with 112 additions and 11 deletions
  1. 37 7
      config/config.go
  2. 9 4
      config/config_test.go
  3. 1 0
      config/data.go
  4. 1 0
      config/data_test.go
  5. 1 0
      config/helper_test.go
  6. 41 0
      config/parse.go
  7. 22 0
      example/example_config.toml

+ 37 - 7
config/config.go

@@ -14,14 +14,39 @@ import (
 
 var ErrPortOutOfRange = errors.New("port out of range")
 var ErrMissingPassword = errors.New("password has not been set")
+var ErrMissingDefaultAccount = errors.New("default_account is missing from config")
 
 // CastingErrors is a simple wrapper around map[string]error. It's endowed with a utility
 // function to check if there are any errors.
-type CastingErrors map[string]error
+type CastingErrors struct {
+	GeneralErrors []error
+	AccountErrors map[string]error
+}
+
+func initCastingErrors() *CastingErrors {
+	c := CastingErrors{}
+	c.AccountErrors = make(map[string]error)
+	return &c
+}
+
+func (c *CastingErrors) appendGeneralError(e error) {
+	c.GeneralErrors = append(c.GeneralErrors, e)
+}
+
+func (c *CastingErrors) String() string {
+	out := "CastingErrors{"
+	out += fmt.Sprintf("GeneralErrors: %s, ", c.GeneralErrors)
+	out += fmt.Sprintf("AccountErrors: %s", c.AccountErrors)
+	out += "}"
+	return out
+}
 
 // Check if there are any errors, i.e. if any value of the map is not nil.
 func (c CastingErrors) Check() bool {
-	for _, err := range c {
+	if len(c.GeneralErrors) != 0 {
+		return false
+	}
+	for _, err := range c.GeneralErrors {
 		if err != nil {
 			return false
 		}
@@ -32,6 +57,7 @@ func (c CastingErrors) Check() bool {
 // MemConfig is the data structure that will be used program-wise. It holds all the
 // necessary information to authenticate and manage each provided account.
 type MemConfig struct {
+	Default  string
 	Accounts map[string]*AccountData
 	Workers  map[string]*worker.Worker
 }
@@ -68,18 +94,23 @@ func (a *AccountData) String() string {
 }
 
 // parseConfig translates a *fileConfig, as obtained from a file read, into a usable
-// *MemConfig that could be used in computation, together with a custom CastingErrors
+// *MemConfig that could be used in computation, together with a custom *CastingErrors
 // type, that holds the translation errors for each account.
-func parseConfig(fileConfig *fileConfig) (*MemConfig, CastingErrors) {
+func parseConfig(fileConfig *fileConfig) (*MemConfig, *CastingErrors) {
+	errors := initCastingErrors()
 	outConfig := initMemConfig()
+	defaultAccount := fileConfig.Default
+	if defaultAccount == "" {
+		errors.appendGeneralError(ErrMissingDefaultAccount)
+	}
+	outConfig.Default = defaultAccount
 	basePath, err := getOrDefaultMailbox(fileConfig.MailboxPath)
 	defaultMessages := getOrDefaultMessages(fileConfig.DefaultMessages)
 	if err != nil {
 		log.Fatal("Could not determine base path")
 	}
-	errors := make(map[string]error)
 	for _, account := range fileConfig.Accounts {
-		outConfig.Accounts[account.Name], errors[account.Name] = parseData(&account, basePath, defaultMessages)
+		outConfig.Accounts[account.Name], errors.AccountErrors[account.Name] = parseData(&account, basePath, defaultMessages)
 		outConfig.Workers[account.Name] = &worker.Worker{}
 	}
 	return &outConfig, errors
@@ -165,7 +196,6 @@ func getPassword(connection *connectionInfo) (string, error) {
 }
 
 func getMailboxPath(name, configPath, basePath string) string {
-	log.Printf("name: %s,\tconfig_path: %s,\tbase_path: %s\n", name, configPath, basePath)
 	if configPath != "" {
 		if info, err := os.Stat(configPath); err == nil || err != os.ErrNotExist && info != nil {
 			if info.IsDir() {

+ 9 - 4
config/config_test.go

@@ -9,8 +9,9 @@ import (
 
 func TestParseConfig(t *testing.T) {
 	expected := &MemConfig{
+		Default: "First Account",
 		Accounts: map[string]*AccountData{
-			"First Account": &AccountData{
+			"First Account": {
 				Host:            "mx.example.com",
 				Port:            993,
 				Username:        "first@example.com",
@@ -19,7 +20,7 @@ func TestParseConfig(t *testing.T) {
 				MailboxPath:     "/opt",
 				Messages:        30,
 			},
-			"Other Account": &AccountData{
+			"Other Account": {
 				Host:            "mail.personal.me",
 				Port:            666,
 				Username:        "h4x0R@personal.me",
@@ -30,8 +31,8 @@ func TestParseConfig(t *testing.T) {
 			},
 		},
 		Workers: map[string]*worker.Worker{
-			"First Account": &worker.Worker{},
-			"Other Account": &worker.Worker{},
+			"First Account": {},
+			"Other Account": {},
 		},
 	}
 	file := writeToTempFile(t, "papero.*.toml", testConfig)
@@ -46,6 +47,10 @@ func TestParseConfig(t *testing.T) {
 		t.Fatal(errs)
 	}
 
+	if result.Default != expected.Default {
+		t.Errorf("Default account does not match. Expected: %s\tResult:\t%s\n", expected.Default, result.Default)
+	}
+
 	if !cmp.Equal(result.Accounts, expected.Accounts) {
 		t.Errorf("Result and expected result differ: %+v\n", cmp.Diff(result.Accounts, expected.Accounts))
 	}

+ 1 - 0
config/data.go

@@ -41,6 +41,7 @@ func (m *maybeInt) UnmarshalText(text []byte) error {
 }
 
 type fileConfig struct {
+	Default         string    `toml:"default_account"`
 	MailboxPath     string    `toml:"mailbox_path"`
 	Accounts        []account `toml:"account"`
 	DefaultMessages maybeInt  `toml:"default_messages"`

+ 1 - 0
config/data_test.go

@@ -26,6 +26,7 @@ func TestShellScriptRunExecutableWithArgs(t *testing.T) {
 
 func TestParseFile(t *testing.T) {
 	expected := &fileConfig{
+		Default:         "First Account",
 		MailboxPath:     "../base/mailbox",
 		DefaultMessages: initMaybeInt(50),
 		Accounts: []account{

+ 1 - 0
config/helper_test.go

@@ -7,6 +7,7 @@ import (
 )
 
 const testConfig = `
+default_account = "First Account"
 mailbox_path = "../base/mailbox"
 default_messages = 50
 

+ 41 - 0
config/parse.go

@@ -2,9 +2,16 @@ package config
 
 import (
 	"errors"
+	"fmt"
 	"log"
+	"os"
+	"path"
+
+	"github.com/mitchellh/go-homedir"
 )
 
+var confFileName = "papero.toml"
+var ErrConfigNotFound = errors.New("unable to find configuration")
 var ErrFailedToParseConfig = errors.New("unable to cast into usable configuration")
 
 func Parse(filePath string) (*MemConfig, error) {
@@ -19,3 +26,37 @@ func Parse(filePath string) (*MemConfig, error) {
 	}
 	return memConfig, nil
 }
+
+// Find looks for the configuration file in the following order:
+//   - $PWD/papero.toml
+//   - ~/.config/papero/papero.toml
+//   - ~/.papero.toml
+//   - /etc/papero.toml
+// returns and error if no file has been found
+func Find() (string, error) {
+	var paths []string
+
+	// Try to append $PWD/papero.toml
+	cwd, err := os.Getwd()
+	if err == nil {
+		paths = append(paths, path.Join(cwd, confFileName))
+	}
+
+	// Try to append ~/.config/papero/papero.toml and ~/.papero.toml
+	home, err := homedir.Dir()
+	if err == nil {
+		paths = append(paths, path.Join(home, ".config", "papero", confFileName))
+		paths = append(paths, path.Join(home, fmt.Sprintf(".%s", confFileName)))
+	}
+
+	// Append /etc/papero.toml
+	paths = append(paths, path.Join("/etc", confFileName))
+
+	for _, file := range paths {
+		info, err := os.Stat(file)
+		if err == nil && !info.IsDir() {
+			return file, nil
+		}
+	}
+	return "", ErrConfigNotFound
+}

+ 22 - 0
example/example_config.toml

@@ -0,0 +1,22 @@
+default_account = "First Account"
+mailbox_path = "../base/mailbox"
+default_messages = 50
+
+[[account]]
+name = "First Account"
+mailbox_path = "/opt"
+messages = 30
+excluded_folders = ["Draft", "Junk"]
+    [account.connection]
+    hostname = "mx.example.com"
+    port = 993
+    username = "first@example.com"
+    password_exec = "echo -n 123qweasdzxc"
+
+[[account]]
+name = "Other Account"
+    [account.connection]
+    hostname = "mail.personal.me"
+    port = 666
+    username = "h4x0R@personal.me"
+    password = "mySup3r5ekre7p4ssw0rd123"