github.com/gfleury/gobbs@v0.0.0-20200831213239-44ca2b94c1a1/pullrequests/diff.go (about)

     1  package pullrequests
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net"
     8  	"net/http"
     9  	"strconv"
    10  
    11  	"github.com/gfleury/gobbs/common"
    12  	"github.com/gfleury/gobbs/common/log"
    13  
    14  	bitbucketv1 "github.com/gfleury/go-bitbucket-v1"
    15  	"github.com/spf13/cobra"
    16  )
    17  
    18  var (
    19  	WhiteColor       = "\033[1;97m"
    20  	GreenColor       = "\033[0;32m"
    21  	RedColor         = "\033[0;31m"
    22  	CyanColor        = "\033[0;36m"
    23  	ResetColor       = "\033[0m"
    24  	diffContextLines *int32
    25  	noColor          *bool
    26  )
    27  
    28  func init() {
    29  	diffContextLines = Diff.Flags().Int32P("lines", "L", 3, "Diff context lines (how many lines before/after)")
    30  	noColor = Diff.Flags().BoolP("nocolor", "N", false, "Disable color output (getting a working diff)")
    31  }
    32  
    33  // Digg is the cmd implementation for getting Raw diff of PullRequests
    34  var Diff = &cobra.Command{
    35  	Use:     "diff pullRequestID",
    36  	Aliases: []string{"inf"},
    37  	Short:   "Diff pull requests for repository",
    38  	Args:    cobra.MinimumNArgs(1),
    39  	RunE: func(cmd *cobra.Command, args []string) error {
    40  		prID, err := strconv.Atoi(args[0])
    41  		if err != nil {
    42  			log.Critical("Argument must be a pull request ID. Err: %s", err.Error())
    43  			return err
    44  		}
    45  
    46  		apiClient, cancel, err := common.APIClient(cmd)
    47  		defer cancel()
    48  
    49  		if err != nil {
    50  			return err
    51  		}
    52  
    53  		if *noColor {
    54  			WhiteColor = ""
    55  			GreenColor = ""
    56  			RedColor = ""
    57  			CyanColor = ""
    58  			ResetColor = ""
    59  		}
    60  
    61  		stashInfo := cmd.Context().Value(common.StashInfoKey).(*common.StashInfo)
    62  		err = mustHaveProjectRepo(stashInfo)
    63  		if err != nil {
    64  			return err
    65  		}
    66  
    67  		opts := map[string]interface{}{
    68  			"contextLines": *diffContextLines,
    69  		}
    70  
    71  		response, err := apiClient.DefaultApi.GetPullRequestDiff(*stashInfo.Project(), *stashInfo.Repo(), prID, opts)
    72  
    73  		if netError, ok := err.(net.Error); (!ok || (ok && !netError.Timeout())) &&
    74  			!errors.Is(err, context.Canceled) &&
    75  			!errors.Is(err, context.DeadlineExceeded) &&
    76  			response != nil && response.Response != nil &&
    77  			response.Response.StatusCode >= http.StatusMultipleChoices {
    78  			common.PrintApiError(response.Values)
    79  			cmd.SilenceUsage = true
    80  			log.Debugf(err.Error())
    81  			return fmt.Errorf("Unable to process request, API Error")
    82  		} else if err != nil {
    83  			cmd.SilenceUsage = true
    84  			return err
    85  		}
    86  
    87  		diffs, err := bitbucketv1.GetDiffResponse(response)
    88  		if err != nil {
    89  			return err
    90  		}
    91  
    92  		less, stdin := common.Pager()
    93  
    94  		go func() {
    95  			for _, diff := range diffs.Diffs {
    96  				// --- a/pullrequests/pr.go
    97  				// +++ b/pullrequests/pr.go
    98  				fmt.Fprintf(stdin, "%s--- %s%s\n", WhiteColor, diff.Source.ToString, ResetColor)
    99  				fmt.Fprintf(stdin, "%s+++ %s%s\n", WhiteColor, diff.Destination.ToString, ResetColor)
   100  				for _, hunk := range diff.Hunks {
   101  					// @@ -15,6 +15,7 @@
   102  					fmt.Fprintf(stdin, "%s@@ -%d,%d +%d,%d @@%s\n", CyanColor, hunk.SourceLine, hunk.SourceSpan, hunk.DestinationLine, hunk.DestinationSpan, CyanColor)
   103  					for _, segment := range hunk.Segments {
   104  						lineStart := " "
   105  						if segment.Type == "ADDED" {
   106  							lineStart = GreenColor + "+"
   107  						} else if segment.Type == "REMOVED" {
   108  							lineStart = RedColor + "-"
   109  						}
   110  						for _, line := range segment.Lines {
   111  							fmt.Fprintf(stdin, "%s%s%s\n", lineStart, line.Line, ResetColor)
   112  						}
   113  					}
   114  				}
   115  			}
   116  			defer stdin.Close()
   117  		}()
   118  
   119  		err = less.Run()
   120  		return err
   121  	},
   122  }