config.go

  1package config
  2
  3import (
  4	"gopkg.in/yaml.v2"
  5
  6	"fmt"
  7	"os"
  8	"path/filepath"
  9
 10	"github.com/charmbracelet/soft/git"
 11	gg "github.com/go-git/go-git/v5"
 12	"github.com/go-git/go-git/v5/plumbing/object"
 13)
 14
 15type Config struct {
 16	Name        string `yaml:"name"`
 17	Host        string `yaml:"host"`
 18	Port        int    `yaml:"port"`
 19	AnonAccess  string `yaml:"anon-access"`
 20	AllowNoKeys bool   `yaml:"allow-no-keys"`
 21	Users       []User `yaml:"users"`
 22	Repos       []Repo `yaml:"repos"`
 23	Source      *git.RepoSource
 24}
 25
 26type User struct {
 27	Name        string   `yaml:"name"`
 28	Admin       bool     `yaml:"admin"`
 29	PublicKey   string   `yaml:"public-key"`
 30	CollabRepos []string `yaml:"collab-repos"`
 31}
 32
 33type Repo struct {
 34	Name string `yaml:"name"`
 35	Repo string `yaml:"repo"`
 36	Note string `yaml:"note"`
 37}
 38
 39func NewConfig(host string, port int, pk string, rs *git.RepoSource) (*Config, error) {
 40	var anonAccess string
 41	var yamlUsers string
 42	var displayHost string
 43	cfg := &Config{}
 44	cfg.Host = host
 45	cfg.Port = port
 46	cfg.Source = rs
 47	if pk == "" {
 48		anonAccess = "read-write"
 49	} else {
 50		anonAccess = "no-access"
 51	}
 52	if host == "" {
 53		displayHost = "localhost"
 54	} else {
 55		displayHost = host
 56	}
 57	yamlConfig := fmt.Sprintf(defaultConfig, displayHost, port, anonAccess)
 58	if pk != "" {
 59		yamlUsers = fmt.Sprintf(hasKeyUserConfig, pk)
 60	} else {
 61		yamlUsers = defaultUserConfig
 62	}
 63	yaml := fmt.Sprintf("%s%s%s", yamlConfig, yamlUsers, exampleUserConfig)
 64	err := cfg.createDefaultConfigRepo(yaml)
 65	if err != nil {
 66		return nil, err
 67	}
 68	return cfg, nil
 69}
 70
 71func (cfg *Config) reload() error {
 72	err := cfg.Source.LoadRepos()
 73	if err != nil {
 74		return err
 75	}
 76	cr, err := cfg.Source.GetRepo("config")
 77	if err != nil {
 78		return err
 79	}
 80	cs, err := cr.LatestFile("config.yaml")
 81	if err != nil {
 82		return err
 83	}
 84	err = yaml.Unmarshal([]byte(cs), cfg)
 85	if err != nil {
 86		return fmt.Errorf("bad yaml in config.yaml: %s", err)
 87	}
 88	return nil
 89}
 90
 91func createFile(path string, content string) error {
 92	f, err := os.Create(path)
 93	if err != nil {
 94		return err
 95	}
 96	defer f.Close()
 97	_, err = f.WriteString(content)
 98	if err != nil {
 99		return err
100	}
101	return f.Sync()
102}
103
104func (cfg *Config) createDefaultConfigRepo(yaml string) error {
105	cn := "config"
106	rs := cfg.Source
107	err := rs.LoadRepos()
108	if err != nil {
109		return err
110	}
111	_, err = rs.GetRepo(cn)
112	if err == git.ErrMissingRepo {
113		cr, err := rs.InitRepo(cn, false)
114		if err != nil {
115			return err
116		}
117
118		rp := filepath.Join(rs.Path, cn, "README.md")
119		err = createFile(rp, defaultReadme)
120		if err != nil {
121			return err
122		}
123		cp := filepath.Join(rs.Path, cn, "config.yaml")
124		err = createFile(cp, yaml)
125		if err != nil {
126			return err
127		}
128		wt, err := cr.Repository.Worktree()
129		if err != nil {
130			return err
131		}
132		_, err = wt.Add("README.md")
133		if err != nil {
134			return err
135		}
136		_, err = wt.Add("config.yaml")
137		if err != nil {
138			return err
139		}
140		_, err = wt.Commit("Default init", &gg.CommitOptions{
141			All: true,
142			Author: &object.Signature{
143				Name:  "Soft Serve Server",
144				Email: "vt100@charm.sh",
145			},
146		})
147		if err != nil {
148			return err
149		}
150		if err != nil {
151			return err
152		}
153	} else if err != nil {
154		return err
155	}
156	return cfg.reload()
157}