mirror of
https://github.com/docker/cli.git
synced 2026-01-13 18:22:35 +03:00
The script was written to only take subcommands at the first and second level
into account, but failed to find the Markdown files for extended descriptions of
subcommands at the third level, such as `docker trust key generate`, and
`docker trust key load`:
WARN: /go/src/github.com/docker/cli/docs/reference/commandline/key_generate.md does not exist, skipping
WARN: /go/src/github.com/docker/cli/docs/reference/commandline/key_load.md does not exist, skipping
WARN: /go/src/github.com/docker/cli/docs/reference/commandline/signer_add.md does not exist, skipping
WARN: /go/src/github.com/docker/cli/docs/reference/commandline/signer_remove.md does not exist, skipping
This patch updates the script to accomodate subcommands that are more deeply
nested. While at it, some minor cleaning and linting issues were also addressed.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
113 lines
2.7 KiB
Go
113 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/docker/cli/cli/command"
|
|
"github.com/docker/cli/cli/command/commands"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/pflag"
|
|
)
|
|
|
|
const descriptionSourcePath = "docs/reference/commandline/"
|
|
|
|
func generateCliYaml(opts *options) error {
|
|
dockerCli, err := command.NewDockerCli()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cmd := &cobra.Command{Use: "docker"}
|
|
commands.AddCommands(cmd, dockerCli)
|
|
disableFlagsInUseLine(cmd)
|
|
source := filepath.Join(opts.source, descriptionSourcePath)
|
|
fmt.Println("Markdown source:", source)
|
|
if err := loadLongDescription(cmd, source); err != nil {
|
|
return err
|
|
}
|
|
|
|
cmd.DisableAutoGenTag = true
|
|
return GenYamlTree(cmd, opts.target)
|
|
}
|
|
|
|
func disableFlagsInUseLine(cmd *cobra.Command) {
|
|
visitAll(cmd, func(ccmd *cobra.Command) {
|
|
// do not add a `[flags]` to the end of the usage line.
|
|
ccmd.DisableFlagsInUseLine = true
|
|
})
|
|
}
|
|
|
|
// visitAll will traverse all commands from the root.
|
|
// This is different from the VisitAll of cobra.Command where only parents
|
|
// are checked.
|
|
func visitAll(root *cobra.Command, fn func(*cobra.Command)) {
|
|
for _, cmd := range root.Commands() {
|
|
visitAll(cmd, fn)
|
|
}
|
|
fn(root)
|
|
}
|
|
|
|
func loadLongDescription(parentCmd *cobra.Command, path string) error {
|
|
for _, cmd := range parentCmd.Commands() {
|
|
if cmd.HasSubCommands() {
|
|
if err := loadLongDescription(cmd, path); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
name := cmd.CommandPath()
|
|
log.Println("INFO: Generating docs for", name)
|
|
if i := strings.Index(name, " "); i >= 0 {
|
|
// remove root command / binary name
|
|
name = name[i+1:]
|
|
}
|
|
if name == "" {
|
|
continue
|
|
}
|
|
mdFile := strings.ReplaceAll(name, " ", "_") + ".md"
|
|
fullPath := filepath.Join(path, mdFile)
|
|
content, err := ioutil.ReadFile(fullPath)
|
|
if os.IsNotExist(err) {
|
|
log.Printf("WARN: %s does not exist, skipping\n", mdFile)
|
|
continue
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
description, examples := parseMDContent(string(content))
|
|
cmd.Long = description
|
|
cmd.Example = examples
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type options struct {
|
|
source string
|
|
target string
|
|
}
|
|
|
|
func parseArgs() (*options, error) {
|
|
opts := &options{}
|
|
cwd, _ := os.Getwd()
|
|
flags := pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError)
|
|
flags.StringVar(&opts.source, "root", cwd, "Path to project root")
|
|
flags.StringVar(&opts.target, "target", "/tmp", "Target path for generated yaml files")
|
|
err := flags.Parse(os.Args[1:])
|
|
return opts, err
|
|
}
|
|
|
|
func main() {
|
|
opts, err := parseArgs()
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
fmt.Println("Project root: ", opts.source)
|
|
fmt.Println("YAML output dir:", opts.target)
|
|
if err := generateCliYaml(opts); err != nil {
|
|
log.Println("Failed to generate yaml files:", err)
|
|
}
|
|
}
|