##// END OF EJS Templates
patch #9627 Add Side by Side in Diff view (Cyril Mougel)...
Jean-Philippe Lang -
r387:2b70760594f2
parent child
Show More
@@ -74,7 +74,8 class RepositoriesController < ApplicationController
74
74
75 def diff
75 def diff
76 @rev_to = params[:rev_to] || (@rev-1)
76 @rev_to = params[:rev_to] || (@rev-1)
77 @diff = @repository.scm.diff(params[:path], @rev, @rev_to)
77 type = params[:type] || 'inline'
78 @diff = @repository.scm.diff(params[:path], @rev, @rev_to, type)
78 show_error and return unless @diff
79 show_error and return unless @diff
79 end
80 end
80
81
@@ -204,4 +205,4 class Date
204 def weeks_ago(date = Date.today)
205 def weeks_ago(date = Date.today)
205 (date.year - self.year)*52 + (date.cweek - self.cweek)
206 (date.year - self.year)*52 + (date.cweek - self.cweek)
206 end
207 end
207 end No newline at end of file
208 end
@@ -16,6 +16,7
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require 'rexml/document'
18 require 'rexml/document'
19 require 'cgi'
19
20
20 module SvnRepos
21 module SvnRepos
21
22
@@ -142,7 +143,7 module SvnRepos
142 raise CommandFailed
143 raise CommandFailed
143 end
144 end
144
145
145 def diff(path, identifier_from, identifier_to=nil)
146 def diff(path, identifier_from, identifier_to=nil, type="inline")
146 path ||= ''
147 path ||= ''
147 if identifier_to and identifier_to.to_i > 0
148 if identifier_to and identifier_to.to_i > 0
148 identifier_to = identifier_to.to_i
149 identifier_to = identifier_to.to_i
@@ -161,7 +162,8 module SvnRepos
161 end
162 end
162 end
163 end
163 return nil if $? && $?.exitstatus != 0
164 return nil if $? && $?.exitstatus != 0
164 diff
165 DiffTableList.new diff, type
166
165 rescue Errno::ENOENT => e
167 rescue Errno::ENOENT => e
166 raise CommandFailed
168 raise CommandFailed
167 end
169 end
@@ -263,5 +265,167 module SvnRepos
263 self.message = attributes[:message] || ""
265 self.message = attributes[:message] || ""
264 self.paths = attributes[:paths]
266 self.paths = attributes[:paths]
265 end
267 end
268
269 end
270
271 # A line of Diff
272 class Diff
273
274 attr_accessor :nb_line_left
275 attr_accessor :line_left
276 attr_accessor :nb_line_right
277 attr_accessor :line_right
278 attr_accessor :type_diff_right
279 attr_accessor :type_diff_left
280
281 def initialize ()
282 self.nb_line_left = ''
283 self.nb_line_right = ''
284 self.line_left = ''
285 self.line_right = ''
286 self.type_diff_right = ''
287 self.type_diff_left = ''
288 end
289
290 def inspect
291 puts '### Start Line Diff ###'
292 puts self.nb_line_left
293 puts self.line_left
294 puts self.nb_line_right
295 puts self.line_right
296 end
297 end
298
299 class DiffTableList < Array
300
301 def initialize (diff, type="inline")
302 diff_table = DiffTable.new type
303 diff.each do |line|
304 if line =~ /^Index: (.*)$/
305 self << diff_table if diff_table.length > 1
306 diff_table = DiffTable.new type
307 end
308 a = diff_table.add_line line
309 end
310 self << diff_table
311 end
312 end
313
314 # Class for create a Diff
315 class DiffTable < Hash
316
317 attr_reader :file_name, :line_num_l, :line_num_r
318
319 # Initialize with a Diff file and the type of Diff View
320 # The type view must be inline or sbs (side_by_side)
321 def initialize (type="inline")
322 @parsing = false
323 @nb_line = 1
324 @start = false
325 @before = 'same'
326 @second = true
327 @type = type
328 end
329
330 # Function for add a line of this Diff
331 def add_line(line)
332 unless @parsing
333 if line =~ /^Index: (.*)$/
334 @file_name = $1
335 return false
336 elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
337 @line_num_l = $2.to_i
338 @line_num_r = $5.to_i
339 @parsing = true
340 end
341 else
342 if line =~ /^_+$/
343 self.delete(self.keys.sort.last)
344 @parsing = false
345 return false
346 elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
347 @line_num_l = $2.to_i
348 @line_num_r = $5.to_i
349 else
350 @nb_line += 1 if parse_line(line, @type)
351 end
352 end
353 return true
354 end
355
356 def inspect
357 puts '### DIFF TABLE ###'
358 puts "file : #{file_name}"
359 self.each do |d|
360 d.inspect
361 end
362 end
363
364 private
365
366 # Test if is a Side By Side type
367 def sbs?(type, func)
368 if @start and type == "sbs"
369 if @before == func and @second
370 tmp_nb_line = @nb_line
371 self[tmp_nb_line] = Diff.new
372 else
373 @second = false
374 tmp_nb_line = @start
375 @start += 1
376 @nb_line -= 1
377 end
378 else
379 tmp_nb_line = @nb_line
380 @start = @nb_line
381 self[tmp_nb_line] = Diff.new
382 @second = true
383 end
384 unless self[tmp_nb_line]
385 @nb_line += 1
386 self[tmp_nb_line] = Diff.new
387 else
388 self[tmp_nb_line]
389 end
390 end
391
392 # Escape the HTML for the diff
393 def escapeHTML(line)
394 CGI.escapeHTML(line).gsub(/\s/, '&nbsp;')
395 end
396
397 def parse_line (line, type="inline")
398 if line[0, 1] == "+"
399 diff = sbs? type, 'add'
400 @before = 'add'
401 diff.line_left = escapeHTML line[1..-1]
402 diff.nb_line_left = @line_num_l
403 diff.type_diff_left = 'diff_in'
404 @line_num_l += 1
405 true
406 elsif line[0, 1] == "-"
407 diff = sbs? type, 'remove'
408 @before = 'remove'
409 diff.line_right = escapeHTML line[1..-1]
410 diff.nb_line_right = @line_num_r
411 diff.type_diff_right = 'diff_out'
412 @line_num_r += 1
413 true
414 elsif line[0, 1] =~ /\s/
415 @before = 'same'
416 @start = false
417 diff = Diff.new
418 diff.line_right = escapeHTML line[1..-1]
419 diff.nb_line_right = @line_num_r
420 diff.line_left = escapeHTML line[1..-1]
421 diff.nb_line_left = @line_num_l
422 self[@nb_line] = diff
423 @line_num_l += 1
424 @line_num_r += 1
425 true
426 else
427 false
428 end
429 end
266 end
430 end
267 end No newline at end of file
431 end
@@ -1,66 +1,88
1 <h2><%= l(:label_revision) %> <%= @rev %>: <%= @path.gsub(/^.*\//, '') %></h2>
1 <h2><%= l(:label_revision) %> <%= @rev %>: <%= @path.gsub(/^.*\//, '') %></h2>
2
2
3 <% parsing = false
3 <!-- Choose view type -->
4 line_num_l = 0
4 <% form_tag({ :controller => 'repositories', :action => 'diff'}, :method => 'get') do %>
5 line_num_r = 0 %>
5 <% params.each do |k, p| %>
6 <% @diff.each do |line| %>
6 <% if k != "type" %>
7 <%
7 <%= hidden_field_tag(k,p) %>
8 if line =~ /^Index: (.*)$/
8 <% end %>
9 if parsing %>
9 <% end %>
10 </tbody></table>
10 <p><label><%= l(:label_view_diff) %></label>
11 <%
11 <%= select_tag 'type', options_for_select([[l(:label_diff_inline), "inline"], [l(:label_diff_side_by_side), "sbs"]], params[:type]), :onchange => "if (this.value != '') {this.form.submit()}" %>
12 end
12 <%= submit_tag l(:button_apply) %></p>
13 parsing = false %>
13 <% end %>
14 <table class="list"><thead>
14 <% @diff.each do |table_file| %>
15 <tr><th colspan="3" class="list-filename"><%= l(:label_attachment) %>: <%= $1 %></th></tr>
15 <% if params[:type] == 'sbs' %>
16 <tr><th>@<%= @rev %></th><th>@<%= @rev_to %></th><th></th></tr>
16 <table class="list">
17 </thead><tbody>
17 <thead>
18 <%
18 <tr>
19 next
19 <th colspan="4" class="list-filename">
20 elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
20 <%= l(:label_attachment) %>: <%= table_file.file_name %>
21 line_num_l = $2.to_i
21 </th>
22 line_num_r = $5.to_i
22 </tr>
23 parsing = true
23 <tr>
24 next
24 <th colspan="2"><%= l(:label_revision) %> <%= @rev %></th>
25 elsif line =~ /^_+$/
25 <th colspan="2"><%= l(:label_revision) %> <%= @rev_to %></th>
26 # We have reached the 'Properties' section.
26 </tr>
27 parsing = false
27 </thead>
28 next
28 <tbody>
29 end
29 <% table_file.keys.sort.each do |key| %>
30 next unless parsing
30 <tr>
31 %>
31 <th class="line-num">
32
32 <%= table_file[key].nb_line_left %>
33 <tr>
33 </th>
34
34 <td class="line-code <%= table_file[key].type_diff_left %>">
35 <% case line[0, 1]
35 <%= table_file[key].line_left %>
36 when " " %>
36 </td>
37 <th class="line-num"><%= line_num_l %></th>
37 <th class="line-num">
38 <th class="line-num"><%= line_num_r %></th>
38 <%= table_file[key].nb_line_right %>
39 <td class="line-code">
39 </th>
40 <% line_num_l = line_num_l + 1
40 <td class="line-code <%= table_file[key].type_diff_right %>">
41 line_num_r = line_num_r + 1
41 <%= table_file[key].line_right %>
42
42 </td>
43 when "-" %>
43 </tr>
44 <th class="line-num"></th>
44 <% end %>
45 <th class="line-num"><%= line_num_r %></th>
45 </tbody>
46 <td class="line-code" style="background: #fdd;">
46 </table>
47 <% line_num_r = line_num_r + 1
48
49 when "+" %>
50 <th class="line-num"><%= line_num_l %></th>
51 <th class="line-num"></th>
52 <td class="line-code" style="background: #dfd;">
53 <% line_num_l = line_num_l + 1
54
55 else
56 next
57 end %>
58
59 <%= h(line[1..-1]).gsub(/\s/, "&nbsp;") %></td></tr>
60
47
48 <% else %>
49 <table class="list">
50 <thead>
51 <tr>
52 <th colspan="3" class="list-filename">
53 <%= l(:label_attachment) %>: <%= table_file.file_name %>
54 </th>
55 </tr>
56 <tr>
57 <th>@<%= @rev %></th>
58 <th>@<%= @rev_to %></th>
59 <th></th>
60 </tr>
61 </thead>
62 <tbody>
63 <% table_file.keys.sort.each do |key, line| %>
64 <tr>
65 <th class="line-num">
66 <%= table_file[key].nb_line_left %>
67 </th>
68 <th class="line-num">
69 <%= table_file[key].nb_line_right %>
70 </th>
71 <% if table_file[key].line_left.empty? %>
72 <td class="line-code <%= table_file[key].type_diff_right %>">
73 <%= table_file[key].line_right %>
74 </td>
75 <% else %>
76 <td class="line-code <%= table_file[key].type_diff_left %>">
77 <%= table_file[key].line_left %>
78 </td>
79 <% end %>
80 </tr>
81 <% end %>
82 </tbody>
83 </table>
84 <% end %>
61 <% end %>
85 <% end %>
62 </tbody>
63 </table>
64
86
65 <% content_for :header_tags do %>
87 <% content_for :header_tags do %>
66 <%= stylesheet_link_tag "scm" %>
88 <%= stylesheet_link_tag "scm" %>
@@ -348,6 +348,9 label_change_plural: Änderungen
348 label_statistics: Statistiken
348 label_statistics: Statistiken
349 label_commits_per_month: Übertragungen pro Monat
349 label_commits_per_month: Übertragungen pro Monat
350 label_commits_per_author: Übertragungen pro Autor
350 label_commits_per_author: Übertragungen pro Autor
351 label_view_diff: View differences
352 label_diff_inline: inline
353 label_diff_side_by_side: side by side
351
354
352 button_login: Einloggen
355 button_login: Einloggen
353 button_submit: OK
356 button_submit: OK
@@ -348,6 +348,9 label_change_plural: Changes
348 label_statistics: Statistics
348 label_statistics: Statistics
349 label_commits_per_month: Commits per month
349 label_commits_per_month: Commits per month
350 label_commits_per_author: Commits per author
350 label_commits_per_author: Commits per author
351 label_view_diff: View differences
352 label_diff_inline: inline
353 label_diff_side_by_side: side by side
351
354
352 button_login: Login
355 button_login: Login
353 button_submit: Submit
356 button_submit: Submit
@@ -348,6 +348,9 label_change_plural: Changes
348 label_statistics: Statistics
348 label_statistics: Statistics
349 label_commits_per_month: Commits per month
349 label_commits_per_month: Commits per month
350 label_commits_per_author: Commits per author
350 label_commits_per_author: Commits per author
351 label_view_diff: View differences
352 label_diff_inline: inline
353 label_diff_side_by_side: side by side
351
354
352 button_login: Conexión
355 button_login: Conexión
353 button_submit: Someter
356 button_submit: Someter
@@ -348,6 +348,9 label_change_plural: Changements
348 label_statistics: Statistiques
348 label_statistics: Statistiques
349 label_commits_per_month: Commits par mois
349 label_commits_per_month: Commits par mois
350 label_commits_per_author: Commits par auteur
350 label_commits_per_author: Commits par auteur
351 label_view_diff: Voir les différences
352 label_diff_inline: en ligne
353 label_diff_side_by_side: côte à côte
351
354
352 button_login: Connexion
355 button_login: Connexion
353 button_submit: Soumettre
356 button_submit: Soumettre
@@ -348,6 +348,9 label_change_plural: Changes
348 label_statistics: Statistics
348 label_statistics: Statistics
349 label_commits_per_month: Commits per month
349 label_commits_per_month: Commits per month
350 label_commits_per_author: Commits per author
350 label_commits_per_author: Commits per author
351 label_view_diff: View differences
352 label_diff_inline: inline
353 label_diff_side_by_side: side by side
351
354
352 button_login: Login
355 button_login: Login
353 button_submit: Invia
356 button_submit: Invia
@@ -349,6 +349,9 label_change_plural: Changes
349 label_statistics: Statistics
349 label_statistics: Statistics
350 label_commits_per_month: Commits per month
350 label_commits_per_month: Commits per month
351 label_commits_per_author: Commits per author
351 label_commits_per_author: Commits per author
352 label_view_diff: View differences
353 label_diff_inline: inline
354 label_diff_side_by_side: side by side
352
355
353 button_login: ログイン
356 button_login: ログイン
354 button_submit: 変更
357 button_submit: 変更
@@ -26,3 +26,11 table.list thead th.list-filename {
26 font-weight: bolder;
26 font-weight: bolder;
27 text-align: left;
27 text-align: left;
28 }
28 }
29
30 .diff_out{
31 background: #fdd;
32 }
33
34 .diff_in{
35 background: #dfd;
36 }
General Comments 0
You need to be logged in to leave comments. Login now