Commit 695fd3cf2c7e01d06e9c335cae208089a4c6bfbd
1 parent
8ae2d215
Exists in
spb-stable
and in
2 other branches
Move protected branches to Project settings
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Showing
13 changed files
with
109 additions
and
119 deletions
Show diff stats
app/controllers/projects/branches_controller.rb
| @@ -7,7 +7,9 @@ class Projects::BranchesController < Projects::ApplicationController | @@ -7,7 +7,9 @@ class Projects::BranchesController < Projects::ApplicationController | ||
| 7 | before_filter :authorize_push!, only: [:create, :destroy] | 7 | before_filter :authorize_push!, only: [:create, :destroy] |
| 8 | 8 | ||
| 9 | def index | 9 | def index |
| 10 | - @branches = Kaminari.paginate_array(@repository.branches).page(params[:page]).per(30) | 10 | + @sort = params[:sort] || 'name' |
| 11 | + @branches = @repository.branches_sorted_by(@sort) | ||
| 12 | + @branches = Kaminari.paginate_array(@branches).page(params[:page]).per(30) | ||
| 11 | end | 13 | end |
| 12 | 14 | ||
| 13 | def recent | 15 | def recent |
app/controllers/projects/protected_branches_controller.rb
| 1 | class Projects::ProtectedBranchesController < Projects::ApplicationController | 1 | class Projects::ProtectedBranchesController < Projects::ApplicationController |
| 2 | # Authorize | 2 | # Authorize |
| 3 | - before_filter :authorize_read_project! | ||
| 4 | before_filter :require_non_empty_project | 3 | before_filter :require_non_empty_project |
| 4 | + before_filter :authorize_admin_project! | ||
| 5 | 5 | ||
| 6 | - before_filter :authorize_admin_project!, only: [:destroy, :create] | 6 | + layout "project_settings" |
| 7 | 7 | ||
| 8 | def index | 8 | def index |
| 9 | @branches = @project.protected_branches.to_a | 9 | @branches = @project.protected_branches.to_a |
app/helpers/tab_helper.rb
| @@ -75,7 +75,7 @@ module TabHelper | @@ -75,7 +75,7 @@ module TabHelper | ||
| 75 | def project_tab_class | 75 | def project_tab_class |
| 76 | return "active" if current_page?(controller: "/projects", action: :edit, id: @project) | 76 | return "active" if current_page?(controller: "/projects", action: :edit, id: @project) |
| 77 | 77 | ||
| 78 | - if ['services', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name | 78 | + if ['services', 'hooks', 'deploy_keys', 'team_members', 'protected_branches'].include? controller.controller_name |
| 79 | "active" | 79 | "active" |
| 80 | end | 80 | end |
| 81 | end | 81 | end |
app/models/repository.rb
| @@ -55,12 +55,6 @@ class Repository | @@ -55,12 +55,6 @@ class Repository | ||
| 55 | tags.find { |tag| tag.name == name } | 55 | tags.find { |tag| tag.name == name } |
| 56 | end | 56 | end |
| 57 | 57 | ||
| 58 | - def recent_branches(limit = 20) | ||
| 59 | - branches.sort do |a, b| | ||
| 60 | - commit(b.target).committed_date <=> commit(a.target).committed_date | ||
| 61 | - end[0..limit] | ||
| 62 | - end | ||
| 63 | - | ||
| 64 | def add_branch(branch_name, ref) | 58 | def add_branch(branch_name, ref) |
| 65 | Rails.cache.delete(cache_key(:branch_names)) | 59 | Rails.cache.delete(cache_key(:branch_names)) |
| 66 | 60 | ||
| @@ -220,4 +214,19 @@ class Repository | @@ -220,4 +214,19 @@ class Repository | ||
| 220 | def clean_old_archives | 214 | def clean_old_archives |
| 221 | Gitlab::Popen.popen(%W(find #{Gitlab.config.gitlab.repository_downloads_path} -mmin +120 -delete)) | 215 | Gitlab::Popen.popen(%W(find #{Gitlab.config.gitlab.repository_downloads_path} -mmin +120 -delete)) |
| 222 | end | 216 | end |
| 217 | + | ||
| 218 | + def branches_sorted_by(value) | ||
| 219 | + case value | ||
| 220 | + when 'recently_updated' | ||
| 221 | + branches.sort do |a, b| | ||
| 222 | + commit(b.target).committed_date <=> commit(a.target).committed_date | ||
| 223 | + end | ||
| 224 | + when 'last_updated' | ||
| 225 | + branches.sort do |a, b| | ||
| 226 | + commit(a.target).committed_date <=> commit(b.target).committed_date | ||
| 227 | + end | ||
| 228 | + else | ||
| 229 | + branches | ||
| 230 | + end | ||
| 231 | + end | ||
| 223 | end | 232 | end |
app/views/layouts/nav/_project.html.haml
| @@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
| 8 | = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref) | 8 | = link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref) |
| 9 | 9 | ||
| 10 | - if project_nav_tab? :commits | 10 | - if project_nav_tab? :commits |
| 11 | - = nav_link(controller: %w(commit commits compare repositories protected_branches tags branches)) do | 11 | + = nav_link(controller: %w(commit commits compare repositories tags branches)) do |
| 12 | = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref) | 12 | = link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref) |
| 13 | 13 | ||
| 14 | - if project_nav_tab? :network | 14 | - if project_nav_tab? :network |
app/views/projects/_settings_nav.html.haml
| @@ -19,3 +19,7 @@ | @@ -19,3 +19,7 @@ | ||
| 19 | = link_to project_services_path(@project) do | 19 | = link_to project_services_path(@project) do |
| 20 | %i.icon-cogs | 20 | %i.icon-cogs |
| 21 | Services | 21 | Services |
| 22 | + = nav_link(controller: :protected_branches) do | ||
| 23 | + = link_to project_protected_branches_path(@project) do | ||
| 24 | + %i.icon-lock | ||
| 25 | + Protected branches |
app/views/projects/branches/_branch.html.haml
| @@ -8,6 +8,7 @@ | @@ -8,6 +8,7 @@ | ||
| 8 | - if @project.protected_branch? branch.name | 8 | - if @project.protected_branch? branch.name |
| 9 | %span.label.label-success | 9 | %span.label.label-success |
| 10 | %i.icon-lock | 10 | %i.icon-lock |
| 11 | + protected | ||
| 11 | .pull-right | 12 | .pull-right |
| 12 | - if can?(current_user, :download_code, @project) | 13 | - if can?(current_user, :download_code, @project) |
| 13 | = render 'projects/repositories/download_archive', ref: branch.name, btn_class: 'btn-grouped btn-group-small' | 14 | = render 'projects/repositories/download_archive', ref: branch.name, btn_class: 'btn-grouped btn-group-small' |
| @@ -21,13 +22,8 @@ | @@ -21,13 +22,8 @@ | ||
| 21 | %i.icon-trash | 22 | %i.icon-trash |
| 22 | 23 | ||
| 23 | - if commit | 24 | - if commit |
| 24 | - %p | ||
| 25 | - = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do | ||
| 26 | - = commit.short_id | ||
| 27 | - = image_tag avatar_icon(commit.author_email), class: "avatar s16", alt: '' | ||
| 28 | - %span.light | ||
| 29 | - = gfm escape_once(truncate(commit.title, length: 40)) | ||
| 30 | - #{time_ago_with_tooltip(commit.committed_date)} | 25 | + %ul.list-unstyled |
| 26 | + = render 'projects/commits/inline_commit', commit: commit, project: @project | ||
| 31 | - else | 27 | - else |
| 32 | %p | 28 | %p |
| 33 | Cant find HEAD commit for this branch | 29 | Cant find HEAD commit for this branch |
app/views/projects/branches/_filter.html.haml
| @@ -1,27 +0,0 @@ | @@ -1,27 +0,0 @@ | ||
| 1 | -%ul.nav.nav-pills.nav-stacked | ||
| 2 | - = nav_link(path: 'branches#recent') do | ||
| 3 | - = link_to recent_project_branches_path(@project) do | ||
| 4 | - Recent | ||
| 5 | - .pull-right | ||
| 6 | - = @repository.recent_branches.count | ||
| 7 | - | ||
| 8 | - = nav_link(path: 'protected_branches#index') do | ||
| 9 | - = link_to project_protected_branches_path(@project) do | ||
| 10 | - Protected | ||
| 11 | - %i.icon-lock | ||
| 12 | - .pull-right | ||
| 13 | - = @project.protected_branches.count | ||
| 14 | - | ||
| 15 | - = nav_link(path: 'branches#index') do | ||
| 16 | - = link_to project_branches_path(@project) do | ||
| 17 | - All branches | ||
| 18 | - .pull-right | ||
| 19 | - = @repository.branch_names.count | ||
| 20 | - | ||
| 21 | - | ||
| 22 | -%hr | ||
| 23 | -- if can? current_user, :push_code, @project | ||
| 24 | - = link_to new_project_branch_path(@project), class: 'btn btn-create' do | ||
| 25 | - %i.icon-add-sign | ||
| 26 | - New branch | ||
| 27 | - |
app/views/projects/branches/index.html.haml
| 1 | = render "projects/commits/head" | 1 | = render "projects/commits/head" |
| 2 | -.row | ||
| 3 | - .col-md-3 | ||
| 4 | - = render "filter" | ||
| 5 | - .col-md-9 | ||
| 6 | - - unless @branches.empty? | ||
| 7 | - %ul.bordered-list.top-list.all-branches | ||
| 8 | - - @branches.each do |branch| | ||
| 9 | - = render "projects/branches/branch", branch: branch | ||
| 10 | - = paginate @branches, theme: 'gitlab' | 2 | +%h3.page-title |
| 3 | + Branches | ||
| 4 | + .pull-right | ||
| 5 | + - if can? current_user, :push_code, @project | ||
| 6 | + = link_to new_project_branch_path(@project), class: 'btn btn-create' do | ||
| 7 | + %i.icon-add-sign | ||
| 8 | + New branch | ||
| 9 | + | ||
| 10 | + .dropdown.inline | ||
| 11 | + %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"} | ||
| 12 | + %span.light sort: | ||
| 13 | + - if @sort.present? | ||
| 14 | + = @sort.humanize | ||
| 15 | + - else | ||
| 16 | + Name | ||
| 17 | + %b.caret | ||
| 18 | + %ul.dropdown-menu | ||
| 19 | + %li | ||
| 20 | + = link_to project_branches_path(sort: nil) do | ||
| 21 | + Name | ||
| 22 | + = link_to project_branches_path(sort: 'recently_updated') do | ||
| 23 | + Recently updated | ||
| 24 | + = link_to project_branches_path(sort: 'last_updated') do | ||
| 25 | + Last updated | ||
| 26 | +%hr | ||
| 27 | +- unless @branches.empty? | ||
| 28 | + %ul.bordered-list.top-list.all-branches | ||
| 29 | + - @branches.each do |branch| | ||
| 30 | + = render "projects/branches/branch", branch: branch | ||
| 31 | + = paginate @branches, theme: 'gitlab' |
app/views/projects/branches/recent.html.haml
app/views/projects/commits/_head.html.haml
| @@ -7,9 +7,9 @@ | @@ -7,9 +7,9 @@ | ||
| 7 | = link_to 'Compare', project_compare_index_path(@project, from: @repository.root_ref, to: @ref || @repository.root_ref) | 7 | = link_to 'Compare', project_compare_index_path(@project, from: @repository.root_ref, to: @ref || @repository.root_ref) |
| 8 | 8 | ||
| 9 | = nav_link(html_options: {class: branches_tab_class}) do | 9 | = nav_link(html_options: {class: branches_tab_class}) do |
| 10 | - = link_to recent_project_branches_path(@project) do | 10 | + = link_to project_branches_path(@project) do |
| 11 | Branches | 11 | Branches |
| 12 | - %span.badge= @repository.branches.length | 12 | + %span.badge= @repository.branches.size |
| 13 | 13 | ||
| 14 | = nav_link(controller: :tags) do | 14 | = nav_link(controller: :tags) do |
| 15 | = link_to project_tags_path(@project) do | 15 | = link_to project_tags_path(@project) do |
app/views/projects/protected_branches/index.html.haml
| 1 | -= render "projects/commits/head" | ||
| 2 | -.row | ||
| 3 | - .col-md-3 | ||
| 4 | - = render "projects/branches/filter" | ||
| 5 | - .col-md-9 | ||
| 6 | - .bs-callout.bs-callout-info | ||
| 7 | - %p Protected branches designed to | ||
| 8 | - %ul | ||
| 9 | - %li prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}. | ||
| 10 | - %li prevent branch from force push | ||
| 11 | - %li prevent branch from removal | ||
| 12 | - %p This ability allows to keep stable branches secured and force code review before merge to protected branches | ||
| 13 | - %p Read more about project permissions #{link_to "here", help_permissions_path, class: "underlined-link"} | 1 | +%h3.page-title Protected branches |
| 2 | +%p.light This ability allows to keep stable branches secured and force code review before merge to protected branches | ||
| 3 | +%hr | ||
| 14 | 4 | ||
| 15 | - - if can? current_user, :admin_project, @project | ||
| 16 | - = form_for [@project, @protected_branch], html: { class: 'form-horizontal' } do |f| | ||
| 17 | - -if @protected_branch.errors.any? | ||
| 18 | - .alert.alert-danger | ||
| 19 | - %ul | ||
| 20 | - - @protected_branch.errors.full_messages.each do |msg| | ||
| 21 | - %li= msg | 5 | +.bs-callout.bs-callout-info |
| 6 | + %p Protected branches designed to | ||
| 7 | + %ul | ||
| 8 | + %li prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}. | ||
| 9 | + %li prevent branch from force push | ||
| 10 | + %li prevent branch from removal | ||
| 11 | + %p Read more about project permissions #{link_to "here", help_permissions_path, class: "underlined-link"} | ||
| 22 | 12 | ||
| 23 | - .form-group | ||
| 24 | - = f.label :name, "Branch", class: 'control-label' | ||
| 25 | - .col-sm-10 | ||
| 26 | - = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "select2"}) | ||
| 27 | - .form-actions | ||
| 28 | - = f.submit 'Protect', class: "btn-create btn" | ||
| 29 | - - unless @branches.empty? | ||
| 30 | - %h5 Already Protected: | ||
| 31 | - %ul.bordered-list.protected-branches-list | ||
| 32 | - - @branches.each do |branch| | ||
| 33 | - %li | ||
| 34 | - %h4 | ||
| 35 | - = link_to project_commits_path(@project, branch.name) do | ||
| 36 | - %strong= branch.name | ||
| 37 | - - if @project.root_ref?(branch.name) | ||
| 38 | - %span.label.label-info default | ||
| 39 | - %span.label.label-success | ||
| 40 | - %i.icon-lock | ||
| 41 | - .pull-right | ||
| 42 | - - if can? current_user, :admin_project, @project | ||
| 43 | - = link_to 'Unprotect', [@project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-remove btn-small" | 13 | +- if can? current_user, :admin_project, @project |
| 14 | + = form_for [@project, @protected_branch], html: { class: 'form-horizontal' } do |f| | ||
| 15 | + -if @protected_branch.errors.any? | ||
| 16 | + .alert.alert-danger | ||
| 17 | + %ul | ||
| 18 | + - @protected_branch.errors.full_messages.each do |msg| | ||
| 19 | + %li= msg | ||
| 44 | 20 | ||
| 45 | - - if commit = branch.commit | ||
| 46 | - = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do | ||
| 47 | - = commit.short_id | ||
| 48 | - %span.light | ||
| 49 | - = gfm escape_once(truncate(commit.title, length: 40)) | ||
| 50 | - #{time_ago_with_tooltip(commit.committed_date)} | ||
| 51 | - - else | ||
| 52 | - (branch was removed from repository) | 21 | + .form-group |
| 22 | + = f.label :name, "Branch", class: 'control-label' | ||
| 23 | + .col-sm-10 | ||
| 24 | + = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "select2"}) | ||
| 25 | + .form-actions | ||
| 26 | + = f.submit 'Protect', class: "btn-create btn" | ||
| 27 | +- unless @branches.empty? | ||
| 28 | + %h5 Already Protected: | ||
| 29 | + %ul.bordered-list.protected-branches-list | ||
| 30 | + - @branches.each do |branch| | ||
| 31 | + %li | ||
| 32 | + %h4 | ||
| 33 | + = link_to project_commits_path(@project, branch.name) do | ||
| 34 | + %strong= branch.name | ||
| 35 | + - if @project.root_ref?(branch.name) | ||
| 36 | + %span.label.label-info default | ||
| 37 | + %span.label.label-success | ||
| 38 | + %i.icon-lock | ||
| 39 | + .pull-right | ||
| 40 | + - if can? current_user, :admin_project, @project | ||
| 41 | + = link_to 'Unprotect', [@project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-remove btn-small" | ||
| 42 | + | ||
| 43 | + - if commit = branch.commit | ||
| 44 | + = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do | ||
| 45 | + = commit.short_id | ||
| 46 | + %span.light | ||
| 47 | + = gfm escape_once(truncate(commit.title, length: 40)) | ||
| 48 | + #{time_ago_with_tooltip(commit.committed_date)} | ||
| 49 | + - else | ||
| 50 | + (branch was removed from repository) |
config/routes.rb
| @@ -243,12 +243,7 @@ Gitlab::Application.routes.draw do | @@ -243,12 +243,7 @@ Gitlab::Application.routes.draw do | ||
| 243 | end | 243 | end |
| 244 | end | 244 | end |
| 245 | 245 | ||
| 246 | - resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } do | ||
| 247 | - collection do | ||
| 248 | - get :recent, constraints: { id: Gitlab::Regex.git_reference_regex } | ||
| 249 | - end | ||
| 250 | - end | ||
| 251 | - | 246 | + resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } |
| 252 | resources :tags, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } | 247 | resources :tags, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } |
| 253 | resources :protected_branches, only: [:index, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } | 248 | resources :protected_branches, only: [:index, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } |
| 254 | 249 |