25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 

138 satır
3.9 KiB

  1. // Copyright 2016 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // +build ignore
  15. // Regen.go regenerates the genproto repository.
  16. //
  17. // Regen.go recursively walks through each directory named by given arguments,
  18. // looking for all .proto files. (Symlinks are not followed.)
  19. // If the pkg_prefix flag is not an empty string,
  20. // any proto file without `go_package` option
  21. // or whose option does not begin with the prefix is ignored.
  22. // If multiple roots contain files with the same name,
  23. // eg "root1/path/to/file" and "root2/path/to/file",
  24. // only the first file is processed; the rest are ignored.
  25. // Protoc is executed on remaining files,
  26. // one invocation per set of files declaring the same Go package.
  27. package main
  28. import (
  29. "flag"
  30. "fmt"
  31. "io/ioutil"
  32. "log"
  33. "os"
  34. "os/exec"
  35. "path/filepath"
  36. "regexp"
  37. "strconv"
  38. "strings"
  39. )
  40. var goPkgOptRe = regexp.MustCompile(`(?m)^option go_package = (.*);`)
  41. func usage() {
  42. fmt.Fprintln(os.Stderr, `usage: go run regen.go -go_out=path/to/output [-pkg_prefix=pkg/prefix] roots...
  43. Most users will not need to run this file directly.
  44. To regenerate this repository, run regen.sh instead.`)
  45. flag.PrintDefaults()
  46. }
  47. func main() {
  48. goOutDir := flag.String("go_out", "", "go_out argument to pass to protoc-gen-go")
  49. pkgPrefix := flag.String("pkg_prefix", "", "only include proto files with go_package starting with this prefix")
  50. flag.Usage = usage
  51. flag.Parse()
  52. if *goOutDir == "" {
  53. log.Fatal("need go_out flag")
  54. }
  55. seenFiles := make(map[string]bool)
  56. pkgFiles := make(map[string][]string)
  57. for _, root := range flag.Args() {
  58. walkFn := func(path string, info os.FileInfo, err error) error {
  59. if err != nil {
  60. return err
  61. }
  62. if !info.Mode().IsRegular() || !strings.HasSuffix(path, ".proto") {
  63. return nil
  64. }
  65. switch rel, err := filepath.Rel(root, path); {
  66. case err != nil:
  67. return err
  68. case seenFiles[rel]:
  69. return nil
  70. default:
  71. seenFiles[rel] = true
  72. }
  73. pkg, err := goPkg(path)
  74. if err != nil {
  75. return err
  76. }
  77. pkgFiles[pkg] = append(pkgFiles[pkg], path)
  78. return nil
  79. }
  80. if err := filepath.Walk(root, walkFn); err != nil {
  81. log.Fatal(err)
  82. }
  83. }
  84. for pkg, fnames := range pkgFiles {
  85. if !strings.HasPrefix(pkg, *pkgPrefix) {
  86. continue
  87. }
  88. if out, err := protoc(*goOutDir, flag.Args(), fnames); err != nil {
  89. log.Fatalf("error executing protoc: %s\n%s", err, out)
  90. }
  91. }
  92. }
  93. // goPkg reports the import path declared in the given file's
  94. // `go_package` option. If the option is missing, goPkg returns empty string.
  95. func goPkg(fname string) (string, error) {
  96. content, err := ioutil.ReadFile(fname)
  97. if err != nil {
  98. return "", err
  99. }
  100. var pkgName string
  101. if match := goPkgOptRe.FindSubmatch(content); len(match) > 0 {
  102. pn, err := strconv.Unquote(string(match[1]))
  103. if err != nil {
  104. return "", err
  105. }
  106. pkgName = pn
  107. }
  108. if p := strings.IndexRune(pkgName, ';'); p > 0 {
  109. pkgName = pkgName[:p]
  110. }
  111. return pkgName, nil
  112. }
  113. // protoc executes the "protoc" command on files named in fnames,
  114. // passing go_out and include flags specified in goOut and includes respectively.
  115. // protoc returns combined output from stdout and stderr.
  116. func protoc(goOut string, includes, fnames []string) ([]byte, error) {
  117. args := []string{"--go_out=plugins=grpc:" + goOut}
  118. for _, inc := range includes {
  119. args = append(args, "-I", inc)
  120. }
  121. args = append(args, fnames...)
  122. return exec.Command("protoc", args...).CombinedOutput()
  123. }