Skip to content

[API] Pull Requests #248

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

Merged
merged 5 commits into from
Dec 2, 2016
Merged
Show file tree
Hide file tree
Changes from all 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
22 changes: 22 additions & 0 deletions models/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,28 @@ func (err ErrPullRequestNotExist) Error() string {
err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBarcnh, err.BaseBranch)
}

// ErrPullRequestAlreadyExists represents a "PullRequestAlreadyExists"-error
type ErrPullRequestAlreadyExists struct {
Copy link
Member

Choose a reason for hiding this comment

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

golint

ID int64
IssueID int64
HeadRepoID int64
BaseRepoID int64
HeadBranch string
BaseBranch string
}

// IsErrPullRequestAlreadyExists checks if an error is a ErrPullRequestAlreadyExists.
func IsErrPullRequestAlreadyExists(err error) bool {
_, ok := err.(ErrPullRequestAlreadyExists)
return ok
}

// Error does pretty-printing :D
func (err ErrPullRequestAlreadyExists) Error() string {
return fmt.Sprintf("pull request already exists for these targets [id: %d, issue_id: %d, head_repo_id: %d, base_repo_id: %d, head_branch: %s, base_branch: %s]",
err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBranch, err.BaseBranch)
}

// _________ __
// \_ ___ \ ____ _____ _____ ____ _____/ |_
// / \ \/ / _ \ / \ / \_/ __ \ / \ __\
Expand Down
16 changes: 16 additions & 0 deletions models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,22 @@ func (issue *Issue) HTMLURL() string {
return fmt.Sprintf("%s/%s/%d", issue.Repo.HTMLURL(), path, issue.Index)
}

// DiffURL returns the absolute URL to this diff
func (issue *Issue) DiffURL() string {
if issue.IsPull {
return fmt.Sprintf("%s/pulls/%d.diff", issue.Repo.HTMLURL(), issue.Index)
}
return ""
}

// PatchURL returns the absolute URL to this patch
func (issue *Issue) PatchURL() string {
if issue.IsPull {
return fmt.Sprintf("%s/pulls/%d.patch", issue.Repo.HTMLURL(), issue.Index)
}
return ""
}

// State returns string representation of issue status.
func (issue *Issue) State() api.StateType {
if issue.IsClosed {
Expand Down
84 changes: 84 additions & 0 deletions models/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,26 @@ func (pr *PullRequest) LoadIssue() (err error) {
// Required - Issue
// Optional - Merger
func (pr *PullRequest) APIFormat() *api.PullRequest {

apiIssue := pr.Issue.APIFormat()
baseBranch, _ := pr.BaseRepo.GetBranch(pr.BaseBranch)
baseCommit, _ := baseBranch.GetCommit()
headBranch, _ := pr.HeadRepo.GetBranch(pr.HeadBranch)
headCommit, _ := headBranch.GetCommit()
apiBaseBranchInfo := &api.PRBranchInfo{
Name: pr.BaseBranch,
Ref: pr.BaseBranch,
Sha: baseCommit.ID.String(),
RepoID: pr.BaseRepoID,
Repository: pr.BaseRepo.APIFormat(nil),
}
apiHeadBranchInfo := &api.PRBranchInfo{
Name: pr.HeadBranch,
Ref: pr.HeadBranch,
Sha: headCommit.ID.String(),
RepoID: pr.HeadRepoID,
Repository: pr.HeadRepo.APIFormat(nil),
}
apiPullRequest := &api.PullRequest{
ID: pr.ID,
Index: pr.Index,
Expand All @@ -134,7 +153,12 @@ func (pr *PullRequest) APIFormat() *api.PullRequest {
State: apiIssue.State,
Comments: apiIssue.Comments,
HTMLURL: pr.Issue.HTMLURL(),
DiffURL: pr.Issue.DiffURL(),
PatchURL: pr.Issue.PatchURL(),
HasMerged: pr.HasMerged,
Base: apiBaseBranchInfo,
Head: apiHeadBranchInfo,
MergeBase: pr.MergeBase,
}

if pr.Status != PullRequestStatusChecking {
Expand Down Expand Up @@ -472,6 +496,46 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
return nil
}

// PullRequestsOptions holds the options for PRs
type PullRequestsOptions struct {
Page int
State string
SortType string
Labels []string
MilestoneID int64
}

func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) *xorm.Session {
sess := x.Where("pull_request.base_repo_id=?", baseRepoID)

sess.Join("INNER", "issue", "pull_request.issue_id = issue.id")
switch opts.State {
case "closed", "open":
sess.And("issue.is_closed=?", opts.State == "closed")
}

return sess
}

// PullRequests returns all pull requests for a base Repo by the given conditions
func PullRequests(baseRepoID int64, opts *PullRequestsOptions) ([]*PullRequest, int64, error) {
if opts.Page <= 0 {
opts.Page = 1
}

countSession := listPullRequestStatement(baseRepoID, opts)
maxResults, err := countSession.Count(new(PullRequest))
if err != nil {
log.Error(4, "Count PRs", err)
return nil, maxResults, err
}

prs := make([]*PullRequest, 0, ItemsPerPage)
findSession := listPullRequestStatement(baseRepoID, opts)
findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage)
return prs, maxResults, findSession.Find(&prs)
}

// GetUnmergedPullRequest returnss a pull request that is open and has not been merged
// by given head/base and repo/branch.
func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch string) (*PullRequest, error) {
Expand Down Expand Up @@ -512,6 +576,26 @@ func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequ
Find(&prs)
}

// GetPullRequestByIndex returns a pull request by the given index
func GetPullRequestByIndex(repoID int64, index int64) (*PullRequest, error) {
pr := &PullRequest{
BaseRepoID: repoID,
Index: index,
}

has, err := x.Get(pr)
if err != nil {
return nil, err
} else if !has {
return nil, ErrPullRequestNotExist{0, repoID, index, 0, "", ""}
}

pr.LoadAttributes()
pr.LoadIssue()

return pr, nil
}

func getPullRequestByID(e Engine, id int64) (*PullRequest, error) {
pr := new(PullRequest)
has, err := e.Id(id).Get(pr)
Expand Down
22 changes: 22 additions & 0 deletions modules/context/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"strings"

"code.gitea.io/git"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
Expand Down Expand Up @@ -103,3 +104,24 @@ func ExtractOwnerAndRepo() macaron.Handler {
ctx.Data["Repository"] = repo
}
}

// ReferencesGitRepo injects the GitRepo into the Context
func ReferencesGitRepo() macaron.Handler {
return func(ctx *APIContext) {
// Empty repository does not have reference information.
if ctx.Repo.Repository.IsBare {
return
}

// For API calls.
if ctx.Repo.GitRepo == nil {
repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
ctx.Error(500, "RepoRef Invalid repo "+repoPath, err)
return
}
ctx.Repo.GitRepo = gitRepo
}
}
}
15 changes: 15 additions & 0 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ func mustEnableIssues(ctx *context.APIContext) {
}
}

func mustAllowPulls(ctx *context.Context) {
if !ctx.Repo.Repository.AllowsPulls() {
ctx.Status(404)
return
}
}

// RegisterRoutes registers all v1 APIs routes to web application.
// FIXME: custom form error response
func RegisterRoutes(m *macaron.Macaron) {
Expand Down Expand Up @@ -305,6 +312,14 @@ func RegisterRoutes(m *macaron.Macaron) {
Delete(reqRepoWriter(), repo.DeleteMilestone)
})
m.Get("/editorconfig/:filename", context.RepoRef(), repo.GetEditorconfig)
m.Group("/pulls", func() {
m.Combo("").Get(bind(api.ListPullRequestsOptions{}), repo.ListPullRequests).Post(reqRepoWriter(), bind(api.CreatePullRequestOption{}), repo.CreatePullRequest)
m.Group("/:index", func() {
m.Combo("").Get(repo.GetPullRequest).Patch(reqRepoWriter(), bind(api.EditPullRequestOption{}), repo.EditPullRequest)
m.Combo("/merge").Get(repo.IsPullRequestMerged).Post(reqRepoWriter(), repo.MergePullRequest)
})

}, mustAllowPulls, context.ReferencesGitRepo())
}, repoAssignment())
}, reqToken())

Expand Down
Loading