From e45cd7ea17636a2d6c527eeda7d9b609c21c2851 Mon Sep 17 00:00:00 2001 From: Jan De Dobbeleer Date: Mon, 10 Oct 2022 08:55:20 +0200 Subject: [PATCH] feat(git): display when in bare repo --- src/segments/git.go | 19 ++++++++++++++++ src/segments/git_test.go | 42 +++++++++++++++++++++++++++++++++++ website/docs/segments/git.mdx | 18 ++++++++------- 3 files changed, 71 insertions(+), 8 deletions(-) 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/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"} 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]: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 }}` |