mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-08-06 22:33:07 +02:00
Fix commit hash colors when filtering by path or aythor (#4789)
- **PR Description** Previously we would call git merge-base with the upstream branch to determine where unpushed commits end and pushed commits start, and also git merge-base with the main branch(es) to see where the merged commits start. This worked ok in normal cases, but it had two problems: - when filtering by path or by author, those merge-base commits would usually not be part of the commit list, so we would miss the point where we should switch from unpushed to pushed, or from pushed to merged. The consequence was that in filtering mode, all commit hashes were always yellow. - when main was merged into a feature branch, we would color all commits from that merge on down in green, even ones that are only part of the feature branch but not main. (See #3796) To fix these problems, we switch our approach to one where we call git rev-list with the branch in question, with negative refspecs for the upstream branch and the main branches, respectively; this gives us the complete picture of which commits are pushed/unpushed/merged, so it also works in the cases described above. And funnily, even though intuitively it feels more expensive, it actually performs better than the merge-base calls (for normal usage scenarios at least), so the commit-loading part of refresh is faster now in general. We are talking about differences like 300ms before, 140ms after, in some unscientific measurements I took (depends a lot on repo sizes, branch length, etc.). An exception are degenerate cases like feature branches with hundreds of thousands of commits, which are slower now; but I don't think we need to worry about those too much. Fixes #3796.
This commit is contained in:
@ -11,6 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/generics/set"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
@ -60,7 +61,7 @@ type GetCommitsOptions struct {
|
|||||||
FilterAuthor string
|
FilterAuthor string
|
||||||
IncludeRebaseCommits bool
|
IncludeRebaseCommits bool
|
||||||
RefName string // e.g. "HEAD" or "my_branch"
|
RefName string // e.g. "HEAD" or "my_branch"
|
||||||
RefForPushedStatus string // the ref to use for determining pushed/unpushed status
|
RefForPushedStatus models.Ref // 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)
|
// If non-empty, show divergence from this ref (left-right log)
|
||||||
@ -98,23 +99,25 @@ func (self *CommitLoader) GetCommits(opts GetCommitsOptions) ([]*models.Commit,
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var ancestor string
|
var unmergedCommitHashes *set.Set[string]
|
||||||
var remoteAncestor string
|
var remoteUnmergedCommitHashes *set.Set[string]
|
||||||
|
mainBranches := opts.MainBranches.Get()
|
||||||
|
|
||||||
go utils.Safe(func() {
|
go utils.Safe(func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
ancestor = opts.MainBranches.GetMergeBase(opts.RefName)
|
if len(mainBranches) > 0 {
|
||||||
|
unmergedCommitHashes = self.getReachableHashes(opts.RefName, mainBranches)
|
||||||
if opts.RefToShowDivergenceFrom != "" {
|
if opts.RefToShowDivergenceFrom != "" {
|
||||||
remoteAncestor = opts.MainBranches.GetMergeBase(opts.RefToShowDivergenceFrom)
|
remoteUnmergedCommitHashes = self.getReachableHashes(opts.RefToShowDivergenceFrom, mainBranches)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
passedFirstPushedCommit := false
|
var unpushedCommitHashes *set.Set[string]
|
||||||
// I can get this before
|
if opts.RefForPushedStatus != nil {
|
||||||
firstPushedCommit, err := self.getFirstPushedCommit(opts.RefForPushedStatus)
|
unpushedCommitHashes = self.getReachableHashes(opts.RefForPushedStatus.FullRefName(),
|
||||||
if err != nil {
|
append([]string{opts.RefForPushedStatus.RefName() + "@{u}"}, mainBranches...))
|
||||||
// must have no upstream branch so we'll consider everything as pushed
|
|
||||||
passedFirstPushedCommit = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
@ -123,19 +126,6 @@ func (self *CommitLoader) GetCommits(opts GetCommitsOptions) ([]*models.Commit,
|
|||||||
return nil, logErr
|
return nil, logErr
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, commit := range commits {
|
|
||||||
if commit.Hash() == firstPushedCommit {
|
|
||||||
passedFirstPushedCommit = true
|
|
||||||
}
|
|
||||||
if !commit.IsTODO() {
|
|
||||||
if passedFirstPushedCommit {
|
|
||||||
commit.Status = models.StatusPushed
|
|
||||||
} else {
|
|
||||||
commit.Status = models.StatusUnpushed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(commits) == 0 {
|
if len(commits) == 0 {
|
||||||
return commits, nil
|
return commits, nil
|
||||||
}
|
}
|
||||||
@ -153,10 +143,10 @@ func (self *CommitLoader) GetCommits(opts GetCommitsOptions) ([]*models.Commit,
|
|||||||
localSectionStart = len(commits)
|
localSectionStart = len(commits)
|
||||||
}
|
}
|
||||||
|
|
||||||
setCommitMergedStatuses(remoteAncestor, commits[:localSectionStart])
|
setCommitStatuses(unpushedCommitHashes, remoteUnmergedCommitHashes, commits[:localSectionStart])
|
||||||
setCommitMergedStatuses(ancestor, commits[localSectionStart:])
|
setCommitStatuses(unpushedCommitHashes, unmergedCommitHashes, commits[localSectionStart:])
|
||||||
} else {
|
} else {
|
||||||
setCommitMergedStatuses(ancestor, commits)
|
setCommitStatuses(unpushedCommitHashes, unmergedCommitHashes, commits)
|
||||||
}
|
}
|
||||||
|
|
||||||
return commits, nil
|
return commits, nil
|
||||||
@ -549,52 +539,40 @@ func (self *CommitLoader) getConflictedSequencerCommit(hashPool *utils.StringPoo
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func setCommitMergedStatuses(ancestor string, commits []*models.Commit) {
|
func setCommitStatuses(unpushedCommitHashes *set.Set[string], unmergedCommitHashes *set.Set[string], commits []*models.Commit) {
|
||||||
if ancestor == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
passedAncestor := false
|
|
||||||
for i, commit := range commits {
|
for i, commit := range commits {
|
||||||
// some commits aren't really commits and don't have hashes, such as the update-ref todo
|
if commit.IsTODO() {
|
||||||
if commit.Hash() != "" && strings.HasPrefix(ancestor, commit.Hash()) {
|
|
||||||
passedAncestor = true
|
|
||||||
}
|
|
||||||
if commit.Status != models.StatusPushed && commit.Status != models.StatusUnpushed {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if passedAncestor {
|
|
||||||
|
if unmergedCommitHashes == nil || unmergedCommitHashes.Includes(commit.Hash()) {
|
||||||
|
if unpushedCommitHashes != nil && unpushedCommitHashes.Includes(commit.Hash()) {
|
||||||
|
commits[i].Status = models.StatusUnpushed
|
||||||
|
} else {
|
||||||
|
commits[i].Status = models.StatusPushed
|
||||||
|
}
|
||||||
|
} else {
|
||||||
commits[i].Status = models.StatusMerged
|
commits[i].Status = models.StatusMerged
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ignoringWarnings(commandOutput string) string {
|
func (self *CommitLoader) getReachableHashes(refName string, notRefNames []string) *set.Set[string] {
|
||||||
trimmedOutput := strings.TrimSpace(commandOutput)
|
output, _, err := self.cmd.New(
|
||||||
split := strings.Split(trimmedOutput, "\n")
|
NewGitCmd("rev-list").
|
||||||
// need to get last line in case the first line is a warning about how the error is ambiguous.
|
|
||||||
// At some point we should find a way to make it unambiguous
|
|
||||||
lastLine := split[len(split)-1]
|
|
||||||
|
|
||||||
return lastLine
|
|
||||||
}
|
|
||||||
|
|
||||||
// getFirstPushedCommit returns the first commit hash which has been pushed to the ref's upstream.
|
|
||||||
// all commits above this are deemed unpushed and marked as such.
|
|
||||||
func (self *CommitLoader) getFirstPushedCommit(refName string) (string, error) {
|
|
||||||
output, err := self.cmd.New(
|
|
||||||
NewGitCmd("merge-base").
|
|
||||||
Arg(refName).
|
Arg(refName).
|
||||||
Arg(strings.TrimPrefix(refName, "refs/heads/") + "@{u}").
|
Arg(lo.Map(notRefNames, func(name string, _ int) string {
|
||||||
|
return "^" + name
|
||||||
|
})...).
|
||||||
ToArgv(),
|
ToArgv(),
|
||||||
).
|
).
|
||||||
DontLog().
|
DontLog().
|
||||||
RunWithOutput()
|
RunWithOutputs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return set.New[string]()
|
||||||
}
|
}
|
||||||
|
|
||||||
return ignoringWarnings(output), nil
|
return set.NewFromSlice(utils.SplitLines(output))
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLog gets the git log.
|
// getLog gets the git log.
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/jesseduffield/generics/set"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
@ -41,9 +42,9 @@ func TestGetCommits(t *testing.T) {
|
|||||||
{
|
{
|
||||||
testName: "should return no commits if there are none",
|
testName: "should return no commits if there are none",
|
||||||
logOrder: "topo-order",
|
logOrder: "topo-order",
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: &models.Branch{Name: "mybranch"}, IncludeRebaseCommits: false},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"rev-list", "refs/heads/mybranch", "^mybranch@{u}"}, "", nil).
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:+%H%x00%at%x00%aN%x00%ae%x00%P%x00%m%x00%D%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%P%x00%m%x00%D%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
||||||
|
|
||||||
expectedCommitOpts: []models.NewCommitOpts{},
|
expectedCommitOpts: []models.NewCommitOpts{},
|
||||||
@ -52,9 +53,9 @@ func TestGetCommits(t *testing.T) {
|
|||||||
{
|
{
|
||||||
testName: "should use proper upstream name for branch",
|
testName: "should use proper upstream name for branch",
|
||||||
logOrder: "topo-order",
|
logOrder: "topo-order",
|
||||||
opts: GetCommitsOptions{RefName: "refs/heads/mybranch", RefForPushedStatus: "refs/heads/mybranch", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "refs/heads/mybranch", RefForPushedStatus: &models.Branch{Name: "mybranch"}, IncludeRebaseCommits: false},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "refs/heads/mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"rev-list", "refs/heads/mybranch", "^mybranch@{u}"}, "", nil).
|
||||||
ExpectGitArgs([]string{"log", "refs/heads/mybranch", "--topo-order", "--oneline", "--pretty=format:+%H%x00%at%x00%aN%x00%ae%x00%P%x00%m%x00%D%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%P%x00%m%x00%D%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
||||||
|
|
||||||
expectedCommitOpts: []models.NewCommitOpts{},
|
expectedCommitOpts: []models.NewCommitOpts{},
|
||||||
@ -63,11 +64,11 @@ func TestGetCommits(t *testing.T) {
|
|||||||
{
|
{
|
||||||
testName: "should return commits if they are present",
|
testName: "should return commits if they are present",
|
||||||
logOrder: "topo-order",
|
logOrder: "topo-order",
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: &models.Branch{Name: "mybranch"}, IncludeRebaseCommits: false},
|
||||||
mainBranches: []string{"master", "main", "develop"},
|
mainBranches: []string{"master", "main", "develop"},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(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{"rev-list", "refs/heads/mybranch", "^mybranch@{u}", "^refs/remotes/origin/master", "^refs/remotes/origin/main"}, "0eea75e8c631fba6b58135697835d58ba4c18dbc\n", 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%P%x00%m%x00%D%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%P%x00%m%x00%D%x00%s", "--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
|
||||||
@ -77,8 +78,9 @@ func TestGetCommits(t *testing.T) {
|
|||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "develop@{u}"}, "", errors.New("error")). // this one doesn't, so it checks origin instead
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "develop@{u}"}, "", errors.New("error")). // this one doesn't, so it checks origin instead
|
||||||
ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/develop"}, "", errors.New("error")). // doesn't exist there, either, so it checks for a local branch
|
ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/develop"}, "", errors.New("error")). // doesn't exist there, either, so it checks for a local branch
|
||||||
ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/develop"}, "", errors.New("error")). // no local branch either
|
ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/develop"}, "", errors.New("error")). // no local branch either
|
||||||
// here it's seeing where our branch diverged from the master branch so that we can mark that commit and parent commits as 'merged'
|
// here it's seeing which of our commits are not on any of the main branches yet
|
||||||
ExpectGitArgs([]string{"merge-base", "HEAD", "refs/remotes/origin/master", "refs/remotes/origin/main"}, "26c07b1ab33860a1a7591a0638f9925ccf497ffa", nil),
|
ExpectGitArgs([]string{"rev-list", "HEAD", "^refs/remotes/origin/master", "^refs/remotes/origin/main"},
|
||||||
|
"0eea75e8c631fba6b58135697835d58ba4c18dbc\nb21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164\ne94e8fc5b6fab4cb755f29f1bdb3ee5e001df35c\nd8084cd558925eb7c9c38afeed5725c21653ab90\n65f910ebd85283b5cce9bf67d03d3f1a9ea3813a\n", nil),
|
||||||
|
|
||||||
expectedCommitOpts: []models.NewCommitOpts{
|
expectedCommitOpts: []models.NewCommitOpts{
|
||||||
{
|
{
|
||||||
@ -197,13 +199,13 @@ func TestGetCommits(t *testing.T) {
|
|||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "should not call merge-base for mainBranches if none exist",
|
testName: "should not call rev-list for mainBranches if none exist",
|
||||||
logOrder: "topo-order",
|
logOrder: "topo-order",
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: &models.Branch{Name: "mybranch"}, IncludeRebaseCommits: false},
|
||||||
mainBranches: []string{"master", "main"},
|
mainBranches: []string{"master", "main"},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(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{"rev-list", "refs/heads/mybranch", "^mybranch@{u}"}, "0eea75e8c631fba6b58135697835d58ba4c18dbc\n", 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%P%x00%m%x00%D%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%P%x00%m%x00%D%x00%s", "--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
|
||||||
@ -233,13 +235,13 @@ func TestGetCommits(t *testing.T) {
|
|||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "should call merge-base for all main branches that exist",
|
testName: "should call rev-list with all main branches that exist",
|
||||||
logOrder: "topo-order",
|
logOrder: "topo-order",
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: &models.Branch{Name: "mybranch"}, IncludeRebaseCommits: false},
|
||||||
mainBranches: []string{"master", "main", "develop", "1.0-hotfixes"},
|
mainBranches: []string{"master", "main", "develop", "1.0-hotfixes"},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(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{"rev-list", "refs/heads/mybranch", "^mybranch@{u}", "^refs/remotes/origin/master", "^refs/remotes/origin/develop", "^refs/remotes/origin/1.0-hotfixes"}, "0eea75e8c631fba6b58135697835d58ba4c18dbc\n", 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%P%x00%m%x00%D%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%P%x00%m%x00%D%x00%s", "--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
|
||||||
@ -249,8 +251,8 @@ func TestGetCommits(t *testing.T) {
|
|||||||
ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/main"}, "", errors.New("error")).
|
ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/main"}, "", errors.New("error")).
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "develop@{u}"}, "refs/remotes/origin/develop", nil).
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "develop@{u}"}, "refs/remotes/origin/develop", nil).
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "1.0-hotfixes@{u}"}, "refs/remotes/origin/1.0-hotfixes", nil).
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "1.0-hotfixes@{u}"}, "refs/remotes/origin/1.0-hotfixes", nil).
|
||||||
// here it's seeing where our branch diverged from the master branch so that we can mark that commit and parent commits as 'merged'
|
// here it's seeing which of our commits are not on any of the main branches yet
|
||||||
ExpectGitArgs([]string{"merge-base", "HEAD", "refs/remotes/origin/master", "refs/remotes/origin/develop", "refs/remotes/origin/1.0-hotfixes"}, "26c07b1ab33860a1a7591a0638f9925ccf497ffa", nil),
|
ExpectGitArgs([]string{"rev-list", "HEAD", "^refs/remotes/origin/master", "^refs/remotes/origin/develop", "^refs/remotes/origin/1.0-hotfixes"}, "0eea75e8c631fba6b58135697835d58ba4c18dbc\n", nil),
|
||||||
|
|
||||||
expectedCommitOpts: []models.NewCommitOpts{
|
expectedCommitOpts: []models.NewCommitOpts{
|
||||||
{
|
{
|
||||||
@ -273,9 +275,9 @@ func TestGetCommits(t *testing.T) {
|
|||||||
{
|
{
|
||||||
testName: "should not specify order if `log.order` is `default`",
|
testName: "should not specify order if `log.order` is `default`",
|
||||||
logOrder: "default",
|
logOrder: "default",
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: &models.Branch{Name: "mybranch"}, IncludeRebaseCommits: false},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"rev-list", "refs/heads/mybranch", "^mybranch@{u}"}, "", nil).
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:+%H%x00%at%x00%aN%x00%ae%x00%P%x00%m%x00%D%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:+%H%x00%at%x00%aN%x00%ae%x00%P%x00%m%x00%D%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
||||||
|
|
||||||
expectedCommitOpts: []models.NewCommitOpts{},
|
expectedCommitOpts: []models.NewCommitOpts{},
|
||||||
@ -284,9 +286,9 @@ func TestGetCommits(t *testing.T) {
|
|||||||
{
|
{
|
||||||
testName: "should set filter path",
|
testName: "should set filter path",
|
||||||
logOrder: "default",
|
logOrder: "default",
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", FilterPath: "src"},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: &models.Branch{Name: "mybranch"}, FilterPath: "src"},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"rev-list", "refs/heads/mybranch", "^mybranch@{u}"}, "", nil).
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:+%H%x00%at%x00%aN%x00%ae%x00%P%x00%m%x00%D%x00%s", "--abbrev=40", "--follow", "--name-status", "--no-show-signature", "--", "src"}, "", nil),
|
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:+%H%x00%at%x00%aN%x00%ae%x00%P%x00%m%x00%D%x00%s", "--abbrev=40", "--follow", "--name-status", "--no-show-signature", "--", "src"}, "", nil),
|
||||||
|
|
||||||
expectedCommitOpts: []models.NewCommitOpts{},
|
expectedCommitOpts: []models.NewCommitOpts{},
|
||||||
@ -536,11 +538,12 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCommitLoader_setCommitMergedStatuses(t *testing.T) {
|
func TestCommitLoader_setCommitStatuses(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
commitOpts []models.NewCommitOpts
|
commitOpts []models.NewCommitOpts
|
||||||
ancestor string
|
unmergedCommits []string
|
||||||
|
unpushedCommits []string
|
||||||
expectedCommitOpts []models.NewCommitOpts
|
expectedCommitOpts []models.NewCommitOpts
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,13 +551,13 @@ func TestCommitLoader_setCommitMergedStatuses(t *testing.T) {
|
|||||||
{
|
{
|
||||||
testName: "basic",
|
testName: "basic",
|
||||||
commitOpts: []models.NewCommitOpts{
|
commitOpts: []models.NewCommitOpts{
|
||||||
{Hash: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
{Hash: "12345", Name: "1", Action: models.ActionNone},
|
||||||
{Hash: "67890", Name: "2", Action: models.ActionNone, Status: models.StatusPushed},
|
{Hash: "67890", Name: "2", Action: models.ActionNone},
|
||||||
{Hash: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
{Hash: "abcde", Name: "3", Action: models.ActionNone},
|
||||||
},
|
},
|
||||||
ancestor: "67890",
|
unmergedCommits: []string{"12345"},
|
||||||
expectedCommitOpts: []models.NewCommitOpts{
|
expectedCommitOpts: []models.NewCommitOpts{
|
||||||
{Hash: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
{Hash: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusPushed},
|
||||||
{Hash: "67890", Name: "2", Action: models.ActionNone, Status: models.StatusMerged},
|
{Hash: "67890", Name: "2", Action: models.ActionNone, Status: models.StatusMerged},
|
||||||
{Hash: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusMerged},
|
{Hash: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusMerged},
|
||||||
},
|
},
|
||||||
@ -562,11 +565,12 @@ func TestCommitLoader_setCommitMergedStatuses(t *testing.T) {
|
|||||||
{
|
{
|
||||||
testName: "with update-ref",
|
testName: "with update-ref",
|
||||||
commitOpts: []models.NewCommitOpts{
|
commitOpts: []models.NewCommitOpts{
|
||||||
{Hash: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
{Hash: "12345", Name: "1", Action: models.ActionNone},
|
||||||
{Hash: "", Name: "", Action: todo.UpdateRef, Status: models.StatusNone},
|
{Hash: "", Name: "", Action: todo.UpdateRef},
|
||||||
{Hash: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
{Hash: "abcde", Name: "3", Action: models.ActionNone},
|
||||||
},
|
},
|
||||||
ancestor: "deadbeef",
|
unmergedCommits: []string{"12345", "abcde"},
|
||||||
|
unpushedCommits: []string{"12345"},
|
||||||
expectedCommitOpts: []models.NewCommitOpts{
|
expectedCommitOpts: []models.NewCommitOpts{
|
||||||
{Hash: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
{Hash: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||||
{Hash: "", Name: "", Action: todo.UpdateRef, Status: models.StatusNone},
|
{Hash: "", Name: "", Action: todo.UpdateRef, Status: models.StatusNone},
|
||||||
@ -581,7 +585,7 @@ func TestCommitLoader_setCommitMergedStatuses(t *testing.T) {
|
|||||||
|
|
||||||
commits := lo.Map(scenario.commitOpts,
|
commits := lo.Map(scenario.commitOpts,
|
||||||
func(opts models.NewCommitOpts, _ int) *models.Commit { return models.NewCommit(hashPool, opts) })
|
func(opts models.NewCommitOpts, _ int) *models.Commit { return models.NewCommit(hashPool, opts) })
|
||||||
setCommitMergedStatuses(scenario.ancestor, commits)
|
setCommitStatuses(set.NewFromSlice(scenario.unpushedCommits), set.NewFromSlice(scenario.unmergedCommits), commits)
|
||||||
expectedCommits := lo.Map(scenario.expectedCommitOpts,
|
expectedCommits := lo.Map(scenario.expectedCommitOpts,
|
||||||
func(opts models.NewCommitOpts, _ int) *models.Commit { return models.NewCommit(hashPool, opts) })
|
func(opts models.NewCommitOpts, _ int) *models.Commit { return models.NewCommit(hashPool, opts) })
|
||||||
assert.Equal(t, expectedCommits, commits)
|
assert.Equal(t, expectedCommits, commits)
|
||||||
|
@ -69,11 +69,11 @@ func (self *MainBranches) GetMergeBase(refName string) string {
|
|||||||
// very rarely, users must quit and restart lazygit to fix it; the latter is
|
// very rarely, users must quit and restart lazygit to fix it; the latter is
|
||||||
// also not very common, but can totally happen and is not an error.
|
// also not very common, but can totally happen and is not an error.
|
||||||
|
|
||||||
output, _ := self.cmd.New(
|
output, _, _ := self.cmd.New(
|
||||||
NewGitCmd("merge-base").Arg(refName).Arg(mainBranches...).
|
NewGitCmd("merge-base").Arg(refName).Arg(mainBranches...).
|
||||||
ToArgv(),
|
ToArgv(),
|
||||||
).DontLog().RunWithOutput()
|
).DontLog().RunWithOutputs()
|
||||||
return ignoringWarnings(output)
|
return strings.TrimSpace(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MainBranches) determineMainBranches(configuredMainBranches []string) []string {
|
func (self *MainBranches) determineMainBranches(configuredMainBranches []string) []string {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package types
|
package models
|
||||||
|
|
||||||
type Ref interface {
|
type Ref interface {
|
||||||
FullRefName() string
|
FullRefName() string
|
||||||
@ -7,8 +7,3 @@ type Ref interface {
|
|||||||
ParentRefName() string
|
ParentRefName() string
|
||||||
Description() string
|
Description() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type RefRange struct {
|
|
||||||
From Ref
|
|
||||||
To Ref
|
|
||||||
}
|
|
@ -59,7 +59,7 @@ func NewBranchesContext(c *ContextCommon) *BranchesContext {
|
|||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BranchesContext) GetSelectedRef() types.Ref {
|
func (self *BranchesContext) GetSelectedRef() models.Ref {
|
||||||
branch := self.GetSelected()
|
branch := self.GetSelected()
|
||||||
if branch == nil {
|
if branch == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -96,7 +96,7 @@ func (self *CommitFilesContext) ModelSearchResults(searchStr string, caseSensiti
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitFilesContext) ReInit(ref types.Ref, refRange *types.RefRange) {
|
func (self *CommitFilesContext) ReInit(ref models.Ref, refRange *types.RefRange) {
|
||||||
self.SetRef(ref)
|
self.SetRef(ref)
|
||||||
self.SetRefRange(refRange)
|
self.SetRefRange(refRange)
|
||||||
if refRange != nil {
|
if refRange != nil {
|
||||||
|
@ -164,7 +164,7 @@ func (self *LocalCommitsContext) CanRebase() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsContext) GetSelectedRef() types.Ref {
|
func (self *LocalCommitsContext) GetSelectedRef() models.Ref {
|
||||||
commit := self.GetSelected()
|
commit := self.GetSelected()
|
||||||
if commit == nil {
|
if commit == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -63,7 +63,7 @@ func (self *ReflogCommitsContext) CanRebase() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ReflogCommitsContext) GetSelectedRef() types.Ref {
|
func (self *ReflogCommitsContext) GetSelectedRef() models.Ref {
|
||||||
commit := self.GetSelected()
|
commit := self.GetSelected()
|
||||||
if commit == nil {
|
if commit == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -54,7 +54,7 @@ func NewRemoteBranchesContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemoteBranchesContext) GetSelectedRef() types.Ref {
|
func (self *RemoteBranchesContext) GetSelectedRef() models.Ref {
|
||||||
remoteBranch := self.GetSelected()
|
remoteBranch := self.GetSelected()
|
||||||
if remoteBranch == nil {
|
if remoteBranch == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -62,10 +62,10 @@ func (self *RemoteBranchesContext) GetSelectedRef() types.Ref {
|
|||||||
return remoteBranch
|
return remoteBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemoteBranchesContext) GetSelectedRefs() ([]types.Ref, int, int) {
|
func (self *RemoteBranchesContext) GetSelectedRefs() ([]models.Ref, int, int) {
|
||||||
items, startIdx, endIdx := self.GetSelectedItems()
|
items, startIdx, endIdx := self.GetSelectedItems()
|
||||||
|
|
||||||
refs := lo.Map(items, func(item *models.RemoteBranch, _ int) types.Ref {
|
refs := lo.Map(items, func(item *models.RemoteBranch, _ int) models.Ref {
|
||||||
return item
|
return item
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ func (self *StashContext) CanRebase() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StashContext) GetSelectedRef() types.Ref {
|
func (self *StashContext) GetSelectedRef() models.Ref {
|
||||||
stash := self.GetSelected()
|
stash := self.GetSelected()
|
||||||
if stash == nil {
|
if stash == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -141,7 +141,7 @@ func NewSubCommitsContext(
|
|||||||
|
|
||||||
type SubCommitsViewModel struct {
|
type SubCommitsViewModel struct {
|
||||||
// name of the ref that the sub-commits are shown for
|
// name of the ref that the sub-commits are shown for
|
||||||
ref types.Ref
|
ref models.Ref
|
||||||
refToShowDivergenceFrom string
|
refToShowDivergenceFrom string
|
||||||
*ListViewModel[*models.Commit]
|
*ListViewModel[*models.Commit]
|
||||||
|
|
||||||
@ -149,11 +149,11 @@ type SubCommitsViewModel struct {
|
|||||||
showBranchHeads bool
|
showBranchHeads bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubCommitsViewModel) SetRef(ref types.Ref) {
|
func (self *SubCommitsViewModel) SetRef(ref models.Ref) {
|
||||||
self.ref = ref
|
self.ref = ref
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubCommitsViewModel) GetRef() types.Ref {
|
func (self *SubCommitsViewModel) GetRef() models.Ref {
|
||||||
return self.ref
|
return self.ref
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ func (self *SubCommitsContext) CanRebase() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubCommitsContext) GetSelectedRef() types.Ref {
|
func (self *SubCommitsContext) GetSelectedRef() models.Ref {
|
||||||
commit := self.GetSelected()
|
commit := self.GetSelected()
|
||||||
if commit == nil {
|
if commit == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -52,7 +52,7 @@ func NewTagsContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TagsContext) GetSelectedRef() types.Ref {
|
func (self *TagsContext) GetSelectedRef() models.Ref {
|
||||||
tag := self.GetSelected()
|
tag := self.GetSelected()
|
||||||
if tag == nil {
|
if tag == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -174,7 +174,7 @@ func (self *DiffHelper) IgnoringWhitespaceSubTitle() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *DiffHelper) OpenDiffToolForRef(selectedRef types.Ref) error {
|
func (self *DiffHelper) OpenDiffToolForRef(selectedRef models.Ref) error {
|
||||||
to := selectedRef.RefName()
|
to := selectedRef.RefName()
|
||||||
from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff("")
|
from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff("")
|
||||||
_, err := self.c.RunSubprocess(self.c.Git().Diff.OpenDiffToolCmdObj(
|
_, err := self.c.RunSubprocess(self.c.Git().Diff.OpenDiffToolCmdObj(
|
||||||
|
@ -288,37 +288,37 @@ func (self *RefreshHelper) refreshCommitsAndCommitFiles() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) determineCheckedOutBranchName() string {
|
func (self *RefreshHelper) determineCheckedOutRef() models.Ref {
|
||||||
if rebasedBranch := self.c.Git().Status.BranchBeingRebased(); rebasedBranch != "" {
|
if rebasedBranch := self.c.Git().Status.BranchBeingRebased(); rebasedBranch != "" {
|
||||||
// During a rebase we're on a detached head, so cannot determine the
|
// During a rebase we're on a detached head, so cannot determine the
|
||||||
// branch name in the usual way. We need to read it from the
|
// branch name in the usual way. We need to read it from the
|
||||||
// ".git/rebase-merge/head-name" file instead.
|
// ".git/rebase-merge/head-name" file instead.
|
||||||
return strings.TrimPrefix(rebasedBranch, "refs/heads/")
|
return &models.Branch{Name: strings.TrimPrefix(rebasedBranch, "refs/heads/")}
|
||||||
}
|
}
|
||||||
|
|
||||||
if bisectInfo := self.c.Git().Bisect.GetInfo(); bisectInfo.Bisecting() && bisectInfo.GetStartHash() != "" {
|
if bisectInfo := self.c.Git().Bisect.GetInfo(); bisectInfo.Bisecting() && bisectInfo.GetStartHash() != "" {
|
||||||
// Likewise, when we're bisecting we're on a detached head as well. In
|
// Likewise, when we're bisecting we're on a detached head as well. In
|
||||||
// this case we read the branch name from the ".git/BISECT_START" file.
|
// this case we read the branch name from the ".git/BISECT_START" file.
|
||||||
return bisectInfo.GetStartHash()
|
return &models.Branch{Name: bisectInfo.GetStartHash()}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In all other cases, get the branch name by asking git what branch is
|
// In all other cases, get the branch name by asking git what branch is
|
||||||
// checked out. Note that if we're on a detached head (for reasons other
|
// checked out. Note that if we're on a detached head (for reasons other
|
||||||
// than rebasing or bisecting, i.e. it was explicitly checked out), then
|
// than rebasing or bisecting, i.e. it was explicitly checked out), then
|
||||||
// this will return an empty string.
|
// this will return an empty string.
|
||||||
if branchName, err := self.c.Git().Branch.CurrentBranchName(); err == nil {
|
if branchName, err := self.c.Git().Branch.CurrentBranchName(); err == nil && branchName != "" {
|
||||||
return branchName
|
return &models.Branch{Name: branchName}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should never get here unless the working copy is corrupt
|
// Should never get here unless the working copy is corrupt
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) refreshCommitsWithLimit() error {
|
func (self *RefreshHelper) refreshCommitsWithLimit() error {
|
||||||
self.c.Mutexes().LocalCommitsMutex.Lock()
|
self.c.Mutexes().LocalCommitsMutex.Lock()
|
||||||
defer self.c.Mutexes().LocalCommitsMutex.Unlock()
|
defer self.c.Mutexes().LocalCommitsMutex.Unlock()
|
||||||
|
|
||||||
checkedOutBranchName := self.determineCheckedOutBranchName()
|
checkedOutRef := self.determineCheckedOutRef()
|
||||||
commits, err := self.c.Git().Loaders.CommitLoader.GetCommits(
|
commits, err := self.c.Git().Loaders.CommitLoader.GetCommits(
|
||||||
git_commands.GetCommitsOptions{
|
git_commands.GetCommitsOptions{
|
||||||
Limit: self.c.Contexts().LocalCommits.GetLimitCommits(),
|
Limit: self.c.Contexts().LocalCommits.GetLimitCommits(),
|
||||||
@ -326,7 +326,7 @@ func (self *RefreshHelper) refreshCommitsWithLimit() error {
|
|||||||
FilterAuthor: self.c.Modes().Filtering.GetAuthor(),
|
FilterAuthor: self.c.Modes().Filtering.GetAuthor(),
|
||||||
IncludeRebaseCommits: true,
|
IncludeRebaseCommits: true,
|
||||||
RefName: self.refForLog(),
|
RefName: self.refForLog(),
|
||||||
RefForPushedStatus: checkedOutBranchName,
|
RefForPushedStatus: checkedOutRef,
|
||||||
All: self.c.Contexts().LocalCommits.GetShowWholeGitGraph(),
|
All: self.c.Contexts().LocalCommits.GetShowWholeGitGraph(),
|
||||||
MainBranches: self.c.Model().MainBranches,
|
MainBranches: self.c.Model().MainBranches,
|
||||||
HashPool: self.c.Model().HashPool,
|
HashPool: self.c.Model().HashPool,
|
||||||
@ -338,7 +338,11 @@ func (self *RefreshHelper) refreshCommitsWithLimit() error {
|
|||||||
self.c.Model().Commits = commits
|
self.c.Model().Commits = commits
|
||||||
self.RefreshAuthors(commits)
|
self.RefreshAuthors(commits)
|
||||||
self.c.Model().WorkingTreeStateAtLastCommitRefresh = self.c.Git().Status.WorkingTreeState()
|
self.c.Model().WorkingTreeStateAtLastCommitRefresh = self.c.Git().Status.WorkingTreeState()
|
||||||
self.c.Model().CheckedOutBranch = checkedOutBranchName
|
if checkedOutRef != nil {
|
||||||
|
self.c.Model().CheckedOutBranch = checkedOutRef.RefName()
|
||||||
|
} else {
|
||||||
|
self.c.Model().CheckedOutBranch = ""
|
||||||
|
}
|
||||||
|
|
||||||
self.refreshView(self.c.Contexts().LocalCommits)
|
self.refreshView(self.c.Contexts().LocalCommits)
|
||||||
return nil
|
return nil
|
||||||
@ -360,7 +364,7 @@ func (self *RefreshHelper) refreshSubCommitsWithLimit() error {
|
|||||||
IncludeRebaseCommits: false,
|
IncludeRebaseCommits: false,
|
||||||
RefName: self.c.Contexts().SubCommits.GetRef().FullRefName(),
|
RefName: self.c.Contexts().SubCommits.GetRef().FullRefName(),
|
||||||
RefToShowDivergenceFrom: self.c.Contexts().SubCommits.GetRefToShowDivergenceFrom(),
|
RefToShowDivergenceFrom: self.c.Contexts().SubCommits.GetRefToShowDivergenceFrom(),
|
||||||
RefForPushedStatus: self.c.Contexts().SubCommits.GetRef().FullRefName(),
|
RefForPushedStatus: self.c.Contexts().SubCommits.GetRef(),
|
||||||
MainBranches: self.c.Model().MainBranches,
|
MainBranches: self.c.Model().MainBranches,
|
||||||
HashPool: self.c.Model().HashPool,
|
HashPool: self.c.Model().HashPool,
|
||||||
},
|
},
|
||||||
|
@ -24,7 +24,7 @@ func NewSubCommitsHelper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ViewSubCommitsOpts struct {
|
type ViewSubCommitsOpts struct {
|
||||||
Ref types.Ref
|
Ref models.Ref
|
||||||
RefToShowDivergenceFrom string
|
RefToShowDivergenceFrom string
|
||||||
TitleRef string
|
TitleRef string
|
||||||
Context types.Context
|
Context types.Context
|
||||||
@ -39,7 +39,7 @@ func (self *SubCommitsHelper) ViewSubCommits(opts ViewSubCommitsOpts) error {
|
|||||||
FilterAuthor: self.c.Modes().Filtering.GetAuthor(),
|
FilterAuthor: self.c.Modes().Filtering.GetAuthor(),
|
||||||
IncludeRebaseCommits: false,
|
IncludeRebaseCommits: false,
|
||||||
RefName: opts.Ref.FullRefName(),
|
RefName: opts.Ref.FullRefName(),
|
||||||
RefForPushedStatus: opts.Ref.FullRefName(),
|
RefForPushedStatus: opts.Ref,
|
||||||
RefToShowDivergenceFrom: opts.RefToShowDivergenceFrom,
|
RefToShowDivergenceFrom: opts.RefToShowDivergenceFrom,
|
||||||
MainBranches: self.c.Model().MainBranches,
|
MainBranches: self.c.Model().MainBranches,
|
||||||
HashPool: self.c.Model().HashPool,
|
HashPool: self.c.Model().HashPool,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ var _ types.IController = &SwitchToDiffFilesController{}
|
|||||||
type CanSwitchToDiffFiles interface {
|
type CanSwitchToDiffFiles interface {
|
||||||
types.IListContext
|
types.IListContext
|
||||||
CanRebase() bool
|
CanRebase() bool
|
||||||
GetSelectedRef() types.Ref
|
GetSelectedRef() models.Ref
|
||||||
GetSelectedRefRangeForDiffFiles() *types.RefRange
|
GetSelectedRefRangeForDiffFiles() *types.RefRange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
)
|
)
|
||||||
@ -9,7 +10,7 @@ var _ types.IController = &SwitchToSubCommitsController{}
|
|||||||
|
|
||||||
type CanSwitchToSubCommits interface {
|
type CanSwitchToSubCommits interface {
|
||||||
types.IListContext
|
types.IListContext
|
||||||
GetSelectedRef() types.Ref
|
GetSelectedRef() models.Ref
|
||||||
ShowBranchHeadsInSubCommits() bool
|
ShowBranchHeadsInSubCommits() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ type CanSwitchToSubCommits interface {
|
|||||||
// but an attribute on it i.e. the ref of an item.
|
// but an attribute on it i.e. the ref of an item.
|
||||||
type SwitchToSubCommitsController struct {
|
type SwitchToSubCommitsController struct {
|
||||||
baseController
|
baseController
|
||||||
*ListControllerTrait[types.Ref]
|
*ListControllerTrait[models.Ref]
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
context CanSwitchToSubCommits
|
context CanSwitchToSubCommits
|
||||||
}
|
}
|
||||||
@ -32,7 +33,7 @@ func NewSwitchToSubCommitsController(
|
|||||||
c,
|
c,
|
||||||
context,
|
context,
|
||||||
context.GetSelectedRef,
|
context.GetSelectedRef,
|
||||||
func() ([]types.Ref, int, int) {
|
func() ([]models.Ref, int, int) {
|
||||||
panic("Not implemented")
|
panic("Not implemented")
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -15,8 +15,8 @@ type ICommitFileTreeViewModel interface {
|
|||||||
ICommitFileTree
|
ICommitFileTree
|
||||||
types.IListCursor
|
types.IListCursor
|
||||||
|
|
||||||
GetRef() types.Ref
|
GetRef() models.Ref
|
||||||
SetRef(types.Ref)
|
SetRef(models.Ref)
|
||||||
GetRefRange() *types.RefRange // can be nil, in which case GetRef should be used
|
GetRefRange() *types.RefRange // can be nil, in which case GetRef should be used
|
||||||
SetRefRange(*types.RefRange) // should be set to nil when selection is not a range
|
SetRefRange(*types.RefRange) // should be set to nil when selection is not a range
|
||||||
GetCanRebase() bool
|
GetCanRebase() bool
|
||||||
@ -30,7 +30,7 @@ type CommitFileTreeViewModel struct {
|
|||||||
|
|
||||||
// this is e.g. the commit for which we're viewing the files, if there is no
|
// this is e.g. the commit for which we're viewing the files, if there is no
|
||||||
// range selection, or if the range selection can't be used for some reason
|
// range selection, or if the range selection can't be used for some reason
|
||||||
ref types.Ref
|
ref models.Ref
|
||||||
|
|
||||||
// this is a commit range for which we're viewing the files. Can be nil, in
|
// this is a commit range for which we're viewing the files. Can be nil, in
|
||||||
// which case ref is used.
|
// which case ref is used.
|
||||||
@ -55,11 +55,11 @@ func NewCommitFileTreeViewModel(getFiles func() []*models.CommitFile, common *co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitFileTreeViewModel) GetRef() types.Ref {
|
func (self *CommitFileTreeViewModel) GetRef() models.Ref {
|
||||||
return self.ref
|
return self.ref
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitFileTreeViewModel) SetRef(ref types.Ref) {
|
func (self *CommitFileTreeViewModel) SetRef(ref models.Ref) {
|
||||||
self.ref = ref
|
self.ref = ref
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
pkg/gui/types/ref_range.go
Normal file
8
pkg/gui/types/ref_range.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import "github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
|
|
||||||
|
type RefRange struct {
|
||||||
|
From models.Ref
|
||||||
|
To models.Ref
|
||||||
|
}
|
Reference in New Issue
Block a user