main.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright 2018-present the CoreDHCP Authors. All rights reserved
  2. // This source code is licensed under the MIT license found in the
  3. // LICENSE file in the root directory of this source tree.
  4. package main
  5. import (
  6. "bufio"
  7. "flag"
  8. "fmt"
  9. "html/template"
  10. "io/ioutil"
  11. "log"
  12. "os"
  13. "path"
  14. "strings"
  15. )
  16. const (
  17. defaultTemplateFile = "coredhcp.go.template"
  18. importBase = "github.com/coredhcp/coredhcp/"
  19. )
  20. var (
  21. flagTemplate = flag.String("template", defaultTemplateFile, "Template file name")
  22. flagOutfile = flag.String("outfile", "", "Output file path")
  23. flagFromFile = flag.String("from", "", "Optional file name to get the plugin list from, one import path per line")
  24. )
  25. var funcMap = template.FuncMap{
  26. "importname": func(importPath string) (string, error) {
  27. parts := strings.Split(importPath, "/")
  28. if len(parts) < 1 {
  29. return "", fmt.Errorf("no components found in import path '%s'", importPath)
  30. }
  31. return parts[len(parts)-1], nil
  32. },
  33. }
  34. func main() {
  35. flag.Parse()
  36. data, err := ioutil.ReadFile(*flagTemplate)
  37. if err != nil {
  38. log.Fatalf("Failed to read template file '%s': %v", *flagTemplate, err)
  39. }
  40. t, err := template.New("coredhcp").Funcs(funcMap).Parse(string(data))
  41. if err != nil {
  42. log.Fatalf("Template parsing failed: %v", err)
  43. }
  44. plugins := make(map[string]bool)
  45. for _, pl := range flag.Args() {
  46. pl := strings.TrimSpace(pl)
  47. if pl == "" {
  48. continue
  49. }
  50. if !strings.ContainsRune(pl, '/') {
  51. // A bare name was specified, not a full import path.
  52. // Coredhcp plugins aren't in the standard library, and it's unlikely someone
  53. // would put them at the base of $GOPATH/src.
  54. // Assume this is one of the builtin plugins. If needed, use the -from option
  55. // which always requires (and uses) exact paths
  56. // XXX: we could also look into github.com/coredhcp/plugins
  57. pl = importBase + pl
  58. }
  59. plugins[pl] = true
  60. }
  61. if *flagFromFile != "" {
  62. // additional plugin names from a text file, one line per plugin import
  63. // path
  64. fd, err := os.Open(*flagFromFile)
  65. if err != nil {
  66. log.Fatalf("Failed to read file '%s': %v", *flagFromFile, err)
  67. }
  68. defer func() {
  69. if err := fd.Close(); err != nil {
  70. log.Printf("Error closing file '%s': %v", *flagFromFile, err)
  71. }
  72. }()
  73. sc := bufio.NewScanner(fd)
  74. for sc.Scan() {
  75. pl := strings.TrimSpace(sc.Text())
  76. if pl == "" {
  77. continue
  78. }
  79. plugins[pl] = true
  80. }
  81. if err := sc.Err(); err != nil {
  82. log.Fatalf("Error reading file '%s': %v", *flagFromFile, err)
  83. }
  84. }
  85. if len(plugins) == 0 {
  86. log.Fatalf("No plugin specified!")
  87. }
  88. outfile := *flagOutfile
  89. if outfile == "" {
  90. tmpdir, err := ioutil.TempDir("", "coredhcp")
  91. if err != nil {
  92. log.Fatalf("Cannot create temporary directory: %v", err)
  93. }
  94. outfile = path.Join(tmpdir, "coredhcp.go")
  95. }
  96. log.Printf("Generating output file '%s' with %d plugin(s):", outfile, len(plugins))
  97. idx := 1
  98. for pl := range plugins {
  99. log.Printf("% 3d) %s", idx, pl)
  100. idx++
  101. }
  102. outFD, err := os.OpenFile(outfile, os.O_CREATE|os.O_WRONLY, 0644)
  103. if err != nil {
  104. log.Fatalf("Failed to create output file '%s': %v", outfile, err)
  105. }
  106. defer func() {
  107. if err := outFD.Close(); err != nil {
  108. log.Printf("Error while closing file descriptor for '%s': %v", outfile, err)
  109. }
  110. }()
  111. // WARNING: no escaping of the provided strings is done
  112. pluginList := make([]string, 0, len(plugins))
  113. for pl := range plugins {
  114. pluginList = append(pluginList, pl)
  115. }
  116. if err := t.Execute(outFD, pluginList); err != nil {
  117. log.Fatalf("Template execution failed: %v", err)
  118. }
  119. log.Printf("Generated file '%s'. You can build it by running 'go build' in the output directory.", outfile)
  120. }