diff options
-rw-r--r-- | CHANGELOG | 2 | ||||
-rw-r--r-- | app/assets/stylesheets/pages/commits.scss | 56 | ||||
-rw-r--r-- | app/controllers/projects/branches_controller.rb | 5 | ||||
-rw-r--r-- | app/models/project.rb | 2 | ||||
-rw-r--r-- | app/models/repository.rb | 37 | ||||
-rw-r--r-- | app/views/projects/branches/_branch.html.haml | 15 |
6 files changed, 117 insertions, 0 deletions
diff --git a/CHANGELOG b/CHANGELOG index d841b149615..b0972ceab68 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -156,6 +156,8 @@ v 8.2.0 - Allow to define cache in `.gitlab-ci.yml` - Fix: 500 error returned if destroy request without HTTP referer (Kazuki Shimizu) - Remove deprecated CI events from project settings page + - Use issue editor as cross reference comment author when issue is edited with a new mention. + - Add graphs of commits ahead and behind default branch (Jeff Stubler) - Improve personal snippet access workflow (Douglas Alexandre) - [API] Add ability to fetch the commit ID of the last commit that actually touched a file - Fix omniauth documentation setting for omnibus configuration (Jon Cairns) diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index c9dfcff6290..879bd287470 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -122,3 +122,59 @@ li.commit { color: $gl-gray; } } + +.divergence-graph { + padding: 12px 12px 0 0; + float: right; + + .graph-side { + position: relative; + width: 80px; + height: 22px; + padding: 5px 0 13px; + float: left; + + .bar { + position: absolute; + height: 4px; + background-color: #ccc; + } + + .bar-behind { + right: 0; + border-radius: 3px 0 0 3px; + } + + .bar-ahead { + left: 0; + border-radius: 0 3px 3px 0; + } + + .count { + padding-top: 6px; + padding-bottom: 0px; + font-size: 12px; + color: #333; + display: block; + } + + .count-behind { + padding-right: 4px; + text-align: right; + } + + .count-ahead { + padding-left: 4px; + text-align: left; + } + } + + .graph-separator { + position: relative; + width: 1px; + height: 18px; + margin: 5px 0 0; + float: left; + background-color: #ccc; + } +} diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 3c2849a7601..4db3b3bf23d 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -9,6 +9,11 @@ class Projects::BranchesController < Projects::ApplicationController @sort = params[:sort] || 'name' @branches = @repository.branches_sorted_by(@sort) @branches = Kaminari.paginate_array(@branches).page(params[:page]).per(PER_PAGE) + + @max_commits = @branches.reduce(0) do |memo, branch| + diverging_commit_counts = repository.diverging_commit_counts(branch) + [memo, diverging_commit_counts[:behind], diverging_commit_counts[:ahead]].max + end end def recent diff --git a/app/models/project.rb b/app/models/project.rb index eadc42d1da5..b1a6cfa86af 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -775,6 +775,8 @@ class Project < ActiveRecord::Base end def change_head(branch) + # Cached divergent commit counts are based on repository head + repository.expire_branch_cache gitlab_shell.update_repository_head(self.path_with_namespace, branch) reload_default_branch end diff --git a/app/models/repository.rb b/app/models/repository.rb index a9bf4eb4033..6ecd2d2f27e 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -175,11 +175,29 @@ class Repository def size cache.fetch(:size) { raw_repository.size } end + + def diverging_commit_counts(branch) + root_ref_hash = raw_repository.rev_parse_target(root_ref).oid + cache.fetch(:"diverging_commit_counts_#{branch.name}") do + # Rugged seems to throw a `ReferenceError` when given branch_names rather + # than SHA-1 hashes + number_commits_behind = commits_between(branch.target, root_ref_hash).size + number_commits_ahead = commits_between(root_ref_hash, branch.target).size + + { behind: number_commits_behind, ahead: number_commits_ahead } + end + end def cache_keys %i(size branch_names tag_names commit_count readme version contribution_guide changelog license) end + + def branch_cache_keys + branches.map do |branch| + :"diverging_commit_counts_#{branch.name}" + end + end def build_cache cache_keys.each do |key| @@ -187,6 +205,12 @@ class Repository send(key) end end + + branches.each do |branch| + unless cache.exist?(:"diverging_commit_counts_#{branch.name}") + send(:diverging_commit_counts, branch) + end + end end def expire_tags_cache @@ -203,6 +227,14 @@ class Repository cache_keys.each do |key| cache.expire(key) end + + expire_branch_cache + end + + def expire_branch_cache + branches.each do |branch| + cache.expire(:"diverging_commit_counts_#{branch.name}") + end end def rebuild_cache @@ -210,6 +242,11 @@ class Repository cache.expire(key) send(key) end + + branches.each do |branch| + cache.expire(:"diverging_commit_counts_#{branch.name}") + diverging_commit_counts(branch) + end end def lookup_cache diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 5081bae6801..a234536723e 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -1,4 +1,8 @@ - commit = @repository.commit(branch.target) +- bar_graph_width_factor = @max_commits > 0 ? 100.0/@max_commits : 0 +- diverging_commit_counts = @repository.diverging_commit_counts(branch) +- number_commits_behind = diverging_commit_counts[:behind] +- number_commits_ahead = diverging_commit_counts[:ahead] %li(class="js-branch-#{branch.name}") %div = link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do @@ -29,6 +33,17 @@ = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-grouped btn-xs btn-remove remove-row has_tooltip', title: "Delete branch", method: :delete, data: { confirm: "Deleting the '#{branch.name}' branch cannot be undone. Are you sure?", container: 'body' }, remote: true do = icon("trash-o") + - if branch.name != @repository.root_ref + .divergence-graph{ title: "#{number_commits_ahead} commits ahead, #{number_commits_behind} commits behind #{@repository.root_ref}" } + .graph-side + .bar.bar-behind{ style: "width: #{number_commits_behind * bar_graph_width_factor}%" } + %span.count.count-behind= number_commits_behind + .graph-separator + .graph-side + .bar.bar-ahead{ style: "width: #{number_commits_ahead * bar_graph_width_factor}%" } + %span.count.count-ahead= number_commits_ahead + + - if commit = render 'projects/branches/commit', commit: commit, project: @project - else |