| // Command gendoc can be used for generating detailed godoc comments |
| // for cmdline-based tools. The user specifies the cmdline-based tool |
| // source file directory <dir> using the first command-line argument |
| // and gendoc executes the tool with flags that generate detailed |
| // godoc comment and output it to <dir>/doc.go. If more than one |
| // command-line argument is provided, they are passed through to the |
| // tool the gendoc executes. |
| // |
| // NOTE: The reason this command is located in under a testdata |
| // directory is to enforce its idiomatic use through "go run |
| // <path>/testdata/gendoc.go <dir> [args]". |
| // |
| // NOTE: The gendoc command itself is not based on the cmdline library |
| // to avoid non-trivial bootstrapping. In particular, if the |
| // compilation of gendoc requires GOPATH to contain the vanadium Go |
| // workspaces, then running the gendoc command requires the v23 tool, |
| // which in turn my depend on the gendoc command. |
| package main |
| |
| import ( |
| "bytes" |
| "fmt" |
| "io/ioutil" |
| "os" |
| "os/exec" |
| "path/filepath" |
| "strings" |
| ) |
| |
| func main() { |
| if err := generate(); err != nil { |
| fmt.Fprintln(os.Stderr, err) |
| os.Exit(1) |
| } |
| } |
| |
| func generate() error { |
| if got, want := len(os.Args[1:]), 1; got < want { |
| return fmt.Errorf("gendoc requires at least one argument\nusage: gendoc <dir> [args]") |
| } |
| pkg := os.Args[1] |
| |
| // Build the gendoc binary in a temporary folder. |
| tmpDir, err := ioutil.TempDir("", "") |
| if err != nil { |
| return fmt.Errorf("TempDir() failed: %v", err) |
| } |
| defer os.RemoveAll(tmpDir) |
| gendocBin := filepath.Join(tmpDir, "gendoc") |
| args := []string{"go", "build", "-o", gendocBin} |
| args = append(args, pkg) |
| buildCmd := exec.Command("v23", args...) |
| if err := buildCmd.Run(); err != nil { |
| return fmt.Errorf("%q failed: %v\n", strings.Join(buildCmd.Args, " "), err) |
| } |
| |
| // Use it to generate the documentation. |
| var out bytes.Buffer |
| if len(os.Args) == 2 { |
| args = []string{"help", "-style=godoc", "..."} |
| } else { |
| args = os.Args[2:] |
| } |
| runCmd := exec.Command(gendocBin, args...) |
| runCmd.Stdout = &out |
| if err := runCmd.Run(); err != nil { |
| return fmt.Errorf("%q failed: %v\n%v\n", strings.Join(runCmd.Args, " "), err) |
| } |
| doc := fmt.Sprintf(`// This file was auto-generated via go generate. |
| // DO NOT UPDATE MANUALLY |
| |
| /* |
| %s*/ |
| package main |
| `, out.String()) |
| |
| // Write the result to doc.go. |
| path, perm := filepath.Join(pkg, "doc.go"), os.FileMode(0644) |
| if err := ioutil.WriteFile(path, []byte(doc), perm); err != nil { |
| return fmt.Errorf("WriteFile(%v, %v) failed: %v\n", path, perm, err) |
| } |
| return nil |
| } |