Skip to content

Commit 51063dd

Browse files
committed
fix: validate jq and install
1 parent 492d69e commit 51063dd

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

internal/cmd/init_spec.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ import (
2222
"fmt"
2323
"io/fs"
2424
"os"
25+
"os/exec"
2526
"path/filepath"
27+
"runtime"
2628
"strings"
2729

2830
"github.com/cloudwego/abcoder/llm/log"
@@ -43,6 +45,11 @@ type mcpServerConfig struct {
4345

4446
// runInitSpec implements the init-spec command
4547
func RunInitSpec(targetDir string) error {
48+
// Check and install jq dependency required by hook scripts
49+
if err := ensureJqInstalled(); err != nil {
50+
return fmt.Errorf("failed to ensure jq is installed: %w", err)
51+
}
52+
4653
if targetDir == "" {
4754
// Default to current directory if not specified
4855
cwd, err := os.Getwd()
@@ -264,3 +271,61 @@ For more information, see:
264271
- https://github.com/cloudwego/abcoder
265272
`, targetDir, configPath, astsDir)
266273
}
274+
275+
// ensureJqInstalled checks if jq is installed and attempts to install it if not found
276+
func ensureJqInstalled() error {
277+
if _, err := exec.LookPath("jq"); err == nil {
278+
log.Info("jq is already installed")
279+
return nil
280+
}
281+
282+
log.Info("jq not found, attempting to install...")
283+
284+
var cmd *exec.Cmd
285+
switch runtime.GOOS {
286+
case "linux":
287+
// Detect available package manager
288+
if _, err := exec.LookPath("apt-get"); err == nil {
289+
cmd = exec.Command("sudo", "apt-get", "install", "-y", "jq")
290+
} else if _, err := exec.LookPath("yum"); err == nil {
291+
cmd = exec.Command("sudo", "yum", "install", "-y", "jq")
292+
} else if _, err := exec.LookPath("dnf"); err == nil {
293+
cmd = exec.Command("sudo", "dnf", "install", "-y", "jq")
294+
} else if _, err := exec.LookPath("apk"); err == nil {
295+
cmd = exec.Command("apk", "add", "jq")
296+
} else {
297+
return fmt.Errorf("jq is required but not found, and no supported package manager (apt-get/yum/dnf/apk) was detected.\n" +
298+
"Please install jq manually:\n" +
299+
" - Ubuntu/Debian: sudo apt-get install -y jq\n" +
300+
" - CentOS/RHEL: sudo yum install -y jq\n" +
301+
" - Fedora: sudo dnf install -y jq\n" +
302+
" - Alpine: apk add jq")
303+
}
304+
case "darwin":
305+
if _, err := exec.LookPath("brew"); err == nil {
306+
cmd = exec.Command("brew", "install", "jq")
307+
} else {
308+
return fmt.Errorf("jq is required but not found, and Homebrew is not available.\n" +
309+
"Please install jq manually:\n" +
310+
" - Install Homebrew first: /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"\n" +
311+
" - Then run: brew install jq")
312+
}
313+
default:
314+
return fmt.Errorf("jq is required but not found. Automatic installation is not supported on %s.\n"+
315+
"Please install jq manually: https://jqlang.github.io/jq/download/", runtime.GOOS)
316+
}
317+
318+
cmd.Stdout = os.Stdout
319+
cmd.Stderr = os.Stderr
320+
if err := cmd.Run(); err != nil {
321+
return fmt.Errorf("failed to install jq: %w", err)
322+
}
323+
324+
// Verify jq is available after installation
325+
if _, err := exec.LookPath("jq"); err != nil {
326+
return fmt.Errorf("jq was installed but still not found in PATH. Please check your PATH configuration")
327+
}
328+
329+
log.Info("jq installed successfully")
330+
return nil
331+
}

0 commit comments

Comments
 (0)