forked from cli/cli
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpr_diff.go
More file actions
138 lines (117 loc) · 2.88 KB
/
pr_diff.go
File metadata and controls
138 lines (117 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package command
import (
"errors"
"fmt"
"os"
"strconv"
"strings"
"github.com/cli/cli/api"
"github.com/cli/cli/utils"
"github.com/spf13/cobra"
)
var prDiffCmd = &cobra.Command{
Use: "diff {<number> | <url>}",
Short: "View a pull request's changes.",
RunE: prDiff,
}
func init() {
prDiffCmd.Flags().StringP("color", "c", "auto", "Whether or not to output color: {always|never|auto}")
prCmd.AddCommand(prDiffCmd)
}
func prDiff(cmd *cobra.Command, args []string) error {
color, err := cmd.Flags().GetString("color")
if err != nil {
return err
}
if !validColorFlag(color) {
return fmt.Errorf("did not understand color: %q. Expected one of always, never, or auto", color)
}
ctx := contextForCommand(cmd)
apiClient, err := apiClientForContext(ctx)
if err != nil {
return err
}
baseRepo, err := determineBaseRepo(apiClient, cmd, ctx)
if err != nil {
return fmt.Errorf("could not determine base repo: %w", err)
}
// begin pr resolution boilerplate
var prNum int
branchWithOwner := ""
if len(args) == 0 {
prNum, branchWithOwner, err = prSelectorForCurrentBranch(ctx, baseRepo)
if err != nil {
return fmt.Errorf("could not query for pull request for current branch: %w", err)
}
} else {
prArg, repo := prFromURL(args[0])
if repo != nil {
baseRepo = repo
} else {
prArg = strings.TrimPrefix(args[0], "#")
}
prNum, err = strconv.Atoi(prArg)
if err != nil {
return errors.New("could not parse pull request argument")
}
}
if prNum < 1 {
pr, err := api.PullRequestForBranch(apiClient, baseRepo, "", branchWithOwner)
if err != nil {
return fmt.Errorf("could not find pull request: %w", err)
}
prNum = pr.Number
}
// end pr resolution boilerplate
diff, err := apiClient.PullRequestDiff(baseRepo, prNum)
if err != nil {
return fmt.Errorf("could not find pull request diff: %w", err)
}
out := cmd.OutOrStdout()
if color == "auto" {
color = "never"
isTTY := false
if outFile, isFile := out.(*os.File); isFile {
isTTY = utils.IsTerminal(outFile)
if isTTY {
color = "always"
}
}
}
if color == "never" {
fmt.Fprint(out, diff)
return nil
}
out = colorableOut(cmd)
for _, diffLine := range strings.Split(diff, "\n") {
output := diffLine
switch {
case isHeaderLine(diffLine):
output = utils.Bold(diffLine)
case isAdditionLine(diffLine):
output = utils.Green(diffLine)
case isRemovalLine(diffLine):
output = utils.Red(diffLine)
}
fmt.Fprintln(out, output)
}
return nil
}
func isHeaderLine(dl string) bool {
prefixes := []string{"+++", "---", "diff", "index"}
for _, p := range prefixes {
if strings.HasPrefix(dl, p) {
return true
}
}
return false
}
func isAdditionLine(dl string) bool {
return strings.HasPrefix(dl, "+")
}
func isRemovalLine(dl string) bool {
return strings.HasPrefix(dl, "-")
}
func validColorFlag(c string) bool {
return c == "auto" || c == "always" || c == "never"
}