github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/cmd/examplegen/generator.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "log" 8 "os" 9 "path/filepath" 10 "strings" 11 ) 12 13 func generateMarkdown(c *Config) error { 14 f, err := os.Create(c.MarkdownOut) 15 if err != nil { 16 return fmt.Errorf("create %s: %v", c.MarkdownOut, err) 17 } 18 defer f.Close() 19 20 var workspace, buildIn, buildOut, protoFile string 21 for _, src := range c.Files { 22 base := filepath.Base(src) 23 ext := filepath.Ext(base) 24 25 if ext == ".proto" { 26 protoFile = src 27 continue 28 } 29 30 switch base { 31 case "BUILD.in": 32 buildIn = src 33 case "BUILD.out": 34 buildOut = src 35 case "WORKSPACE": 36 workspace = src 37 } 38 } 39 40 if buildIn == "" { 41 log.Panicf("BUILD.in not found: %+v", c) 42 } 43 if buildOut == "" { 44 log.Panicf("BUILD.out not found: %+v", c) 45 } 46 47 fmt.Fprintf(f, "---\n") 48 fmt.Fprintf(f, "layout: default\n") 49 fmt.Fprintf(f, "title: %s\n", c.Name) 50 fmt.Fprintf(f, "permalink: examples/%s\n", c.Name) 51 fmt.Fprintf(f, "parent: Examples\n") 52 fmt.Fprintf(f, "---\n\n\n") 53 54 fmt.Fprintf(f, "# %s example\n\n", c.Name) 55 56 fmt.Fprintf(f, "`bazel test %s_test`\n\n", c.Label) 57 58 fmt.Fprintf(f, "\n## `BUILD.bazel` (after gazelle)\n\n") 59 if err := printFileBlock("BUILD.bazel", "python", buildOut, f); err != nil { 60 return err 61 } 62 63 fmt.Fprintf(f, "\n## `BUILD.bazel` (before gazelle)\n\n") 64 if err := printFileBlock("BUILD.bazel", "python", buildIn, f); err != nil { 65 return err 66 } 67 68 fmt.Fprintf(f, "\n## `WORKSPACE`\n\n") 69 if err := printFileBlock(filepath.Base(workspace), "python", workspace, f); err != nil { 70 return err 71 } 72 73 if false { 74 if err := printFileBlock(filepath.Base(protoFile), "proto", protoFile, f); err != nil { 75 return err 76 } 77 } 78 79 return nil 80 } 81 82 func generateTest(c *Config) error { 83 f, err := os.Create(c.TestOut) 84 if err != nil { 85 return fmt.Errorf("create %s: %v", c.TestOut, err) 86 } 87 defer f.Close() 88 89 fmt.Fprintln(f, testHeader) 90 fmt.Fprintln(f, c.TestContent) 91 92 fmt.Fprintln(f, "var txtar=`") 93 94 fmt.Fprintf(f, "-- WORKSPACE --\n") 95 data, err := ioutil.ReadFile(c.WorkspaceIn) 96 if err != nil { 97 return fmt.Errorf("read %q: %v", c.WorkspaceIn, err) 98 } 99 if _, err := f.Write(data); err != nil { 100 return fmt.Errorf("write %q: %v", c.WorkspaceIn, err) 101 } 102 // seek out the WORKSPACE file and append it now such that the WORKSPACE in 103 // the testdata is concatenated with the config.WorkspaceIn. 104 for _, src := range c.Files { 105 if filepath.Base(src) != "WORKSPACE" { 106 continue 107 } 108 data, err := ioutil.ReadFile(src) 109 if err != nil { 110 return fmt.Errorf("read %q: %v", src, err) 111 } 112 f.WriteString("\n") 113 if _, err := f.Write(data); err != nil { 114 return fmt.Errorf("write: %v", err) 115 } 116 break 117 } 118 119 for _, src := range c.Files { 120 dst := mapFilename(src) 121 if dst == "" { 122 continue 123 } 124 125 dstFilename := filepath.Base(dst) 126 if c.StripPrefix != "" { 127 dstFilename = stripRel(c.StripPrefix, dst) 128 } 129 130 fmt.Fprintf(f, "-- %s --\n", dstFilename) 131 132 data, err := ioutil.ReadFile(src) 133 if err != nil { 134 return fmt.Errorf("read %q: %v", src, err) 135 } 136 if _, err := f.Write(data); err != nil { 137 return fmt.Errorf("write %q: %v", dst, err) 138 } 139 f.WriteString("\n") 140 } 141 142 fmt.Fprintln(f, "`") 143 144 return nil 145 } 146 147 func mapFilename(in string) string { 148 dir := filepath.Dir(in) 149 base := filepath.Base(in) 150 151 switch base { 152 case "WORKSPACE": 153 return "" 154 case "BUILD.in": 155 return "" 156 case "BUILD.out": 157 return filepath.Join(dir, "BUILD.bazel") 158 } 159 160 return in 161 } 162 163 func printFileBlock(name, syntax, filename string, out io.Writer) error { 164 fmt.Fprintf(out, "~~~%s\n", syntax) 165 data, err := ioutil.ReadFile(filename) 166 if err != nil { 167 log.Panicf("%s: read %q: %v", name, filename, err) 168 } 169 if _, err := out.Write(data); err != nil { 170 log.Panicf("%s: write %q: %v", name, filename, err) 171 } 172 fmt.Fprintf(out, "~~~\n\n") 173 174 return nil 175 } 176 177 // stripRel removes the rel prefix from a filename (if has matching prefix) 178 func stripRel(rel string, filename string) string { 179 if !strings.HasPrefix(filename, rel) { 180 return filename 181 } 182 filename = filename[len(rel):] 183 return strings.TrimPrefix(filename, "/") 184 }