Skip to content

Commit 5090452

Browse files
committed
Import man/generate.go with history from docker/cli
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2 parents 4b6fbdb + ca0d6b2 commit 5090452

1 file changed

Lines changed: 123 additions & 0 deletions

File tree

man/generate.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"log"
7+
"os"
8+
"path/filepath"
9+
"strconv"
10+
"time"
11+
12+
"github.com/docker/cli/cli/command"
13+
"github.com/docker/cli/cli/command/commands"
14+
"github.com/spf13/cobra"
15+
"github.com/spf13/cobra/doc"
16+
"github.com/spf13/pflag"
17+
)
18+
19+
const descriptionSourcePath = "man/src/"
20+
21+
func generateManPages(opts *options) error {
22+
header := &doc.GenManHeader{
23+
Title: "DOCKER",
24+
Section: "1",
25+
Source: "Docker Community",
26+
Manual: "Docker User Manuals",
27+
}
28+
29+
// If SOURCE_DATE_EPOCH is set, in order to allow reproducible package
30+
// builds, we explicitly set the build time to SOURCE_DATE_EPOCH.
31+
if epoch := os.Getenv("SOURCE_DATE_EPOCH"); epoch != "" {
32+
unixEpoch, err := strconv.ParseInt(epoch, 10, 64)
33+
if err != nil {
34+
return fmt.Errorf("invalid SOURCE_DATE_EPOCH: %v", err)
35+
}
36+
now := time.Unix(unixEpoch, 0)
37+
header.Date = &now
38+
}
39+
40+
dockerCli, err := command.NewDockerCli()
41+
if err != nil {
42+
return err
43+
}
44+
cmd := &cobra.Command{Use: "docker"}
45+
commands.AddCommands(cmd, dockerCli)
46+
source := filepath.Join(opts.source, descriptionSourcePath)
47+
if err := loadLongDescription(cmd, source); err != nil {
48+
return err
49+
}
50+
51+
cmd.DisableAutoGenTag = true
52+
cmd.DisableFlagsInUseLine = true
53+
return doc.GenManTreeFromOpts(cmd, doc.GenManTreeOptions{
54+
Header: header,
55+
Path: opts.target,
56+
CommandSeparator: "-",
57+
})
58+
}
59+
60+
func loadLongDescription(cmd *cobra.Command, path string) error {
61+
for _, cmd := range cmd.Commands() {
62+
cmd.DisableFlagsInUseLine = true
63+
if cmd.Name() == "" {
64+
continue
65+
}
66+
fullpath := filepath.Join(path, cmd.Name()+".md")
67+
68+
if cmd.HasSubCommands() {
69+
loadLongDescription(cmd, filepath.Join(path, cmd.Name()))
70+
}
71+
72+
if _, err := os.Stat(fullpath); err != nil {
73+
log.Printf("WARN: %s does not exist, skipping\n", fullpath)
74+
continue
75+
}
76+
77+
content, err := ioutil.ReadFile(fullpath)
78+
if err != nil {
79+
return err
80+
}
81+
cmd.Long = string(content)
82+
83+
fullpath = filepath.Join(path, cmd.Name()+"-example.md")
84+
if _, err := os.Stat(fullpath); err != nil {
85+
continue
86+
}
87+
88+
content, err = ioutil.ReadFile(fullpath)
89+
if err != nil {
90+
return err
91+
}
92+
cmd.Example = string(content)
93+
94+
}
95+
return nil
96+
}
97+
98+
type options struct {
99+
source string
100+
target string
101+
}
102+
103+
func parseArgs() (*options, error) {
104+
opts := &options{}
105+
cwd, _ := os.Getwd()
106+
flags := pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError)
107+
flags.StringVar(&opts.source, "root", cwd, "Path to project root")
108+
flags.StringVar(&opts.target, "target", "/tmp", "Target path for generated man pages")
109+
err := flags.Parse(os.Args[1:])
110+
return opts, err
111+
}
112+
113+
func main() {
114+
opts, err := parseArgs()
115+
if err != nil {
116+
fmt.Fprintln(os.Stderr, err.Error())
117+
}
118+
fmt.Printf("Project root: %s\n", opts.source)
119+
fmt.Printf("Generating man pages into %s\n", opts.target)
120+
if err := generateManPages(opts); err != nil {
121+
fmt.Fprintf(os.Stderr, "Failed to generate man pages: %s\n", err.Error())
122+
}
123+
}

0 commit comments

Comments
 (0)