diff --git a/go/cmd/internal/docgen/docgen.go b/go/cmd/internal/docgen/docgen.go index f52042e80af..ab38e9420bc 100644 --- a/go/cmd/internal/docgen/docgen.go +++ b/go/cmd/internal/docgen/docgen.go @@ -116,7 +116,6 @@ func restructure(rootDir string, dir string, name string, commands []*cobra.Comm fullCmdFilename := strings.Join([]string{name, cmd.Name()}, "_") children := cmd.Commands() - switch { case len(children) > 0: // Command (top-level or not) with children. @@ -151,7 +150,6 @@ func restructure(rootDir string, dir string, name string, commands []*cobra.Comm oldName := filepath.Join(rootDir, fullCmdFilename+".md") newName := filepath.Join(dir, fullCmdFilename+".md") - if err := os.Rename(oldName, newName); err != nil { return fmt.Errorf("failed to move child command %s to its parent's dir: %w", fullCmdFilename, err) } @@ -166,6 +164,14 @@ func restructure(rootDir string, dir string, name string, commands []*cobra.Comm } default: // Top-level command without children. Nothing to restructure. + // However we still need to anonymize the homedir in the help text. + if cmd.Name() == "help" { + // all commands with children have their own "help" subcommand, + // which we do not generate docs for + continue + } + f := filepath.Join(dir, fullCmdFilename+".md") + _ = anonymizeHomedir(f) // it is possible that the file does not exist, so we ignore the error continue } } @@ -190,11 +196,14 @@ func anonymizeHomedir(file string) (err error) { if err != nil { return err } + if _, err := os.Stat(file); err != nil { + return nil + } // We're replacing the stuff inside the square brackets in the example sed // below: // 's:Paths to search for config files in. (default \[.*\])$:Paths to search for config files in. (default \[\]):' - sed := exec.Command("sed", "-i", "", "-e", fmt.Sprintf("s:%s::i", wd), file) + sed := exec.Command("sed", "-i", "", "-e", fmt.Sprintf("s:%s:%s:", wd, ""), file) if out, err := sed.CombinedOutput(); err != nil { return fmt.Errorf("%w: %s", err, out) } @@ -224,7 +233,6 @@ func getCommitID(ref string) (string, error) { const frontmatter = `--- title: %s series: %s -commit: %s --- ` @@ -240,7 +248,7 @@ func frontmatterFilePrepender(sha string) func(filename string) string { cmdName = strings.ReplaceAll(cmdName, "_", " ") - return fmt.Sprintf(frontmatter, cmdName, root, sha) + return fmt.Sprintf(frontmatter, cmdName, root) } } diff --git a/go/cmd/internal/docgen/docgen_test.go b/go/cmd/internal/docgen/docgen_test.go new file mode 100644 index 00000000000..741f5ecc577 --- /dev/null +++ b/go/cmd/internal/docgen/docgen_test.go @@ -0,0 +1,191 @@ +/* +Copyright 2024 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package docgen + +import ( + "strings" + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/require" +) + +func TestGenerateMarkdownTree(t *testing.T) { + tests := []struct { + name string + dir string + cmd *cobra.Command + expectErr bool + }{ + { + name: "Empty dir", + dir: "", + cmd: &cobra.Command{}, + expectErr: true, + }, + { + name: "current dir", + dir: "./", + cmd: &cobra.Command{}, + expectErr: true, + }, + { + name: "Permission denied", + dir: "/root", + cmd: &cobra.Command{}, + expectErr: true, + }, + { + name: "Not a directory error", + dir: "./docgen.go", + cmd: &cobra.Command{}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := GenerateMarkdownTree(tt.cmd, tt.dir) + if !tt.expectErr { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} + +func TestRestructure(t *testing.T) { + rootCmd := &cobra.Command{ + Use: "root-command", + } + cmd := &cobra.Command{ + Use: "random", + } + rootCmd.AddCommand(cmd) + cmds := []*cobra.Command{rootCmd} + + tests := []struct { + name string + rootDir string + dir string + cmds []*cobra.Command + expectErr bool + }{ + { + name: "Empty commands", + cmds: []*cobra.Command{}, + }, + { + name: "Non-empty commands", + rootDir: "../", + dir: "./", + cmds: cmds, + expectErr: true, + }, + { + name: "No subcommands", + rootDir: "../", + dir: "./", + cmds: []*cobra.Command{{Use: "help"}, {Use: "test-cmd"}}, + expectErr: true, + }, + { + name: "No subcommands with rootDir and dir unset", + cmds: []*cobra.Command{{Use: "random"}}, + expectErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := restructure(tt.rootDir, tt.dir, tt.name, tt.cmds) + if !tt.expectErr { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} + +func TestLinkHandler(t *testing.T) { + tests := []struct { + name string + fileName string + expectedStr string + }{ + { + name: "Normal value", + fileName: "Some_value", + expectedStr: "./some_value/", + }, + { + name: "Abnormal value", + fileName: `./.jash13_24`, + expectedStr: "../", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + str := linkHandler(tt.fileName) + require.Equal(t, tt.expectedStr, str) + }) + } +} + +func TestNewParentLinkSedCommand(t *testing.T) { + tests := []struct { + name string + parentDir string + fileName string + expectedOutput string + }{ + { + name: "Empty values", + expectedOutput: "sed -i -e s:(.//):(../):i ", + }, + { + name: "Normal value", + parentDir: "./", + fileName: "Some_value", + expectedOutput: "sed -i -e s:(././/):(../):i Some_value", + }, + { + name: "Abnormal value", + parentDir: "/root", + fileName: `./.jash13_24`, + expectedOutput: "sed -i -e s:(.//root/):(../):i ./.jash13_24", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := newParentLinkSedCommand(tt.parentDir, tt.fileName) + // We only check for suffix because the sed command's actual path may differ on different machines. + require.True(t, strings.HasSuffix(cmd.String(), tt.expectedOutput)) + }) + } +} + +func TestGetCommitID(t *testing.T) { + // This function should return an error when the reference is not in the + // git tree. + _, err := getCommitID("invalid ref") + require.Error(t, err) +}