fix: skip non-existent command dirs instead of creating them (#2534)

lif created

Check if the command source directory exists before walking it.
If it doesn't exist, return early with no commands instead of
auto-creating it via MkdirAll. Remove the now-unused ensureDir
helper.

Fixes #2526

Signed-off-by: majiayu000 <1835304752@qq.com>

Change summary

internal/commands/commands.go      | 11 +-----
internal/commands/commands_test.go | 53 ++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+), 9 deletions(-)

Detailed changes

internal/commands/commands.go 🔗

@@ -130,8 +130,8 @@ func loadAll(sources []commandSource) ([]CustomCommand, error) {
 }
 
 func loadFromSource(source commandSource) ([]CustomCommand, error) {
-	if err := ensureDir(source.path); err != nil {
-		return nil, err
+	if _, err := os.Stat(source.path); os.IsNotExist(err) {
+		return nil, nil
 	}
 
 	var commands []CustomCommand
@@ -216,13 +216,6 @@ func getXDGCommandsDir() string {
 	return ""
 }
 
-func ensureDir(path string) error {
-	if _, err := os.Stat(path); os.IsNotExist(err) {
-		return os.MkdirAll(path, 0o755)
-	}
-	return nil
-}
-
 func isMarkdownFile(name string) bool {
 	return strings.HasSuffix(strings.ToLower(name), ".md")
 }

internal/commands/commands_test.go 🔗

@@ -0,0 +1,53 @@
+package commands
+
+import (
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestLoadFromSource_NonExistentDir(t *testing.T) {
+	t.Parallel()
+
+	dir := filepath.Join(t.TempDir(), "does-not-exist")
+
+	cmds, err := loadFromSource(commandSource{path: dir, prefix: userCommandPrefix})
+	require.NoError(t, err)
+	require.Empty(t, cmds)
+
+	// directory must NOT have been created
+	_, statErr := os.Stat(dir)
+	require.True(t, os.IsNotExist(statErr))
+}
+
+func TestLoadFromSource_ExistingDir(t *testing.T) {
+	t.Parallel()
+
+	dir := t.TempDir()
+	require.NoError(t, os.WriteFile(filepath.Join(dir, "hello.md"), []byte("say hello"), 0o644))
+
+	cmds, err := loadFromSource(commandSource{path: dir, prefix: userCommandPrefix})
+	require.NoError(t, err)
+	require.Len(t, cmds, 1)
+	require.Equal(t, "user:hello", cmds[0].ID)
+	require.Equal(t, "say hello", cmds[0].Content)
+}
+
+func TestLoadAll_MixedSources(t *testing.T) {
+	t.Parallel()
+
+	existing := t.TempDir()
+	require.NoError(t, os.WriteFile(filepath.Join(existing, "cmd.md"), []byte("content"), 0o644))
+
+	missing := filepath.Join(t.TempDir(), "nope")
+
+	cmds, err := loadAll([]commandSource{
+		{path: existing, prefix: userCommandPrefix},
+		{path: missing, prefix: projectCommandPrefix},
+	})
+	require.NoError(t, err)
+	require.Len(t, cmds, 1)
+	require.Equal(t, "user:cmd", cmds[0].ID)
+}