BigW Consortium Gitlab

branches.rb 4.9 KB
Newer Older
1 2 3 4
require 'mime/types'

module API
  class Branches < Grape::API
5 6
    include PaginationParams

7 8
    before { authorize! :download_code, user_project }

9 10 11
    params do
      requires :id, type: String, desc: 'The ID of a project'
    end
12
    resource :projects, requirements: { id: %r{[^/]+} } do
13 14 15
      desc 'Get a project repository branches' do
        success Entities::RepoBranch
      end
16 17 18
      params do
        use :pagination
      end
19
      get ":id/repository/branches" do
20
        branches = ::Kaminari.paginate_array(user_project.repository.branches.sort_by(&:name))
21

22
        present paginate(branches), with: Entities::RepoBranch, project: user_project
23 24
      end

25 26 27 28
      desc 'Get a single branch' do
        success Entities::RepoBranch
      end
      params do
29
        requires :branch, type: String, desc: 'The name of the branch'
30
      end
31
      get ':id/repository/branches/:branch', requirements: { branch: /.+/ } do
32 33
        branch = user_project.repository.find_branch(params[:branch])
        not_found!("Branch") unless branch
34

35
        present branch, with: Entities::RepoBranch, project: user_project
36 37
      end

38 39 40
      # Note: The internal data model moved from `developers_can_{merge,push}` to `allowed_to_{merge,push}`
      # in `gitlab-org/gitlab-ce!5081`. The API interface has not been changed (to maintain compatibility),
      # but it works with the changed data model to infer `developers_can_merge` and `developers_can_push`.
41 42 43 44
      desc 'Protect a single branch' do
        success Entities::RepoBranch
      end
      params do
45
        requires :branch, type: String, desc: 'The name of the branch'
46 47 48
        optional :developers_can_push, type: Boolean, desc: 'Flag if developers can push to that branch'
        optional :developers_can_merge, type: Boolean, desc: 'Flag if developers can merge to that branch'
      end
49
      put ':id/repository/branches/:branch/protect', requirements: { branch: /.+/ } do
50 51
        authorize_admin_project

52 53 54 55
        branch = user_project.repository.find_branch(params[:branch])
        not_found!('Branch') unless branch

        protected_branch = user_project.protected_branches.find_by(name: branch.name)
56

57
        protected_branch_params = {
58 59 60
          name: branch.name,
          developers_can_push: params[:developers_can_push],
          developers_can_merge: params[:developers_can_merge]
61 62
        }

63
        service_args = [user_project, current_user, protected_branch_params]
64

65 66 67 68 69
        protected_branch = if protected_branch
                             ProtectedBranches::ApiUpdateService.new(*service_args).execute(protected_branch)
                           else
                             ProtectedBranches::ApiCreateService.new(*service_args).execute
                           end
70

71
        if protected_branch.valid?
72
          present branch, with: Entities::RepoBranch, project: user_project
73
        else
74
          render_api_error!(protected_branch.errors.full_messages, 422)
75
        end
76 77
      end

78 79 80 81
      desc 'Unprotect a single branch' do
        success Entities::RepoBranch
      end
      params do
82
        requires :branch, type: String, desc: 'The name of the branch'
83
      end
84
      put ':id/repository/branches/:branch/unprotect', requirements: { branch: /.+/ } do
85 86
        authorize_admin_project

87 88 89
        branch = user_project.repository.find_branch(params[:branch])
        not_found!("Branch") unless branch
        protected_branch = user_project.protected_branches.find_by(name: branch.name)
90
        protected_branch&.destroy
91

92
        present branch, with: Entities::RepoBranch, project: user_project
93
      end
94

95 96 97 98
      desc 'Create branch' do
        success Entities::RepoBranch
      end
      params do
99
        requires :branch, type: String, desc: 'The name of the branch'
100 101
        requires :ref, type: String, desc: 'Create branch from commit sha or existing branch'
      end
102 103
      post ":id/repository/branches" do
        authorize_push_project
104

105
        result = CreateBranchService.new(user_project, current_user).
106
                 execute(params[:branch], params[:ref])
107

108 109
        if result[:status] == :success
          present result[:branch],
110
                  with: Entities::RepoBranch,
111 112 113 114
                  project: user_project
        else
          render_api_error!(result[:message], 400)
        end
115
      end
116

117 118
      desc 'Delete a branch'
      params do
119
        requires :branch, type: String, desc: 'The name of the branch'
120
      end
121
      delete ":id/repository/branches/:branch", requirements: { branch: /.+/ } do
122
        authorize_push_project
123

124
        result = DeleteBranchService.new(user_project, current_user).
125
                 execute(params[:branch])
126

127
        if result[:status] != :success
128
          render_api_error!(result[:message], result[:return_code])
129
        end
130
      end
131

132
      desc 'Delete all merged branches'
133 134 135
      delete ":id/repository/merged_branches" do
        DeleteMergedBranchesService.new(user_project, current_user).async_execute

136
        accepted!
137
      end
138 139 140
    end
  end
end