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	Private bool   `yaml:"private"`
 38}
 39
 40func NewConfig(host string, port int, pk string, rs *git.RepoSource) (*Config, error) {
 41	var anonAccess string
 42	var yamlUsers string
 43	var displayHost string
 44	cfg := &Config{}
 45	cfg.Host = host
 46	cfg.Port = port
 47	cfg.Source = rs
 48	if pk == "" {
 49		anonAccess = "read-write"
 50	} else {
 51		anonAccess = "no-access"
 52	}
 53	if host == "" {
 54		displayHost = "localhost"
 55	} else {
 56		displayHost = host
 57	}
 58	yamlConfig := fmt.Sprintf(defaultConfig, displayHost, port, anonAccess)
 59	if pk != "" {
 60		yamlUsers = fmt.Sprintf(hasKeyUserConfig, pk)
 61	} else {
 62		yamlUsers = defaultUserConfig
 63	}
 64	yaml := fmt.Sprintf("%s%s%s", yamlConfig, yamlUsers, exampleUserConfig)
 65	err := cfg.createDefaultConfigRepo(yaml)
 66	if err != nil {
 67		return nil, err
 68	}
 69	return cfg, nil
 70}
 71
 72func (cfg *Config) reload() error {
 73	err := cfg.Source.LoadRepos()
 74	if err != nil {
 75		return err
 76	}
 77	cr, err := cfg.Source.GetRepo("config")
 78	if err != nil {
 79		return err
 80	}
 81	cs, err := cr.LatestFile("config.yaml")
 82	if err != nil {
 83		return err
 84	}
 85	err = yaml.Unmarshal([]byte(cs), cfg)
 86	if err != nil {
 87		return fmt.Errorf("bad yaml in config.yaml: %s", err)
 88	}
 89	return nil
 90}
 91
 92func createFile(path string, content string) error {
 93	f, err := os.Create(path)
 94	if err != nil {
 95		return err
 96	}
 97	defer f.Close()
 98	_, err = f.WriteString(content)
 99	if err != nil {
100		return err
101	}
102	return f.Sync()
103}
104
105func (cfg *Config) createDefaultConfigRepo(yaml string) error {
106	cn := "config"
107	rs := cfg.Source
108	err := rs.LoadRepos()
109	if err != nil {
110		return err
111	}
112	_, err = rs.GetRepo(cn)
113	if err == git.ErrMissingRepo {
114		cr, err := rs.InitRepo(cn, false)
115		if err != nil {
116			return err
117		}
118
119		rp := filepath.Join(rs.Path, cn, "README.md")
120		err = createFile(rp, defaultReadme)
121		if err != nil {
122			return err
123		}
124		cp := filepath.Join(rs.Path, cn, "config.yaml")
125		err = createFile(cp, yaml)
126		if err != nil {
127			return err
128		}
129		wt, err := cr.Repository.Worktree()
130		if err != nil {
131			return err
132		}
133		_, err = wt.Add("README.md")
134		if err != nil {
135			return err
136		}
137		_, err = wt.Add("config.yaml")
138		if err != nil {
139			return err
140		}
141		_, err = wt.Commit("Default init", &gg.CommitOptions{
142			All: true,
143			Author: &object.Signature{
144				Name:  "Soft Serve Server",
145				Email: "vt100@charm.sh",
146			},
147		})
148		if err != nil {
149			return err
150		}
151		if err != nil {
152			return err
153		}
154	} else if err != nil {
155		return err
156	}
157	return cfg.reload()
158}
159
160func (cfg *Config) isPrivate(repo string) bool {
161	for _, r := range cfg.Repos {
162		if r.Repo == repo {
163			return r.Private
164		}
165	}
166	return false
167}