fix: treat meta cmd as shell command string, prepend tools dir to PATH
- ResolveTool now returns cmd field as-is instead of trying to resolve it as a binary path. This allows meta-only tools to use full shell command strings with env vars, pipes, and subshells. - Prepend ~/.config/ollie/tools to PATH when executing tools so cmd fields can reference other tools by name.
This commit is contained in:
parent
92d9fec51a
commit
9b98a958cc
|
|
@ -143,6 +143,14 @@ func executeSandboxed(ctx context.Context, toolPath, stdinData, cwd string, envE
|
||||||
for k, v := range envExtra {
|
for k, v := range envExtra {
|
||||||
envMap[k] = v
|
envMap[k] = v
|
||||||
}
|
}
|
||||||
|
// Prepend tools directory to PATH so meta-only cmd fields can reference other tools
|
||||||
|
if toolsDir := toolsrv.ToolsPath(); toolsDir != "" {
|
||||||
|
if existing := envMap["PATH"]; existing != "" {
|
||||||
|
envMap["PATH"] = toolsDir + ":" + existing
|
||||||
|
} else {
|
||||||
|
envMap["PATH"] = toolsDir
|
||||||
|
}
|
||||||
|
}
|
||||||
// Compute NAMESPACE if not set
|
// Compute NAMESPACE if not set
|
||||||
if _, ok := envMap["NAMESPACE"]; !ok {
|
if _, ok := envMap["NAMESPACE"]; !ok {
|
||||||
if ns := Plan9Namespace(envMap); ns != "" {
|
if ns := Plan9Namespace(envMap); ns != "" {
|
||||||
|
|
|
||||||
|
|
@ -187,10 +187,10 @@ func ToolInfoFromMeta(name string, m *MetaFile) ToolInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveTool returns the executable path for a named tool.
|
// ResolveTool returns the command string for a named tool.
|
||||||
// Resolution order:
|
// Resolution order:
|
||||||
// 1. ~/.config/ollie/tools/<name> (local wrapper wins over system binary)
|
// 1. ~/.config/ollie/tools/<name> (local script/binary)
|
||||||
// 2. .meta "cmd" field (after variant resolution; absolute path or bare name via $PATH)
|
// 2. .meta "cmd" field (returned as-is; it's a shell command string)
|
||||||
// 3. exec.LookPath(<name>) as final fallback
|
// 3. exec.LookPath(<name>) as final fallback
|
||||||
func ResolveTool(name string) (string, error) {
|
func ResolveTool(name string) (string, error) {
|
||||||
// Local tools path always wins — allows wrappers to shadow system binaries.
|
// Local tools path always wins — allows wrappers to shadow system binaries.
|
||||||
|
|
@ -199,22 +199,11 @@ func ResolveTool(name string) (string, error) {
|
||||||
return local, nil
|
return local, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check .meta cmd field (after variant resolution).
|
// Check .meta cmd field — return as-is (shell command string, not a path to resolve).
|
||||||
if m, err := LoadMetaFile(name); err == nil && m != nil {
|
if m, err := LoadMetaFile(name); err == nil && m != nil {
|
||||||
resolved := m.Resolve()
|
resolved := m.Resolve()
|
||||||
if resolved != nil && resolved.Cmd != "" {
|
if resolved != nil && resolved.Cmd != "" {
|
||||||
// Check tools path for the cmd name first
|
return resolved.Cmd, nil
|
||||||
cmdLocal := filepath.Join(ToolsPath(), resolved.Cmd)
|
|
||||||
if info, err := os.Stat(cmdLocal); err == nil && !info.IsDir() {
|
|
||||||
return cmdLocal, nil
|
|
||||||
}
|
|
||||||
if filepath.IsAbs(resolved.Cmd) {
|
|
||||||
return resolved.Cmd, nil
|
|
||||||
}
|
|
||||||
if p, err := exec.LookPath(resolved.Cmd); err == nil {
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("tool %s: cmd %q not found in PATH", name, resolved.Cmd)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue