From 56a59a1b32b4da572289100ae83c3ad75bdbaa2f Mon Sep 17 00:00:00 2001 From: Jan De Dobbeleer Date: Thu, 1 Sep 2022 19:49:17 +0200 Subject: [PATCH] feat(git): add link to GitKraken --- src/segments/git.go | 62 ++++++++++++++++++++--------------- src/segments/git_test.go | 22 ++++++------- website/docs/segments/git.mdx | 2 ++ 3 files changed, 49 insertions(+), 37 deletions(-) diff --git a/src/segments/git.go b/src/segments/git.go index a7355ef6..e88fa409 100644 --- a/src/segments/git.go +++ b/src/segments/git.go @@ -2,6 +2,7 @@ package segments import ( "fmt" + url2 "net/url" "oh-my-posh/environment" "oh-my-posh/properties" "oh-my-posh/regex" @@ -34,27 +35,6 @@ func (s *GitStatus) add(code string) { } } -type Git struct { - scm - - Working *GitStatus - Staging *GitStatus - Ahead int - Behind int - HEAD string - Ref string - Hash string - BranchStatus string - Upstream string - UpstreamIcon string - UpstreamURL string - UpstreamGone bool - StashCount int - WorktreeCount int - IsWorkTree bool - RepoName string -} - const ( // FetchStatus fetches the status of the repository FetchStatus properties.Property = "fetch_status" @@ -109,6 +89,28 @@ const ( GITCOMMAND = "git" ) +type Git struct { + scm + + Working *GitStatus + Staging *GitStatus + Ahead int + Behind int + HEAD string + Ref string + Hash string + ShortHash string + BranchStatus string + Upstream string + UpstreamIcon string + UpstreamURL string + UpstreamGone bool + StashCount int + WorktreeCount int + IsWorkTree bool + RepoName string +} + func (g *Git) Template() string { return " {{ .HEAD }} {{ .BranchStatus }}{{ if .Working.Changed }} \uF044 {{ .Working.String }}{{ end }}{{ if and (.Staging.Changed) (.Working.Changed) }} |{{ end }}{{ if .Staging.Changed }} \uF046 {{ .Staging.String }}{{ end }}{{ if gt .StashCount 0}} \uF692 {{ .StashCount }}{{ end }}{{ if gt .WorktreeCount 0}} \uf1bb {{ .WorktreeCount }}{{ end }} " //nolint: lll } @@ -140,6 +142,12 @@ func (g *Git) Enabled() bool { return true } +func (g *Git) Kraken() string { + root := g.getGitCommandOutput("rev-list", "--max-parents=0", "HEAD") + remote := g.getGitCommandOutput("remote", "get-url", "origin") + return fmt.Sprintf("gitkraken://repolink/%s/commit/%s?url=%s", root, g.Hash, url2.QueryEscape(remote)) +} + func (g *Git) shouldDisplay() bool { // when in a WSL shared folder, we must use git.exe and convert paths accordingly // for worktrees, stashes, and path to work @@ -307,7 +315,8 @@ func (g *Git) setGitStatus() { output := g.getGitCommandOutput(args...) for _, line := range strings.Split(output, "\n") { if strings.HasPrefix(line, HASH) && len(line) >= len(HASH)+7 { - g.Hash = line[len(HASH) : len(HASH)+7] + g.ShortHash = line[len(HASH) : len(HASH)+7] + g.Hash = line[len(HASH):] continue } if strings.HasPrefix(line, REF) && len(line) > len(REF) { @@ -480,7 +489,7 @@ func (g *Git) getGitRefFileSymbolicName(refFile string) string { func (g *Git) setPrettyHEADName() { // we didn't fetch status, fallback to parsing the HEAD file - if len(g.Hash) == 0 { + if len(g.ShortHash) == 0 { HEADRef := g.FileContents(g.workingDir, "HEAD") if strings.HasPrefix(HEADRef, BRANCHPREFIX) { branchName := strings.TrimPrefix(HEADRef, BRANCHPREFIX) @@ -489,7 +498,8 @@ func (g *Git) setPrettyHEADName() { } // no branch, points to commit if len(HEADRef) >= 7 { - g.Hash = HEADRef[0:7] + g.ShortHash = HEADRef[0:7] + g.Hash = HEADRef[0:] } } // check for tag @@ -499,11 +509,11 @@ func (g *Git) setPrettyHEADName() { return } // fallback to commit - if len(g.Hash) == 0 { + if len(g.ShortHash) == 0 { g.HEAD = g.props.GetString(NoCommitsIcon, "\uF594 ") return } - g.HEAD = fmt.Sprintf("%s%s", g.props.GetString(CommitIcon, "\uF417"), g.Hash) + g.HEAD = fmt.Sprintf("%s%s", g.props.GetString(CommitIcon, "\uF417"), g.ShortHash) } func (g *Git) getStashContext() int { diff --git a/src/segments/git_test.go b/src/segments/git_test.go index adbf87ee..fb0107c8 100644 --- a/src/segments/git_test.go +++ b/src/segments/git_test.go @@ -308,8 +308,8 @@ func TestSetGitHEADContextClean(t *testing.T) { RevertIcon: "revert ", }, }, - Hash: "1234567", - Ref: tc.Ref, + ShortHash: "1234567", + Ref: tc.Ref, } g.setGitHEADContext() assert.Equal(t, tc.Expected, g.HEAD, tc.Case) @@ -318,17 +318,17 @@ func TestSetGitHEADContextClean(t *testing.T) { func TestSetPrettyHEADName(t *testing.T) { cases := []struct { - Case string - Expected string - Hash string - Tag string - HEAD string + Case string + Expected string + ShortHash string + Tag string + HEAD string }{ {Case: "main", Expected: "branch main", HEAD: BRANCHPREFIX + "main"}, {Case: "no hash", Expected: "commit 1234567", HEAD: "12345678910"}, - {Case: "hash on tag", Hash: "132312322321", Expected: "tag tag-1", HEAD: "12345678910", Tag: "tag-1"}, + {Case: "hash on tag", ShortHash: "132312322321", Expected: "tag tag-1", HEAD: "12345678910", Tag: "tag-1"}, {Case: "no hash on tag", Expected: "tag tag-1", Tag: "tag-1"}, - {Case: "hash on commit", Hash: "1234567", Expected: "commit 1234567"}, + {Case: "hash on commit", ShortHash: "1234567", Expected: "commit 1234567"}, {Case: "no hash on commit", Expected: "commit 1234567", HEAD: "12345678910"}, } for _, tc := range cases { @@ -346,7 +346,7 @@ func TestSetPrettyHEADName(t *testing.T) { TagIcon: "tag ", }, }, - Hash: tc.Hash, + ShortHash: tc.ShortHash, } g.setPrettyHEADName() assert.Equal(t, tc.Expected, g.HEAD, tc.Case) @@ -485,7 +485,7 @@ func TestSetGitStatus(t *testing.T) { g.setGitStatus() assert.Equal(t, tc.ExpectedStaging, g.Staging, tc.Case) assert.Equal(t, tc.ExpectedWorking, g.Working, tc.Case) - assert.Equal(t, tc.ExpectedHash, g.Hash, tc.Case) + assert.Equal(t, tc.ExpectedHash, g.ShortHash, tc.Case) assert.Equal(t, tc.ExpectedRef, g.Ref, tc.Case) assert.Equal(t, tc.ExpectedUpstream, g.Upstream, tc.Case) assert.Equal(t, tc.ExpectedUpstreamGone, g.UpstreamGone, tc.Case) diff --git a/website/docs/segments/git.mdx b/website/docs/segments/git.mdx index 88ecfda8..f8746293 100644 --- a/website/docs/segments/git.mdx +++ b/website/docs/segments/git.mdx @@ -131,6 +131,7 @@ instead of the repo path. - `.WorktreeCount`: `int` - the worktree count - `.IsWorkTree`: `boolean` - if in a worktree 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 }}` ### GitStatus @@ -146,3 +147,4 @@ instead of the repo path. [hyperlinks]: /docs/configuration/templates#helper-functions [untracked]: https://git-scm.com/docs/git-status#Documentation/git-status.txt---untracked-filesltmodegt [submodules]: https://git-scm.com/docs/git-status#Documentation/git-status.txt---ignore-submodulesltwhengt +[kraken-ref]: https://www.gitkraken.com/invite/nQmDPR9D