From 09d4c95f152021f4496ccaa8c95731f96c344fd7 Mon Sep 17 00:00:00 2001 From: Jan De Dobbeleer Date: Sat, 10 Oct 2020 16:38:57 +0200 Subject: [PATCH] refactor: reduce git cli calls should impact #45 --- docs/docs/segment-git.md | 4 +-- segment_git.go | 66 +++++++++++++++++++--------------------- segment_git_test.go | 28 ++++++++--------- 3 files changed, 46 insertions(+), 52 deletions(-) diff --git a/docs/docs/segment-git.md b/docs/docs/segment-git.md index 6faea206..d0737114 100644 --- a/docs/docs/segment-git.md +++ b/docs/docs/segment-git.md @@ -31,7 +31,7 @@ Local changes can also shown by default using the following syntax for both the "local_staged_icon": "", "rebase_icon": " ", "cherry_pick_icon": " ", - "detached_icon": " ", + "commit_icon": " ", "tag_icon": "笠 " } } @@ -48,5 +48,5 @@ Local changes can also shown by default using the following syntax for both the - display_status: `boolean` - display the local changes or not - rebase_icon: `string` - icon/text to display before the context when in a rebase - cherry_pick_icon: `string` - icon/text to display before the context when doing a cherry-pick -- detached_icon: `string` - icon/text to display before the detached head context +- commit_icon: `string` - icon/text to display before the commit context - tag_icon: `string` - icon/text to display before the tag context diff --git a/segment_git.go b/segment_git.go index 8e4e4e13..a5347cb6 100755 --- a/segment_git.go +++ b/segment_git.go @@ -13,7 +13,7 @@ type gitRepo struct { staging *gitStatus ahead int behind int - branch string + HEAD string upstream string stashCount int } @@ -51,8 +51,8 @@ const ( RebaseIcon Property = "rebase_icon" //CherryPickIcon shows before the cherry-pick context CherryPickIcon Property = "cherry_pick_icon" - //DetachedIcon shows before the detached context - DetachedIcon Property = "detached_icon" + //CommitIcon shows before the detached context + CommitIcon Property = "commit_icon" //TagIcon shows before the tag context TagIcon Property = "tag_icon" ) @@ -69,7 +69,7 @@ func (g *git) string() string { g.getGitStatus() buffer := new(bytes.Buffer) // branchName - fmt.Fprintf(buffer, "%s", g.repo.branch) + fmt.Fprintf(buffer, "%s", g.repo.HEAD) displayStatus := g.props.getBool(DisplayStatus, true) if !displayStatus { return buffer.String() @@ -115,7 +115,7 @@ func (g *git) getGitStatus() { g.repo.behind, _ = strconv.Atoi(status["behind"]) g.repo.upstream = status["upstream"] } - g.repo.branch = g.getGitHEADContext() + g.repo.HEAD = g.getGitHEADContext(status["local"]) g.repo.stashCount = g.getStashContext() } @@ -124,41 +124,21 @@ func (g *git) getGitCommandOutput(args ...string) string { return g.env.runCommand("git", args...) } -func (g *git) getGitHEADContext() string { - commit := g.getGitCommandOutput("rev-parse", "--short", "HEAD") - rebase := g.getGitCommandOutput("rebase", "--show-current-patch") - if rebase != "" { - return g.getGitRebaseContext(commit) - } - // branch - icon := g.props.getString(BranchIcon, "BRANCH:") - ref := g.getGitCommandOutput("symbolic-ref", "-q", "--short", "HEAD") +func (g *git) getGitHEADContext(ref string) string { + branchIcon := g.props.getString(BranchIcon, "BRANCH:") if ref == "" { - // get a tag name if there's a match for HEAD - icon = g.props.getString(TagIcon, "TAG:") - ref = g.getGitCommandOutput("describe", "--tags", "--exact-match") + ref = g.getPrettyHEADName() + } else { + ref = fmt.Sprintf("%s%s", branchIcon, ref) } - // validate additional context - if g.env.hasFiles(".git/CHERRY_PICK_HEAD") { - sha := g.getGitRefFileSymbolicName("CHERRY_PICK_HEAD") - icon := g.props.getString(CherryPickIcon, "CHERRY PICK:") - return fmt.Sprintf("%s%s onto %s", icon, sha, ref) - } - if ref == "" { - ref = commit - icon = g.props.getString(DetachedIcon, "DETACHED:") - } - return fmt.Sprintf("%s%s", icon, ref) -} - -func (g *git) getGitRebaseContext(commit string) string { + // rebase if g.env.hasFolder(".git/rebase-merge") { origin := g.getGitRefFileSymbolicName("rebase-merge/orig-head") onto := g.getGitRefFileSymbolicName("rebase-merge/onto") step := g.getGitFileContents("rebase-merge/msgnum") total := g.getGitFileContents("rebase-merge/end") icon := g.props.getString(RebaseIcon, "REBASE:") - return fmt.Sprintf("%s%s onto %s (%s/%s) at %s", icon, origin, onto, step, total, commit) + return fmt.Sprintf("%s%s%s onto %s%s (%s/%s) at %s", icon, branchIcon, origin, branchIcon, onto, step, total, ref) } if g.env.hasFolder(".git/rebase-apply") { head := g.getGitFileContents("rebase-apply/head-name") @@ -166,10 +146,26 @@ func (g *git) getGitRebaseContext(commit string) string { step := g.getGitFileContents("rebase-apply/next") total := g.getGitFileContents("rebase-apply/last") icon := g.props.getString(RebaseIcon, "REBASING:") - return fmt.Sprintf("%s%s (%s/%s) at %s", icon, origin, step, total, commit) + return fmt.Sprintf("%s%s%s (%s/%s) at %s", icon, branchIcon, origin, step, total, ref) } - icon := g.props.getString(RebaseIcon, "REBASE:") - return fmt.Sprintf("%sUNKNOWN", icon) + // cherry-pick + if g.env.hasFiles(".git/CHERRY_PICK_HEAD") { + sha := g.getGitRefFileSymbolicName("CHERRY_PICK_HEAD") + icon := g.props.getString(CherryPickIcon, "CHERRY PICK:") + return fmt.Sprintf("%s%s onto %s", icon, sha, ref) + } + return ref +} + +func (g *git) getPrettyHEADName() string { + // check for tag + ref := g.getGitCommandOutput("describe", "--tags", "--exact-match") + if ref != "" { + return fmt.Sprintf("%s%s", g.props.getString(TagIcon, "TAG:"), ref) + } + // fallback to commit + ref = g.getGitCommandOutput("rev-parse", "--short", "HEAD") + return fmt.Sprintf("%s%s", g.props.getString(CommitIcon, "COMMIT:"), ref) } func (g *git) getGitFileContents(file string) string { diff --git a/segment_git_test.go b/segment_git_test.go index 14bc3d9e..173c05c6 100755 --- a/segment_git_test.go +++ b/segment_git_test.go @@ -68,8 +68,6 @@ func setupHEADContextEnv(context *detachedContext) environmentInfo { env.On("getFileContent", ".git/CHERRY_PICK_HEAD").Return(context.cherryPickSHA) env.On("hasFiles", ".git/CHERRY_PICK_HEAD").Return(context.cherryPick) env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "rev-parse", "--short", "HEAD"}).Return(context.currentCommit) - env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "rebase", "--show-current-patch"}).Return(context.rebase) - env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "symbolic-ref", "-q", "--short", "HEAD"}).Return(context.branchName) env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "describe", "--tags", "--exact-match"}).Return(context.tagName) env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "name-rev", "--name-only", "--exclude=tags/*", context.origin}).Return(context.origin) env.On("runCommand", "git", []string{"-c", "core.quotepath=false", "-c", "color.status=false", "name-rev", "--name-only", "--exclude=tags/*", context.onto}).Return(context.onto) @@ -78,7 +76,7 @@ func setupHEADContextEnv(context *detachedContext) environmentInfo { } func TestGetGitDetachedCommitHash(t *testing.T) { - want := "DETACHED:lalasha1" + want := "COMMIT:lalasha1" context := &detachedContext{ currentCommit: "lalasha1", } @@ -86,7 +84,7 @@ func TestGetGitDetachedCommitHash(t *testing.T) { g := &git{ env: env, } - got := g.getGitHEADContext() + got := g.getGitHEADContext("") assert.Equal(t, want, got) } @@ -100,12 +98,12 @@ func TestGetGitHEADContextTagName(t *testing.T) { g := &git{ env: env, } - got := g.getGitHEADContext() + got := g.getGitHEADContext("") assert.Equal(t, want, got) } func TestGetGitHEADContextRebaseMerge(t *testing.T) { - want := "REBASE:cool-feature-bro onto main (2/3) at whatever" + want := "REBASE:BRANCH:cool-feature-bro onto BRANCH:main (2/3) at COMMIT:whatever" context := &detachedContext{ currentCommit: "whatever", rebase: "true", @@ -119,12 +117,12 @@ func TestGetGitHEADContextRebaseMerge(t *testing.T) { g := &git{ env: env, } - got := g.getGitHEADContext() + got := g.getGitHEADContext("") assert.Equal(t, want, got) } func TestGetGitHEADContextRebaseApply(t *testing.T) { - want := "REBASING:cool-feature-bro (2/3) at whatever" + want := "REBASING:BRANCH:cool-feature-bro (2/3) at COMMIT:whatever" context := &detachedContext{ currentCommit: "whatever", rebase: "true", @@ -137,12 +135,12 @@ func TestGetGitHEADContextRebaseApply(t *testing.T) { g := &git{ env: env, } - got := g.getGitHEADContext() + got := g.getGitHEADContext("") assert.Equal(t, want, got) } func TestGetGitHEADContextRebaseUnknown(t *testing.T) { - want := "REBASE:UNKNOWN" + want := "COMMIT:whatever" context := &detachedContext{ currentCommit: "whatever", rebase: "true", @@ -151,12 +149,12 @@ func TestGetGitHEADContextRebaseUnknown(t *testing.T) { g := &git{ env: env, } - got := g.getGitHEADContext() + got := g.getGitHEADContext("") assert.Equal(t, want, got) } func TestGetGitHEADContextCherryPickOnBranch(t *testing.T) { - want := "CHERRY PICK:pickme onto main" + want := "CHERRY PICK:pickme onto BRANCH:main" context := &detachedContext{ currentCommit: "whatever", branchName: "main", @@ -167,12 +165,12 @@ func TestGetGitHEADContextCherryPickOnBranch(t *testing.T) { g := &git{ env: env, } - got := g.getGitHEADContext() + got := g.getGitHEADContext("main") assert.Equal(t, want, got) } func TestGetGitHEADContextCherryPickOnTag(t *testing.T) { - want := "CHERRY PICK:pickme onto v3.4.6" + want := "CHERRY PICK:pickme onto TAG:v3.4.6" context := &detachedContext{ currentCommit: "whatever", tagName: "v3.4.6", @@ -183,7 +181,7 @@ func TestGetGitHEADContextCherryPickOnTag(t *testing.T) { g := &git{ env: env, } - got := g.getGitHEADContext() + got := g.getGitHEADContext("") assert.Equal(t, want, got) }