Added default_account and Find function
This commit is contained in:
parent
4b283db0f1
commit
5fb994bd68
7 changed files with 112 additions and 11 deletions
|
@ -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,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))
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
)
|
||||
|
||||
const testConfig = `
|
||||
default_account = "First Account"
|
||||
mailbox_path = "../base/mailbox"
|
||||
default_messages = 50
|
||||
|
||||
|
|
|
@ -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
example/example_config.toml
Normal file
22
example/example_config.toml
Normal file
|
@ -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"
|
Loading…
Reference in a new issue