cerrado @ 4ea63e98cc999ab05d1ac98b64875d7413e86972

  1package config
  2
  3import (
  4	"errors"
  5	"fmt"
  6	"io"
  7	"os"
  8	"path"
  9	"strconv"
 10
 11	"git.gabrielgio.me/cerrado/pkg/u"
 12	"git.sr.ht/~emersion/go-scfg"
 13)
 14
 15var (
 16	ScanPathErr = errors.New("Scan path does not exist")
 17	RepoPathErr = errors.New("Repository path does not exist")
 18)
 19
 20type (
 21
 22	// scan represents piece of the scan from the configuration file.
 23	scan struct {
 24		Path   string
 25		Public bool
 26	}
 27
 28	// configuration represents file configuration.
 29	configuration struct {
 30		Scan       *scan
 31		RootReadme string
 32	}
 33
 34	// This is a per repository configuration.
 35	GitRepositoryConfiguration struct {
 36		Name   string
 37		Path   string
 38		Public bool
 39	}
 40
 41	// ConfigurationRepository represents the configuration repository (as in
 42	// database repositories).
 43	// This holds all the function necessary to ask for configuration
 44	// information.
 45	ConfigurationRepository struct {
 46		rootReadme   string
 47		repositories []*GitRepositoryConfiguration
 48	}
 49)
 50
 51func LoadConfigurationRepository(configPath string) (*ConfigurationRepository, error) {
 52	f, err := os.Open(configPath)
 53	if err != nil {
 54		return nil, err
 55	}
 56
 57	config, err := parse(f)
 58	if err != nil {
 59		return nil, err
 60	}
 61
 62	repo := &ConfigurationRepository{
 63		rootReadme: config.RootReadme,
 64	}
 65
 66	err = repo.expandOnScanPath(config.Scan.Path, config.Scan.Public)
 67	if err != nil {
 68		return nil, err
 69	}
 70	return repo, nil
 71
 72}
 73
 74// GetRootReadme returns root read path
 75func (c *ConfigurationRepository) GetRootReadme() string {
 76	return c.rootReadme
 77}
 78
 79// GetByName returns configuration of repository for a given name.
 80// It returns nil if there is not match for it.
 81func (c *ConfigurationRepository) GetByName(name string) *GitRepositoryConfiguration {
 82	for _, r := range c.repositories {
 83		if r.Name == name {
 84			return r
 85		}
 86	}
 87	return nil
 88}
 89
 90// List returns all the configuration for all repositories.
 91func (c *ConfigurationRepository) List() []*GitRepositoryConfiguration {
 92	return c.repositories
 93}
 94
 95// expandOnScanPath scans the scanPath for folders taking them as repositories
 96// and applying them default configuration.
 97func (c *ConfigurationRepository) expandOnScanPath(scanPath string, public bool) error {
 98	if !u.FileExist(scanPath) {
 99		return ScanPathErr
100	}
101
102	entries, err := os.ReadDir(scanPath)
103	if err != nil {
104		return err
105	}
106
107	c.repositories = make([]*GitRepositoryConfiguration, 0)
108	for _, e := range entries {
109		if !e.IsDir() {
110			continue
111		}
112
113		fullPath := path.Join(scanPath, e.Name())
114		c.repositories = append(c.repositories, &GitRepositoryConfiguration{
115			Name:   e.Name(),
116			Path:   fullPath,
117			Public: public,
118		})
119	}
120	return nil
121}
122
123func parse(r io.Reader) (*configuration, error) {
124	block, err := scfg.Read(r)
125	if err != nil {
126		return nil, err
127	}
128
129	config := defaultConfiguration()
130
131	err = setScan(block, config.Scan)
132	if err != nil {
133		return nil, err
134	}
135
136	err = setRootReadme(block, &config.RootReadme)
137	if err != nil {
138		return nil, err
139	}
140
141	return config, nil
142}
143
144func defaultConfiguration() *configuration {
145	return &configuration{
146		Scan: &scan{
147			Public: true,
148			Path:   "",
149		},
150		RootReadme: "",
151	}
152}
153
154func setRootReadme(block scfg.Block, readme *string) error {
155	scanDir := block.Get("root-readme")
156	return setString(scanDir, readme)
157}
158
159func setScan(block scfg.Block, scan *scan) error {
160	scanDir := block.Get("scan")
161	err := setString(scanDir, &scan.Path)
162	if err != nil {
163		return err
164	}
165
166	public := scanDir.Children.Get("public")
167	return setBool(public, &scan.Public)
168}
169
170func setBool(dir *scfg.Directive, field *bool) error {
171	if dir != nil {
172
173		p1, _ := u.First(dir.Params)
174		v, err := strconv.ParseBool(p1)
175		if err != nil {
176			return fmt.Errorf("Error parsing bool param of %s: %w", dir.Name, err)
177		}
178		*field = v
179	}
180	return nil
181}
182
183func setString(dir *scfg.Directive, field *string) error {
184	if dir != nil {
185		*field, _ = u.First(dir.Params)
186	}
187	return nil
188}