145 lines
3.6 KiB
Go
145 lines
3.6 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/ihexxa/gocfg"
|
|
|
|
"github.com/ihexxa/quickshare/src/db/sitestore"
|
|
"github.com/ihexxa/quickshare/src/kvstore/boltdbpvd"
|
|
)
|
|
|
|
type Args struct {
|
|
Host string `short:"h" long:"host" description:"server hostname"`
|
|
Port int `short:"p" long:"port" description:"server port"`
|
|
DbPath string `short:"d" long:"db" description:"path of the quickshare.db"`
|
|
Configs []string `short:"c" long:"configs" description:"config path"`
|
|
}
|
|
|
|
// LoadCfg loads the default config, the config in database, config files and arguments in order.
|
|
// All config values will be merged into one, and the latter overwrites the former.
|
|
// Each config can be part of the whole ServerCfg
|
|
func LoadCfg(args *Args) (*gocfg.Cfg, error) {
|
|
defaultCfg, err := DefaultConfig()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cfg, err := gocfg.New(NewConfig()).Load(gocfg.JSONStr(defaultCfg))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
tmpCfg := *cfg
|
|
dbPath, err := getDbPath(&tmpCfg, args.Configs, args.DbPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
_, err = os.Stat(dbPath)
|
|
if err == nil {
|
|
cfg, err = mergeDbConfig(cfg, dbPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else if err != nil {
|
|
if !os.IsNotExist(err) {
|
|
return nil, err
|
|
} else {
|
|
fmt.Printf("warning: Database does not exist in (%s), skipped\n", dbPath)
|
|
}
|
|
}
|
|
|
|
cfg, err = mergeConfigFiles(cfg, args.Configs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return mergeArgs(cfg, args)
|
|
}
|
|
|
|
func mergeDbConfig(cfg *gocfg.Cfg, dbPath string) (*gocfg.Cfg, error) {
|
|
kv := boltdbpvd.New(dbPath, 1024)
|
|
defer kv.Close()
|
|
|
|
siteStore, err := sitestore.NewSiteStore(kv)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fail to new site config store: %s", err)
|
|
}
|
|
|
|
clientCfg, err := siteStore.GetCfg()
|
|
if err != nil {
|
|
if errors.Is(err, sitestore.ErrNotFound) {
|
|
return cfg, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
clientCfgBytes, err := json.Marshal(clientCfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cfgStr := fmt.Sprintf(`{"site": %s}`, string(clientCfgBytes))
|
|
return cfg.Load(gocfg.JSONStr(cfgStr))
|
|
}
|
|
|
|
// getDbPath returns db path from arguments, configs, default config in order
|
|
// this is a little tricky
|
|
func getDbPath(cfg *gocfg.Cfg, configPaths []string, argDbPath string) (string, error) {
|
|
if argDbPath != "" {
|
|
return argDbPath, nil
|
|
}
|
|
|
|
var err error
|
|
|
|
for _, configPath := range configPaths {
|
|
if strings.HasSuffix(configPath, ".yml") || strings.HasSuffix(configPath, ".yaml") {
|
|
cfg, err = cfg.Load(gocfg.YAML(configPath))
|
|
} else if strings.HasSuffix(configPath, ".json") {
|
|
cfg, err = cfg.Load(gocfg.JSON(configPath))
|
|
} else {
|
|
return "", fmt.Errorf("unknown config file type (.yml .yaml .json are supported): %s", configPath)
|
|
}
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
return cfg.GrabString("Db.DbPath"), nil
|
|
}
|
|
|
|
func mergeConfigFiles(cfg *gocfg.Cfg, configPaths []string) (*gocfg.Cfg, error) {
|
|
var err error
|
|
|
|
for _, configPath := range configPaths {
|
|
if strings.HasSuffix(configPath, ".yml") || strings.HasSuffix(configPath, ".yaml") {
|
|
cfg, err = cfg.Load(gocfg.YAML(configPath))
|
|
} else if strings.HasSuffix(configPath, ".json") {
|
|
cfg, err = cfg.Load(gocfg.JSON(configPath))
|
|
} else {
|
|
return nil, fmt.Errorf("unknown config file type (.yml .yaml .json are supported): %s", configPath)
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func mergeArgs(cfg *gocfg.Cfg, args *Args) (*gocfg.Cfg, error) {
|
|
if args.Host != "" {
|
|
cfg.SetString("Server.Host", args.Host)
|
|
}
|
|
if args.Port != 0 {
|
|
cfg.SetInt("Server.Port", args.Port)
|
|
}
|
|
if args.DbPath != "" {
|
|
cfg.SetString("Db.DbPath", args.DbPath)
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|