Complete package for generating ocds structs (with extensions) in golang
This commit is contained in:
1 parent
da726550d4
commit
35974fa070
47 files changed
+9861
-299
No files matched your search
@@ -0,0 +1,106 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func newGenerateCmd(opts *options) *cobra.Command {
|
||||
var (
|
||||
out string
|
||||
pkg string
|
||||
check bool
|
||||
excludeFieldDoc bool
|
||||
)
|
||||
cmd := &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "Generate Go types from the config",
|
||||
Long: `Generate fetches the schemas and extensions named in the config and writes
|
||||
the Go types to --out. Use --out - to write to stdout.
|
||||
|
||||
With --check, nothing is written; the command fails if the output file is
|
||||
missing or differs from what would be generated. Use this in CI to catch
|
||||
generated code that is stale or was edited by hand.`,
|
||||
Example: ` ocdsgen generate -c extensions.json -o ocds_gen.go -p tenders
|
||||
ocdsgen generate --check --strict
|
||||
//go:generate go tool ocdsgen generate -c extensions.json -o ocds_gen.go -p tenders`,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
if pkg == "" {
|
||||
var err error
|
||||
if pkg, err = packageFromPath(out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
cfg, g, err := opts.setup(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
src, err := g.Run(cfg, pkg, filepath.Base(opts.config), excludeFieldDoc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch {
|
||||
case out == "-":
|
||||
if _, err := cmd.OutOrStdout().Write(src); err != nil {
|
||||
return err
|
||||
}
|
||||
case check:
|
||||
existing, err := os.ReadFile(out)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return fmt.Errorf("%s does not exist; run ocdsgen generate", out)
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(existing, src) {
|
||||
return fmt.Errorf("%s is out of date; run ocdsgen generate", out)
|
||||
}
|
||||
fmt.Fprintf(cmd.ErrOrStderr(), "%s is up to date\n", out)
|
||||
default:
|
||||
if err := os.WriteFile(out, src, 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return opts.finish(g)
|
||||
},
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVarP(&out, "out", "o", "ocds_gen.go", `output Go file, or "-" for stdout`)
|
||||
f.StringVarP(&pkg, "package", "p", "", "Go package name (default: name of the output file's directory)")
|
||||
f.BoolVar(&check, "check", false, "verify the output file is up to date instead of writing it")
|
||||
f.BoolVar(&excludeFieldDoc, "exclude-field-doc", false, `exclude documentation for definition fields`)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// packageFromPath derives a package name from the directory the output file
|
||||
// will be written to, e.g. internal/tenders/ocds_gen.go -> tenders.
|
||||
func packageFromPath(out string) (string, error) {
|
||||
if out == "-" {
|
||||
return "", errors.New("--package is required when writing to stdout")
|
||||
}
|
||||
abs, err := filepath.Abs(out)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
dir := filepath.Base(filepath.Dir(abs))
|
||||
name := strings.Map(func(r rune) rune {
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
|
||||
return unicode.ToLower(r)
|
||||
}
|
||||
return -1
|
||||
}, dir)
|
||||
if !token.IsIdentifier(name) || token.IsKeyword(name) {
|
||||
return "", fmt.Errorf("can't derive a package name from directory %q; pass --package", dir)
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
Reference in new issue
Block a user