Project

General

Profile

Defect #7064 » hg-2010-12-10.diff

Toshi MARUYAMA, 2010-12-10 09:17

View differences:

app/helpers/repositories_helper.rb
166 166
  end
167 167
  
168 168
  def mercurial_field_tags(form, repository)
169
      content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)))
169
    content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?))) +
170
    content_tag('p', form.select(:path_encoding, [nil] + Setting::ENCODINGS,
171
                                 :label => 'Path encoding'))
170 172
  end
171 173

  
172 174
  def git_field_tags(form, repository)
app/models/repository.rb
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
require 'redmine/scm/adapters/path_encodable_wrapper'
19

  
18 20
class Repository < ActiveRecord::Base
19 21
  belongs_to :project
20 22
  has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
......
38 40
  end
39 41

  
40 42
  def scm
41
    @scm ||= self.scm_adapter.new url, root_url, login, password
43
    @scm ||= new_scm
42 44
    update_attribute(:root_url, @scm.root_url) if root_url.blank?
43 45
    @scm
44 46
  end
......
105 107
  # Default behaviour is to search in cached changesets
106 108
  def latest_changesets(path, rev, limit=10)
107 109
    if path.blank?
108
      changesets.find(:all, :include => :user,
109
                            :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
110
                            :limit => limit)
110
      changesets.find(:all, :include => :user, :limit => limit)
111 111
    else
112
      changes.find(:all, :include => {:changeset => :user}, 
113
                         :conditions => ["path = ?", path.with_leading_slash],
114
                         :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
115
                         :limit => limit).collect(&:changeset)
112
      changesets.find(:all, :select => "DISTINCT #{Changeset.table_name}.*",
113
                      :joins => :changes,
114
                      :conditions => ["#{Change.table_name}.path = ? OR #{Change.table_name}.path LIKE ? ESCAPE ?",
115
                                      path.with_leading_slash,
116
                                      "#{path.with_leading_slash.gsub(/[%_\\]/) { |s| "\\#{s}" }}/%", '\\'],
117
                      :include => :user, :limit => limit)
116 118
    end
117 119
  end
118 120
    
......
198 200
  end
199 201
  
200 202
  private
203

  
204
  def new_scm
205
    scm = self.scm_adapter.new url, root_url, login, password
206
    scm = Redmine::Scm::Adapters::PathEncodableWrapper.new(scm, path_encoding) unless path_encoding.blank?
207
    scm
208
  end
201 209
  
202 210
  def before_save
203 211
    # Strips url and root_url
app/models/repository/mercurial.rb
18 18
require 'redmine/scm/adapters/mercurial_adapter'
19 19

  
20 20
class Repository::Mercurial < Repository
21
  # sort changesets by revision number
22
  has_many :changesets, :order => "#{Changeset.table_name}.id DESC", :foreign_key => 'repository_id'
23

  
21 24
  attr_protected :root_url
22 25
  validates_presence_of :url
23 26

  
db/migrate/20101115000000_add_repositories_path_encoding.rb
1
class AddRepositoriesPathEncoding < ActiveRecord::Migration
2
  def self.up
3
    add_column :repositories, :path_encoding, :string, :limit => 64, :default => nil
4
  end
5

  
6
  def self.down
7
    remove_column :repositories, :path_encoding
8
  end
9
end
lib/redmine/scm/adapters/mercurial/hg-template-0.9.5.tmpl
3 3
changeset_verbose = 'This template must be used with --debug option\n'
4 4
changeset_debug = '<logentry revision="{rev}" node="{node|short}">\n<author>{author|escape}</author>\n<date>{date|isodate}</date>\n<paths>\n{files}{file_adds}{file_dels}{file_copies}</paths>\n<msg>{desc|escape}</msg>\n{tags}</logentry>\n\n'
5 5

  
6
file = '<path action="M">{file|escape}</path>\n'
7
file_add = '<path action="A">{file_add|escape}</path>\n'
8
file_del = '<path action="D">{file_del|escape}</path>\n'
9
file_copy = '<path-copied copyfrom-path="{source|escape}">{name|urlescape}</path-copied>\n'
6
file = '<path action="M">{file|urlescape}</path>\n'
7
file_add = '<path action="A">{file_add|urlescape}</path>\n'
8
file_del = '<path action="D">{file_del|urlescape}</path>\n'
9
file_copy = '<path-copied copyfrom-path="{source|urlescape}">{name|urlescape}</path-copied>\n'
10 10
tag = '<tag>{tag|escape}</tag>\n'
11 11
header='<?xml version="1.0" encoding="UTF-8" ?>\n<log>\n\n'
12 12
# footer="</log>"
lib/redmine/scm/adapters/mercurial/hg-template-1.0.tmpl
3 3
changeset_verbose = 'This template must be used with --debug option\n'
4 4
changeset_debug = '<logentry revision="{rev}" node="{node|short}">\n<author>{author|escape}</author>\n<date>{date|isodate}</date>\n<paths>\n{file_mods}{file_adds}{file_dels}{file_copies}</paths>\n<msg>{desc|escape}</msg>\n{tags}</logentry>\n\n'
5 5

  
6
file_mod = '<path action="M">{file_mod|escape}</path>\n'
7
file_add = '<path action="A">{file_add|escape}</path>\n'
8
file_del = '<path action="D">{file_del|escape}</path>\n'
9
file_copy = '<path-copied copyfrom-path="{source|escape}">{name|urlescape}</path-copied>\n'
6
file_mod = '<path action="M">{file_mod|urlescape}</path>\n'
7
file_add = '<path action="A">{file_add|urlescape}</path>\n'
8
file_del = '<path action="D">{file_del|urlescape}</path>\n'
9
file_copy = '<path-copied copyfrom-path="{source|urlescape}">{name|urlescape}</path-copied>\n'
10 10
tag = '<tag>{tag|escape}</tag>\n'
11 11
header='<?xml version="1.0" encoding="UTF-8" ?>\n<log>\n\n'
12 12
# footer="</log>"
lib/redmine/scm/adapters/mercurial_adapter.rb
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 17

  
18 18
require 'redmine/scm/adapters/abstract_adapter'
19
require 'cgi'
19 20

  
20 21
module Redmine
21 22
  module Scm
......
127 128
                    from_rev = logentry.attributes['revision']
128 129
                  end
129 130
                  paths << {:action => path.attributes['action'],
130
                    :path => "/#{path.text}",
131
                    :from_path => from_path ? "/#{from_path}" : nil,
131
                    :path => "/#{CGI.unescape(path.text)}",
132
                    :from_path => from_path ? "/#{CGI.unescape(from_path)}" : nil,
132 133
                    :from_revision => from_rev ? from_rev : nil
133 134
                  }
134 135
                end
lib/redmine/scm/adapters/path_encodable_wrapper.rb
1
# redMine - project management software
2
# Copyright (C) 2006-2010  Jean-Philippe Lang
3
# Copyright (C) 2010 Yuya Nishihara <yuya@tcha.org>
4
#
5
# This program is free software; you can redistribute it and/or
6
# modify it under the terms of the GNU General Public License
7
# as published by the Free Software Foundation; either version 2
8
# of the License, or (at your option) any later version.
9
#
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18

  
19
require 'delegate'
20
require 'iconv'
21

  
22
module Redmine
23
  module Scm
24
    module Adapters
25
      # wraps scm adapter to convert path encodings
26
      class PathEncodableWrapper < SimpleDelegator  # :nodoc:
27
        def initialize(scm, path_encoding)
28
          super(scm)
29
          @path_encoding = path_encoding
30
        end
31

  
32
        def entry(path=nil, identifier=nil)
33
          convert_entry!(super(to_scm_path(path), identifier))
34
        end
35

  
36
        def entries(path=nil, identifier=nil)
37
          convert_entries!(super(to_scm_path(path), identifier))
38
        end
39

  
40
        def properties(path, identifier=nil)
41
          super(to_scm_path(path), identifier)
42
        end
43

  
44
        def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
45
          convert_revisions!(super(to_scm_path(path), identifier_from, identifier_to, options))
46
        end
47

  
48
        def diff(path, identifier_from, identifier_to=nil)
49
          super(to_scm_path(path), identifier_from, identifier_to)
50
        end
51

  
52
        def cat(path, identifier=nil)
53
          super(to_scm_path(path), identifier)
54
        end
55

  
56
        def annotate(path, identifier=nil)
57
          super(to_scm_path(path), identifier)
58
        end
59

  
60
        private
61

  
62
        def convert_entry!(entry)
63
          return unless entry
64
          entry.name = from_scm_path(entry.name)
65
          entry.path = from_scm_path(entry.path)
66
          entry
67
        end
68

  
69
        def convert_entries!(entries)
70
          return unless entries
71
          entries.each { |e| convert_entry!(e) }
72
          entries
73
        end
74

  
75
        def convert_revisions!(revisions)
76
          return unless revisions
77
          revisions.each do |rev|
78
            next unless rev.paths
79
            rev.paths.each do |e|
80
              e[:path] = from_scm_path(e[:path])
81
              e[:from_path] = from_scm_path(e[:from_path])
82
            end
83
          end
84
          revisions
85
        end
86

  
87
        # convert repository path string to utf-8
88
        def from_scm_path(s)
89
          return unless s
90
          begin
91
            Iconv.conv('UTF-8', @path_encoding, s)
92
          rescue Iconv::Failure => err
93
            raise CommandFailed, "failed to convert path from #{@path_encoding} to UTF-8. #{err}"
94
          end
95
        end
96

  
97
        # convert utf-8 path string to repository encoding
98
        def to_scm_path(s)
99
          return unless s
100
          begin
101
            Iconv.conv(@path_encoding, 'UTF-8', s)
102
          rescue Iconv::Failure => err
103
            raise CommandFailed, "failed to convert path from UTF-8 to #{@path_encoding}. #{err}"
104
          end
105
        end
106
      end
107
    end
108
  end
109
end
test/functional/repositories_mercurial_controller_test.rb
32 32
    @request    = ActionController::TestRequest.new
33 33
    @response   = ActionController::TestResponse.new
34 34
    User.current = nil
35
    Repository::Mercurial.create(:project => Project.find(3), :url => REPOSITORY_PATH)
35
    assert @repository = Repository::Mercurial.create(
36
                            :project       => Project.find(3),
37
                            :url           => REPOSITORY_PATH,
38
                            :path_encoding => 'ISO-8859-1'
39
                            )
40
    @repository.fetch_changesets
41
    @repository.reload
36 42
  end
37 43
  
38 44
  if File.directory?(REPOSITORY_PATH)
......
49 55
      assert_response :success
50 56
      assert_template 'show'
51 57
      assert_not_nil assigns(:entries)
52
      assert_equal 3, assigns(:entries).size
58
      assert_equal 4, assigns(:entries).size
53 59
      assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
54 60
      assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
55 61
      assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
......
74 80
      assert_not_nil assigns(:entries)
75 81
      assert_equal ['delete.png'], assigns(:entries).collect(&:name)
76 82
    end
77
    
83

  
84
    def test_show_directory_sql_escape_percent
85
      get :show, :id => 3, :path => ['sql_escape', 'percent%dir'], :rev => 13
86
      assert_response :success
87
      assert_template 'show'
88

  
89
      assert_not_nil assigns(:entries)
90
      assert_equal ['percent%file1.txt', 'percentfile1.txt'], assigns(:entries).collect(&:name)
91
      changesets = assigns(:changesets)
92
      assert_not_nil changesets
93
      assert_equal %w(13 11 10 9), changesets.collect(&:revision)
94
    end
95

  
96
    def test_show_directory_latin_1
97
      get :show, :id => 3, :path => ['latin-1-dir'], :rev => 19
98
      assert_response :success
99
      assert_template 'show'
100

  
101
      assert_not_nil assigns(:entries)
102
      assert_equal ["make-latin-1-file.rb", "test-\xc3\x9c-1.txt","test-\xc3\x9c-2.txt", "test-\xc3\x9c.txt"], assigns(:entries).collect(&:name)
103
      changesets = assigns(:changesets)
104
      assert_not_nil changesets
105
      assert_equal %w(19 18 17 16 15), changesets.collect(&:revision)
106
    end
107

  
78 108
    def test_changes
79 109
      get :changes, :id => 3, :path => ['images', 'edit.png']
80 110
      assert_response :success
......
88 118
      assert_template 'entry'
89 119
      # Line 19
90 120
      assert_tag :tag => 'th',
91
                 :content => /10/,
92
                 :attributes => { :class => /line-num/ },
121
                 :content => '10',
122
                 :attributes => { :class => 'line-num' },
93 123
                 :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
94 124
    end
125

  
126
    def test_entry_show_latin_1
127
      get :entry, :id => 3, :path => ['latin-1-dir', "test-\xc3\x9c-2.txt"], :rev => 19
128
      assert_response :success
129
      assert_template 'entry'
130
      # Line 19
131
      assert_tag :tag => 'th',
132
                 :content => '1',
133
                 :attributes => { :class => 'line-num' },
134
                 :sibling => { :tag => 'td', :content => /Mercurial is a distributed version control system/ }
135
    end
95 136
    
96 137
    def test_entry_download
97 138
      get :entry, :id => 3, :path => ['sources', 'watchers_controller.rb'], :format => 'raw'
......
115 156
      assert_template 'diff'
116 157
      # Line 22 removed
117 158
      assert_tag :tag => 'th',
118
                 :content => /22/,
159
                 :content => '22',
119 160
                 :sibling => { :tag => 'td', 
120 161
                               :attributes => { :class => /diff_out/ },
121 162
                               :content => /def remove/ }
122 163
    end
123 164
    
165
    def test_diff_latin_1
166
      get :diff, :id => 3, :rev => 19
167
      assert_response :success
168
      assert_template 'diff'
169
      assert_tag :tag => 'th',
170
                 :content => '2',
171
                 :sibling => { :tag => 'td', 
172
                               :attributes => { :class => /diff_in/ },
173
                               :content => /It is written in Python/ }
174
    end
175

  
124 176
    def test_annotate
125 177
      get :annotate, :id => 3, :path => ['sources', 'watchers_controller.rb']
126 178
      assert_response :success
127 179
      assert_template 'annotate'
128
      # Line 23, revision 4
129
      assert_tag :tag => 'th', :content => /23/,
130
                 :sibling => { :tag => 'td', :child => { :tag => 'a', :content => /4/ } },
131
                 :sibling => { :tag => 'td', :content => /jsmith/ },
180
      # Line 23, revision 4:def6d2f1254a
181
      assert_tag :tag => 'th',
182
                 :content => '23',
183
                 :attributes => { :class => 'line-num' },
184
                 :sibling =>
185
                       {
186
                         :tag => 'td',
187
                         :attributes => { :class => 'revision' },
188
                         :child => { :tag => 'a', :content => '4' }
189
                         # :child => { :tag => 'a', :content => /4:def6d2f1/ }
190
                       }
191
      assert_tag :tag => 'th',
192
                 :content => '23',
193
                 :attributes => { :class => 'line-num' },
194
                 :sibling =>
195
                       {
196
                          :tag     => 'td'    ,
197
                          :content => 'jsmith' ,
198
                          :attributes => { :class   => 'author' },
199
                          
200
                        }
201
      assert_tag :tag => 'th',
202
                 :content => '23',
203
                 :attributes => { :class => 'line-num' },
132 204
                 :sibling => { :tag => 'td', :content => /watcher =/ }
133 205
    end
206

  
207
    def test_annotate_latin_1
208
      get :annotate, :id => 3, :path => ['latin-1-dir', "test-\xc3\x9c-2.txt"], :rev => 19
209
      assert_response :success
210
      assert_template 'annotate'
211
      assert_tag :tag => 'th',
212
                 :content => '1',
213
                 :attributes => { :class => 'line-num' },
214
                 :sibling =>
215
                       {
216
                         :tag => 'td',
217
                         :attributes => { :class => 'revision' },
218
                         :child => { :tag => 'a', :content => '18' }
219
                       }
220
      assert_tag :tag => 'th',
221
                 :content => '1',
222
                 :attributes => { :class => 'line-num' },
223
                 :sibling =>
224
                       {
225
                          :tag     => 'td'    ,
226
                          :content => 'jsmith' ,
227
                          :attributes => { :class   => 'author' },
228
                          
229
                        }
230
      assert_tag :tag => 'th',
231
                 :content => '1',
232
                 :attributes => { :class => 'line-num' },
233
                 :sibling => { :tag => 'td', :content => /Mercurial is a distributed version control system/ }
234

  
235
    end
236

  
134 237
  else
135 238
    puts "Mercurial test repository NOT FOUND. Skipping functional tests !!!"
136 239
    def test_fake; assert true end
137 240
  end
138 241
end
242

  
test/unit/lib/redmine/scm/adapters/mercurial_adapter_test.rb
9 9
    TEMPLATE_EXTENSION = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_EXTENSION
10 10
    
11 11
    REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/mercurial_repository'
12
    
13
    def test_hgversion
14
      to_test = { "Mercurial Distributed SCM (version 0.9.5)\n" => [0,9,5],
15
                  "Mercurial Distributed SCM (1.0)\n" => [1,0],
16
                  "Mercurial Distributed SCM (1e4ddc9ac9f7+20080325)\n" => nil,
17
                  "Mercurial Distributed SCM (1.0.1+20080525)\n" => [1,0,1],
18
                  "Mercurial Distributed SCM (1916e629a29d)\n" => nil,
19
                  "Mercurial SCM Distribuito (versione 0.9.5)\n" => [0,9,5],
20
                  "(1.6)\n(1.7)\n(1.8)"           => [1,6],
21
                  "(1.7.1)\r\n(1.8.1)\r\n(1.9.1)" => [1,7,1]}
22 12

  
23
      to_test.each do |s, v|
24
        test_hgversion_for(s, v)
13
    if File.directory?(REPOSITORY_PATH)  
14
      def setup
15
        @adapter = Redmine::Scm::Adapters::MercurialAdapter.new(REPOSITORY_PATH)
25 16
      end
26
    end
27
    
28
    def test_template_path
29
      to_test = { [0,9,5] => "0.9.5",
30
                  [1,0] => "1.0",
31
                  [] => "1.0",
32
                  [1,0,1] => "1.0",
33
                  [1,7]   => "1.0",
34
                  [1,7,1] => "1.0"}
35
      to_test.each do |v, template|
36
        test_template_path_for(v, template)
17

  
18
      def test_hgversion
19
        to_test = { "Mercurial Distributed SCM (version 0.9.5)\n"  => [0,9,5],
20
                    "Mercurial Distributed SCM (1.0)\n"            => [1,0],
21
                    "Mercurial Distributed SCM (1e4ddc9ac9f7+20080325)\n" => nil,
22
                    "Mercurial Distributed SCM (1.0.1+20080525)\n" => [1,0,1],
23
                    "Mercurial Distributed SCM (1916e629a29d)\n"   => nil,
24
                    "Mercurial SCM Distribuito (versione 0.9.5)\n" => [0,9,5],
25
                    "(1.6)\n(1.7)\n(1.8)"           => [1,6],
26
                    "(1.7.1)\r\n(1.8.1)\r\n(1.9.1)" => [1,7,1]}
27

  
28
        to_test.each do |s, v|
29
          test_hgversion_for(s, v)
30
        end
37 31
      end
38
    end
39
    
40
    private
41
    
42
    def test_hgversion_for(hgversion, version)
43
      Redmine::Scm::Adapters::MercurialAdapter.expects(:hgversion_from_command_line).returns(hgversion)
44
      adapter = Redmine::Scm::Adapters::MercurialAdapter
45
      assert_equal version, adapter.hgversion
46
    end
47
    
48
    def test_template_path_for(version, template)
49
      adapter = Redmine::Scm::Adapters::MercurialAdapter
50
      assert_equal "#{TEMPLATES_DIR}/#{TEMPLATE_NAME}-#{template}.#{TEMPLATE_EXTENSION}", adapter.template_path_for(version)
51
      assert File.exist?(adapter.template_path_for(version))
32

  
33
      def test_template_path
34
        to_test = { [0,9,5] => "0.9.5",
35
                       [1,0]    => "1.0",
36
                       []       => "1.0",
37
                       [1,0,1]  => "1.0",
38
                       [1,7]    => "1.0",
39
                       [1,7,1]  => "1.0"}
40
        to_test.each do |v, template|
41
          test_template_path_for(v, template)
42
        end
43
      end
44

  
45
      def test_cat
46
        assert     @adapter.cat("sources/welcome_controller.rb", 2)
47
        assert_nil @adapter.cat("sources/welcome_controller.rb")
48
      end
49

  
50
      private
51

  
52
      def test_hgversion_for(hgversion, version)
53
        @adapter.class.expects(:hgversion_from_command_line).returns(hgversion)
54
        assert_equal version, @adapter.class.hgversion
55
      end
56

  
57
      def test_template_path_for(version, template)
58
        assert_equal "#{TEMPLATES_DIR}/#{TEMPLATE_NAME}-#{template}.#{TEMPLATE_EXTENSION}",
59
                     @adapter.class.template_path_for(version)
60
        assert File.exist?(@adapter.class.template_path_for(version))
61
      end
62
    else
63
      puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!"
64
      def test_fake; assert true end
52 65
    end
53 66
  end
54
  
67

  
55 68
rescue LoadError
56 69
  class MercurialMochaFake < ActiveSupport::TestCase
57 70
    def test_fake; assert(false, "Requires mocha to run those tests")  end
test/unit/repository_mercurial_test.rb
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
    assert @repository = Repository::Mercurial.create(:project => @project, :url => REPOSITORY_PATH)
28
    assert @repository = Repository::Mercurial.create(
29
                            :project       => @project,
30
                            :url           => REPOSITORY_PATH,
31
                            :path_encoding => 'ISO-8859-1'
32
                            )
29 33
  end
30
  
34

  
31 35
  if File.directory?(REPOSITORY_PATH)  
32 36
    def test_fetch_changesets_from_scratch
33 37
      @repository.fetch_changesets
34 38
      @repository.reload
35 39
      
36
      assert_equal 6, @repository.changesets.count
37
      assert_equal 11, @repository.changes.count
38
      assert_equal "Initial import.\nThe repository contains 3 files.", @repository.changesets.find_by_revision('0').comments
40
      assert_equal 21, @repository.changesets.count
41
      assert_equal 30, @repository.changes.count
42
      assert_equal "Initial import.\nThe repository contains 3 files.",
43
                   @repository.changesets.find_by_revision('0').comments
39 44
    end
40 45
    
41 46
    def test_fetch_changesets_incremental
......
46 51
      assert_equal 3, @repository.changesets.count
47 52
      
48 53
      @repository.fetch_changesets
49
      assert_equal 6, @repository.changesets.count
54
      assert_equal 21, @repository.changesets.count
50 55
    end
51
    
56

  
52 57
    def test_entries
53 58
      assert_equal 2, @repository.entries("sources", 2).size
54 59
      assert_equal 1, @repository.entries("sources", 3).size
55 60
    end
56 61

  
57 62
    def test_locate_on_outdated_repository
58
      # Change the working dir state
59
      %x{hg -R #{REPOSITORY_PATH} up -r 0}
63
      # For bare repository; that is, a repository without a working copy
64
      # $ hg update null
65
      # See http://mercurial.selenic.com/wiki/GitConcepts?action=recall&rev=46#Bare_repositories
60 66
      assert_equal 1, @repository.entries("images", 0).size
61 67
      assert_equal 2, @repository.entries("images").size
62 68
      assert_equal 2, @repository.entries("images", 2).size
63 69
    end
64 70

  
71
    def test_changeset_order_by_revision
72
      @repository.fetch_changesets
73
      @repository.reload
65 74

  
66
    def test_cat
67
      assert @repository.scm.cat("sources/welcome_controller.rb", 2)
68
      assert_nil @repository.scm.cat("sources/welcome_controller.rb")
75
      c0 = @repository.latest_changeset
76
      c1 = @repository.changesets.find_by_revision('0')
77
      # sorted by revision (id), not by date
78
      assert c0.revision.to_i > c1.revision.to_i
79
      assert c0.committed_on  < c1.committed_on
69 80
    end
70 81

  
82
    def test_latest_changesets
83
      @repository.fetch_changesets
84
      @repository.reload
85

  
86
      # with_limit
87
      changesets = @repository.latest_changesets('', nil, 2)
88
      assert_equal @repository.latest_changesets('', nil)[0, 2], changesets
89

  
90
      # with_filepath
91
      changesets = @repository.latest_changesets('sql_escape/percent%dir/percent%file1.txt', nil)
92
      assert_equal %w|11 10 9|, changesets.collect(&:revision)
93

  
94
      changesets = @repository.latest_changesets('/sql_escape/underscore_dir/understrike_file.txt', nil)
95
      assert_equal %w|12 9|, changesets.collect(&:revision)
96

  
97
      # with_dirpath
98
      changesets = @repository.latest_changesets('sql_escape/percent%dir', nil)
99
      assert_equal %w|13 11 10 9|, changesets.collect(&:revision)
100
    end
101

  
102
    def test_copied_files
103
      @repository.fetch_changesets
104
      @repository.reload
105

  
106
      cs1 = @repository.changesets.find_by_revision('13')
107
      c1  = cs1.changes
108
      assert_equal 2, c1.size
109
      assert_equal 'A', c1[0].action
110
      assert_equal '/sql_escape/percent%dir/percentfile1.txt',  c1[0].path
111
      assert_equal '/sql_escape/percent%dir/percent%file1.txt', c1[0].from_path
112

  
113
      assert_equal 'A', c1[1].action
114
      assert_equal '/sql_escape/underscore_dir/understrike-file.txt', c1[1].path
115
      assert_equal '/sql_escape/underscore_dir/understrike_file.txt', c1[1].from_path
116

  
117
      cs2 = @repository.changesets.find_by_revision('17')
118
      c2  = cs2.changes
119
      assert_equal 1, c2.size
120
      assert_equal 'A', c2[0].action
121
      assert_equal "/latin-1-dir/test-\xc3\x9c-1.txt",  c2[0].path
122
      assert_equal "/latin-1-dir/test-\xc3\x9c.txt",    c2[0].from_path
123
    end
71 124
  else
72 125
    puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!"
73 126
    def test_fake; assert true end
74 127
  end
75 128
end
129

  
(5-5/14)