@@ -0,0 +1,9 | |||
|
1 | class AddIndexOnChangesetsScmid < ActiveRecord::Migration | |
|
2 | def self.up | |
|
3 | add_index :changesets, [:repository_id, :scmid], :name => :changesets_repos_scmid | |
|
4 | end | |
|
5 | ||
|
6 | def self.down | |
|
7 | remove_index :changesets, :name => :changesets_repos_scmid | |
|
8 | end | |
|
9 | end |
@@ -0,0 +1,1 | |||
|
1 | Texte encod� en ISO-8859-1. No newline at end of file |
@@ -1,5 +1,5 | |||
|
1 | 1 | # Redmine - project management software |
|
2 |
# Copyright (C) 2006-200 |
|
|
2 | # Copyright (C) 2006-2010 Jean-Philippe Lang | |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
@@ -57,6 +57,10 class Changeset < ActiveRecord::Base | |||
|
57 | 57 | super |
|
58 | 58 | end |
|
59 | 59 | |
|
60 | def committer=(arg) | |
|
61 | write_attribute(:committer, self.class.to_utf8(arg.to_s)) | |
|
62 | end | |
|
63 | ||
|
60 | 64 | def project |
|
61 | 65 | repository.project |
|
62 | 66 | end |
@@ -171,11 +175,12 class Changeset < ActiveRecord::Base | |||
|
171 | 175 | encoding = Setting.commit_logs_encoding.to_s.strip |
|
172 | 176 | unless encoding.blank? || encoding == 'UTF-8' |
|
173 | 177 | begin |
|
174 |
|
|
|
178 | str = Iconv.conv('UTF-8', encoding, str) | |
|
175 | 179 | rescue Iconv::Failure |
|
176 | 180 | # do nothing here |
|
177 | 181 | end |
|
178 | 182 | end |
|
179 | str | |
|
183 | # removes invalid UTF8 sequences | |
|
184 | Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3] | |
|
180 | 185 | end |
|
181 | 186 | end |
@@ -40,23 +40,26 class Repository::Git < Repository | |||
|
40 | 40 | # With SCM's that have a sequential commit numbering, redmine is able to be |
|
41 | 41 | # clever and only fetch changesets going forward from the most recent one |
|
42 | 42 | # it knows about. However, with git, you never know if people have merged |
|
43 |
# commits into the middle of the repository history, so we |
|
|
44 | # parse the entire log. | |
|
43 | # commits into the middle of the repository history, so we should parse | |
|
44 | # the entire log. Since it's way too slow for large repositories, we only | |
|
45 | # parse 1 week before the last known commit. | |
|
46 | # The repository can still be fully reloaded by calling #clear_changesets | |
|
47 | # before fetching changesets (eg. for offline resync) | |
|
45 | 48 | def fetch_changesets |
|
46 | # Save ourselves an expensive operation if we're already up to date | |
|
47 | return if scm.num_revisions == changesets.count | |
|
49 | c = changesets.find(:first, :order => 'committed_on DESC') | |
|
50 | since = (c ? c.committed_on - 7.days : nil) | |
|
48 | 51 | |
|
49 | revisions = scm.revisions('', nil, nil, :all => true) | |
|
52 | revisions = scm.revisions('', nil, nil, :all => true, :since => since) | |
|
50 | 53 | return if revisions.nil? || revisions.empty? |
|
51 | 54 | |
|
52 | # Find revisions that redmine knows about already | |
|
53 | existing_revisions = changesets.find(:all).map!{|c| c.scmid} | |
|
55 | recent_changesets = changesets.find(:all, :conditions => ['committed_on >= ?', since]) | |
|
54 | 56 | |
|
55 | 57 | # Clean out revisions that are no longer in git |
|
56 | Changeset.delete_all(["scmid NOT IN (?) AND repository_id = (?)", revisions.map{|r| r.scmid}, self.id]) | |
|
58 | recent_changesets.each {|c| c.destroy unless revisions.detect {|r| r.scmid.to_s == c.scmid.to_s }} | |
|
57 | 59 | |
|
58 | 60 | # Subtract revisions that redmine already knows about |
|
59 | revisions.reject!{|r| existing_revisions.include?(r.scmid)} | |
|
61 | recent_revisions = recent_changesets.map{|c| c.scmid} | |
|
62 | revisions.reject!{|r| recent_revisions.include?(r.scmid)} | |
|
60 | 63 | |
|
61 | 64 | # Save the remaining ones to the database |
|
62 | 65 | revisions.each{|r| r.save(self)} unless revisions.nil? |
@@ -33,21 +33,22 module Redmine | |||
|
33 | 33 | end |
|
34 | 34 | |
|
35 | 35 | def branches |
|
36 |
|
|
|
36 | return @branches if @branches | |
|
37 | @branches = [] | |
|
37 | 38 | cmd = "#{GIT_BIN} --git-dir #{target('')} branch" |
|
38 | 39 | shellout(cmd) do |io| |
|
39 | 40 | io.each_line do |line| |
|
40 | branches << line.match('\s*\*?\s*(.*)$')[1] | |
|
41 | @branches << line.match('\s*\*?\s*(.*)$')[1] | |
|
41 | 42 | end |
|
42 | 43 | end |
|
43 | branches.sort! | |
|
44 | @branches.sort! | |
|
44 | 45 | end |
|
45 | 46 | |
|
46 | 47 | def tags |
|
47 |
|
|
|
48 | return @tags if @tags | |
|
48 | 49 | cmd = "#{GIT_BIN} --git-dir #{target('')} tag" |
|
49 | 50 | shellout(cmd) do |io| |
|
50 | io.readlines.sort!.map{|t| t.strip} | |
|
51 | @tags = io.readlines.sort!.map{|t| t.strip} | |
|
51 | 52 | end |
|
52 | 53 | end |
|
53 | 54 | |
@@ -110,20 +111,16 module Redmine | |||
|
110 | 111 | end |
|
111 | 112 | end |
|
112 | 113 | |
|
113 | def num_revisions | |
|
114 | cmd = "#{GIT_BIN} --git-dir #{target('')} log --all --pretty=format:'' | wc -l" | |
|
115 | shellout(cmd) {|io| io.gets.chomp.to_i + 1} | |
|
116 | end | |
|
117 | ||
|
118 | 114 | def revisions(path, identifier_from, identifier_to, options={}) |
|
119 | 115 | revisions = Revisions.new |
|
120 | 116 | |
|
121 |
cmd = "#{GIT_BIN} --git-dir #{target('')} log -- |
|
|
117 | cmd = "#{GIT_BIN} --git-dir #{target('')} log --raw --date=iso --pretty=fuller" | |
|
122 | 118 | cmd << " --reverse" if options[:reverse] |
|
123 | 119 | cmd << " --all" if options[:all] |
|
124 | 120 | cmd << " -n #{options[:limit]} " if options[:limit] |
|
125 | 121 | cmd << " #{shell_quote(identifier_from + '..')} " if identifier_from |
|
126 | 122 | cmd << " #{shell_quote identifier_to} " if identifier_to |
|
123 | cmd << " --since=#{shell_quote(options[:since].strftime("%Y-%m-%d %H:%M:%S"))}" if options[:since] | |
|
127 | 124 | cmd << " -- #{path}" if path && !path.empty? |
|
128 | 125 | |
|
129 | 126 | shellout(cmd) do |io| |
@@ -1,5 +1,7 | |||
|
1 | # redMine - project management software | |
|
2 | # Copyright (C) 2006-2007 Jean-Philippe Lang | |
|
1 | # encoding: utf-8 | |
|
2 | # | |
|
3 | # Redmine - project management software | |
|
4 | # Copyright (C) 2006-2010 Jean-Philippe Lang | |
|
3 | 5 | # |
|
4 | 6 | # This program is free software; you can redistribute it and/or |
|
5 | 7 | # modify it under the terms of the GNU General Public License |
@@ -117,4 +119,18 class ChangesetTest < ActiveSupport::TestCase | |||
|
117 | 119 | changeset = Changeset.find_by_revision('10') |
|
118 | 120 | assert_nil changeset.next |
|
119 | 121 | end |
|
122 | ||
|
123 | def test_comments_should_be_converted_to_utf8 | |
|
124 | with_settings :commit_logs_encoding => 'ISO-8859-1' do | |
|
125 | c = Changeset.new | |
|
126 | c.comments = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt") | |
|
127 | assert_equal "Texte encodé en ISO-8859-1.", c.comments | |
|
128 | end | |
|
129 | end | |
|
130 | ||
|
131 | def test_invalid_utf8_sequences_in_comments_should_be_stripped | |
|
132 | c = Changeset.new | |
|
133 | c.comments = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt") | |
|
134 | assert_equal "Texte encod en ISO-8859-1.", c.comments | |
|
135 | end | |
|
120 | 136 | end |
@@ -35,7 +35,7 class RepositoryGitTest < ActiveSupport::TestCase | |||
|
35 | 35 | @repository.reload |
|
36 | 36 | |
|
37 | 37 | assert_equal 12, @repository.changesets.count |
|
38 |
assert_equal 2 |
|
|
38 | assert_equal 21, @repository.changes.count | |
|
39 | 39 | |
|
40 | 40 | commit = @repository.changesets.find(:first, :order => 'committed_on ASC') |
|
41 | 41 | assert_equal "Initial import.\nThe repository contains 3 files.", commit.comments |
General Comments 0
You need to be logged in to leave comments.
Login now