mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-06-15 00:15:32 +02:00
more work on rebasing including visual indicators
This commit is contained in:
@ -8,23 +8,30 @@ import (
|
|||||||
type Commit struct {
|
type Commit struct {
|
||||||
Sha string
|
Sha string
|
||||||
Name string
|
Name string
|
||||||
Pushed bool
|
Status string // one of "unpushed", "pushed", "merged", or "rebasing"
|
||||||
Merged bool
|
|
||||||
DisplayString string
|
DisplayString string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDisplayStrings is a function.
|
// GetDisplayStrings is a function.
|
||||||
func (c *Commit) GetDisplayStrings() []string {
|
func (c *Commit) GetDisplayStrings() []string {
|
||||||
red := color.New(color.FgRed)
|
red := color.New(color.FgRed)
|
||||||
yellow := color.New(color.FgGreen)
|
yellow := color.New(color.FgYellow)
|
||||||
green := color.New(color.FgYellow)
|
green := color.New(color.FgGreen)
|
||||||
white := color.New(color.FgWhite)
|
white := color.New(color.FgWhite)
|
||||||
|
blue := color.New(color.FgBlue)
|
||||||
|
|
||||||
shaColor := yellow
|
var shaColor *color.Color
|
||||||
if c.Pushed {
|
switch c.Status {
|
||||||
|
case "unpushed":
|
||||||
shaColor = red
|
shaColor = red
|
||||||
} else if !c.Merged {
|
case "pushed":
|
||||||
|
shaColor = yellow
|
||||||
|
case "merged":
|
||||||
shaColor = green
|
shaColor = green
|
||||||
|
case "rebasing":
|
||||||
|
shaColor = blue
|
||||||
|
default:
|
||||||
|
shaColor = white
|
||||||
}
|
}
|
||||||
|
|
||||||
return []string{shaColor.Sprint(c.Sha), white.Sprint(c.Name)}
|
return []string{shaColor.Sprint(c.Sha), white.Sprint(c.Name)}
|
||||||
|
@ -3,10 +3,14 @@ package commands
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -149,7 +153,7 @@ func (c *GitCommand) GetStatusFiles() []*File {
|
|||||||
HasUnstagedChanges: unstagedChange != " ",
|
HasUnstagedChanges: unstagedChange != " ",
|
||||||
Tracked: !untracked,
|
Tracked: !untracked,
|
||||||
Deleted: unstagedChange == "D" || stagedChange == "D",
|
Deleted: unstagedChange == "D" || stagedChange == "D",
|
||||||
HasMergeConflicts: change == "UU",
|
HasMergeConflicts: change == "UU" || change == "AA",
|
||||||
Type: c.OSCommand.FileType(filename),
|
Type: c.OSCommand.FileType(filename),
|
||||||
}
|
}
|
||||||
files = append(files, file)
|
files = append(files, file)
|
||||||
@ -240,9 +244,9 @@ func (c *GitCommand) GetCommitDifferences(from, to string) (string, string) {
|
|||||||
return strings.TrimSpace(pushableCount), strings.TrimSpace(pullableCount)
|
return strings.TrimSpace(pushableCount), strings.TrimSpace(pullableCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommitsToPush 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 *GitCommand) GetCommitsToPush() map[string]bool {
|
func (c *GitCommand) GetUnpushedCommits() map[string]bool {
|
||||||
pushables := map[string]bool{}
|
pushables := map[string]bool{}
|
||||||
o, err := c.OSCommand.RunCommandWithOutput("git rev-list @{u}..HEAD --abbrev-commit")
|
o, err := c.OSCommand.RunCommandWithOutput("git rev-list @{u}..HEAD --abbrev-commit")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -273,6 +277,10 @@ func (c *GitCommand) ContinueRebaseBranch() error {
|
|||||||
return c.OSCommand.RunCommand("git rebase --continue")
|
return c.OSCommand.RunCommand("git rebase --continue")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *GitCommand) SkipRebaseBranch() error {
|
||||||
|
return c.OSCommand.RunCommand("git rebase --skip")
|
||||||
|
}
|
||||||
|
|
||||||
func (c *GitCommand) AbortRebaseBranch() error {
|
func (c *GitCommand) AbortRebaseBranch() error {
|
||||||
return c.OSCommand.RunCommand("git rebase --abort")
|
return c.OSCommand.RunCommand("git rebase --abort")
|
||||||
}
|
}
|
||||||
@ -455,11 +463,11 @@ func (c *GitCommand) IsInMergeState() (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *GitCommand) IsInRebaseState() (bool, error) {
|
func (c *GitCommand) IsInRebaseState() (bool, error) {
|
||||||
output, err := c.OSCommand.RunCommandWithOutput("git status --untracked-files=all")
|
exists, err := c.OSCommand.FileExists(".git/rebase-apply")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return strings.Contains(output, "rebase in progress"), nil
|
return exists, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveFile directly
|
// RemoveFile directly
|
||||||
@ -527,24 +535,105 @@ func (c *GitCommand) getMergeBase() (string, error) {
|
|||||||
return output, nil
|
return output, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRebasingCommits obtains the commits that we're in the process of rebasing
|
||||||
|
func (c *GitCommand) GetRebasingCommits() ([]*Commit, error) {
|
||||||
|
rebasing, err := c.IsInRebaseState()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !rebasing {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rewrittenCount := 0
|
||||||
|
bytesContent, err := ioutil.ReadFile(".git/rebase-apply/rewritten")
|
||||||
|
if err == nil {
|
||||||
|
content := string(bytesContent)
|
||||||
|
rewrittenCount = len(strings.Split(content, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// we know we're rebasing, so lets get all the files whose names have numbers
|
||||||
|
commits := []*Commit{}
|
||||||
|
err = filepath.Walk(".git/rebase-apply", func(path string, f os.FileInfo, err error) error {
|
||||||
|
if rewrittenCount > 0 {
|
||||||
|
rewrittenCount -= 1
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
re := regexp.MustCompile(`^\d+$`)
|
||||||
|
if !re.MatchString(f.Name()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
bytesContent, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
content := string(bytesContent)
|
||||||
|
commit, err := c.CommitFromPatch(content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
commits = append([]*Commit{commit}, commits...)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return commits, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// assuming the file starts like this:
|
||||||
|
// From e93d4193e6dd45ca9cf3a5a273d7ba6cd8b8fb20 Mon Sep 17 00:00:00 2001
|
||||||
|
// From: Lazygit Tester <test@example.com>
|
||||||
|
// Date: Wed, 5 Dec 2018 21:03:23 +1100
|
||||||
|
// Subject: second commit on master
|
||||||
|
func (c *GitCommand) CommitFromPatch(content string) (*Commit, error) {
|
||||||
|
lines := strings.Split(content, "\n")
|
||||||
|
sha := strings.Split(lines[0], " ")[1][0:7]
|
||||||
|
name := strings.TrimPrefix(lines[3], "Subject: ")
|
||||||
|
return &Commit{
|
||||||
|
Sha: sha,
|
||||||
|
Name: name,
|
||||||
|
Status: "rebasing",
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetCommits obtains the commits of the current branch
|
// GetCommits obtains the commits of the current branch
|
||||||
func (c *GitCommand) GetCommits() ([]*Commit, error) {
|
func (c *GitCommand) GetCommits() ([]*Commit, error) {
|
||||||
pushables := c.GetCommitsToPush()
|
commits := []*Commit{}
|
||||||
|
// here we want to also prepend the commits that we're in the process of rebasing
|
||||||
|
rebasingCommits, err := c.GetRebasingCommits()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(rebasingCommits) > 0 {
|
||||||
|
commits = append(commits, rebasingCommits...)
|
||||||
|
}
|
||||||
|
|
||||||
|
unpushedCommits := c.GetUnpushedCommits()
|
||||||
log := c.GetLog()
|
log := c.GetLog()
|
||||||
|
|
||||||
lines := utils.SplitLines(log)
|
|
||||||
commits := make([]*Commit, len(lines))
|
|
||||||
// now we can split it up and turn it into commits
|
// now we can split it up and turn it into commits
|
||||||
for i, line := range lines {
|
for _, line := range utils.SplitLines(log) {
|
||||||
splitLine := strings.Split(line, " ")
|
splitLine := strings.Split(line, " ")
|
||||||
sha := splitLine[0]
|
sha := splitLine[0]
|
||||||
_, pushed := pushables[sha]
|
_, unpushed := unpushedCommits[sha]
|
||||||
commits[i] = &Commit{
|
status := map[bool]string{true: "unpushed", false: "pushed"}[unpushed]
|
||||||
|
commits = append(commits, &Commit{
|
||||||
Sha: sha,
|
Sha: sha,
|
||||||
Name: strings.Join(splitLine[1:], " "),
|
Name: strings.Join(splitLine[1:], " "),
|
||||||
Pushed: pushed,
|
Status: status,
|
||||||
DisplayString: strings.Join(splitLine, " "),
|
DisplayString: strings.Join(splitLine, " "),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
if len(rebasingCommits) > 0 {
|
||||||
|
currentCommit := commits[len(rebasingCommits)]
|
||||||
|
blue := color.New(color.FgYellow)
|
||||||
|
youAreHere := blue.Sprint("<-- YOU ARE HERE ---")
|
||||||
|
currentCommit.Name = fmt.Sprintf("%s %s", youAreHere, currentCommit.Name)
|
||||||
}
|
}
|
||||||
return c.setCommitMergedStatuses(commits)
|
return c.setCommitMergedStatuses(commits)
|
||||||
}
|
}
|
||||||
@ -562,7 +651,12 @@ func (c *GitCommand) setCommitMergedStatuses(commits []*Commit) ([]*Commit, erro
|
|||||||
if strings.HasPrefix(ancestor, commit.Sha) {
|
if strings.HasPrefix(ancestor, commit.Sha) {
|
||||||
passedAncestor = true
|
passedAncestor = true
|
||||||
}
|
}
|
||||||
commits[i].Merged = passedAncestor
|
if commit.Status != "pushed" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if passedAncestor {
|
||||||
|
commits[i].Status = "merged"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return commits, nil
|
return commits, nil
|
||||||
}
|
}
|
||||||
|
@ -202,3 +202,14 @@ func (c *OSCommand) CreateTempFile(filename, content string) (string, error) {
|
|||||||
func (c *OSCommand) RemoveFile(filename string) error {
|
func (c *OSCommand) RemoveFile(filename string) error {
|
||||||
return os.Remove(filename)
|
return os.Remove(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileExists checks whether a file exists at the specified path
|
||||||
|
func (c *OSCommand) FileExists(path string) (bool, error) {
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
@ -96,7 +96,7 @@ func (gui *Gui) handleBranchesPrevLine(g *gocui.Gui, v *gocui.View) error {
|
|||||||
|
|
||||||
func (gui *Gui) handleRebase(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleRebase(g *gocui.Gui, v *gocui.View) error {
|
||||||
|
|
||||||
selectedBranch := gui.getSelectedBranch(v).Name
|
selectedBranch := gui.getSelectedBranch().Name
|
||||||
checkedOutBranch := gui.State.Branches[0].Name
|
checkedOutBranch := gui.State.Branches[0].Name
|
||||||
title := "Rebasing"
|
title := "Rebasing"
|
||||||
prompt := fmt.Sprintf("Are you sure you want to rebase %s onto %s?", checkedOutBranch, selectedBranch)
|
prompt := fmt.Sprintf("Are you sure you want to rebase %s onto %s?", checkedOutBranch, selectedBranch)
|
||||||
@ -109,11 +109,14 @@ func (gui *Gui) handleRebase(g *gocui.Gui, v *gocui.View) error {
|
|||||||
|
|
||||||
if err := gui.GitCommand.RebaseBranch(selectedBranch); err != nil {
|
if err := gui.GitCommand.RebaseBranch(selectedBranch); err != nil {
|
||||||
gui.Log.Errorln(err)
|
gui.Log.Errorln(err)
|
||||||
if err := gui.createConfirmationPanel(g, v, "Rebase failed", "Rebasing failed, would you like to resolve it?",
|
if err := gui.createConfirmationPanel(g, v, "Rebase failed", "Damn, conflicts! To abort press 'esc', otherwise press 'enter'",
|
||||||
func(g *gocui.Gui, v *gocui.View) error {
|
func(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}, func(g *gocui.Gui, v *gocui.View) error {
|
}, func(g *gocui.Gui, v *gocui.View) error {
|
||||||
return gui.GitCommand.AbortRebaseBranch()
|
if err := gui.GitCommand.AbortRebaseBranch(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return gui.refreshSidePanels(g)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
gui.Log.Errorln(err)
|
gui.Log.Errorln(err)
|
||||||
}
|
}
|
||||||
|
@ -118,11 +118,7 @@ func (gui *Gui) stageSelectedFile(g *gocui.Gui) error {
|
|||||||
return gui.GitCommand.StageFile(file.Name)
|
return gui.GitCommand.StageFile(file.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleSwitchToStagingPanel(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) handleEnterFile(g *gocui.Gui, v *gocui.View) error {
|
||||||
stagingView, err := g.View("staging")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
file, err := gui.getSelectedFile(g)
|
file, err := gui.getSelectedFile(g)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != gui.Errors.ErrNoFiles {
|
if err != gui.Errors.ErrNoFiles {
|
||||||
@ -130,10 +126,17 @@ func (gui *Gui) handleSwitchToStagingPanel(g *gocui.Gui, v *gocui.View) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if file.HasMergeConflicts {
|
||||||
|
return gui.handleSwitchToMerge(g, v)
|
||||||
|
}
|
||||||
if !file.HasUnstagedChanges {
|
if !file.HasUnstagedChanges {
|
||||||
gui.Log.WithField("staging", "staging").Info("making error panel")
|
gui.Log.WithField("staging", "staging").Info("making error panel")
|
||||||
return gui.createErrorPanel(g, gui.Tr.SLocalize("FileStagingRequirements"))
|
return gui.createErrorPanel(g, gui.Tr.SLocalize("FileStagingRequirements"))
|
||||||
}
|
}
|
||||||
|
stagingView, err := g.View("staging")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := gui.switchFocus(g, v, stagingView); err != nil {
|
if err := gui.switchFocus(g, v, stagingView); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -256,7 +259,7 @@ func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleCommitPress(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.HasMergeConflicts {
|
if len(gui.stagedFiles()) == 0 && gui.State.WorkingTreeState == "normal" {
|
||||||
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit"))
|
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit"))
|
||||||
}
|
}
|
||||||
commitMessageView := gui.getCommitMessageView(g)
|
commitMessageView := gui.getCommitMessageView(g)
|
||||||
@ -270,7 +273,7 @@ func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleAmendCommitPress(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.HasMergeConflicts {
|
if len(gui.stagedFiles()) == 0 && gui.State.WorkingTreeState == "normal" {
|
||||||
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit"))
|
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit"))
|
||||||
}
|
}
|
||||||
title := strings.Title(gui.Tr.SLocalize("AmendLastCommit"))
|
title := strings.Title(gui.Tr.SLocalize("AmendLastCommit"))
|
||||||
@ -294,7 +297,7 @@ func (gui *Gui) handleAmendCommitPress(g *gocui.Gui, filesView *gocui.View) erro
|
|||||||
// handleCommitEditorPress - handle when the user wants to commit changes via
|
// handleCommitEditorPress - handle when the user wants to commit changes via
|
||||||
// their editor rather than via the popup panel
|
// their editor rather than via the popup panel
|
||||||
func (gui *Gui) handleCommitEditorPress(g *gocui.Gui, filesView *gocui.View) error {
|
func (gui *Gui) handleCommitEditorPress(g *gocui.Gui, filesView *gocui.View) error {
|
||||||
if len(gui.stagedFiles()) == 0 && !gui.State.HasMergeConflicts {
|
if len(gui.stagedFiles()) == 0 && gui.State.WorkingTreeState == "normal" {
|
||||||
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit"))
|
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit"))
|
||||||
}
|
}
|
||||||
gui.PrepareSubProcess(g, "git", "commit")
|
gui.PrepareSubProcess(g, "git", "commit")
|
||||||
@ -347,15 +350,27 @@ func (gui *Gui) refreshStateFiles() {
|
|||||||
files := gui.GitCommand.GetStatusFiles()
|
files := gui.GitCommand.GetStatusFiles()
|
||||||
gui.State.Files = gui.GitCommand.MergeStatusFiles(gui.State.Files, files)
|
gui.State.Files = gui.GitCommand.MergeStatusFiles(gui.State.Files, files)
|
||||||
gui.refreshSelectedLine(&gui.State.Panels.Files.SelectedLine, len(gui.State.Files))
|
gui.refreshSelectedLine(&gui.State.Panels.Files.SelectedLine, len(gui.State.Files))
|
||||||
gui.updateHasMergeConflictStatus()
|
gui.updateWorkTreeState()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) updateHasMergeConflictStatus() error {
|
func (gui *Gui) updateWorkTreeState() error {
|
||||||
merging, err := gui.GitCommand.IsInMergeState()
|
merging, err := gui.GitCommand.IsInMergeState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gui.State.HasMergeConflicts = merging
|
if merging {
|
||||||
|
gui.State.WorkingTreeState = "merging"
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
rebasing, err := gui.GitCommand.IsInRebaseState()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if rebasing {
|
||||||
|
gui.State.WorkingTreeState = "rebasing"
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
gui.State.WorkingTreeState = "normal"
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +125,7 @@ type guiState struct {
|
|||||||
Platform commands.Platform
|
Platform commands.Platform
|
||||||
Updating bool
|
Updating bool
|
||||||
Panels *panelStates
|
Panels *panelStates
|
||||||
|
WorkingTreeState string // one of "merging", "rebasing", "normal"
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGui builds a new gui handler
|
// NewGui builds a new gui handler
|
||||||
|
@ -216,7 +216,7 @@ func (gui *Gui) GetKeybindings() []*Binding {
|
|||||||
ViewName: "files",
|
ViewName: "files",
|
||||||
Key: gocui.KeyEnter,
|
Key: gocui.KeyEnter,
|
||||||
Modifier: gocui.ModNone,
|
Modifier: gocui.ModNone,
|
||||||
Handler: gui.handleSwitchToStagingPanel,
|
Handler: gui.handleEnterFile,
|
||||||
Description: gui.Tr.SLocalize("StageLines"),
|
Description: gui.Tr.SLocalize("StageLines"),
|
||||||
KeyReadable: "enter",
|
KeyReadable: "enter",
|
||||||
}, {
|
}, {
|
||||||
|
@ -20,11 +20,12 @@ func (gui *Gui) findConflicts(content string) ([]commands.Conflict, error) {
|
|||||||
conflicts := make([]commands.Conflict, 0)
|
conflicts := make([]commands.Conflict, 0)
|
||||||
var newConflict commands.Conflict
|
var newConflict commands.Conflict
|
||||||
for i, line := range utils.SplitLines(content) {
|
for i, line := range utils.SplitLines(content) {
|
||||||
if line == "<<<<<<< HEAD" || line == "<<<<<<< MERGE_HEAD" || line == "<<<<<<< Updated upstream" {
|
trimmedLine := strings.TrimPrefix(line, "++")
|
||||||
|
if trimmedLine == "<<<<<<< HEAD" || trimmedLine == "<<<<<<< MERGE_HEAD" || trimmedLine == "<<<<<<< Updated upstream" {
|
||||||
newConflict = commands.Conflict{Start: i}
|
newConflict = commands.Conflict{Start: i}
|
||||||
} else if line == "=======" {
|
} else if trimmedLine == "=======" {
|
||||||
newConflict.Middle = i
|
newConflict.Middle = i
|
||||||
} else if strings.HasPrefix(line, ">>>>>>> ") {
|
} else if strings.HasPrefix(trimmedLine, ">>>>>>> ") {
|
||||||
newConflict.End = i
|
newConflict.End = i
|
||||||
conflicts = append(conflicts, newConflict)
|
conflicts = append(conflicts, newConflict)
|
||||||
}
|
}
|
||||||
@ -258,11 +259,17 @@ func (gui *Gui) handleCompleteMerge(g *gocui.Gui) error {
|
|||||||
gui.refreshFiles(g)
|
gui.refreshFiles(g)
|
||||||
if rebase, err := gui.GitCommand.IsInRebaseState(); rebase && err == nil {
|
if rebase, err := gui.GitCommand.IsInRebaseState(); rebase && err == nil {
|
||||||
if err := gui.GitCommand.ContinueRebaseBranch(); err != nil {
|
if err := gui.GitCommand.ContinueRebaseBranch(); err != nil {
|
||||||
|
if strings.Contains(err.Error(), "No changes - did you forget to use") {
|
||||||
|
if err := gui.GitCommand.SkipRebaseBranch(); err != nil {
|
||||||
gui.Log.Errorln(err)
|
gui.Log.Errorln(err)
|
||||||
}
|
}
|
||||||
if err := gui.refreshSidePanels(g); err != nil {
|
} else {
|
||||||
gui.Log.Errorln(err)
|
gui.Log.Errorln(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := gui.refreshSidePanels(g); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return gui.switchFocus(g, nil, filesView)
|
return gui.switchFocus(g, nil, filesView)
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,11 @@ func (gui *Gui) refreshStatus(g *gocui.Gui) error {
|
|||||||
pushables, pullables := gui.GitCommand.GetCurrentBranchUpstreamDifferenceCount()
|
pushables, pullables := gui.GitCommand.GetCurrentBranchUpstreamDifferenceCount()
|
||||||
fmt.Fprint(v, "↑"+pushables+"↓"+pullables)
|
fmt.Fprint(v, "↑"+pushables+"↓"+pullables)
|
||||||
branches := gui.State.Branches
|
branches := gui.State.Branches
|
||||||
if err := gui.updateHasMergeConflictStatus(); err != nil {
|
if err := gui.updateWorkTreeState(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if gui.State.HasMergeConflicts {
|
if gui.State.WorkingTreeState != "normal" {
|
||||||
fmt.Fprint(v, utils.ColoredString(" (merging)", color.FgYellow))
|
fmt.Fprint(v, utils.ColoredString(fmt.Sprintf(" (%s)", gui.State.WorkingTreeState), color.FgYellow))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(branches) == 0 {
|
if len(branches) == 0 {
|
||||||
|
@ -24,30 +24,62 @@ git add file1
|
|||||||
git add directory
|
git add directory
|
||||||
git commit -m "first commit"
|
git commit -m "first commit"
|
||||||
|
|
||||||
git checkout -b develop
|
|
||||||
|
|
||||||
|
git checkout -b develop
|
||||||
echo "once upon a time there was a dog" >> file1
|
echo "once upon a time there was a dog" >> file1
|
||||||
add_spacing file1
|
add_spacing file1
|
||||||
echo "once upon a time there was another dog" >> file1
|
echo "once upon a time there was another dog" >> file1
|
||||||
git add file1
|
git add file1
|
||||||
|
|
||||||
echo "test2" > directory/file
|
echo "test2" > directory/file
|
||||||
echo "test2" > directory/file2
|
echo "test2" > directory/file2
|
||||||
git add directory
|
git add directory
|
||||||
|
|
||||||
git commit -m "first commit on develop"
|
git commit -m "first commit on develop"
|
||||||
|
|
||||||
git checkout master
|
|
||||||
|
|
||||||
|
git checkout master
|
||||||
echo "once upon a time there was a cat" >> file1
|
echo "once upon a time there was a cat" >> file1
|
||||||
add_spacing file1
|
add_spacing file1
|
||||||
echo "once upon a time there was another cat" >> file1
|
echo "once upon a time there was another cat" >> file1
|
||||||
git add file1
|
git add file1
|
||||||
|
|
||||||
echo "test3" > directory/file
|
echo "test3" > directory/file
|
||||||
echo "test3" > directory/file2
|
echo "test3" > directory/file2
|
||||||
git add directory
|
git add directory
|
||||||
|
git commit -m "first commit on master"
|
||||||
|
|
||||||
git commit -m "first commit on develop"
|
|
||||||
|
|
||||||
git merge develop # should have a merge conflict here
|
git checkout develop
|
||||||
|
echo "once upon a time there was a mouse" >> file3
|
||||||
|
git add file3
|
||||||
|
git commit -m "second commit on develop"
|
||||||
|
|
||||||
|
|
||||||
|
git checkout master
|
||||||
|
echo "once upon a time there was a horse" >> file3
|
||||||
|
git add file3
|
||||||
|
git commit -m "second commit on master"
|
||||||
|
|
||||||
|
|
||||||
|
git checkout develop
|
||||||
|
echo "once upon a time there was a mouse" >> file4
|
||||||
|
git add file4
|
||||||
|
git commit -m "third commit on develop"
|
||||||
|
|
||||||
|
|
||||||
|
git checkout master
|
||||||
|
echo "once upon a time there was a horse" >> file4
|
||||||
|
git add file4
|
||||||
|
git commit -m "third commit on master"
|
||||||
|
|
||||||
|
|
||||||
|
git checkout develop
|
||||||
|
echo "once upon a time there was a mouse" >> file5
|
||||||
|
git add file5
|
||||||
|
git commit -m "fourth commit on develop"
|
||||||
|
|
||||||
|
|
||||||
|
git checkout master
|
||||||
|
echo "once upon a time there was a horse" >> file5
|
||||||
|
git add file5
|
||||||
|
git commit -m "fourth commit on master"
|
||||||
|
|
||||||
|
# git merge develop # should have a merge conflict here
|
||||||
|
Reference in New Issue
Block a user