package config import ( "errors" "fmt" "io" "os" "path" "strconv" "git.gabrielgio.me/cerrado/pkg/u" "git.sr.ht/~emersion/go-scfg" ) var ( ScanPathErr = errors.New("Scan path does not exist") RepoPathErr = errors.New("Repository path does not exist") ) type ( // scan represents piece of the scan from the configuration file. scan struct { Path string Public bool } // configuration represents file configuration. configuration struct { Scan *scan RootReadme string } // This is a per repository configuration. GitRepositoryConfiguration struct { Name string Path string Public bool } // ConfigurationRepository represents the configuration repository (as in // database repositories). // This holds all the function necessary to ask for configuration // information. ConfigurationRepository struct { rootReadme string repositories []*GitRepositoryConfiguration } ) func LoadConfigurationRepository(configPath string) (*ConfigurationRepository, error) { f, err := os.Open(configPath) if err != nil { return nil, err } config, err := parse(f) if err != nil { return nil, err } repo := &ConfigurationRepository{ rootReadme: config.RootReadme, } err = repo.expandOnScanPath(config.Scan.Path, config.Scan.Public) if err != nil { return nil, err } return repo, nil } // GetRootReadme returns root read path func (c *ConfigurationRepository) GetRootReadme() string { return c.rootReadme } // GetByName returns configuration of repository for a given name. // It returns nil if there is not match for it. func (c *ConfigurationRepository) GetByName(name string) *GitRepositoryConfiguration { for _, r := range c.repositories { if r.Name == name { return r } } return nil } // List returns all the configuration for all repositories. func (c *ConfigurationRepository) List() []*GitRepositoryConfiguration { return c.repositories } // expandOnScanPath scans the scanPath for folders taking them as repositories // and applying them default configuration. func (c *ConfigurationRepository) expandOnScanPath(scanPath string, public bool) error { if !u.FileExist(scanPath) { return ScanPathErr } entries, err := os.ReadDir(scanPath) if err != nil { return err } c.repositories = make([]*GitRepositoryConfiguration, 0) for _, e := range entries { if !e.IsDir() { continue } fullPath := path.Join(scanPath, e.Name()) c.repositories = append(c.repositories, &GitRepositoryConfiguration{ Name: e.Name(), Path: fullPath, Public: public, }) } return nil } func parse(r io.Reader) (*configuration, error) { block, err := scfg.Read(r) if err != nil { return nil, err } config := defaultConfiguration() err = setScan(block, config.Scan) if err != nil { return nil, err } err = setRootReadme(block, &config.RootReadme) if err != nil { return nil, err } return config, nil } func defaultConfiguration() *configuration { return &configuration{ Scan: &scan{ Public: true, Path: "", }, RootReadme: "", } } func setRootReadme(block scfg.Block, readme *string) error { scanDir := block.Get("root-readme") return setString(scanDir, readme) } func setScan(block scfg.Block, scan *scan) error { scanDir := block.Get("scan") err := setString(scanDir, &scan.Path) if err != nil { return err } public := scanDir.Children.Get("public") return setBool(public, &scan.Public) } func setBool(dir *scfg.Directive, field *bool) error { if dir != nil { p1, _ := u.First(dir.Params) v, err := strconv.ParseBool(p1) if err != nil { return fmt.Errorf("Error parsing bool param of %s: %w", dir.Name, err) } *field = v } return nil } func setString(dir *scfg.Directive, field *string) error { if dir != nil { *field, _ = u.First(dir.Params) } return nil }