summaryrefslogtreecommitdiffstats
path: root/pkg/commands/patch_rebases.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/commands/patch_rebases.go')
-rw-r--r--pkg/commands/patch_rebases.go153
1 files changed, 153 insertions, 0 deletions
diff --git a/pkg/commands/patch_rebases.go b/pkg/commands/patch_rebases.go
new file mode 100644
index 000000000..40c3358ac
--- /dev/null
+++ b/pkg/commands/patch_rebases.go
@@ -0,0 +1,153 @@
+package commands
+
+import "github.com/go-errors/errors"
+
+// DeletePatchesFromCommit applies a patch in reverse for a commit
+func (c *GitCommand) DeletePatchesFromCommit(commits []*Commit, commitIndex int, p *PatchManager) error {
+ if err := c.BeginInteractiveRebaseForCommit(commits, commitIndex); err != nil {
+ return err
+ }
+
+ // apply each patch in reverse
+ if err := p.ApplyPatches(true); err != nil {
+ if err := c.GenericMerge("rebase", "abort"); err != nil {
+ return err
+ }
+ return err
+ }
+
+ // time to amend the selected commit
+ if _, err := c.AmendHead(); err != nil {
+ return err
+ }
+
+ // continue
+ return c.GenericMerge("rebase", "continue")
+}
+
+func (c *GitCommand) MovePatchToSelectedCommit(commits []*Commit, sourceCommitIdx int, destinationCommitIdx int, p *PatchManager) error {
+ if sourceCommitIdx < destinationCommitIdx {
+ if err := c.BeginInteractiveRebaseForCommit(commits, destinationCommitIdx); err != nil {
+ return err
+ }
+
+ // apply each patch forward
+ if err := p.ApplyPatches(false); err != nil {
+ if err := c.GenericMerge("rebase", "abort"); err != nil {
+ return err
+ }
+ return err
+ }
+
+ // amend the destination commit
+ if _, err := c.AmendHead(); err != nil {
+ return err
+ }
+
+ // continue
+ return c.GenericMerge("rebase", "continue")
+ }
+
+ 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 {
+ if err := c.GenericMerge("rebase", "abort"); err != nil {
+ 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 {
+ if err := c.GenericMerge("rebase", "abort"); err != nil {
+ return err
+ }
+ return err
+ }
+
+ // amend the destination commit
+ if _, err := c.AmendHead(); err != nil {
+ return err
+ }
+
+ return c.GenericMerge("rebase", "continue")
+ }
+
+ return c.GenericMerge("rebase", "continue")
+}
+
+func (c *GitCommand) PullPatchIntoIndex(commits []*Commit, commitIdx int, p *PatchManager) error {
+ if err := c.BeginInteractiveRebaseForCommit(commits, commitIdx); err != nil {
+ return err
+ }
+
+ if err := p.ApplyPatches(true); err != nil {
+ if err := c.GenericMerge("rebase", "abort"); err != nil {
+ return err
+ }
+ 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 {
+ if err := c.GenericMerge("rebase", "abort"); err != nil {
+ return err
+ }
+ return err
+ }
+
+ return nil
+ }
+
+ return c.GenericMerge("rebase", "continue")
+}