]> source.dussan.org Git - redmine.git/commitdiff
Fixed: performance issue on RepositoriesController#revisions when a changeset has...
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Tue, 15 May 2007 21:32:36 +0000 (21:32 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Tue, 15 May 2007 21:32:36 +0000 (21:32 +0000)
Also added pagination for changes on changeset details view.

git-svn-id: http://redmine.rubyforge.org/svn/trunk@535 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/repositories_controller.rb
app/models/repository.rb
app/views/repositories/revision.rhtml
test/fixtures/changes.yml [new file with mode: 0644]
test/unit/repository_test.rb

index fdfe936f7b0ef39158c19b2d530fc9eda948835c..4252e58beace84f3fee8e718f5b40e7f06421399 100644 (file)
@@ -49,7 +49,7 @@ class RepositoriesController < ApplicationController
       show_error and return unless @entry
     end
     @repository.changesets_with_path @path do
-      @changeset_count = @repository.changesets.count
+      @changeset_count = @repository.changesets.count(:select => "DISTINCT #{Changeset.table_name}.id")
       @changeset_pages = Paginator.new self, @changeset_count,
                                                                      25,
                                                                      params['page']                                                            
@@ -71,6 +71,13 @@ class RepositoriesController < ApplicationController
   def revision
     @changeset = @repository.changesets.find_by_revision(@rev)
     show_error and return unless @changeset
+    @changes_count = @changeset.changes.size
+    @changes_pages = Paginator.new self, @changes_count, 150, params['page']                                                           
+    @changes = @changeset.changes.find(:all,
+                                               :limit  =>  @changes_pages.items_per_page,
+                                               :offset =>  @changes_pages.current.offset)
+       
+       render :action => "revision", :layout => false if request.xhr?  
   end
   
   def diff
index 02dfda6b75eadbaf20a517d7fcce260eecff6c63..692c446d60db453a5591bddee2e33a54f830b8ce 100644 (file)
@@ -40,7 +40,9 @@ class Repository < ActiveRecord::Base
     path = "/#{path}%"
     path = url.gsub(/^#{root_url}/, '') + path if root_url && root_url != url
     path.squeeze!("/")
-    Changeset.with_scope(:find => { :include => :changes, :conditions => ["#{Change.table_name}.path LIKE ?", path] }) do 
+    # Custom select and joins is done to allow conditions on changes table without loading associated Change objects
+    # Required for changesets with a great number of changes (eg. 100,000)
+    Changeset.with_scope(:find => { :select => "DISTINCT #{Changeset.table_name}.*", :joins => "LEFT OUTER JOIN #{Change.table_name} ON #{Change.table_name}.changeset_id = #{Changeset.table_name}.id", :conditions => ["#{Change.table_name}.path LIKE ?", path] }) do 
       yield
     end 
   end
index 8919e45a23c7858b7c300fdc38bb74c853fba0d5..5cf5c2e412574a6734d719bccc3eba99d42f0b4a 100644 (file)
@@ -28,7 +28,7 @@
 <p><%= link_to(l(:label_view_diff), :action => 'diff', :id => @project, :path => "", :rev => @changeset.revision) if @changeset.changes.any? %></p>
 <table class="list">
 <tbody>
-<% @changeset.changes.each do |change| %>
+<% @changes.each do |change| %>
 <tr class="<%= cycle 'odd', 'even' %>">
 <td><div class="square action_<%= change.action %>"></div> <%= change.path %></td>
 <td align="right">
@@ -40,8 +40,9 @@
 <% end %>
 </tbody>
 </table>
-<p><%= lwr(:label_modification, @changeset.changes.length) %></p>
+<p><%= pagination_links_full @changes_pages, :rev => @changeset.revision %>
+[ <%= @changes_pages.current.first_item %> - <%= @changes_pages.current.last_item %> / <%= @changes_count %> ]</p>
 
 <% content_for :header_tags do %>
 <%= stylesheet_link_tag "scm" %>
-<% end %>
\ No newline at end of file
+<% end %>
diff --git a/test/fixtures/changes.yml b/test/fixtures/changes.yml
new file mode 100644 (file)
index 0000000..30acbd0
--- /dev/null
@@ -0,0 +1,16 @@
+--- \r
+changes_001: \r
+  id: 1\r
+  changeset_id: 100\r
+  action: A\r
+  path: /test/some/path/in/the/repo\r
+  from_path:\r
+  from_revision:\r
+changes_002: \r
+  id: 2\r
+  changeset_id: 100\r
+  action: A\r
+  path: /test/some/path/elsewhere/in/the/repo\r
+  from_path:\r
+  from_revision:\r
+  
\ No newline at end of file
index 5e0fb56fd81b39952b3659beb5b68d20c47d5550..fd4fb67370b3487c2c2bacaf99280ea2b13272a9 100644 (file)
 require File.dirname(__FILE__) + '/../test_helper'
 
 class RepositoryTest < Test::Unit::TestCase
-  fixtures :projects, :repositories, :issues, :issue_statuses, :changesets
+  fixtures :projects, :repositories, :issues, :issue_statuses, :changesets, :changes
+  
+  def setup
+    @repository = Project.find(1).repository
+  end
   \r
   def test_create\r
     repository = Repository.new(:project => Project.find(2))
@@ -33,10 +37,9 @@ class RepositoryTest < Test::Unit::TestCase
   end\r
 
   def test_cant_change_url
-    repository = Project.find(1).repository
-    url = repository.url
-    repository.url = "svn://anotherhost"
-    assert_equal  url, repository.url
+    url = @repository.url
+    @repository.url = "svn://anotherhost"
+    assert_equal  url, @repository.url
   end
   
   def test_scan_changesets_for_issue_ids
@@ -56,4 +59,12 @@ class RepositoryTest < Test::Unit::TestCase
     # ignoring commits referencing an issue of another project
     assert_equal [], Issue.find(4).changesets
   end
+  
+  def test_changesets_with_path
+    @repository.changesets_with_path '/some/path' do
+      assert_equal 1, @repository.changesets.count(:select => "DISTINCT #{Changeset.table_name}.id")
+      changesets = @repository.changesets.find(:all)
+      assert_equal 1, changesets.size
+    end
+  end
 end