]> source.dussan.org Git - redmine.git/commitdiff
Merged r3394, r3466, r3467, r3468 and r3471 from trunk.
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 28 Feb 2010 09:51:10 +0000 (09:51 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 28 Feb 2010 09:51:10 +0000 (09:51 +0000)
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.9-stable@3501 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/models/changeset.rb
app/models/repository/git.rb
db/migrate/20100221100219_add_index_on_changesets_scmid.rb [new file with mode: 0644]
lib/redmine/scm/adapters/git_adapter.rb
test/fixtures/encoding/iso-8859-1.txt [new file with mode: 0644]
test/unit/changeset_test.rb
test/unit/repository_git_test.rb

index f7145631e0ee625d78533fd5bc080ff77fd91e93..fcd7bb122387e4929629ee04b4bcfab7e6883f68 100644 (file)
@@ -1,5 +1,5 @@
 # Redmine - project management software
-# Copyright (C) 2006-2008  Jean-Philippe Lang
+# Copyright (C) 2006-2010  Jean-Philippe Lang
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -57,6 +57,10 @@ class Changeset < ActiveRecord::Base
     super
   end
   
+  def committer=(arg)
+    write_attribute(:committer, self.class.to_utf8(arg.to_s))
+  end
+
   def project
     repository.project
   end
@@ -171,11 +175,12 @@ class Changeset < ActiveRecord::Base
     encoding = Setting.commit_logs_encoding.to_s.strip
     unless encoding.blank? || encoding == 'UTF-8'
       begin
-        return Iconv.conv('UTF-8', encoding, str)
+        str = Iconv.conv('UTF-8', encoding, str)
       rescue Iconv::Failure
         # do nothing here
       end
     end
-    str
+    # removes invalid UTF8 sequences
+    Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + '  ')[0..-3]
   end
 end
index dd5e9e3166f48730b4e080c91e6f3cfd2f1a43a0..473eb07e290d864efb530683b3e329915bbc9728 100644 (file)
@@ -40,23 +40,26 @@ class Repository::Git < Repository
   # With SCM's that have a sequential commit numbering, redmine is able to be
   # clever and only fetch changesets going forward from the most recent one
   # it knows about.  However, with git, you never know if people have merged
-  # commits into the middle of the repository history, so we always have to
-  # parse the entire log.
+  # commits into the middle of the repository history, so we should parse
+  # the entire log. Since it's way too slow for large repositories, we only
+  # parse 1 week before the last known commit.
+  # The repository can still be fully reloaded by calling #clear_changesets
+  # before fetching changesets (eg. for offline resync)
   def fetch_changesets
-    # Save ourselves an expensive operation if we're already up to date
-    return if scm.num_revisions == changesets.count
+    c = changesets.find(:first, :order => 'committed_on DESC')
+    since = (c ? c.committed_on - 7.days : nil)
 
-    revisions = scm.revisions('', nil, nil, :all => true)
+    revisions = scm.revisions('', nil, nil, :all => true, :since => since)
     return if revisions.nil? || revisions.empty?
 
-    # Find revisions that redmine knows about already
-    existing_revisions = changesets.find(:all).map!{|c| c.scmid}
+    recent_changesets = changesets.find(:all, :conditions => ['committed_on >= ?', since])
 
     # Clean out revisions that are no longer in git
-    Changeset.delete_all(["scmid NOT IN (?) AND repository_id = (?)", revisions.map{|r| r.scmid}, self.id])
+    recent_changesets.each {|c| c.destroy unless revisions.detect {|r| r.scmid.to_s == c.scmid.to_s }}
 
     # Subtract revisions that redmine already knows about
-    revisions.reject!{|r| existing_revisions.include?(r.scmid)}
+    recent_revisions = recent_changesets.map{|c| c.scmid}
+    revisions.reject!{|r| recent_revisions.include?(r.scmid)}
 
     # Save the remaining ones to the database
     revisions.each{|r| r.save(self)} unless revisions.nil?
diff --git a/db/migrate/20100221100219_add_index_on_changesets_scmid.rb b/db/migrate/20100221100219_add_index_on_changesets_scmid.rb
new file mode 100644 (file)
index 0000000..96d85a3
--- /dev/null
@@ -0,0 +1,9 @@
+class AddIndexOnChangesetsScmid < ActiveRecord::Migration
+  def self.up
+    add_index :changesets, [:repository_id, :scmid], :name => :changesets_repos_scmid
+  end
+
+  def self.down
+    remove_index :changesets, :name => :changesets_repos_scmid
+  end
+end
index 14e1674b1286caf46688352299cf213648205bd0..75a33a05499b2b5c20a42f2cfa431ed0501b71f5 100644 (file)
@@ -33,21 +33,22 @@ module Redmine
         end
 
         def branches
-          branches = []
+          return @branches if @branches
+          @branches = []
           cmd = "#{GIT_BIN} --git-dir #{target('')} branch"
           shellout(cmd) do |io|
             io.each_line do |line|
-              branches << line.match('\s*\*?\s*(.*)$')[1]
+              @branches << line.match('\s*\*?\s*(.*)$')[1]
             end
           end
-          branches.sort!
+          @branches.sort!
         end
 
         def tags
-          tags = []
+          return @tags if @tags
           cmd = "#{GIT_BIN} --git-dir #{target('')} tag"
           shellout(cmd) do |io|
-            io.readlines.sort!.map{|t| t.strip}
+            @tags = io.readlines.sort!.map{|t| t.strip}
           end
         end
 
@@ -110,20 +111,16 @@ module Redmine
           end
         end
 
-        def num_revisions
-          cmd = "#{GIT_BIN} --git-dir #{target('')} log --all --pretty=format:'' | wc -l"
-          shellout(cmd) {|io| io.gets.chomp.to_i + 1}
-        end
-
         def revisions(path, identifier_from, identifier_to, options={})
           revisions = Revisions.new
 
-          cmd = "#{GIT_BIN} --git-dir #{target('')} log --find-copies-harder --raw --date=iso --pretty=fuller"
+          cmd = "#{GIT_BIN} --git-dir #{target('')} log --raw --date=iso --pretty=fuller"
           cmd << " --reverse" if options[:reverse]
           cmd << " --all" if options[:all]
           cmd << " -n #{options[:limit]} " if options[:limit]
           cmd << " #{shell_quote(identifier_from + '..')} " if identifier_from
           cmd << " #{shell_quote identifier_to} " if identifier_to
+          cmd << " --since=#{shell_quote(options[:since].strftime("%Y-%m-%d %H:%M:%S"))}" if options[:since]
           cmd << " -- #{path}" if path && !path.empty?
 
           shellout(cmd) do |io|
diff --git a/test/fixtures/encoding/iso-8859-1.txt b/test/fixtures/encoding/iso-8859-1.txt
new file mode 100644 (file)
index 0000000..8ad6cc0
--- /dev/null
@@ -0,0 +1 @@
+Texte encodé en ISO-8859-1.
\ No newline at end of file
index 8d57c43abbd56c9d169e5f541b2e00bf27bc88a3..8010383feab5c037c95e9517fa439f597ba1719f 100644 (file)
@@ -1,5 +1,7 @@
-# redMine - project management software
-# Copyright (C) 2006-2007  Jean-Philippe Lang
+# encoding: utf-8
+#
+# Redmine - project management software
+# Copyright (C) 2006-2010  Jean-Philippe Lang
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -117,4 +119,18 @@ class ChangesetTest < ActiveSupport::TestCase
     changeset = Changeset.find_by_revision('10')
     assert_nil changeset.next
   end
+  
+  def test_comments_should_be_converted_to_utf8
+    with_settings :commit_logs_encoding => 'ISO-8859-1' do
+      c = Changeset.new
+      c.comments = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
+      assert_equal "Texte encodé en ISO-8859-1.", c.comments
+    end
+  end
+  
+  def test_invalid_utf8_sequences_in_comments_should_be_stripped
+    c = Changeset.new
+    c.comments = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
+    assert_equal "Texte encod en ISO-8859-1.", c.comments
+  end
 end
index 5ebbb00c15782e6b6c3111180d1b7dd75af437c4..71b3e4da547b6248449e4e794abef6dd07f194ed 100644 (file)
@@ -35,7 +35,7 @@ class RepositoryGitTest < ActiveSupport::TestCase
       @repository.reload
       
       assert_equal 12, @repository.changesets.count
-      assert_equal 20, @repository.changes.count
+      assert_equal 21, @repository.changes.count
       
       commit = @repository.changesets.find(:first, :order => 'committed_on ASC')
       assert_equal "Initial import.\nThe repository contains 3 files.", commit.comments