summaryrefslogtreecommitdiff
path: root/git/test/test_diff.py
blob: 98e72d6c8fb2b3173c4d4e2db850eede36890f5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# test_diff.py
# Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php

from git.test.lib import (
                        TestBase, 
                        StringProcessAdapter, 
                        fixture, 
                        assert_equal, 
                        assert_true
                        )

from git.diff import *

class TestDiff(TestBase):
            
    def _assert_diff_format(self, diffs):
        # verify that the format of the diff is sane
        for diff in diffs:
            if diff.a_mode:
                assert isinstance(diff.a_mode, int)
            if diff.b_mode:
                assert isinstance(diff.b_mode, int)
                
            if diff.a_blob:
                assert not diff.a_blob.path.endswith('\n')
            if diff.b_blob:
                assert not diff.b_blob.path.endswith('\n')
        # END for each diff
        return diffs
    
    def test_list_from_string_new_mode(self):
        output = StringProcessAdapter(fixture('diff_new_mode'))
        diffs = Diff._index_from_patch_format(self.rorepo, output.stdout)
        self._assert_diff_format(diffs)
        
        assert_equal(1, len(diffs))
        assert_equal(10, len(diffs[0].diff.splitlines()))

    def test_diff_with_rename(self):
        output = StringProcessAdapter(fixture('diff_rename'))
        diffs = Diff._index_from_patch_format(self.rorepo, output.stdout)
        self._assert_diff_format(diffs)
        
        assert_equal(1, len(diffs))

        diff = diffs[0]
        assert_true(diff.renamed)
        assert_equal(diff.rename_from, 'AUTHORS')
        assert_equal(diff.rename_to, 'CONTRIBUTORS')

    def test_diff_with_rename_raw(self):
        output = StringProcessAdapter(fixture('diff_rename_raw'))
        diffs = Diff._index_from_raw_format(self.rorepo, output.stdout)
        self._assert_diff_format(diffs)

        diffs = filter(lambda d: d.renamed, diffs)
        assert_equal(3, len(diffs))

        diff = diffs[0]
        assert_true(diff.renamed)
        assert_equal(diff.rename_from, 'git/test/test_reflog.py')
        assert_equal(diff.rename_to, 'git/test/refs/test_reflog.py')

    def test_diff_patch_format(self):
        # test all of the 'old' format diffs for completness - it should at least
        # be able to deal with it
        fixtures = ("diff_2", "diff_2f", "diff_f", "diff_i", "diff_mode_only", 
                    "diff_new_mode", "diff_numstat", "diff_p", "diff_rename", 
                    "diff_tree_numstat_root" )
        
        for fixture_name in fixtures:
            diff_proc = StringProcessAdapter(fixture(fixture_name))
            diffs = Diff._index_from_patch_format(self.rorepo, diff_proc.stdout)
        # END for each fixture

    def test_diff_interface(self):
        # test a few variations of the main diff routine
        assertion_map = dict()
        for i, commit in enumerate(self.rorepo.iter_commits('0.1.6', max_count=2)):
            diff_item = commit
            if i%2 == 0:
                diff_item = commit.tree
            # END use tree every second item
            
            for other in (None, commit.Index, commit.parents[0]):
                for paths in (None, "CHANGES", ("CHANGES", "lib")):
                    for create_patch in range(2):
                        diff_index = diff_item.diff(other, paths, create_patch)
                        assert isinstance(diff_index, DiffIndex)
                        
                        if diff_index:
                            self._assert_diff_format(diff_index)
                            for ct in DiffIndex.change_type:
                                key = 'ct_%s'%ct
                                assertion_map.setdefault(key, 0)
                                assertion_map[key] = assertion_map[key]+len(list(diff_index.iter_change_type(ct)))  
                            # END for each changetype
                            
                            # check entries
                            diff_set = set()
                            diff_set.add(diff_index[0])
                            diff_set.add(diff_index[0])
                            assert len(diff_set) == 1
                            assert diff_index[0] == diff_index[0]
                            assert not (diff_index[0] != diff_index[0])
                        # END diff index checking 
                    # END for each patch option
                # END for each path option
            # END for each other side
        # END for each commit

        # test rename detection
        rename_commit = self.rorepo.rev_parse('4772fe0')
        rename_diffs = rename_commit.parents[0].diff(rename_commit, M=True)
        rename_diffs = filter(lambda d: d.renamed, rename_diffs)
        assert len(rename_diffs) == 3
        assert rename_diffs[0].rename_from == rename_diffs[0].a_blob.path
        assert rename_diffs[0].rename_to == rename_diffs[0].b_blob.path
        
        # assert we could always find at least one instance of the members we 
        # can iterate in the diff index - if not this indicates its not working correctly
        # or our test does not span the whole range of possibilities
        for key,value in assertion_map.items():
            assert value, "Did not find diff for %s" % key
        # END for each iteration type 
        
        # test path not existing in the index - should be ignored
        c = self.rorepo.head.commit
        cp = c.parents[0]
        diff_index = c.diff(cp, ["does/not/exist"])
        assert len(diff_index) == 0