mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-02 03:28:28 -04:00
@@ -699,6 +699,7 @@ func redetectMatugenVersion(old matugenFlags) (matugenFlags, bool) {
|
||||
|
||||
func detectMatugenVersionLocked() (matugenFlags, error) {
|
||||
cmd := exec.Command("matugen", "--version")
|
||||
cmd.Env = utils.EnvWithUserBinPath(nil)
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return matugenFlags{}, fmt.Errorf("failed to get matugen version: %w", err)
|
||||
@@ -755,6 +756,7 @@ func runMatugen(baseArgs []string) error {
|
||||
|
||||
args := buildMatugenArgs(baseArgs, flags)
|
||||
cmd := exec.Command("matugen", args...)
|
||||
cmd.Env = utils.EnvWithUserBinPath(nil)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
runErr := cmd.Run()
|
||||
@@ -772,6 +774,7 @@ func runMatugen(baseArgs []string) error {
|
||||
log.Warnf("Matugen version changed (v4: %v -> %v), retrying", flags.isV4, newFlags.isV4)
|
||||
args = buildMatugenArgs(baseArgs, newFlags)
|
||||
retryCmd := exec.Command("matugen", args...)
|
||||
retryCmd.Env = utils.EnvWithUserBinPath(nil)
|
||||
retryCmd.Stdout = os.Stdout
|
||||
retryCmd.Stderr = os.Stderr
|
||||
return retryCmd.Run()
|
||||
@@ -814,6 +817,7 @@ func execDryRun(opts *Options, flags matugenFlags) (string, error) {
|
||||
}
|
||||
|
||||
cmd := exec.Command("matugen", baseArgs...)
|
||||
cmd.Env = utils.EnvWithUserBinPath(nil)
|
||||
var stderr strings.Builder
|
||||
cmd.Stderr = &stderr
|
||||
output, err := cmd.Output()
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AppChecker interface {
|
||||
@@ -31,7 +34,20 @@ func (DefaultAppChecker) AnyFlatpakExists(flatpaks ...string) bool {
|
||||
|
||||
func CommandExists(cmd string) bool {
|
||||
_, err := exec.LookPath(cmd)
|
||||
return err == nil
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
if strings.ContainsRune(cmd, os.PathSeparator) {
|
||||
return false
|
||||
}
|
||||
for _, dir := range userBinDirs() {
|
||||
path := filepath.Join(dir, cmd)
|
||||
info, statErr := os.Stat(path)
|
||||
if statErr == nil && !info.IsDir() && info.Mode()&0o111 != 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func AnyCommandExists(cmds ...string) bool {
|
||||
@@ -42,3 +58,58 @@ func AnyCommandExists(cmds ...string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func EnvWithUserBinPath(env []string) []string {
|
||||
if env == nil {
|
||||
env = os.Environ()
|
||||
}
|
||||
|
||||
out := append([]string(nil), env...)
|
||||
pathIndex := -1
|
||||
pathValue := ""
|
||||
for i, entry := range out {
|
||||
if strings.HasPrefix(entry, "PATH=") {
|
||||
pathIndex = i
|
||||
pathValue = strings.TrimPrefix(entry, "PATH=")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
parts := filepath.SplitList(pathValue)
|
||||
seen := make(map[string]struct{}, len(parts))
|
||||
for _, part := range parts {
|
||||
if part != "" {
|
||||
seen[part] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
prepend := make([]string, 0, 2)
|
||||
for _, dir := range userBinDirs() {
|
||||
if dir == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[dir]; ok {
|
||||
continue
|
||||
}
|
||||
prepend = append(prepend, dir)
|
||||
seen[dir] = struct{}{}
|
||||
}
|
||||
|
||||
parts = append(prepend, parts...)
|
||||
newPath := "PATH=" + strings.Join(parts, string(os.PathListSeparator))
|
||||
if pathIndex >= 0 {
|
||||
out[pathIndex] = newPath
|
||||
} else {
|
||||
out = append(out, newPath)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func userBinDirs() []string {
|
||||
dirs := []string{}
|
||||
if home, err := os.UserHomeDir(); err == nil && home != "" {
|
||||
dirs = append(dirs, filepath.Join(home, ".local", "bin"))
|
||||
}
|
||||
dirs = append(dirs, "/usr/local/bin")
|
||||
return dirs
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCommandExistsFallsBackToLocalBin(t *testing.T) {
|
||||
home := t.TempDir()
|
||||
binDir := filepath.Join(home, ".local", "bin")
|
||||
require.NoError(t, os.MkdirAll(binDir, 0o755))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(binDir, "pywalfox"), []byte("#!/bin/sh\n"), 0o755))
|
||||
|
||||
t.Setenv("HOME", home)
|
||||
t.Setenv("PATH", t.TempDir())
|
||||
|
||||
assert.True(t, CommandExists("pywalfox"))
|
||||
}
|
||||
|
||||
func TestCommandExistsIgnoresNonExecutableLocalBinFile(t *testing.T) {
|
||||
home := t.TempDir()
|
||||
binDir := filepath.Join(home, ".local", "bin")
|
||||
require.NoError(t, os.MkdirAll(binDir, 0o755))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(binDir, "pywalfox"), []byte("not executable"), 0o644))
|
||||
|
||||
t.Setenv("HOME", home)
|
||||
t.Setenv("PATH", t.TempDir())
|
||||
|
||||
assert.False(t, CommandExists("pywalfox"))
|
||||
}
|
||||
|
||||
func TestEnvWithUserBinPathPrependsLocalBin(t *testing.T) {
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
|
||||
env := EnvWithUserBinPath([]string{"PATH=/usr/bin", "OTHER=value"})
|
||||
var pathValue string
|
||||
for _, entry := range env {
|
||||
if strings.HasPrefix(entry, "PATH=") {
|
||||
pathValue = strings.TrimPrefix(entry, "PATH=")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
parts := filepath.SplitList(pathValue)
|
||||
require.NotEmpty(t, parts)
|
||||
assert.Equal(t, filepath.Join(home, ".local", "bin"), parts[0])
|
||||
assert.Contains(t, parts, "/usr/local/bin")
|
||||
assert.Contains(t, env, "OTHER=value")
|
||||
}
|
||||
Reference in New Issue
Block a user