~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/plugins/news_merge/news_merge.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-01-29 11:48:10 UTC
  • mfrom: (4988.1.2 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20100129114810-pizbq0hfw5wctdaq
(jam) Merge 2.1.0rc2 into bzr.dev, including per-file merge hook

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
 
20
20
from bzrlib.plugins.news_merge.parser import simple_parse
21
 
from bzrlib import merge3
 
21
from bzrlib import merge, merge3
22
22
 
23
23
 
24
24
magic_marker = '|NEWS-MERGE-MAGIC-MARKER|'
25
25
 
26
26
 
27
 
def news_merger(params):
28
 
    """Perform a simple 3-way merge of a bzr NEWS file.
29
 
    
30
 
    Each section of a bzr NEWS file is essentially an ordered set of bullet
31
 
    points, so we can simply take a set of bullet points, determine which
32
 
    bullets to add and which to remove, sort, and reserialize.
33
 
    """
34
 
    # Transform the different versions of the NEWS file into a bunch of text
35
 
    # lines where each line matches one part of the overall structure, e.g. a
36
 
    # heading or bullet.
37
 
    def munge(lines):
38
 
        return list(blocks_to_fakelines(simple_parse(''.join(lines))))
39
 
    this_lines = munge(params.this_lines)
40
 
    other_lines = munge(params.other_lines)
41
 
    base_lines = munge(params.base_lines)
42
 
    m3 = merge3.Merge3(base_lines, this_lines, other_lines)
43
 
    result_lines = []
44
 
    for group in m3.merge_groups():
45
 
        if group[0] == 'conflict':
46
 
            _, base, a, b = group
47
 
            # Are all the conflicting lines bullets?  If so, we can merge this.
48
 
            for line_set in [base, a, b]:
49
 
                for line in line_set:
50
 
                    if not line.startswith('bullet'):
51
 
                        # Something else :(
52
 
                        # Maybe the default merge can cope.
53
 
                        return 'not_applicable', None
54
 
            # Calculate additions and deletions.
55
 
            new_in_a = set(a).difference(base)
56
 
            new_in_b = set(b).difference(base)
57
 
            all_new = new_in_a.union(new_in_b)
58
 
            deleted_in_a = set(base).difference(a)
59
 
            deleted_in_b = set(base).difference(b)
60
 
            # Combine into the final set of bullet points.
61
 
            final = all_new.difference(deleted_in_a).difference(deleted_in_b)
62
 
            # Sort, and emit.
63
 
            final = sorted(final, key=sort_key)
64
 
            result_lines.extend(final)
65
 
        else:
66
 
            result_lines.extend(group[1])
67
 
    # Transform the merged elements back into real blocks of lines.
68
 
    return 'success', list(fakelines_to_blocks(result_lines))
 
27
class NewsMerger(merge.ConfigurableFileMerger):
 
28
    """Merge bzr NEWS files."""
 
29
 
 
30
    name_prefix = "news"
 
31
 
 
32
    def merge_text(self, params):
 
33
        """Perform a simple 3-way merge of a bzr NEWS file.
 
34
        
 
35
        Each section of a bzr NEWS file is essentially an ordered set of bullet
 
36
        points, so we can simply take a set of bullet points, determine which
 
37
        bullets to add and which to remove, sort, and reserialize.
 
38
        """
 
39
        # Transform the different versions of the NEWS file into a bunch of
 
40
        # text lines where each line matches one part of the overall
 
41
        # structure, e.g. a heading or bullet.
 
42
        def munge(lines):
 
43
            return list(blocks_to_fakelines(simple_parse(''.join(lines))))
 
44
        this_lines = munge(params.this_lines)
 
45
        other_lines = munge(params.other_lines)
 
46
        base_lines = munge(params.base_lines)
 
47
        m3 = merge3.Merge3(base_lines, this_lines, other_lines)
 
48
        result_lines = []
 
49
        for group in m3.merge_groups():
 
50
            if group[0] == 'conflict':
 
51
                _, base, a, b = group
 
52
                # Are all the conflicting lines bullets?  If so, we can merge
 
53
                # this.
 
54
                for line_set in [base, a, b]:
 
55
                    for line in line_set:
 
56
                        if not line.startswith('bullet'):
 
57
                            # Something else :(
 
58
                            # Maybe the default merge can cope.
 
59
                            return 'not_applicable', None
 
60
                # Calculate additions and deletions.
 
61
                new_in_a = set(a).difference(base)
 
62
                new_in_b = set(b).difference(base)
 
63
                all_new = new_in_a.union(new_in_b)
 
64
                deleted_in_a = set(base).difference(a)
 
65
                deleted_in_b = set(base).difference(b)
 
66
                # Combine into the final set of bullet points.
 
67
                final = all_new.difference(deleted_in_a).difference(
 
68
                    deleted_in_b)
 
69
                # Sort, and emit.
 
70
                final = sorted(final, key=sort_key)
 
71
                result_lines.extend(final)
 
72
            else:
 
73
                result_lines.extend(group[1])
 
74
        # Transform the merged elements back into real blocks of lines.
 
75
        return 'success', list(fakelines_to_blocks(result_lines))
69
76
 
70
77
 
71
78
def blocks_to_fakelines(blocks):