##// END OF EJS Templates
Merged r5091 from trunk....
Toshi MARUYAMA -
r4972:891ed84fe39e
parent child
Show More
@@ -1,105 +1,105
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require 'redmine/scm/adapters/mercurial_adapter'
19 19
20 20 class Repository::Mercurial < Repository
21 21 # sort changesets by revision number
22 22 has_many :changesets, :order => "#{Changeset.table_name}.id DESC", :foreign_key => 'repository_id'
23 23
24 24 attr_protected :root_url
25 25 validates_presence_of :url
26 26
27 27 def scm_adapter
28 28 Redmine::Scm::Adapters::MercurialAdapter
29 29 end
30 30
31 31 def self.scm_name
32 32 'Mercurial'
33 33 end
34 34
35 35 def entries(path=nil, identifier=nil)
36 36 entries=scm.entries(path, identifier)
37 37 if entries
38 38 entries.each do |entry|
39 39 next unless entry.is_file?
40 40 # Set the filesize unless browsing a specific revision
41 41 if identifier.nil?
42 42 full_path = File.join(root_url, entry.path)
43 43 entry.size = File.stat(full_path).size if File.file?(full_path)
44 44 end
45 45 # Search the DB for the entry's last change
46 46 change = changes.find(:first, :conditions => ["path = ?", scm.with_leading_slash(entry.path)], :order => "#{Changeset.table_name}.committed_on DESC")
47 47 if change
48 48 entry.lastrev.identifier = change.changeset.revision
49 49 entry.lastrev.name = change.changeset.revision
50 50 entry.lastrev.author = change.changeset.committer
51 51 entry.lastrev.revision = change.revision
52 52 end
53 53 end
54 54 end
55 55 entries
56 56 end
57 57
58 58 # Returns the latest changesets for +path+; sorted by revision number
59 59 def latest_changesets(path, rev, limit=10)
60 60 if path.blank?
61 changesets.find(:all, :include => :user, :limit => limit)
61 changesets.find(:all, :include => :user, :limit => limit, :order => "id DESC")
62 62 else
63 63 changes.find(:all, :include => {:changeset => :user},
64 64 :conditions => ["path = ?", path.with_leading_slash],
65 65 :order => "#{Changeset.table_name}.id DESC",
66 66 :limit => limit).collect(&:changeset)
67 67 end
68 68 end
69 69
70 70 def fetch_changesets
71 71 scm_info = scm.info
72 72 if scm_info
73 73 # latest revision found in database
74 74 db_revision = latest_changeset ? latest_changeset.revision.to_i : -1
75 75 # latest revision in the repository
76 76 latest_revision = scm_info.lastrev
77 77 return if latest_revision.nil?
78 78 scm_revision = latest_revision.identifier.to_i
79 79 if db_revision < scm_revision
80 80 logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
81 81 identifier_from = db_revision + 1
82 82 while (identifier_from <= scm_revision)
83 83 # loads changesets by batches of 100
84 84 identifier_to = [identifier_from + 99, scm_revision].min
85 85 revisions = scm.revisions('', identifier_from, identifier_to, :with_paths => true)
86 86 transaction do
87 87 revisions.each do |revision|
88 88 changeset = Changeset.create(:repository => self,
89 89 :revision => revision.identifier,
90 90 :scmid => revision.scmid,
91 91 :committer => revision.author,
92 92 :committed_on => revision.time,
93 93 :comments => revision.message)
94 94
95 95 revision.paths.each do |change|
96 96 changeset.create_change(change)
97 97 end
98 98 end
99 99 end unless revisions.nil?
100 100 identifier_from = identifier_to + 1
101 101 end
102 102 end
103 103 end
104 104 end
105 105 end
@@ -1,129 +1,130
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 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
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class RepositoryMercurialTest < ActiveSupport::TestCase
21 21 fixtures :projects
22 22
23 23 # No '..' in the repository path
24 24 REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/mercurial_repository'
25 25
26 26 def setup
27 27 @project = Project.find(1)
28 28 assert @repository = Repository::Mercurial.create(:project => @project, :url => REPOSITORY_PATH)
29 29 end
30 30
31 31 if File.directory?(REPOSITORY_PATH)
32 32 def test_fetch_changesets_from_scratch
33 33 @repository.fetch_changesets
34 34 @repository.reload
35 35
36 36 assert_equal 17, @repository.changesets.count
37 37 assert_equal 25, @repository.changes.count
38 38 assert_equal "Initial import.\nThe repository contains 3 files.", @repository.changesets.find_by_revision('0').comments
39 39 end
40 40
41 41 def test_fetch_changesets_incremental
42 42 @repository.fetch_changesets
43 43 # Remove changesets with revision > 2
44 44 @repository.changesets.find(:all).each {|c| c.destroy if c.revision.to_i > 2}
45 45 @repository.reload
46 46 assert_equal 3, @repository.changesets.count
47 47
48 48 @repository.fetch_changesets
49 49 assert_equal 17, @repository.changesets.count
50 50 end
51 51
52 52 def test_entries
53 53 assert_equal 2, @repository.entries("sources", 2).size
54 54 assert_equal 1, @repository.entries("sources", 3).size
55 55 end
56 56
57 57 def test_locate_on_outdated_repository
58 58 assert_equal 1, @repository.entries("images", 0).size
59 59 assert_equal 2, @repository.entries("images").size
60 60 assert_equal 2, @repository.entries("images", 2).size
61 61 end
62 62
63 63 def test_isodatesec
64 64 # Template keyword 'isodatesec' supported in Mercurial 1.0 and higher
65 65 if @repository.scm.class.client_version_above?([1, 0])
66 66 @repository.fetch_changesets
67 67 @repository.reload
68 68 rev0_committed_on = Time.gm(2007, 12, 14, 9, 22, 52)
69 69 assert_equal @repository.changesets.find_by_revision('0').committed_on, rev0_committed_on
70 70 end
71 71 end
72 72
73 73 def test_changeset_order_by_revision
74 74 @repository.fetch_changesets
75 75 @repository.reload
76 76
77 77 c0 = @repository.latest_changeset
78 78 c1 = @repository.changesets.find_by_revision('0')
79 79 # sorted by revision (id), not by date
80 80 assert c0.revision.to_i > c1.revision.to_i
81 81 assert c0.committed_on < c1.committed_on
82 82 end
83 83
84 84 def test_latest_changesets
85 85 @repository.fetch_changesets
86 86 @repository.reload
87 87
88 88 # with_limit
89 89 changesets = @repository.latest_changesets('', nil, 2)
90 assert_equal @repository.latest_changesets('', nil)[0, 2], changesets
90 # assert_equal @repository.latest_changesets('', nil)[0, 2], changesets
91 assert_equal %w|16 15|, changesets.collect(&:revision)
91 92
92 93 # with_filepath
93 94 changesets = @repository.latest_changesets('/sql_escape/percent%dir/percent%file1.txt', nil)
94 95 assert_equal %w|11 10 9|, changesets.collect(&:revision)
95 96
96 97 changesets = @repository.latest_changesets('/sql_escape/underscore_dir/understrike_file.txt', nil)
97 98 assert_equal %w|12 9|, changesets.collect(&:revision)
98 99 end
99 100
100 101 def test_copied_files
101 102 @repository.fetch_changesets
102 103 @repository.reload
103 104
104 105 cs1 = @repository.changesets.find_by_revision('13')
105 106 assert_not_nil cs1
106 107 c1 = cs1.changes.sort_by(&:path)
107 108 assert_equal 2, c1.size
108 109
109 110 assert_equal 'A', c1[0].action
110 111 assert_equal '/sql_escape/percent%dir/percentfile1.txt', c1[0].path
111 112 assert_equal '/sql_escape/percent%dir/percent%file1.txt', c1[0].from_path
112 113
113 114 assert_equal 'A', c1[1].action
114 115 assert_equal '/sql_escape/underscore_dir/understrike-file.txt', c1[1].path
115 116 assert_equal '/sql_escape/underscore_dir/understrike_file.txt', c1[1].from_path
116 117
117 118 cs2 = @repository.changesets.find_by_revision('15')
118 119 c2 = cs2.changes
119 120 assert_equal 1, c2.size
120 121
121 122 assert_equal 'A', c2[0].action
122 123 assert_equal '/README (1)[2]&,%.-3_4', c2[0].path
123 124 assert_equal '/README', c2[0].from_path
124 125 end
125 126 else
126 127 puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!"
127 128 def test_fake; assert true end
128 129 end
129 130 end
General Comments 0
You need to be logged in to leave comments. Login now