mirror of
https://github.com/cheat/cheat.git
synced 2026-03-07 03:03:32 +01:00
fix: comment out community cheatpath in --init output (#773)
cheat --init now comments out the community cheatpath by default and includes a git clone instruction with the resolved path. This prevents warnings about missing directories when users save the --init output as their config without also cloning community cheatsheets. Closes #773 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -62,6 +62,20 @@ func cmdInit() {
|
|||||||
configs = strings.Replace(configs, "EDITOR_PATH", editor, -1)
|
configs = strings.Replace(configs, "EDITOR_PATH", editor, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// comment out the community cheatpath by default, since the directory
|
||||||
|
// won't exist until the user clones it
|
||||||
|
configs = strings.Replace(configs,
|
||||||
|
" - name: community\n"+
|
||||||
|
" path: "+community+"\n"+
|
||||||
|
" tags: [ community ]\n"+
|
||||||
|
" readonly: true",
|
||||||
|
" #- name: community\n"+
|
||||||
|
" # path: "+community+"\n"+
|
||||||
|
" # tags: [ community ]\n"+
|
||||||
|
" # readonly: true",
|
||||||
|
-1,
|
||||||
|
)
|
||||||
|
|
||||||
// output the templated configs
|
// output the templated configs
|
||||||
fmt.Println(configs)
|
fmt.Println(configs)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ cheatpaths:
|
|||||||
tags: [ work ]
|
tags: [ work ]
|
||||||
readonly: false
|
readonly: false
|
||||||
|
|
||||||
# Community cheatsheets are stored here by default:
|
# Community cheatsheets (https://github.com/cheat/cheatsheets):
|
||||||
|
# To install: git clone https://github.com/cheat/cheatsheets COMMUNITY_PATH
|
||||||
- name: community
|
- name: community
|
||||||
path: COMMUNITY_PATH
|
path: COMMUNITY_PATH
|
||||||
tags: [ community ]
|
tags: [ community ]
|
||||||
|
|||||||
@@ -24,6 +24,59 @@ func TestFirstRunIntegration(t *testing.T) {
|
|||||||
t.Fatalf("failed to build cheat: %v\nOutput: %s", err, output)
|
t.Fatalf("failed to build cheat: %v\nOutput: %s", err, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Run("init comments out community", func(t *testing.T) {
|
||||||
|
testHome := t.TempDir()
|
||||||
|
env := firstRunEnv(testHome)
|
||||||
|
|
||||||
|
cmd := exec.Command(binPath, "--init")
|
||||||
|
cmd.Env = env
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("--init failed: %v\nOutput: %s", err, output)
|
||||||
|
}
|
||||||
|
outStr := string(output)
|
||||||
|
|
||||||
|
// No placeholder strings should survive (regression for #721)
|
||||||
|
assertNoPlaceholders(t, outStr)
|
||||||
|
|
||||||
|
// Community cheatpath should be commented out
|
||||||
|
assertCommunityCommentedOut(t, outStr)
|
||||||
|
|
||||||
|
// Personal and work cheatpaths should be active (uncommented)
|
||||||
|
assertCheatpathActive(t, outStr, "personal")
|
||||||
|
assertCheatpathActive(t, outStr, "work")
|
||||||
|
|
||||||
|
// Should include clone instructions
|
||||||
|
if !strings.Contains(outStr, "git clone") {
|
||||||
|
t.Error("expected git clone instructions in --init output")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the config and verify it loads without errors.
|
||||||
|
// --init only outputs config, it doesn't create directories,
|
||||||
|
// so we need to create the cheatpath dirs the config references.
|
||||||
|
confpath := filepath.Join(testHome, "conf.yml")
|
||||||
|
if err := os.WriteFile(confpath, output, 0644); err != nil {
|
||||||
|
t.Fatalf("failed to write config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the confdir that --init used (same logic as cmd_init.go)
|
||||||
|
initConfpaths := firstRunConfpaths(testHome)
|
||||||
|
initConfdir := filepath.Dir(initConfpaths[0])
|
||||||
|
for _, name := range []string{"personal", "work"} {
|
||||||
|
dir := filepath.Join(initConfdir, "cheatsheets", name)
|
||||||
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||||
|
t.Fatalf("failed to create %s dir: %v", name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd2 := exec.Command(binPath, "--directories")
|
||||||
|
cmd2.Env = append(append([]string{}, env...), "CHEAT_CONFIG_PATH="+confpath)
|
||||||
|
output2, err := cmd2.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("config from --init failed to load: %v\nOutput: %s", err, output2)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("decline config creation", func(t *testing.T) {
|
t.Run("decline config creation", func(t *testing.T) {
|
||||||
testHome := t.TempDir()
|
testHome := t.TempDir()
|
||||||
env := firstRunEnv(testHome)
|
env := firstRunEnv(testHome)
|
||||||
@@ -67,19 +120,22 @@ func TestFirstRunIntegration(t *testing.T) {
|
|||||||
t.Fatalf("config file not found at %s", confpath)
|
t.Fatalf("config file not found at %s", confpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify community cheatpath is commented out in config
|
// Verify config file contents
|
||||||
content, err := os.ReadFile(confpath)
|
content, err := os.ReadFile(confpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to read config: %v", err)
|
t.Fatalf("failed to read config: %v", err)
|
||||||
}
|
}
|
||||||
contentStr := string(content)
|
contentStr := string(content)
|
||||||
for _, line := range strings.Split(contentStr, "\n") {
|
|
||||||
trimmed := strings.TrimSpace(line)
|
// No placeholder strings should survive (regression for #721)
|
||||||
if trimmed == "- name: community" {
|
assertNoPlaceholders(t, contentStr)
|
||||||
t.Error("community cheatpath should be commented out")
|
|
||||||
break
|
// Community cheatpath should be commented out
|
||||||
}
|
assertCommunityCommentedOut(t, contentStr)
|
||||||
}
|
|
||||||
|
// Personal and work cheatpaths should be active (uncommented)
|
||||||
|
assertCheatpathActive(t, contentStr, "personal")
|
||||||
|
assertCheatpathActive(t, contentStr, "work")
|
||||||
|
|
||||||
// Verify personal and work directories were created
|
// Verify personal and work directories were created
|
||||||
confdir := filepath.Dir(confpath)
|
confdir := filepath.Dir(confpath)
|
||||||
@@ -163,6 +219,74 @@ func parseCreatedConfPath(t *testing.T, output string) string {
|
|||||||
return strings.TrimSpace(rest)
|
return strings.TrimSpace(rest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// firstRunConfpaths returns the config file paths that cheat would check
|
||||||
|
// for the given home directory, matching the logic in config.Paths().
|
||||||
|
func firstRunConfpaths(home string) []string {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
return []string{
|
||||||
|
filepath.Join(home, "AppData", "Roaming", "cheat", "conf.yml"),
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return []string{
|
||||||
|
filepath.Join(home, ".config", "cheat", "conf.yml"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// assertNoPlaceholders verifies that no template placeholder strings survived
|
||||||
|
// in the config output. This is the regression check for #721 (literal
|
||||||
|
// PAGER_PATH appearing in the config).
|
||||||
|
func assertNoPlaceholders(t *testing.T, content string) {
|
||||||
|
t.Helper()
|
||||||
|
placeholders := []string{
|
||||||
|
"PAGER_PATH",
|
||||||
|
"COMMUNITY_PATH",
|
||||||
|
"PERSONAL_PATH",
|
||||||
|
"WORK_PATH",
|
||||||
|
}
|
||||||
|
for _, p := range placeholders {
|
||||||
|
if strings.Contains(content, p) {
|
||||||
|
t.Errorf("placeholder %q was not replaced in config", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// EDITOR_PATH is special: it survives if no editor is found.
|
||||||
|
// In our test env EDITOR=vi is set, so it should be replaced.
|
||||||
|
if strings.Contains(content, "editor: EDITOR_PATH") {
|
||||||
|
t.Error("placeholder EDITOR_PATH was not replaced in config")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// assertCommunityCommentedOut verifies that the community cheatpath entry
|
||||||
|
// is commented out (not active) in the config.
|
||||||
|
func assertCommunityCommentedOut(t *testing.T, content string) {
|
||||||
|
t.Helper()
|
||||||
|
for _, line := range strings.Split(content, "\n") {
|
||||||
|
trimmed := strings.TrimSpace(line)
|
||||||
|
if trimmed == "- name: community" {
|
||||||
|
t.Error("community cheatpath should be commented out")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !strings.Contains(content, "#- name: community") {
|
||||||
|
t.Error("expected commented-out community cheatpath")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// assertCheatpathActive verifies that a named cheatpath is present and
|
||||||
|
// uncommented in the config.
|
||||||
|
func assertCheatpathActive(t *testing.T, content string, name string) {
|
||||||
|
t.Helper()
|
||||||
|
marker := "- name: " + name
|
||||||
|
for _, line := range strings.Split(content, "\n") {
|
||||||
|
trimmed := strings.TrimSpace(line)
|
||||||
|
if trimmed == marker {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Errorf("expected active (uncommented) cheatpath %q", name)
|
||||||
|
}
|
||||||
|
|
||||||
// firstRunConfigExists checks whether a cheat config file exists under the
|
// firstRunConfigExists checks whether a cheat config file exists under the
|
||||||
// given home directory at any of the standard locations.
|
// given home directory at any of the standard locations.
|
||||||
func firstRunConfigExists(home string) bool {
|
func firstRunConfigExists(home string) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user