git_adapter_test.rb 20.6 KB
Newer Older
1 2
# encoding: utf-8

3
# This file includes UTF-8 "Felix Schäfer".
4
# We need to consider Ruby 1.9 compatibility.
5

6
require File.expand_path('../../../../../../test_helper', __FILE__)
7 8
begin
  require 'mocha'
9

10
  class GitAdapterTest < ActiveSupport::TestCase
11
    REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
12

13 14
    FELIX_UTF8 = "Felix Schäfer"
    FELIX_HEX  = "Felix Sch\xC3\xA4fer"
15
    CHAR_1_HEX = "\xc3\x9c"
16

17 18 19 20 21 22
    ## Ruby uses ANSI api to fork a process on Windows.
    ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
    ## and these are incompatible with ASCII.
    # WINDOWS_PASS = Redmine::Platform.mswin?
    WINDOWS_PASS = false

23 24 25 26 27 28 29 30
    ## Git, Mercurial and CVS path encodings are binary.
    ## Subversion supports URL encoding for path.
    ## Redmine Mercurial adapter and extension use URL encoding.
    ## Git accepts only binary path in command line parameter.
    ## So, there is no way to use binary command line parameter in JRuby.
    JRUBY_SKIP     = (RUBY_PLATFORM == 'java')
    JRUBY_SKIP_STR = "TODO: This test fails in JRuby"

31 32
    if File.directory?(REPOSITORY_PATH)
      def setup
33 34 35 36 37 38 39
        adapter_class = Redmine::Scm::Adapters::GitAdapter
        assert adapter_class
        assert adapter_class.client_command
        assert_equal true, adapter_class.client_available
        assert_equal true, adapter_class.client_version_above?([1])
        assert_equal true, adapter_class.client_version_above?([1, 0])

40 41 42 43 44 45
        @adapter = Redmine::Scm::Adapters::GitAdapter.new(
                      REPOSITORY_PATH,
                      nil,
                      nil,
                      nil,
                      'ISO-8859-1'
46
                   )
47
        assert @adapter
48
        @char_1 = CHAR_1_HEX.dup
49 50 51
        if @char_1.respond_to?(:force_encoding)
          @char_1.force_encoding('UTF-8')
        end
52
      end
53

54 55 56 57 58 59 60 61 62
      def test_scm_version
        to_test = { "git version 1.7.3.4\n"             => [1,7,3,4],
                    "1.6.1\n1.7\n1.8"                   => [1,6,1],
                    "1.6.2\r\n1.8.1\r\n1.9.1"           => [1,6,2]}
        to_test.each do |s, v|
          test_scm_version_for(s, v)
        end
      end

63
      def test_branches
64 65 66 67
        brs = []
        @adapter.branches.each do |b|
          brs << b
        end
68 69 70 71 72
        assert_equal 5, brs.length
        br_issue_8857 = brs[-5]
        assert_equal 'issue-8857', br_issue_8857.to_s 
        assert_equal '2a682156a3b6e77a8bf9cd4590e8db757f3c6c78', br_issue_8857.revision
        assert_equal br_issue_8857.scmid, br_issue_8857.revision
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
        br_latin_1_path = brs[-4]
        assert_equal 'latin-1-path-encoding', br_latin_1_path.to_s 
        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', br_latin_1_path.revision
        assert_equal br_latin_1_path.scmid, br_latin_1_path.revision
        br_master = brs[-3]
        assert_equal 'master', br_master.to_s
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master.revision
        assert_equal br_master.scmid, br_master.revision
        br_latin_1 = brs[-2]
        assert_equal 'test-latin-1', br_latin_1.to_s
        assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', br_latin_1.revision
        assert_equal br_latin_1.scmid, br_latin_1.revision
        br_test = brs[-1]
        assert_equal 'test_branch', br_test.to_s
        assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', br_test.revision
        assert_equal br_test.scmid, br_test.revision
89
      end
90

91 92 93 94 95 96 97
      def test_tags
        assert_equal  [
              "tag00.lightweight",
              "tag01.annotated",
            ], @adapter.tags
      end

98
      def test_revisions_master_all
99 100 101 102
        revs1 = []
        @adapter.revisions('', nil, "master",{}) do |rev|
          revs1 << rev
        end
103 104 105 106
        assert_equal 15, revs1.length
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 0].identifier
        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier

107 108
        revs2 = []
        @adapter.revisions('', nil, "master",
109
                           {:reverse => true}) do |rev|
110 111
          revs2 << rev
        end
112 113 114 115 116
        assert_equal 15, revs2.length
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
      end

117
      def test_revisions_master_merged_rev
118 119 120 121 122 123 124
        revs1 = []
        @adapter.revisions('',
                           "713f4944648826f558cf548222f813dabe7cbb04",
                           "master",
                           {:reverse => true}) do |rev|
          revs1 << rev
        end
125 126 127 128 129 130 131 132
        assert_equal 8, revs1.length
        assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', revs1[ 0].identifier
        assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 1].identifier
        # 4a07fe31b is not a child of 713f49446
        assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 2].identifier
        # Merged revision
        assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 3].identifier
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
133

134 135 136 137 138 139 140
        revs2 = []
        @adapter.revisions('',
                           "fba357b886984ee71185ad2065e65fc0417d9b92",
                           "master",
                           {:reverse => true}) do |rev|
          revs2 << rev
        end
141 142 143 144 145 146 147
        assert_equal 7, revs2.length
        assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs2[ 0].identifier
        # 4a07fe31b is not a child of fba357b8869
        assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs2[ 1].identifier
        # Merged revision
        assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs2[ 2].identifier
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
148 149
      end

150
      def test_revisions_branch_latin_1_path_encoding_all
151 152 153 154
        revs1 = []
        @adapter.revisions('', nil, "latin-1-path-encoding",{}) do |rev|
          revs1 << rev
        end
155 156 157 158
        assert_equal 8, revs1.length
        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[ 0].identifier
        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier

159 160
        revs2 = []
        @adapter.revisions('', nil, "latin-1-path-encoding",
161
                           {:reverse => true}) do |rev|
162 163
          revs2 << rev
        end
164 165 166 167 168
        assert_equal 8, revs2.length
        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
      end

169
      def test_revisions_branch_latin_1_path_encoding_with_rev
170 171 172 173 174 175 176
        revs1 = []
        @adapter.revisions('',
                           '7234cb2750b63f47bff735edc50a1c0a433c2518',
                           "latin-1-path-encoding",
                           {:reverse => true}) do |rev|
          revs1 << rev
        end
177 178 179 180
        assert_equal 7, revs1.length
        assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 0].identifier
        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier

181 182 183 184 185 186 187
        revs2 = []
        @adapter.revisions('',
                           '57ca437c0acbbcb749821fdf3726a1367056d364',
                           "latin-1-path-encoding",
                           {:reverse => true}) do |rev|
          revs2 << rev
        end
188 189 190 191 192
        assert_equal 3, revs2.length
        assert_equal '4fc55c43bf3d3dc2efb66145365ddc17639ce81e', revs2[ 0].identifier
        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
      end

193
      def test_revisions_invalid_rev
194 195
        revs1 = []
        @adapter.revisions('',
196 197 198
                           '1234abcd',
                           "master",
                           {:reverse => true}) do |rev|
199 200
          revs1 << rev
        end
201 202 203
        assert_equal [], revs1
      end

204 205 206 207 208 209 210 211 212 213 214 215 216
      def test_revisions_includes_master_two_revs
        revs1 = []
        @adapter.revisions('', nil, nil,
                           {:reverse => true,
                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
                            :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43']}) do |rev|
          revs1 << rev
        end
        assert_equal 2, revs1.length
        assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
      end

217 218 219 220
      def test_revisions_includes_master_two_revs_from_origin
        revs1 = []
        @adapter.revisions('', nil, nil,
                           {:reverse => true,
221
                            :includes => ['899a15dba03a3b350b89c3f537e4bbe02a03cdc9']}) do |rev|
222 223 224 225 226 227 228
          revs1 << rev
        end
        assert_equal 2, revs1.length
        assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier
        assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 1].identifier
      end

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
      def test_revisions_includes_merged_revs
        revs1 = []
        @adapter.revisions('', nil, nil,
                           {:reverse => true,
                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
                            :excludes => ['fba357b886984ee71185ad2065e65fc0417d9b92']}) do |rev|
          revs1 << rev
        end
        assert_equal 7, revs1.length
        assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 0].identifier
        assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 1].identifier
        assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 2].identifier
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
      end

      def test_revisions_includes_two_heads
        revs1 = []
        @adapter.revisions('', nil, nil,
                           {:reverse => true,
                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
                                          '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127'],
                            :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43',
                                          '4fc55c43bf3d3dc2efb66145365ddc17639ce81e']}) do |rev|
          revs1 << rev
        end
        assert_equal 4, revs1.length
        assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
        assert_equal '64f1f3e89ad1cb57976ff0ad99a107012ba3481d', revs1[-2].identifier
        assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
      end

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
      def test_revisions_disjointed_histories_revisions
        revs1 = []
        @adapter.revisions('', nil, nil,
                           {:reverse => true,
                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
                                          '92397af84d22f27389c822848ecd5b463c181583'],
                            :excludes => ['95488a44bc25f7d1f97d775a31359539ff333a63',
                                          '4f26664364207fa8b1af9f8722647ab2d4ac5d43'] }) do |rev|
          revs1 << rev
        end
        assert_equal 4, revs1.length
        assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
        assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
        assert_equal 'bc201c95999c4f10d018b0aa03b541cd6a2ff0ee', revs1[-2].identifier
        assert_equal '92397af84d22f27389c822848ecd5b463c181583', revs1[-1].identifier
      end

278 279 280 281 282 283 284 285 286 287 288
      def test_revisions_invalid_rev_excludes
        revs1 = []
        @adapter.revisions('', nil, nil,
                           {:reverse => true,
                            :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
                            :excludes => ['0123abcd4567']}) do |rev|
          revs1 << rev
        end
        assert_equal [], revs1
      end

289 290
      def test_getting_revisions_with_spaces_in_filename
        assert_equal 1, @adapter.revisions("filemane with spaces.txt",
291
                                           nil, "master").length
292 293
      end

294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
      def test_parents
        revs1 = []
        @adapter.revisions('',
                           nil,
                           "master",
                           {:reverse => true}) do |rev|
          revs1 << rev
        end
        assert_equal 15, revs1.length
        assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
                     revs1[0].identifier
        assert_equal nil, revs1[0].parents
        assert_equal "899a15dba03a3b350b89c3f537e4bbe02a03cdc9",
                     revs1[1].identifier
        assert_equal 1, revs1[1].parents.length
        assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
                     revs1[1].parents[0]
        assert_equal "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
                     revs1[10].identifier
        assert_equal 2, revs1[10].parents.length
        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8",
                     revs1[10].parents[0]
        assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da",
                     revs1[10].parents[1]
      end

320 321 322
      def test_getting_revisions_with_leading_and_trailing_spaces_in_filename
        assert_equal " filename with a leading space.txt ",
           @adapter.revisions(" filename with a leading space.txt ",
323
                               nil, "master")[0].paths[0][:path]
324 325 326 327 328 329 330 331 332 333 334 335
      end

      def test_getting_entries_with_leading_and_trailing_spaces_in_filename
        assert_equal " filename with a leading space.txt ",
           @adapter.entries('',
                   '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name
      end

      def test_annotate
        annotate = @adapter.annotate('sources/watchers_controller.rb')
        assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
        assert_equal 41, annotate.lines.size
336 337
        assert_equal "# This program is free software; you can redistribute it and/or",
                     annotate.lines[4].strip
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
        assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
                      annotate.revisions[4].identifier
        assert_equal "jsmith", annotate.revisions[4].author
      end

      def test_annotate_moved_file
        annotate = @adapter.annotate('renamed_test.txt')
        assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
        assert_equal 2, annotate.lines.size
      end

      def test_last_rev
        last_rev = @adapter.lastrev("README",
                                    "4f26664364207fa8b1af9f8722647ab2d4ac5d43")
        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid
        assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier
        assert_equal "Adam Soltys <asoltys@gmail.com>", last_rev.author
        assert_equal "2009-06-24 05:27:38".to_time, last_rev.time
      end

      def test_last_rev_with_spaces_in_filename
        last_rev = @adapter.lastrev("filemane with spaces.txt",
                                    "ed5bb786bbda2dee66a2d50faf51429dbc043a7b")
361 362
        str_felix_utf8 = FELIX_UTF8.dup
        str_felix_hex  = FELIX_HEX.dup
363 364 365 366
        last_rev_author = last_rev.author
        if last_rev_author.respond_to?(:force_encoding)
          last_rev_author.force_encoding('UTF-8')
        end
367 368
        assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid
        assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier
369 370 371
        assert_equal "#{str_felix_utf8} <felix@fachschaften.org>",
                       last_rev.author
        assert_equal "#{str_felix_hex} <felix@fachschaften.org>",
372 373 374
                       last_rev.author
        assert_equal "2010-09-18 19:59:46".to_time, last_rev.time
      end
375

376
      def test_latin_1_path
377 378
        if WINDOWS_PASS
          #
379 380
        elsif JRUBY_SKIP
          puts JRUBY_SKIP_STR
381 382 383 384 385 386 387 388
        else
          p2 = "latin-1-dir/test-#{@char_1}-2.txt"
          ['4fc55c43bf3d3dc2efb66145365ddc17639ce81e', '4fc55c43bf3'].each do |r1|
            assert @adapter.diff(p2, r1)
            assert @adapter.cat(p2, r1)
            assert_equal 1, @adapter.annotate(p2, r1).lines.length
            ['64f1f3e89ad1cb57976ff0ad99a107012ba3481d', '64f1f3e89ad1cb5797'].each do |r2|
              assert @adapter.diff(p2, r1, r2)
389 390
            end
          end
391 392 393
        end
      end

394
      def test_entries_tag
395 396
        entries1 = @adapter.entries(nil, 'tag01.annotated',
                                    options = {:report_last_commit => true})
397 398 399 400 401 402 403 404 405 406 407 408 409 410
        assert entries1
        assert_equal 3, entries1.size
        assert_equal 'sources', entries1[1].name
        assert_equal 'sources', entries1[1].path
        assert_equal 'dir', entries1[1].kind
        readme = entries1[2]
        assert_equal 'README', readme.name
        assert_equal 'README', readme.path
        assert_equal 'file', readme.kind
        assert_equal 27, readme.size
        assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', readme.lastrev.identifier
        assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
      end

411
      def test_entries_branch
412 413
        entries1 = @adapter.entries(nil, 'test_branch',
                                    options = {:report_last_commit => true})
414 415 416 417 418 419 420 421 422 423 424 425 426 427
        assert entries1
        assert_equal 4, entries1.size
        assert_equal 'sources', entries1[1].name
        assert_equal 'sources', entries1[1].path
        assert_equal 'dir', entries1[1].kind
        readme = entries1[2]
        assert_equal 'README', readme.name
        assert_equal 'README', readme.path
        assert_equal 'file', readme.kind
        assert_equal 159, readme.size
        assert_equal '713f4944648826f558cf548222f813dabe7cbb04', readme.lastrev.identifier
        assert_equal Time.gm(2009, 6, 19, 4, 37, 23), readme.lastrev.time
      end

428
      def test_entries_latin_1_files
429 430 431 432 433 434 435 436 437
        entries1 = @adapter.entries('latin-1-dir', '64f1f3e8')
        assert entries1
        assert_equal 3, entries1.size
        f1 = entries1[1]
        assert_equal "test-#{@char_1}-2.txt", f1.name
        assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path
        assert_equal 'file', f1.kind
      end

438
      def test_entries_latin_1_dir
439 440
        if WINDOWS_PASS
          #
441 442
        elsif JRUBY_SKIP
          puts JRUBY_SKIP_STR
443
        else
444 445
          entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir",
                                      '1ca7f5ed')
446 447 448 449 450 451 452 453 454
          assert entries1
          assert_equal 3, entries1.size
          f1 = entries1[1]
          assert_equal "test-#{@char_1}-2.txt", f1.name
          assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path
          assert_equal 'file', f1.kind
        end
      end

455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
      def test_path_encoding_default_utf8
        adpt1 = Redmine::Scm::Adapters::GitAdapter.new(
                                  REPOSITORY_PATH
                                )
        assert_equal "UTF-8", adpt1.path_encoding
        adpt2 = Redmine::Scm::Adapters::GitAdapter.new(
                                  REPOSITORY_PATH,
                                  nil,
                                  nil,
                                  nil,
                                  ""
                                )
        assert_equal "UTF-8", adpt2.path_encoding
      end

470 471 472 473
      def test_cat_path_invalid
        assert_nil @adapter.cat('invalid')
      end

474 475 476 477 478
      def test_cat_revision_invalid
        assert     @adapter.cat('README')
        assert_nil @adapter.cat('README', 'abcd1234efgh')
      end

479 480 481 482
      def test_diff_path_invalid
        assert_equal [], @adapter.diff('invalid', '713f4944648826f5')
      end

483 484 485 486 487 488
      def test_diff_revision_invalid
        assert_nil @adapter.diff(nil, 'abcd1234efgh')
        assert_nil @adapter.diff(nil, '713f4944648826f5', 'abcd1234efgh')
        assert_nil @adapter.diff(nil, 'abcd1234efgh', '713f4944648826f5')
      end

489 490 491 492
      def test_annotate_path_invalid
        assert_nil @adapter.annotate('invalid')
      end

493 494 495 496 497
      def test_annotate_revision_invalid
        assert     @adapter.annotate('README')
        assert_nil @adapter.annotate('README', 'abcd1234efgh')
      end

498 499 500 501 502 503 504
      private

      def test_scm_version_for(scm_command_version, version)
        @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
        assert_equal version, @adapter.class.scm_command_version
      end

505 506 507
    else
      puts "Git test repository NOT FOUND. Skipping unit tests !!!"
      def test_fake; assert true end
508
    end
509 510 511 512 513
  end

rescue LoadError
  class GitMochaFake < ActiveSupport::TestCase
    def test_fake; assert(false, "Requires mocha to run those tests")  end
514 515
  end
end