From 9fdf92b226032d39503dbf40ef931d5d017b4235 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 5 Jun 2021 15:56:50 +1000 Subject: [PATCH] more refactoring WIP WIP --- pkg/commands/models/branch.go | 23 +++++++++++++++++ pkg/gui/branches_panel.go | 15 +++++------ pkg/gui/files_panel.go | 44 +++++++++++++++++++++++--------- pkg/gui/presentation/branches.go | 24 ++++++++++++----- pkg/gui/status_panel.go | 13 +++------- 5 files changed, 81 insertions(+), 38 deletions(-) diff --git a/pkg/commands/models/branch.go b/pkg/commands/models/branch.go index c95e335f9..3b8268bff 100644 --- a/pkg/commands/models/branch.go +++ b/pkg/commands/models/branch.go @@ -24,3 +24,26 @@ func (b *Branch) ID() string { func (b *Branch) Description() string { return b.RefName() } + +// this method does not consider the case where the git config states that a branch is tracking the config. +// The Pullables value here is based on whether or not we saw an upstream when doing `git branch` +func (b *Branch) IsTrackingRemote() bool { + return b.IsRealBranch() && b.Pullables != "?" +} + +func (b *Branch) MatchesUpstream() bool { + return b.IsRealBranch() && b.Pushables == "0" && b.Pullables == "0" +} + +func (b *Branch) HasCommitsToPush() bool { + return b.IsRealBranch() && b.Pushables != "0" +} + +func (b *Branch) HasCommitsToPull() bool { + return b.IsRealBranch() && b.Pullables != "0" +} + +// for when we're in a detached head state +func (b *Branch) IsRealBranch() bool { + return b.Pushables != "" && b.Pullables != "" +} diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index 3ffa1c24a..863622f94 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -379,16 +379,14 @@ func (gui *Gui) handleRebaseOntoBranch(selectedBranchName string) error { func (gui *Gui) handleFastForward() error { branch := gui.getSelectedBranch() - if branch == nil { + if branch == nil || !branch.IsRealBranch() { return nil } - if branch.Pushables == "" { - return nil - } - if branch.Pushables == "?" { + + if !branch.IsTrackingRemote() { return gui.createErrorPanel(gui.Tr.FwdNoUpstream) } - if branch.Pushables != "0" { + if branch.HasCommitsToPush() { return gui.createErrorPanel(gui.Tr.FwdCommitsToPush) } @@ -435,7 +433,7 @@ func (gui *Gui) handleCreateResetToBranchMenu() error { func (gui *Gui) handleRenameBranch() error { branch := gui.getSelectedBranch() - if branch == nil { + if branch == nil || !branch.IsRealBranch() { return nil } @@ -469,8 +467,7 @@ func (gui *Gui) handleRenameBranch() error { // I could do an explicit check here for whether the branch is tracking a remote branch // but if we've selected it we'll already know that via Pullables and Pullables. // Bit of a hack but I'm lazy. - notTrackingRemote := branch.Pullables == "?" - if notTrackingRemote { + if !branch.IsTrackingRemote() { return promptForNewName() } diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index f2bb6d43d..2c045504e 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -617,7 +617,7 @@ func (gui *Gui) handlePullFiles() error { } // if we have no upstream branch we need to set that first - if currentBranch.Pullables == "?" { + if !currentBranch.IsTrackingRemote() { // see if we have this branch in our config with an upstream conf, err := gui.GitCommand.Repo.Config() if err != nil { @@ -740,16 +740,21 @@ func (gui *Gui) pushFiles() error { return nil } - if currentBranch.Pullables == "?" { - // see if we have this branch in our config with an upstream - conf, err := gui.GitCommand.Repo.Config() + if currentBranch.IsTrackingRemote() { + if currentBranch.HasCommitsToPull() { + return gui.requestToForcePush() + } else { + return gui.pushWithForceFlag(false, "", "") + } + } else { + // see if we have an upstream for this branch in our config + upstream, err := gui.upstreamForBranchInConfig(currentBranch.Name) if err != nil { return gui.surfaceError(err) } - for branchName, branch := range conf.Branches { - if branchName == currentBranch.Name { - return gui.pushWithForceFlag(false, "", fmt.Sprintf("%s %s", branch.Remote, branchName)) - } + + if upstream != "" { + return gui.pushWithForceFlag(false, "", upstream) } if gui.GitCommand.PushToCurrent { @@ -758,15 +763,15 @@ func (gui *Gui) pushFiles() error { return gui.prompt(promptOpts{ title: gui.Tr.EnterUpstream, initialContent: "origin " + currentBranch.Name, - handleConfirm: func(response string) error { - return gui.pushWithForceFlag(false, response, "") + handleConfirm: func(upstream string) error { + return gui.pushWithForceFlag(false, upstream, "") }, }) } - } else if currentBranch.Pullables == "0" { - return gui.pushWithForceFlag(false, "", "") } +} +func (gui *Gui) requestToForcePush() error { forcePushDisabled := gui.Config.GetUserConfig().Git.DisableForcePushing if forcePushDisabled { return gui.createErrorPanel(gui.Tr.ForcePushDisabled) @@ -781,6 +786,21 @@ func (gui *Gui) pushFiles() error { }) } +func (gui *Gui) upstreamForBranchInConfig(branchName string) (string, error) { + conf, err := gui.GitCommand.Repo.Config() + if err != nil { + return "", err + } + + for configBranchName, configBranch := range conf.Branches { + if configBranchName == branchName { + return fmt.Sprintf("%s %s", configBranch.Remote, configBranchName), nil + } + } + + return "", nil +} + func (gui *Gui) handleSwitchToMerge() error { file := gui.getSelectedFile() if file == nil { diff --git a/pkg/gui/presentation/branches.go b/pkg/gui/presentation/branches.go index 72def1f6c..3e51e3d66 100644 --- a/pkg/gui/presentation/branches.go +++ b/pkg/gui/presentation/branches.go @@ -33,13 +33,8 @@ func getBranchDisplayStrings(b *models.Branch, fullDescription bool, diffed bool nameColorAttr = theme.DiffTerminalColor } coloredName := utils.ColoredString(displayName, nameColorAttr) - if b.Pushables != "" && b.Pullables != "" && b.Pushables != "?" && b.Pullables != "?" { - trackColor := color.FgYellow - if b.Pushables == "0" && b.Pullables == "0" { - trackColor = color.FgGreen - } - track := utils.ColoredString(fmt.Sprintf("↑%s↓%s", b.Pushables, b.Pullables), trackColor) - coloredName = fmt.Sprintf("%s %s", coloredName, track) + if b.IsTrackingRemote() { + coloredName = fmt.Sprintf("%s %s", coloredName, ColoredBranchStatus(b)) } recencyColor := color.FgCyan @@ -69,3 +64,18 @@ func GetBranchColor(name string) color.Attribute { return theme.DefaultTextColor } } + +func ColoredBranchStatus(branch *models.Branch) string { + colour := color.FgYellow + if branch.MatchesUpstream() { + colour = color.FgGreen + } else if !branch.IsTrackingRemote() { + colour = color.FgRed + } + + return utils.ColoredString(BranchStatus(branch), colour) +} + +func BranchStatus(branch *models.Branch) string { + return fmt.Sprintf("↑%s↓%s", branch.Pushables, branch.Pullables) +} diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index c682a377d..adf1651ea 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -23,15 +23,8 @@ func (gui *Gui) refreshStatus() { } status := "" - if currentBranch.Pushables != "" && currentBranch.Pullables != "" { - trackColor := color.FgYellow - if currentBranch.Pushables == "0" && currentBranch.Pullables == "0" { - trackColor = color.FgGreen - } else if currentBranch.Pushables == "?" && currentBranch.Pullables == "?" { - trackColor = color.FgRed - } - - status = utils.ColoredString(fmt.Sprintf("↑%s↓%s ", currentBranch.Pushables, currentBranch.Pullables), trackColor) + if currentBranch.IsRealBranch() { + status += presentation.ColoredBranchStatus(currentBranch) + " " } if gui.GitCommand.WorkingTreeState() != commands.REBASE_MODE_NORMAL { @@ -75,7 +68,7 @@ func (gui *Gui) handleStatusClick() error { } cx, _ := gui.Views.Status.Cursor() - upstreamStatus := fmt.Sprintf("↑%s↓%s", currentBranch.Pushables, currentBranch.Pullables) + upstreamStatus := presentation.BranchStatus(currentBranch) repoName := utils.GetCurrentRepoName() switch gui.GitCommand.WorkingTreeState() { case commands.REBASE_MODE_REBASING, commands.REBASE_MODE_MERGING: