resolve checks if a command is available and installs it via install if needed. Returns the path to the usable binary.
(ctx context.Context, command, version string, install installFunc)
| 54 | // resolve checks if a command is available and installs it via install if |
| 55 | // needed. Returns the path to the usable binary. |
| 56 | func resolve(ctx context.Context, command, version string, install installFunc) (string, error) { |
| 57 | // Check system PATH first — return original command name (not full path) |
| 58 | // so the caller uses it as-is via exec.Command. |
| 59 | if _, err := exec.LookPath(command); err == nil { |
| 60 | return command, nil |
| 61 | } |
| 62 | |
| 63 | // Check if already installed in our bin dir. |
| 64 | binPath := filepath.Join(BinDir(), command) |
| 65 | if info, err := os.Stat(binPath); err == nil && info.Mode()&0o111 != 0 { |
| 66 | return binPath, nil |
| 67 | } |
| 68 | |
| 69 | // Use singleflight to deduplicate concurrent installs of the same command. |
| 70 | result, err, _ := installGroup.Do(command, func() (any, error) { |
| 71 | return safeInstall(ctx, command, version, install) |
| 72 | }) |
| 73 | if err != nil { |
| 74 | return "", err |
| 75 | } |
| 76 | |
| 77 | return result.(string), nil |
| 78 | } |
| 79 | |
| 80 | // safeInstall wraps install with panic recovery. Without this, |
| 81 | // singleflight wraps any panic in *panicError and re-raises it via |