24
24
magic_marker = '|NEWS-MERGE-MAGIC-MARKER|'
27
class NewsMerger(merge.AbstractPerFileMerger):
28
"""Merge bzr NEWS files.
30
:ivar: affected_files.
27
class NewsMerger(merge.ConfigurableFileMerger):
28
"""Merge bzr NEWS files."""
33
30
def __init__(self, merger):
34
super(NewsMerger, self).__init__(merger)
35
self.affected_files = None
31
super(NewsMerger, self).__init__(merger, 'news')
37
def merge_contents(self, params):
33
def merge_text(self, params):
38
34
"""Perform a simple 3-way merge of a bzr NEWS file.
40
36
Each section of a bzr NEWS file is essentially an ordered set of bullet
41
37
points, so we can simply take a set of bullet points, determine which
42
38
bullets to add and which to remove, sort, and reserialize.
44
# First, check whether this custom merge logic should be used. We
45
# expect most files should not be merged by this file.
46
if params.winner == 'other':
47
# OTHER is a straight winner, rely on default merge.
48
return 'not_applicable', None
49
elif not params.is_file_merge():
50
# THIS and OTHER aren't both files.
51
return 'not_applicable', None
52
elif not self.filename_matches_config(params):
53
# The filename isn't listed in the 'news_merge_files' config
55
return 'not_applicable', None
56
40
# Transform the different versions of the NEWS file into a bunch of
57
41
# text lines where each line matches one part of the overall
58
42
# structure, e.g. a heading or bullet.
91
75
# Transform the merged elements back into real blocks of lines.
92
76
return 'success', list(fakelines_to_blocks(result_lines))
94
def filename_matches_config(self, params):
95
affected_files = self.affected_files
96
if affected_files is None:
97
config = self.merger.this_tree.branch.get_config()
98
# Until bzr provides a better policy for caching the config, we
99
# just add the part we're interested in to the params to avoid
100
# reading the config files repeatedly (bazaar.conf, location.conf,
102
affected_files = config.get_user_option_as_list('news_merge_files')
103
if affected_files is None:
104
# If nothing was specified in the config, we have nothing to do,
105
# but we use None in the params to start the caching.
107
self.affected_files = affected_files
109
filename = params.merger.this_tree.id2path(params.file_id)
110
if filename in affected_files:
115
79
def blocks_to_fakelines(blocks):
116
80
for kind, text in blocks: