- commit
- 6950fe8
- parent
- c169202
- author
- Eric Bower
- date
- 2024-07-21 14:49:58 -0400 EDT
feat(cli): add `--accept` and `--close` to `pr add` cmd refactor(cli): always print PR summary when applicable
M
cli.go
+117,
-124
1@@ -56,6 +56,87 @@ func printPatches(sesh ssh.Session, patches []*Patch) {
2 }
3 }
4
5+func prSummary(be *Backend, pr GitPatchRequest, sesh ssh.Session, prID int64) error {
6+ request, err := pr.GetPatchRequestByID(prID)
7+ if err != nil {
8+ return err
9+ }
10+
11+ wish.Printf(sesh, "Info\n====\n")
12+ wish.Printf(sesh, "URL: https://%s/prs/%d\n\n", be.Cfg.Url, prID)
13+
14+ writer := NewTabWriter(sesh)
15+ fmt.Fprintln(writer, "ID\tName\tStatus\tDate")
16+ fmt.Fprintf(
17+ writer,
18+ "%d\t%s\t[%s]\t%s\n",
19+ request.ID, request.Name, request.Status, request.CreatedAt.Format(be.Cfg.TimeFormat),
20+ )
21+ writer.Flush()
22+
23+ patchsets, err := pr.GetPatchsetsByPrID(prID)
24+ if err != nil {
25+ return err
26+ }
27+
28+ wish.Printf(sesh, "\nPatchsets\n====\n")
29+
30+ writerSet := NewTabWriter(sesh)
31+ fmt.Fprintln(writerSet, "ID\tType\tUser\tDate")
32+ for _, patchset := range patchsets {
33+ user, err := pr.GetUserByID(patchset.UserID)
34+ if err != nil {
35+ be.Logger.Error("cannot find user for patchset", "err", err)
36+ continue
37+ }
38+ isReview := ""
39+ if patchset.Review {
40+ isReview = "[review]"
41+ }
42+
43+ fmt.Fprintf(
44+ writerSet,
45+ "%s\t%s\t%s\t%s\n",
46+ getFormattedPatchsetID(patchset.ID),
47+ isReview,
48+ user.Name,
49+ patchset.CreatedAt.Format(be.Cfg.TimeFormat),
50+ )
51+ }
52+ writerSet.Flush()
53+
54+ latest, err := getPatchsetFromOpt(patchsets, "")
55+ if err != nil {
56+ return err
57+ }
58+
59+ patches, err := pr.GetPatchesByPatchsetID(latest.ID)
60+ if err != nil {
61+ return err
62+ }
63+
64+ wish.Printf(sesh, "\nPatches from latest patchset\n====\n")
65+
66+ opatches := patches
67+ w := NewTabWriter(sesh)
68+ fmt.Fprintln(w, "Idx\tTitle\tCommit\tAuthor\tDate")
69+ for idx, patch := range opatches {
70+ timestamp := patch.AuthorDate.Format(be.Cfg.TimeFormat)
71+ fmt.Fprintf(
72+ w,
73+ "%d\t%s\t%s\t%s <%s>\t%s\n",
74+ idx,
75+ patch.Title,
76+ truncateSha(patch.CommitSha),
77+ patch.AuthorName,
78+ patch.AuthorEmail,
79+ timestamp,
80+ )
81+ }
82+ w.Flush()
83+ return nil
84+}
85+
86 func NewCli(sesh ssh.Session, be *Backend, pr GitPatchRequest) *cli.App {
87 desc := `Patch requests (PR) are the simplest way to submit, review, and accept changes to your git repository.
88 Here's how it works:
89@@ -369,18 +450,7 @@ Here's how it works:
90 "PR submitted! Use the ID for interacting with this PR.",
91 )
92
93- writer := NewTabWriter(sesh)
94- fmt.Fprintln(writer, "ID\tName\tURL")
95- fmt.Fprintf(
96- writer,
97- "%d\t%s\t%s\n",
98- prq.ID,
99- prq.Name,
100- fmt.Sprintf("https://%s/prs/%d", be.Cfg.Url, prq.ID),
101- )
102- writer.Flush()
103-
104- return nil
105+ return prSummary(be, pr, sesh, prq.ID)
106 },
107 },
108 {
109@@ -482,84 +552,7 @@ Here's how it works:
110 if err != nil {
111 return err
112 }
113- request, err := pr.GetPatchRequestByID(prID)
114- if err != nil {
115- return err
116- }
117-
118- wish.Printf(sesh, "Info\n====\n")
119-
120- writer := NewTabWriter(sesh)
121- fmt.Fprintln(writer, "ID\tName\tStatus\tDate")
122- fmt.Fprintf(
123- writer,
124- "%d\t%s\t[%s]\t%s\n",
125- request.ID, request.Name, request.Status, request.CreatedAt.Format(be.Cfg.TimeFormat),
126- )
127- writer.Flush()
128-
129- patchsets, err := pr.GetPatchsetsByPrID(prID)
130- if err != nil {
131- return err
132- }
133-
134- wish.Printf(sesh, "\nPatchsets\n====\n")
135-
136- writerSet := NewTabWriter(sesh)
137- fmt.Fprintln(writerSet, "ID\tType\tUser\tDate")
138- for _, patchset := range patchsets {
139- user, err := pr.GetUserByID(patchset.UserID)
140- if err != nil {
141- be.Logger.Error("cannot find user for patchset", "err", err)
142- continue
143- }
144- isReview := ""
145- if patchset.Review {
146- isReview = "[review]"
147- }
148-
149- fmt.Fprintf(
150- writerSet,
151- "%s\t%s\t%s\t%s\n",
152- getFormattedPatchsetID(patchset.ID),
153- isReview,
154- user.Name,
155- patchset.CreatedAt.Format(be.Cfg.TimeFormat),
156- )
157- }
158- writerSet.Flush()
159-
160- latest, err := getPatchsetFromOpt(patchsets, "")
161- if err != nil {
162- return err
163- }
164-
165- patches, err := pr.GetPatchesByPatchsetID(latest.ID)
166- if err != nil {
167- return err
168- }
169-
170- wish.Printf(sesh, "\nPatches from latest patchset\n====\n")
171-
172- opatches := patches
173- w := NewTabWriter(sesh)
174- fmt.Fprintln(w, "Idx\tTitle\tCommit\tAuthor\tDate")
175- for idx, patch := range opatches {
176- timestamp := patch.AuthorDate.Format(be.Cfg.TimeFormat)
177- fmt.Fprintf(
178- w,
179- "%d\t%s\t%s\t%s <%s>\t%s\n",
180- idx,
181- patch.Title,
182- truncateSha(patch.CommitSha),
183- patch.AuthorName,
184- patch.AuthorEmail,
185- timestamp,
186- )
187- }
188- w.Flush()
189-
190- return nil
191+ return prSummary(be, pr, sesh, prID)
192 },
193 },
194 {
195@@ -598,10 +591,11 @@ Here's how it works:
196 }
197
198 err = pr.UpdatePatchRequestStatus(prID, user.ID, "accepted")
199- if err == nil {
200- wish.Printf(sesh, "Accepted PR %s (#%d)\n", patchReq.Name, patchReq.ID)
201+ if err != nil {
202+ return err
203 }
204- return err
205+ wish.Printf(sesh, "Accepted PR %s (#%d)\n", patchReq.Name, patchReq.ID)
206+ return prSummary(be, pr, sesh, prID)
207 },
208 },
209 {
210@@ -642,10 +636,11 @@ Here's how it works:
211 }
212
213 err = pr.UpdatePatchRequestStatus(prID, user.ID, "closed")
214- if err == nil {
215- wish.Printf(sesh, "Closed PR %s (#%d)\n", patchReq.Name, patchReq.ID)
216+ if err != nil {
217+ return err
218 }
219- return err
220+ wish.Printf(sesh, "Closed PR %s (#%d)\n", patchReq.Name, patchReq.ID)
221+ return prSummary(be, pr, sesh, prID)
222 },
223 },
224 {
225@@ -689,7 +684,7 @@ Here's how it works:
226 if err == nil {
227 wish.Printf(sesh, "Reopened PR %s (#%d)\n", patchReq.Name, patchReq.ID)
228 }
229- return err
230+ return prSummary(be, pr, sesh, prID)
231 },
232 },
233 {
234@@ -749,7 +744,15 @@ Here's how it works:
235 Flags: []cli.Flag{
236 &cli.BoolFlag{
237 Name: "review",
238- Usage: "mark patch as a review",
239+ Usage: "submit patchset and mark PR as reviewed",
240+ },
241+ &cli.BoolFlag{
242+ Name: "accept",
243+ Usage: "submit patchset and mark PR as accepted",
244+ },
245+ &cli.BoolFlag{
246+ Name: "close",
247+ Usage: "submit patchset and mark PR as closed",
248 },
249 },
250 Action: func(cCtx *cli.Context) error {
251@@ -774,15 +777,27 @@ Here's how it works:
252
253 isAdmin := be.IsAdmin(sesh.PublicKey())
254 isReview := cCtx.Bool("review")
255+ isAccept := cCtx.Bool("accept")
256+ isClose := cCtx.Bool("close")
257 isPrOwner := be.IsPrOwner(prq.UserID, user.ID)
258 if !isAdmin && !isPrOwner {
259 return fmt.Errorf("unauthorized, you are not the owner of this PR")
260 }
261
262 op := OpNormal
263+ nextStatus := "open"
264 if isReview {
265- wish.Println(sesh, "Marking new patchset as a review")
266+ wish.Println(sesh, "Marking PR as reviewed")
267+ nextStatus = "reviewed"
268 op = OpReview
269+ } else if isAccept {
270+ wish.Println(sesh, "Marking PR as accepted")
271+ nextStatus = "accepted"
272+ op = OpAccept
273+ } else if isClose {
274+ wish.Println(sesh, "Marking PR as closed")
275+ nextStatus = "closed"
276+ op = OpClose
277 }
278
279 patches, err := pr.SubmitPatchset(prID, user.ID, op, sesh)
280@@ -795,37 +810,15 @@ Here's how it works:
281 return nil
282 }
283
284- reviewTxt := ""
285- if isReview {
286- err = pr.UpdatePatchRequestStatus(prID, user.ID, "reviewed")
287+ if nextStatus != "" {
288+ err = pr.UpdatePatchRequestStatus(prID, user.ID, nextStatus)
289 if err != nil {
290 return err
291 }
292- reviewTxt = "[review]"
293 }
294
295 wish.Println(sesh, "Patches submitted!")
296- writer := NewTabWriter(sesh)
297- fmt.Fprintln(
298- writer,
299- "ID\tTitle",
300- )
301- for _, patch := range patches {
302- fmt.Fprintf(
303- writer,
304- "%d\t%s %s\n",
305- patch.ID,
306- patch.Title,
307- reviewTxt,
308- )
309- }
310- writer.Flush()
311-
312- wish.Println(
313- sesh,
314- fmt.Sprintf("https://%s/prs/%d", be.Cfg.Url, prq.ID),
315- )
316- return nil
317+ return prSummary(be, pr, sesh, prID)
318 },
319 },
320 },
M
pr.go
+2,
-0
1@@ -17,6 +17,8 @@ type PatchsetOp int
2 const (
3 OpNormal PatchsetOp = iota
4 OpReview
5+ OpAccept
6+ OpClose
7 )
8
9 type GitPatchRequest interface {
M
util.go
+3,
-0
1@@ -31,6 +31,9 @@ func randSeq(n int) string {
2 }
3
4 func truncateSha(sha string) string {
5+ if len(sha) < 7 {
6+ return sha
7+ }
8 return sha[:7]
9 }
10