@@ -27,6 +27,11 @@ import (
"github.com/go-git/go-git/v5/storage/memory"
)
+var (
+ // ErrNoConfig is returned when a repo has no config file.
+ ErrNoConfig = errors.New("no config file found")
+)
+
// Config is the Soft Serve configuration.
type Config struct {
Name string `yaml:"name" json:"name"`
@@ -124,31 +129,40 @@ func NewConfig(cfg *config.Config) (*Config, error) {
return c, nil
}
+// readConfig reads the config file for the repo. All config files are stored in
+// the config repo.
func (cfg *Config) readConfig(repo string, v interface{}) error {
- cr, err := cfg.Source.GetRepo(repo)
+ cr, err := cfg.Source.GetRepo("config")
if err != nil {
return err
}
- cy, _, err := cr.LatestFile(repo + ".yaml")
- if err != nil && !errors.Is(err, git.ErrFileNotFound) {
- return fmt.Errorf("error reading %s.yaml: %w", repo, err)
+ // Parse YAML files
+ var cy string
+ for _, ext := range []string{".yaml", ".yml"} {
+ cy, _, err = cr.LatestFile(repo + ext)
+ if err != nil && !errors.Is(err, git.ErrFileNotFound) {
+ return err
+ } else if err == nil {
+ break
+ }
}
+ // Parse JSON files
cj, _, err := cr.LatestFile(repo + ".json")
if err != nil && !errors.Is(err, git.ErrFileNotFound) {
- return fmt.Errorf("error reading %s.json: %w", repo, err)
+ return err
}
if cy != "" {
err = yaml.Unmarshal([]byte(cy), v)
if err != nil {
- return fmt.Errorf("bad yaml in %s.yaml: %s", repo, err)
+ return err
}
} else if cj != "" {
err = json.Unmarshal([]byte(cj), v)
if err != nil {
- return fmt.Errorf("bad json in %s.json: %s", repo, err)
+ return err
}
} else {
- return fmt.Errorf("no config file found for %q", repo)
+ return ErrNoConfig
}
return nil
}
@@ -164,16 +178,41 @@ func (cfg *Config) Reload() error {
if err := cfg.readConfig("config", cfg); err != nil {
return fmt.Errorf("error reading config: %w", err)
}
+ // sanitize repo configs
+ repos := make(map[string]RepoConfig, 0)
+ for _, r := range cfg.Repos {
+ repos[r.Repo] = r
+ }
+ for _, r := range cfg.Source.AllRepos() {
+ var rc RepoConfig
+ repo := r.Repo()
+ if repo == "config" {
+ continue
+ }
+ if err := cfg.readConfig(repo, &rc); err != nil {
+ if !errors.Is(err, ErrNoConfig) {
+ log.Printf("error reading config: %v", err)
+ }
+ continue
+ }
+ repos[r.Repo()] = rc
+ }
+ cfg.Repos = make([]RepoConfig, 0, len(repos))
+ for n, r := range repos {
+ r.Repo = n
+ cfg.Repos = append(cfg.Repos, r)
+ }
+ // Populate readmes and descriptions
for _, r := range cfg.Source.AllRepos() {
- name := r.Name()
+ repo := r.Repo()
err = r.UpdateServerInfo()
if err != nil {
- log.Printf("error updating server info for %s: %s", name, err)
+ log.Printf("error updating server info for %s: %s", repo, err)
}
pat := "README*"
rp := ""
for _, rr := range cfg.Repos {
- if name == rr.Repo {
+ if repo == rr.Repo {
rp = rr.Readme
r.name = rr.Name
r.description = rr.Note
@@ -187,7 +226,7 @@ func (cfg *Config) Reload() error {
rm := ""
fc, fp, _ := r.LatestFile(pat)
rm = fc
- if name == "config" {
+ if repo == "config" {
md, err := templatize(rm, cfg)
if err != nil {
return err