Commit 07c39c99 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'brunsa2/gitlab-ce-diverging-branch-graphs' into 'master'

Add graphs of commits ahead/behind default branch (by @brunsa2)

Replaces https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/1716

See merge request !2301
parents 7c3c901a 2e8ec7e7
...@@ -156,6 +156,8 @@ v 8.2.0 ...@@ -156,6 +156,8 @@ v 8.2.0
- Allow to define cache in `.gitlab-ci.yml` - Allow to define cache in `.gitlab-ci.yml`
- Fix: 500 error returned if destroy request without HTTP referer (Kazuki Shimizu) - Fix: 500 error returned if destroy request without HTTP referer (Kazuki Shimizu)
- Remove deprecated CI events from project settings page - 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) - Improve personal snippet access workflow (Douglas Alexandre)
- [API] Add ability to fetch the commit ID of the last commit that actually touched a file - [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) - Fix omniauth documentation setting for omnibus configuration (Jon Cairns)
......
...@@ -122,3 +122,59 @@ li.commit { ...@@ -122,3 +122,59 @@ li.commit {
color: $gl-gray; 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;
}
}
...@@ -9,6 +9,11 @@ class Projects::BranchesController < Projects::ApplicationController ...@@ -9,6 +9,11 @@ class Projects::BranchesController < Projects::ApplicationController
@sort = params[:sort] || 'name' @sort = params[:sort] || 'name'
@branches = @repository.branches_sorted_by(@sort) @branches = @repository.branches_sorted_by(@sort)
@branches = Kaminari.paginate_array(@branches).page(params[:page]).per(PER_PAGE) @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 end
def recent def recent
......
...@@ -775,6 +775,8 @@ class Project < ActiveRecord::Base ...@@ -775,6 +775,8 @@ class Project < ActiveRecord::Base
end end
def change_head(branch) 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) gitlab_shell.update_repository_head(self.path_with_namespace, branch)
reload_default_branch reload_default_branch
end end
......
...@@ -175,11 +175,29 @@ class Repository ...@@ -175,11 +175,29 @@ class Repository
def size def size
cache.fetch(:size) { raw_repository.size } cache.fetch(:size) { raw_repository.size }
end 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 def cache_keys
%i(size branch_names tag_names commit_count %i(size branch_names tag_names commit_count
readme version contribution_guide changelog license) readme version contribution_guide changelog license)
end end
def branch_cache_keys
branches.map do |branch|
:"diverging_commit_counts_#{branch.name}"
end
end
def build_cache def build_cache
cache_keys.each do |key| cache_keys.each do |key|
...@@ -187,6 +205,12 @@ class Repository ...@@ -187,6 +205,12 @@ class Repository
send(key) send(key)
end end
end end
branches.each do |branch|
unless cache.exist?(:"diverging_commit_counts_#{branch.name}")
send(:diverging_commit_counts, branch)
end
end
end end
def expire_tags_cache def expire_tags_cache
...@@ -203,6 +227,14 @@ class Repository ...@@ -203,6 +227,14 @@ class Repository
cache_keys.each do |key| cache_keys.each do |key|
cache.expire(key) cache.expire(key)
end end
expire_branch_cache
end
def expire_branch_cache
branches.each do |branch|
cache.expire(:"diverging_commit_counts_#{branch.name}")
end
end end
def rebuild_cache def rebuild_cache
...@@ -210,6 +242,11 @@ class Repository ...@@ -210,6 +242,11 @@ class Repository
cache.expire(key) cache.expire(key)
send(key) send(key)
end end
branches.each do |branch|
cache.expire(:"diverging_commit_counts_#{branch.name}")
diverging_commit_counts(branch)
end
end end
def lookup_cache def lookup_cache
......
- commit = @repository.commit(branch.target) - 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}") %li(class="js-branch-#{branch.name}")
%div %div
= link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do = link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do
...@@ -29,6 +33,17 @@ ...@@ -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 = 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") = 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 - if commit
= render 'projects/branches/commit', commit: commit, project: @project = render 'projects/branches/commit', commit: commit, project: @project
- else - else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment