mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
76 lines
1.7 KiB
Go
76 lines
1.7 KiB
Go
package shim
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"os"
|
||
|
|
"os/exec"
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
"sync"
|
||
|
|
|
||
|
|
"github.com/safedep/dry/log"
|
||
|
|
)
|
||
|
|
|
||
|
|
const pmgBinSuffix = "/.pmg/bin"
|
||
|
|
|
||
|
|
var resolverMu sync.Mutex
|
||
|
|
|
||
|
|
func FilterPMGFromPath(pathEnv string) string {
|
||
|
|
if pathEnv == "" {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
entries := filepath.SplitList(pathEnv)
|
||
|
|
filtered := make([]string, 0, len(entries))
|
||
|
|
|
||
|
|
for _, entry := range entries {
|
||
|
|
if !strings.HasSuffix(entry, pmgBinSuffix) {
|
||
|
|
filtered = append(filtered, entry)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return strings.Join(filtered, string(os.PathListSeparator))
|
||
|
|
}
|
||
|
|
|
||
|
|
// ResolveRealBinary finds the real binary path for a command by searching
|
||
|
|
// PATH with ~/.pmg/bin stripped out. This prevents exec.CommandContext from
|
||
|
|
// resolving to the shim script, which would cause infinite recursion.
|
||
|
|
func ResolveRealBinary(name string) (string, error) {
|
||
|
|
resolverMu.Lock()
|
||
|
|
defer resolverMu.Unlock()
|
||
|
|
|
||
|
|
originalPath := os.Getenv("PATH")
|
||
|
|
filteredPath := FilterPMGFromPath(originalPath)
|
||
|
|
|
||
|
|
if err := os.Setenv("PATH", filteredPath); err != nil {
|
||
|
|
return "", fmt.Errorf("failed to set filtered PATH: %w", err)
|
||
|
|
}
|
||
|
|
defer func() {
|
||
|
|
if err := os.Setenv("PATH", originalPath); err != nil {
|
||
|
|
log.Warnf("failed to restore PATH: %v", err)
|
||
|
|
}
|
||
|
|
}()
|
||
|
|
|
||
|
|
resolved, err := exec.LookPath(name)
|
||
|
|
if err != nil {
|
||
|
|
return "", fmt.Errorf("could not find %s in PATH (excluding pmg shims): %w", name, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
return resolved, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func FilterPMGFromEnv(env []string) []string {
|
||
|
|
result := make([]string, 0, len(env))
|
||
|
|
|
||
|
|
for _, entry := range env {
|
||
|
|
if pathValue, ok := strings.CutPrefix(entry, "PATH="); ok {
|
||
|
|
filtered := FilterPMGFromPath(pathValue)
|
||
|
|
result = append(result, "PATH="+filtered)
|
||
|
|
} else {
|
||
|
|
result = append(result, entry)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result
|
||
|
|
}
|