-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
add API endpoints to update/delete protected branch #7093
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,12 @@ | |
package repo | ||
|
||
import ( | ||
"net/http" | ||
"strings" | ||
|
||
"code.gitea.io/gitea/models" | ||
"code.gitea.io/gitea/modules/auth" | ||
"code.gitea.io/gitea/modules/base" | ||
"code.gitea.io/gitea/modules/context" | ||
"code.gitea.io/gitea/modules/git" | ||
api "code.gitea.io/gitea/modules/structs" | ||
|
@@ -45,23 +51,30 @@ func GetBranch(ctx *context.APIContext) { | |
ctx.NotFound() | ||
return | ||
} | ||
branch, err := ctx.Repo.Repository.GetBranch(ctx.Repo.BranchName) | ||
branchName := ctx.Repo.BranchName | ||
branch, err := ctx.Repo.Repository.GetBranch(branchName) | ||
if err != nil { | ||
if git.IsErrBranchNotExist(err) { | ||
ctx.NotFound(err) | ||
} else { | ||
ctx.Error(500, "GetBranch", err) | ||
ctx.Error(http.StatusInternalServerError, "GetBranch", err) | ||
} | ||
return | ||
} | ||
|
||
protected, err := ctx.Repo.Repository.IsProtectedBranch(branchName, ctx.Repo.Owner) | ||
if err != nil { | ||
ctx.Error(http.StatusInternalServerError, "IsProtectedBranch", err) | ||
return | ||
} | ||
|
||
c, err := branch.GetCommit() | ||
if err != nil { | ||
ctx.Error(500, "GetCommit", err) | ||
ctx.Error(http.StatusInternalServerError, "GetCommit", err) | ||
return | ||
} | ||
|
||
ctx.JSON(200, convert.ToBranch(ctx.Repo.Repository, branch, c)) | ||
ctx.JSON(http.StatusOK, convert.ToBranch(ctx.Repo.Repository, branch, c, protected)) | ||
} | ||
|
||
// ListBranches list all the branches of a repository | ||
|
@@ -87,19 +100,204 @@ func ListBranches(ctx *context.APIContext) { | |
// "$ref": "#/responses/BranchList" | ||
branches, err := ctx.Repo.Repository.GetBranches() | ||
if err != nil { | ||
ctx.Error(500, "GetBranches", err) | ||
ctx.Error(http.StatusInternalServerError, "GetBranches", err) | ||
return | ||
} | ||
|
||
apiBranches := make([]*api.Branch, len(branches)) | ||
for i := range branches { | ||
c, err := branches[i].GetCommit() | ||
if err != nil { | ||
ctx.Error(500, "GetCommit", err) | ||
ctx.Error(http.StatusInternalServerError, "GetCommit", err) | ||
return | ||
} | ||
|
||
protected, err := ctx.Repo.Repository.IsProtectedBranch(branches[i].Name, ctx.Repo.Owner) | ||
if err != nil { | ||
ctx.Error(http.StatusInternalServerError, "IsProtectedBranch", err) | ||
return | ||
} | ||
|
||
apiBranches[i] = convert.ToBranch(ctx.Repo.Repository, branches[i], c, protected) | ||
} | ||
|
||
ctx.JSON(http.StatusOK, &apiBranches) | ||
} | ||
|
||
// GetProtectedBranchBy getting protected branch by ID/Name | ||
func GetProtectedBranchBy(ctx *context.APIContext) { | ||
// swagger:operation GET /repos/{owner}/{repo}/branches/{branch}/protection repository repoGetBranchProtection | ||
// --- | ||
// summary: Retrieve a specific branch protection from a repository | ||
// produces: | ||
// - application/json | ||
// parameters: | ||
// - name: owner | ||
// in: path | ||
// description: owner of the repo | ||
// type: string | ||
// required: true | ||
// - name: repo | ||
// in: path | ||
// description: name of the repo | ||
// type: string | ||
// required: true | ||
// - name: branch | ||
// in: path | ||
// description: branch to get | ||
// type: string | ||
// required: true | ||
// responses: | ||
// "200": | ||
// "$ref": "#/responses/Branch" | ||
protectBranch, err := models.GetProtectedBranchBy(ctx.Repo.Repository.ID, ctx.Params(":branch")) | ||
if err != nil { | ||
if !git.IsErrBranchNotExist(err) { | ||
ctx.Error(http.StatusInternalServerError, "GetProtectedBranchBy", err) | ||
return | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Xorm will not give an error if there is no row in the database, but an empty object.
|
||
apiBranches[i] = convert.ToBranch(ctx.Repo.Repository, branches[i], c) | ||
} | ||
ctx.JSON(http.StatusOK, protectBranch) | ||
} | ||
|
||
ctx.JSON(200, &apiBranches) | ||
// UpdateProtectBranch saves branch protection options of repository. | ||
// If ID is 0, it creates a new record. Otherwise, updates existing record. | ||
// This function also performs check if whitelist user and team's IDs have been changed | ||
// to avoid unnecessary whitelist delete and regenerate. | ||
func UpdateProtectBranch(ctx *context.APIContext, f auth.ProtectBranchForm) { | ||
// swagger:operation PUT /repos/{owner}/{repo}/branches/{branch}/protection repository repoUpdateProtectBranch | ||
// --- | ||
// summary: Update branch protection of a repository | ||
// produces: | ||
// - application/json | ||
// parameters: | ||
// - name: owner | ||
// in: path | ||
// description: owner of the repo | ||
// type: string | ||
// required: true | ||
// - name: repo | ||
// in: path | ||
// description: name of the repo | ||
// type: string | ||
// required: true | ||
// - name: branch | ||
// in: path | ||
// description: branch to update | ||
// type: string | ||
// required: true | ||
// - name: body | ||
// in: body | ||
// required: true | ||
// schema: | ||
// "$ref": "#/definitions/ProtectBranchForm" | ||
// responses: | ||
// "200": | ||
// "$ref": "#/responses/Branch" | ||
branch := ctx.Params(":branch") | ||
protectBranch, err := models.GetProtectedBranchBy(ctx.Repo.Repository.ID, branch) | ||
if err != nil { | ||
if !git.IsErrBranchNotExist(err) { | ||
ctx.Error(http.StatusInternalServerError, "GetProtectedBranchBy", err) | ||
return | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same problem as above with xorm. |
||
} | ||
|
||
if f.Protected { | ||
if protectBranch == nil { | ||
protectBranch = &models.ProtectedBranch{ | ||
RepoID: ctx.Repo.Repository.ID, | ||
BranchName: branch, | ||
} | ||
} | ||
|
||
var whitelistUsers, whitelistTeams, mergeWhitelistUsers, mergeWhitelistTeams, approvalsWhitelistUsers, approvalsWhitelistTeams []int64 | ||
protectBranch.EnableWhitelist = f.EnableWhitelist | ||
if strings.TrimSpace(f.WhitelistUsers) != "" { | ||
whitelistUsers, _ = base.StringsToInt64s(strings.Split(f.WhitelistUsers, ",")) | ||
} | ||
if strings.TrimSpace(f.WhitelistTeams) != "" { | ||
whitelistTeams, _ = base.StringsToInt64s(strings.Split(f.WhitelistTeams, ",")) | ||
} | ||
protectBranch.EnableMergeWhitelist = f.EnableMergeWhitelist | ||
if strings.TrimSpace(f.MergeWhitelistUsers) != "" { | ||
mergeWhitelistUsers, _ = base.StringsToInt64s(strings.Split(f.MergeWhitelistUsers, ",")) | ||
} | ||
if strings.TrimSpace(f.MergeWhitelistTeams) != "" { | ||
mergeWhitelistTeams, _ = base.StringsToInt64s(strings.Split(f.MergeWhitelistTeams, ",")) | ||
} | ||
protectBranch.RequiredApprovals = f.RequiredApprovals | ||
if strings.TrimSpace(f.ApprovalsWhitelistUsers) != "" { | ||
approvalsWhitelistUsers, _ = base.StringsToInt64s(strings.Split(f.ApprovalsWhitelistUsers, ",")) | ||
} | ||
if strings.TrimSpace(f.ApprovalsWhitelistTeams) != "" { | ||
approvalsWhitelistTeams, _ = base.StringsToInt64s(strings.Split(f.ApprovalsWhitelistTeams, ",")) | ||
} | ||
if err = models.UpdateProtectBranch(ctx.Repo.Repository, protectBranch, models.WhitelistOptions{ | ||
UserIDs: whitelistUsers, | ||
TeamIDs: whitelistTeams, | ||
MergeUserIDs: mergeWhitelistUsers, | ||
MergeTeamIDs: mergeWhitelistTeams, | ||
ApprovalsUserIDs: approvalsWhitelistUsers, | ||
ApprovalsTeamIDs: approvalsWhitelistTeams, | ||
}); err != nil { | ||
ctx.Error(http.StatusInternalServerError, "UpdateProtectBranch", err) | ||
return | ||
} | ||
} else if protectBranch != nil { | ||
if err := ctx.Repo.Repository.DeleteProtectedBranch(protectBranch.ID); err != nil { | ||
ctx.Error(http.StatusInternalServerError, "DeleteProtectedBranch", err) | ||
return | ||
} | ||
} | ||
ctx.JSON(http.StatusOK, protectBranch) | ||
} | ||
|
||
// DeleteProtectedBranch removes ProtectedBranch relation between the user and repository. | ||
func DeleteProtectedBranch(ctx *context.APIContext) { | ||
// swagger:operation DELETE /repos/{owner}/{repo}/branches/{branch}/protection repository repoDeleteProtectedBranch | ||
// --- | ||
// summary: Remove branch protection from a repository | ||
// produces: | ||
// - application/json | ||
// parameters: | ||
// - name: owner | ||
// in: path | ||
// description: owner of the repo | ||
// type: string | ||
// required: true | ||
// - name: repo | ||
// in: path | ||
// description: name of the repo | ||
// type: string | ||
// required: true | ||
// - name: branch | ||
// in: path | ||
// description: branch to remove protection | ||
// type: string | ||
// required: true | ||
// responses: | ||
// "204": | ||
// "$ref": "#/responses/empty" | ||
branchName := ctx.Params(":branch") | ||
protected, err := ctx.Repo.Repository.IsProtectedBranch(branchName, ctx.Repo.Owner) | ||
if err != nil { | ||
ctx.Error(http.StatusInternalServerError, "IsProtectedBranch", err) | ||
return | ||
} | ||
if !protected { | ||
ctx.Status(http.StatusNoContent) | ||
return | ||
} | ||
protectBranch, err := models.GetProtectedBranchBy(ctx.Repo.Repository.ID, branchName) | ||
if err != nil { | ||
if !git.IsErrBranchNotExist(err) { | ||
ctx.Error(http.StatusInternalServerError, "GetProtectedBranchBy", err) | ||
return | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same problem as above with xorm. Maybe ok to give 404 directly if protected branch doesn't exist. |
||
} | ||
if err = ctx.Repo.Repository.DeleteProtectedBranch(protectBranch.ID); err != nil { | ||
ctx.Error(http.StatusInternalServerError, "DeleteProtectedBranch", err) | ||
} | ||
ctx.Status(http.StatusNoContent) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need more details about the branch protection settings but not only a
bool
.