2016-01-28 22:49:05 +03:00
// Copyright 2016 The Gogs Authors. All rights reserved.
2019-04-19 15:17:27 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2016-01-15 21:24:03 +03:00
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
import (
2021-06-07 17:52:59 +03:00
"errors"
2020-04-19 05:38:09 +03:00
"fmt"
2019-12-20 20:07:12 +03:00
"net/http"
2020-02-13 02:19:35 +03:00
"code.gitea.io/gitea/models"
2021-11-24 12:49:20 +03:00
user_model "code.gitea.io/gitea/models/user"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/context"
2019-11-10 07:41:51 +03:00
"code.gitea.io/gitea/modules/convert"
2019-04-19 15:17:27 +03:00
"code.gitea.io/gitea/modules/git"
2019-05-11 13:21:34 +03:00
api "code.gitea.io/gitea/modules/structs"
2021-01-26 18:36:53 +03:00
"code.gitea.io/gitea/modules/web"
2021-02-03 22:06:13 +03:00
"code.gitea.io/gitea/routers/api/v1/utils"
2020-10-13 21:50:57 +03:00
pull_service "code.gitea.io/gitea/services/pull"
2020-09-11 17:14:48 +03:00
repo_service "code.gitea.io/gitea/services/repository"
2016-01-15 21:24:03 +03:00
)
2016-11-24 10:04:31 +03:00
// GetBranch get a branch of a repository
2016-03-14 01:49:16 +03:00
func GetBranch ( ctx * context . APIContext ) {
2017-11-13 10:02:25 +03:00
// swagger:operation GET /repos/{owner}/{repo}/branches/{branch} repository repoGetBranch
// ---
2019-11-16 22:39:18 +03:00
// summary: Retrieve a specific branch from a repository, including its effective branch protection
2017-11-13 10:02:25 +03:00
// 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"
2020-11-14 19:13:55 +03:00
// "404":
// "$ref": "#/responses/notFound"
2019-12-20 20:07:12 +03:00
2020-11-14 19:13:55 +03:00
branchName := ctx . Params ( "*" )
2021-11-24 10:56:24 +03:00
branch , err := repo_service . GetBranch ( ctx . Repo . Repository , branchName )
2016-01-15 21:24:03 +03:00
if err != nil {
2019-04-19 15:17:27 +03:00
if git . IsErrBranchNotExist ( err ) {
2019-03-19 05:29:43 +03:00
ctx . NotFound ( err )
2017-06-11 05:57:28 +03:00
} else {
2019-12-20 20:07:12 +03:00
ctx . Error ( http . StatusInternalServerError , "GetBranch" , err )
2017-06-11 05:57:28 +03:00
}
2016-01-15 21:24:03 +03:00
return
}
2016-02-03 01:07:40 +03:00
2016-01-15 21:24:03 +03:00
c , err := branch . GetCommit ( )
if err != nil {
2019-12-20 20:07:12 +03:00
ctx . Error ( http . StatusInternalServerError , "GetCommit" , err )
2016-01-15 21:24:03 +03:00
return
}
2016-02-03 01:07:40 +03:00
2020-11-14 19:13:55 +03:00
branchProtection , err := ctx . Repo . Repository . GetBranchProtection ( branchName )
2019-11-16 22:39:18 +03:00
if err != nil {
2019-12-20 20:07:12 +03:00
ctx . Error ( http . StatusInternalServerError , "GetBranchProtection" , err )
2019-11-16 22:39:18 +03:00
return
}
2020-03-21 06:41:33 +03:00
br , err := convert . ToBranch ( ctx . Repo . Repository , branch , c , branchProtection , ctx . User , ctx . Repo . IsAdmin ( ) )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "convert.ToBranch" , err )
return
}
ctx . JSON ( http . StatusOK , br )
2016-01-15 21:24:03 +03:00
}
2020-04-19 05:38:09 +03:00
// DeleteBranch get a branch of a repository
func DeleteBranch ( ctx * context . APIContext ) {
// swagger:operation DELETE /repos/{owner}/{repo}/branches/{branch} repository repoDeleteBranch
// ---
// summary: Delete a specific branch 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 delete
// type: string
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
// "403":
// "$ref": "#/responses/error"
2020-11-14 19:13:55 +03:00
// "404":
// "$ref": "#/responses/notFound"
2020-04-19 05:38:09 +03:00
2020-11-14 19:13:55 +03:00
branchName := ctx . Params ( "*" )
2020-04-19 05:38:09 +03:00
2021-06-07 17:52:59 +03:00
if err := repo_service . DeleteBranch ( ctx . User , ctx . Repo . Repository , ctx . Repo . GitRepo , branchName ) ; err != nil {
switch {
case git . IsErrBranchNotExist ( err ) :
2020-04-19 05:38:09 +03:00
ctx . NotFound ( err )
2021-06-07 17:52:59 +03:00
case errors . Is ( err , repo_service . ErrBranchIsDefault ) :
ctx . Error ( http . StatusForbidden , "DefaultBranch" , fmt . Errorf ( "can not delete default branch" ) )
case errors . Is ( err , repo_service . ErrBranchIsProtected ) :
ctx . Error ( http . StatusForbidden , "IsProtectedBranch" , fmt . Errorf ( "branch protected" ) )
default :
ctx . Error ( http . StatusInternalServerError , "DeleteBranch" , err )
2020-04-19 05:38:09 +03:00
}
return
}
ctx . Status ( http . StatusNoContent )
}
2020-05-29 21:16:20 +03:00
// CreateBranch creates a branch for a user's repository
2021-01-26 18:36:53 +03:00
func CreateBranch ( ctx * context . APIContext ) {
2020-05-29 21:16:20 +03:00
// swagger:operation POST /repos/{owner}/{repo}/branches repository repoCreateBranch
// ---
// summary: Create a branch
// consumes:
// - application/json
// 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: body
// in: body
// schema:
// "$ref": "#/definitions/CreateBranchRepoOption"
// responses:
// "201":
// "$ref": "#/responses/Branch"
// "404":
// description: The old branch does not exist.
// "409":
// description: The branch with the same name already exists.
2021-01-26 18:36:53 +03:00
opt := web . GetForm ( ctx ) . ( * api . CreateBranchRepoOption )
2020-05-29 21:16:20 +03:00
if ctx . Repo . Repository . IsEmpty {
ctx . Error ( http . StatusNotFound , "" , "Git Repository is empty." )
return
}
if len ( opt . OldBranchName ) == 0 {
opt . OldBranchName = ctx . Repo . Repository . DefaultBranch
}
2021-11-17 18:17:31 +03:00
err := repo_service . CreateNewBranch ( ctx . User , ctx . Repo . Repository , opt . OldBranchName , opt . BranchName )
2020-05-29 21:16:20 +03:00
if err != nil {
if models . IsErrBranchDoesNotExist ( err ) {
ctx . Error ( http . StatusNotFound , "" , "The old branch does not exist" )
}
if models . IsErrTagAlreadyExists ( err ) {
ctx . Error ( http . StatusConflict , "" , "The branch with the same tag already exists." )
} else if models . IsErrBranchAlreadyExists ( err ) || git . IsErrPushOutOfDate ( err ) {
ctx . Error ( http . StatusConflict , "" , "The branch already exists." )
} else if models . IsErrBranchNameConflict ( err ) {
ctx . Error ( http . StatusConflict , "" , "The branch with the same name already exists." )
} else {
ctx . Error ( http . StatusInternalServerError , "CreateRepoBranch" , err )
}
return
}
2021-11-24 10:56:24 +03:00
branch , err := repo_service . GetBranch ( ctx . Repo . Repository , opt . BranchName )
2020-05-29 21:16:20 +03:00
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetBranch" , err )
return
}
commit , err := branch . GetCommit ( )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetCommit" , err )
return
}
branchProtection , err := ctx . Repo . Repository . GetBranchProtection ( branch . Name )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetBranchProtection" , err )
return
}
br , err := convert . ToBranch ( ctx . Repo . Repository , branch , commit , branchProtection , ctx . User , ctx . Repo . IsAdmin ( ) )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "convert.ToBranch" , err )
return
}
ctx . JSON ( http . StatusCreated , br )
}
2016-11-24 10:04:31 +03:00
// ListBranches list all the branches of a repository
2016-03-14 01:49:16 +03:00
func ListBranches ( ctx * context . APIContext ) {
2017-11-13 10:02:25 +03:00
// swagger:operation GET /repos/{owner}/{repo}/branches repository repoListBranches
// ---
// summary: List a repository's branches
// 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
2021-02-03 22:06:13 +03:00
// - name: page
// in: query
// description: page number of results to return (1-based)
// type: integer
// - name: limit
// in: query
// description: page size of results
// type: integer
2017-11-13 10:02:25 +03:00
// responses:
// "200":
// "$ref": "#/responses/BranchList"
2019-12-20 20:07:12 +03:00
2021-02-03 22:06:13 +03:00
listOptions := utils . GetListOptions ( ctx )
skip , _ := listOptions . GetStartEnd ( )
2021-11-17 18:17:31 +03:00
branches , totalNumOfBranches , err := repo_service . GetBranches ( ctx . Repo . Repository , skip , listOptions . PageSize )
2016-01-15 21:24:03 +03:00
if err != nil {
2019-12-20 20:07:12 +03:00
ctx . Error ( http . StatusInternalServerError , "GetBranches" , err )
2016-01-15 21:24:03 +03:00
return
}
2016-02-03 01:07:40 +03:00
apiBranches := make ( [ ] * api . Branch , len ( branches ) )
for i := range branches {
c , err := branches [ i ] . GetCommit ( )
2016-01-15 21:24:03 +03:00
if err != nil {
2019-12-20 20:07:12 +03:00
ctx . Error ( http . StatusInternalServerError , "GetCommit" , err )
2016-01-16 12:36:16 +03:00
return
2016-01-15 21:24:03 +03:00
}
2019-11-16 22:39:18 +03:00
branchProtection , err := ctx . Repo . Repository . GetBranchProtection ( branches [ i ] . Name )
if err != nil {
2019-12-20 20:07:12 +03:00
ctx . Error ( http . StatusInternalServerError , "GetBranchProtection" , err )
2019-11-16 22:39:18 +03:00
return
}
2020-03-21 06:41:33 +03:00
apiBranches [ i ] , err = convert . ToBranch ( ctx . Repo . Repository , branches [ i ] , c , branchProtection , ctx . User , ctx . Repo . IsAdmin ( ) )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "convert.ToBranch" , err )
return
}
2016-01-15 21:24:03 +03:00
}
2016-02-03 01:07:40 +03:00
2021-08-12 15:43:08 +03:00
ctx . SetLinkHeader ( totalNumOfBranches , listOptions . PageSize )
ctx . SetTotalCountHeader ( int64 ( totalNumOfBranches ) )
2019-12-20 20:07:12 +03:00
ctx . JSON ( http . StatusOK , & apiBranches )
2016-01-15 21:24:03 +03:00
}
2020-02-13 02:19:35 +03:00
// GetBranchProtection gets a branch protection
func GetBranchProtection ( ctx * context . APIContext ) {
// swagger:operation GET /repos/{owner}/{repo}/branch_protections/{name} repository repoGetBranchProtection
// ---
// summary: Get a specific branch protection for the 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: name
// in: path
// description: name of protected branch
// type: string
// required: true
// responses:
// "200":
// "$ref": "#/responses/BranchProtection"
// "404":
// "$ref": "#/responses/notFound"
repo := ctx . Repo . Repository
bpName := ctx . Params ( ":name" )
bp , err := models . GetProtectedBranchBy ( repo . ID , bpName )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetProtectedBranchByID" , err )
return
}
if bp == nil || bp . RepoID != repo . ID {
ctx . NotFound ( )
return
}
ctx . JSON ( http . StatusOK , convert . ToBranchProtection ( bp ) )
}
// ListBranchProtections list branch protections for a repo
func ListBranchProtections ( ctx * context . APIContext ) {
// swagger:operation GET /repos/{owner}/{repo}/branch_protections repository repoListBranchProtection
// ---
// summary: List branch protections for 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
// responses:
// "200":
// "$ref": "#/responses/BranchProtectionList"
repo := ctx . Repo . Repository
bps , err := repo . GetProtectedBranches ( )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetProtectedBranches" , err )
return
}
apiBps := make ( [ ] * api . BranchProtection , len ( bps ) )
for i := range bps {
apiBps [ i ] = convert . ToBranchProtection ( bps [ i ] )
}
ctx . JSON ( http . StatusOK , apiBps )
}
// CreateBranchProtection creates a branch protection for a repo
2021-01-26 18:36:53 +03:00
func CreateBranchProtection ( ctx * context . APIContext ) {
2020-02-13 02:19:35 +03:00
// swagger:operation POST /repos/{owner}/{repo}/branch_protections repository repoCreateBranchProtection
// ---
// summary: Create a branch protections for a repository
// consumes:
// - application/json
// 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: body
// in: body
// schema:
// "$ref": "#/definitions/CreateBranchProtectionOption"
// responses:
// "201":
// "$ref": "#/responses/BranchProtection"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
// "422":
// "$ref": "#/responses/validationError"
2021-01-26 18:36:53 +03:00
form := web . GetForm ( ctx ) . ( * api . CreateBranchProtectionOption )
2020-02-13 02:19:35 +03:00
repo := ctx . Repo . Repository
// Currently protection must match an actual branch
2021-11-30 23:06:32 +03:00
if ! git . IsBranchExist ( ctx . Req . Context ( ) , ctx . Repo . Repository . RepoPath ( ) , form . BranchName ) {
2020-02-13 02:19:35 +03:00
ctx . NotFound ( )
return
}
protectBranch , err := models . GetProtectedBranchBy ( repo . ID , form . BranchName )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetProtectBranchOfRepoByName" , err )
return
} else if protectBranch != nil {
ctx . Error ( http . StatusForbidden , "Create branch protection" , "Branch protection already exist" )
return
}
var requiredApprovals int64
if form . RequiredApprovals > 0 {
requiredApprovals = form . RequiredApprovals
}
2021-11-24 12:49:20 +03:00
whitelistUsers , err := user_model . GetUserIDsByNames ( form . PushWhitelistUsernames , false )
2020-02-13 02:19:35 +03:00
if err != nil {
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
2020-02-13 02:19:35 +03:00
ctx . Error ( http . StatusUnprocessableEntity , "User does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetUserIDsByNames" , err )
return
}
2021-11-24 12:49:20 +03:00
mergeWhitelistUsers , err := user_model . GetUserIDsByNames ( form . MergeWhitelistUsernames , false )
2020-02-13 02:19:35 +03:00
if err != nil {
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
2020-02-13 02:19:35 +03:00
ctx . Error ( http . StatusUnprocessableEntity , "User does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetUserIDsByNames" , err )
return
}
2021-11-24 12:49:20 +03:00
approvalsWhitelistUsers , err := user_model . GetUserIDsByNames ( form . ApprovalsWhitelistUsernames , false )
2020-02-13 02:19:35 +03:00
if err != nil {
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
2020-02-13 02:19:35 +03:00
ctx . Error ( http . StatusUnprocessableEntity , "User does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetUserIDsByNames" , err )
return
}
var whitelistTeams , mergeWhitelistTeams , approvalsWhitelistTeams [ ] int64
if repo . Owner . IsOrganization ( ) {
whitelistTeams , err = models . GetTeamIDsByNames ( repo . OwnerID , form . PushWhitelistTeams , false )
if err != nil {
if models . IsErrTeamNotExist ( err ) {
ctx . Error ( http . StatusUnprocessableEntity , "Team does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetTeamIDsByNames" , err )
return
}
mergeWhitelistTeams , err = models . GetTeamIDsByNames ( repo . OwnerID , form . MergeWhitelistTeams , false )
if err != nil {
if models . IsErrTeamNotExist ( err ) {
ctx . Error ( http . StatusUnprocessableEntity , "Team does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetTeamIDsByNames" , err )
return
}
approvalsWhitelistTeams , err = models . GetTeamIDsByNames ( repo . OwnerID , form . ApprovalsWhitelistTeams , false )
if err != nil {
if models . IsErrTeamNotExist ( err ) {
ctx . Error ( http . StatusUnprocessableEntity , "Team does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetTeamIDsByNames" , err )
return
}
}
protectBranch = & models . ProtectedBranch {
2020-11-28 22:30:46 +03:00
RepoID : ctx . Repo . Repository . ID ,
BranchName : form . BranchName ,
CanPush : form . EnablePush ,
EnableWhitelist : form . EnablePush && form . EnablePushWhitelist ,
EnableMergeWhitelist : form . EnableMergeWhitelist ,
WhitelistDeployKeys : form . EnablePush && form . EnablePushWhitelist && form . PushWhitelistDeployKeys ,
EnableStatusCheck : form . EnableStatusCheck ,
StatusCheckContexts : form . StatusCheckContexts ,
EnableApprovalsWhitelist : form . EnableApprovalsWhitelist ,
RequiredApprovals : requiredApprovals ,
BlockOnRejectedReviews : form . BlockOnRejectedReviews ,
BlockOnOfficialReviewRequests : form . BlockOnOfficialReviewRequests ,
DismissStaleApprovals : form . DismissStaleApprovals ,
RequireSignedCommits : form . RequireSignedCommits ,
ProtectedFilePatterns : form . ProtectedFilePatterns ,
2021-09-11 17:21:17 +03:00
UnprotectedFilePatterns : form . UnprotectedFilePatterns ,
2020-11-28 22:30:46 +03:00
BlockOnOutdatedBranch : form . BlockOnOutdatedBranch ,
2020-02-13 02:19:35 +03:00
}
err = models . UpdateProtectBranch ( ctx . Repo . Repository , protectBranch , models . WhitelistOptions {
UserIDs : whitelistUsers ,
TeamIDs : whitelistTeams ,
MergeUserIDs : mergeWhitelistUsers ,
MergeTeamIDs : mergeWhitelistTeams ,
ApprovalsUserIDs : approvalsWhitelistUsers ,
ApprovalsTeamIDs : approvalsWhitelistTeams ,
} )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "UpdateProtectBranch" , err )
return
}
2020-10-13 21:50:57 +03:00
if err = pull_service . CheckPrsForBaseBranch ( ctx . Repo . Repository , protectBranch . BranchName ) ; err != nil {
ctx . Error ( http . StatusInternalServerError , "CheckPrsForBaseBranch" , err )
return
}
2020-02-13 02:19:35 +03:00
// Reload from db to get all whitelists
bp , err := models . GetProtectedBranchBy ( ctx . Repo . Repository . ID , form . BranchName )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetProtectedBranchByID" , err )
return
}
if bp == nil || bp . RepoID != ctx . Repo . Repository . ID {
ctx . Error ( http . StatusInternalServerError , "New branch protection not found" , err )
return
}
ctx . JSON ( http . StatusCreated , convert . ToBranchProtection ( bp ) )
}
// EditBranchProtection edits a branch protection for a repo
2021-01-26 18:36:53 +03:00
func EditBranchProtection ( ctx * context . APIContext ) {
2020-02-13 02:19:35 +03:00
// swagger:operation PATCH /repos/{owner}/{repo}/branch_protections/{name} repository repoEditBranchProtection
// ---
// summary: Edit a branch protections for a repository. Only fields that are set will be changed
// consumes:
// - application/json
// 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: name
// in: path
// description: name of protected branch
// type: string
// required: true
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/EditBranchProtectionOption"
// responses:
// "200":
// "$ref": "#/responses/BranchProtection"
// "404":
// "$ref": "#/responses/notFound"
// "422":
// "$ref": "#/responses/validationError"
2021-01-26 18:36:53 +03:00
form := web . GetForm ( ctx ) . ( * api . EditBranchProtectionOption )
2020-02-13 02:19:35 +03:00
repo := ctx . Repo . Repository
bpName := ctx . Params ( ":name" )
protectBranch , err := models . GetProtectedBranchBy ( repo . ID , bpName )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetProtectedBranchByID" , err )
return
}
if protectBranch == nil || protectBranch . RepoID != repo . ID {
ctx . NotFound ( )
return
}
if form . EnablePush != nil {
if ! * form . EnablePush {
protectBranch . CanPush = false
protectBranch . EnableWhitelist = false
protectBranch . WhitelistDeployKeys = false
} else {
protectBranch . CanPush = true
if form . EnablePushWhitelist != nil {
if ! * form . EnablePushWhitelist {
protectBranch . EnableWhitelist = false
protectBranch . WhitelistDeployKeys = false
} else {
protectBranch . EnableWhitelist = true
if form . PushWhitelistDeployKeys != nil {
protectBranch . WhitelistDeployKeys = * form . PushWhitelistDeployKeys
}
}
}
}
}
if form . EnableMergeWhitelist != nil {
protectBranch . EnableMergeWhitelist = * form . EnableMergeWhitelist
}
if form . EnableStatusCheck != nil {
protectBranch . EnableStatusCheck = * form . EnableStatusCheck
}
if protectBranch . EnableStatusCheck {
protectBranch . StatusCheckContexts = form . StatusCheckContexts
}
if form . RequiredApprovals != nil && * form . RequiredApprovals >= 0 {
protectBranch . RequiredApprovals = * form . RequiredApprovals
}
if form . EnableApprovalsWhitelist != nil {
protectBranch . EnableApprovalsWhitelist = * form . EnableApprovalsWhitelist
}
if form . BlockOnRejectedReviews != nil {
protectBranch . BlockOnRejectedReviews = * form . BlockOnRejectedReviews
}
2020-11-28 22:30:46 +03:00
if form . BlockOnOfficialReviewRequests != nil {
protectBranch . BlockOnOfficialReviewRequests = * form . BlockOnOfficialReviewRequests
}
2020-02-13 02:19:35 +03:00
if form . DismissStaleApprovals != nil {
protectBranch . DismissStaleApprovals = * form . DismissStaleApprovals
}
if form . RequireSignedCommits != nil {
protectBranch . RequireSignedCommits = * form . RequireSignedCommits
}
2020-03-27 01:26:34 +03:00
if form . ProtectedFilePatterns != nil {
protectBranch . ProtectedFilePatterns = * form . ProtectedFilePatterns
}
2021-09-11 17:21:17 +03:00
if form . UnprotectedFilePatterns != nil {
protectBranch . UnprotectedFilePatterns = * form . UnprotectedFilePatterns
}
2020-04-17 04:00:36 +03:00
if form . BlockOnOutdatedBranch != nil {
protectBranch . BlockOnOutdatedBranch = * form . BlockOnOutdatedBranch
}
2020-02-13 02:19:35 +03:00
var whitelistUsers [ ] int64
if form . PushWhitelistUsernames != nil {
2021-11-24 12:49:20 +03:00
whitelistUsers , err = user_model . GetUserIDsByNames ( form . PushWhitelistUsernames , false )
2020-02-13 02:19:35 +03:00
if err != nil {
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
2020-02-13 02:19:35 +03:00
ctx . Error ( http . StatusUnprocessableEntity , "User does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetUserIDsByNames" , err )
return
}
} else {
whitelistUsers = protectBranch . WhitelistUserIDs
}
var mergeWhitelistUsers [ ] int64
if form . MergeWhitelistUsernames != nil {
2021-11-24 12:49:20 +03:00
mergeWhitelistUsers , err = user_model . GetUserIDsByNames ( form . MergeWhitelistUsernames , false )
2020-02-13 02:19:35 +03:00
if err != nil {
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
2020-02-13 02:19:35 +03:00
ctx . Error ( http . StatusUnprocessableEntity , "User does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetUserIDsByNames" , err )
return
}
} else {
mergeWhitelistUsers = protectBranch . MergeWhitelistUserIDs
}
var approvalsWhitelistUsers [ ] int64
if form . ApprovalsWhitelistUsernames != nil {
2021-11-24 12:49:20 +03:00
approvalsWhitelistUsers , err = user_model . GetUserIDsByNames ( form . ApprovalsWhitelistUsernames , false )
2020-02-13 02:19:35 +03:00
if err != nil {
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
2020-02-13 02:19:35 +03:00
ctx . Error ( http . StatusUnprocessableEntity , "User does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetUserIDsByNames" , err )
return
}
} else {
approvalsWhitelistUsers = protectBranch . ApprovalsWhitelistUserIDs
}
var whitelistTeams , mergeWhitelistTeams , approvalsWhitelistTeams [ ] int64
if repo . Owner . IsOrganization ( ) {
if form . PushWhitelistTeams != nil {
whitelistTeams , err = models . GetTeamIDsByNames ( repo . OwnerID , form . PushWhitelistTeams , false )
if err != nil {
if models . IsErrTeamNotExist ( err ) {
ctx . Error ( http . StatusUnprocessableEntity , "Team does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetTeamIDsByNames" , err )
return
}
} else {
whitelistTeams = protectBranch . WhitelistTeamIDs
}
if form . MergeWhitelistTeams != nil {
mergeWhitelistTeams , err = models . GetTeamIDsByNames ( repo . OwnerID , form . MergeWhitelistTeams , false )
if err != nil {
if models . IsErrTeamNotExist ( err ) {
ctx . Error ( http . StatusUnprocessableEntity , "Team does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetTeamIDsByNames" , err )
return
}
} else {
mergeWhitelistTeams = protectBranch . MergeWhitelistTeamIDs
}
if form . ApprovalsWhitelistTeams != nil {
approvalsWhitelistTeams , err = models . GetTeamIDsByNames ( repo . OwnerID , form . ApprovalsWhitelistTeams , false )
if err != nil {
if models . IsErrTeamNotExist ( err ) {
ctx . Error ( http . StatusUnprocessableEntity , "Team does not exist" , err )
return
}
ctx . Error ( http . StatusInternalServerError , "GetTeamIDsByNames" , err )
return
}
} else {
approvalsWhitelistTeams = protectBranch . ApprovalsWhitelistTeamIDs
}
}
err = models . UpdateProtectBranch ( ctx . Repo . Repository , protectBranch , models . WhitelistOptions {
UserIDs : whitelistUsers ,
TeamIDs : whitelistTeams ,
MergeUserIDs : mergeWhitelistUsers ,
MergeTeamIDs : mergeWhitelistTeams ,
ApprovalsUserIDs : approvalsWhitelistUsers ,
ApprovalsTeamIDs : approvalsWhitelistTeams ,
} )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "UpdateProtectBranch" , err )
return
}
2020-10-13 21:50:57 +03:00
if err = pull_service . CheckPrsForBaseBranch ( ctx . Repo . Repository , protectBranch . BranchName ) ; err != nil {
ctx . Error ( http . StatusInternalServerError , "CheckPrsForBaseBranch" , err )
return
}
2020-02-13 02:19:35 +03:00
// Reload from db to ensure get all whitelists
bp , err := models . GetProtectedBranchBy ( repo . ID , bpName )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetProtectedBranchBy" , err )
return
}
if bp == nil || bp . RepoID != ctx . Repo . Repository . ID {
ctx . Error ( http . StatusInternalServerError , "New branch protection not found" , err )
return
}
ctx . JSON ( http . StatusOK , convert . ToBranchProtection ( bp ) )
}
// DeleteBranchProtection deletes a branch protection for a repo
func DeleteBranchProtection ( ctx * context . APIContext ) {
// swagger:operation DELETE /repos/{owner}/{repo}/branch_protections/{name} repository repoDeleteBranchProtection
// ---
// summary: Delete a specific branch protection for the 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: name
// in: path
// description: name of protected branch
// type: string
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
// "404":
// "$ref": "#/responses/notFound"
repo := ctx . Repo . Repository
bpName := ctx . Params ( ":name" )
bp , err := models . GetProtectedBranchBy ( repo . ID , bpName )
if err != nil {
ctx . Error ( http . StatusInternalServerError , "GetProtectedBranchByID" , err )
return
}
if bp == nil || bp . RepoID != repo . ID {
ctx . NotFound ( )
return
}
if err := ctx . Repo . Repository . DeleteProtectedBranch ( bp . ID ) ; err != nil {
ctx . Error ( http . StatusInternalServerError , "DeleteProtectedBranch" , err )
return
}
ctx . Status ( http . StatusNoContent )
}