mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-03-05 20:49:04 -08:00
parent
a627be6b64
commit
b8c09f92ab
|
@ -6,6 +6,7 @@ import (
|
|||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||
|
@ -14,6 +15,19 @@ import (
|
|||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
type Commit struct {
|
||||
// git log -1 --pretty="format:%an%n%ae%n%cn%n%ce%n%at%n%s"
|
||||
Author *User
|
||||
Committer *User
|
||||
Subject string
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Email string
|
||||
}
|
||||
|
||||
// GitStatus represents part of the status of a git repository
|
||||
type GitStatus struct {
|
||||
ScmStatus
|
||||
|
@ -119,6 +133,8 @@ type Git struct {
|
|||
poshgit bool
|
||||
stashCount int
|
||||
worktreeCount int
|
||||
|
||||
commit *Commit
|
||||
}
|
||||
|
||||
func (g *Git) Template() string {
|
||||
|
@ -160,6 +176,43 @@ func (g *Git) Enabled() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (g *Git) Commit() *Commit {
|
||||
if g.commit != nil {
|
||||
return g.commit
|
||||
}
|
||||
g.commit = &Commit{
|
||||
Author: &User{},
|
||||
Committer: &User{},
|
||||
}
|
||||
commitBody := g.getGitCommandOutput("log", "-1", "--pretty=format:an:%an%nae:%ae%ncn:%cn%nce:%ce%nat:%at%nsu:%s")
|
||||
splitted := strings.Split(strings.TrimSpace(commitBody), "\n")
|
||||
for _, line := range splitted {
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) <= 3 {
|
||||
continue
|
||||
}
|
||||
anchor := line[:3]
|
||||
line = line[3:]
|
||||
switch anchor {
|
||||
case "an:":
|
||||
g.commit.Author.Name = line
|
||||
case "ae:":
|
||||
g.commit.Author.Email = line
|
||||
case "cn:":
|
||||
g.commit.Committer.Name = line
|
||||
case "ce:":
|
||||
g.commit.Committer.Email = line
|
||||
case "at:":
|
||||
if t, err := strconv.ParseInt(line, 10, 64); err == nil {
|
||||
g.commit.Timestamp = time.Unix(t, 0)
|
||||
}
|
||||
case "su:":
|
||||
g.commit.Subject = line
|
||||
}
|
||||
}
|
||||
return g.commit
|
||||
}
|
||||
|
||||
func (g *Git) StashCount() int {
|
||||
if g.poshgit || g.stashCount != 0 {
|
||||
return g.stashCount
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/mock"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
|
@ -892,3 +893,85 @@ func TestGitIgnoreSubmodules(t *testing.T) {
|
|||
assert.Equal(t, tc.Expected, got, tc.Case)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitCommit(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
Expected *Commit
|
||||
Output string
|
||||
}{
|
||||
{
|
||||
Case: "Clean commit",
|
||||
Output: `
|
||||
an:Jan De Dobbeleer
|
||||
ae:jan@ohmyposh.dev
|
||||
cn:Jan De Dobbeleer
|
||||
ce:jan@ohmyposh.dev
|
||||
at:1673176335
|
||||
su:docs(error): you can't use cross segment properties
|
||||
`,
|
||||
Expected: &Commit{
|
||||
Author: &User{
|
||||
Name: "Jan De Dobbeleer",
|
||||
Email: "jan@ohmyposh.dev",
|
||||
},
|
||||
Committer: &User{
|
||||
Name: "Jan De Dobbeleer",
|
||||
Email: "jan@ohmyposh.dev",
|
||||
},
|
||||
Subject: "docs(error): you can't use cross segment properties",
|
||||
Timestamp: time.Unix(1673176335, 0),
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: "No commit output",
|
||||
Expected: &Commit{
|
||||
Author: &User{},
|
||||
Committer: &User{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: "No author",
|
||||
Output: `
|
||||
an:
|
||||
ae:
|
||||
cn:Jan De Dobbeleer
|
||||
ce:jan@ohmyposh.dev
|
||||
at:1673176335
|
||||
su:docs(error): you can't use cross segment properties
|
||||
`,
|
||||
Expected: &Commit{
|
||||
Author: &User{},
|
||||
Committer: &User{
|
||||
Name: "Jan De Dobbeleer",
|
||||
Email: "jan@ohmyposh.dev",
|
||||
},
|
||||
Subject: "docs(error): you can't use cross segment properties",
|
||||
Timestamp: time.Unix(1673176335, 0),
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: "Bad timestamp",
|
||||
Output: `
|
||||
at:err
|
||||
`,
|
||||
Expected: &Commit{
|
||||
Author: &User{},
|
||||
Committer: &User{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.MockGitCommand("", tc.Output, "log", "-1", "--pretty=format:an:%an%nae:%ae%ncn:%cn%nce:%ce%nat:%at%nsu:%s")
|
||||
g := &Git{
|
||||
scm: scm{
|
||||
env: env,
|
||||
command: "git",
|
||||
},
|
||||
}
|
||||
got := g.Commit()
|
||||
assert.Equal(t, tc.Expected, got, tc.Case)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,6 +145,7 @@ You can set the following properties to `true` to enable fetching additional inf
|
|||
| `.IsBare` | `boolean` | if in a bare repo or not, only set when `fetch_bare_info` is set to `true` |
|
||||
| `.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 }}` |
|
||||
| `.Commit` | `Commit` | HEAD commit information (see below) |
|
||||
|
||||
### GitStatus
|
||||
|
||||
|
@ -158,6 +159,22 @@ You can set the following properties to `true` to enable fetching additional inf
|
|||
| `.Changed` | `boolean` | if the status contains changes or not |
|
||||
| `.String` | `string` | a string representation of the changes above |
|
||||
|
||||
### Commit
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------------ | ----------- | -------------------------------------- |
|
||||
| `.Author` | `User` | the author or the commit (see below) |
|
||||
| `.Committer` | `User` | the comitter or the commit (see below) |
|
||||
| `.Subject` | `string` | the commit subject |
|
||||
| `.Timestamp` | `time.Time` | the commit timestamp |
|
||||
|
||||
### User
|
||||
|
||||
| Name | Type | Description |
|
||||
| -------- | -------- | ---------------- |
|
||||
| `.Name` | `string` | the user's name |
|
||||
| `.Email` | `string` | the user's email |
|
||||
|
||||
Local changes use the following syntax:
|
||||
|
||||
| Icon | Description |
|
||||
|
|
Loading…
Reference in a new issue