mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-28 16:02:01 +03:00
Add option RefToShowDivergenceFrom to GetCommitsOptions
Not used yet.
This commit is contained in:
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -68,6 +69,8 @@ type GetCommitsOptions struct {
|
|||||||
RefForPushedStatus string // the ref to use for determining pushed/unpushed status
|
RefForPushedStatus string // the ref to use for determining pushed/unpushed status
|
||||||
// determines if we show the whole git graph i.e. pass the '--all' flag
|
// determines if we show the whole git graph i.e. pass the '--all' flag
|
||||||
All bool
|
All bool
|
||||||
|
// If non-empty, show divergence from this ref (left-right log)
|
||||||
|
RefToShowDivergenceFrom string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommits obtains the commits of the current branch
|
// GetCommits obtains the commits of the current branch
|
||||||
@ -93,17 +96,21 @@ func (self *CommitLoader) GetCommits(opts GetCommitsOptions) ([]*models.Commit,
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
logErr = self.getLogCmd(opts).RunAndProcessLines(func(line string) (bool, error) {
|
logErr = self.getLogCmd(opts).RunAndProcessLines(func(line string) (bool, error) {
|
||||||
commit := self.extractCommitFromLine(line)
|
commit := self.extractCommitFromLine(line, opts.RefToShowDivergenceFrom != "")
|
||||||
commits = append(commits, commit)
|
commits = append(commits, commit)
|
||||||
return false, nil
|
return false, nil
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
var ancestor string
|
var ancestor string
|
||||||
|
var remoteAncestor string
|
||||||
go utils.Safe(func() {
|
go utils.Safe(func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
ancestor = self.getMergeBase(opts.RefName)
|
ancestor = self.getMergeBase(opts.RefName)
|
||||||
|
if opts.RefToShowDivergenceFrom != "" {
|
||||||
|
remoteAncestor = self.getMergeBase(opts.RefToShowDivergenceFrom)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
passedFirstPushedCommit := false
|
passedFirstPushedCommit := false
|
||||||
@ -137,7 +144,24 @@ func (self *CommitLoader) GetCommits(opts GetCommitsOptions) ([]*models.Commit,
|
|||||||
return commits, nil
|
return commits, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
setCommitMergedStatuses(ancestor, commits)
|
if opts.RefToShowDivergenceFrom != "" {
|
||||||
|
sort.SliceStable(commits, func(i, j int) bool {
|
||||||
|
// In the divergence view we want incoming commits to come first
|
||||||
|
return commits[i].Divergence > commits[j].Divergence
|
||||||
|
})
|
||||||
|
|
||||||
|
_, localSectionStart, found := lo.FindIndexOf(commits, func(commit *models.Commit) bool {
|
||||||
|
return commit.Divergence == models.DivergenceLeft
|
||||||
|
})
|
||||||
|
if !found {
|
||||||
|
localSectionStart = len(commits)
|
||||||
|
}
|
||||||
|
|
||||||
|
setCommitMergedStatuses(remoteAncestor, commits[:localSectionStart])
|
||||||
|
setCommitMergedStatuses(ancestor, commits[localSectionStart:])
|
||||||
|
} else {
|
||||||
|
setCommitMergedStatuses(ancestor, commits)
|
||||||
|
}
|
||||||
|
|
||||||
return commits, nil
|
return commits, nil
|
||||||
}
|
}
|
||||||
@ -177,8 +201,8 @@ func (self *CommitLoader) MergeRebasingCommits(commits []*models.Commit) ([]*mod
|
|||||||
// then puts them into a commit object
|
// then puts them into a commit object
|
||||||
// example input:
|
// example input:
|
||||||
// 8ad01fe32fcc20f07bc6693f87aa4977c327f1e1|10 hours ago|Jesse Duffield| (HEAD -> master, tag: v0.15.2)|refresh commits when adding a tag
|
// 8ad01fe32fcc20f07bc6693f87aa4977c327f1e1|10 hours ago|Jesse Duffield| (HEAD -> master, tag: v0.15.2)|refresh commits when adding a tag
|
||||||
func (self *CommitLoader) extractCommitFromLine(line string) *models.Commit {
|
func (self *CommitLoader) extractCommitFromLine(line string, showDivergence bool) *models.Commit {
|
||||||
split := strings.SplitN(line, "\x00", 7)
|
split := strings.SplitN(line, "\x00", 8)
|
||||||
|
|
||||||
sha := split[0]
|
sha := split[0]
|
||||||
unixTimestamp := split[1]
|
unixTimestamp := split[1]
|
||||||
@ -187,6 +211,10 @@ func (self *CommitLoader) extractCommitFromLine(line string) *models.Commit {
|
|||||||
extraInfo := strings.TrimSpace(split[4])
|
extraInfo := strings.TrimSpace(split[4])
|
||||||
parentHashes := split[5]
|
parentHashes := split[5]
|
||||||
message := split[6]
|
message := split[6]
|
||||||
|
divergence := models.DivergenceNone
|
||||||
|
if showDivergence {
|
||||||
|
divergence = lo.Ternary(split[7] == "<", models.DivergenceLeft, models.DivergenceRight)
|
||||||
|
}
|
||||||
|
|
||||||
tags := []string{}
|
tags := []string{}
|
||||||
|
|
||||||
@ -220,6 +248,7 @@ func (self *CommitLoader) extractCommitFromLine(line string) *models.Commit {
|
|||||||
AuthorName: authorName,
|
AuthorName: authorName,
|
||||||
AuthorEmail: authorEmail,
|
AuthorEmail: authorEmail,
|
||||||
Parents: parents,
|
Parents: parents,
|
||||||
|
Divergence: divergence,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +278,7 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode
|
|||||||
|
|
||||||
fullCommits := map[string]*models.Commit{}
|
fullCommits := map[string]*models.Commit{}
|
||||||
err = cmdObj.RunAndProcessLines(func(line string) (bool, error) {
|
err = cmdObj.RunAndProcessLines(func(line string) (bool, error) {
|
||||||
commit := self.extractCommitFromLine(line)
|
commit := self.extractCommitFromLine(line, false)
|
||||||
fullCommits[commit.Sha] = commit
|
fullCommits[commit.Sha] = commit
|
||||||
return false, nil
|
return false, nil
|
||||||
})
|
})
|
||||||
@ -623,8 +652,13 @@ func (self *CommitLoader) getFirstPushedCommit(refName string) (string, error) {
|
|||||||
func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
|
func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
|
||||||
config := self.UserConfig.Git.Log
|
config := self.UserConfig.Git.Log
|
||||||
|
|
||||||
|
refSpec := opts.RefName
|
||||||
|
if opts.RefToShowDivergenceFrom != "" {
|
||||||
|
refSpec += "..." + opts.RefToShowDivergenceFrom
|
||||||
|
}
|
||||||
|
|
||||||
cmdArgs := NewGitCmd("log").
|
cmdArgs := NewGitCmd("log").
|
||||||
Arg(opts.RefName).
|
Arg(refSpec).
|
||||||
ArgIf(config.Order != "default", "--"+config.Order).
|
ArgIf(config.Order != "default", "--"+config.Order).
|
||||||
ArgIf(opts.All, "--all").
|
ArgIf(opts.All, "--all").
|
||||||
Arg("--oneline").
|
Arg("--oneline").
|
||||||
@ -633,6 +667,7 @@ func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
|
|||||||
ArgIf(opts.Limit, "-300").
|
ArgIf(opts.Limit, "-300").
|
||||||
ArgIf(opts.FilterPath != "", "--follow").
|
ArgIf(opts.FilterPath != "", "--follow").
|
||||||
Arg("--no-show-signature").
|
Arg("--no-show-signature").
|
||||||
|
ArgIf(opts.RefToShowDivergenceFrom != "", "--left-right").
|
||||||
Arg("--").
|
Arg("--").
|
||||||
ArgIf(opts.FilterPath != "", opts.FilterPath).
|
ArgIf(opts.FilterPath != "", opts.FilterPath).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
@ -640,4 +675,4 @@ func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
|
|||||||
return self.cmd.New(cmdArgs).DontLog()
|
return self.cmd.New(cmdArgs).DontLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
const prettyFormat = `--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s`
|
const prettyFormat = `--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m`
|
||||||
|
@ -45,7 +45,7 @@ func TestGetCommits(t *testing.T) {
|
|||||||
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
||||||
|
|
||||||
expectedCommits: []*models.Commit{},
|
expectedCommits: []*models.Commit{},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
@ -57,7 +57,7 @@ func TestGetCommits(t *testing.T) {
|
|||||||
opts: GetCommitsOptions{RefName: "refs/heads/mybranch", RefForPushedStatus: "refs/heads/mybranch", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "refs/heads/mybranch", RefForPushedStatus: "refs/heads/mybranch", IncludeRebaseCommits: false},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "refs/heads/mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "refs/heads/mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
ExpectGitArgs([]string{"log", "refs/heads/mybranch", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
ExpectGitArgs([]string{"log", "refs/heads/mybranch", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
||||||
|
|
||||||
expectedCommits: []*models.Commit{},
|
expectedCommits: []*models.Commit{},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
@ -72,7 +72,7 @@ func TestGetCommits(t *testing.T) {
|
|||||||
// here it's seeing which commits are yet to be pushed
|
// here it's seeing which commits are yet to be pushed
|
||||||
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
// here it's actually getting all the commits in a formatted form, one per line
|
// here it's actually getting all the commits in a formatted form, one per line
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, commitsOutput, nil).
|
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, commitsOutput, nil).
|
||||||
// here it's testing which of the configured main branches have an upstream
|
// here it's testing which of the configured main branches have an upstream
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "refs/remotes/origin/master", nil). // this one does
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "refs/remotes/origin/master", nil). // this one does
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")). // this one doesn't, so it checks origin instead
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")). // this one doesn't, so it checks origin instead
|
||||||
@ -209,7 +209,7 @@ func TestGetCommits(t *testing.T) {
|
|||||||
// here it's seeing which commits are yet to be pushed
|
// here it's seeing which commits are yet to be pushed
|
||||||
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
// here it's actually getting all the commits in a formatted form, one per line
|
// here it's actually getting all the commits in a formatted form, one per line
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, singleCommitOutput, nil).
|
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, singleCommitOutput, nil).
|
||||||
// here it's testing which of the configured main branches exist; neither does
|
// here it's testing which of the configured main branches exist; neither does
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "", errors.New("error")).
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "", errors.New("error")).
|
||||||
ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/master"}, "", errors.New("error")).
|
ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/master"}, "", errors.New("error")).
|
||||||
@ -246,7 +246,7 @@ func TestGetCommits(t *testing.T) {
|
|||||||
// here it's seeing which commits are yet to be pushed
|
// here it's seeing which commits are yet to be pushed
|
||||||
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
// here it's actually getting all the commits in a formatted form, one per line
|
// here it's actually getting all the commits in a formatted form, one per line
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, singleCommitOutput, nil).
|
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, singleCommitOutput, nil).
|
||||||
// here it's testing which of the configured main branches exist
|
// here it's testing which of the configured main branches exist
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "refs/remotes/origin/master", nil).
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "refs/remotes/origin/master", nil).
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")).
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")).
|
||||||
@ -282,7 +282,7 @@ func TestGetCommits(t *testing.T) {
|
|||||||
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
||||||
|
|
||||||
expectedCommits: []*models.Commit{},
|
expectedCommits: []*models.Commit{},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
@ -294,7 +294,7 @@ func TestGetCommits(t *testing.T) {
|
|||||||
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", FilterPath: "src"},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", FilterPath: "src"},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--follow", "--no-show-signature", "--", "src"}, "", nil),
|
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--follow", "--no-show-signature", "--", "src"}, "", nil),
|
||||||
|
|
||||||
expectedCommits: []*models.Commit{},
|
expectedCommits: []*models.Commit{},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
|
@ -30,6 +30,17 @@ const (
|
|||||||
ActionConflict = todo.Comment + 1
|
ActionConflict = todo.Comment + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Divergence int
|
||||||
|
|
||||||
|
// For a divergence log (left/right comparison of two refs) this is set to
|
||||||
|
// either DivergenceLeft or DivergenceRight for each commit; for normal
|
||||||
|
// commit views it is always DivergenceNone.
|
||||||
|
const (
|
||||||
|
DivergenceNone Divergence = iota
|
||||||
|
DivergenceLeft
|
||||||
|
DivergenceRight
|
||||||
|
)
|
||||||
|
|
||||||
// Commit : A git commit
|
// Commit : A git commit
|
||||||
type Commit struct {
|
type Commit struct {
|
||||||
Sha string
|
Sha string
|
||||||
@ -41,6 +52,7 @@ type Commit struct {
|
|||||||
AuthorName string // something like 'Jesse Duffield'
|
AuthorName string // something like 'Jesse Duffield'
|
||||||
AuthorEmail string // something like 'jessedduffield@gmail.com'
|
AuthorEmail string // something like 'jessedduffield@gmail.com'
|
||||||
UnixTimestamp int64
|
UnixTimestamp int64
|
||||||
|
Divergence Divergence // set to DivergenceNone unless we are showing the divergence view
|
||||||
|
|
||||||
// SHAs of parent commits (will be multiple if it's a merge commit)
|
// SHAs of parent commits (will be multiple if it's a merge commit)
|
||||||
Parents []string
|
Parents []string
|
||||||
|
Reference in New Issue
Block a user