2019-11-04 10:47:25 +02:00
|
|
|
package commands
|
|
|
|
|
2020-04-27 18:31:22 +02:00
|
|
|
import (
|
|
|
|
"fmt"
|
2020-08-15 03:18:40 +02:00
|
|
|
|
2020-04-27 18:31:22 +02:00
|
|
|
"github.com/go-errors/errors"
|
2020-09-29 12:28:39 +02:00
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
2020-08-15 03:18:40 +02:00
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
2020-04-27 18:31:22 +02:00
|
|
|
)
|
2019-11-04 10:47:25 +02:00
|
|
|
|
|
|
|
// DeletePatchesFromCommit applies a patch in reverse for a commit
|
2020-09-29 10:36:54 +02:00
|
|
|
func (c *GitCommand) DeletePatchesFromCommit(commits []*models.Commit, commitIndex int, p *patch.PatchManager) error {
|
2019-11-04 10:47:25 +02:00
|
|
|
if err := c.BeginInteractiveRebaseForCommit(commits, commitIndex); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// apply each patch in reverse
|
|
|
|
if err := p.ApplyPatches(true); err != nil {
|
2020-09-29 12:03:39 +02:00
|
|
|
if err := c.GenericMergeOrRebaseAction("rebase", "abort"); err != nil {
|
2019-11-04 10:47:25 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// time to amend the selected commit
|
|
|
|
if _, err := c.AmendHead(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-11-05 02:56:29 +02:00
|
|
|
c.onSuccessfulContinue = func() error {
|
2019-11-05 09:10:47 +02:00
|
|
|
c.PatchManager.Reset()
|
2019-11-05 02:56:29 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-11-04 10:47:25 +02:00
|
|
|
// continue
|
2020-09-29 12:03:39 +02:00
|
|
|
return c.GenericMergeOrRebaseAction("rebase", "continue")
|
2019-11-04 10:47:25 +02:00
|
|
|
}
|
|
|
|
|
2020-09-29 10:36:54 +02:00
|
|
|
func (c *GitCommand) MovePatchToSelectedCommit(commits []*models.Commit, sourceCommitIdx int, destinationCommitIdx int, p *patch.PatchManager) error {
|
2019-11-04 10:47:25 +02:00
|
|
|
if sourceCommitIdx < destinationCommitIdx {
|
|
|
|
if err := c.BeginInteractiveRebaseForCommit(commits, destinationCommitIdx); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// apply each patch forward
|
|
|
|
if err := p.ApplyPatches(false); err != nil {
|
2020-09-29 12:03:39 +02:00
|
|
|
if err := c.GenericMergeOrRebaseAction("rebase", "abort"); err != nil {
|
2019-11-04 10:47:25 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// amend the destination commit
|
|
|
|
if _, err := c.AmendHead(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-11-05 02:56:29 +02:00
|
|
|
c.onSuccessfulContinue = func() error {
|
2019-11-05 09:10:47 +02:00
|
|
|
c.PatchManager.Reset()
|
2019-11-05 02:56:29 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-11-04 10:47:25 +02:00
|
|
|
// continue
|
2020-09-29 12:03:39 +02:00
|
|
|
return c.GenericMergeOrRebaseAction("rebase", "continue")
|
2019-11-04 10:47:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(commits)-1 < sourceCommitIdx {
|
|
|
|
return errors.New("index outside of range of commits")
|
|
|
|
}
|
|
|
|
|
|
|
|
// we can make this GPG thing possible it just means we need to do this in two parts:
|
|
|
|
// one where we handle the possibility of a credential request, and the other
|
|
|
|
// where we continue the rebase
|
|
|
|
if c.usingGpg() {
|
|
|
|
return errors.New(c.Tr.SLocalize("DisabledForGPG"))
|
|
|
|
}
|
|
|
|
|
|
|
|
baseIndex := sourceCommitIdx + 1
|
|
|
|
todo := ""
|
|
|
|
for i, commit := range commits[0:baseIndex] {
|
|
|
|
a := "pick"
|
|
|
|
if i == sourceCommitIdx || i == destinationCommitIdx {
|
|
|
|
a = "edit"
|
|
|
|
}
|
|
|
|
todo = a + " " + commit.Sha + " " + commit.Name + "\n" + todo
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd, err := c.PrepareInteractiveRebaseCommand(commits[baseIndex].Sha, todo, true)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.OSCommand.RunPreparedCommand(cmd); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// apply each patch in reverse
|
|
|
|
if err := p.ApplyPatches(true); err != nil {
|
2020-09-29 12:03:39 +02:00
|
|
|
if err := c.GenericMergeOrRebaseAction("rebase", "abort"); err != nil {
|
2019-11-04 10:47:25 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// amend the source commit
|
|
|
|
if _, err := c.AmendHead(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.onSuccessfulContinue != nil {
|
|
|
|
return errors.New("You are midway through another rebase operation. Please abort to start again")
|
|
|
|
}
|
|
|
|
|
|
|
|
c.onSuccessfulContinue = func() error {
|
|
|
|
// now we should be up to the destination, so let's apply forward these patches to that.
|
|
|
|
// ideally we would ensure we're on the right commit but I'm not sure if that check is necessary
|
|
|
|
if err := p.ApplyPatches(false); err != nil {
|
2020-09-29 12:03:39 +02:00
|
|
|
if err := c.GenericMergeOrRebaseAction("rebase", "abort"); err != nil {
|
2019-11-04 10:47:25 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// amend the destination commit
|
|
|
|
if _, err := c.AmendHead(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-11-05 02:56:29 +02:00
|
|
|
c.onSuccessfulContinue = func() error {
|
2019-11-05 09:10:47 +02:00
|
|
|
c.PatchManager.Reset()
|
2019-11-05 02:56:29 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-09-29 12:03:39 +02:00
|
|
|
return c.GenericMergeOrRebaseAction("rebase", "continue")
|
2019-11-04 10:47:25 +02:00
|
|
|
}
|
|
|
|
|
2020-09-29 12:03:39 +02:00
|
|
|
return c.GenericMergeOrRebaseAction("rebase", "continue")
|
2019-11-04 10:47:25 +02:00
|
|
|
}
|
|
|
|
|
2020-09-29 10:36:54 +02:00
|
|
|
func (c *GitCommand) PullPatchIntoIndex(commits []*models.Commit, commitIdx int, p *patch.PatchManager, stash bool) error {
|
2020-03-28 03:43:31 +02:00
|
|
|
if stash {
|
|
|
|
if err := c.StashSave(c.Tr.SLocalize("StashPrefix") + commits[commitIdx].Sha); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-04 10:47:25 +02:00
|
|
|
if err := c.BeginInteractiveRebaseForCommit(commits, commitIdx); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := p.ApplyPatches(true); err != nil {
|
2020-03-28 03:43:31 +02:00
|
|
|
if c.WorkingTreeState() == "rebasing" {
|
2020-09-29 12:03:39 +02:00
|
|
|
if err := c.GenericMergeOrRebaseAction("rebase", "abort"); err != nil {
|
2020-03-28 03:43:31 +02:00
|
|
|
return err
|
|
|
|
}
|
2019-11-04 10:47:25 +02:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// amend the commit
|
|
|
|
if _, err := c.AmendHead(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.onSuccessfulContinue != nil {
|
|
|
|
return errors.New("You are midway through another rebase operation. Please abort to start again")
|
|
|
|
}
|
|
|
|
|
|
|
|
c.onSuccessfulContinue = func() error {
|
|
|
|
// add patches to index
|
|
|
|
if err := p.ApplyPatches(false); err != nil {
|
2020-03-28 03:43:31 +02:00
|
|
|
if c.WorkingTreeState() == "rebasing" {
|
2020-09-29 12:03:39 +02:00
|
|
|
if err := c.GenericMergeOrRebaseAction("rebase", "abort"); err != nil {
|
2020-03-28 03:43:31 +02:00
|
|
|
return err
|
|
|
|
}
|
2019-11-04 10:47:25 +02:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-03-28 03:43:31 +02:00
|
|
|
if stash {
|
|
|
|
if err := c.StashDo(0, "apply"); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-05 09:10:47 +02:00
|
|
|
c.PatchManager.Reset()
|
2019-11-04 10:47:25 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-09-29 12:03:39 +02:00
|
|
|
return c.GenericMergeOrRebaseAction("rebase", "continue")
|
2019-11-04 10:47:25 +02:00
|
|
|
}
|
2020-04-27 18:31:22 +02:00
|
|
|
|
2020-09-29 10:36:54 +02:00
|
|
|
func (c *GitCommand) PullPatchIntoNewCommit(commits []*models.Commit, commitIdx int, p *patch.PatchManager) error {
|
2020-04-27 18:31:22 +02:00
|
|
|
if err := c.BeginInteractiveRebaseForCommit(commits, commitIdx); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := p.ApplyPatches(true); err != nil {
|
2020-09-29 12:03:39 +02:00
|
|
|
if err := c.GenericMergeOrRebaseAction("rebase", "abort"); err != nil {
|
2020-04-27 18:31:22 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// amend the commit
|
|
|
|
if _, err := c.AmendHead(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// add patches to index
|
|
|
|
if err := p.ApplyPatches(false); err != nil {
|
2020-09-29 12:03:39 +02:00
|
|
|
if err := c.GenericMergeOrRebaseAction("rebase", "abort"); err != nil {
|
2020-04-27 18:31:22 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
head_message, _ := c.GetHeadCommitMessage()
|
|
|
|
new_message := fmt.Sprintf("Split from \"%s\"", head_message)
|
|
|
|
_, err := c.Commit(new_message, "")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.onSuccessfulContinue != nil {
|
|
|
|
return errors.New("You are midway through another rebase operation. Please abort to start again")
|
|
|
|
}
|
|
|
|
|
|
|
|
c.PatchManager.Reset()
|
2020-09-29 12:03:39 +02:00
|
|
|
return c.GenericMergeOrRebaseAction("rebase", "continue")
|
2020-04-27 18:31:22 +02:00
|
|
|
}
|