Repository: JanDeDobbeleer/oh-my-posh
Pull request #2924 (2022-10-10 06:55:47)

feat(git): display when in bare repo
### Prerequisites

- [x] I have read and understood the [contributing guide][CONTRIBUTING.md]
- [x] The commit message follows the [conventional commits][cc] guidelines
- [x] Tests for the changes have been added (for bug fixes/features)
- [x] Docs have been added/updated (for bug fixes/features)

<!---

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.

-->

[CONTRIBUTING.md]: https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/CONTRIBUTING.md
[cc]: https://www.conventionalcommits.org/en/v1.0.0/#summary



Patch:
diff --git a/src/segments/git.go b/src/segments/git.go
index 13d8fc53..0a24154e 100644
--- a/src/segments/git.go
+++ b/src/segments/git.go
@@ -110,6 +110,7 @@ type Git struct {
 	WorktreeCount  int
 	IsWorkTree     bool
 	RepoName       string
+	IsBare         bool
 }
 
 func (g *Git) Template() string {
@@ -122,6 +123,17 @@ func (g *Git) Enabled() bool {
 	}
 
 	g.RepoName = environment.Base(g.env, g.convertToLinuxPath(g.realDir))
+
+	if g.IsBare {
+		head := g.FileContents(g.workingDir, "HEAD")
+		branchIcon := g.props.GetString(BranchIcon, "\uE0A0")
+		g.Ref = strings.Replace(head, "ref: refs/heads/", "", 1)
+		g.HEAD = fmt.Sprintf("%s%s", branchIcon, g.Ref)
+		g.Working = &GitStatus{}
+		g.Staging = &GitStatus{}
+		return true
+	}
+
 	if g.props.GetBool(FetchWorktreeCount, false) {
 		g.WorktreeCount = g.getWorktreeContext()
 	}
@@ -170,6 +182,13 @@ func (g *Git) shouldDisplay() bool {
 
 	gitdir, err := g.env.HasParentFilePath(".git")
 	if err != nil {
+		g.realDir = g.env.Pwd()
+		bare := g.getGitCommandOutput("rev-parse", "--is-bare-repository")
+		if bare == "true" {
+			g.IsBare = true
+			g.workingDir = g.realDir
+			return true
+		}
 		return false
 	}
 
diff --git a/website/docs/segments/git.mdx b/website/docs/segments/git.mdx
index 6751641e..d6ca03fe 100644
--- a/website/docs/segments/git.mdx
+++ b/website/docs/segments/git.mdx
@@ -30,6 +30,7 @@ You can then use the `POSH_GIT_STRING` environment variable in a [text segment][
 ```json
 "template": "{{ if .Env.POSH_GIT_STRING }} {{ .Env.POSH_GIT_STRING }} {{ end }}"
 ```
+
 :::
 
 ## Sample Configuration
@@ -66,15 +67,15 @@ You can then use the `POSH_GIT_STRING` environment variable in a [text segment][
 As doing multiple git calls can slow down the prompt experience, we do not fetch information by default.
 You can set the following properties to `true` to enable fetching additional information (and populate the template).
 
-| Name                   | Type                | Description                                                                                                                                                                                                                                                                                                   |
-| ---------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `fetch_status`         | `boolean`           | fetch the local changes - defaults to `false`                                                                                                                                                                                                                                                                 |
-| `fetch_stash_count`    | `boolean`           | fetch stash count - defaults to `false`                                                                                                                                                                                                                                                                       |
-| `fetch_worktree_count` | `boolean`           | fetch worktree count - defaults to `false`                                                                                                                                                                                                                                                                    |
-| `fetch_upstream_icon`  | `boolean`           | fetch upstream icon - defaults to `false`                                                                                                                                                                                                                                                                     |
+| Name                   | Type                | Description                                                                                                                                                                                                                                                                                                                           |
+| ---------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `fetch_status`         | `boolean`           | fetch the local changes - defaults to `false`                                                                                                                                                                                                                                                                                         |
+| `fetch_stash_count`    | `boolean`           | fetch stash count - defaults to `false`                                                                                                                                                                                                                                                                                               |
+| `fetch_worktree_count` | `boolean`           | fetch worktree count - defaults to `false`                                                                                                                                                                                                                                                                                            |
+| `fetch_upstream_icon`  | `boolean`           | fetch upstream icon - defaults to `false`                                                                                                                                                                                                                                                                                             |
 | `untracked_modes`      | `map[string]string` | map of repo's where to override the default [untracked files mode][untracked]:<ul><li>`no`</li><li>`normal`</li><li>`all`</li></ul>For example `"untracked_modes": { "/Users/me/repos/repo1": "no" }` - defaults to `normal` for all repo's. If you want to override for all repo's, use `*` to set the mode instead of the repo path |
-| `ignore_submodules`    | `map[string]string` | map of repo's where to change the [--ignore-submodules][submodules] flag (`none`, `untracked`, `dirty` or `all`). For example `"ignore_submodules": { "/Users/me/repos/repo1": "all" }`. If you want to override for all repo's, use `*` to set the mode instead of the repo path                             |
-| `native_fallback`      | `boolean`           | when set to `true` and `git.exe` is not available when inside a WSL2 shared Windows drive, we will fallback to the native git executable to fetch data. Not all information can be displayed in this case. Defaults to `false`                                                                                |
+| `ignore_submodules`    | `map[string]string` | map of repo's where to change the [--ignore-submodules][submodules] flag (`none`, `untracked`, `dirty` or `all`). For example `"ignore_submodules": { "/Users/me/repos/repo1": "all" }`. If you want to override for all repo's, use `*` to set the mode instead of the repo path                                                     |
+| `native_fallback`      | `boolean`           | when set to `true` and `git.exe` is not available when inside a WSL2 shared Windows drive, we will fallback to the native git executable to fetch data. Not all information can be displayed in this case. Defaults to `false`                                                                                                        |
 
 ### Icons
 
@@ -141,6 +142,7 @@ You can set the following properties to `true` to enable fetching additional inf
 | `.StashCount`    | `int`       | the stash count                                                                                                                  |
 | `.WorktreeCount` | `int`       | the worktree count                                                                                                               |
 | `.IsWorkTree`    | `boolean`   | if in a worktree repo or not                                                                                                     |
+| `.IsBare`        | `boolean`   | if in a bare repo or not                                                                                                         |
 | `.Dir`           | `string`    | the repository's root directory                                                                                                  |
 | `.Kraken`        | `string`    | a link to the current HEAD in [GitKraken][kraken-ref] for use in [hyperlinks][hyperlinks] in templates `{{ url .HEAD .Kraken }}` |
 


Test patch:
diff --git a/src/segments/git_test.go b/src/segments/git_test.go
index 1a96bedc..5d00bab6 100644
--- a/src/segments/git_test.go
+++ b/src/segments/git_test.go
@@ -1,6 +1,7 @@
 package segments
 
 import (
+	"errors"
 	"fmt"
 	"oh-my-posh/environment"
 	"oh-my-posh/mock"
@@ -144,6 +145,47 @@ func TestEnabledInWorktree(t *testing.T) {
 	}
 }
 
+func TestEnabledInBareRepo(t *testing.T) {
+	cases := []struct {
+		Case            string
+		HEAD            string
+		IsBare          string
+		ExpectedEnabled bool
+		ExpectedHEAD    string
+	}{
+		{
+			Case:            "Bare repo on main",
+			IsBare:          "true",
+			HEAD:            "ref: refs/heads/main",
+			ExpectedEnabled: true,
+			ExpectedHEAD:    "main",
+		},
+		{
+			Case:   "Not a bare repo",
+			IsBare: "false",
+		},
+	}
+	for _, tc := range cases {
+		pwd := "/home/user/bare.git"
+		env := new(mock.MockedEnvironment)
+		env.On("InWSLSharedDrive").Return(false)
+		env.On("GOOS").Return("")
+		env.On("HasCommand", "git").Return(true)
+		env.On("HasParentFilePath", ".git").Return(&environment.FileInfo{}, errors.New("nope"))
+		env.MockGitCommand(pwd, tc.IsBare, "rev-parse", "--is-bare-repository")
+		env.On("Pwd").Return(pwd)
+		env.On("FileContent", "/home/user/bare.git/HEAD").Return(tc.HEAD)
+		g := &Git{
+			scm: scm{
+				env:   env,
+				props: properties.Map{},
+			},
+		}
+		assert.Equal(t, g.Enabled(), tc.ExpectedEnabled, tc.Case)
+		assert.Equal(t, g.Ref, tc.ExpectedHEAD, tc.Case)
+	}
+}
+
 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"}