From 198d237679bcc19655138f76a11770c3ef91ec4f Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Fri, 27 Mar 2020 19:12:15 +1100 Subject: more centralised handling of refreshing --- pkg/commands/branch_list_builder.go | 9 +-- pkg/commands/commit.go | 16 ++--- pkg/commands/commit_list_builder.go | 19 +++--- pkg/commands/git.go | 18 +++--- pkg/gui/branches_panel.go | 20 +++--- pkg/gui/commit_files_panel.go | 2 +- pkg/gui/commit_message_panel.go | 2 +- pkg/gui/commits_panel.go | 13 ++-- pkg/gui/credentials_panel.go | 2 +- pkg/gui/files_panel.go | 10 +-- pkg/gui/gui.go | 5 +- pkg/gui/merge_panel.go | 2 +- pkg/gui/patch_options_panel.go | 4 +- pkg/gui/presentation/commits.go | 3 +- pkg/gui/presentation/reflog_commits.go | 6 +- pkg/gui/rebase_options_panel.go | 8 +-- pkg/gui/remote_branches_panel.go | 2 +- pkg/gui/reset_menu_panel.go | 5 +- pkg/gui/status_panel.go | 31 ++++------ pkg/gui/undoing.go | 13 ++-- pkg/gui/view_helpers.go | 107 ++++++++++++++++++++++++++++----- pkg/utils/date.go | 8 ++- 22 files changed, 179 insertions(+), 126 deletions(-) (limited to 'pkg') diff --git a/pkg/commands/branch_list_builder.go b/pkg/commands/branch_list_builder.go index f7949d2bc..1430bbf92 100644 --- a/pkg/commands/branch_list_builder.go +++ b/pkg/commands/branch_list_builder.go @@ -2,7 +2,6 @@ package commands import ( "regexp" - "strconv" "strings" "github.com/jesseduffield/lazygit/pkg/utils" @@ -145,13 +144,7 @@ func (b *BranchListBuilder) obtainReflogBranches() []*Branch { reflogBranches := make([]*Branch, 0, len(b.ReflogCommits)) for _, commit := range b.ReflogCommits { if match := re.FindStringSubmatch(commit.Name); len(match) == 3 { - timestamp, err := strconv.Atoi(commit.Date) - if err != nil { - b.Log.Errorf("couldn't parse reflog date: %s", commit.Date) - continue - } - - recency := utils.UnixToTimeAgo(timestamp) + recency := utils.UnixToTimeAgo(commit.UnixTimestamp) for _, branchName := range match[1:] { if !foundBranchesMap[branchName] { foundBranchesMap[branchName] = true diff --git a/pkg/commands/commit.go b/pkg/commands/commit.go index a400da928..ea4192b33 100644 --- a/pkg/commands/commit.go +++ b/pkg/commands/commit.go @@ -2,14 +2,14 @@ package commands // Commit : A git commit type Commit struct { - Sha string - Name string - Status string // one of "unpushed", "pushed", "merged", "rebasing" or "selected" - Action string // one of "", "pick", "edit", "squash", "reword", "drop", "fixup" - Tags []string - ExtraInfo string // something like 'HEAD -> master, tag: v0.15.2' - Author string - Date string + Sha string + Name string + Status string // one of "unpushed", "pushed", "merged", "rebasing" or "selected" + Action string // one of "", "pick", "edit", "squash", "reword", "drop", "fixup" + Tags []string + ExtraInfo string // something like 'HEAD -> master, tag: v0.15.2' + Author string + UnixTimestamp int64 } func (c *Commit) ShortSha() string { diff --git a/pkg/commands/commit_list_builder.go b/pkg/commands/commit_list_builder.go index a39ab7593..b48c305c4 100644 --- a/pkg/commands/commit_list_builder.go +++ b/pkg/commands/commit_list_builder.go @@ -7,6 +7,7 @@ import ( "os/exec" "path/filepath" "regexp" + "strconv" "strings" "github.com/fatih/color" @@ -56,7 +57,7 @@ func (c *CommitListBuilder) extractCommitFromLine(line string) *Commit { split := strings.Split(line, SEPARATION_CHAR) sha := split[0] - date := split[1] + unixTimestamp := split[1] author := split[2] extraInfo := strings.TrimSpace(split[3]) message := strings.Join(split[4:], SEPARATION_CHAR) @@ -70,13 +71,15 @@ func (c *CommitListBuilder) extractCommitFromLine(line string) *Commit { } } + unitTimestampInt, _ := strconv.Atoi(unixTimestamp) + return &Commit{ - Sha: sha, - Name: message, - Tags: tags, - ExtraInfo: extraInfo, - Date: date, - Author: author, + Sha: sha, + Name: message, + Tags: tags, + ExtraInfo: extraInfo, + UnixTimestamp: int64(unitTimestampInt), + Author: author, } } @@ -305,5 +308,5 @@ func (c *CommitListBuilder) getLogCmd(limit bool) *exec.Cmd { limitFlag = "-300" } - return c.OSCommand.ExecutableFromString(fmt.Sprintf("git log --oneline --pretty=format:\"%%H%s%%ar%s%%aN%s%%d%s%%s\" %s --abbrev=%d", SEPARATION_CHAR, SEPARATION_CHAR, SEPARATION_CHAR, SEPARATION_CHAR, limitFlag, 20)) + 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 ", SEPARATION_CHAR, SEPARATION_CHAR, SEPARATION_CHAR, SEPARATION_CHAR, limitFlag, 20)) } diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 42b075915..803cfe2d4 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -484,11 +484,7 @@ func (c *GitCommand) GitStatus() (string, error) { // IsInMergeState states whether we are still mid-merge func (c *GitCommand) IsInMergeState() (bool, error) { - output, err := c.OSCommand.RunCommandWithOutput("git status --untracked-files=all") - if err != nil { - return false, err - } - return strings.Contains(output, "conclude merge") || strings.Contains(output, "unmerged paths"), nil + return c.OSCommand.FileExists(fmt.Sprintf("%s/MERGE_HEAD", c.DotGitDir)) } // RebaseMode returns "" for non-rebase mode, "normal" for normal rebase @@ -1133,14 +1129,16 @@ func (c *GitCommand) GetNewReflogCommits(lastReflogCommit *Commit) ([]*Commit, e return false, nil } + unixTimestamp, _ := strconv.Atoi(match[2]) + commit := &Commit{ - Sha: match[1], - Name: match[3], - Date: match[2], - Status: "reflog", + Sha: match[1], + Name: match[3], + UnixTimestamp: int64(unixTimestamp), + Status: "reflog", } - if lastReflogCommit != nil && commit.Sha == lastReflogCommit.Sha && commit.Date == lastReflogCommit.Date { + if lastReflogCommit != nil && commit.Sha == lastReflogCommit.Sha && commit.UnixTimestamp == lastReflogCommit.UnixTimestamp { // after this point we already have these reflogs loaded so we'll simply return the new ones return true, nil } diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index 268247630..6efb52264 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -127,7 +127,7 @@ func (gui *Gui) handleForceCheckout(g *gocui.Gui, v *gocui.View) error { if err := gui.GitCommand.Checkout(branch.Name, commands.CheckoutOptions{Force: true}); err != nil { _ = gui.createErrorPanel(g, err.Error()) } - return gui.refreshSidePanels(g) + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) }, nil) } @@ -167,14 +167,13 @@ func (gui *Gui) handleCheckoutRef(ref string, options handleCheckoutRefOptions) } onSuccess() - if err := gui.GitCommand.StashDo(0, "pop"); err != nil { - if err := gui.refreshSidePanels(g); err != nil { + if err := gui.refreshSidePanels(refreshOptions{mode: BLOCK_UI}); err != nil { return err } return gui.createErrorPanel(g, err.Error()) } - return gui.refreshSidePanels(g) + return gui.refreshSidePanels(refreshOptions{mode: BLOCK_UI}) }, nil) } @@ -182,10 +181,9 @@ func (gui *Gui) handleCheckoutRef(ref string, options handleCheckoutRefOptions) return err } } - onSuccess() - return gui.refreshSidePanels(gui.g) + return gui.refreshSidePanels(refreshOptions{mode: BLOCK_UI}) }) } @@ -218,10 +216,8 @@ func (gui *Gui) handleNewBranch(g *gocui.Gui, v *gocui.View) error { if err := gui.GitCommand.NewBranch(gui.trimmedContent(v), branch.Name); err != nil { return gui.createErrorPanel(g, err.Error()) } - if err := gui.refreshSidePanels(g); err != nil { - return gui.createErrorPanel(g, err.Error()) - } - return gui.handleBranchSelect(g, v) + gui.State.Panels.Branches.SelectedLine = 0 + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) }) } @@ -263,7 +259,7 @@ func (gui *Gui) deleteNamedBranch(g *gocui.Gui, v *gocui.View, selectedBranch *c } return gui.createErrorPanel(g, errMessage) } - return gui.refreshSidePanels(g) + return gui.refreshSidePanels(refreshOptions{mode: ASYNC, scope: []int{BRANCHES}}) }, nil) } @@ -357,7 +353,7 @@ func (gui *Gui) handleFastForward(g *gocui.Gui, v *gocui.View) error { if err := gui.GitCommand.PullWithoutPasswordCheck("--ff-only"); err != nil { _ = gui.createErrorPanel(gui.g, err.Error()) } - _ = gui.refreshSidePanels(gui.g) + _ = gui.refreshSidePanels(refreshOptions{mode: ASYNC}) } else { if err := gui.GitCommand.FastForward(branch.Name, remoteName, remoteBranchName); err != nil { _ = gui.createErrorPanel(gui.g, err.Error()) diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go index cafc4f95b..4d4cdcbbb 100644 --- a/pkg/gui/commit_files_panel.go +++ b/pkg/gui/commit_files_panel.go @@ -85,7 +85,7 @@ func (gui *Gui) handleDiscardOldFileChange(g *gocui.Gui, v *gocui.View) error { } } - return gui.refreshSidePanels(gui.g) + return gui.refreshSidePanels(refreshOptions{mode: BLOCK_UI}) }) }, nil) } diff --git a/pkg/gui/commit_message_panel.go b/pkg/gui/commit_message_panel.go index ea65dc9cf..8c11e5a83 100644 --- a/pkg/gui/commit_message_panel.go +++ b/pkg/gui/commit_message_panel.go @@ -48,7 +48,7 @@ func (gui *Gui) handleCommitConfirm(g *gocui.Gui, v *gocui.View) error { _ = v.SetOrigin(0, 0) _, _ = g.SetViewOnBottom("commitMessage") _ = gui.switchFocus(g, v, gui.getFilesView()) - return gui.refreshSidePanels(g) + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) } func (gui *Gui) handleCommitClose(g *gocui.Gui, v *gocui.View) error { diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index e0b904f5b..c2757ab93 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -72,10 +72,6 @@ func (gui *Gui) handleCommitSelect(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) refreshCommits(g *gocui.Gui) error { - if err := gui.updateWorkTreeState(); err != nil { - return gui.createErrorPanel(gui.g, err.Error()) - } - wg := sync.WaitGroup{} wg.Add(2) @@ -87,6 +83,9 @@ func (gui *Gui) refreshCommits(g *gocui.Gui) error { go func() { gui.refreshCommitsWithLimit() + if g.CurrentView() == gui.getCommitFilesView() || (g.CurrentView() == gui.getMainView() || gui.State.MainContext == "patch-building") { + gui.refreshCommitFilesView() + } wg.Done() }() @@ -94,10 +93,6 @@ func (gui *Gui) refreshCommits(g *gocui.Gui) error { gui.refreshStatus() - if g.CurrentView() == gui.getCommitFilesView() || (g.CurrentView() == gui.getMainView() || gui.State.MainContext == "patch-building") { - return gui.refreshCommitFilesView() - } - return nil } @@ -497,7 +492,7 @@ func (gui *Gui) handleCreateFixupCommit(g *gocui.Gui, v *gocui.View) error { return gui.createErrorPanel(g, err.Error()) } - return gui.refreshSidePanels(gui.g) + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) }, nil) } diff --git a/pkg/gui/credentials_panel.go b/pkg/gui/credentials_panel.go index aa2caecfa..7be93cc94 100644 --- a/pkg/gui/credentials_panel.go +++ b/pkg/gui/credentials_panel.go @@ -100,6 +100,6 @@ func (gui *Gui) HandleCredentialsPopup(g *gocui.Gui, popupOpened bool, cmdErr er _ = gui.createSpecificErrorPanel(errMessage, gui.getFilesView(), false) } else { _ = gui.closeConfirmationPrompt(g, true) - _ = gui.refreshSidePanels(g) + _ = gui.refreshSidePanels(refreshOptions{mode: ASYNC}) } } diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index bcfeccaa1..bee4cc6f8 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -278,7 +278,7 @@ func (gui *Gui) handleWIPCommitPress(g *gocui.Gui, filesView *gocui.View) error } func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error { - if len(gui.stagedFiles()) == 0 && gui.State.WorkingTreeState == "normal" { + if len(gui.stagedFiles()) == 0 && gui.workingTreeState() == "normal" { return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit")) } commitMessageView := gui.getCommitMessageView() @@ -298,7 +298,7 @@ func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error { } func (gui *Gui) handleAmendCommitPress(g *gocui.Gui, filesView *gocui.View) error { - if len(gui.stagedFiles()) == 0 && gui.State.WorkingTreeState == "normal" { + if len(gui.stagedFiles()) == 0 && gui.workingTreeState() == "normal" { return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit")) } if len(gui.State.Commits) == 0 { @@ -317,14 +317,14 @@ func (gui *Gui) handleAmendCommitPress(g *gocui.Gui, filesView *gocui.View) erro return nil } - return gui.refreshSidePanels(g) + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) }, nil) } // handleCommitEditorPress - handle when the user wants to commit changes via // their editor rather than via the popup panel func (gui *Gui) handleCommitEditorPress(g *gocui.Gui, filesView *gocui.View) error { - if len(gui.stagedFiles()) == 0 && gui.State.WorkingTreeState == "normal" { + if len(gui.stagedFiles()) == 0 && gui.workingTreeState() == "normal" { return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit")) } gui.PrepareSubProcess(g, "git", "commit") @@ -375,7 +375,7 @@ func (gui *Gui) refreshStateFiles() error { } gui.refreshSelectedLine(&gui.State.Panels.Files.SelectedLine, len(gui.State.Files)) - return gui.updateWorkTreeState() + return nil } func (gui *Gui) catSelectedFile(g *gocui.Gui) (string, error) { diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index b4805b7f3..1c3c733c0 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -194,7 +194,6 @@ type guiState struct { Platform commands.Platform Updating bool Panels *panelStates - WorkingTreeState string // one of "merging", "rebasing", "normal" MainContext string // used to keep the main and secondary views' contexts in sync CherryPickedCommits []*commands.Commit SplitMainPanel bool @@ -351,7 +350,7 @@ func (gui *Gui) scrollDownConfirmationPanel(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleRefresh(g *gocui.Gui, v *gocui.View) error { - return gui.refreshSidePanels(g) + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) } func max(a, b int) int { @@ -863,7 +862,7 @@ func (gui *Gui) loadNewRepo() error { } gui.waitForIntro.Done() - if err := gui.refreshSidePanels(gui.g); err != nil { + if err := gui.refreshSidePanels(refreshOptions{mode: ASYNC}); err != nil { return err } diff --git a/pkg/gui/merge_panel.go b/pkg/gui/merge_panel.go index fa0928f22..e94d5541c 100644 --- a/pkg/gui/merge_panel.go +++ b/pkg/gui/merge_panel.go @@ -281,7 +281,7 @@ func (gui *Gui) handleCompleteMerge() error { } // if we got conflicts after unstashing, we don't want to call any git // commands to continue rebasing/merging here - if gui.State.WorkingTreeState == "normal" { + if gui.workingTreeState() == "normal" { return gui.handleEscapeMerge(gui.g, gui.getMainView()) } // if there are no more files with merge conflicts, we should ask whether the user wants to continue diff --git a/pkg/gui/patch_options_panel.go b/pkg/gui/patch_options_panel.go index 3d24c2b11..c47374889 100644 --- a/pkg/gui/patch_options_panel.go +++ b/pkg/gui/patch_options_panel.go @@ -59,7 +59,7 @@ func (gui *Gui) getPatchCommitIndex() int { } func (gui *Gui) validateNormalWorkingTreeState() (bool, error) { - if gui.State.WorkingTreeState != "normal" { + if gui.workingTreeState() != "normal" { return false, gui.createErrorPanel(gui.g, gui.Tr.SLocalize("CantPatchWhileRebasingError")) } return true, nil @@ -128,7 +128,7 @@ func (gui *Gui) handleApplyPatch() error { if err := gui.GitCommand.PatchManager.ApplyPatches(false); err != nil { return gui.createErrorPanel(gui.g, err.Error()) } - return gui.refreshSidePanels(gui.g) + return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) } func (gui *Gui) handleResetPatch() error { diff --git a/pkg/gui/presentation/commits.go b/pkg/gui/presentation/commits.go index dedf4a01b..b54f928ac 100644 --- a/pkg/gui/presentation/commits.go +++ b/pkg/gui/presentation/commits.go @@ -63,8 +63,7 @@ func getFullDescriptionDisplayStringsForCommit(c *commands.Commit, cherryPickedC } tagString := "" - truncatedDate := utils.TruncateWithEllipsis(c.Date, 15) - secondColumnString := blue.Sprint(truncatedDate) + secondColumnString := blue.Sprint(utils.UnixToDate(c.UnixTimestamp)) if c.Action != "" { secondColumnString = cyan.Sprint(c.Action) } else if c.ExtraInfo != "" { diff --git a/pkg/gui/presentation/reflog_commits.go b/pkg/gui/presentation/reflog_commits.go index a3e39a70d..e57560b76 100644 --- a/pkg/gui/presentation/reflog_commits.go +++ b/pkg/gui/presentation/reflog_commits.go @@ -27,7 +27,11 @@ func GetReflogCommitListDisplayStrings(commits []*commands.Commit, fullDescripti func getFullDescriptionDisplayStringsForReflogCommit(c *commands.Commit) []string { defaultColor := color.New(theme.DefaultTextColor) - return []string{utils.ColoredString(c.ShortSha(), color.FgBlue), utils.ColoredString(c.Date, color.FgMagenta), defaultColor.Sprint(c.Name)} + return []string{ + utils.ColoredString(c.ShortSha(), color.FgBlue), + utils.ColoredString(utils.UnixToDate(c.UnixTimestamp), color.FgMagenta), + defaultColor.Sprint(c.Name), + } } func getDisplayStringsForReflogCommit(c *commands.Commit) []string { diff --git a/pkg/gui/rebase_options_panel.go b/pkg/gui/rebase_options_panel.go index a4ba8e35a..05bc44bb3 100644 --- a/pkg/gui/rebase_options_panel.go +++ b/pkg/gui/rebase_options_panel.go @@ -10,7 +10,7 @@ import ( func (gui *Gui) handleCreateRebaseOptionsMenu(g *gocui.Gui, v *gocui.View) error { options := []string{"continue", "abort"} - if gui.State.WorkingTreeState == "rebasing" { + if gui.workingTreeState() == "rebasing" { options = append(options, "skip") } @@ -27,7 +27,7 @@ func (gui *Gui) handleCreateRebaseOptionsMenu(g *gocui.Gui, v *gocui.View) error } var title string - if gui.State.WorkingTreeState == "merging" { + if gui.workingTreeState() == "merging" { title = gui.Tr.SLocalize("MergeOptionsTitle") } else { title = gui.Tr.SLocalize("RebaseOptionsTitle") @@ -37,7 +37,7 @@ func (gui *Gui) handleCreateRebaseOptionsMenu(g *gocui.Gui, v *gocui.View) error } func (gui *Gui) genericMergeCommand(command string) error { - status := gui.State.WorkingTreeState + status := gui.workingTreeState() if status != "merging" && status != "rebasing" { return gui.createErrorPanel(gui.g, gui.Tr.SLocalize("NotMergingOrRebasing")) @@ -63,7 +63,7 @@ func (gui *Gui) genericMergeCommand(command string) error { } func (gui *Gui) handleGenericMergeCommandResult(result error) error { - if err := gui.refreshSidePanels(gui.g); err != nil { + if err := gui.refreshSidePanels(refreshOptions{mode: ASYNC}); err != nil { return err } if result == nil { diff --git a/pkg/gui/remote_branches_panel.go b/pkg/gui/remote_branches_panel.go index ffc353de4..69628e6f9 100644 --- a/pkg/gui/remote_branches_panel.go +++ b/pkg/gui/remote_branches_panel.go @@ -126,7 +126,7 @@ func (gui *Gui) handleSetBranchUpstream(g *gocui.Gui, v *gocui.View) error { return err } - return gui.refreshSidePanels(gui.g) + return gui.refreshSidePanels(refreshOptions{scope: []int{BRANCHES, REMOTES}}) }, nil) } diff --git a/pkg/gui/reset_menu_panel.go b/pkg/gui/reset_menu_panel.go index dab7ee9dd..1c3dce5bf 100644 --- a/pkg/gui/reset_menu_panel.go +++ b/pkg/gui/reset_menu_panel.go @@ -21,10 +21,7 @@ func (gui *Gui) resetToRef(ref string, strength string, options commands.RunComm // loading a heap of commits is slow so we limit them whenever doing a reset gui.State.Panels.Commits.LimitCommits = true - if err := gui.refreshCommits(gui.g); err != nil { - return err - } - if err := gui.refreshFiles(); err != nil { + if err := gui.refreshSidePanels(refreshOptions{scope: []int{FILES, BRANCHES, REFLOG, COMMITS}}); err != nil { return err } if err := gui.resetOrigin(gui.getCommitsView()); err != nil { diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index c6ebff794..6a952b580 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -12,6 +12,7 @@ import ( // never call this on its own, it should only be called from within refreshCommits() func (gui *Gui) refreshStatus() { + currentBranch := gui.currentBranch() status := "" @@ -26,8 +27,8 @@ func (gui *Gui) refreshStatus() { status = utils.ColoredString(fmt.Sprintf("ā†‘%sā†“%s ", currentBranch.Pushables, currentBranch.Pullables), trackColor) } - if gui.State.WorkingTreeState != "normal" { - status += utils.ColoredString(fmt.Sprintf("(%s) ", gui.State.WorkingTreeState), color.FgYellow) + if gui.workingTreeState() != "normal" { + status += utils.ColoredString(fmt.Sprintf("(%s) ", gui.workingTreeState()), color.FgYellow) } name := utils.ColoredString(currentBranch.Name, presentation.GetBranchColor(currentBranch.Name)) @@ -59,10 +60,9 @@ func (gui *Gui) handleStatusClick(g *gocui.Gui, v *gocui.View) error { cx, _ := v.Cursor() upstreamStatus := fmt.Sprintf("ā†‘%sā†“%s", currentBranch.Pushables, currentBranch.Pullables) repoName := utils.GetCurrentRepoName() - gui.Log.Warn(gui.State.WorkingTreeState) - switch gui.State.WorkingTreeState { + switch gui.workingTreeState() { case "rebasing", "merging": - workingTreeStatus := fmt.Sprintf("(%s)", gui.State.WorkingTreeState) + workingTreeStatus := fmt.Sprintf("(%s)", gui.workingTreeState()) if cursorInSubstring(cx, upstreamStatus+" ", workingTreeStatus) { return gui.handleCreateRebaseOptionsMenu(gui.g, v) } @@ -128,23 +128,14 @@ func lazygitTitle() string { |___/ |___/ ` } -func (gui *Gui) updateWorkTreeState() error { - rebaseMode, err := gui.GitCommand.RebaseMode() - if err != nil { - return err - } +func (gui *Gui) workingTreeState() string { + rebaseMode, _ := gui.GitCommand.RebaseMode() if rebaseMode != "" { - gui.State.WorkingTreeState = "rebasing" - return nil - } - merging, err := gui.GitCommand.IsInMergeState() - if err != nil { - return err + return "rebasing" } + merging, _ := gui.GitCommand.IsInMergeState() if merging { - gui.State.WorkingTreeState = "merging" - return nil + return "merging" } - gui.State.WorkingTreeState = "normal" - return nil + return "normal" } diff --git a/pkg/gui/undoing.go b/pkg/gui/undoing.go index 0fba4b86b..4bdff1421 100644 --- a/pkg/gui/undoing.go +++ b/pkg/gui/undoing.go @@ -87,7 +87,7 @@ func (gui *Gui) reflogUndo(g *gocui.Gui, v *gocui.View) error { undoEnvVars := []string{"GIT_REFLOG_ACTION=[lazygit undo]"} undoingStatus := gui.Tr.SLocalize("UndoingStatus") - if gui.State.WorkingTreeState == "rebasing" { + if gui.workingTreeState() == "rebasing" { return gui.createErrorPanel(gui.g, gui.Tr.SLocalize("cantUndoWhileRebasing")) } @@ -118,7 +118,7 @@ func (gui *Gui) reflogRedo(g *gocui.Gui, v *gocui.View) error { redoEnvVars := []string{"GIT_REFLOG_ACTION=[lazygit redo]"} redoingStatus := gui.Tr.SLocalize("RedoingStatus") - if gui.State.WorkingTreeState == "rebasing" { + if gui.workingTreeState() == "rebasing" { return gui.createErrorPanel(gui.g, gui.Tr.SLocalize("cantRedoWhileRebasing")) } @@ -183,20 +183,17 @@ func (gui *Gui) handleHardResetWithAutoStash(commitSha string, options handleHar } if err := gui.GitCommand.StashDo(0, "pop"); err != nil { - if err := gui.refreshSidePanels(g); err != nil { + if err := gui.refreshSidePanels(refreshOptions{}); err != nil { return err } return gui.createErrorPanel(g, err.Error()) } - return gui.refreshSidePanels(g) + return nil }) }, nil) } return gui.WithWaitingStatus(options.WaitingStatus, func() error { - if err := reset(); err != nil { - return err - } - return gui.refreshSidePanels(gui.g) + return reset() }) } diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 831facb84..f4227ba67 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -14,27 +14,104 @@ import ( var cyclableViews = []string{"status", "files", "branches", "commits", "stash"} -func (gui *Gui) refreshSidePanels(g *gocui.Gui) error { +const ( + COMMITS = iota + BRANCHES + FILES + STASH + REFLOG + TAGS + REMOTES +) + +const ( + SYNC = iota // wait until everything is done before returning + ASYNC // return immediately, allowing each independent thing to update itself + BLOCK_UI // wrap code in an update call to ensure UI updates all at once and keybindings aren't executed till complete +) + +type refreshOptions struct { + then func() + scope []int + mode int +} + +type innerRefreshOptions struct { + scopeMap map[int]bool + mode int +} + +func intArrToMap(arr []int) map[int]bool { + output := map[int]bool{} + for _, el := range arr { + output[el] = true + } + return output +} + +func (gui *Gui) refreshSidePanels(options refreshOptions) error { wg := sync.WaitGroup{} - wg.Add(3) + f := func() { + var scopeMap map[int]bool + if len(options.scope) == 0 { + scopeMap = intArrToMap([]int{COMMITS, BRANCHES, FILES, STASH, REFLOG, TAGS, REMOTES}) + } else { + scopeMap = intArrToMap(options.scope) + } - func() { - gui.refreshCommits(g) - wg.Done() - }() + if scopeMap[COMMITS] || scopeMap[BRANCHES] || scopeMap[REFLOG] || scopeMap[TAGS] || scopeMap[REMOTES] { + wg.Add(1) + func() { + if options.mode == ASYNC { + go gui.refreshCommits(gui.g) + } else { + gui.refreshCommits(gui.g) + } + wg.Done() + }() + } + + if scopeMap[FILES] { + wg.Add(1) + func() { + if options.mode == ASYNC { + go gui.refreshFiles() + } else { + gui.refreshFiles() + } + wg.Done() + }() + + } - func() { - gui.refreshFiles() - wg.Done() - }() + if scopeMap[STASH] { + wg.Add(1) + func() { + if options.mode == ASYNC { + go gui.refreshStashEntries(gui.g) + } else { + gui.refreshStashEntries(gui.g) + } + wg.Done() + }() + } - func() { - gui.refreshStashEntries(g) - wg.Done() - }() + wg.Wait() - wg.Wait() + if options.then != nil { + options.then() + } + } + + if options.mode == BLOCK_UI { + gui.g.Update(func(g *gocui.Gui) error { + f() + return nil + }) + } else { + f() + } return nil } diff --git a/pkg/utils/date.go b/pkg/utils/date.go index 7f8f8f8a5..40165ecaa 100644 --- a/pkg/utils/date.go +++ b/pkg/utils/date.go @@ -5,9 +5,9 @@ import ( "time" ) -func UnixToTimeAgo(timestamp int) string { +func UnixToTimeAgo(timestamp int64) string { now := time.Now().Unix() - delta := float64(now - int64(timestamp)) + delta := float64(now - timestamp) // we go seconds, minutes, hours, days, weeks, months, years conversions := []float64{60, 60, 24, 7, 4.34524, 12} labels := []string{"s", "m", "h", "d", "w", "m", "y"} @@ -19,3 +19,7 @@ func UnixToTimeAgo(timestamp int) string { } return fmt.Sprintf("%dy", int(delta)) } + +func UnixToDate(timestamp int64) string { + return time.Unix(timestamp, 0).Format(time.RFC822) +} -- cgit v1.2.3