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  }