github.com/abhinav/git-pr@v0.6.1-0.20171029234004-54218d68c11b/pr/land.go (about)

     1  package pr
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/abhinav/git-pr/service"
     8  )
     9  
    10  // Land the given pull request.
    11  func (s *Service) Land(ctx context.Context, req *service.LandRequest) (*service.LandResponse, error) {
    12  	pr := req.PullRequest
    13  	if err := UpdateMessage(req.Editor, pr); err != nil {
    14  		return nil, err
    15  	}
    16  
    17  	// If the base branch doesn't exist locally, check it out. If it exists,
    18  	// it's okay for it to be out of sync with the remote.
    19  	base := *pr.Base.Ref
    20  	if !s.git.DoesBranchExist(base) {
    21  		if err := s.git.CreateBranch(base, *pr.Base.Ref); err != nil {
    22  			return nil, err
    23  		}
    24  	}
    25  
    26  	// If the branch is checked out locally, make sure it's in sync with
    27  	// remote.
    28  	if req.LocalBranch != "" {
    29  		hash, err := s.git.SHA1(req.LocalBranch)
    30  		if err != nil {
    31  			return nil, err
    32  		}
    33  
    34  		if hash != *pr.Head.SHA {
    35  			return nil, fmt.Errorf(
    36  				"SHA1 of local branch %v of pull request %v does not match GitHub. "+
    37  					"Make sure that your local checkout of %v is in sync.",
    38  				req.LocalBranch, *pr.HTMLURL, req.LocalBranch)
    39  		}
    40  	}
    41  
    42  	if err := s.gh.SquashPullRequest(ctx, pr); err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	if err := s.git.Checkout(base); err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	// TODO: Remove hard coded remote name
    51  	if err := s.git.Pull("origin", base); err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	if req.LocalBranch != "" {
    56  		if err := s.git.DeleteBranch(req.LocalBranch); err != nil {
    57  			return nil, err
    58  		}
    59  	}
    60  
    61  	// Nothing else to do if we don't own this pull request.
    62  	if !s.gh.IsOwned(ctx, pr.Head) {
    63  		return nil, nil
    64  	}
    65  
    66  	dependents, err := s.gh.ListPullRequestsByBase(ctx, *pr.Head.Ref)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	var res service.LandResponse
    72  	if len(dependents) > 0 {
    73  		rebaseRes, err := s.Rebase(ctx, &service.RebaseRequest{PullRequests: dependents, Base: base})
    74  		if err != nil {
    75  			return nil, fmt.Errorf("failed to rebase dependents of %v: %v", *pr.HTMLURL, err)
    76  		}
    77  		res.BranchesNotUpdated = rebaseRes.BranchesNotUpdated
    78  	}
    79  
    80  	// TODO: What happens on branch deletion if we had dependents but none
    81  	// were owned by us?
    82  	if err := s.gh.DeleteBranch(ctx, *pr.Head.Ref); err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	if req.LocalBranch != "" {
    87  		// TODO: Remove hard coded remote name
    88  		if err := s.git.DeleteRemoteTrackingBranch("origin", req.LocalBranch); err != nil {
    89  			return nil, err
    90  		}
    91  	}
    92  
    93  	return &res, nil
    94  }