main.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
  2. // license. Its contents can be found at:
  3. // http://creativecommons.org/publicdomain/zero/1.0/
  4. package main
  5. import (
  6. "flag"
  7. "fmt"
  8. "github.com/jteeuwen/go-bindata/lib"
  9. "os"
  10. "path"
  11. "path/filepath"
  12. "unicode"
  13. )
  14. var (
  15. pipe = false
  16. in = ""
  17. out = flag.String("out", "", "Optional path and name of the output file.")
  18. pkgname = flag.String("pkg", "main", "Name of the package to generate.")
  19. funcname = flag.String("func", "", "Optional name of the function to generate.")
  20. prefix = flag.String("prefix", "", "Optional path prefix to strip off map keys and function names.")
  21. uncompressed = flag.Bool("uncompressed", false, "The specified resource will /not/ be GZIP compressed when this flag is specified. This alters the generated output code.")
  22. nomemcopy = flag.Bool("nomemcopy", false, "Use a .rodata hack to get rid of unnecessary memcopies. Refer to the documentation to see what implications this carries.")
  23. tags = flag.String("tags", "", "Optional build tags")
  24. toc = flag.Bool("toc", false, "Generate a table of contents for this and other files. The input filepath becomes the map key. This option is only useable in non-pipe mode.")
  25. version = flag.Bool("version", false, "Display version information.")
  26. )
  27. func main() {
  28. parseArgs()
  29. if pipe {
  30. bindata.Translate(os.Stdin, os.Stdout, *pkgname, *funcname, *uncompressed, *nomemcopy)
  31. return
  32. }
  33. fs, err := os.Open(in)
  34. if err != nil {
  35. fmt.Fprintf(os.Stderr, "[e] %s\n", err)
  36. return
  37. }
  38. defer fs.Close()
  39. fd, err := os.Create(*out)
  40. if err != nil {
  41. fmt.Fprintf(os.Stderr, "[e] %s\n", err)
  42. return
  43. }
  44. defer fd.Close()
  45. if *tags != "" {
  46. fmt.Fprintf(fd, "// +build %s\n\n", *tags)
  47. }
  48. // Translate binary to Go code.
  49. bindata.Translate(fs, fd, *pkgname, *funcname, *uncompressed, *nomemcopy)
  50. // Append the TOC init function to the end of the output file and
  51. // write the `bindata-toc.go` file, if applicable.
  52. if *toc {
  53. dir, _ := filepath.Split(*out)
  54. err := bindata.CreateTOC(dir, *pkgname)
  55. if err != nil {
  56. fmt.Fprintf(os.Stderr, "[e] %s\n", err)
  57. return
  58. }
  59. bindata.WriteTOCInit(fd, in, *prefix, *funcname)
  60. }
  61. }
  62. // parseArgs processes and verifies commandline arguments.
  63. func parseArgs() {
  64. flag.Usage = func() {
  65. fmt.Printf("Usage: %s [options] <filename>\n\n", os.Args[0])
  66. flag.PrintDefaults()
  67. }
  68. flag.Parse()
  69. if *version {
  70. fmt.Printf("%s\n", bindata.Version())
  71. os.Exit(0)
  72. }
  73. pipe = flag.NArg() == 0
  74. if !pipe {
  75. *prefix, _ = filepath.Abs(filepath.Clean(*prefix))
  76. in, _ = filepath.Abs(filepath.Clean(flag.Args()[0]))
  77. *out = safeFilename(*out, in)
  78. }
  79. if len(*pkgname) == 0 {
  80. fmt.Fprintln(os.Stderr, "[w] No package name specified. Using 'main'.")
  81. *pkgname = "main"
  82. } else {
  83. if unicode.IsDigit(rune((*pkgname)[0])) {
  84. // Identifier can't start with a digit.
  85. *pkgname = "_" + *pkgname
  86. }
  87. }
  88. if len(*funcname) == 0 {
  89. if pipe {
  90. // Can't infer from input file name in this mode.
  91. fmt.Fprintln(os.Stderr, "[e] No function name specified.")
  92. os.Exit(1)
  93. }
  94. *funcname = bindata.SafeFuncname(in, *prefix)
  95. fmt.Fprintf(os.Stderr, "[w] No function name specified. Using %s.\n", *funcname)
  96. }
  97. }
  98. // safeFilename creates a safe output filename from the given
  99. // output and input paths.
  100. func safeFilename(out, in string) string {
  101. var filename string
  102. if len(out) == 0 {
  103. filename = in + ".go"
  104. _, err := os.Lstat(filename)
  105. if err == nil {
  106. // File already exists. Pad name with a sequential number until we
  107. // find a name that is available.
  108. count := 0
  109. for {
  110. filename = path.Join(out, fmt.Sprintf("%s.%d.go", in, count))
  111. _, err = os.Lstat(filename)
  112. if err != nil {
  113. break
  114. }
  115. count++
  116. }
  117. }
  118. } else {
  119. filename, _ = filepath.Abs(filepath.Clean(out))
  120. }
  121. // Ensure output directory exists while we're here.
  122. dir, _ := filepath.Split(filename)
  123. _, err := os.Lstat(dir)
  124. if err != nil {
  125. os.MkdirAll(dir, 0755)
  126. }
  127. return filename
  128. }