Commit d46cb3fd1c8aa423df72fabcdd504d39d91317e2

Authored by Dmitriy Zaporozhets
2 parents 8c50707d 59b6de93

Merge pull request #2847 from hiroponz/improve-overlap-lines

Improve overlap of lines in network graph
lib/gitlab/graph/commit.rb
@@ -5,12 +5,13 @@ module Gitlab @@ -5,12 +5,13 @@ module Gitlab
5 class Commit 5 class Commit
6 include ActionView::Helpers::TagHelper 6 include ActionView::Helpers::TagHelper
7 7
8 - attr_accessor :time, :space, :refs 8 + attr_accessor :time, :space, :refs, :parent_spaces
9 9
10 def initialize(commit) 10 def initialize(commit)
11 @_commit = commit 11 @_commit = commit
12 @time = -1 12 @time = -1
13 @space = 0 13 @space = 0
  14 + @parent_spaces = []
14 end 15 end
15 16
16 def method_missing(m, *args, &block) 17 def method_missing(m, *args, &block)
@@ -28,6 +29,7 @@ module Gitlab @@ -28,6 +29,7 @@ module Gitlab
28 } 29 }
29 h[:time] = time 30 h[:time] = time
30 h[:space] = space 31 h[:space] = space
  32 + h[:parent_spaces] = parent_spaces
31 h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil? 33 h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil?
32 h[:id] = sha 34 h[:id] = sha
33 h[:date] = date 35 h[:date] = date
lib/gitlab/graph/json_builder.rb
@@ -17,7 +17,6 @@ module Gitlab @@ -17,7 +17,6 @@ module Gitlab
17 17
18 @commits = collect_commits 18 @commits = collect_commits
19 @days = index_commits 19 @days = index_commits
20 - @space = 0  
21 end 20 end
22 21
23 def to_json(*args) 22 def to_json(*args)
@@ -54,7 +53,7 @@ module Gitlab @@ -54,7 +53,7 @@ module Gitlab
54 # 53 #
55 # @return [Array<TimeDate>] list of commit dates corelated with time on commits 54 # @return [Array<TimeDate>] list of commit dates corelated with time on commits
56 def index_commits 55 def index_commits
57 - days, heads = [], [] 56 + days, heads, times = [], [], []
58 map = {} 57 map = {}
59 58
60 commits.reverse.each_with_index do |c,i| 59 commits.reverse.each_with_index do |c,i|
@@ -62,6 +61,7 @@ module Gitlab @@ -62,6 +61,7 @@ module Gitlab
62 days[i] = c.committed_date 61 days[i] = c.committed_date
63 map[c.id] = c 62 map[c.id] = c
64 heads += c.refs unless c.refs.nil? 63 heads += c.refs unless c.refs.nil?
  64 + times[i] = c
65 end 65 end
66 66
67 heads.select!{|h| h.is_a? Grit::Head or h.is_a? Grit::Remote} 67 heads.select!{|h| h.is_a? Grit::Head or h.is_a? Grit::Remote}
@@ -87,9 +87,62 @@ module Gitlab @@ -87,9 +87,62 @@ module Gitlab
87 end 87 end
88 end 88 end
89 89
  90 + # find parent spaces for not overlap lines
  91 + times.each do |c|
  92 + c.parent_spaces.concat(find_free_parent_spaces(c, map, times))
  93 + end
  94 +
90 days 95 days
91 end 96 end
92 97
  98 + def find_free_parent_spaces(commit, map, times)
  99 + spaces = []
  100 +
  101 + commit.parents.each do |p|
  102 + if map.include?(p.id) then
  103 + parent = map[p.id]
  104 +
  105 + range = if commit.time < parent.time then
  106 + commit.time..parent.time
  107 + else
  108 + parent.time..commit.time
  109 + end
  110 +
  111 + space = if commit.space >= parent.space then
  112 + find_free_parent_space(range, map, parent.space, 1, commit.space, times)
  113 + else
  114 + find_free_parent_space(range, map, parent.space, -1, parent.space, times)
  115 + end
  116 +
  117 + mark_reserved(range, space)
  118 + spaces << space
  119 + end
  120 + end
  121 +
  122 + spaces
  123 + end
  124 +
  125 + def find_free_parent_space(range, map, space_base, space_step, space_default, times)
  126 + if is_overlap?(range, times, space_default) then
  127 + find_free_space(range, map, space_base, space_step)
  128 + else
  129 + space_default
  130 + end
  131 + end
  132 +
  133 + def is_overlap?(range, times, overlap_space)
  134 + range.each do |i|
  135 + if i != range.first &&
  136 + i != range.last &&
  137 + times[i].space == overlap_space then
  138 +
  139 + return true;
  140 + end
  141 + end
  142 +
  143 + false
  144 + end
  145 +
93 # Add space mark on commit and its parents 146 # Add space mark on commit and its parents
94 # 147 #
95 # @param [Graph::Commit] the commit object. 148 # @param [Graph::Commit] the commit object.
@@ -99,8 +152,9 @@ module Gitlab @@ -99,8 +152,9 @@ module Gitlab
99 if leaves.empty? 152 if leaves.empty?
100 return 153 return
101 end 154 end
102 - @space = find_free_space(leaves, map)  
103 - leaves.each{|l| l.space = @space} 155 + time_range = leaves.last.time..leaves.first.time
  156 + space = find_free_space(time_range, map, 1, 2)
  157 + leaves.each{|l| l.space = space}
104 # and mark it as reserved 158 # and mark it as reserved
105 min_time = leaves.last.time 159 min_time = leaves.last.time
106 parents = leaves.last.parents.collect 160 parents = leaves.last.parents.collect
@@ -117,7 +171,7 @@ module Gitlab @@ -117,7 +171,7 @@ module Gitlab
117 else 171 else
118 max_time = parent_time - 1 172 max_time = parent_time - 1
119 end 173 end
120 - mark_reserved(min_time..max_time, @space) 174 + mark_reserved(min_time..max_time, space)
121 175
122 # Visit branching chains 176 # Visit branching chains
123 leaves.each do |l| 177 leaves.each do |l|
@@ -134,28 +188,22 @@ module Gitlab @@ -134,28 +188,22 @@ module Gitlab
134 end 188 end
135 end 189 end
136 190
137 - def find_free_space(leaves, map)  
138 - time_range = leaves.last.time..leaves.first.time 191 + def find_free_space(time_range, map, space_base, space_step)
139 reserved = [] 192 reserved = []
140 for day in time_range 193 for day in time_range
141 reserved += @_reserved[day] 194 reserved += @_reserved[day]
142 end 195 end
143 - space = base_space(leaves, map)  
144 - while (reserved.include? space) || (space == @space) do  
145 - space += 1  
146 - end  
147 -  
148 - space  
149 - end  
150 196
151 - def base_space(leaves, map)  
152 - parents = []  
153 - leaves.each do |l|  
154 - parents.concat l.parents.collect.select{|p| map.include? p.id and map[p.id].space.nonzero?} 197 + space = space_base
  198 + while reserved.include?(space) do
  199 + space += space_step
  200 + if space <= 0 then
  201 + space_step *= -1
  202 + space = space_base + space_step
  203 + end
155 end 204 end
156 205
157 - space = parents.map{|p| map[p.id].space}.max || 0  
158 - space += 1 206 + space
159 end 207 end
160 208
161 # Takes most left subtree branch of commits 209 # Takes most left subtree branch of commits
vendor/assets/javascripts/branch-graph.js
@@ -104,8 +104,9 @@ @@ -104,8 +104,9 @@
104 104
105 for (i = 0; i < this.commitCount; i++) { 105 for (i = 0; i < this.commitCount; i++) {
106 var x = offsetX + 20 * this.commits[i].time 106 var x = offsetX + 20 * this.commits[i].time
107 - , y = offsetY + 20 * this.commits[i].space  
108 - , c; 107 + , y = offsetY + 10 * this.commits[i].space
  108 + , c
  109 + , ps;
109 110
110 // Draw dot 111 // Draw dot
111 r.circle(x, y, 3).attr({ 112 r.circle(x, y, 3).attr({
@@ -116,9 +117,11 @@ @@ -116,9 +117,11 @@
116 // Draw lines 117 // Draw lines
117 for (var j = 0, jj = this.commits[i].parents.length; j < jj; j++) { 118 for (var j = 0, jj = this.commits[i].parents.length; j < jj; j++) {
118 c = this.preparedCommits[this.commits[i].parents[j][0]]; 119 c = this.preparedCommits[this.commits[i].parents[j][0]];
  120 + ps = this.commits[i].parent_spaces[j];
119 if (c) { 121 if (c) {
120 var cx = offsetX + 20 * c.time 122 var cx = offsetX + 20 * c.time
121 - , cy = offsetY + 20 * c.space; 123 + , cy = offsetY + 10 * c.space
  124 + , psy = offsetY + 10 * ps;
122 if (c.space == this.commits[i].space) { 125 if (c.space == this.commits[i].space) {
123 r.path([ 126 r.path([
124 "M", x, y, 127 "M", x, y,
@@ -129,13 +132,25 @@ @@ -129,13 +132,25 @@
129 }); 132 });
130 133
131 } else if (c.space < this.commits[i].space) { 134 } else if (c.space < this.commits[i].space) {
132 - r.path(["M", x - 5, y + .0001, "l-5-2,0,4,5,-2C", x - 5, y, x - 17, y + 2, x - 20, y - 5, "L", cx, y - 5, cx, cy]) 135 + r.path([
  136 + "M", x - 5, y,
  137 + "l-5-2,0,4,5,-2",
  138 + "L", x - 10, y,
  139 + "L", x - 15, psy,
  140 + "L", cx + 5, psy,
  141 + "L", cx, cy])
133 .attr({ 142 .attr({
134 stroke: this.colors[this.commits[i].space], 143 stroke: this.colors[this.commits[i].space],
135 "stroke-width": 2 144 "stroke-width": 2
136 }); 145 });
137 } else { 146 } else {
138 - r.path(["M", x - 3, y + 6, "l-4,3,4,2,0,-5L", x - 10, y + 20, "L", x - 10, cy, cx, cy]) 147 + r.path([
  148 + "M", x - 3, y + 6,
  149 + "l-4,3,4,2,0,-5",
  150 + "L", x - 5, y + 10,
  151 + "L", x - 10, psy,
  152 + "L", cx + 5, psy,
  153 + "L", cx, cy])
139 .attr({ 154 .attr({
140 stroke: this.colors[c.space], 155 stroke: this.colors[c.space],
141 "stroke-width": 2 156 "stroke-width": 2