Index: app/views/issues/diff.rhtml =================================================================== --- app/views/issues/diff.rhtml (revision 0) +++ app/views/issues/diff.rhtml (revision 0) @@ -0,0 +1,31 @@ +<% content_for :header_tags do -%> + <%= stylesheet_link_tag "scm" -%> +<% end -%> + +<% html_title "##{@issue.id}: #{@issue.subject} - change #{@detail.id}" %> + +<%= l(:field_issue) %>: <%= link_to( "##{@issue.id} " + h(@issue.subject), + :controller => 'issues', :action => 'show', :id => @issue) %> +

+

<%= l(:label_diff) %>:
+ <%= render :partial => 'common/diff', :locals => {:diff => @diff, + :diff_type => 'inline'} %> +

+ +

+

+ <%= l(:label_show_old_value) %> +
+ + +

+

+

+ <%= l(:label_show_new_value) %> +
+ +

Index: app/controllers/issues_controller.rb =================================================================== --- app/controllers/issues_controller.rb (revision 1709) +++ app/controllers/issues_controller.rb (working copy) @@ -22,7 +22,10 @@ before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment] before_filter :find_issues, :only => [:bulk_edit, :move, :destroy] before_filter :find_project, :only => [:new, :update_form, :preview] - before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu] + + before_filter :authorize, :except => [:index, :changes, :preview, + :update_form, :context_menu, :diff] + before_filter :find_optional_project, :only => [:index, :changes] accept_key_auth :index, :changes @@ -360,7 +363,24 @@ render :partial => 'common/preview' end -private + #warning - relies on availability of 'diff' utility + def diff + @detail = JournalDetail.find(params[:id]) + @issue = @detail.journal.issue + Tempfile.open 'issue_description_oldval', 'tmp' do |old_val_file| + old_val_file.write normalize(@detail.old_value) + Tempfile.open 'issue_description_oldval', 'tmp' do |new_val_file| + new_val_file.write normalize(@detail.value) + old_val_file.close + new_val_file.close + #at this moment old_val_file and new_val_file files still exist - they + # will disappear after these objects finalization + @diff = `diff #{old_val_file.path} #{new_val_file.path} -U 3` + end + end + end + + private def find_issue @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category]) @project = @issue.project @@ -427,4 +447,14 @@ end end end + + #Converts \n-terminated string to \r\n-teminated. At least FF on Windows + # inserts \r\n everywhere, even if original text was \n-terminated (that's + # how it is after Trac migration) + def normalize(long_string) + #we assume that if one line is \r\n\'ed, all others are too + return long_string if long_string["\r\n"] + long_string.split("\n").join("\r\n") + end + end Index: app/helpers/issues_helper.rb =================================================================== --- app/helpers/issues_helper.rb (revision 1709) +++ app/helpers/issues_helper.rb (working copy) @@ -75,6 +75,10 @@ when 'fixed_version_id' v = Version.find_by_id(detail.value) and value = v.name if detail.value v = Version.find_by_id(detail.old_value) and old_value = v.name if detail.old_value + when 'description' + return content_tag('strong', l(:field_description)) + ' ' + + link_to(l(:text_journal_just_changed), + :controller => 'issues', :action => 'diff', :id => detail.id) end when 'cf' custom_field = CustomField.find_by_id(detail.prop_key) Index: app/models/issue.rb =================================================================== --- app/models/issue.rb (revision 1709) +++ app/models/issue.rb (working copy) @@ -136,7 +136,7 @@ def before_save if @current_journal # attributes changes - (Issue.column_names - %w(id description)).each {|c| + (Issue.column_names - ['id']).each {|c| @current_journal.details << JournalDetail.new(:property => 'attr', :prop_key => c, :old_value => @issue_before_change.send(c), Index: app/models/journal_detail.rb =================================================================== --- app/models/journal_detail.rb (revision 1709) +++ app/models/journal_detail.rb (working copy) @@ -17,9 +17,4 @@ class JournalDetail < ActiveRecord::Base belongs_to :journal - - def before_save - self.value = value[0..254] if value && value.is_a?(String) - self.old_value = old_value[0..254] if old_value && old_value.is_a?(String) - end end Index: db/migrate/096_allow_long_journal_details_values.rb =================================================================== --- db/migrate/096_allow_long_journal_details_values.rb (revision 0) +++ db/migrate/096_allow_long_journal_details_values.rb (revision 0) @@ -0,0 +1,10 @@ +class AllowLongJournalDetailsValues < ActiveRecord::Migration + def self.up + change_column :journal_details, :old_value, :text + change_column :journal_details, :value, :text + end + + def self.down + #no need + end +end Index: lang/en.yml =================================================================== --- lang/en.yml (revision 1709) +++ lang/en.yml (working copy) @@ -521,6 +521,9 @@ label_planning: Planning label_incoming_emails: Incoming emails label_generate_key: Generate a key +label_diff: Difference +label_show_old_value: Show old value +label_show_new_value: Show new value button_login: Login button_submit: Submit @@ -572,6 +575,7 @@ text_workflow_edit: Select a role and a tracker to edit the workflow text_are_you_sure: Are you sure ? text_journal_changed: changed from %s to %s +text_journal_just_changed: changed text_journal_set_to: set to %s text_journal_deleted: deleted text_tip_task_begin_day: task beginning this day Index: lang/ru.yml =================================================================== --- lang/ru.yml (revision 1709) +++ lang/ru.yml (working copy) @@ -471,6 +471,9 @@ label_associated_revisions: Связанные редакции label_issues_by: Сортировать по %s label_display_per_page: 'На страницу: %s' +label_diff: Различия +label_show_old_value: Показать старое значение +label_show_new_value: Показать новое значение button_login: Вход button_submit: Принять @@ -521,6 +524,7 @@ text_are_you_sure: Подтвердите text_journal_changed: параметр изменился с %s на %s text_journal_set_to: параметр изменился на %s +text_journal_just_changed: параметр изменился text_journal_deleted: удалено text_tip_task_begin_day: дата начала задачи text_tip_task_end_day: дата завершения задачи Index: test/fixtures/journal_details.yml =================================================================== --- test/fixtures/journal_details.yml (revision 1709) +++ test/fixtures/journal_details.yml (working copy) @@ -13,3 +13,10 @@ value: "30" prop_key: done_ratio journal_id: 1 +description_change: + old_value: "one two three" + property: attr + id: 3 + value: "one one two three" + prop_key: description + journal_id: 1 Index: test/functional/issues_controller_test.rb =================================================================== --- test/functional/issues_controller_test.rb (revision 1709) +++ test/functional/issues_controller_test.rb (working copy) @@ -638,4 +638,10 @@ j = issue.journals.find(:first, :order => 'created_on DESC') assert_equal 'attachment', j.details.first.property end + + def test_diff + @request.session[:user_id] = 2 + get :diff, :id => journal_details(:description_change).id + assert_response :success + end end