autogits/workflow-pr/submodules.go
2025-02-04 14:24:38 +01:00

174 lines
3.2 KiB
Go

package main
import (
"bytes"
"errors"
"fmt"
"io"
"strings"
"unicode"
)
type Submodule struct {
Name string
Path string
Url string
Update string
Branch string
Ignore string
Shallow string
}
var SyntaxError error = errors.New("Syntax error")
func (sub *Submodule) parseSubmoduleName(line string) error {
line = strings.TrimSpace(line)
if line[0:10] != "submodule " {
return SyntaxError
}
r := strings.NewReader(line[10:])
ch, _, err := r.ReadRune()
for ; ; ch, _, err = r.ReadRune() {
if err != nil {
return fmt.Errorf("%c %d", ch, 32)
}
if !unicode.IsSpace(ch) {
break
}
}
if ch != '"' {
return fmt.Errorf("%c %d", ch, 36)
// return SyntaxError
}
var b strings.Builder
for ch, _, err = r.ReadRune(); ch != '"'; ch, _, err = r.ReadRune() {
if err != nil {
return fmt.Errorf("%c %d", ch, 32)
}
b.WriteRune(ch)
}
if ch != '"' {
return fmt.Errorf("%c %d", ch, 45)
// return SyntaxError
}
for ch, _, err = r.ReadRune(); unicode.IsSpace(ch); ch, _, err = r.ReadRune() {
if err != nil {
return fmt.Errorf("%d %w", 38, err)
}
}
if ch != ']' || err != nil {
return fmt.Errorf("%c %d, %w", ch, 50, err)
// return SyntaxError
}
sub.Name = b.String()
for ch, _, err = r.ReadRune(); ; ch, _, _ = r.ReadRune() {
if err == io.EOF {
return nil
}
if !unicode.IsSpace(ch) {
return SyntaxError
}
}
}
func (s *Submodule) parseKeyValue(line string) error {
eqLoc := strings.Index(line, "=")
if eqLoc < 0 || eqLoc == len(line)-1 {
return SyntaxError
}
key := strings.ToLower(strings.TrimSpace(line[0:eqLoc]))
val := strings.TrimSpace(line[eqLoc+1:])
if len(val) == 0 {
return SyntaxError
}
switch key {
case "path":
s.Path = val
case "url":
s.Url = val
case "shallow":
s.Shallow = val
case "ignore":
s.Ignore = val
case "branch":
s.Branch = val
case "update":
s.Update = val
default:
return SyntaxError
}
return nil
}
func ParseSubmodulesFile(reader io.Reader) ([]Submodule, error) {
data, err := io.ReadAll(reader)
if err != nil {
return nil, err
}
var sub *Submodule
ret := []Submodule{}
lines := bytes.Split(data, []byte("\n"))
for _, l := range lines {
line := string(bytes.TrimSpace(l))
if len(line) == 0 {
continue
}
if line[0] == '[' {
if sub != nil {
ret = append(ret, *sub)
}
sub = &Submodule{}
if err := sub.parseSubmoduleName(line[1:]); err != nil {
return nil, err
}
} else if sub == nil {
return nil, SyntaxError
} else {
if err := sub.parseKeyValue(line); err != nil {
return nil, err
}
}
}
if sub != nil {
ret = append(ret, *sub)
}
return ret, nil
}
func writeValue(out io.Writer, key, value string) {
if len(value) > 0 {
out.Write([]byte(fmt.Sprintf("\t%s = %s\n", key, value)))
}
}
func WriteSubmodules(subs []Submodule, out io.Writer) error {
for _, sub := range subs {
if len(sub.Name) < 1 {
return fmt.Errorf("Submodule with no name.")
}
out.Write([]byte(fmt.Sprintf("[submodule \"%s\"]\n", sub.Name)))
writeValue(out, "path", sub.Path)
writeValue(out, "url", sub.Url)
writeValue(out, "branch", sub.Branch)
writeValue(out, "ignore", sub.Ignore)
writeValue(out, "shallow", sub.Shallow)
writeValue(out, "update", sub.Update)
}
return nil
}