github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/revert.go (about) 1 package git 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 ) 7 8 type RevertOptions struct { 9 Edit bool 10 11 MergeParent int 12 13 NoCommit bool 14 SignOff bool 15 16 MergeStrategy string 17 MergeStrategyOption string 18 19 Continue, Quit, Abort bool 20 } 21 22 // Reverts the given commits from the HEAD. Revert doesn't actually create the 23 // new commit, it returns the new tree and leaves it up to the caller (who has 24 // a better chance of knowing the appropriate commit message..) 25 func Revert(c *Client, opts RevertOptions, commits []Commitish) error { 26 switch { 27 case len(commits) == 0: 28 return fmt.Errorf("Must provide commit to revert") 29 case len(commits) > 1: 30 return fmt.Errorf("Only 1 revert at a time currently supported. Sequencer not implemented") 31 } 32 33 // Ensure that the tree is clean before doing anything. 34 worktree, err := DiffFiles(c, DiffFilesOptions{}, nil) 35 if err != nil { 36 return err 37 } 38 if len(worktree) > 0 { 39 return fmt.Errorf("Untracked changes to files would be modified. Aborting") 40 } 41 head, err := c.GetHeadCommit() 42 if err != nil { 43 return err 44 } 45 46 if err := UpdateRef(c, UpdateRefOptions{NoDeref: true}, "REVERT_HEAD", head, ""); err != nil { 47 return err 48 } 49 50 cmt, err := commits[0].CommitID(c) 51 if err != nil { 52 return err 53 } 54 parents, err := cmt.Parents(c) 55 if err != nil { 56 return err 57 } 58 var diff []HashDiff 59 if len(parents) == 0 { 60 // FIXME: This shouldn't be the case, but needs to be handled 61 // as a special case. 62 return fmt.Errorf("Can not revert initial commit.") 63 } else if len(parents) == 1 { 64 diffs, err := DiffTree(c, &DiffTreeOptions{}, parents[0], cmt, nil) 65 if err != nil { 66 return err 67 } 68 diff = diffs 69 } else if opts.MergeParent <= 0 { 70 return fmt.Errorf("Must specify merge parent to revert a merge commit.") 71 } else { 72 // the merge parent is 1 indexed. 73 diffs, err := DiffTree(c, &DiffTreeOptions{}, parents[opts.MergeParent-1], cmt, nil) 74 if err != nil { 75 return err 76 } 77 diff = diffs 78 } 79 80 patch, err := ioutil.TempFile("", "gitrevertpatch") 81 if err != nil { 82 return err 83 } 84 if err := GeneratePatch(c, DiffCommonOptions{Patch: true}, diff, patch); err != nil { 85 return err 86 } 87 if err := Apply(c, ApplyOptions{ThreeWay: true, Reverse: true, Index: true}, []File{File(patch.Name())}); err != nil { 88 return err 89 } 90 return nil 91 }