From a1ff6b5c4adcc37062a299f8b4d5cb8a4b7bb6e4 Mon Sep 17 00:00:00 2001 From: David Kizivat Date: Mon, 9 Sep 2024 18:53:48 +0200 Subject: [PATCH] feat(git): add lists of commit's head, tag and remote references --- src/segments/git.go | 29 +++++++++++++++++- src/segments/git_test.go | 50 +++++++++++++++++++++++++++++-- website/docs/segments/scm/git.mdx | 17 ++++++++++- 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/src/segments/git.go b/src/segments/git.go index d318a484..a91cfb83 100644 --- a/src/segments/git.go +++ b/src/segments/git.go @@ -22,6 +22,13 @@ type Commit struct { Subject string Timestamp time.Time Sha string + Refs *Refs +} + +type Refs struct { + Heads []string + Tags []string + Remotes []string } type User struct { @@ -210,8 +217,9 @@ func (g *Git) Commit() *Commit { g.commit = &Commit{ Author: &User{}, Committer: &User{}, + Refs: &Refs{}, } - commitBody := g.getGitCommandOutput("log", "-1", "--pretty=format:an:%an%nae:%ae%ncn:%cn%nce:%ce%nat:%at%nsu:%s%nha:%H") + commitBody := g.getGitCommandOutput("log", "-1", "--pretty=format:an:%an%nae:%ae%ncn:%cn%nce:%ce%nat:%at%nsu:%s%nha:%H%nrf:%D", "--decorate=full") splitted := strings.Split(strings.TrimSpace(commitBody), "\n") for _, line := range splitted { line = strings.TrimSpace(line) @@ -237,6 +245,25 @@ func (g *Git) Commit() *Commit { g.commit.Subject = line case "ha:": g.commit.Sha = line + case "rf:": + refs := strings.Split(line, ", ") + for _, ref := range refs { + ref = strings.TrimSpace(ref) + switch { + case strings.HasSuffix(ref, "HEAD"): + continue + case strings.HasPrefix(ref, "tag: refs/tags/"): + g.commit.Refs.Tags = append(g.commit.Refs.Tags, strings.TrimPrefix(ref, "tag: refs/tags/")) + case strings.HasPrefix(ref, "refs/remotes/"): + g.commit.Refs.Remotes = append(g.commit.Refs.Remotes, strings.TrimPrefix(ref, "refs/remotes/")) + case strings.HasPrefix(ref, "HEAD -> refs/heads/"): + g.commit.Refs.Heads = append(g.commit.Refs.Heads, strings.TrimPrefix(ref, "HEAD -> refs/heads/")) + case strings.HasPrefix(ref, "refs/heads/"): + g.commit.Refs.Heads = append(g.commit.Refs.Heads, strings.TrimPrefix(ref, "refs/heads/")) + default: + g.commit.Refs.Heads = append(g.commit.Refs.Heads, ref) + } + } } } return g.commit diff --git a/src/segments/git_test.go b/src/segments/git_test.go index c9b6e42b..a83c9640 100644 --- a/src/segments/git_test.go +++ b/src/segments/git_test.go @@ -990,6 +990,7 @@ func TestGitCommit(t *testing.T) { at:1673176335 su:docs(error): you can't use cross segment properties ha:1234567891011121314 + rf:HEAD -> refs/heads/main, tag: refs/tags/tag-1, tag: refs/tags/0.3.4, refs/remotes/origin/main, refs/remotes/origin/dev, refs/heads/dev, refs/remotes/origin/HEAD `, Expected: &Commit{ Author: &User{ @@ -1002,7 +1003,12 @@ func TestGitCommit(t *testing.T) { }, Subject: "docs(error): you can't use cross segment properties", Timestamp: time.Unix(1673176335, 0), - Sha: "1234567891011121314", + Refs: &Refs{ + Tags: []string{"tag-1", "0.3.4"}, + Heads: []string{"main", "dev"}, + Remotes: []string{"origin/main", "origin/dev"}, + }, + Sha: "1234567891011121314", }, }, { @@ -1010,6 +1016,7 @@ func TestGitCommit(t *testing.T) { Expected: &Commit{ Author: &User{}, Committer: &User{}, + Refs: &Refs{}, }, }, { @@ -1030,6 +1037,44 @@ func TestGitCommit(t *testing.T) { }, Subject: "docs(error): you can't use cross segment properties", Timestamp: time.Unix(1673176335, 0), + Refs: &Refs{}, + }, + }, + { + Case: "No refs", + Output: ` + rf:HEAD + `, + Expected: &Commit{ + Author: &User{}, + Committer: &User{}, + Refs: &Refs{}, + }, + }, + { + Case: "Just tag ref", + Output: ` + rf:HEAD, tag: refs/tags/tag-1 + `, + Expected: &Commit{ + Author: &User{}, + Committer: &User{}, + Refs: &Refs{ + Tags: []string{"tag-1"}, + }, + }, + }, + { + Case: "Feature branch including slash", + Output: ` + rf:HEAD, tag: refs/tags/feat/feat-1 + `, + Expected: &Commit{ + Author: &User{}, + Committer: &User{}, + Refs: &Refs{ + Tags: []string{"feat/feat-1"}, + }, }, }, { @@ -1040,13 +1085,14 @@ func TestGitCommit(t *testing.T) { Expected: &Commit{ Author: &User{}, Committer: &User{}, + Refs: &Refs{}, }, }, } for _, tc := range cases { env := new(mock.Environment) - env.MockGitCommand("", tc.Output, "log", "-1", "--pretty=format:an:%an%nae:%ae%ncn:%cn%nce:%ce%nat:%at%nsu:%s%nha:%H") + env.MockGitCommand("", tc.Output, "log", "-1", "--pretty=format:an:%an%nae:%ae%ncn:%cn%nce:%ce%nat:%at%nsu:%s%nha:%H%nrf:%D", "--decorate=full") g := &Git{ scm: scm{ env: env, diff --git a/website/docs/segments/scm/git.mdx b/website/docs/segments/scm/git.mdx index 2857950f..bfd6763d 100644 --- a/website/docs/segments/scm/git.mdx +++ b/website/docs/segments/scm/git.mdx @@ -37,7 +37,7 @@ import Config from "@site/src/components/Config.js"; source: "cli", mapped_branches: { "feat/*": "🚀 ", - "bug/*": "🐛 ", + "bug/*": "🐛 ", }, }, }} @@ -175,6 +175,7 @@ Local changes use the following syntax: | `.Subject` | `string` | the commit subject | | `.Timestamp` | `time.Time` | the commit timestamp | | `.Sha` | `string` | the commit SHA1 | +| `.Refs` | `Refs` | the commit references | ### User @@ -183,6 +184,20 @@ Local changes use the following syntax: | `.Name` | `string` | the user's name | | `.Email` | `string` | the user's email | +### Refs + +| Name | Type | Description | +| ---------- | ---------- | ----------------- | +| `.Heads` | `[]string` | branches | +| `.Tags` | `[]string` | commit's tags | +| `.Remotes` | `[]string` | remote references | + +As these are arrays of strings, you can join them using the `join` function: + +```template +{{ join ", " .Commit.Refs.Tags }} +``` + ## posh-git If you want to display the default [posh-git][poshgit] output, **do not** use this segment