77 "net/http"
88 "os"
99 "os/exec"
10- "strconv"
1110 "strings"
1211 "time"
1312
@@ -16,57 +15,77 @@ import (
1615 "go.abhg.dev/gs/internal/ioutil"
1716)
1817
19- type isMergedResponse struct {
20- Merged bool `json:"merged "`
18+ type areMergedRequest struct {
19+ IDs [] ChangeID `json:"ids "`
2120}
2221
23- var _ = shamhubHandler ("GET /{owner}/{repo}/change/{number}/merged" , (* ShamHub ).handleIsMerged )
22+ type areMergedResponse struct {
23+ Merged []bool `json:"merged"`
24+ }
25+
26+ var _ = shamhubHandler ("POST /{owner}/{repo}/change/merged" , (* ShamHub ).handleAreMerged )
2427
25- func (sh * ShamHub ) handleIsMerged (w http.ResponseWriter , r * http.Request ) {
26- owner , repo , numStr := r .PathValue ("owner" ), r .PathValue ("repo" ), r . PathValue ( "number " )
27- if owner == "" || repo == "" || numStr == "" {
28+ func (sh * ShamHub ) handleAreMerged (w http.ResponseWriter , r * http.Request ) {
29+ owner , repo := r .PathValue ("owner" ), r .PathValue ("repo" )
30+ if owner == "" || repo == "" {
2831 http .Error (w , "owner, repo, and number are required" , http .StatusBadRequest )
2932 return
3033 }
3134
32- num , err := strconv . Atoi ( numStr )
33- if err != nil {
35+ var req areMergedRequest
36+ if err := json . NewDecoder ( r . Body ). Decode ( & req ); err != nil {
3437 http .Error (w , err .Error (), http .StatusBadRequest )
3538 return
3639 }
3740
41+ changeNumToIdx := make (map [int ]int , len (req .IDs ))
42+ for i , id := range req .IDs {
43+ changeNumToIdx [int (id )] = i
44+ }
45+
3846 sh .mu .RLock ()
39- var (
40- merged bool
41- found bool
42- )
47+ merged := make ([]bool , len (sh .changes ))
4348 for _ , c := range sh .changes {
44- if c .Owner == owner && c .Repo == repo && c .Number == num {
45- merged = c .State == shamChangeMerged
46- found = true
47- break
49+ if c .Owner == owner && c .Repo == repo {
50+ idx , ok := changeNumToIdx [c .Number ]
51+ if ! ok {
52+ continue
53+ }
54+ merged [idx ] = c .State == shamChangeMerged
55+ delete (changeNumToIdx , c .Number )
56+
57+ if len (changeNumToIdx ) == 0 {
58+ break
59+ }
4860 }
4961 }
5062 sh .mu .RUnlock ()
5163
52- if ! found {
53- http .Error (w , "change not found" , http .StatusNotFound )
64+ if len (changeNumToIdx ) > 0 {
65+ w .WriteHeader (http .StatusNotFound )
66+ fmt .Fprintf (w , "changes not found: %v" , changeNumToIdx )
5467 return
5568 }
5669
5770 enc := json .NewEncoder (w )
5871 enc .SetIndent ("" , " " )
59- if err := enc .Encode (isMergedResponse {Merged : merged }); err != nil {
72+ if err := enc .Encode (areMergedResponse {Merged : merged }); err != nil {
6073 http .Error (w , err .Error (), http .StatusInternalServerError )
6174 }
6275}
6376
64- func (f * forgeRepository ) ChangeIsMerged (ctx context.Context , fid forge.ChangeID ) (bool , error ) {
65- id := fid .(ChangeID )
66- u := f .apiURL .JoinPath (f .owner , f .repo , "change" , strconv .Itoa (int (id )), "merged" )
67- var res isMergedResponse
68- if err := f .client .Get (ctx , u .String (), & res ); err != nil {
69- return false , fmt .Errorf ("is merged: %w" , err )
77+ func (f * forgeRepository ) ChangesAreMerged (ctx context.Context , fids []forge.ChangeID ) ([]bool , error ) {
78+ ids := make ([]ChangeID , len (fids ))
79+ for i , fid := range fids {
80+ ids [i ] = fid .(ChangeID )
81+ }
82+
83+ u := f .apiURL .JoinPath (f .owner , f .repo , "change" , "merged" )
84+ req := areMergedRequest {IDs : ids }
85+
86+ var res areMergedResponse
87+ if err := f .client .Post (ctx , u .String (), req , & res ); err != nil {
88+ return nil , fmt .Errorf ("are merged: %w" , err )
7089 }
7190 return res .Merged , nil
7291}
0 commit comments