Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Give user a link to create PR after push #4716

Merged
merged 5 commits into from
Oct 20, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions cmd/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"fmt"
"net/url"
"os"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -174,6 +175,7 @@ func runHookPostReceive(c *cli.Context) error {
hookSetup("hooks/post-receive.log")

// the environment setted on serv command
repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64)
repoUser := os.Getenv(models.EnvRepoUsername)
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
repoName := os.Getenv(models.EnvRepoName)
Expand Down Expand Up @@ -211,6 +213,47 @@ func runHookPostReceive(c *cli.Context) error {
}); err != nil {
log.GitLogger.Error(2, "Update: %v", err)
}

if strings.HasPrefix(refFullName, git.BranchPrefix) {
branch := strings.TrimPrefix(refFullName, git.BranchPrefix)
repo, pullRequestAllowed, err := private.GetRepository(repoID)
if err != nil {
log.GitLogger.Error(2, "get repo: %v", err)
break
}
if !pullRequestAllowed {
break
}

baseRepo := repo
if repo.IsFork {
baseRepo = repo.BaseRepo
}

if !repo.IsFork && branch == baseRepo.DefaultBranch {
break
}

pr, err := private.ActivePullRequest(baseRepo.ID, repo.ID, baseRepo.DefaultBranch, branch)
if err != nil {
log.GitLogger.Error(2, "get active pr: %v", err)
break
}

fmt.Fprintln(os.Stderr, "")
if pr == nil {
if repo.IsFork {
branch = fmt.Sprintf("%s:%s", repo.OwnerName, branch)
}
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", branch)
fmt.Fprintf(os.Stderr, " %s/compare/%s...%s\n", baseRepo.HTMLURL(), url.QueryEscape(baseRepo.DefaultBranch), url.QueryEscape(branch))
} else {
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
fmt.Fprintf(os.Stderr, " %s/pulls/%d\n", baseRepo.HTMLURL(), pr.Index)
}
fmt.Fprintln(os.Stderr, "")
}

}

return nil
Expand Down
64 changes: 64 additions & 0 deletions modules/private/repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package private
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment head

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed my PHPStorm template for the project, thanks.


import (
"encoding/json"
"fmt"
"net/url"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)

// GetRepository return the repository by its ID and a bool about if it's allowed to have PR
func GetRepository(repoID int64) (*models.Repository, bool, error) {
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/repository/%d", repoID)
log.GitLogger.Trace("GetRepository: %s", reqURL)

resp, err := newInternalRequest(reqURL, "GET").Response()
if err != nil {
return nil, false, err
}

var repoInfo struct {
Repository *models.Repository
AllowPullRequest bool
}
if err := json.NewDecoder(resp.Body).Decode(&repoInfo); err != nil {
return nil, false, err
}

defer resp.Body.Close()

// All 2XX status codes are accepted and others will return an error
if resp.StatusCode/100 != 2 {
return nil, false, fmt.Errorf("failed to retrieve repository: %s", decodeJSONError(resp).Err)
}

return repoInfo.Repository, repoInfo.AllowPullRequest, nil
}

// ActivePullRequest returns an active pull request if it exists
func ActivePullRequest(baseRepoID int64, headRepoID int64, baseBranch, headBranch string) (*models.PullRequest, error) {
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/active-pull-request?baseRepoID=%d&headRepoID=%d&baseBranch=%s&headBranch=%s", baseRepoID, headRepoID, url.QueryEscape(baseBranch), url.QueryEscape(headBranch))
log.GitLogger.Trace("ActivePullRequest: %s", reqURL)

resp, err := newInternalRequest(reqURL, "GET").Response()
if err != nil {
return nil, err
}

var pr *models.PullRequest
if err := json.NewDecoder(resp.Body).Decode(&pr); err != nil {
return nil, err
}

defer resp.Body.Close()

// All 2XX status codes are accepted and others will return an error
if resp.StatusCode/100 != 2 {
return nil, fmt.Errorf("failed to retrieve pull request: %s", decodeJSONError(resp).Err)
}

return pr, nil
}
2 changes: 2 additions & 0 deletions routers/private/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/push/update", PushUpdate)
m.Get("/protectedbranch/:pbid/:userid", CanUserPush)
m.Get("/branch/:id/*", GetProtectedBranchBy)
m.Get("/repository/:rid", GetRepository)
m.Get("/active-pull-request", GetActivePullRequest)
}, CheckInternalToken)
}
79 changes: 79 additions & 0 deletions routers/private/repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package private

import (
"net/http"
"net/url"

"code.gitea.io/gitea/models"
macaron "gopkg.in/macaron.v1"
)

// GetRepository return the default branch of a repository
func GetRepository(ctx *macaron.Context) {
repoID := ctx.ParamsInt64(":rid")
repository, err := models.GetRepositoryByID(repoID)
repository.MustOwnerName()
allowPulls := repository.AllowsPulls()
// put it back to nil because json unmarshal can't unmarshal it
repository.Units = nil

if err != nil {
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
"err": err.Error(),
})
return
}

if repository.IsFork {
repository.GetBaseRepo()
if err != nil {
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
"err": err.Error(),
})
return
}
repository.BaseRepo.MustOwnerName()
allowPulls = repository.BaseRepo.AllowsPulls()
// put it back to nil because json unmarshal can't unmarshal it
repository.BaseRepo.Units = nil
}

ctx.JSON(http.StatusOK, struct {
Repository *models.Repository
AllowPullRequest bool
}{
Repository: repository,
AllowPullRequest: allowPulls,
})
}

// GetActivePullRequest return an active pull request when it exists or an empty object
func GetActivePullRequest(ctx *macaron.Context) {
baseRepoID := ctx.QueryInt64("baseRepoID")
headRepoID := ctx.QueryInt64("headRepoID")
baseBranch, err := url.QueryUnescape(ctx.QueryTrim("baseBranch"))
if err != nil {
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
"err": err.Error(),
})
return
}

headBranch, err := url.QueryUnescape(ctx.QueryTrim("headBranch"))
if err != nil {
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
"err": err.Error(),
})
return
}

pr, err := models.GetUnmergedPullRequest(headRepoID, baseRepoID, headBranch, baseBranch)
if err != nil && !models.IsErrPullRequestNotExist(err) {
ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
"err": err.Error(),
})
return
}

ctx.JSON(http.StatusOK, pr)
}