Repository: JanDeDobbeleer/oh-my-posh
Pull request #1500 (2021-12-24 14:20:40)

fix(git): detect submodules and fix path
### Prerequisites

- [x] I have read and understood the `CONTRIBUTING` guide
- [x] The commit message follows the [conventional commits][cc] guidelines
- [x] Tests for the changes have been added (for bug fixes/features)
- [ ] Docs have been added / updated (for bug fixes/features)

### Description

Fix submodules detection and display

<!---

Tips:

If you're not comfortable with working with Git, we're working a guide (https://ohmyposh.dev/docs/contributing_git) to help you out.
Oh My Posh advises GitKraken (https://www.gitkraken.com/invite/nQmDPR9D) as your preferred cross platform Git GUI power tool.

-->

[cc]: https://www.conventionalcommits.org/en/v1.0.0/#summary


lnu: stash working:
<img width="848" alt="image" src="https://user-images.githubusercontent.com/1829553/147358832-5ce0d22c-0785-449e-bee5-3e9b6ab79ef8.png">

lnu: rebase in progress:
<img width="1070" alt="image" src="https://user-images.githubusercontent.com/1829553/147359194-f046f691-ba19-4868-bf39-96c4d50b0bbc.png">


Patch:
diff --git a/src/segment_git.go b/src/segment_git.go
index b13583fc..0a16d5b4 100644
--- a/src/segment_git.go
+++ b/src/segment_git.go
@@ -134,14 +134,28 @@ func (g *git) enabled() bool {
 		// 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
 		// strips the last .git/worktrees part
 		// :ind+5 = index + /.git
 		ind := strings.LastIndex(g.gitWorkingFolder, "/.git/worktrees")
-		g.gitRootFolder = g.gitWorkingFolder[:ind+5]
-		g.gitRealFolder = strings.TrimSuffix(g.env.getFileContent(g.gitWorkingFolder+"/gitdir"), ".git\n")
-		g.IsWorkTree = true
-		return true
+		if ind > -1 {
+			g.gitRootFolder = g.gitWorkingFolder[:ind+5]
+			g.gitRealFolder = strings.TrimSuffix(g.env.getFileContent(g.gitWorkingFolder+"/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.gitWorkingFolder, "/.git/modules")
+		if ind > -1 {
+			g.gitRootFolder = gitdir.parentFolder + "/" + g.gitWorkingFolder
+			g.gitRealFolder = g.gitRootFolder
+			g.gitWorkingFolder = g.gitRootFolder
+			return true
+		}
+
+		return false
 	}
 	return false
 }


Test patch:
diff --git a/src/segment_git_test.go b/src/segment_git_test.go
index 89907fd7..ed0ff1b6 100644
--- a/src/segment_git_test.go
+++ b/src/segment_git_test.go
@@ -72,6 +72,31 @@ func TestEnabledInWorkingTree(t *testing.T) {
 	assert.Equal(t, "/dev/folder_worktree", g.gitRealFolder)
 }
 
+func TestEnabledInSubmodule(t *testing.T) {
+	env := new(MockedEnvironment)
+	env.On("inWSLSharedDrive", nil).Return(false)
+	env.On("hasCommand", "git").Return(true)
+	env.On("getRuntimeGOOS", nil).Return("")
+	env.On("isWsl", nil).Return(false)
+	fileInfo := &fileInfo{
+		path:         "/dev/parent/test-submodule/.git",
+		parentFolder: "/dev/parent/test-submodule",
+		isDir:        false,
+	}
+	env.On("hasParentFilePath", ".git").Return(fileInfo, nil)
+	env.On("getFileContent", "/dev/parent/test-submodule/.git").Return("gitdir: ../.git/modules/test-submodule")
+	env.On("getFileContent", "/dev/parent/.git/modules/test-submodule").Return("/dev/folder_worktree.git\n")
+	g := &git{
+		scm: scm{
+			env: env,
+		},
+	}
+	assert.True(t, g.enabled())
+	assert.Equal(t, "/dev/parent/test-submodule/../.git/modules/test-submodule", g.gitWorkingFolder)
+	assert.Equal(t, "/dev/parent/test-submodule/../.git/modules/test-submodule", g.gitRealFolder)
+	assert.Equal(t, "/dev/parent/test-submodule/../.git/modules/test-submodule", g.gitRootFolder)
+}
+
 func TestGetGitOutputForCommand(t *testing.T) {
 	args := []string{"-C", "", "--no-optional-locks", "-c", "core.quotepath=false", "-c", "color.status=false"}
 	commandArgs := []string{"symbolic-ref", "--short", "HEAD"}