~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to __init__.py

  • Committer: Aaron Bentley
  • Date: 2007-04-10 16:24:05 UTC
  • mto: (2520.4.1 bzr.mpbundle) (0.9.13 temp)
  • mto: This revision was merged to the branch mainline in revision 2631.
  • Revision ID: abentley@panoramicfeedback.com-20070410162405-sczvbxmrwek7l2g5
Get single-parent comparison working

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from difflib import SequenceMatcher
 
2
 
1
3
class MultiParent(object):
2
4
 
3
 
    def __init__(self):
4
 
        self.hunks = []
 
5
    def __init__(self, hunks=None):
 
6
        if hunks is not None:
 
7
            self.hunks = hunks
 
8
        else:
 
9
            self.hunks = []
 
10
 
 
11
    def __repr__(self):
 
12
        return "MultiParent(%r)" % self.hunks
 
13
 
 
14
    def __eq__(self, other):
 
15
        if self.__class__ is not other.__class__:
 
16
            return False
 
17
        return (self.hunks == other.hunks)
5
18
 
6
19
    @staticmethod
7
20
    def from_lines(text, parents=()):
8
 
        diff = MultiParent()
9
 
        diff.hunks.append(NewText(text))
 
21
        def compare(parent):
 
22
            return SequenceMatcher(None, parent, text).get_matching_blocks()
 
23
        parent_comparisons = [compare(p) for p in parents]
 
24
        cur_line = 0
 
25
        new_text = NewText([])
 
26
        parent_text = []
 
27
        block_iter = [iter(i) for i in parent_comparisons]
 
28
        diff = MultiParent([])
 
29
        def next_block(p):
 
30
            try:
 
31
                return block_iter[p].next()
 
32
            except StopIteration:
 
33
                return None
 
34
        cur_block = [next_block(p) for p, i in enumerate(block_iter)]
 
35
        while cur_line < len(text):
 
36
            #import pdb; pdb.set_trace()
 
37
            best_match = None
 
38
            for p, block in enumerate(cur_block):
 
39
                if block is None:
 
40
                    continue
 
41
                i, j, n = block
 
42
                while j + n < cur_line:
 
43
                    block = cur_block[p] = next_block(p)
 
44
                    if block is None:
 
45
                        break
 
46
                    i, j, n = block
 
47
                if block is None:
 
48
                    continue
 
49
                if j > cur_line:
 
50
                    continue
 
51
                offset = cur_line - j
 
52
                i += offset
 
53
                j = cur_line
 
54
                n -= offset
 
55
                if n == 0:
 
56
                    continue
 
57
                if best_match is None or n > best_match.num_lines:
 
58
                    best_match = ParentText(p, i, j, n)
 
59
            if best_match is None:
 
60
                new_text.lines.append(text[cur_line])
 
61
                cur_line += 1
 
62
            else:
 
63
                if len(new_text.lines) > 0:
 
64
                    diff.hunks.append(new_text)
 
65
                    new_text = NewText([])
 
66
                diff.hunks.append(best_match)
 
67
                cur_line += best_match.num_lines
 
68
        if len(new_text.lines) > 0:
 
69
            diff.hunks.append(new_text)
10
70
        return diff
11
71
 
12
72
    @classmethod
24
84
        if self.__class__ is not other.__class__:
25
85
            return False
26
86
        return (other.lines == self.lines)
 
87
 
 
88
    def __repr__(self):
 
89
        return 'NewText(%r)' % self.lines
 
90
 
 
91
 
 
92
class ParentText(object):
 
93
 
 
94
    def __init__(self, parent, parent_pos, child_pos, num_lines):
 
95
        self.parent = parent
 
96
        self.parent_pos = parent_pos
 
97
        self.child_pos = child_pos
 
98
        self.num_lines = num_lines
 
99
 
 
100
    def __repr__(self):
 
101
        return 'ParentText(%(parent)r, %(parent_pos)r, %(child_pos)r,'\
 
102
            ' %(num_lines)r)' % self.__dict__
 
103
 
 
104
    def __eq__(self, other):
 
105
        if self.__class__ != other.__class__:
 
106
            return False
 
107
        return (self.__dict__ == other.__dict__)