mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-15 22:26:40 +02:00
add sub commit context
This commit is contained in:
parent
41df63cdc4
commit
974c6510b8
@ -37,14 +37,14 @@ type CommitListBuilder struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewCommitListBuilder builds a new commit list builder
|
// NewCommitListBuilder builds a new commit list builder
|
||||||
func NewCommitListBuilder(log *logrus.Entry, gitCommand *GitCommand, osCommand *OSCommand, tr *i18n.Localizer, cherryPickedCommits []*Commit) (*CommitListBuilder, error) {
|
func NewCommitListBuilder(log *logrus.Entry, gitCommand *GitCommand, osCommand *OSCommand, tr *i18n.Localizer, cherryPickedCommits []*Commit) *CommitListBuilder {
|
||||||
return &CommitListBuilder{
|
return &CommitListBuilder{
|
||||||
Log: log,
|
Log: log,
|
||||||
GitCommand: gitCommand,
|
GitCommand: gitCommand,
|
||||||
OSCommand: osCommand,
|
OSCommand: osCommand,
|
||||||
Tr: tr,
|
Tr: tr,
|
||||||
CherryPickedCommits: cherryPickedCommits,
|
CherryPickedCommits: cherryPickedCommits,
|
||||||
}, nil
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractCommitFromLine takes a line from a git log and extracts the sha, message, date, and tag if present
|
// extractCommitFromLine takes a line from a git log and extracts the sha, message, date, and tag if present
|
||||||
@ -82,33 +82,40 @@ func (c *CommitListBuilder) extractCommitFromLine(line string) *Commit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GetCommitsOptions struct {
|
type GetCommitsOptions struct {
|
||||||
Limit bool
|
Limit bool
|
||||||
FilterPath string
|
FilterPath string
|
||||||
|
IncludeRebaseCommits bool
|
||||||
|
RefName string // e.g. "HEAD" or "my_branch"
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommits obtains the commits of the current branch
|
// GetCommits obtains the commits of the current branch
|
||||||
func (c *CommitListBuilder) GetCommits(options GetCommitsOptions) ([]*Commit, error) {
|
func (c *CommitListBuilder) GetCommits(opts GetCommitsOptions) ([]*Commit, error) {
|
||||||
commits := []*Commit{}
|
commits := []*Commit{}
|
||||||
var rebasingCommits []*Commit
|
var rebasingCommits []*Commit
|
||||||
rebaseMode, err := c.GitCommand.RebaseMode()
|
rebaseMode := ""
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
if opts.IncludeRebaseCommits {
|
||||||
}
|
var err error
|
||||||
if rebaseMode != "" && options.FilterPath == "" {
|
rebaseMode, err = c.GitCommand.RebaseMode()
|
||||||
// here we want to also prepend the commits that we're in the process of rebasing
|
|
||||||
rebasingCommits, err = c.getRebasingCommits(rebaseMode)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(rebasingCommits) > 0 {
|
if rebaseMode != "" && opts.FilterPath == "" {
|
||||||
commits = append(commits, rebasingCommits...)
|
// here we want to also prepend the commits that we're in the process of rebasing
|
||||||
|
rebasingCommits, err = c.getRebasingCommits(rebaseMode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(rebasingCommits) > 0 {
|
||||||
|
commits = append(commits, rebasingCommits...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unpushedCommits := c.getUnpushedCommits()
|
unpushedCommits := c.getUnpushedCommits(opts.RefName)
|
||||||
cmd := c.getLogCmd(options)
|
cmd := c.getLogCmd(opts)
|
||||||
|
|
||||||
err = RunLineOutputCmd(cmd, func(line string) (bool, error) {
|
err := RunLineOutputCmd(cmd, func(line string) (bool, error) {
|
||||||
if strings.Split(line, " ")[0] != "gpg:" {
|
if strings.Split(line, " ")[0] != "gpg:" {
|
||||||
commit := c.extractCommitFromLine(line)
|
commit := c.extractCommitFromLine(line)
|
||||||
_, unpushed := unpushedCommits[commit.ShortSha()]
|
_, unpushed := unpushedCommits[commit.ShortSha()]
|
||||||
@ -287,9 +294,9 @@ func (c *CommitListBuilder) getMergeBase() (string, error) {
|
|||||||
|
|
||||||
// getUnpushedCommits Returns the sha's of the commits that have not yet been pushed
|
// getUnpushedCommits Returns the sha's of the commits that have not yet been pushed
|
||||||
// to the remote branch of the current branch, a map is returned to ease look up
|
// to the remote branch of the current branch, a map is returned to ease look up
|
||||||
func (c *CommitListBuilder) getUnpushedCommits() map[string]bool {
|
func (c *CommitListBuilder) getUnpushedCommits(refName string) map[string]bool {
|
||||||
pushables := map[string]bool{}
|
pushables := map[string]bool{}
|
||||||
o, err := c.OSCommand.RunCommandWithOutput("git rev-list @{u}..HEAD --abbrev-commit --abbrev=8")
|
o, err := c.OSCommand.RunCommandWithOutput("git rev-list %s@{u}..%s --abbrev-commit --abbrev=8", refName, refName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pushables
|
return pushables
|
||||||
}
|
}
|
||||||
@ -301,16 +308,16 @@ func (c *CommitListBuilder) getUnpushedCommits() map[string]bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getLog gets the git log.
|
// getLog gets the git log.
|
||||||
func (c *CommitListBuilder) getLogCmd(options GetCommitsOptions) *exec.Cmd {
|
func (c *CommitListBuilder) getLogCmd(opts GetCommitsOptions) *exec.Cmd {
|
||||||
limitFlag := ""
|
limitFlag := ""
|
||||||
if options.Limit {
|
if opts.Limit {
|
||||||
limitFlag = "-300"
|
limitFlag = "-300"
|
||||||
}
|
}
|
||||||
|
|
||||||
filterFlag := ""
|
filterFlag := ""
|
||||||
if options.FilterPath != "" {
|
if opts.FilterPath != "" {
|
||||||
filterFlag = fmt.Sprintf(" --follow -- %s", c.OSCommand.Quote(options.FilterPath))
|
filterFlag = fmt.Sprintf(" --follow -- %s", c.OSCommand.Quote(opts.FilterPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.OSCommand.ExecutableFromString(fmt.Sprintf("git log --oneline --pretty=format:\"%%H%s%%at%s%%aN%s%%d%s%%s\" %s --abbrev=%d --date=unix %s", SEPARATION_CHAR, SEPARATION_CHAR, SEPARATION_CHAR, SEPARATION_CHAR, limitFlag, 20, filterFlag))
|
return c.OSCommand.ExecutableFromString(fmt.Sprintf("git log %s --oneline --pretty=format:\"%%H%s%%at%s%%aN%s%%d%s%%s\" %s --abbrev=%d --date=unix %s", opts.RefName, SEPARATION_CHAR, SEPARATION_CHAR, SEPARATION_CHAR, SEPARATION_CHAR, limitFlag, 20, filterFlag))
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ func TestCommitListBuilderGetUnpushedCommits(t *testing.T) {
|
|||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
c := NewDummyCommitListBuilder()
|
c := NewDummyCommitListBuilder()
|
||||||
c.OSCommand.SetCommand(s.command)
|
c.OSCommand.SetCommand(s.command)
|
||||||
s.test(c.getUnpushedCommits())
|
s.test(c.getUnpushedCommits("HEAD"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,3 +36,7 @@ func (f *File) Names() []string {
|
|||||||
func (f *File) Matches(f2 *File) bool {
|
func (f *File) Matches(f2 *File) bool {
|
||||||
return utils.StringArraysOverlap(f.Names(), f2.Names())
|
return utils.StringArraysOverlap(f.Names(), f2.Names())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *File) ID() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
@ -98,12 +98,16 @@ func (gui *Gui) refreshCommits() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) refreshCommitsWithLimit() error {
|
func (gui *Gui) refreshCommitsWithLimit() error {
|
||||||
builder, err := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr, gui.State.CherryPickedCommits)
|
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr, gui.State.CherryPickedCommits)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
commits, err := builder.GetCommits(commands.GetCommitsOptions{Limit: gui.State.Panels.Commits.LimitCommits, FilterPath: gui.State.FilterPath})
|
commits, err := builder.GetCommits(
|
||||||
|
commands.GetCommitsOptions{
|
||||||
|
Limit: gui.State.Panels.Commits.LimitCommits,
|
||||||
|
FilterPath: gui.State.FilterPath,
|
||||||
|
IncludeRebaseCommits: true,
|
||||||
|
RefName: "HEAD",
|
||||||
|
},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package gui
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ const (
|
|||||||
TAGS_CONTEXT_KEY = "tags"
|
TAGS_CONTEXT_KEY = "tags"
|
||||||
BRANCH_COMMITS_CONTEXT_KEY = "commits"
|
BRANCH_COMMITS_CONTEXT_KEY = "commits"
|
||||||
REFLOG_COMMITS_CONTEXT_KEY = "reflogCommits"
|
REFLOG_COMMITS_CONTEXT_KEY = "reflogCommits"
|
||||||
|
SUB_COMMITS_CONTEXT_KEY = "subCommits"
|
||||||
COMMIT_FILES_CONTEXT_KEY = "commitFiles"
|
COMMIT_FILES_CONTEXT_KEY = "commitFiles"
|
||||||
STASH_CONTEXT_KEY = "stash"
|
STASH_CONTEXT_KEY = "stash"
|
||||||
MAIN_NORMAL_CONTEXT_KEY = "normal"
|
MAIN_NORMAL_CONTEXT_KEY = "normal"
|
||||||
@ -129,6 +131,7 @@ type ContextTree struct {
|
|||||||
BranchCommits SimpleContextNode
|
BranchCommits SimpleContextNode
|
||||||
CommitFiles SimpleContextNode
|
CommitFiles SimpleContextNode
|
||||||
ReflogCommits SimpleContextNode
|
ReflogCommits SimpleContextNode
|
||||||
|
SubCommits SimpleContextNode
|
||||||
Stash SimpleContextNode
|
Stash SimpleContextNode
|
||||||
Normal SimpleContextNode
|
Normal SimpleContextNode
|
||||||
Staging SimpleContextNode
|
Staging SimpleContextNode
|
||||||
@ -160,6 +163,7 @@ func (gui *Gui) allContexts() []Context {
|
|||||||
gui.Contexts.Staging.Context,
|
gui.Contexts.Staging.Context,
|
||||||
gui.Contexts.Merging.Context,
|
gui.Contexts.Merging.Context,
|
||||||
gui.Contexts.PatchBuilding.Context,
|
gui.Contexts.PatchBuilding.Context,
|
||||||
|
gui.Contexts.SubCommits.Context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +198,9 @@ func (gui *Gui) contextTree() ContextTree {
|
|||||||
ReflogCommits: SimpleContextNode{
|
ReflogCommits: SimpleContextNode{
|
||||||
Context: gui.reflogCommitsListContext(),
|
Context: gui.reflogCommitsListContext(),
|
||||||
},
|
},
|
||||||
|
SubCommits: SimpleContextNode{
|
||||||
|
Context: gui.subCommitsListContext(),
|
||||||
|
},
|
||||||
Branches: SimpleContextNode{
|
Branches: SimpleContextNode{
|
||||||
Context: gui.branchesListContext(),
|
Context: gui.branchesListContext(),
|
||||||
},
|
},
|
||||||
@ -510,6 +517,31 @@ func (gui *Gui) currentContext() Context {
|
|||||||
return gui.State.ContextStack[len(gui.State.ContextStack)-1]
|
return gui.State.ContextStack[len(gui.State.ContextStack)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) currentSideContext() *ListContext {
|
||||||
|
stack := gui.State.ContextStack
|
||||||
|
|
||||||
|
// on startup the stack can be empty so we'll return an empty string in that case
|
||||||
|
if len(stack) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the first context in the stack with the type of SIDE_CONTEXT
|
||||||
|
for i := range stack {
|
||||||
|
context := stack[len(stack)-1-i]
|
||||||
|
|
||||||
|
if context.GetKind() == SIDE_CONTEXT {
|
||||||
|
gui.Log.Warn(spew.Sdump(context.GetKey()))
|
||||||
|
return context.(*ListContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) defaultSideContext() Context {
|
||||||
|
return gui.Contexts.Files.Context
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) setInitialViewContexts() {
|
func (gui *Gui) setInitialViewContexts() {
|
||||||
// arguably we should only have our ViewContextMap and we should do away with
|
// arguably we should only have our ViewContextMap and we should do away with
|
||||||
// contexts on views, or vice versa
|
// contexts on views, or vice versa
|
||||||
|
@ -173,6 +173,13 @@ type reflogCommitPanelState struct {
|
|||||||
listPanelState
|
listPanelState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type subCommitPanelState struct {
|
||||||
|
listPanelState
|
||||||
|
|
||||||
|
// e.g. name of branch whose commits we're looking at
|
||||||
|
refName string
|
||||||
|
}
|
||||||
|
|
||||||
type stashPanelState struct {
|
type stashPanelState struct {
|
||||||
listPanelState
|
listPanelState
|
||||||
}
|
}
|
||||||
@ -199,6 +206,7 @@ type panelStates struct {
|
|||||||
Tags *tagsPanelState
|
Tags *tagsPanelState
|
||||||
Commits *commitPanelState
|
Commits *commitPanelState
|
||||||
ReflogCommits *reflogCommitPanelState
|
ReflogCommits *reflogCommitPanelState
|
||||||
|
SubCommits *subCommitPanelState
|
||||||
Stash *stashPanelState
|
Stash *stashPanelState
|
||||||
Menu *menuPanelState
|
Menu *menuPanelState
|
||||||
LineByLine *lineByLinePanelState
|
LineByLine *lineByLinePanelState
|
||||||
@ -237,6 +245,7 @@ type guiState struct {
|
|||||||
// if we're not in filtering mode, CommitFiles and FilteredReflogCommits will be
|
// if we're not in filtering mode, CommitFiles and FilteredReflogCommits will be
|
||||||
// one and the same
|
// one and the same
|
||||||
ReflogCommits []*commands.Commit
|
ReflogCommits []*commands.Commit
|
||||||
|
SubCommits []*commands.Commit
|
||||||
Remotes []*commands.Remote
|
Remotes []*commands.Remote
|
||||||
RemoteBranches []*commands.RemoteBranch
|
RemoteBranches []*commands.RemoteBranch
|
||||||
Tags []*commands.Tag
|
Tags []*commands.Tag
|
||||||
@ -289,13 +298,15 @@ func (gui *Gui) resetState() {
|
|||||||
CherryPickedCommits: make([]*commands.Commit, 0),
|
CherryPickedCommits: make([]*commands.Commit, 0),
|
||||||
StashEntries: make([]*commands.StashEntry, 0),
|
StashEntries: make([]*commands.StashEntry, 0),
|
||||||
Panels: &panelStates{
|
Panels: &panelStates{
|
||||||
|
// TODO: work out why some of these are -1 and some are 0. Last time I checked there was a good reason but I'm less certain now
|
||||||
Files: &filePanelState{listPanelState{SelectedLineIdx: -1}},
|
Files: &filePanelState{listPanelState{SelectedLineIdx: -1}},
|
||||||
Branches: &branchPanelState{listPanelState{SelectedLineIdx: 0}},
|
Branches: &branchPanelState{listPanelState{SelectedLineIdx: 0}},
|
||||||
Remotes: &remotePanelState{listPanelState{SelectedLineIdx: 0}},
|
Remotes: &remotePanelState{listPanelState{SelectedLineIdx: 0}},
|
||||||
RemoteBranches: &remoteBranchesState{listPanelState{SelectedLineIdx: -1}},
|
RemoteBranches: &remoteBranchesState{listPanelState{SelectedLineIdx: -1}},
|
||||||
Tags: &tagsPanelState{listPanelState{SelectedLineIdx: -1}},
|
Tags: &tagsPanelState{listPanelState{SelectedLineIdx: -1}},
|
||||||
Commits: &commitPanelState{listPanelState: listPanelState{SelectedLineIdx: -1}, LimitCommits: true},
|
Commits: &commitPanelState{listPanelState: listPanelState{SelectedLineIdx: -1}, LimitCommits: true},
|
||||||
ReflogCommits: &reflogCommitPanelState{listPanelState{SelectedLineIdx: 0}}, // TODO: might need to make -1
|
ReflogCommits: &reflogCommitPanelState{listPanelState{SelectedLineIdx: 0}},
|
||||||
|
SubCommits: &subCommitPanelState{listPanelState: listPanelState{SelectedLineIdx: 0}, refName: ""},
|
||||||
CommitFiles: &commitFilesPanelState{listPanelState: listPanelState{SelectedLineIdx: -1}, refName: ""},
|
CommitFiles: &commitFilesPanelState{listPanelState: listPanelState{SelectedLineIdx: -1}, refName: ""},
|
||||||
Stash: &stashPanelState{listPanelState{SelectedLineIdx: -1}},
|
Stash: &stashPanelState{listPanelState{SelectedLineIdx: -1}},
|
||||||
Menu: &menuPanelState{listPanelState: listPanelState{SelectedLineIdx: 0}, OnPress: nil},
|
Menu: &menuPanelState{listPanelState: listPanelState{SelectedLineIdx: 0}, OnPress: nil},
|
||||||
|
@ -555,6 +555,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||||||
Handler: gui.handleClipboardCopyBranch,
|
Handler: gui.handleClipboardCopyBranch,
|
||||||
Description: gui.Tr.SLocalize("copyBranchNameToClipboard"),
|
Description: gui.Tr.SLocalize("copyBranchNameToClipboard"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ViewName: "branches",
|
||||||
|
Contexts: []string{LOCAL_BRANCHES_CONTEXT_KEY},
|
||||||
|
Key: gui.getKey("universal.goInto"),
|
||||||
|
Handler: gui.wrappedHandler(gui.handleSwitchToSubCommits),
|
||||||
|
Description: gui.Tr.SLocalize("viewCommits"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ViewName: "branches",
|
ViewName: "branches",
|
||||||
Contexts: []string{TAGS_CONTEXT_KEY},
|
Contexts: []string{TAGS_CONTEXT_KEY},
|
||||||
@ -590,6 +597,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||||||
Handler: gui.handleCreateResetToTagMenu,
|
Handler: gui.handleCreateResetToTagMenu,
|
||||||
Description: gui.Tr.SLocalize("viewResetOptions"),
|
Description: gui.Tr.SLocalize("viewResetOptions"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ViewName: "branches",
|
||||||
|
Contexts: []string{TAGS_CONTEXT_KEY},
|
||||||
|
Key: gui.getKey("universal.goInto"),
|
||||||
|
Handler: gui.wrappedHandler(gui.handleSwitchToSubCommits),
|
||||||
|
Description: gui.Tr.SLocalize("viewCommits"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ViewName: "branches",
|
ViewName: "branches",
|
||||||
Key: gui.getKey("universal.nextTab"),
|
Key: gui.getKey("universal.nextTab"),
|
||||||
@ -616,6 +630,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||||||
Handler: gui.handleCreateResetToRemoteBranchMenu,
|
Handler: gui.handleCreateResetToRemoteBranchMenu,
|
||||||
Description: gui.Tr.SLocalize("viewResetOptions"),
|
Description: gui.Tr.SLocalize("viewResetOptions"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ViewName: "branches",
|
||||||
|
Contexts: []string{REMOTE_BRANCHES_CONTEXT_KEY},
|
||||||
|
Key: gui.getKey("universal.goInto"),
|
||||||
|
Handler: gui.wrappedHandler(gui.handleSwitchToSubCommits),
|
||||||
|
Description: gui.Tr.SLocalize("viewCommits"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ViewName: "branches",
|
ViewName: "branches",
|
||||||
Contexts: []string{REMOTES_CONTEXT_KEY},
|
Contexts: []string{REMOTES_CONTEXT_KEY},
|
||||||
@ -818,6 +839,27 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||||||
Handler: gui.handleCreateReflogResetMenu,
|
Handler: gui.handleCreateReflogResetMenu,
|
||||||
Description: gui.Tr.SLocalize("viewResetOptions"),
|
Description: gui.Tr.SLocalize("viewResetOptions"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ViewName: "branches",
|
||||||
|
Contexts: []string{SUB_COMMITS_CONTEXT_KEY},
|
||||||
|
Key: gui.getKey("universal.goInto"),
|
||||||
|
Handler: gui.wrappedHandler(gui.handleViewSubCommitFiles),
|
||||||
|
Description: gui.Tr.SLocalize("viewCommitFiles"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ViewName: "branches",
|
||||||
|
Contexts: []string{SUB_COMMITS_CONTEXT_KEY},
|
||||||
|
Key: gui.getKey("universal.select"),
|
||||||
|
Handler: gui.handleCheckoutSubCommit,
|
||||||
|
Description: gui.Tr.SLocalize("checkoutCommit"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ViewName: "branches",
|
||||||
|
Contexts: []string{SUB_COMMITS_CONTEXT_KEY},
|
||||||
|
Key: gui.getKey("commits.viewResetOptions"),
|
||||||
|
Handler: gui.wrappedHandler(gui.handleCreateSubCommitResetMenu),
|
||||||
|
Description: gui.Tr.SLocalize("viewResetOptions"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ViewName: "stash",
|
ViewName: "stash",
|
||||||
Key: gui.getKey("universal.goInto"),
|
Key: gui.getKey("universal.goInto"),
|
||||||
|
@ -338,7 +338,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
func (gui *Gui) onInitialViewsCreation() error {
|
func (gui *Gui) onInitialViewsCreation() error {
|
||||||
gui.setInitialViewContexts()
|
gui.setInitialViewContexts()
|
||||||
|
|
||||||
if err := gui.switchContext(gui.Contexts.Files.Context); err != nil {
|
if err := gui.switchContext(gui.defaultSideContext()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,14 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: if we don't end up using this, delete it
|
||||||
|
const (
|
||||||
|
CONTAINS_NOTHING = iota
|
||||||
|
CONTAINS_COMMITS
|
||||||
|
CONTAINS_FILES
|
||||||
|
CONTAINS_BRANCHES
|
||||||
|
)
|
||||||
|
|
||||||
type ListContext struct {
|
type ListContext struct {
|
||||||
ViewName string
|
ViewName string
|
||||||
ContextKey string
|
ContextKey string
|
||||||
@ -21,12 +29,17 @@ type ListContext struct {
|
|||||||
Kind int
|
Kind int
|
||||||
ParentContext Context
|
ParentContext Context
|
||||||
WindowName string
|
WindowName string
|
||||||
|
Contains int
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListItem interface {
|
type ListItem interface {
|
||||||
ID() string
|
ID() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lc *ListContext) GetContains() int {
|
||||||
|
return lc.Contains
|
||||||
|
}
|
||||||
|
|
||||||
func (lc *ListContext) SetWindowName(windowName string) {
|
func (lc *ListContext) SetWindowName(windowName string) {
|
||||||
lc.WindowName = windowName
|
lc.WindowName = windowName
|
||||||
}
|
}
|
||||||
@ -69,7 +82,6 @@ func (lc *ListContext) GetSelectedItem() ListItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (lc *ListContext) GetSelectedItemId() string {
|
func (lc *ListContext) GetSelectedItemId() string {
|
||||||
|
|
||||||
item := lc.GetSelectedItem()
|
item := lc.GetSelectedItem()
|
||||||
|
|
||||||
if item == nil {
|
if item == nil {
|
||||||
@ -119,6 +131,13 @@ func (lc *ListContext) HandleFocus() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view, err := lc.Gui.g.View(lc.ViewName)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
view.FocusPoint(0, lc.GetPanelState().GetSelectedLineIdx())
|
||||||
|
|
||||||
if lc.Gui.inDiffMode() {
|
if lc.Gui.inDiffMode() {
|
||||||
return lc.Gui.renderDiff()
|
return lc.Gui.renderDiff()
|
||||||
}
|
}
|
||||||
@ -248,6 +267,7 @@ func (gui *Gui) menuListContext() *ListContext {
|
|||||||
Gui: gui,
|
Gui: gui,
|
||||||
RendersToMainView: false,
|
RendersToMainView: false,
|
||||||
Kind: PERSISTENT_POPUP,
|
Kind: PERSISTENT_POPUP,
|
||||||
|
Contains: CONTAINS_NOTHING,
|
||||||
|
|
||||||
// no GetDisplayStrings field because we do a custom render on menu creation
|
// no GetDisplayStrings field because we do a custom render on menu creation
|
||||||
}
|
}
|
||||||
@ -267,6 +287,7 @@ func (gui *Gui) filesListContext() *ListContext {
|
|||||||
GetDisplayStrings: func() [][]string {
|
GetDisplayStrings: func() [][]string {
|
||||||
return presentation.GetFileListDisplayStrings(gui.State.Files, gui.State.Diff.Ref)
|
return presentation.GetFileListDisplayStrings(gui.State.Files, gui.State.Diff.Ref)
|
||||||
},
|
},
|
||||||
|
Contains: CONTAINS_NOTHING,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,6 +304,7 @@ func (gui *Gui) branchesListContext() *ListContext {
|
|||||||
GetDisplayStrings: func() [][]string {
|
GetDisplayStrings: func() [][]string {
|
||||||
return presentation.GetBranchListDisplayStrings(gui.State.Branches, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Diff.Ref)
|
return presentation.GetBranchListDisplayStrings(gui.State.Branches, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Diff.Ref)
|
||||||
},
|
},
|
||||||
|
Contains: CONTAINS_COMMITS,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,6 +322,7 @@ func (gui *Gui) remotesListContext() *ListContext {
|
|||||||
GetDisplayStrings: func() [][]string {
|
GetDisplayStrings: func() [][]string {
|
||||||
return presentation.GetRemoteListDisplayStrings(gui.State.Remotes, gui.State.Diff.Ref)
|
return presentation.GetRemoteListDisplayStrings(gui.State.Remotes, gui.State.Diff.Ref)
|
||||||
},
|
},
|
||||||
|
Contains: CONTAINS_BRANCHES,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,6 +339,7 @@ func (gui *Gui) remoteBranchesListContext() *ListContext {
|
|||||||
GetDisplayStrings: func() [][]string {
|
GetDisplayStrings: func() [][]string {
|
||||||
return presentation.GetRemoteBranchListDisplayStrings(gui.State.RemoteBranches, gui.State.Diff.Ref)
|
return presentation.GetRemoteBranchListDisplayStrings(gui.State.RemoteBranches, gui.State.Diff.Ref)
|
||||||
},
|
},
|
||||||
|
Contains: CONTAINS_COMMITS,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +356,7 @@ func (gui *Gui) tagsListContext() *ListContext {
|
|||||||
GetDisplayStrings: func() [][]string {
|
GetDisplayStrings: func() [][]string {
|
||||||
return presentation.GetTagListDisplayStrings(gui.State.Tags, gui.State.Diff.Ref)
|
return presentation.GetTagListDisplayStrings(gui.State.Tags, gui.State.Diff.Ref)
|
||||||
},
|
},
|
||||||
|
Contains: CONTAINS_COMMITS,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,6 +374,7 @@ func (gui *Gui) branchCommitsListContext() *ListContext {
|
|||||||
GetDisplayStrings: func() [][]string {
|
GetDisplayStrings: func() [][]string {
|
||||||
return presentation.GetCommitListDisplayStrings(gui.State.Commits, gui.State.ScreenMode != SCREEN_NORMAL, gui.cherryPickedCommitShaMap(), gui.State.Diff.Ref)
|
return presentation.GetCommitListDisplayStrings(gui.State.Commits, gui.State.ScreenMode != SCREEN_NORMAL, gui.cherryPickedCommitShaMap(), gui.State.Diff.Ref)
|
||||||
},
|
},
|
||||||
|
Contains: CONTAINS_FILES,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,6 +391,24 @@ func (gui *Gui) reflogCommitsListContext() *ListContext {
|
|||||||
GetDisplayStrings: func() [][]string {
|
GetDisplayStrings: func() [][]string {
|
||||||
return presentation.GetReflogCommitListDisplayStrings(gui.State.FilteredReflogCommits, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Diff.Ref)
|
return presentation.GetReflogCommitListDisplayStrings(gui.State.FilteredReflogCommits, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Diff.Ref)
|
||||||
},
|
},
|
||||||
|
Contains: CONTAINS_FILES,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) subCommitsListContext() *ListContext {
|
||||||
|
return &ListContext{
|
||||||
|
ViewName: "branches",
|
||||||
|
ContextKey: SUB_COMMITS_CONTEXT_KEY,
|
||||||
|
GetItemsLength: func() int { return len(gui.State.SubCommits) },
|
||||||
|
GetPanelState: func() IListPanelState { return gui.State.Panels.SubCommits },
|
||||||
|
OnFocus: gui.handleSubCommitSelect,
|
||||||
|
Gui: gui,
|
||||||
|
RendersToMainView: true,
|
||||||
|
Kind: SIDE_CONTEXT,
|
||||||
|
GetDisplayStrings: func() [][]string {
|
||||||
|
return presentation.GetCommitListDisplayStrings(gui.State.SubCommits, gui.State.ScreenMode != SCREEN_NORMAL, gui.cherryPickedCommitShaMap(), gui.State.Diff.Ref)
|
||||||
|
},
|
||||||
|
Contains: CONTAINS_COMMITS,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,6 +425,7 @@ func (gui *Gui) stashListContext() *ListContext {
|
|||||||
GetDisplayStrings: func() [][]string {
|
GetDisplayStrings: func() [][]string {
|
||||||
return presentation.GetStashEntryListDisplayStrings(gui.State.StashEntries, gui.State.Diff.Ref)
|
return presentation.GetStashEntryListDisplayStrings(gui.State.StashEntries, gui.State.Diff.Ref)
|
||||||
},
|
},
|
||||||
|
Contains: CONTAINS_FILES,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,6 +443,7 @@ func (gui *Gui) commitFilesListContext() *ListContext {
|
|||||||
GetDisplayStrings: func() [][]string {
|
GetDisplayStrings: func() [][]string {
|
||||||
return presentation.GetCommitFileListDisplayStrings(gui.State.CommitFiles, gui.State.Diff.Ref)
|
return presentation.GetCommitFileListDisplayStrings(gui.State.CommitFiles, gui.State.Diff.Ref)
|
||||||
},
|
},
|
||||||
|
Contains: CONTAINS_NOTHING,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,6 +457,7 @@ func (gui *Gui) getListContexts() []*ListContext {
|
|||||||
gui.tagsListContext(),
|
gui.tagsListContext(),
|
||||||
gui.branchCommitsListContext(),
|
gui.branchCommitsListContext(),
|
||||||
gui.reflogCommitsListContext(),
|
gui.reflogCommitsListContext(),
|
||||||
|
gui.subCommitsListContext(),
|
||||||
gui.stashListContext(),
|
gui.stashListContext(),
|
||||||
gui.commitFilesListContext(),
|
gui.commitFilesListContext(),
|
||||||
}
|
}
|
||||||
|
113
pkg/gui/sub_commits_panel.go
Normal file
113
pkg/gui/sub_commits_panel.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package gui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/gocui"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||||
|
)
|
||||||
|
|
||||||
|
// list panel functions
|
||||||
|
|
||||||
|
func (gui *Gui) getSelectedSubCommit() *commands.Commit {
|
||||||
|
selectedLine := gui.State.Panels.SubCommits.SelectedLineIdx
|
||||||
|
commits := gui.State.SubCommits
|
||||||
|
if selectedLine == -1 || len(commits) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return commits[selectedLine]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) handleSubCommitSelect() error {
|
||||||
|
commit := gui.getSelectedSubCommit()
|
||||||
|
var task updateTask
|
||||||
|
if commit == nil {
|
||||||
|
task = gui.createRenderStringTask("No commits")
|
||||||
|
} else {
|
||||||
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
|
gui.GitCommand.ShowCmdStr(commit.Sha, gui.State.FilterPath),
|
||||||
|
)
|
||||||
|
|
||||||
|
task = gui.createRunPtyTask(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gui.refreshMain(refreshMainOpts{
|
||||||
|
main: &viewUpdateOpts{
|
||||||
|
title: "Commit",
|
||||||
|
task: task,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) handleCheckoutSubCommit(g *gocui.Gui, v *gocui.View) error {
|
||||||
|
commit := gui.getSelectedSubCommit()
|
||||||
|
if commit == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := gui.ask(askOpts{
|
||||||
|
returnToView: gui.getCommitsView(),
|
||||||
|
returnFocusOnClose: true,
|
||||||
|
title: gui.Tr.SLocalize("checkoutCommit"),
|
||||||
|
prompt: gui.Tr.SLocalize("SureCheckoutThisCommit"),
|
||||||
|
handleConfirm: func() error {
|
||||||
|
return gui.handleCheckoutRef(commit.Sha, handleCheckoutRefOptions{})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.State.Panels.SubCommits.SelectedLineIdx = 0
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) handleCreateSubCommitResetMenu() error {
|
||||||
|
commit := gui.getSelectedSubCommit()
|
||||||
|
|
||||||
|
return gui.createResetMenu(commit.Sha)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) handleViewSubCommitFiles() error {
|
||||||
|
commit := gui.getSelectedSubCommit()
|
||||||
|
if commit == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return gui.switchToCommitFilesContext(commit.Sha, REF_TYPE_OTHER_COMMIT, gui.Contexts.SubCommits.Context, "branches")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) switchToSubCommitsContext(refName string) error {
|
||||||
|
// need to populate my sub commits
|
||||||
|
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr, gui.State.CherryPickedCommits)
|
||||||
|
|
||||||
|
commits, err := builder.GetCommits(
|
||||||
|
commands.GetCommitsOptions{
|
||||||
|
Limit: gui.State.Panels.Commits.LimitCommits,
|
||||||
|
FilterPath: gui.State.FilterPath,
|
||||||
|
IncludeRebaseCommits: false,
|
||||||
|
RefName: refName,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.State.SubCommits = commits
|
||||||
|
gui.State.Panels.SubCommits.refName = refName
|
||||||
|
gui.State.Panels.SubCommits.SelectedLineIdx = 0
|
||||||
|
gui.Contexts.SubCommits.Context.SetParentContext(gui.currentSideContext())
|
||||||
|
|
||||||
|
return gui.switchContext(gui.Contexts.SubCommits.Context)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) handleSwitchToSubCommits() error {
|
||||||
|
currentContext := gui.currentSideContext()
|
||||||
|
if currentContext == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.Log.Warn(currentContext.GetKey())
|
||||||
|
|
||||||
|
return gui.switchToSubCommitsContext(currentContext.GetSelectedItemId())
|
||||||
|
}
|
@ -1173,6 +1173,9 @@ func addEnglish(i18nObject *i18n.Bundle) error {
|
|||||||
}, &i18n.Message{
|
}, &i18n.Message{
|
||||||
ID: "buildingPatch",
|
ID: "buildingPatch",
|
||||||
Other: "building patch",
|
Other: "building patch",
|
||||||
|
}, &i18n.Message{
|
||||||
|
ID: "viewCommits",
|
||||||
|
Other: "view commits",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user