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}