mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-02-21 02:55:37 -08:00
parent
859fd0bbef
commit
f2ccee6df6
|
@ -110,8 +110,7 @@ func (env *ShellEnvironment) ConvertToWindowsPath(path string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (env *ShellEnvironment) ConvertToLinuxPath(path string) string {
|
func (env *ShellEnvironment) ConvertToLinuxPath(path string) string {
|
||||||
linuxPath, err := env.RunCommand("wslpath", "-u", path)
|
if linuxPath, err := env.RunCommand("wslpath", "-u", path); err == nil {
|
||||||
if err == nil {
|
|
||||||
return linuxPath
|
return linuxPath
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"oh-my-posh/environment"
|
"oh-my-posh/environment"
|
||||||
"oh-my-posh/properties"
|
"oh-my-posh/properties"
|
||||||
"oh-my-posh/regex"
|
"oh-my-posh/regex"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -144,63 +145,84 @@ func (g *Git) shouldDisplay() bool {
|
||||||
// we must use git.exe and convert paths accordingly
|
// we must use git.exe and convert paths accordingly
|
||||||
// for worktrees, stashes, and path to work
|
// for worktrees, stashes, and path to work
|
||||||
g.IsWslSharedPath = g.env.InWSLSharedDrive()
|
g.IsWslSharedPath = g.env.InWSLSharedDrive()
|
||||||
|
|
||||||
if !g.env.HasCommand(g.getCommand(GITCOMMAND)) {
|
if !g.env.HasCommand(g.getCommand(GITCOMMAND)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
gitdir, err := g.env.HasParentFilePath(".git")
|
gitdir, err := g.env.HasParentFilePath(".git")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.shouldIgnoreRootRepository(gitdir.ParentFolder) {
|
if g.shouldIgnoreRootRepository(gitdir.ParentFolder) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if gitdir.IsDir {
|
if !gitdir.IsDir {
|
||||||
g.workingFolder = gitdir.Path
|
return g.hasWorktree(gitdir)
|
||||||
g.rootFolder = gitdir.Path
|
|
||||||
// convert the worktree file path to a windows one when in wsl 2 shared folder
|
|
||||||
g.realFolder = strings.TrimSuffix(g.convertToWindowsPath(gitdir.Path), ".git")
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
// handle worktree
|
|
||||||
|
g.workingFolder = gitdir.Path
|
||||||
|
g.rootFolder = gitdir.Path
|
||||||
|
// convert the worktree file path to a windows one when in wsl 2 shared folder
|
||||||
|
g.realFolder = strings.TrimSuffix(g.convertToWindowsPath(gitdir.Path), ".git")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Git) hasWorktree(gitdir *environment.FileInfo) bool {
|
||||||
g.rootFolder = gitdir.Path
|
g.rootFolder = gitdir.Path
|
||||||
dirPointer := strings.Trim(g.env.FileContent(gitdir.Path), " \r\n")
|
dirPointer := strings.Trim(g.env.FileContent(gitdir.Path), " \r\n")
|
||||||
matches := regex.FindNamedRegexMatch(`^gitdir: (?P<dir>.*)$`, dirPointer)
|
matches := regex.FindNamedRegexMatch(`^gitdir: (?P<dir>.*)$`, dirPointer)
|
||||||
if matches != nil && matches["dir"] != "" {
|
if matches == nil || matches["dir"] == "" {
|
||||||
// if we open a worktree file in a shared wsl2 folder, we have to convert it back
|
return false
|
||||||
// to the mounted path
|
}
|
||||||
g.workingFolder = g.convertToLinuxPath(matches["dir"])
|
// if we open a worktree file in a shared wsl2 folder, we have to convert it back
|
||||||
|
// to the mounted path
|
||||||
|
g.workingFolder = 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.workingFolder, "/.git/worktrees")
|
ind := strings.LastIndex(g.workingFolder, "/.git/worktrees")
|
||||||
if ind > -1 {
|
if ind > -1 {
|
||||||
g.rootFolder = g.workingFolder[:ind+5]
|
gitDir := filepath.Join(g.workingFolder, "gitdir")
|
||||||
g.realFolder = strings.TrimSuffix(g.env.FileContent(g.workingFolder+"/gitdir"), ".git\n")
|
g.rootFolder = g.workingFolder[:ind+5]
|
||||||
|
g.realFolder = strings.TrimSuffix(g.env.FileContent(gitDir), ".git\n")
|
||||||
|
g.IsWorkTree = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// in submodules, the path looks like this: gitdir: ../.git/modules/test-submodule
|
||||||
|
// we need the parent folder to detect where the real .git folder is
|
||||||
|
ind = strings.LastIndex(g.workingFolder, "/.git/modules")
|
||||||
|
if ind > -1 {
|
||||||
|
g.rootFolder = filepath.Join(gitdir.ParentFolder, g.workingFolder)
|
||||||
|
// this might be both a worktree and a submodule, where the path would look like
|
||||||
|
// this: ../.git/modules/module/path/worktrees/location. We cannot distinguish
|
||||||
|
// between worktree and a module path containing the word 'worktree,' however.
|
||||||
|
ind = strings.LastIndex(g.rootFolder, g.env.PathSeparator()+"worktrees"+g.env.PathSeparator())
|
||||||
|
if ind > -1 && g.env.HasFilesInDir(g.rootFolder, "gitdir") {
|
||||||
|
gitDir := filepath.Join(g.rootFolder, "gitdir")
|
||||||
|
realGitFolder := filepath.Clean(g.env.FileContent(gitDir))
|
||||||
|
g.realFolder = strings.TrimSuffix(realGitFolder, ".git\n")
|
||||||
|
g.rootFolder = g.rootFolder[:ind]
|
||||||
|
g.workingFolder = g.rootFolder
|
||||||
g.IsWorkTree = true
|
g.IsWorkTree = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// in submodules, the path looks like this: gitdir: ../.git/modules/test-submodule
|
g.realFolder = g.rootFolder
|
||||||
// we need the parent folder to detect where the real .git folder is
|
g.workingFolder = g.rootFolder
|
||||||
ind = strings.LastIndex(g.workingFolder, "/.git/modules")
|
return true
|
||||||
if ind > -1 {
|
}
|
||||||
g.rootFolder = gitdir.ParentFolder + "/" + g.workingFolder
|
|
||||||
g.realFolder = g.rootFolder
|
|
||||||
g.workingFolder = g.rootFolder
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for separate git folder(--separate-git-dir)
|
// check for separate git folder(--separate-git-dir)
|
||||||
// check if the folder contains a HEAD file
|
// check if the folder contains a HEAD file
|
||||||
if g.env.HasFilesInDir(g.workingFolder, "HEAD") {
|
if g.env.HasFilesInDir(g.workingFolder, "HEAD") {
|
||||||
gitFolder := strings.TrimSuffix(g.rootFolder, ".git")
|
gitFolder := strings.TrimSuffix(g.rootFolder, ".git")
|
||||||
g.rootFolder = g.workingFolder
|
g.rootFolder = g.workingFolder
|
||||||
g.workingFolder = gitFolder
|
g.workingFolder = gitFolder
|
||||||
g.realFolder = gitFolder
|
g.realFolder = gitFolder
|
||||||
return true
|
return true
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"oh-my-posh/environment"
|
"oh-my-posh/environment"
|
||||||
"oh-my-posh/mock"
|
"oh-my-posh/mock"
|
||||||
"oh-my-posh/properties"
|
"oh-my-posh/properties"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -55,91 +57,97 @@ func TestEnabledInWorkingDirectory(t *testing.T) {
|
||||||
assert.Equal(t, fileInfo.Path, g.workingFolder)
|
assert.Equal(t, fileInfo.Path, g.workingFolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnabledInWorkingTree(t *testing.T) {
|
func TestEnabledInWorktree(t *testing.T) {
|
||||||
env := new(mock.MockedEnvironment)
|
cases := []struct {
|
||||||
env.On("InWSLSharedDrive").Return(false)
|
Case string
|
||||||
env.On("HasCommand", "git").Return(true)
|
ExpectedEnabled bool
|
||||||
env.On("GOOS").Return("")
|
WorkingFolder string
|
||||||
env.On("IsWsl").Return(false)
|
WorkingFolderAddon string
|
||||||
env.On("PathSeparator").Return("/")
|
WorkingFolderContent string
|
||||||
fileInfo := &environment.FileInfo{
|
GitDirContent string
|
||||||
Path: "/dev/folder_worktree/.git",
|
ExpectedRealFolder string
|
||||||
ParentFolder: "/dev/folder_worktree",
|
ExpectedWorkingFolder string
|
||||||
IsDir: false,
|
ExpectedRootFolder string
|
||||||
}
|
WindowsPaths bool
|
||||||
env.On("FileContent", "/dev/real_folder/.git/worktrees/folder_worktree/HEAD").Return("")
|
}{
|
||||||
env.MockGitCommand(fileInfo.ParentFolder, "", "describe", "--tags", "--exact-match")
|
{
|
||||||
env.On("HasParentFilePath", ".git").Return(fileInfo, nil)
|
Case: "worktree",
|
||||||
env.On("FileContent", "/dev/folder_worktree/.git").Return("gitdir: /dev/real_folder/.git/worktrees/folder_worktree")
|
ExpectedEnabled: true,
|
||||||
env.On("FileContent", "/dev/real_folder/.git/worktrees/folder_worktree/gitdir").Return("/dev/folder_worktree.git\n")
|
WorkingFolder: "/dev/.git/worktrees/folder_worktree",
|
||||||
g := &Git{
|
WorkingFolderAddon: "gitdir",
|
||||||
scm: scm{
|
WorkingFolderContent: "/dev/worktree.git\n",
|
||||||
env: env,
|
ExpectedWorkingFolder: "/dev/.git/worktrees/folder_worktree",
|
||||||
props: properties.Map{},
|
ExpectedRealFolder: "/dev/worktree",
|
||||||
|
ExpectedRootFolder: "/dev/.git",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "submodule",
|
||||||
|
ExpectedEnabled: true,
|
||||||
|
WorkingFolder: "./.git/modules/submodule",
|
||||||
|
ExpectedWorkingFolder: "/dev/.git/modules/submodule",
|
||||||
|
ExpectedRealFolder: "/dev/.git/modules/submodule",
|
||||||
|
ExpectedRootFolder: "/dev/.git/modules/submodule",
|
||||||
|
WindowsPaths: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "submodule with root working folder",
|
||||||
|
ExpectedEnabled: true,
|
||||||
|
WorkingFolder: "/repo/.git/modules/submodule",
|
||||||
|
ExpectedWorkingFolder: "/dev/repo/.git/modules/submodule",
|
||||||
|
ExpectedRealFolder: "/dev/repo/.git/modules/submodule",
|
||||||
|
ExpectedRootFolder: "/dev/repo/.git/modules/submodule",
|
||||||
|
WindowsPaths: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "submodule with worktrees",
|
||||||
|
ExpectedEnabled: true,
|
||||||
|
WorkingFolder: "./.git/modules/module/path/worktrees/location",
|
||||||
|
WorkingFolderAddon: "/dev/",
|
||||||
|
GitDirContent: "/dev/worktree.git\n",
|
||||||
|
ExpectedWorkingFolder: "/dev/.git/modules/module/path",
|
||||||
|
ExpectedRealFolder: "/dev/worktree",
|
||||||
|
ExpectedRootFolder: "/dev/.git/modules/module/path",
|
||||||
|
WindowsPaths: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "separate git dir",
|
||||||
|
ExpectedEnabled: true,
|
||||||
|
WorkingFolder: "/dev/separate/.git/posh",
|
||||||
|
ExpectedWorkingFolder: "/dev/",
|
||||||
|
ExpectedRealFolder: "/dev/",
|
||||||
|
ExpectedRootFolder: "/dev/separate/.git/posh",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
assert.True(t, g.Enabled())
|
fileInfo := &environment.FileInfo{
|
||||||
assert.Equal(t, "/dev/real_folder/.git/worktrees/folder_worktree", g.workingFolder)
|
Path: "/dev/.git",
|
||||||
assert.Equal(t, "/dev/folder_worktree", g.realFolder)
|
ParentFolder: "/dev",
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
env := new(mock.MockedEnvironment)
|
||||||
|
env.On("FileContent", "/dev/.git").Return(fmt.Sprintf("gitdir: %s", tc.WorkingFolder))
|
||||||
|
env.On("FileContent", filepath.Join(tc.WorkingFolder, tc.WorkingFolderAddon)).Return(tc.WorkingFolderContent)
|
||||||
|
env.On("HasFilesInDir", tc.WorkingFolder, "HEAD").Return(true)
|
||||||
|
env.On("HasFilesInDir", filepath.Join(tc.WorkingFolderAddon, tc.WorkingFolder), "gitdir").Return(true)
|
||||||
|
env.On("FileContent", filepath.Join(tc.WorkingFolderAddon, tc.WorkingFolder, "gitdir")).Return(tc.GitDirContent)
|
||||||
|
env.On("PathSeparator").Return(string(os.PathSeparator))
|
||||||
|
g := &Git{
|
||||||
|
scm: scm{
|
||||||
|
env: env,
|
||||||
|
props: properties.Map{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, tc.ExpectedEnabled, g.hasWorktree(fileInfo), tc.Case)
|
||||||
|
if tc.WindowsPaths {
|
||||||
|
tc.ExpectedRealFolder = filepath.Clean(tc.ExpectedRealFolder)
|
||||||
|
tc.ExpectedRootFolder = filepath.Clean(tc.ExpectedRootFolder)
|
||||||
|
tc.ExpectedWorkingFolder = filepath.Clean(tc.ExpectedWorkingFolder)
|
||||||
|
}
|
||||||
|
assert.Equal(t, tc.ExpectedWorkingFolder, g.workingFolder, tc.Case)
|
||||||
|
assert.Equal(t, tc.ExpectedRealFolder, g.realFolder, tc.Case)
|
||||||
|
assert.Equal(t, tc.ExpectedRootFolder, g.rootFolder, tc.Case)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnabledInSubmodule(t *testing.T) {
|
|
||||||
env := new(mock.MockedEnvironment)
|
|
||||||
env.On("InWSLSharedDrive").Return(false)
|
|
||||||
env.On("HasCommand", "git").Return(true)
|
|
||||||
env.On("GOOS").Return("")
|
|
||||||
env.On("IsWsl").Return(false)
|
|
||||||
env.On("PathSeparator").Return("/")
|
|
||||||
fileInfo := &environment.FileInfo{
|
|
||||||
Path: "/dev/parent/test-submodule/.git",
|
|
||||||
ParentFolder: "/dev/parent/test-submodule",
|
|
||||||
IsDir: false,
|
|
||||||
}
|
|
||||||
env.On("FileContent", "/dev/parent/test-submodule/../.git/modules/test-submodule/HEAD").Return("")
|
|
||||||
env.MockGitCommand("/dev/parent/test-submodule/../.git/modules/test-submodule", "", "describe", "--tags", "--exact-match")
|
|
||||||
env.On("HasParentFilePath", ".git").Return(fileInfo, nil)
|
|
||||||
env.On("FileContent", "/dev/parent/test-submodule/.git").Return("gitdir: ../.git/modules/test-submodule")
|
|
||||||
env.On("FileContent", "/dev/parent/.git/modules/test-submodule").Return("/dev/folder_worktree.git\n")
|
|
||||||
g := &Git{
|
|
||||||
scm: scm{
|
|
||||||
env: env,
|
|
||||||
props: properties.Map{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
assert.True(t, g.Enabled())
|
|
||||||
assert.Equal(t, "/dev/parent/test-submodule/../.git/modules/test-submodule", g.workingFolder)
|
|
||||||
assert.Equal(t, "/dev/parent/test-submodule/../.git/modules/test-submodule", g.realFolder)
|
|
||||||
assert.Equal(t, "/dev/parent/test-submodule/../.git/modules/test-submodule", g.rootFolder)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnabledInSeparateGitDir(t *testing.T) {
|
|
||||||
env := new(mock.MockedEnvironment)
|
|
||||||
env.On("InWSLSharedDrive").Return(false)
|
|
||||||
env.On("HasCommand", "git").Return(true)
|
|
||||||
env.On("GOOS").Return("")
|
|
||||||
env.On("IsWsl").Return(false)
|
|
||||||
env.On("PathSeparator").Return("/")
|
|
||||||
fileInfo := &environment.FileInfo{
|
|
||||||
Path: "/dev/parent/test-separate-git-dir/.git",
|
|
||||||
ParentFolder: "/dev/parent/test-separate-git-dir",
|
|
||||||
IsDir: false,
|
|
||||||
}
|
|
||||||
env.On("HasFilesInDir", "/dev/separate-git-dir", "HEAD").Return(true)
|
|
||||||
env.On("FileContent", "/dev/parent/test-separate-git-dir//HEAD").Return("")
|
|
||||||
env.MockGitCommand("/dev/parent/test-separate-git-dir/", "", "describe", "--tags", "--exact-match")
|
|
||||||
env.On("HasParentFilePath", ".git").Return(fileInfo, nil)
|
|
||||||
env.On("FileContent", "/dev/parent/test-separate-git-dir/.git").Return("gitdir: /dev/separate-git-dir")
|
|
||||||
g := &Git{
|
|
||||||
scm: scm{
|
|
||||||
env: env,
|
|
||||||
props: properties.Map{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
assert.True(t, g.Enabled())
|
|
||||||
assert.Equal(t, "/dev/parent/test-separate-git-dir/", g.workingFolder)
|
|
||||||
assert.Equal(t, "/dev/parent/test-separate-git-dir/", g.realFolder)
|
|
||||||
assert.Equal(t, "/dev/separate-git-dir", g.rootFolder)
|
|
||||||
}
|
|
||||||
func TestGetGitOutputForCommand(t *testing.T) {
|
func TestGetGitOutputForCommand(t *testing.T) {
|
||||||
args := []string{"-C", "", "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}
|
args := []string{"-C", "", "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}
|
||||||
commandArgs := []string{"symbolic-ref", "--short", "HEAD"}
|
commandArgs := []string{"symbolic-ref", "--short", "HEAD"}
|
||||||
|
|
Loading…
Reference in a new issue