From 0c886eddfb429f31352d0908fe993d415d7d3709 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Sat, 2 Mar 2019 20:00:26 +1100 Subject: [PATCH] Revert "remove old rebase code now that we're only ever interactively rebasing" This reverts commit 1a19b1412d3da03992403cf62fddf06031de2927. --- pkg/commands/git.go | 19 ++++++-- pkg/git/commit_list_builder.go | 84 +++++++++++++++++++++++++++++++--- pkg/gui/status_panel.go | 8 ++-- 3 files changed, 98 insertions(+), 13 deletions(-) diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 711215d3b..ecfd86eb2 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -419,9 +419,22 @@ func (c *GitCommand) IsInMergeState() (bool, error) { return strings.Contains(output, "conclude merge") || strings.Contains(output, "unmerged paths"), nil } -// IsInRebasingState tells us if we are rebasing -func (c *GitCommand) IsInRebasingState() (bool, error) { - return c.OSCommand.FileExists(".git/rebase-merge") +// RebaseMode returns "" for non-rebase mode, "normal" for normal rebase +// and "interactive" for interactive rebase +func (c *GitCommand) RebaseMode() (string, error) { + exists, err := c.OSCommand.FileExists(".git/rebase-apply") + if err != nil { + return "", err + } + if exists { + return "normal", nil + } + exists, err = c.OSCommand.FileExists(".git/rebase-merge") + if exists { + return "interactive", err + } else { + return "", err + } } // RemoveFile directly diff --git a/pkg/git/commit_list_builder.go b/pkg/git/commit_list_builder.go index 08a10fafc..4f3268195 100644 --- a/pkg/git/commit_list_builder.go +++ b/pkg/git/commit_list_builder.go @@ -3,6 +3,9 @@ package git import ( "fmt" "io/ioutil" + "os" + "path/filepath" + "regexp" "strings" "github.com/fatih/color" @@ -45,13 +48,13 @@ func NewCommitListBuilder(log *logrus.Entry, gitCommand *commands.GitCommand, os func (c *CommitListBuilder) GetCommits() ([]*commands.Commit, error) { commits := []*commands.Commit{} var rebasingCommits []*commands.Commit - isRebasing, err := c.GitCommand.IsInRebasingState() + rebaseMode, err := c.GitCommand.RebaseMode() if err != nil { return nil, err } - if isRebasing { + if rebaseMode != "" { // here we want to also prepend the commits that we're in the process of rebasing - rebasingCommits, err = c.getRebasingCommits() + rebasingCommits, err = c.getRebasingCommits(rebaseMode) if err != nil { return nil, err } @@ -76,7 +79,7 @@ func (c *CommitListBuilder) GetCommits() ([]*commands.Commit, error) { DisplayString: strings.Join(splitLine, " "), }) } - if isRebasing { + if rebaseMode != "" { currentCommit := commits[len(rebasingCommits)] blue := color.New(color.FgYellow) youAreHere := blue.Sprintf("<-- %s ---", c.Tr.SLocalize("YouAreHere")) @@ -96,6 +99,59 @@ func (c *CommitListBuilder) GetCommits() ([]*commands.Commit, error) { return commits, nil } +// getRebasingCommits obtains the commits that we're in the process of rebasing +func (c *CommitListBuilder) getRebasingCommits(rebaseMode string) ([]*commands.Commit, error) { + switch rebaseMode { + case "normal": + return c.getNormalRebasingCommits() + case "interactive": + return c.getInteractiveRebasingCommits() + default: + return nil, nil + } +} + +func (c *CommitListBuilder) getNormalRebasingCommits() ([]*commands.Commit, error) { + 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 := []*commands.Commit{} + err = filepath.Walk(".git/rebase-apply", func(path string, f os.FileInfo, err error) error { + if rewrittenCount > 0 { + rewrittenCount-- + 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([]*commands.Commit{commit}, commits...) + return nil + }) + if err != nil { + return nil, err + } + + return commits, nil +} + // git-rebase-todo example: // pick ac446ae94ee560bdb8d1d057278657b251aaef17 ac446ae // pick afb893148791a2fbd8091aeb81deba4930c73031 afb8931 @@ -105,10 +161,10 @@ func (c *CommitListBuilder) GetCommits() ([]*commands.Commit, error) { // pick ac446ae94ee560bdb8d1d057278657b251aaef17 blah commit on master // pick afb893148791a2fbd8091aeb81deba4930c73031 fourth commit on master -// getRebasingCommits takes our git-rebase-todo and our git-rebase-todo.backup files +// getInteractiveRebasingCommits takes our git-rebase-todo and our git-rebase-todo.backup files // and extracts out the sha and names of commits that we still have to go // in the rebase: -func (c *CommitListBuilder) getRebasingCommits() ([]*commands.Commit, error) { +func (c *CommitListBuilder) getInteractiveRebasingCommits() ([]*commands.Commit, error) { bytesContent, err := ioutil.ReadFile(".git/rebase-merge/git-rebase-todo") if err != nil { c.Log.Info(fmt.Sprintf("error occured reading git-rebase-todo: %s", err.Error())) @@ -134,6 +190,22 @@ func (c *CommitListBuilder) getRebasingCommits() ([]*commands.Commit, error) { return nil, nil } +// assuming the file starts like this: +// From e93d4193e6dd45ca9cf3a5a273d7ba6cd8b8fb20 Mon Sep 17 00:00:00 2001 +// From: Lazygit Tester +// Date: Wed, 5 Dec 2018 21:03:23 +1100 +// Subject: second commit on master +func (c *CommitListBuilder) commitFromPatch(content string) (*commands.Commit, error) { + lines := strings.Split(content, "\n") + sha := strings.Split(lines[0], " ")[1][0:7] + name := strings.TrimPrefix(lines[3], "Subject: ") + return &commands.Commit{ + Sha: sha, + Name: name, + Status: "rebasing", + }, nil +} + func (c *CommitListBuilder) setCommitMergedStatuses(commits []*commands.Commit) ([]*commands.Commit, error) { ancestor, err := c.getMergeBase() if err != nil { diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index 8c03c30de..0ac9bd662 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -101,14 +101,14 @@ func (gui *Gui) updateWorkTreeState() error { gui.State.WorkingTreeState = "merging" return nil } - isRebasing, err := gui.GitCommand.IsInRebasingState() + rebaseMode, err := gui.GitCommand.RebaseMode() if err != nil { return err } - if isRebasing { + if rebaseMode != "" { gui.State.WorkingTreeState = "rebasing" - } else { - gui.State.WorkingTreeState = "normal" + return nil } + gui.State.WorkingTreeState = "normal" return nil }