-
Notifications
You must be signed in to change notification settings - Fork 243
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat : generate manpages for cli during crc setup (#4181)
+ crc should generate manpages for all sub commands and place them in `~/.local/share/man/man1` directory + These man pages would only be generated once, crc would skip generation if it detects man pages already present in target directory + These generated man pages would be cleaned up during `crc cleanup` Signed-off-by: Rohan Kumar <rohaan@redhat.com>
- Loading branch information
1 parent
9537264
commit 080022d
Showing
32 changed files
with
9,965 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package cmd | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestCrcManPageGenerator_WhenInvoked_GeneratesManPagesForAllCrcSubCommands(t *testing.T) { | ||
// Given | ||
dir := t.TempDir() | ||
|
||
// When | ||
err := crcManPageGenerator(dir) | ||
|
||
// Then | ||
assert.NoError(t, err) | ||
files, readErr := os.ReadDir(dir) | ||
assert.NoError(t, readErr) | ||
var manPagesFiles []string | ||
for _, manPage := range files { | ||
manPagesFiles = append(manPagesFiles, manPage.Name()) | ||
} | ||
assert.ElementsMatch(t, []string{ | ||
"crc-bundle-generate.1", | ||
"crc-bundle.1", | ||
"crc-cleanup.1", | ||
"crc-config-get.1", | ||
"crc-config-set.1", | ||
"crc-config-unset.1", | ||
"crc-config-view.1", | ||
"crc-config.1", | ||
"crc-console.1", | ||
"crc-delete.1", | ||
"crc-ip.1", | ||
"crc-oc-env.1", | ||
"crc-podman-env.1", | ||
"crc-setup.1", | ||
"crc-start.1", | ||
"crc-status.1", | ||
"crc-stop.1", | ||
"crc-version.1", | ||
"crc.1", | ||
}, manPagesFiles) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
package adminhelper | ||
|
||
import ( | ||
"compress/gzip" | ||
"fmt" | ||
"io" | ||
"os" | ||
"path/filepath" | ||
"runtime" | ||
"strings" | ||
|
||
"github.com/spf13/cobra/doc" | ||
|
||
"github.com/crc-org/crc/v2/pkg/crc/logging" | ||
) | ||
|
||
var ( | ||
rootCrcManPage = "crc.1.gz" | ||
operatingSystem = runtime.GOOS | ||
osEnvGetter = os.Getenv | ||
osEnvSetter = os.Setenv | ||
CrcManPageHeader = &doc.GenManHeader{ | ||
Title: "CRC", | ||
Section: "1", | ||
} | ||
) | ||
|
||
func GenerateManPages(manPageGenerator func(targetDir string) error, targetDir string) error { | ||
manUserCommandTargetFolder := filepath.Join(targetDir, "man1") | ||
if shouldGenerateManPages(manUserCommandTargetFolder) { | ||
if _, err := os.Stat(manUserCommandTargetFolder); os.IsNotExist(err) { | ||
err = os.MkdirAll(manUserCommandTargetFolder, 0755) | ||
if err != nil { | ||
logging.Errorf("error in creating dir for man pages: %s", err.Error()) | ||
} | ||
} | ||
temporaryManPagesDir, err := generateManPagesInTemporaryDirectory(manPageGenerator) | ||
if err != nil { | ||
return err | ||
} | ||
err = compressManPages(temporaryManPagesDir, manUserCommandTargetFolder) | ||
if err != nil { | ||
return fmt.Errorf("error in compressing man pages: %s", err.Error()) | ||
} | ||
err = updateManPathEnvironmentVariable(targetDir) | ||
if err != nil { | ||
return fmt.Errorf("error updating MANPATH environment variable: %s", err.Error()) | ||
} | ||
err = os.RemoveAll(temporaryManPagesDir) | ||
if err != nil { | ||
return fmt.Errorf("error removing temporary man pages directory: %s", err.Error()) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func updateManPathEnvironmentVariable(folder string) error { | ||
manPath := osEnvGetter("MANPATH") | ||
if !manPathAlreadyContains(folder, manPath) { | ||
if manPath == "" { | ||
manPath = folder | ||
} else { | ||
manPath = fmt.Sprintf("%s%c%s", manPath, os.PathListSeparator, folder) | ||
} | ||
err := osEnvSetter("MANPATH", manPath) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func manPathAlreadyContains(manPathEnvVarValue string, folder string) bool { | ||
manDirs := strings.Split(manPathEnvVarValue, string(os.PathListSeparator)) | ||
for _, manDir := range manDirs { | ||
if manDir == folder { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func generateManPagesInTemporaryDirectory(manPageGenerator func(targetDir string) error) (string, error) { | ||
tempDir, err := os.MkdirTemp("", "crc-manpages") | ||
if err != nil { | ||
return "", err | ||
} | ||
manPagesGenerationErr := manPageGenerator(tempDir) | ||
if manPagesGenerationErr != nil { | ||
return "", manPagesGenerationErr | ||
} | ||
logging.Debugf("Successfully generated manpages in %s", tempDir) | ||
return tempDir, nil | ||
} | ||
|
||
func compressManPages(manPagesSourceFolder string, manPagesTargetFolder string) error { | ||
return filepath.Walk(manPagesSourceFolder, func(path string, info os.FileInfo, err error) error { | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if info.IsDir() { | ||
return nil | ||
} | ||
|
||
srcFile, err := os.Open(path) | ||
if err != nil { | ||
return err | ||
} | ||
defer srcFile.Close() | ||
|
||
compressedFilePath := filepath.Join(manPagesTargetFolder, info.Name()+".gz") | ||
compressedFile, err := os.Create(compressedFilePath) | ||
if err != nil { | ||
return err | ||
} | ||
defer compressedFile.Close() | ||
|
||
gzipWriter := gzip.NewWriter(compressedFile) | ||
defer gzipWriter.Close() | ||
|
||
_, err = io.Copy(gzipWriter, srcFile) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
}) | ||
} | ||
|
||
func manPagesAlreadyGenerated(manPagesTargetFolder string) bool { | ||
rootCrcManPageFilePath := filepath.Join(manPagesTargetFolder, rootCrcManPage) | ||
if _, err := os.Stat(rootCrcManPageFilePath); os.IsNotExist(err) { | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
func shouldGenerateManPages(manUserCommandTargetFolder string) bool { | ||
return operatingSystem != "windows" && !manPagesAlreadyGenerated(manUserCommandTargetFolder) | ||
} | ||
|
||
func RemoveCrcManPages(manPageDir string) error { | ||
manUserCommandTargetFolder := filepath.Join(manPageDir, "man1") | ||
err := filepath.Walk(manUserCommandTargetFolder, func(path string, info os.FileInfo, err error) error { | ||
if err != nil { | ||
return err | ||
} | ||
if !info.IsDir() && filepath.Base(path)[:len("crc")] == "crc" { | ||
err = os.Remove(path) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
}) | ||
return err | ||
} |
Oops, something went wrong.