158 lines
3.7 KiB
Go
158 lines
3.7 KiB
Go
|
|
// generate_plugindata is a tool used to inject the sample configuration into all the plugins
|
||
|
|
// It extracts the sample configuration from the plugins README.md
|
||
|
|
// Then using the file plugin_name_sample_config.go as a template, and will be updated with the sample configuration
|
||
|
|
// This tool is then also used to revert these changes with the `--clean` flag
|
||
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bufio"
|
||
|
|
"bytes"
|
||
|
|
"flag"
|
||
|
|
"fmt"
|
||
|
|
"log" //nolint:revive
|
||
|
|
"os"
|
||
|
|
"strings"
|
||
|
|
"text/template"
|
||
|
|
|
||
|
|
"github.com/yuin/goldmark"
|
||
|
|
gast "github.com/yuin/goldmark/ast"
|
||
|
|
"github.com/yuin/goldmark/text"
|
||
|
|
)
|
||
|
|
|
||
|
|
func createSourceName(packageName string) string {
|
||
|
|
return fmt.Sprintf("%s_sample_config.go", packageName)
|
||
|
|
}
|
||
|
|
|
||
|
|
// extractPluginData reads the README.md to get the sample configuration
|
||
|
|
func extractPluginData() (string, error) {
|
||
|
|
readMe, err := os.ReadFile("README.md")
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
p := goldmark.DefaultParser()
|
||
|
|
r := text.NewReader(readMe)
|
||
|
|
root := p.Parse(r)
|
||
|
|
|
||
|
|
var currentSection string
|
||
|
|
for n := root.FirstChild(); n != nil; n = n.NextSibling() {
|
||
|
|
switch tok := n.(type) {
|
||
|
|
case *gast.Heading:
|
||
|
|
if tok.FirstChild() != nil {
|
||
|
|
currentSection = string(tok.FirstChild().Text(readMe))
|
||
|
|
}
|
||
|
|
case *gast.FencedCodeBlock:
|
||
|
|
if currentSection == "Configuration" && string(tok.Language(readMe)) == "toml" {
|
||
|
|
var config []byte
|
||
|
|
for i := 0; i < tok.Lines().Len(); i++ {
|
||
|
|
line := tok.Lines().At(i)
|
||
|
|
config = append(config, line.Value(readMe)...)
|
||
|
|
}
|
||
|
|
return string(config), nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fmt.Printf("No configuration found for plugin: %s\n", os.Getenv("GOPACKAGE"))
|
||
|
|
|
||
|
|
return "", nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// generatePluginData parses the main source file of the plugin as a template and updates it with the sample configuration
|
||
|
|
// The original source file is saved so that these changes can be reverted
|
||
|
|
func generatePluginData(packageName string, sampleConfig string) error {
|
||
|
|
sourceName := createSourceName(packageName)
|
||
|
|
|
||
|
|
plugin, err := os.ReadFile(sourceName)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
generatedTemplate := template.Must(template.New("").Parse(string(plugin)))
|
||
|
|
|
||
|
|
f, err := os.Create(sourceName)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
defer f.Close()
|
||
|
|
|
||
|
|
err = generatedTemplate.Execute(f, struct {
|
||
|
|
SampleConfig string
|
||
|
|
}{
|
||
|
|
SampleConfig: sampleConfig,
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
var newSampleConfigFunc = ` return ` + "`{{ .SampleConfig }}`\n"
|
||
|
|
|
||
|
|
// cleanGeneratedFiles will revert the changes made by generatePluginData
|
||
|
|
func cleanGeneratedFiles(packageName string) error {
|
||
|
|
sourceName := createSourceName(packageName)
|
||
|
|
sourcefile, err := os.Open(sourceName)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
defer sourcefile.Close()
|
||
|
|
|
||
|
|
var c []byte
|
||
|
|
buf := bytes.NewBuffer(c)
|
||
|
|
|
||
|
|
scanner := bufio.NewScanner(sourcefile)
|
||
|
|
|
||
|
|
var sampleconfigSection bool
|
||
|
|
for scanner.Scan() {
|
||
|
|
if sampleconfigSection && strings.TrimSpace(scanner.Text()) == "}" {
|
||
|
|
sampleconfigSection = false
|
||
|
|
if _, err := buf.Write([]byte(newSampleConfigFunc)); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if !sampleconfigSection {
|
||
|
|
if _, err := buf.Write(scanner.Bytes()); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if _, err = buf.WriteString("\n"); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if !sampleconfigSection && strings.Contains(scanner.Text(), "SampleConfig() string") {
|
||
|
|
sampleconfigSection = true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
err = os.WriteFile(sourceName, buf.Bytes(), 0664)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func main() {
|
||
|
|
clean := flag.Bool("clean", false, "Remove generated files")
|
||
|
|
flag.Parse()
|
||
|
|
|
||
|
|
goPackage := os.Getenv("GOPACKAGE")
|
||
|
|
|
||
|
|
if *clean {
|
||
|
|
err := cleanGeneratedFiles(goPackage)
|
||
|
|
if err != nil {
|
||
|
|
log.Fatal(err)
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
s, err := extractPluginData()
|
||
|
|
if err != nil {
|
||
|
|
log.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
err = generatePluginData(goPackage, s)
|
||
|
|
if err != nil {
|
||
|
|
log.Fatal(err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|