Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow merge the existing description/workaround in errors.toml #867

Merged
merged 1 commit into from
Oct 29, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 39 additions & 27 deletions components/errdoc/errdoc-gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,17 @@ import (
)

var opt struct {
source string
module string
output string
source string
module string
output string
retainCode bool
}

func init() {
flag.StringVar(&opt.source, "source", "", "The source directory of error documentation")
flag.StringVar(&opt.module, "module", "", "The module name of target repository")
flag.StringVar(&opt.output, "output", "", "The output path of error documentation file")
flag.BoolVar(&opt.retainCode, "retain-code", false, "Retain the generated code when generator exit")
}

func log(format string, args ...interface{}) {
Expand Down Expand Up @@ -82,7 +84,10 @@ func main() {
if err := os.MkdirAll(targetDir, 0755); err != nil {
fatal("Cannot create the errdoc: %+v", err)
}
defer os.RemoveAll(targetDir)

if !opt.retainCode {
defer os.RemoveAll(targetDir)
}

tmpl := `
package main
Expand All @@ -95,7 +100,9 @@ import (
"reflect"
"fmt"
"sort"
"strings"

"github.com/BurntSushi/toml"
"github.com/pingcap/errors"
{{- range $decl := .}}
{{$decl.PackageName}} "{{- $decl.ImportPath}}"
Expand All @@ -107,23 +114,27 @@ func main() {
flag.StringVar(&outpath, "output", "", "Specify the error documentation output file path")
flag.Parse()
if outpath == "" {
println("Usage: ./_errdoc-generator --out /path/to/errors.toml")
println("Usage: ./_errdoc-generator --output /path/to/errors.toml")
os.Exit(1)
}

// Read-in the exists file and merge the description/workaround from exists file
existDefinition := map[string]spec{}
if file, err := ioutil.ReadFile(outpath); err == nil {
err = toml.Unmarshal(file, &existDefinition)
if err != nil {
println(fmt.Sprintf("Invalid toml file %s when merging exists description/workaround: %v", outpath, err))
os.Exit(1)
}
}

var allErrors []error
{{- range $decl := .}}
{{- range $err := $decl.ErrNames}}
allErrors = append(allErrors, {{$decl.PackageName}}.{{- $err}})
allErrors = append(allErrors, {{$decl.PackageName}}.{{- $err}})
{{- end}}
{{- end}}

type spec struct {
Code string
Message string
Description string
Workaround string
}

var dedup = map[string]spec{}
for _, e := range allErrors {
terr, ok := e.(*errors.Error)
Expand All @@ -135,21 +146,17 @@ func main() {
message := val.FieldByName("message")
if previous, found := dedup[codeText.String()]; found {
println("Duplicated error code:", codeText.String())
if message.String() < previous.Message {
if message.String() < previous.Error {
continue
}
}
description := val.FieldByName("description")
workaround := val.FieldByName("workaround ")
s := spec{
Code: codeText.String(),
Message: message.String(),
}
if description.IsValid() {
s.Description = description.String()
Code: codeText.String(),
Error: message.String(),
}
if workaround.IsValid() {
s.Workaround = workaround.String()
if exist, found := existDefinition[s.Code]; found {
s.Description = strings.TrimSpace(exist.Description)
s.Workaround = strings.TrimSpace(exist.Workaround)
}
dedup[codeText.String()] = s
}
Expand All @@ -162,16 +169,16 @@ func main() {
sort.Slice(sorted, func(i, j int) bool {
// TiDB exits duplicated code
if sorted[i].Code == sorted[j].Code {
return sorted[i].Message < sorted[j].Message
return sorted[i].Error < sorted[j].Error
}
return sorted[i].Code < sorted[j].Code
})

// We don't use toml library to serialize it due to cannot reserve the order for map[string]spec
buffer := bytes.NewBufferString("# AUTOGENERATED BY github.com/pingcap/tiup/components/errdoc/errdoc-gen\n" +
"# DO NOT EDIT THIS FILE, PLEASE CHANGE ERROR DEFINITION IF CONTENT IMPROPER.\n\n")
"# YOU CAN CHANGE THE 'description'/'workaround' FIELDS IF THEM ARE IMPROPER.\n\n")
for _, item := range sorted {
buffer.WriteString(fmt.Sprintf("[\"%s\"]\nerror = '''\n%s\n'''\n", item.Code, item.Message))
buffer.WriteString(fmt.Sprintf("[\"%s\"]\nerror = '''\n%s\n'''\n", item.Code, item.Error))
if item.Description != "" {
buffer.WriteString(fmt.Sprintf("description = '''\n%s\n'''\n", item.Description))
}
Expand All @@ -184,7 +191,12 @@ func main() {
panic(err)
}
}
`
` + "type spec struct {\n" +
"Code string\n" +
"Error string `toml:\"error\"`\n" +
"Description string `toml:\"description\"`\n" +
"Workaround string `toml:\"workaround\"`\n" +
"}"

t, err := template.New("_errdoc-template").Parse(tmpl)
if err != nil {
Expand Down