##// END OF EJS Templates
scm: mercurial: latest changesets improvement and supporting tag (#1981)....
Toshi MARUYAMA -
r5003:c8ce22c2751a
parent child
Show More
@@ -1,125 +1,137
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require 'redmine/scm/adapters/mercurial_adapter'
18 require 'redmine/scm/adapters/mercurial_adapter'
19
19
20 class Repository::Mercurial < Repository
20 class Repository::Mercurial < Repository
21 # sort changesets by revision number
21 # sort changesets by revision number
22 has_many :changesets, :order => "#{Changeset.table_name}.id DESC", :foreign_key => 'repository_id'
22 has_many :changesets, :order => "#{Changeset.table_name}.id DESC", :foreign_key => 'repository_id'
23
23
24 attr_protected :root_url
24 attr_protected :root_url
25 validates_presence_of :url
25 validates_presence_of :url
26
26
27 FETCH_AT_ONCE = 100 # number of changesets to fetch at once
27 FETCH_AT_ONCE = 100 # number of changesets to fetch at once
28
28
29 ATTRIBUTE_KEY_NAMES = {
29 ATTRIBUTE_KEY_NAMES = {
30 "url" => "Root directory",
30 "url" => "Root directory",
31 }
31 }
32 def self.human_attribute_name(attribute_key_name)
32 def self.human_attribute_name(attribute_key_name)
33 ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
33 ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
34 end
34 end
35
35
36 def self.scm_adapter_class
36 def self.scm_adapter_class
37 Redmine::Scm::Adapters::MercurialAdapter
37 Redmine::Scm::Adapters::MercurialAdapter
38 end
38 end
39
39
40 def self.scm_name
40 def self.scm_name
41 'Mercurial'
41 'Mercurial'
42 end
42 end
43
43
44 def repo_log_encoding
44 def repo_log_encoding
45 'UTF-8'
45 'UTF-8'
46 end
46 end
47
47
48 # Returns the readable identifier for the given mercurial changeset
48 # Returns the readable identifier for the given mercurial changeset
49 def self.format_changeset_identifier(changeset)
49 def self.format_changeset_identifier(changeset)
50 "#{changeset.revision}:#{changeset.scmid}"
50 "#{changeset.revision}:#{changeset.scmid}"
51 end
51 end
52
52
53 # Returns the identifier for the given Mercurial changeset
53 # Returns the identifier for the given Mercurial changeset
54 def self.changeset_identifier(changeset)
54 def self.changeset_identifier(changeset)
55 changeset.scmid
55 changeset.scmid
56 end
56 end
57
57
58 def branches
58 def branches
59 nil
59 nil
60 end
60 end
61
61
62 def tags
62 def tags
63 nil
63 nil
64 end
64 end
65
65
66 def diff_format_revisions(cs, cs_to, sep=':')
66 def diff_format_revisions(cs, cs_to, sep=':')
67 super(cs, cs_to, ' ')
67 super(cs, cs_to, ' ')
68 end
68 end
69
69
70 # Finds and returns a revision with a number or the beginning of a hash
70 # Finds and returns a revision with a number or the beginning of a hash
71 def find_changeset_by_name(name)
71 def find_changeset_by_name(name)
72 return nil if name.nil? || name.empty?
72 return nil if name.nil? || name.empty?
73 if /[^\d]/ =~ name or name.to_s.size > 8
73 if /[^\d]/ =~ name or name.to_s.size > 8
74 e = changesets.find(:first, :conditions => ['scmid = ?', name.to_s])
74 e = changesets.find(:first, :conditions => ['scmid = ?', name.to_s])
75 else
75 else
76 e = changesets.find(:first, :conditions => ['revision = ?', name.to_s])
76 e = changesets.find(:first, :conditions => ['revision = ?', name.to_s])
77 end
77 end
78 return e if e
78 return e if e
79 changesets.find(:first, :conditions => ['scmid LIKE ?', "#{name}%"]) # last ditch
79 changesets.find(:first, :conditions => ['scmid LIKE ?', "#{name}%"]) # last ditch
80 end
80 end
81
81
82 # Returns the latest changesets for +path+; sorted by revision number
82 # Returns the latest changesets for +path+; sorted by revision number
83 # Default behavior is to search in cached changesets
84 #
83 #
85 # Because :order => 'id DESC' is defined at 'has_many',
84 # Because :order => 'id DESC' is defined at 'has_many',
86 # there is no need to set 'order'.
85 # there is no need to set 'order'.
87 # But, MySQL test fails.
86 # But, MySQL test fails.
88 # Sqlite3 and PostgreSQL pass.
87 # Sqlite3 and PostgreSQL pass.
89 # Is this MySQL bug?
88 # Is this MySQL bug?
90 def latest_changesets(path, rev, limit=10)
89 def latest_changesets(path, rev, limit=10)
91 if path.blank?
90 changesets.find(:all, :include => :user,
92 changesets.find(:all, :include => :user, :limit => limit, :order => 'id DESC')
91 :conditions => latest_changesets_cond(path, rev, limit),
93 else
92 :limit => limit, :order => "#{Changeset.table_name}.id DESC")
94 changesets.find(:all, :select => "DISTINCT #{Changeset.table_name}.*",
93 end
95 :joins => :changes,
94
96 :conditions => ["#{Change.table_name}.path = ? OR #{Change.table_name}.path LIKE ? ESCAPE ?",
95 def latest_changesets_cond(path, rev, limit)
97 path.with_leading_slash,
96 cond, args = [], []
98 "#{path.with_leading_slash.gsub(/[%_\\]/) { |s| "\\#{s}" }}/%", '\\'],
97
99 :include => :user, :limit => limit,
98 if last = rev ? find_changeset_by_name(scm.tagmap[rev] || rev) : nil
100 :order => "#{Changeset.table_name}.id DESC" )
99 cond << "#{Changeset.table_name}.id <= ?"
100 args << last.id
101 end
101 end
102
103 unless path.blank?
104 cond << "EXISTS (SELECT * FROM #{Change.table_name}
105 WHERE #{Change.table_name}.changeset_id = #{Changeset.table_name}.id
106 AND (#{Change.table_name}.path = ?
107 OR #{Change.table_name}.path LIKE ? ESCAPE ?))"
108 args << path.with_leading_slash
109 args << "#{path.with_leading_slash.gsub(/[%_\\]/) { |s| "\\#{s}" }}/%" << '\\'
110 end
111
112 [cond.join(' AND '), *args] unless cond.empty?
102 end
113 end
114 private :latest_changesets_cond
103
115
104 def fetch_changesets
116 def fetch_changesets
105 scm_rev = scm.info.lastrev.revision.to_i
117 scm_rev = scm.info.lastrev.revision.to_i
106 db_rev = latest_changeset ? latest_changeset.revision.to_i : -1
118 db_rev = latest_changeset ? latest_changeset.revision.to_i : -1
107 return unless db_rev < scm_rev # already up-to-date
119 return unless db_rev < scm_rev # already up-to-date
108
120
109 logger.debug "Fetching changesets for repository #{url}" if logger
121 logger.debug "Fetching changesets for repository #{url}" if logger
110 (db_rev + 1).step(scm_rev, FETCH_AT_ONCE) do |i|
122 (db_rev + 1).step(scm_rev, FETCH_AT_ONCE) do |i|
111 transaction do
123 transaction do
112 scm.each_revision('', i, [i + FETCH_AT_ONCE - 1, scm_rev].min) do |re|
124 scm.each_revision('', i, [i + FETCH_AT_ONCE - 1, scm_rev].min) do |re|
113 cs = Changeset.create(:repository => self,
125 cs = Changeset.create(:repository => self,
114 :revision => re.revision,
126 :revision => re.revision,
115 :scmid => re.scmid,
127 :scmid => re.scmid,
116 :committer => re.author,
128 :committer => re.author,
117 :committed_on => re.time,
129 :committed_on => re.time,
118 :comments => re.message)
130 :comments => re.message)
119 re.paths.each { |e| cs.create_change(e) }
131 re.paths.each { |e| cs.create_change(e) }
120 end
132 end
121 end
133 end
122 end
134 end
123 self
135 self
124 end
136 end
125 end
137 end
@@ -1,337 +1,337
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19 require 'repositories_controller'
19 require 'repositories_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class RepositoriesController; def rescue_action(e) raise e end; end
22 class RepositoriesController; def rescue_action(e) raise e end; end
23
23
24 class RepositoriesMercurialControllerTest < ActionController::TestCase
24 class RepositoriesMercurialControllerTest < ActionController::TestCase
25 fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules
25 fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules
26
26
27 # No '..' in the repository path
27 # No '..' in the repository path
28 REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/mercurial_repository'
28 REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/mercurial_repository'
29 CHAR_1_HEX = "\xc3\x9c"
29 CHAR_1_HEX = "\xc3\x9c"
30
30
31 ruby19_non_utf8_pass = (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
31 ruby19_non_utf8_pass = (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
32
32
33 def setup
33 def setup
34 @controller = RepositoriesController.new
34 @controller = RepositoriesController.new
35 @request = ActionController::TestRequest.new
35 @request = ActionController::TestRequest.new
36 @response = ActionController::TestResponse.new
36 @response = ActionController::TestResponse.new
37 User.current = nil
37 User.current = nil
38 @repository = Repository::Mercurial.create(
38 @repository = Repository::Mercurial.create(
39 :project => Project.find(3),
39 :project => Project.find(3),
40 :url => REPOSITORY_PATH,
40 :url => REPOSITORY_PATH,
41 :path_encoding => 'ISO-8859-1'
41 :path_encoding => 'ISO-8859-1'
42 )
42 )
43 assert @repository
43 assert @repository
44 @diff_c_support = true
44 @diff_c_support = true
45 @char_1 = CHAR_1_HEX.dup
45 @char_1 = CHAR_1_HEX.dup
46 @tag_char_1 = "tag-#{CHAR_1_HEX}-00"
46 @tag_char_1 = "tag-#{CHAR_1_HEX}-00"
47 @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
47 @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
48 @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
48 @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
49 if @char_1.respond_to?(:force_encoding)
49 if @char_1.respond_to?(:force_encoding)
50 @char_1.force_encoding('UTF-8')
50 @char_1.force_encoding('UTF-8')
51 @tag_char_1.force_encoding('UTF-8')
51 @tag_char_1.force_encoding('UTF-8')
52 @branch_char_0.force_encoding('UTF-8')
52 @branch_char_0.force_encoding('UTF-8')
53 @branch_char_1.force_encoding('UTF-8')
53 @branch_char_1.force_encoding('UTF-8')
54 end
54 end
55 end
55 end
56
56
57 if ruby19_non_utf8_pass
57 if ruby19_non_utf8_pass
58 puts "TODO: Mercurial functional test fails in Ruby 1.9 " +
58 puts "TODO: Mercurial functional test fails in Ruby 1.9 " +
59 "and Encoding.default_external is not UTF-8. " +
59 "and Encoding.default_external is not UTF-8. " +
60 "Current value is '#{Encoding.default_external.to_s}'"
60 "Current value is '#{Encoding.default_external.to_s}'"
61 def test_fake; assert true end
61 def test_fake; assert true end
62 elsif File.directory?(REPOSITORY_PATH)
62 elsif File.directory?(REPOSITORY_PATH)
63 def test_show
63 def test_show
64 get :show, :id => 3
64 get :show, :id => 3
65 assert_response :success
65 assert_response :success
66 assert_template 'show'
66 assert_template 'show'
67 assert_not_nil assigns(:entries)
67 assert_not_nil assigns(:entries)
68 assert_not_nil assigns(:changesets)
68 assert_not_nil assigns(:changesets)
69 end
69 end
70
70
71 def test_show_root
71 def test_show_root
72 @repository.fetch_changesets
72 @repository.fetch_changesets
73 @repository.reload
73 @repository.reload
74 get :show, :id => 3
74 get :show, :id => 3
75 assert_response :success
75 assert_response :success
76 assert_template 'show'
76 assert_template 'show'
77 assert_not_nil assigns(:entries)
77 assert_not_nil assigns(:entries)
78 assert_equal 4, assigns(:entries).size
78 assert_equal 4, assigns(:entries).size
79 assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
79 assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
80 assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
80 assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
81 assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
81 assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
82 assert_not_nil assigns(:changesets)
82 assert_not_nil assigns(:changesets)
83 assigns(:changesets).size > 0
83 assigns(:changesets).size > 0
84 end
84 end
85
85
86 def test_show_directory
86 def test_show_directory
87 @repository.fetch_changesets
87 @repository.fetch_changesets
88 @repository.reload
88 @repository.reload
89 get :show, :id => 3, :path => ['images']
89 get :show, :id => 3, :path => ['images']
90 assert_response :success
90 assert_response :success
91 assert_template 'show'
91 assert_template 'show'
92 assert_not_nil assigns(:entries)
92 assert_not_nil assigns(:entries)
93 assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
93 assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
94 entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
94 entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
95 assert_not_nil entry
95 assert_not_nil entry
96 assert_equal 'file', entry.kind
96 assert_equal 'file', entry.kind
97 assert_equal 'images/edit.png', entry.path
97 assert_equal 'images/edit.png', entry.path
98 assert_not_nil assigns(:changesets)
98 assert_not_nil assigns(:changesets)
99 assigns(:changesets).size > 0
99 assigns(:changesets).size > 0
100 end
100 end
101
101
102 def test_show_at_given_revision
102 def test_show_at_given_revision
103 @repository.fetch_changesets
103 @repository.fetch_changesets
104 @repository.reload
104 @repository.reload
105 [0, '0', '0885933ad4f6'].each do |r1|
105 [0, '0', '0885933ad4f6'].each do |r1|
106 get :show, :id => 3, :path => ['images'], :rev => r1
106 get :show, :id => 3, :path => ['images'], :rev => r1
107 assert_response :success
107 assert_response :success
108 assert_template 'show'
108 assert_template 'show'
109 assert_not_nil assigns(:entries)
109 assert_not_nil assigns(:entries)
110 assert_equal ['delete.png'], assigns(:entries).collect(&:name)
110 assert_equal ['delete.png'], assigns(:entries).collect(&:name)
111 assert_not_nil assigns(:changesets)
111 assert_not_nil assigns(:changesets)
112 assigns(:changesets).size > 0
112 assigns(:changesets).size > 0
113 end
113 end
114 end
114 end
115
115
116 def test_show_directory_sql_escape_percent
116 def test_show_directory_sql_escape_percent
117 @repository.fetch_changesets
117 @repository.fetch_changesets
118 @repository.reload
118 @repository.reload
119 [13, '13', '3a330eb32958'].each do |r1|
119 [13, '13', '3a330eb32958'].each do |r1|
120 get :show, :id => 3, :path => ['sql_escape', 'percent%dir'], :rev => r1
120 get :show, :id => 3, :path => ['sql_escape', 'percent%dir'], :rev => r1
121 assert_response :success
121 assert_response :success
122 assert_template 'show'
122 assert_template 'show'
123
123
124 assert_not_nil assigns(:entries)
124 assert_not_nil assigns(:entries)
125 assert_equal ['percent%file1.txt', 'percentfile1.txt'], assigns(:entries).collect(&:name)
125 assert_equal ['percent%file1.txt', 'percentfile1.txt'], assigns(:entries).collect(&:name)
126 changesets = assigns(:changesets)
126 changesets = assigns(:changesets)
127 assigns(:changesets).size > 0
127 assigns(:changesets).size > 0
128
128
129 ## This is not yet implemented.
129 ## This is not yet implemented.
130 # assert_not_nil changesets
130 # assert_not_nil changesets
131 # assert_equal %w(13 11 10 9), changesets.collect(&:revision)
131 # assert_equal %w(13 11 10 9), changesets.collect(&:revision)
132 end
132 end
133 end
133 end
134
134
135 def test_show_directory_latin_1
135 def test_show_directory_latin_1
136 @repository.fetch_changesets
136 @repository.fetch_changesets
137 @repository.reload
137 @repository.reload
138 [21, '21', 'adf805632193'].each do |r1|
138 [21, '21', 'adf805632193'].each do |r1|
139 get :show, :id => 3, :path => ['latin-1-dir'], :rev => r1
139 get :show, :id => 3, :path => ['latin-1-dir'], :rev => r1
140 assert_response :success
140 assert_response :success
141 assert_template 'show'
141 assert_template 'show'
142
142
143 assert_not_nil assigns(:entries)
143 assert_not_nil assigns(:entries)
144 assert_equal ["make-latin-1-file.rb",
144 assert_equal ["make-latin-1-file.rb",
145 "test-#{@char_1}-1.txt",
145 "test-#{@char_1}-1.txt",
146 "test-#{@char_1}-2.txt",
146 "test-#{@char_1}-2.txt",
147 "test-#{@char_1}.txt"], assigns(:entries).collect(&:name)
147 "test-#{@char_1}.txt"], assigns(:entries).collect(&:name)
148 changesets = assigns(:changesets)
148 changesets = assigns(:changesets)
149 assert_not_nil changesets
149 assert_not_nil changesets
150 assert_equal %w(27 21 20 19 18 17), changesets.collect(&:revision)
150 assert_equal %w(21 20 19 18 17), changesets.collect(&:revision)
151 end
151 end
152 end
152 end
153
153
154 def test_changes
154 def test_changes
155 get :changes, :id => 3, :path => ['images', 'edit.png']
155 get :changes, :id => 3, :path => ['images', 'edit.png']
156 assert_response :success
156 assert_response :success
157 assert_template 'changes'
157 assert_template 'changes'
158 assert_tag :tag => 'h2', :content => 'edit.png'
158 assert_tag :tag => 'h2', :content => 'edit.png'
159 end
159 end
160
160
161 def test_entry_show
161 def test_entry_show
162 get :entry, :id => 3, :path => ['sources', 'watchers_controller.rb']
162 get :entry, :id => 3, :path => ['sources', 'watchers_controller.rb']
163 assert_response :success
163 assert_response :success
164 assert_template 'entry'
164 assert_template 'entry'
165 # Line 10
165 # Line 10
166 assert_tag :tag => 'th',
166 assert_tag :tag => 'th',
167 :content => '10',
167 :content => '10',
168 :attributes => { :class => 'line-num' },
168 :attributes => { :class => 'line-num' },
169 :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
169 :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
170 end
170 end
171
171
172 def test_entry_show_latin_1
172 def test_entry_show_latin_1
173 [21, '21', 'adf805632193'].each do |r1|
173 [21, '21', 'adf805632193'].each do |r1|
174 get :entry, :id => 3, :path => ['latin-1-dir', "test-#{@char_1}-2.txt"], :rev => r1
174 get :entry, :id => 3, :path => ['latin-1-dir', "test-#{@char_1}-2.txt"], :rev => r1
175 assert_response :success
175 assert_response :success
176 assert_template 'entry'
176 assert_template 'entry'
177 assert_tag :tag => 'th',
177 assert_tag :tag => 'th',
178 :content => '1',
178 :content => '1',
179 :attributes => { :class => 'line-num' },
179 :attributes => { :class => 'line-num' },
180 :sibling => { :tag => 'td', :content => /Mercurial is a distributed version control system/ }
180 :sibling => { :tag => 'td', :content => /Mercurial is a distributed version control system/ }
181 end
181 end
182 end
182 end
183
183
184 def test_entry_download
184 def test_entry_download
185 get :entry, :id => 3, :path => ['sources', 'watchers_controller.rb'], :format => 'raw'
185 get :entry, :id => 3, :path => ['sources', 'watchers_controller.rb'], :format => 'raw'
186 assert_response :success
186 assert_response :success
187 # File content
187 # File content
188 assert @response.body.include?('WITHOUT ANY WARRANTY')
188 assert @response.body.include?('WITHOUT ANY WARRANTY')
189 end
189 end
190
190
191 def test_directory_entry
191 def test_directory_entry
192 get :entry, :id => 3, :path => ['sources']
192 get :entry, :id => 3, :path => ['sources']
193 assert_response :success
193 assert_response :success
194 assert_template 'show'
194 assert_template 'show'
195 assert_not_nil assigns(:entry)
195 assert_not_nil assigns(:entry)
196 assert_equal 'sources', assigns(:entry).name
196 assert_equal 'sources', assigns(:entry).name
197 end
197 end
198
198
199 def test_diff
199 def test_diff
200 @repository.fetch_changesets
200 @repository.fetch_changesets
201 @repository.reload
201 @repository.reload
202
202
203 [4, '4', 'def6d2f1254a'].each do |r1|
203 [4, '4', 'def6d2f1254a'].each do |r1|
204 # Full diff of changeset 4
204 # Full diff of changeset 4
205 get :diff, :id => 3, :rev => r1
205 get :diff, :id => 3, :rev => r1
206 assert_response :success
206 assert_response :success
207 assert_template 'diff'
207 assert_template 'diff'
208
208
209 if @diff_c_support
209 if @diff_c_support
210 # Line 22 removed
210 # Line 22 removed
211 assert_tag :tag => 'th',
211 assert_tag :tag => 'th',
212 :content => '22',
212 :content => '22',
213 :sibling => { :tag => 'td',
213 :sibling => { :tag => 'td',
214 :attributes => { :class => /diff_out/ },
214 :attributes => { :class => /diff_out/ },
215 :content => /def remove/ }
215 :content => /def remove/ }
216 assert_tag :tag => 'h2', :content => /4:def6d2f1254a/
216 assert_tag :tag => 'h2', :content => /4:def6d2f1254a/
217 end
217 end
218 end
218 end
219 end
219 end
220
220
221 def test_diff_two_revs
221 def test_diff_two_revs
222 @repository.fetch_changesets
222 @repository.fetch_changesets
223 @repository.reload
223 @repository.reload
224
224
225 [2, '400bb8672109', '400', 400].each do |r1|
225 [2, '400bb8672109', '400', 400].each do |r1|
226 [4, 'def6d2f1254a'].each do |r2|
226 [4, 'def6d2f1254a'].each do |r2|
227 get :diff, :id => 3, :rev => r1,
227 get :diff, :id => 3, :rev => r1,
228 :rev_to => r2
228 :rev_to => r2
229 assert_response :success
229 assert_response :success
230 assert_template 'diff'
230 assert_template 'diff'
231
231
232 diff = assigns(:diff)
232 diff = assigns(:diff)
233 assert_not_nil diff
233 assert_not_nil diff
234 assert_tag :tag => 'h2', :content => /4:def6d2f1254a 2:400bb8672109/
234 assert_tag :tag => 'h2', :content => /4:def6d2f1254a 2:400bb8672109/
235 end
235 end
236 end
236 end
237 end
237 end
238
238
239 def test_diff_latin_1
239 def test_diff_latin_1
240 [21, 'adf805632193'].each do |r1|
240 [21, 'adf805632193'].each do |r1|
241 get :diff, :id => 3, :rev => r1
241 get :diff, :id => 3, :rev => r1
242 assert_response :success
242 assert_response :success
243 assert_template 'diff'
243 assert_template 'diff'
244 assert_tag :tag => 'th',
244 assert_tag :tag => 'th',
245 :content => '2',
245 :content => '2',
246 :sibling => { :tag => 'td',
246 :sibling => { :tag => 'td',
247 :attributes => { :class => /diff_in/ },
247 :attributes => { :class => /diff_in/ },
248 :content => /It is written in Python/ }
248 :content => /It is written in Python/ }
249 end
249 end
250 end
250 end
251
251
252 def test_annotate
252 def test_annotate
253 get :annotate, :id => 3, :path => ['sources', 'watchers_controller.rb']
253 get :annotate, :id => 3, :path => ['sources', 'watchers_controller.rb']
254 assert_response :success
254 assert_response :success
255 assert_template 'annotate'
255 assert_template 'annotate'
256 # Line 23, revision 4:def6d2f1254a
256 # Line 23, revision 4:def6d2f1254a
257 assert_tag :tag => 'th',
257 assert_tag :tag => 'th',
258 :content => '23',
258 :content => '23',
259 :attributes => { :class => 'line-num' },
259 :attributes => { :class => 'line-num' },
260 :sibling =>
260 :sibling =>
261 {
261 {
262 :tag => 'td',
262 :tag => 'td',
263 :attributes => { :class => 'revision' },
263 :attributes => { :class => 'revision' },
264 :child => { :tag => 'a', :content => '4:def6d2f1254a' }
264 :child => { :tag => 'a', :content => '4:def6d2f1254a' }
265 }
265 }
266 assert_tag :tag => 'th',
266 assert_tag :tag => 'th',
267 :content => '23',
267 :content => '23',
268 :attributes => { :class => 'line-num' },
268 :attributes => { :class => 'line-num' },
269 :sibling =>
269 :sibling =>
270 {
270 {
271 :tag => 'td' ,
271 :tag => 'td' ,
272 :content => 'jsmith' ,
272 :content => 'jsmith' ,
273 :attributes => { :class => 'author' },
273 :attributes => { :class => 'author' },
274 }
274 }
275 assert_tag :tag => 'th',
275 assert_tag :tag => 'th',
276 :content => '23',
276 :content => '23',
277 :attributes => { :class => 'line-num' },
277 :attributes => { :class => 'line-num' },
278 :sibling => { :tag => 'td', :content => /watcher =/ }
278 :sibling => { :tag => 'td', :content => /watcher =/ }
279 end
279 end
280
280
281 def test_annotate_at_given_revision
281 def test_annotate_at_given_revision
282 @repository.fetch_changesets
282 @repository.fetch_changesets
283 @repository.reload
283 @repository.reload
284 [2, '400bb8672109', '400', 400].each do |r1|
284 [2, '400bb8672109', '400', 400].each do |r1|
285 get :annotate, :id => 3, :rev => r1, :path => ['sources', 'watchers_controller.rb']
285 get :annotate, :id => 3, :rev => r1, :path => ['sources', 'watchers_controller.rb']
286 assert_response :success
286 assert_response :success
287 assert_template 'annotate'
287 assert_template 'annotate'
288 assert_tag :tag => 'h2', :content => /@ 2:400bb8672109/
288 assert_tag :tag => 'h2', :content => /@ 2:400bb8672109/
289 end
289 end
290 end
290 end
291
291
292 def test_annotate_latin_1
292 def test_annotate_latin_1
293 [21, '21', 'adf805632193'].each do |r1|
293 [21, '21', 'adf805632193'].each do |r1|
294 get :annotate, :id => 3, :path => ['latin-1-dir', "test-#{@char_1}-2.txt"], :rev => r1
294 get :annotate, :id => 3, :path => ['latin-1-dir', "test-#{@char_1}-2.txt"], :rev => r1
295 assert_response :success
295 assert_response :success
296 assert_template 'annotate'
296 assert_template 'annotate'
297 assert_tag :tag => 'th',
297 assert_tag :tag => 'th',
298 :content => '1',
298 :content => '1',
299 :attributes => { :class => 'line-num' },
299 :attributes => { :class => 'line-num' },
300 :sibling =>
300 :sibling =>
301 {
301 {
302 :tag => 'td',
302 :tag => 'td',
303 :attributes => { :class => 'revision' },
303 :attributes => { :class => 'revision' },
304 :child => { :tag => 'a', :content => '20:709858aafd1b' }
304 :child => { :tag => 'a', :content => '20:709858aafd1b' }
305 }
305 }
306 assert_tag :tag => 'th',
306 assert_tag :tag => 'th',
307 :content => '1',
307 :content => '1',
308 :attributes => { :class => 'line-num' },
308 :attributes => { :class => 'line-num' },
309 :sibling =>
309 :sibling =>
310 {
310 {
311 :tag => 'td' ,
311 :tag => 'td' ,
312 :content => 'jsmith' ,
312 :content => 'jsmith' ,
313 :attributes => { :class => 'author' },
313 :attributes => { :class => 'author' },
314
314
315 }
315 }
316 assert_tag :tag => 'th',
316 assert_tag :tag => 'th',
317 :content => '1',
317 :content => '1',
318 :attributes => { :class => 'line-num' },
318 :attributes => { :class => 'line-num' },
319 :sibling => { :tag => 'td', :content => /Mercurial is a distributed version control system/ }
319 :sibling => { :tag => 'td', :content => /Mercurial is a distributed version control system/ }
320
320
321 end
321 end
322 end
322 end
323
323
324 def test_empty_revision
324 def test_empty_revision
325 @repository.fetch_changesets
325 @repository.fetch_changesets
326 @repository.reload
326 @repository.reload
327 ['', ' ', nil].each do |r|
327 ['', ' ', nil].each do |r|
328 get :revision, :id => 3, :rev => r
328 get :revision, :id => 3, :rev => r
329 assert_response 404
329 assert_response 404
330 assert_error_tag :content => /was not found/
330 assert_error_tag :content => /was not found/
331 end
331 end
332 end
332 end
333 else
333 else
334 puts "Mercurial test repository NOT FOUND. Skipping functional tests !!!"
334 puts "Mercurial test repository NOT FOUND. Skipping functional tests !!!"
335 def test_fake; assert true end
335 def test_fake; assert true end
336 end
336 end
337 end
337 end
General Comments 0
You need to be logged in to leave comments. Login now