Skip to content

Commit 965aa2a

Browse files
committed
Give user a link to create PR after push
1 parent bc06ab4 commit 965aa2a

File tree

4 files changed

+144
-0
lines changed

4 files changed

+144
-0
lines changed

cmd/hook.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"bufio"
99
"bytes"
1010
"fmt"
11+
"net/url"
1112
"os"
1213
"path/filepath"
1314
"strconv"
@@ -174,6 +175,7 @@ func runHookPostReceive(c *cli.Context) error {
174175
hookSetup("hooks/post-receive.log")
175176

176177
// the environment setted on serv command
178+
repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64)
177179
repoUser := os.Getenv(models.EnvRepoUsername)
178180
isUncyclo := (os.Getenv(models.EnvRepoIsUncyclo) == "true")
179181
repoName := os.Getenv(models.EnvRepoName)
@@ -211,6 +213,36 @@ func runHookPostReceive(c *cli.Context) error {
211213
}); err != nil {
212214
log.GitLogger.Error(2, "Update: %v", err)
213215
}
216+
217+
if strings.HasPrefix(refFullName, git.BranchPrefix) {
218+
branch := strings.TrimPrefix(refFullName, git.BranchPrefix)
219+
repository, err := private.GetRepository(repoID)
220+
if err != nil {
221+
log.GitLogger.Error(2, "get repository: %v", err)
222+
break
223+
}
224+
225+
// Don't propose to create new PR if it's default branch
226+
if branch == repository.DefaultBranch {
227+
break
228+
}
229+
230+
pr, err := private.ActivePullRequest(repoID, repository.DefaultBranch, branch)
231+
if err != nil {
232+
log.GitLogger.Error(2, "get active pr: %v", err)
233+
break
234+
}
235+
fmt.Fprintln(os.Stderr, "")
236+
if pr == nil {
237+
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", branch)
238+
fmt.Fprintf(os.Stderr, " %s%s/%s/compare/%s...%s\n", setting.AppURL, repoUser, repoName, url.QueryEscape(repository.DefaultBranch), url.QueryEscape(branch))
239+
} else {
240+
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
241+
fmt.Fprintf(os.Stderr, " %s%s/%s/pulls/%d\n", setting.AppURL, repoUser, repoName, pr.Index)
242+
}
243+
fmt.Fprintln(os.Stderr, "")
244+
}
245+
214246
}
215247

216248
return nil

modules/private/repository.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package private
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/url"
7+
8+
"code.gitea.io/gitea/models"
9+
"code.gitea.io/gitea/modules/log"
10+
"code.gitea.io/gitea/modules/setting"
11+
)
12+
13+
// GetRepository return the repository by its ID
14+
func GetRepository(repoID int64) (*models.Repository, error) {
15+
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/repository/%d", repoID)
16+
log.GitLogger.Trace("GetRepository: %s", reqURL)
17+
18+
resp, err := newInternalRequest(reqURL, "GET").Response()
19+
if err != nil {
20+
return nil, err
21+
}
22+
23+
var repository *models.Repository
24+
if err := json.NewDecoder(resp.Body).Decode(&repository); err != nil {
25+
return nil, err
26+
}
27+
28+
defer resp.Body.Close()
29+
30+
// All 2XX status codes are accepted and others will return an error
31+
if resp.StatusCode/100 != 2 {
32+
return nil, fmt.Errorf("failed to retrieve repository: %s", decodeJSONError(resp).Err)
33+
}
34+
35+
return repository, nil
36+
}
37+
38+
// ActivePullRequest returns an active pull request if it exists
39+
func ActivePullRequest(repoID int64, baseBranch, headBranch string) (*models.PullRequest, error) {
40+
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/active-pull-request/%d/%s...%s", repoID, url.QueryEscape(baseBranch), url.QueryEscape(headBranch))
41+
log.GitLogger.Trace("ActivePullRequest: %s", reqURL)
42+
43+
resp, err := newInternalRequest(reqURL, "GET").Response()
44+
if err != nil {
45+
log.GitLogger.Trace(err.Error())
46+
return nil, err
47+
}
48+
49+
var pr *models.PullRequest
50+
if err := json.NewDecoder(resp.Body).Decode(&pr); err != nil {
51+
return nil, err
52+
}
53+
54+
defer resp.Body.Close()
55+
56+
// All 2XX status codes are accepted and others will return an error
57+
if resp.StatusCode/100 != 2 {
58+
return nil, fmt.Errorf("failed to retrieve pull request: %s", decodeJSONError(resp).Err)
59+
}
60+
61+
return pr, nil
62+
}

routers/private/internal.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,7 @@ func RegisterRoutes(m *macaron.Macaron) {
4444
m.Post("/push/update", PushUpdate)
4545
m.Get("/protectedbranch/:pbid/:userid", CanUserPush)
4646
m.Get("/branch/:id/*", GetProtectedBranchBy)
47+
m.Get("/repository/:rid", GetRepository)
48+
m.Get("/active-pull-request/:rid/*", GetActivePullRequest)
4749
}, CheckInternalToken)
4850
}

routers/private/repository.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package private
2+
3+
import (
4+
"net/http"
5+
"net/url"
6+
"strings"
7+
8+
"code.gitea.io/gitea/models"
9+
macaron "gopkg.in/macaron.v1"
10+
)
11+
12+
// GetRepository return the default branch of a repository
13+
func GetRepository(ctx *macaron.Context) {
14+
repoID := ctx.ParamsInt64(":rid")
15+
repository, err := models.GetRepositoryByID(repoID)
16+
if err != nil {
17+
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
18+
"err": err.Error(),
19+
})
20+
return
21+
}
22+
23+
ctx.JSON(http.StatusOK, repository)
24+
}
25+
26+
// GetActivePullRequest return an active pull request when it exists or an empty object
27+
func GetActivePullRequest(ctx *macaron.Context) {
28+
repoID := ctx.ParamsInt64(":rid")
29+
30+
infoPath, err := url.QueryUnescape(ctx.Params("*"))
31+
if err != nil {
32+
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
33+
"err": err.Error(),
34+
})
35+
return
36+
}
37+
infos := strings.Split(infoPath, "...")
38+
39+
pr, err := models.GetUnmergedPullRequest(repoID, repoID, infos[1], infos[0])
40+
if err != nil && !models.IsErrPullRequestNotExist(err) {
41+
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
42+
"err": err.Error(),
43+
})
44+
return
45+
}
46+
47+
ctx.JSON(http.StatusOK, pr)
48+
}

0 commit comments

Comments
 (0)