mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-02-21 02:55:37 -08:00
fix(git): use the right git executable for WSL
git executable detection path conversion when needed
This commit is contained in:
parent
52d7badbac
commit
77993158e2
|
@ -100,12 +100,16 @@ type environmentInfo interface {
|
||||||
doGet(url string, timeout int, requestModifiers ...HTTPRequestModifier) ([]byte, error)
|
doGet(url string, timeout int, requestModifiers ...HTTPRequestModifier) ([]byte, error)
|
||||||
hasParentFilePath(path string) (fileInfo *fileInfo, err error)
|
hasParentFilePath(path string) (fileInfo *fileInfo, err error)
|
||||||
isWsl() bool
|
isWsl() bool
|
||||||
|
isWsl2() bool
|
||||||
stackCount() int
|
stackCount() int
|
||||||
getTerminalWidth() (int, error)
|
getTerminalWidth() (int, error)
|
||||||
getCachePath() string
|
getCachePath() string
|
||||||
cache() cache
|
cache() cache
|
||||||
close()
|
close()
|
||||||
logs() string
|
logs() string
|
||||||
|
inWSLSharedDrive() bool
|
||||||
|
convertToLinuxPath(path string) string
|
||||||
|
convertToWindowsPath(path string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
type commandCache struct {
|
type commandCache struct {
|
||||||
|
|
|
@ -5,6 +5,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/v3/host"
|
"github.com/shirou/gopsutil/v3/host"
|
||||||
|
@ -33,6 +34,15 @@ func (env *environment) isWsl() bool {
|
||||||
return env.getenv("WSL_DISTRO_NAME") != ""
|
return env.getenv("WSL_DISTRO_NAME") != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *environment) isWsl2() bool {
|
||||||
|
defer env.trace(time.Now(), "isWsl2")
|
||||||
|
if !env.isWsl() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
uname := env.getFileContent("/proc/sys/kernel/osrelease")
|
||||||
|
return strings.Contains(uname, "WSL2")
|
||||||
|
}
|
||||||
|
|
||||||
func (env *environment) getTerminalWidth() (int, error) {
|
func (env *environment) getTerminalWidth() (int, error) {
|
||||||
defer env.trace(time.Now(), "getTerminalWidth")
|
defer env.trace(time.Now(), "getTerminalWidth")
|
||||||
width, err := terminal.Width()
|
width, err := terminal.Width()
|
||||||
|
@ -63,3 +73,23 @@ func (env *environment) getCachePath() string {
|
||||||
func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistryValue, error) {
|
func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistryValue, error) {
|
||||||
return nil, errors.New("not implemented")
|
return nil, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *environment) inWSLSharedDrive() bool {
|
||||||
|
return env.isWsl() && strings.HasPrefix(env.getcwd(), "/mnt/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *environment) convertToWindowsPath(path string) string {
|
||||||
|
windowsPath, err := env.runCommand("wslpath", "-w", path)
|
||||||
|
if err == nil {
|
||||||
|
return windowsPath
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *environment) convertToLinuxPath(path string) string {
|
||||||
|
linuxPath, err := env.runCommand("wslpath", "-u", path)
|
||||||
|
if err == nil {
|
||||||
|
return linuxPath
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
|
@ -75,6 +75,11 @@ func (env *environment) isWsl() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *environment) isWsl2() bool {
|
||||||
|
defer env.trace(time.Now(), "isWsl2")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (env *environment) getTerminalWidth() (int, error) {
|
func (env *environment) getTerminalWidth() (int, error) {
|
||||||
defer env.trace(time.Now(), "getTerminalWidth")
|
defer env.trace(time.Now(), "getTerminalWidth")
|
||||||
handle, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0)
|
handle, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0)
|
||||||
|
@ -243,3 +248,15 @@ func (env *environment) getWindowsRegistryKeyValue(path string) (*windowsRegistr
|
||||||
return nil, errors.New(errorLogMsg)
|
return nil, errors.New(errorLogMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *environment) inWSLSharedDrive() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *environment) convertToWindowsPath(path string) string {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *environment) convertToLinuxPath(path string) string {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
|
@ -45,11 +45,13 @@ type git struct {
|
||||||
WorktreeCount int
|
WorktreeCount int
|
||||||
IsWorkTree bool
|
IsWorkTree bool
|
||||||
|
|
||||||
gitWorkingFolder string // .git working folder, can be different of root if using worktree
|
gitWorkingFolder string // .git working folder
|
||||||
gitRootFolder string // .git root folder
|
gitRootFolder string // .git root folder
|
||||||
gitWorktreeFolder string // .git real worktree path
|
gitRealFolder string // .git real folder(can be different from current path when in worktrees)
|
||||||
|
|
||||||
gitCommand string
|
gitCommand string
|
||||||
|
|
||||||
|
IsWslSharedPath bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -102,6 +104,10 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *git) enabled() bool {
|
func (g *git) enabled() bool {
|
||||||
|
// when in wsl/wsl2 and in a windows shared folder
|
||||||
|
// we must use git.exe and convert paths accordingly
|
||||||
|
// for worktrees, stashes, and path to work
|
||||||
|
g.IsWslSharedPath = g.env.inWSLSharedDrive()
|
||||||
if !g.env.hasCommand(g.getGitCommand()) {
|
if !g.env.hasCommand(g.getGitCommand()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -116,7 +122,8 @@ func (g *git) enabled() bool {
|
||||||
if gitdir.isDir {
|
if gitdir.isDir {
|
||||||
g.gitWorkingFolder = gitdir.path
|
g.gitWorkingFolder = gitdir.path
|
||||||
g.gitRootFolder = gitdir.path
|
g.gitRootFolder = gitdir.path
|
||||||
g.gitWorktreeFolder = strings.TrimSuffix(gitdir.path, ".git")
|
// convert the worktree file path to a windows one when in wsl 2 shared folder
|
||||||
|
g.gitRealFolder = strings.TrimSuffix(g.convertToWindowsPath(gitdir.path), ".git")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// handle worktree
|
// handle worktree
|
||||||
|
@ -124,13 +131,15 @@ func (g *git) enabled() bool {
|
||||||
dirPointer := strings.Trim(g.env.getFileContent(gitdir.path), " \r\n")
|
dirPointer := strings.Trim(g.env.getFileContent(gitdir.path), " \r\n")
|
||||||
matches := findNamedRegexMatch(`^gitdir: (?P<dir>.*)$`, dirPointer)
|
matches := findNamedRegexMatch(`^gitdir: (?P<dir>.*)$`, dirPointer)
|
||||||
if matches != nil && matches["dir"] != "" {
|
if matches != nil && matches["dir"] != "" {
|
||||||
g.gitWorkingFolder = matches["dir"]
|
// if we open a worktree file in a shared wsl2 folder, we have to convert it back
|
||||||
|
// to the mounted path
|
||||||
|
g.gitWorkingFolder = g.convertToLinuxPath(matches["dir"])
|
||||||
// in worktrees, the path looks like this: gitdir: path/.git/worktrees/branch
|
// in worktrees, the path looks like this: gitdir: path/.git/worktrees/branch
|
||||||
// strips the last .git/worktrees part
|
// strips the last .git/worktrees part
|
||||||
// :ind+5 = index + /.git
|
// :ind+5 = index + /.git
|
||||||
ind := strings.LastIndex(g.gitWorkingFolder, "/.git/worktrees")
|
ind := strings.LastIndex(g.gitWorkingFolder, "/.git/worktrees")
|
||||||
g.gitRootFolder = g.gitWorkingFolder[:ind+5]
|
g.gitRootFolder = g.gitWorkingFolder[:ind+5]
|
||||||
g.gitWorktreeFolder = strings.TrimSuffix(g.env.getFileContent(g.gitWorkingFolder+"/gitdir"), ".git\n")
|
g.gitRealFolder = strings.TrimSuffix(g.env.getFileContent(g.gitWorkingFolder+"/gitdir"), ".git\n")
|
||||||
g.IsWorkTree = true
|
g.IsWorkTree = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -278,25 +287,15 @@ func (g *git) getGitCommand() string {
|
||||||
if len(g.gitCommand) > 0 {
|
if len(g.gitCommand) > 0 {
|
||||||
return g.gitCommand
|
return g.gitCommand
|
||||||
}
|
}
|
||||||
inWSL2SharedDrive := func(env environmentInfo) bool {
|
|
||||||
if !env.isWsl() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(env.getcwd(), "/mnt/") {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
uname, _ := g.env.runCommand("uname", "-r")
|
|
||||||
return strings.Contains(uname, "WSL2")
|
|
||||||
}
|
|
||||||
g.gitCommand = "git"
|
g.gitCommand = "git"
|
||||||
if g.env.getRuntimeGOOS() == windowsPlatform || inWSL2SharedDrive(g.env) {
|
if g.env.getRuntimeGOOS() == windowsPlatform || g.IsWslSharedPath {
|
||||||
g.gitCommand = "git.exe"
|
g.gitCommand = "git.exe"
|
||||||
}
|
}
|
||||||
return g.gitCommand
|
return g.gitCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *git) getGitCommandOutput(args ...string) string {
|
func (g *git) getGitCommandOutput(args ...string) string {
|
||||||
args = append([]string{"-C", g.gitWorktreeFolder, "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}, args...)
|
args = append([]string{"-C", g.gitRealFolder, "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}, args...)
|
||||||
val, _ := g.env.runCommand(g.getGitCommand(), args...)
|
val, _ := g.env.runCommand(g.getGitCommand(), args...)
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
@ -490,3 +489,17 @@ func (g *git) getOriginURL(upstream string) string {
|
||||||
}
|
}
|
||||||
return keyVal
|
return keyVal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *git) convertToWindowsPath(path string) string {
|
||||||
|
if !g.IsWslSharedPath {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
return g.env.convertToWindowsPath(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *git) convertToLinuxPath(path string) string {
|
||||||
|
if !g.IsWslSharedPath {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
return g.env.convertToLinuxPath(path)
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ const (
|
||||||
|
|
||||||
func TestEnabledGitNotFound(t *testing.T) {
|
func TestEnabledGitNotFound(t *testing.T) {
|
||||||
env := new(MockedEnvironment)
|
env := new(MockedEnvironment)
|
||||||
|
env.On("inWSLSharedDrive", nil).Return(false)
|
||||||
env.On("hasCommand", "git").Return(false)
|
env.On("hasCommand", "git").Return(false)
|
||||||
env.On("getRuntimeGOOS", nil).Return("")
|
env.On("getRuntimeGOOS", nil).Return("")
|
||||||
env.On("isWsl", nil).Return(false)
|
env.On("isWsl", nil).Return(false)
|
||||||
|
@ -28,6 +29,7 @@ func TestEnabledGitNotFound(t *testing.T) {
|
||||||
|
|
||||||
func TestEnabledInWorkingDirectory(t *testing.T) {
|
func TestEnabledInWorkingDirectory(t *testing.T) {
|
||||||
env := new(MockedEnvironment)
|
env := new(MockedEnvironment)
|
||||||
|
env.On("inWSLSharedDrive", nil).Return(false)
|
||||||
env.On("hasCommand", "git").Return(true)
|
env.On("hasCommand", "git").Return(true)
|
||||||
env.On("getRuntimeGOOS", nil).Return("")
|
env.On("getRuntimeGOOS", nil).Return("")
|
||||||
env.On("isWsl", nil).Return(false)
|
env.On("isWsl", nil).Return(false)
|
||||||
|
@ -48,6 +50,7 @@ func TestEnabledInWorkingDirectory(t *testing.T) {
|
||||||
|
|
||||||
func TestEnabledInWorkingTree(t *testing.T) {
|
func TestEnabledInWorkingTree(t *testing.T) {
|
||||||
env := new(MockedEnvironment)
|
env := new(MockedEnvironment)
|
||||||
|
env.On("inWSLSharedDrive", nil).Return(false)
|
||||||
env.On("hasCommand", "git").Return(true)
|
env.On("hasCommand", "git").Return(true)
|
||||||
env.On("getRuntimeGOOS", nil).Return("")
|
env.On("getRuntimeGOOS", nil).Return("")
|
||||||
env.On("isWsl", nil).Return(false)
|
env.On("isWsl", nil).Return(false)
|
||||||
|
@ -66,7 +69,7 @@ func TestEnabledInWorkingTree(t *testing.T) {
|
||||||
}
|
}
|
||||||
assert.True(t, g.enabled())
|
assert.True(t, g.enabled())
|
||||||
assert.Equal(t, "/dev/real_folder/.git/worktrees/folder_worktree", g.gitWorkingFolder)
|
assert.Equal(t, "/dev/real_folder/.git/worktrees/folder_worktree", g.gitWorkingFolder)
|
||||||
assert.Equal(t, "/dev/folder_worktree", g.gitWorktreeFolder)
|
assert.Equal(t, "/dev/folder_worktree", g.gitRealFolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetGitOutputForCommand(t *testing.T) {
|
func TestGetGitOutputForCommand(t *testing.T) {
|
||||||
|
@ -195,6 +198,7 @@ func TestSetGitHEADContextClean(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := new(MockedEnvironment)
|
env := new(MockedEnvironment)
|
||||||
|
env.On("inWSLSharedDrive", nil).Return(false)
|
||||||
env.On("getRuntimeGOOS", nil).Return("unix")
|
env.On("getRuntimeGOOS", nil).Return("unix")
|
||||||
env.On("isWsl", nil).Return(false)
|
env.On("isWsl", nil).Return(false)
|
||||||
env.mockGitCommand("", "describe", "--tags", "--exact-match")
|
env.mockGitCommand("", "describe", "--tags", "--exact-match")
|
||||||
|
@ -537,17 +541,18 @@ func TestShouldIgnoreRootRepository(t *testing.T) {
|
||||||
|
|
||||||
func TestGetGitCommand(t *testing.T) {
|
func TestGetGitCommand(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
Case string
|
Case string
|
||||||
Expected string
|
Expected string
|
||||||
IsWSL bool
|
IsWSL bool
|
||||||
IsWSL1 bool
|
IsWSL1 bool
|
||||||
GOOS string
|
GOOS string
|
||||||
CWD string
|
CWD string
|
||||||
|
IsWslSharedPath bool
|
||||||
}{
|
}{
|
||||||
{Case: "On Windows", Expected: "git.exe", GOOS: windowsPlatform},
|
{Case: "On Windows", Expected: "git.exe", GOOS: windowsPlatform},
|
||||||
{Case: "Non Windows", Expected: "git"},
|
{Case: "Non Windows", Expected: "git"},
|
||||||
{Case: "Iside WSL2, non shared", IsWSL: true, Expected: "git"},
|
{Case: "Iside WSL2, non shared", IsWSL: true, Expected: "git"},
|
||||||
{Case: "Iside WSL2, shared", Expected: "git.exe", IsWSL: true, CWD: "/mnt/bill"},
|
{Case: "Iside WSL2, shared", Expected: "git.exe", IsWSL: true, IsWslSharedPath: true, CWD: "/mnt/bill"},
|
||||||
{Case: "Iside WSL1, shared", Expected: "git", IsWSL: true, IsWSL1: true, CWD: "/mnt/bill"},
|
{Case: "Iside WSL1, shared", Expected: "git", IsWSL: true, IsWSL1: true, CWD: "/mnt/bill"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,6 +571,12 @@ func TestGetGitCommand(t *testing.T) {
|
||||||
env: env,
|
env: env,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if tc.IsWslSharedPath {
|
||||||
|
env.On("inWSLSharedDrive", nil).Return(true)
|
||||||
|
g.IsWslSharedPath = tc.IsWslSharedPath
|
||||||
|
} else {
|
||||||
|
env.On("inWSLSharedDrive", nil).Return(false)
|
||||||
|
}
|
||||||
assert.Equal(t, tc.Expected, g.getGitCommand(), tc.Case)
|
assert.Equal(t, tc.Expected, g.getGitCommand(), tc.Case)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,6 +154,11 @@ func (env *MockedEnvironment) isWsl() bool {
|
||||||
return args.Bool(0)
|
return args.Bool(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *MockedEnvironment) isWsl2() bool {
|
||||||
|
args := env.Called(nil)
|
||||||
|
return args.Bool(0)
|
||||||
|
}
|
||||||
|
|
||||||
func (env *MockedEnvironment) getTerminalWidth() (int, error) {
|
func (env *MockedEnvironment) getTerminalWidth() (int, error) {
|
||||||
args := env.Called(nil)
|
args := env.Called(nil)
|
||||||
return args.Int(0), args.Error(1)
|
return args.Int(0), args.Error(1)
|
||||||
|
@ -178,6 +183,21 @@ func (env *MockedEnvironment) logs() string {
|
||||||
return args.String(0)
|
return args.String(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (env *MockedEnvironment) inWSLSharedDrive() bool {
|
||||||
|
args := env.Called(nil)
|
||||||
|
return args.Bool(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *MockedEnvironment) convertToWindowsPath(path string) string {
|
||||||
|
args := env.Called(nil)
|
||||||
|
return args.String(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (env *MockedEnvironment) convertToLinuxPath(path string) string {
|
||||||
|
args := env.Called(nil)
|
||||||
|
return args.String(0)
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
homeBill = "/home/bill"
|
homeBill = "/home/bill"
|
||||||
homeJan = "/usr/home/jan"
|
homeJan = "/usr/home/jan"
|
||||||
|
|
Loading…
Reference in a new issue