@@ -757,3 +757,130 @@ func TriggerTask(ctx *context.Context) {
757
757
go models .AddTestPullRequestTask (pusher , repo .ID , branch , true )
758
758
ctx .Status (202 )
759
759
}
760
+
761
+ // CleanUpPullRequest responses for delete merged branch when PR has been merged
762
+ func CleanUpPullRequest (ctx * context.Context ) {
763
+ issue := checkPullInfo (ctx )
764
+ if ctx .Written () {
765
+ return
766
+ }
767
+
768
+ pr , err := models .GetPullRequestByIssueID (issue .ID )
769
+ if err != nil {
770
+ if models .IsErrPullRequestNotExist (err ) {
771
+ ctx .Handle (404 , "GetPullRequestByIssueID" , nil )
772
+ } else {
773
+ ctx .Handle (500 , "GetPullRequestByIssueID" , err )
774
+ }
775
+ return
776
+ }
777
+
778
+ // Allow cleanup only for merged PR
779
+ if ! pr .HasMerged {
780
+ ctx .Handle (404 , "CleanUpPullRequest" , nil )
781
+ return
782
+ }
783
+
784
+ if err = pr .GetHeadRepo (); err != nil {
785
+ ctx .Handle (500 , "GetHeadRepo" , err )
786
+ return
787
+ } else if pr .HeadRepo == nil {
788
+ // Forked repository has already been deleted
789
+ ctx .Handle (404 , "CleanUpPullRequest" , nil )
790
+ return
791
+ } else if pr .GetBaseRepo (); err != nil {
792
+ ctx .Handle (500 , "GetBaseRepo" , err )
793
+ return
794
+ } else if pr .HeadRepo .GetOwner (); err != nil {
795
+ ctx .Handle (500 , "HeadRepo.GetOwner" , err )
796
+ return
797
+ }
798
+
799
+ if ! ctx .User .IsWriterOfRepo (pr .HeadRepo ) {
800
+ ctx .Handle (403 , "CleanUpPullRequest" , nil )
801
+ return
802
+ }
803
+
804
+ fullBranchName := pr .HeadRepo .Owner .Name + "/" + pr .HeadBranch
805
+
806
+ gitRepo , err := git .OpenRepository (pr .HeadRepo .RepoPath ())
807
+ if err != nil {
808
+ ctx .Handle (500 , fmt .Sprintf ("OpenRepository[%s]" , pr .HeadRepo .RepoPath ()), err )
809
+ return
810
+ }
811
+
812
+ gitBaseRepo , err := git .OpenRepository (pr .BaseRepo .RepoPath ())
813
+ if err != nil {
814
+ ctx .Handle (500 , fmt .Sprintf ("OpenRepository[%s]" , pr .BaseRepo .RepoPath ()), err )
815
+ return
816
+ }
817
+
818
+ defer func () {
819
+ ctx .JSON (200 , map [string ]interface {}{
820
+ "redirect" : pr .BaseRepo .Link () + "/pulls/" + com .ToStr (issue .Index ),
821
+ })
822
+ }()
823
+
824
+ if pr .HeadBranch == pr .HeadRepo .DefaultBranch || ! gitRepo .IsBranchExist (pr .HeadBranch ) {
825
+ ctx .Flash .Error (ctx .Tr ("repo.branch.deletion_failed" , fullBranchName ))
826
+ return
827
+ }
828
+
829
+ // Check if branch is not protected
830
+ if protected , err := pr .HeadRepo .IsProtectedBranch (pr .HeadBranch ); err != nil || protected {
831
+ if err != nil {
832
+ log .Error (4 , "HeadRepo.IsProtectedBranch: %v" , err )
833
+ }
834
+ ctx .Flash .Error (ctx .Tr ("repo.branch.deletion_failed" , fullBranchName ))
835
+ return
836
+ }
837
+
838
+ // Check if branch has no new commits
839
+ if len (pr .MergedCommitID ) > 0 {
840
+ branchCommitID , err := gitRepo .GetBranchCommitID (pr .HeadBranch )
841
+ if err != nil {
842
+ log .Error (4 , "GetBranchCommitID: %v" , err )
843
+ ctx .Flash .Error (ctx .Tr ("repo.branch.deletion_failed" , fullBranchName ))
844
+ return
845
+ }
846
+
847
+ commit , err := gitBaseRepo .GetCommit (pr .MergedCommitID )
848
+ if err != nil {
849
+ log .Error (4 , "GetCommit: %v" , err )
850
+ ctx .Flash .Error (ctx .Tr ("repo.branch.deletion_failed" , fullBranchName ))
851
+ return
852
+ }
853
+
854
+ isParent := false
855
+ for i := 0 ; i < commit .ParentCount (); i ++ {
856
+ if parent , err := commit .Parent (i ); err != nil {
857
+ log .Error (4 , "Parent: %v" , err )
858
+ ctx .Flash .Error (ctx .Tr ("repo.branch.deletion_failed" , fullBranchName ))
859
+ return
860
+ } else if parent .ID .String () == branchCommitID {
861
+ isParent = true
862
+ break
863
+ }
864
+ }
865
+
866
+ if ! isParent {
867
+ ctx .Flash .Error (ctx .Tr ("repo.branch.delete_branch_has_new_commits" , fullBranchName ))
868
+ return
869
+ }
870
+ }
871
+
872
+ if err := gitRepo .DeleteBranch (pr .HeadBranch , git.DeleteBranchOptions {
873
+ Force : true ,
874
+ }); err != nil {
875
+ log .Error (4 , "DeleteBranch: %v" , err )
876
+ ctx .Flash .Error (ctx .Tr ("repo.branch.deletion_failed" , fullBranchName ))
877
+ return
878
+ }
879
+
880
+ if err := models .AddDeletePRBranchComment (ctx .User , pr .BaseRepo , issue .ID , pr .HeadBranch ); err != nil {
881
+ // Do not fail here as branch has already been deleted
882
+ log .Error (4 , "DeleteBranch: %v" , err )
883
+ }
884
+
885
+ ctx .Flash .Success (ctx .Tr ("repo.branch.deletion_success" , fullBranchName ))
886
+ }
0 commit comments